LCOV - code coverage report
Current view: top level - cipher - cipher-cfb.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 107 151 70.9 %
Date: 2017-03-02 16:44:37 Functions: 4 4 100.0 %

          Line data    Source code
       1             : /* cipher-cfb.c  - Generic CFB mode implementation
       2             :  * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
       3             :  *               2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
       4             :  *
       5             :  * This file is part of Libgcrypt.
       6             :  *
       7             :  * Libgcrypt is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU Lesser general Public License as
       9             :  * published by the Free Software Foundation; either version 2.1 of
      10             :  * the License, or (at your option) any later version.
      11             :  *
      12             :  * Libgcrypt is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with this program; if not, see <http://www.gnu.org/licenses/>.
      19             :  */
      20             : 
      21             : #include <config.h>
      22             : #include <stdio.h>
      23             : #include <stdlib.h>
      24             : #include <string.h>
      25             : #include <errno.h>
      26             : 
      27             : #include "g10lib.h"
      28             : #include "cipher.h"
      29             : #include "bufhelp.h"
      30             : #include "./cipher-internal.h"
      31             : 
      32             : 
      33             : gcry_err_code_t
      34       66208 : _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
      35             :                           unsigned char *outbuf, size_t outbuflen,
      36             :                           const unsigned char *inbuf, size_t inbuflen)
      37             : {
      38             :   unsigned char *ivp;
      39       66208 :   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
      40       66208 :   size_t blocksize = c->spec->blocksize;
      41       66208 :   size_t blocksize_x_2 = blocksize + blocksize;
      42             :   unsigned int burn, nburn;
      43             : 
      44             :   /* Tell compiler that we require a cipher with a 64bit or 128 bit block
      45             :    * length, to allow better optimization of this function.  */
      46       66208 :   if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
      47           0 :     return GPG_ERR_INV_LENGTH;
      48             : 
      49       66208 :   if (outbuflen < inbuflen)
      50           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
      51             : 
      52       66208 :   if ( inbuflen <= c->unused )
      53             :     {
      54             :       /* Short enough to be encoded by the remaining XOR mask. */
      55             :       /* XOR the input with the IV and store input into IV. */
      56           0 :       ivp = c->u_iv.iv + blocksize - c->unused;
      57           0 :       buf_xor_2dst(outbuf, ivp, inbuf, inbuflen);
      58           0 :       c->unused -= inbuflen;
      59           0 :       return 0;
      60             :     }
      61             : 
      62       66208 :   burn = 0;
      63             : 
      64       66208 :   if ( c->unused )
      65             :     {
      66             :       /* XOR the input with the IV and store input into IV */
      67           0 :       inbuflen -= c->unused;
      68           0 :       ivp = c->u_iv.iv + blocksize - c->unused;
      69           0 :       buf_xor_2dst(outbuf, ivp, inbuf, c->unused);
      70           0 :       outbuf += c->unused;
      71           0 :       inbuf += c->unused;
      72           0 :       c->unused = 0;
      73             :     }
      74             : 
      75             :   /* Now we can process complete blocks.  We use a loop as long as we
      76             :      have at least 2 blocks and use conditions for the rest.  This
      77             :      also allows to use a bulk encryption function if available.  */
      78       66208 :   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc)
      79       13310 :     {
      80       13310 :       size_t nblocks = inbuflen / blocksize;
      81       13310 :       c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
      82       13310 :       outbuf += nblocks * blocksize;
      83       13310 :       inbuf  += nblocks * blocksize;
      84       13310 :       inbuflen -= nblocks * blocksize;
      85             :     }
      86             :   else
      87             :     {
      88     5857444 :       while ( inbuflen >= blocksize_x_2 )
      89             :         {
      90             :           /* Encrypt the IV. */
      91     5751648 :           nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
      92     5751648 :           burn = nburn > burn ? nburn : burn;
      93             :           /* XOR the input with the IV and store input into IV.  */
      94     5751648 :           buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
      95     5751648 :           outbuf += blocksize;
      96     5751648 :           inbuf += blocksize;
      97     5751648 :           inbuflen -= blocksize;
      98             :         }
      99             :     }
     100             : 
     101       66208 :   if ( inbuflen >= blocksize )
     102             :     {
     103             :       /* Save the current IV and then encrypt the IV. */
     104       52898 :       buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
     105       52898 :       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
     106       52898 :       burn = nburn > burn ? nburn : burn;
     107             :       /* XOR the input with the IV and store input into IV */
     108       52898 :       buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
     109       52898 :       outbuf += blocksize;
     110       52898 :       inbuf += blocksize;
     111       52898 :       inbuflen -= blocksize;
     112             :     }
     113       66208 :   if ( inbuflen )
     114             :     {
     115             :       /* Save the current IV and then encrypt the IV. */
     116           0 :       buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
     117           0 :       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
     118           0 :       burn = nburn > burn ? nburn : burn;
     119           0 :       c->unused = blocksize;
     120             :       /* Apply the XOR. */
     121           0 :       c->unused -= inbuflen;
     122           0 :       buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, inbuflen);
     123           0 :       outbuf += inbuflen;
     124           0 :       inbuf += inbuflen;
     125           0 :       inbuflen = 0;
     126             :     }
     127             : 
     128       66208 :   if (burn > 0)
     129       50898 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     130             : 
     131       66208 :   return 0;
     132             : }
     133             : 
     134             : 
     135             : gcry_err_code_t
     136       57994 : _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
     137             :                           unsigned char *outbuf, size_t outbuflen,
     138             :                           const unsigned char *inbuf, size_t inbuflen)
     139             : {
     140             :   unsigned char *ivp;
     141       57994 :   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
     142       57994 :   size_t blocksize = c->spec->blocksize;
     143       57994 :   size_t blocksize_x_2 = blocksize + blocksize;
     144             :   unsigned int burn, nburn;
     145             : 
     146             :   /* Tell compiler that we require a cipher with a 64bit or 128 bit block
     147             :    * length, to allow better optimization of this function.  */
     148       57994 :   if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
     149           0 :     return GPG_ERR_INV_LENGTH;
     150             : 
     151       57994 :   if (outbuflen < inbuflen)
     152           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     153             : 
     154       57994 :   if (inbuflen <= c->unused)
     155             :     {
     156             :       /* Short enough to be encoded by the remaining XOR mask. */
     157             :       /* XOR the input with the IV and store input into IV. */
     158           0 :       ivp = c->u_iv.iv + blocksize - c->unused;
     159           0 :       buf_xor_n_copy(outbuf, ivp, inbuf, inbuflen);
     160           0 :       c->unused -= inbuflen;
     161           0 :       return 0;
     162             :     }
     163             : 
     164       57994 :   burn = 0;
     165             : 
     166       57994 :   if (c->unused)
     167             :     {
     168             :       /* XOR the input with the IV and store input into IV. */
     169           0 :       inbuflen -= c->unused;
     170           0 :       ivp = c->u_iv.iv + blocksize - c->unused;
     171           0 :       buf_xor_n_copy(outbuf, ivp, inbuf, c->unused);
     172           0 :       outbuf += c->unused;
     173           0 :       inbuf += c->unused;
     174           0 :       c->unused = 0;
     175             :     }
     176             : 
     177             :   /* Now we can process complete blocks.  We use a loop as long as we
     178             :      have at least 2 blocks and use conditions for the rest.  This
     179             :      also allows to use a bulk encryption function if available.  */
     180       57994 :   if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec)
     181       41200 :     {
     182       41200 :       size_t nblocks = inbuflen / blocksize;
     183       41200 :       c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
     184       41200 :       outbuf += nblocks * blocksize;
     185       41200 :       inbuf  += nblocks * blocksize;
     186       41200 :       inbuflen -= nblocks * blocksize;
     187             :     }
     188             :   else
     189             :     {
     190     1805736 :       while (inbuflen >= blocksize_x_2 )
     191             :         {
     192             :           /* Encrypt the IV. */
     193     1772148 :           nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
     194     1772148 :           burn = nburn > burn ? nburn : burn;
     195             :           /* XOR the input with the IV and store input into IV. */
     196     1772148 :           buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
     197     1772148 :           outbuf += blocksize;
     198     1772148 :           inbuf += blocksize;
     199     1772148 :           inbuflen -= blocksize;
     200             :         }
     201             :     }
     202             : 
     203       57994 :   if (inbuflen >= blocksize )
     204             :     {
     205             :       /* Save the current IV and then encrypt the IV. */
     206       16794 :       buf_cpy ( c->lastiv, c->u_iv.iv, blocksize);
     207       16794 :       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
     208       16794 :       burn = nburn > burn ? nburn : burn;
     209             :       /* XOR the input with the IV and store input into IV */
     210       16794 :       buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
     211       16794 :       outbuf += blocksize;
     212       16794 :       inbuf += blocksize;
     213       16794 :       inbuflen -= blocksize;
     214             :     }
     215             : 
     216       57994 :   if (inbuflen)
     217             :     {
     218             :       /* Save the current IV and then encrypt the IV. */
     219           0 :       buf_cpy ( c->lastiv, c->u_iv.iv, blocksize );
     220           0 :       nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
     221           0 :       burn = nburn > burn ? nburn : burn;
     222           0 :       c->unused = blocksize;
     223             :       /* Apply the XOR. */
     224           0 :       c->unused -= inbuflen;
     225           0 :       buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, inbuflen);
     226           0 :       outbuf += inbuflen;
     227           0 :       inbuf += inbuflen;
     228           0 :       inbuflen = 0;
     229             :     }
     230             : 
     231       57994 :   if (burn > 0)
     232       14902 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     233             : 
     234       57994 :   return 0;
     235             : }
     236             : 
     237             : 
     238             : gcry_err_code_t
     239       10210 : _gcry_cipher_cfb8_encrypt (gcry_cipher_hd_t c,
     240             :                           unsigned char *outbuf, size_t outbuflen,
     241             :                           const unsigned char *inbuf, size_t inbuflen)
     242             : {
     243       10210 :   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
     244       10210 :   size_t blocksize = c->spec->blocksize;
     245             :   unsigned int burn, nburn;
     246             : 
     247       10210 :   if (outbuflen < inbuflen)
     248           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     249             : 
     250       10210 :   burn = 0;
     251             : 
     252     2549824 :   while ( inbuflen > 0)
     253             :     {
     254             :       int i;
     255             : 
     256             :       /* Encrypt the IV. */
     257     2529404 :       nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
     258     2529404 :       burn = nburn > burn ? nburn : burn;
     259             : 
     260     2529404 :       outbuf[0] = c->lastiv[0] ^ inbuf[0];
     261             : 
     262             :       /* Bitshift iv by 8 bit to the left */
     263    33015424 :       for (i = 0; i < blocksize-1; i++)
     264    30486020 :         c->u_iv.iv[i] = c->u_iv.iv[i+1];
     265             : 
     266             :       /* append cipher text to iv */
     267     2529404 :       c->u_iv.iv[blocksize-1] = outbuf[0];
     268             : 
     269     2529404 :       outbuf += 1;
     270     2529404 :       inbuf += 1;
     271     2529404 :       inbuflen -= 1;
     272             :     }
     273             : 
     274       10210 :   if (burn > 0)
     275        9427 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     276             : 
     277       10210 :   return 0;
     278             : }
     279             : 
     280             : 
     281             : gcry_err_code_t
     282       10210 : _gcry_cipher_cfb8_decrypt (gcry_cipher_hd_t c,
     283             :                           unsigned char *outbuf, size_t outbuflen,
     284             :                           const unsigned char *inbuf, size_t inbuflen)
     285             : {
     286       10210 :   gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
     287       10210 :   size_t blocksize = c->spec->blocksize;
     288             :   unsigned int burn, nburn;
     289             :   unsigned char appendee;
     290             : 
     291       10210 :   if (outbuflen < inbuflen)
     292           0 :     return GPG_ERR_BUFFER_TOO_SHORT;
     293             : 
     294       10210 :   burn = 0;
     295             : 
     296     2549824 :   while (inbuflen > 0)
     297             :     {
     298             :       int i;
     299             : 
     300             :       /* Encrypt the IV. */
     301     2529404 :       nburn = enc_fn ( &c->context.c, c->lastiv, c->u_iv.iv );
     302     2529404 :       burn = nburn > burn ? nburn : burn;
     303             : 
     304             :       /* inbuf might == outbuf, make sure we keep the value
     305             :          so we can append it later */
     306     2529404 :       appendee = inbuf[0];
     307             : 
     308     2529404 :       outbuf[0] = inbuf[0] ^ c->lastiv[0];
     309             : 
     310             :       /* Bitshift iv by 8 bit to the left */
     311    33015424 :       for (i = 0; i < blocksize-1; i++)
     312    30486020 :         c->u_iv.iv[i] = c->u_iv.iv[i+1];
     313             : 
     314     2529404 :       c->u_iv.iv[blocksize-1] = appendee;
     315             : 
     316     2529404 :       outbuf += 1;
     317     2529404 :       inbuf += 1;
     318     2529404 :       inbuflen -= 1;
     319             :     }
     320             : 
     321       10210 :   if (burn > 0)
     322        9427 :     _gcry_burn_stack (burn + 4 * sizeof(void *));
     323             : 
     324       10210 :   return 0;
     325             : }

Generated by: LCOV version 1.13