Ignore:
Timestamp:
Jul 18, 2015, 5:06:52 PM (6 years ago)
Author:
katerina
Message:

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/rijndael-api-fst.c

    r230 r481  
    1 /*
    2  * rijndael-api-fst.c   v2.3   April '2000
    3  *
    4  * Optimised ANSI C code
    5  *
    6  * authors: v1.0: Antoon Bosselaers
    7  *          v2.0: Vincent Rijmen
    8  *          v2.1: Vincent Rijmen
    9  *          v2.2: Vincent Rijmen
    10  *          v2.3: Paulo Barreto
    11  *          v2.4: Vincent Rijmen
    12  *
    13  * This code is placed in the public domain.
     1/*      $NetBSD: rijndael-api-fst.c,v 1.24 2011/05/14 16:46:55 jmmv Exp $       */
     2
     3/**
     4 * rijndael-api-fst.c
     5 *
     6 * @version 2.9 (December 2000)
     7 *
     8 * Optimised ANSI C code for the Rijndael cipher (now AES)
     9 *
     10 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
     11 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
     12 * @author Paulo Barreto <paulo.barreto@terra.com.br>
     13 *
     14 * This code is hereby placed in the public domain.
     15 *
     16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
     17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     19 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
     20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
     23 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     24 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
     25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     27 *
     28 * Acknowledgements:
     29 *
     30 * We are deeply indebted to the following people for their bug reports,
     31 * fixes, and improvement suggestions to this implementation. Though we
     32 * tried to list all contributions, we apologise in advance for any
     33 * missing reference.
     34 *
     35 * Andrew Bales <Andrew.Bales@Honeywell.com>
     36 * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
     37 * John Skodon <skodonj@webquill.com>
    1438 */
    15 
    1639#include "config_xor.h"
    1740
    18 #include <stdio.h>
    19 #include <assert.h>
    2041#include <stdlib.h>
    2142#include <string.h>
    2243
     44
    2345#ifdef SH_ENCRYPT
    2446
    2547#include "rijndael-api-fst.h"
    2648
    27 int makeKey(keyInstance *key, RIJ_BYTE direction, int keyLen, char *keyMaterial) {
    28   word8 k[MAXKC][4];
    29   int i;
    30   char *keyMat;
    31  
    32   if (key == NULL) {
    33     return BAD_KEY_INSTANCE;
    34   }
    35  
    36   if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
    37     key->direction = direction;
    38   } else {
    39     return BAD_KEY_DIR;
    40   }
    41  
    42   if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
    43     key->keyLen = keyLen;
    44   } else {
    45     return BAD_KEY_MAT;
    46   }
    47  
    48   if (keyMaterial != NULL) {
    49     strncpy(key->keyMaterial, keyMaterial, keyLen/4);
    50   }
    51  
    52   key->ROUNDS = keyLen/32 + 6;
    53  
    54   /* initialize key schedule: */
    55   keyMat = key->keyMaterial;
    56 #ifndef BINARY_KEY_MATERIAL
    57   for (i = 0; i < key->keyLen/8; i++) {
    58     int t, j;
    59    
    60     t = *keyMat++;
    61     if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
    62     else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
    63     else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
    64     else return BAD_KEY_MAT;
    65    
    66     t = *keyMat++;
    67     if ((t >= '0') && (t <= '9')) j ^= (t - '0');
    68     else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
    69     else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
    70     else return BAD_KEY_MAT;
    71    
    72     k[i >> 2][i & 3] = (word8)j;
    73   }
    74 #else
    75   for (i = 0; i < key->keyLen/8; i++) {
    76     k[i >> 2][i & 3] = (word8)keyMat[i];
    77   }
    78 #endif /* ?BINARY_KEY_MATERIAL */
    79   rijndaelKeySched(k, key->keySched, key->ROUNDS);
    80   if (direction == DIR_DECRYPT) {
    81     rijndaelKeyEncToDec(key->keySched, key->ROUNDS);
    82   }
    83  
    84   return TRUE;
    85 }
    86 
    87 int cipherInit(cipherInstance *cipher, RIJ_BYTE mode, char *IV) {
    88   if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
    89     cipher->mode = mode;
    90   } else {
    91     return BAD_CIPHER_MODE;
    92   }
    93   if (IV != NULL) {
    94 #ifndef BINARY_KEY_MATERIAL
    95     int i;
    96     for (i = 0; i < MAX_IV_SIZE; i++) {
    97       int t, j;
    98      
    99       t = IV[2*i];
    100       if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
    101       else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
    102       else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
    103       else return BAD_CIPHER_INSTANCE;
    104      
    105       t = IV[2*i+1];
    106       if ((t >= '0') && (t <= '9')) j ^= (t - '0');
    107       else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
    108       else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
    109       else return BAD_CIPHER_INSTANCE;
    110      
    111       cipher->IV[i] = (word8)j;
    112     }
    113 #else
    114     memcpy(cipher->IV, IV, MAX_IV_SIZE);
    115 #endif /* ?BINARY_KEY_MATERIAL */
    116   } else {
    117     memset(cipher->IV, 0, MAX_IV_SIZE);
    118   }
    119   return TRUE;
    120 }
    121 
    122 int blockEncrypt(cipherInstance *cipher, keyInstance *key,
    123                  RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
    124   int i, k, numBlocks;
    125   union {
    126     word32 bloc4[4];
    127     word8  block[16];
    128   } bb;
    129   union {
    130     word32 i4[4];
    131     word8  iv[4][4];
    132   } iu;
    133  
    134   if (cipher == NULL ||
    135       key == NULL ||
    136       key->direction == DIR_DECRYPT) {
    137     return BAD_CIPHER_STATE;
    138   }
    139   if (input == NULL || inputLen <= 0) {
    140     return 0; /* nothing to do */
    141   }
    142  
    143   numBlocks = inputLen/128;
    144  
    145   switch (cipher->mode) {
    146   case MODE_ECB:
    147     for (i = numBlocks; i > 0; i--) {
    148       rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS);
    149       input += 16;
    150       outBuffer += 16;
    151     }
    152     break;
    153    
    154   case MODE_CBC:
    155     /* fix the memory alignment for HP-UX 10.20
    156      * R. Wichmann  Mon Jun 18 22:36:55 CEST 2001
    157      */
    158 #if STRICT_ALIGN
    159     memcpy(iu.iv, cipher->IV, 16);
    160     bb.bloc4[0] = iu.i4[0] ^ ((word32*)input)[0];
    161     bb.bloc4[1] = iu.i4[1] ^ ((word32*)input)[1];
    162     bb.bloc4[2] = iu.i4[2] ^ ((word32*)input)[2];
    163     bb.bloc4[3] = iu.i4[3] ^ ((word32*)input)[3];
    164 #else  /* !STRICT_ALIGN */
    165     ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0];
    166     ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1];
    167     ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2];
    168     ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3];
    169 #endif /* ?STRICT_ALIGN */
    170     rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
    171     input += 16;
    172     for (i = numBlocks - 1; i > 0; i--) {
    173       bb.bloc4[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0];
    174       bb.bloc4[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1];
    175       bb.bloc4[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2];
    176       bb.bloc4[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3];
    177       outBuffer += 16;
    178       rijndaelEncrypt(bb.block, outBuffer, key->keySched, key->ROUNDS);
    179       input += 16;
    180     }
    181     break;
    182    
    183   case MODE_CFB1:
    184 #if STRICT_ALIGN
    185     memcpy(iu.iv, cipher->IV, 16);
    186 #else  /* !STRICT_ALIGN */
    187     *((word32*)iv[0]) = *((word32*)(cipher->IV   ));
    188     *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
    189     *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
    190     *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
    191 #endif /* ?STRICT_ALIGN */
    192     for (i = numBlocks; i > 0; i--) {
    193       for (k = 0; k < 128; k++) {
    194         bb.bloc4[0] = iu.i4[0];
    195         bb.bloc4[1] = iu.i4[1];
    196         bb.bloc4[2] = iu.i4[2];
    197         bb.bloc4[3] = iu.i4[3];
    198         rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
    199         outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
    200         iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
    201         iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
    202         iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
    203         iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
    204         iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
    205         iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
    206         iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
    207         iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
    208         iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
    209         iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
    210         iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
    211         iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
    212         iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
    213         iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
    214         iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
    215         iu.iv[3][3] = (iu.iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
    216       }
    217     }
    218     break;
    219    
    220   default:
    221     return BAD_CIPHER_STATE;
    222   }
    223  
    224   return 128*numBlocks;
    225 }
    226 
    227 int blockDecrypt(cipherInstance *cipher, keyInstance *key,
    228                  RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer) {
    229   int i, k, numBlocks;
    230   union {
    231     word32 bloc4[4];
    232     word8  block[16];
    233   } bb;
    234   union {
    235     word32 i4[4];
    236     word8  iv[4][4];
    237   } iu;
    238  
    239   if (cipher == NULL ||
    240       key == NULL ||
    241       ((cipher->mode != MODE_CFB1) && (key->direction == DIR_ENCRYPT))) {
    242     return BAD_CIPHER_STATE;
    243   }
    244   if (input == NULL || inputLen <= 0) {
    245     return 0; /* nothing to do */
    246   }
    247  
    248   numBlocks = inputLen/128;
    249  
    250   switch (cipher->mode) {
    251   case MODE_ECB:
    252     for (i = numBlocks; i > 0; i--) {
    253       rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS);
    254       input += 16;
    255       outBuffer += 16;
    256     }
    257     break;
    258    
    259   case MODE_CBC:
    260 #if STRICT_ALIGN
    261     memcpy(iu.iv, cipher->IV, 16);
    262 #else
    263     *((word32*)iu.i4[0]) = *((word32*)(cipher->IV   ));
    264     *((word32*)iu.i4[1]) = *((word32*)(cipher->IV+ 4));
    265     *((word32*)iu.i4[2]) = *((word32*)(cipher->IV+ 8));
    266     *((word32*)iu.i4[3]) = *((word32*)(cipher->IV+12));
     49static void xor16(u8 *d, const u8 *a, const u8* b)
     50{
     51  size_t i;
     52
     53        for (i = 0; i < 4; i++) {
     54                *d++ = *a++ ^ *b++;
     55                *d++ = *a++ ^ *b++;
     56                *d++ = *a++ ^ *b++;
     57                *d++ = *a++ ^ *b++;
     58        }
     59}
     60
     61int
     62rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
     63    const char *keyMaterial)
     64{
     65        u8 cipherKey[RIJNDAEL_MAXKB];
     66        int i;
     67
     68        if (key == NULL) {
     69                return BAD_KEY_INSTANCE;
     70        }
     71
     72        if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
     73                key->direction = direction;
     74        } else {
     75                return BAD_KEY_DIR;
     76        }
     77
     78        if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
     79                key->keyLen = keyLen;
     80        } else {
     81                return BAD_KEY_MAT;
     82        }
     83
     84        if (keyMaterial != NULL) {
     85                char temp[RIJNDAEL_MAX_KEY_SIZE];
     86                for (i = 0; i < key->keyLen/8; i++) {
     87                  int t, j;
     88                 
     89                  t = *keyMaterial++;
     90                  if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
     91                  else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
     92                  else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
     93                  else return BAD_KEY_MAT;
     94                 
     95                  t = *keyMaterial++;
     96                  if ((t >= '0') && (t <= '9')) j ^= (t - '0');
     97                  else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
     98                  else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
     99                  else return BAD_KEY_MAT;
     100                 
     101                  temp[i] = (u8)j;
     102                }
     103
     104                /* memcpy(key->keyMaterial, keyMaterial, keyLen/8); */
     105                memcpy(key->keyMaterial, temp, keyLen/8);
     106        }
     107
     108        /* initialize key schedule: */
     109        memcpy(cipherKey, key->keyMaterial, keyLen/8);
     110        if (direction == DIR_ENCRYPT) {
     111                key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
     112        } else {
     113                key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
     114        }
     115        rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
     116        return TRUE;
     117}
     118
     119int
     120rijndael_cipherInit(cipherInstance *cipher, BYTE mode, const char *IV)
     121{
     122        if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
     123                cipher->mode = mode;
     124        } else {
     125                return BAD_CIPHER_MODE;
     126        }
     127        if (IV != NULL) {
     128                memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
     129        } else {
     130                memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
     131        }
     132        return TRUE;
     133}
     134
     135int
     136rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
     137    const BYTE *input, int inputLen, BYTE *outBuffer)
     138{
     139        int i, k, t, numBlocks;
     140        u8 block[16], *iv;
     141
     142        if (cipher == NULL ||
     143                key == NULL ||
     144                key->direction == DIR_DECRYPT) {
     145                return BAD_CIPHER_STATE;
     146        }
     147        if (input == NULL || inputLen <= 0) {
     148                return 0; /* nothing to do */
     149        }
     150
     151        numBlocks = inputLen/128;
     152
     153        switch (cipher->mode) {
     154        case MODE_ECB:
     155                for (i = numBlocks; i > 0; i--) {
     156                        rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
     157                        input += 16;
     158                        outBuffer += 16;
     159                }
     160                break;
     161
     162        case MODE_CBC:
     163                iv = (u8 *)cipher->IV;
     164                for (i = numBlocks; i > 0; i--) {
     165                        xor16(block, input, iv);
     166                        rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
     167                        iv = outBuffer;
     168                        input += 16;
     169                        outBuffer += 16;
     170                }
     171                break;
     172
     173        case MODE_CFB1:
     174                iv = (u8 *)cipher->IV;
     175                for (i = numBlocks; i > 0; i--) {
     176                        memcpy(outBuffer, input, 16);
     177                        for (k = 0; k < 128; k++) {
     178                                rijndaelEncrypt(key->ek, key->Nr, iv, block);
     179                                outBuffer[k >> 3] ^=
     180                                    (block[0] & 0x80U) >> (k & 7);
     181                                for (t = 0; t < 15; t++) {
     182                                        iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
     183                                }
     184                                iv[15] = (iv[15] << 1) |
     185                                    ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
     186                        }
     187                        outBuffer += 16;
     188                        input += 16;
     189                }
     190                break;
     191
     192        default:
     193                return BAD_CIPHER_STATE;
     194        }
     195
     196        return 128 * numBlocks;
     197}
     198
     199/**
     200 * Encrypt data partitioned in octets, using RFC 2040-like padding.
     201 *
     202 * @param   input           data to be encrypted (octet sequence)
     203 * @param   inputOctets         input length in octets (not bits)
     204 * @param   outBuffer       encrypted output data
     205 *
     206 * @return      length in octets (not bits) of the encrypted output buffer.
     207 */
     208int
     209rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
     210    const BYTE *input, int inputOctets, BYTE *outBuffer)
     211{
     212        int i, numBlocks, padLen;
     213        u8 block[16], *iv;
     214
     215        if (cipher == NULL ||
     216                key == NULL ||
     217                key->direction == DIR_DECRYPT) {
     218                return BAD_CIPHER_STATE;
     219        }
     220        if (input == NULL || inputOctets <= 0) {
     221                return 0; /* nothing to do */
     222        }
     223
     224        numBlocks = inputOctets / 16;
     225
     226        switch (cipher->mode) {
     227        case MODE_ECB:
     228                for (i = numBlocks; i > 0; i--) {
     229                        rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
     230                        input += 16;
     231                        outBuffer += 16;
     232                }
     233                padLen = 16 - (inputOctets - 16*numBlocks);
     234                memcpy(block, input, 16 - padLen);
     235                memset(block + 16 - padLen, padLen, padLen);
     236                rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
     237                break;
     238
     239        case MODE_CBC:
     240                iv = (u8 *)cipher->IV;
     241                for (i = numBlocks; i > 0; i--) {
     242                        xor16(block, input, iv);
     243                        rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
     244                        iv = outBuffer;
     245                        input += 16;
     246                        outBuffer += 16;
     247                }
     248                padLen = 16 - (inputOctets - 16*numBlocks);
     249                for (i = 0; i < 16 - padLen; i++) {
     250                        block[i] = input[i] ^ iv[i];
     251                }
     252                for (i = 16 - padLen; i < 16; i++) {
     253                        block[i] = (BYTE)padLen ^ iv[i];
     254                }
     255                rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
     256                break;
     257
     258        default:
     259                return BAD_CIPHER_STATE;
     260        }
     261
     262        return 16 * (numBlocks + 1);
     263}
     264
     265int
     266rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
     267    const BYTE *input, int inputLen, BYTE *outBuffer)
     268{
     269        int i, k, t, numBlocks;
     270        u8 block[16], *iv;
     271
     272        if (cipher == NULL ||
     273                key == NULL ||
     274                (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
     275                return BAD_CIPHER_STATE;
     276        }
     277        if (input == NULL || inputLen <= 0) {
     278                return 0; /* nothing to do */
     279        }
     280
     281        numBlocks = inputLen/128;
     282
     283        switch (cipher->mode) {
     284        case MODE_ECB:
     285                for (i = numBlocks; i > 0; i--) {
     286                        rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
     287                        input += 16;
     288                        outBuffer += 16;
     289                }
     290                break;
     291
     292        case MODE_CBC:
     293                iv = (u8 *)cipher->IV;
     294                for (i = numBlocks; i > 0; i--) {
     295                        rijndaelDecrypt(key->rk, key->Nr, input, block);
     296                        xor16(block, block, iv);
     297                        if (numBlocks > 1)
     298                          memcpy(cipher->IV, input, 16);
     299                        memcpy(outBuffer, block, 16);
     300                        input += 16;
     301                        outBuffer += 16;
     302                }
     303                break;
     304
     305    case MODE_CFB1:
     306                iv = (u8 *)cipher->IV;
     307                for (i = numBlocks; i > 0; i--) {
     308                        memcpy(outBuffer, input, 16);
     309                        for (k = 0; k < 128; k++) {
     310                                rijndaelEncrypt(key->ek, key->Nr, iv, block);
     311                                for (t = 0; t < 15; t++) {
     312                                        iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
     313                                }
     314                                iv[15] = (iv[15] << 1) |
     315                                    ((input[k >> 3] >> (7 - (k & 7))) & 1);
     316                                outBuffer[k >> 3] ^= (block[0] & 0x80U) >>
     317                                    (k & 7);
     318                        }
     319                        outBuffer += 16;
     320                        input += 16;
     321                }
     322                break;
     323
     324        default:
     325                return BAD_CIPHER_STATE;
     326        }
     327
     328        return 128 * numBlocks;
     329}
     330
     331int
     332rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
     333    const BYTE *input, int inputOctets, BYTE *outBuffer)
     334{
     335        int i, numBlocks, padLen;
     336        u8 block[16], *iv;
     337
     338        if (cipher == NULL ||
     339                key == NULL ||
     340                key->direction == DIR_ENCRYPT) {
     341                return BAD_CIPHER_STATE;
     342        }
     343        if (input == NULL || inputOctets <= 0) {
     344                return 0; /* nothing to do */
     345        }
     346        if (inputOctets % 16 != 0) {
     347                return BAD_DATA;
     348        }
     349
     350        numBlocks = inputOctets/16;
     351
     352        switch (cipher->mode) {
     353        case MODE_ECB:
     354                /* all blocks but last */
     355                for (i = numBlocks - 1; i > 0; i--) {
     356                        rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
     357                        input += 16;
     358                        outBuffer += 16;
     359                }
     360                /* last block */
     361                rijndaelDecrypt(key->rk, key->Nr, input, block);
     362                padLen = block[15];
     363                if (padLen >= 16) {
     364                        return BAD_DATA;
     365                }
     366                for (i = 16 - padLen; i < 16; i++) {
     367                        if (block[i] != padLen) {
     368                                return BAD_DATA;
     369                        }
     370                }
     371                memcpy(outBuffer, block, 16 - padLen);
     372                break;
     373
     374        case MODE_CBC:
     375                iv = (u8 *)cipher->IV;
     376                /* all blocks but last */
     377                for (i = numBlocks - 1; i > 0; i--) {
     378                        rijndaelDecrypt(key->rk, key->Nr, input, block);
     379                        xor16(block, block, iv);
     380                        memcpy(cipher->IV, input, 16);
     381                        memcpy(outBuffer, block, 16);
     382                        input += 16;
     383                        outBuffer += 16;
     384                }
     385                /* last block */
     386                rijndaelDecrypt(key->rk, key->Nr, input, block);
     387                xor16(block, block, iv);
     388                padLen = block[15];
     389                if (padLen <= 0 || padLen > 16) {
     390                        return BAD_DATA;
     391                }
     392                for (i = 16 - padLen; i < 16; i++) {
     393                        if (block[i] != padLen) {
     394                                return BAD_DATA;
     395                        }
     396                }
     397                memcpy(outBuffer, block, 16 - padLen);
     398                break;
     399
     400        default:
     401                return BAD_CIPHER_STATE;
     402        }
     403
     404        return 16 * numBlocks - padLen;
     405}
     406
    267407#endif
    268     for (i = numBlocks; i > 0; i--) {
    269       rijndaelDecrypt(input, bb.block, key->keySched, key->ROUNDS);
    270       bb.bloc4[0] ^= iu.i4[0];
    271       bb.bloc4[1] ^= iu.i4[1];
    272       bb.bloc4[2] ^= iu.i4[2];
    273       bb.bloc4[3] ^= iu.i4[3];
    274 #if STRICT_ALIGN
    275       memcpy(iu.iv, input, 16);
    276       memcpy(outBuffer, bb.block, 16);
    277 #else
    278       *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0];
    279       *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1];
    280       *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2];
    281       *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3];
    282 #endif
    283       input += 16;
    284       outBuffer += 16;
    285     }
    286     break;
    287    
    288   case MODE_CFB1:
    289 #if STRICT_ALIGN
    290     memcpy(iu.iv, cipher->IV, 16);
    291 #else
    292     *((word32*)iv[0]) = *((word32*)(cipher->IV));
    293     *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4));
    294     *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8));
    295     *((word32*)iv[3]) = *((word32*)(cipher->IV+12));
    296 #endif
    297     for (i = numBlocks; i > 0; i--) {
    298       for (k = 0; k < 128; k++) {
    299         bb.bloc4[0] = iu.i4[0];
    300         bb.bloc4[1] = iu.i4[1];
    301         bb.bloc4[2] = iu.i4[2];
    302         bb.bloc4[3] = iu.i4[3];
    303         rijndaelEncrypt(bb.block, bb.block, key->keySched, key->ROUNDS);
    304         iu.iv[0][0] = (iu.iv[0][0] << 1) | (iu.iv[0][1] >> 7);
    305         iu.iv[0][1] = (iu.iv[0][1] << 1) | (iu.iv[0][2] >> 7);
    306         iu.iv[0][2] = (iu.iv[0][2] << 1) | (iu.iv[0][3] >> 7);
    307         iu.iv[0][3] = (iu.iv[0][3] << 1) | (iu.iv[1][0] >> 7);
    308         iu.iv[1][0] = (iu.iv[1][0] << 1) | (iu.iv[1][1] >> 7);
    309         iu.iv[1][1] = (iu.iv[1][1] << 1) | (iu.iv[1][2] >> 7);
    310         iu.iv[1][2] = (iu.iv[1][2] << 1) | (iu.iv[1][3] >> 7);
    311         iu.iv[1][3] = (iu.iv[1][3] << 1) | (iu.iv[2][0] >> 7);
    312         iu.iv[2][0] = (iu.iv[2][0] << 1) | (iu.iv[2][1] >> 7);
    313         iu.iv[2][1] = (iu.iv[2][1] << 1) | (iu.iv[2][2] >> 7);
    314         iu.iv[2][2] = (iu.iv[2][2] << 1) | (iu.iv[2][3] >> 7);
    315         iu.iv[2][3] = (iu.iv[2][3] << 1) | (iu.iv[3][0] >> 7);
    316         iu.iv[3][0] = (iu.iv[3][0] << 1) | (iu.iv[3][1] >> 7);
    317         iu.iv[3][1] = (iu.iv[3][1] << 1) | (iu.iv[3][2] >> 7);
    318         iu.iv[3][2] = (iu.iv[3][2] << 1) | (iu.iv[3][3] >> 7);
    319         iu.iv[3][3] = (iu.iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
    320         outBuffer[k/8] ^= (bb.block[0] & 0x80) >> (k & 7);
    321       }
    322     }
    323     break;
    324    
    325   default:
    326     return BAD_CIPHER_STATE;
    327   }
    328  
    329   return 128*numBlocks;
    330 }
    331 #ifdef INTERMEDIATE_VALUE_KAT
    332 /**
    333  *      cipherUpdateRounds:
    334  *
    335  *      Encrypts/Decrypts exactly one full block a specified number of rounds.
    336  *      Only used in the Intermediate Value Known Answer Test. 
    337  *
    338  *      Returns:
    339  *              TRUE - on success
    340  *              BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
    341  */
    342 int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
    343                 RIJ_BYTE *input, int inputLen, RIJ_BYTE *outBuffer, int rounds) {
    344         int j;
    345         word8 block[4][4];
    346 
    347         if (cipher == NULL || key == NULL) {
    348                 return BAD_CIPHER_STATE;
    349         }
    350 
    351         for (j = 3; j >= 0; j--) {
    352                 /* parse input stream into rectangular array */
    353                 *((word32*)block[j]) = *((word32*)(input+4*j));
    354         }
    355 
    356         switch (key->direction) {
    357         case DIR_ENCRYPT:
    358                 rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds);
    359                 break;
    360                
    361         case DIR_DECRYPT:
    362                 rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds);
    363                 break;
    364                
    365         default:
    366                 return BAD_KEY_DIR;
    367         }
    368 
    369         for (j = 3; j >= 0; j--) {
    370                 /* parse rectangular array into output ciphertext bytes */
    371                 *((word32*)(outBuffer+4*j)) = *((word32*)block[j]);
    372         }
    373        
    374         return TRUE;
    375 }
    376 #endif /* INTERMEDIATE_VALUE_KAT */
    377 #endif
Note: See TracChangeset for help on using the changeset viewer.