Page principale | Hiérarchie des classes | Liste alphabétique | Liste des classes | Liste des fichiers | Membres de classe | Membres de fichier | Pages associées

rijndael-api-fst.c

00001 /**
00002  * rijndael-api-fst.c
00003  *
00004  * @version 2.9 (December 2000)
00005  *
00006  * Optimised ANSI C code for the Rijndael cipher (now AES)
00007  *
00008  * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
00009  * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
00010  * @author Paulo Barreto <paulo.barreto@terra.com.br>
00011  *
00012  * This code is hereby placed in the public domain.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
00015  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00017  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
00018  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00019  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00020  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
00021  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
00022  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
00023  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
00024  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00025  *
00026  * Acknowledgements:
00027  *
00028  * We are deeply indebted to the following people for their bug reports,
00029  * fixes, and improvement suggestions to this implementation. Though we
00030  * tried to list all contributions, we apologise in advance for any
00031  * missing reference.
00032  *
00033  * Andrew Bales <Andrew.Bales@Honeywell.com>
00034  * Markus Friedl <markus.friedl@informatik.uni-erlangen.de>
00035  * John Skodon <skodonj@webquill.com>
00036  */
00037 
00038 #include <assert.h>
00039 #include <stdlib.h>
00040 #include <string.h>
00041 
00042 #include "rijndael-alg-fst.h"
00043 #include "rijndael-api-fst.h"
00044 
00045 int makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
00046     int i;
00047     char *keyMat;
00048     u8 cipherKey[MAXKB];
00049     
00050     if (key == NULL) {
00051         return BAD_KEY_INSTANCE;
00052     }
00053 
00054     if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
00055         key->direction = direction;
00056     } else {
00057         return BAD_KEY_DIR;
00058     }
00059 
00060     if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
00061         key->keyLen = keyLen;
00062     } else {
00063         return BAD_KEY_MAT;
00064     }
00065 
00066     if (keyMaterial != NULL) {
00067         strncpy(key->keyMaterial, keyMaterial, keyLen/4);
00068     }
00069 
00070     /* initialize key schedule: */
00071     keyMat = key->keyMaterial;
00072     for (i = 0; i < key->keyLen/8; i++) {
00073         int t, v;
00074 
00075         t = *keyMat++;
00076         if ((t >= '0') && (t <= '9')) v = (t - '0') << 4;
00077         else if ((t >= 'a') && (t <= 'f')) v = (t - 'a' + 10) << 4;
00078         else if ((t >= 'A') && (t <= 'F')) v = (t - 'A' + 10) << 4;
00079         else return BAD_KEY_MAT;
00080         
00081         t = *keyMat++;
00082         if ((t >= '0') && (t <= '9')) v ^= (t - '0');
00083         else if ((t >= 'a') && (t <= 'f')) v ^= (t - 'a' + 10);
00084         else if ((t >= 'A') && (t <= 'F')) v ^= (t - 'A' + 10);
00085         else return BAD_KEY_MAT;
00086         
00087         cipherKey[i] = (u8)v;
00088     }
00089     if (direction == DIR_ENCRYPT) {
00090         key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
00091     } else {
00092         key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
00093     }
00094     rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
00095     return TRUE;
00096 }
00097 
00098 int cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
00099     if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
00100         cipher->mode = mode;
00101     } else {
00102         return BAD_CIPHER_MODE;
00103     }
00104     if (IV != NULL) {
00105         int i;
00106         for (i = 0; i < MAX_IV_SIZE; i++) {
00107             int t, j;
00108 
00109             t = IV[2*i];
00110             if ((t >= '0') && (t <= '9')) j = (t - '0') << 4;
00111             else if ((t >= 'a') && (t <= 'f')) j = (t - 'a' + 10) << 4;
00112             else if ((t >= 'A') && (t <= 'F')) j = (t - 'A' + 10) << 4;
00113             else return BAD_CIPHER_INSTANCE;
00114         
00115             t = IV[2*i+1];
00116             if ((t >= '0') && (t <= '9')) j ^= (t - '0');
00117             else if ((t >= 'a') && (t <= 'f')) j ^= (t - 'a' + 10);
00118             else if ((t >= 'A') && (t <= 'F')) j ^= (t - 'A' + 10);
00119             else return BAD_CIPHER_INSTANCE;
00120             
00121             cipher->IV[i] = (u8)j;
00122         }
00123     } else {
00124         memset(cipher->IV, 0, MAX_IV_SIZE);
00125     }
00126     return TRUE;
00127 }
00128 
00129 int blockEncrypt(cipherInstance *cipher, keyInstance *key,
00130         BYTE *input, int inputLen, BYTE *outBuffer) {
00131     int i, k, t, numBlocks;
00132     u8 block[16], *iv;
00133 
00134     if (cipher == NULL ||
00135         key == NULL ||
00136         key->direction == DIR_DECRYPT) {
00137         return BAD_CIPHER_STATE;
00138     }
00139     if (input == NULL || inputLen <= 0) {
00140         return 0; /* nothing to do */
00141     }
00142 
00143     numBlocks = inputLen/128;
00144     
00145     switch (cipher->mode) {
00146     case MODE_ECB:
00147         for (i = numBlocks; i > 0; i--) {
00148             rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
00149             input += 16;
00150             outBuffer += 16;
00151         }
00152         break;
00153         
00154     case MODE_CBC:
00155         iv = cipher->IV;
00156         for (i = numBlocks; i > 0; i--) {
00157             ((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
00158             ((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
00159             ((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
00160             ((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
00161             rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
00162             iv = outBuffer;
00163             input += 16;
00164             outBuffer += 16;
00165         }
00166         break;
00167 
00168     case MODE_CFB1:
00169         iv = cipher->IV;
00170         for (i = numBlocks; i > 0; i--) {
00171             memcpy(outBuffer, input, 16);
00172             for (k = 0; k < 128; k++) {
00173                 rijndaelEncrypt(key->ek, key->Nr, iv, block);
00174                 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
00175                 for (t = 0; t < 15; t++) {
00176                     iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
00177                 }
00178                 iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1);
00179             }
00180             outBuffer += 16;
00181             input += 16;
00182         }
00183         break;
00184 
00185     default:
00186         return BAD_CIPHER_STATE;
00187     }
00188     
00189     return 128*numBlocks;
00190 }
00191 
00192 /**
00193  * Encrypt data partitioned in octets, using RFC 2040-like padding.
00194  *
00195  * @param   input           data to be encrypted (octet sequence)
00196  * @param   inputOctets     input length in octets (not bits)
00197  * @param   outBuffer       encrypted output data
00198  *
00199  * @return  length in octets (not bits) of the encrypted output buffer.
00200  */
00201 int padEncrypt(cipherInstance *cipher, keyInstance *key,
00202         BYTE *input, int inputOctets, BYTE *outBuffer) {
00203     int i, numBlocks, padLen;
00204     u8 block[16], *iv;
00205 
00206     if (cipher == NULL ||
00207         key == NULL ||
00208         key->direction == DIR_DECRYPT) {
00209         return BAD_CIPHER_STATE;
00210     }
00211     if (input == NULL || inputOctets <= 0) {
00212         return 0; /* nothing to do */
00213     }
00214 
00215     numBlocks = inputOctets/16;
00216 
00217     switch (cipher->mode) {
00218     case MODE_ECB:
00219         for (i = numBlocks; i > 0; i--) {
00220             rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
00221             input += 16;
00222             outBuffer += 16;
00223         }
00224         padLen = 16 - (inputOctets - 16*numBlocks);
00225         assert(padLen > 0 && padLen <= 16);
00226         memcpy(block, input, 16 - padLen);
00227         memset(block + 16 - padLen, padLen, padLen);
00228         rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
00229         break;
00230 
00231     case MODE_CBC:
00232         iv = cipher->IV;
00233         for (i = numBlocks; i > 0; i--) {
00234             ((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0];
00235             ((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1];
00236             ((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2];
00237             ((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3];
00238             rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
00239             iv = outBuffer;
00240             input += 16;
00241             outBuffer += 16;
00242         }
00243         padLen = 16 - (inputOctets - 16*numBlocks);
00244         assert(padLen > 0 && padLen <= 16);
00245         for (i = 0; i < 16 - padLen; i++) {
00246             block[i] = input[i] ^ iv[i];
00247         }
00248         for (i = 16 - padLen; i < 16; i++) {
00249             block[i] = (BYTE)padLen ^ iv[i];
00250         }
00251         rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
00252         break;
00253 
00254     default:
00255         return BAD_CIPHER_STATE;
00256     }
00257 
00258     return 16*(numBlocks + 1);
00259 }
00260 
00261 int blockDecrypt(cipherInstance *cipher, keyInstance *key,
00262         BYTE *input, int inputLen, BYTE *outBuffer) {
00263     int i, k, t, numBlocks;
00264     u8 block[16], *iv;
00265 
00266     if (cipher == NULL ||
00267         key == NULL ||
00268         cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT) {
00269         return BAD_CIPHER_STATE;
00270     }
00271     if (input == NULL || inputLen <= 0) {
00272         return 0; /* nothing to do */
00273     }
00274 
00275     numBlocks = inputLen/128;
00276 
00277     switch (cipher->mode) {
00278     case MODE_ECB:
00279         for (i = numBlocks; i > 0; i--) {
00280             rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
00281             input += 16;
00282             outBuffer += 16;
00283         }
00284         break;
00285         
00286     case MODE_CBC:
00287         iv = cipher->IV;
00288         for (i = numBlocks; i > 0; i--) {
00289             rijndaelDecrypt(key->rk, key->Nr, input, block);
00290             ((u32*)block)[0] ^= ((u32*)iv)[0];
00291             ((u32*)block)[1] ^= ((u32*)iv)[1];
00292             ((u32*)block)[2] ^= ((u32*)iv)[2];
00293             ((u32*)block)[3] ^= ((u32*)iv)[3];
00294             memcpy(cipher->IV, input, 16);
00295             memcpy(outBuffer, block, 16);
00296             input += 16;
00297             outBuffer += 16;
00298         }
00299         break;
00300 
00301     case MODE_CFB1:
00302         iv = cipher->IV;
00303         for (i = numBlocks; i > 0; i--) {
00304             memcpy(outBuffer, input, 16);
00305             for (k = 0; k < 128; k++) {
00306                 rijndaelEncrypt(key->ek, key->Nr, iv, block);
00307                 for (t = 0; t < 15; t++) {
00308                     iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7);
00309                 }
00310                 iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1);
00311                 outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7);
00312             }
00313             outBuffer += 16;
00314             input += 16;
00315         }
00316         break;
00317 
00318     default:
00319         return BAD_CIPHER_STATE;
00320     }
00321     
00322     return 128*numBlocks;
00323 }
00324 
00325 int padDecrypt(cipherInstance *cipher, keyInstance *key,
00326         BYTE *input, int inputOctets, BYTE *outBuffer) {
00327     int i, numBlocks, padLen;
00328     u8 block[16];
00329 
00330     if (cipher == NULL ||
00331         key == NULL ||
00332         key->direction == DIR_ENCRYPT) {
00333         return BAD_CIPHER_STATE;
00334     }
00335     if (input == NULL || inputOctets <= 0) {
00336         return 0; /* nothing to do */
00337     }
00338     if (inputOctets % 16 != 0) {
00339         return BAD_DATA;
00340     }
00341 
00342     numBlocks = inputOctets/16;
00343 
00344     switch (cipher->mode) {
00345     case MODE_ECB:
00346         /* all blocks but last */
00347         for (i = numBlocks - 1; i > 0; i--) {
00348             rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
00349             input += 16;
00350             outBuffer += 16;
00351         }
00352         /* last block */
00353         rijndaelDecrypt(key->rk, key->Nr, input, block);
00354         padLen = block[15];
00355         if (padLen >= 16) {
00356             return BAD_DATA;
00357         }
00358         for (i = 16 - padLen; i < 16; i++) {
00359             if (block[i] != padLen) {
00360                 return BAD_DATA;
00361             }
00362         }
00363         memcpy(outBuffer, block, 16 - padLen);
00364         break;
00365         
00366     case MODE_CBC:
00367         /* all blocks but last */
00368         for (i = numBlocks - 1; i > 0; i--) {
00369             rijndaelDecrypt(key->rk, key->Nr, input, block);
00370             ((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
00371             ((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
00372             ((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
00373             ((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
00374             memcpy(cipher->IV, input, 16);
00375             memcpy(outBuffer, block, 16);
00376             input += 16;
00377             outBuffer += 16;
00378         }
00379         /* last block */
00380         rijndaelDecrypt(key->rk, key->Nr, input, block);
00381         ((u32*)block)[0] ^= ((u32*)cipher->IV)[0];
00382         ((u32*)block)[1] ^= ((u32*)cipher->IV)[1];
00383         ((u32*)block)[2] ^= ((u32*)cipher->IV)[2];
00384         ((u32*)block)[3] ^= ((u32*)cipher->IV)[3];
00385         padLen = block[15];
00386         if (padLen <= 0 || padLen > 16) {
00387             return BAD_DATA;
00388         }
00389         for (i = 16 - padLen; i < 16; i++) {
00390             if (block[i] != padLen) {
00391                 return BAD_DATA;
00392             }
00393         }
00394         memcpy(outBuffer, block, 16 - padLen);
00395         break;
00396     
00397     default:
00398         return BAD_CIPHER_STATE;
00399     }
00400     
00401     return 16*numBlocks - padLen;
00402 }
00403 
00404 #ifdef INTERMEDIATE_VALUE_KAT
00405 /**
00406  *  cipherUpdateRounds:
00407  *
00408  *  Encrypts/Decrypts exactly one full block a specified number of rounds.
00409  *  Only used in the Intermediate Value Known Answer Test.  
00410  *
00411  *  Returns:
00412  *      TRUE - on success
00413  *      BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized)
00414  */
00415 int cipherUpdateRounds(cipherInstance *cipher, keyInstance *key,
00416         BYTE *input, int inputLen, BYTE *outBuffer, int rounds) {
00417     u8 block[16];
00418 
00419     if (cipher == NULL || key == NULL) {
00420         return BAD_CIPHER_STATE;
00421     }
00422 
00423     memcpy(block, input, 16);
00424 
00425     switch (key->direction) {
00426     case DIR_ENCRYPT:
00427         rijndaelEncryptRound(key->rk, key->Nr, block, rounds);
00428         break;
00429         
00430     case DIR_DECRYPT:
00431         rijndaelDecryptRound(key->rk, key->Nr, block, rounds);
00432         break;
00433         
00434     default:
00435         return BAD_KEY_DIR;
00436     } 
00437 
00438     memcpy(outBuffer, block, 16);
00439     
00440     return TRUE;
00441 }
00442 #endif /* INTERMEDIATE_VALUE_KAT */

Généré le Thu Sep 6 13:57:46 2007 pour A.I.F. par  doxygen 1.3.9.1