19132d507SHajimu UMEMOTO /* $KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $ */ 2fe2869c8SKris Kennaway 39132d507SHajimu UMEMOTO /* 49132d507SHajimu UMEMOTO * rijndael-api-fst.c v2.3 April '2000 5fe2869c8SKris Kennaway * 69132d507SHajimu UMEMOTO * Optimised ANSI C code 7fe2869c8SKris Kennaway * 89132d507SHajimu UMEMOTO * authors: v1.0: Antoon Bosselaers 99132d507SHajimu UMEMOTO * v2.0: Vincent Rijmen 109132d507SHajimu UMEMOTO * v2.1: Vincent Rijmen 119132d507SHajimu UMEMOTO * v2.2: Vincent Rijmen 129132d507SHajimu UMEMOTO * v2.3: Paulo Barreto 139132d507SHajimu UMEMOTO * v2.4: Vincent Rijmen 14fe2869c8SKris Kennaway * 159132d507SHajimu UMEMOTO * This code is placed in the public domain. 16fe2869c8SKris Kennaway */ 17fe2869c8SKris Kennaway 18ad39da78SDavid E. O'Brien #include <sys/cdefs.h> 19ad39da78SDavid E. O'Brien __FBSDID("$FreeBSD$"); 20ad39da78SDavid E. O'Brien 21fe2869c8SKris Kennaway #include <sys/param.h> 2233841545SHajimu UMEMOTO #ifdef _KERNEL 2333841545SHajimu UMEMOTO #include <sys/systm.h> 2433841545SHajimu UMEMOTO #else 2533841545SHajimu UMEMOTO #include <string.h> 2633841545SHajimu UMEMOTO #endif 275129dcfcSHajimu UMEMOTO 285129dcfcSHajimu UMEMOTO #include <crypto/rijndael/rijndael_local.h> 29fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-alg-fst.h> 30fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-api-fst.h> 319132d507SHajimu UMEMOTO 329132d507SHajimu UMEMOTO #ifndef TRUE 339132d507SHajimu UMEMOTO #define TRUE 1 349132d507SHajimu UMEMOTO #endif 359132d507SHajimu UMEMOTO 369132d507SHajimu UMEMOTO typedef u_int8_t BYTE; 3727da1009SPoul-Henning Kamp 38fe2869c8SKris Kennaway int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { 395129dcfcSHajimu UMEMOTO u_int8_t cipherKey[RIJNDAEL_MAXKB]; 40fe2869c8SKris Kennaway 41fe2869c8SKris Kennaway if (key == NULL) { 42fe2869c8SKris Kennaway return BAD_KEY_INSTANCE; 43fe2869c8SKris Kennaway } 44fe2869c8SKris Kennaway 45fe2869c8SKris Kennaway if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 46fe2869c8SKris Kennaway key->direction = direction; 47fe2869c8SKris Kennaway } else { 48fe2869c8SKris Kennaway return BAD_KEY_DIR; 49fe2869c8SKris Kennaway } 50fe2869c8SKris Kennaway 51fe2869c8SKris Kennaway if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 52fe2869c8SKris Kennaway key->keyLen = keyLen; 53fe2869c8SKris Kennaway } else { 54fe2869c8SKris Kennaway return BAD_KEY_MAT; 55fe2869c8SKris Kennaway } 56fe2869c8SKris Kennaway 57fe2869c8SKris Kennaway if (keyMaterial != NULL) { 585129dcfcSHajimu UMEMOTO memcpy(key->keyMaterial, keyMaterial, keyLen/8); 59fe2869c8SKris Kennaway } 60fe2869c8SKris Kennaway 61fe2869c8SKris Kennaway /* initialize key schedule: */ 625129dcfcSHajimu UMEMOTO memcpy(cipherKey, key->keyMaterial, keyLen/8); 635129dcfcSHajimu UMEMOTO if (direction == DIR_ENCRYPT) { 645129dcfcSHajimu UMEMOTO key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen); 655129dcfcSHajimu UMEMOTO } else { 665129dcfcSHajimu UMEMOTO key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen); 67fe2869c8SKris Kennaway } 685129dcfcSHajimu UMEMOTO rijndaelKeySetupEnc(key->ek, cipherKey, keyLen); 69fe2869c8SKris Kennaway return TRUE; 70fe2869c8SKris Kennaway } 71fe2869c8SKris Kennaway 72fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 73fe2869c8SKris Kennaway if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 74fe2869c8SKris Kennaway cipher->mode = mode; 75fe2869c8SKris Kennaway } else { 76fe2869c8SKris Kennaway return BAD_CIPHER_MODE; 77fe2869c8SKris Kennaway } 78fe2869c8SKris Kennaway if (IV != NULL) { 795129dcfcSHajimu UMEMOTO memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE); 80fe2869c8SKris Kennaway } else { 815129dcfcSHajimu UMEMOTO memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE); 82fe2869c8SKris Kennaway } 83fe2869c8SKris Kennaway return TRUE; 84fe2869c8SKris Kennaway } 85fe2869c8SKris Kennaway 86fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 87fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 889132d507SHajimu UMEMOTO int i, k, numBlocks; 895129dcfcSHajimu UMEMOTO u_int8_t block[16], iv[4][4]; 90fe2869c8SKris Kennaway 91fe2869c8SKris Kennaway if (cipher == NULL || 92fe2869c8SKris Kennaway key == NULL || 93fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 94fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 95fe2869c8SKris Kennaway } 96fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 97fe2869c8SKris Kennaway return 0; /* nothing to do */ 98fe2869c8SKris Kennaway } 99fe2869c8SKris Kennaway 100fe2869c8SKris Kennaway numBlocks = inputLen/128; 101fe2869c8SKris Kennaway 102fe2869c8SKris Kennaway switch (cipher->mode) { 103fe2869c8SKris Kennaway case MODE_ECB: 104fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 1055129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 106fe2869c8SKris Kennaway input += 16; 107fe2869c8SKris Kennaway outBuffer += 16; 108fe2869c8SKris Kennaway } 109fe2869c8SKris Kennaway break; 110fe2869c8SKris Kennaway 111fe2869c8SKris Kennaway case MODE_CBC: 1123011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1135129dcfcSHajimu UMEMOTO memcpy(block, cipher->IV, 16); 1145129dcfcSHajimu UMEMOTO memcpy(iv, input, 16); 1155129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0]; 1165129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1]; 1175129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2]; 1185129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3]; 1193011d4b3SHajimu UMEMOTO #else 1205129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] = ((u_int32_t*)cipher->IV)[0] ^ ((u_int32_t*)input)[0]; 1215129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] = ((u_int32_t*)cipher->IV)[1] ^ ((u_int32_t*)input)[1]; 1225129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] = ((u_int32_t*)cipher->IV)[2] ^ ((u_int32_t*)input)[2]; 1235129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] = ((u_int32_t*)cipher->IV)[3] ^ ((u_int32_t*)input)[3]; 1243011d4b3SHajimu UMEMOTO #endif 1255129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 126fe2869c8SKris Kennaway input += 16; 1279132d507SHajimu UMEMOTO for (i = numBlocks - 1; i > 0; i--) { 1289132d507SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1295129dcfcSHajimu UMEMOTO memcpy(block, outBuffer, 16); 1305129dcfcSHajimu UMEMOTO memcpy(iv, input, 16); 1315129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0]; 1325129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1]; 1335129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2]; 1345129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3]; 1359132d507SHajimu UMEMOTO #else 1365129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] = ((u_int32_t*)outBuffer)[0] ^ ((u_int32_t*)input)[0]; 1375129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] = ((u_int32_t*)outBuffer)[1] ^ ((u_int32_t*)input)[1]; 1385129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] = ((u_int32_t*)outBuffer)[2] ^ ((u_int32_t*)input)[2]; 1395129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] = ((u_int32_t*)outBuffer)[3] ^ ((u_int32_t*)input)[3]; 1409132d507SHajimu UMEMOTO #endif 141fe2869c8SKris Kennaway outBuffer += 16; 1425129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 1439132d507SHajimu UMEMOTO input += 16; 144fe2869c8SKris Kennaway } 145fe2869c8SKris Kennaway break; 146fe2869c8SKris Kennaway 147fe2869c8SKris Kennaway case MODE_CFB1: 1483011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1495129dcfcSHajimu UMEMOTO memcpy(iv, cipher->IV, 16); 1509132d507SHajimu UMEMOTO #else /* !STRICT_ALIGN */ 1515129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV )); 1525129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4)); 1535129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8)); 1545129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12)); 1559132d507SHajimu UMEMOTO #endif /* ?STRICT_ALIGN */ 156fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 157fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 1585129dcfcSHajimu UMEMOTO *((u_int32_t*) block ) = *((u_int32_t*)iv[0]); 1595129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]); 1605129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]); 1615129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]); 1625129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->ek, key->Nr, block, 1635129dcfcSHajimu UMEMOTO block); 1649132d507SHajimu UMEMOTO outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 1659132d507SHajimu UMEMOTO iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 1669132d507SHajimu UMEMOTO iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 1679132d507SHajimu UMEMOTO iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 1689132d507SHajimu UMEMOTO iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 1699132d507SHajimu UMEMOTO iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 1709132d507SHajimu UMEMOTO iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 1719132d507SHajimu UMEMOTO iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 1729132d507SHajimu UMEMOTO iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 1739132d507SHajimu UMEMOTO iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 1749132d507SHajimu UMEMOTO iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 1759132d507SHajimu UMEMOTO iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 1769132d507SHajimu UMEMOTO iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 1779132d507SHajimu UMEMOTO iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 1789132d507SHajimu UMEMOTO iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 1799132d507SHajimu UMEMOTO iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 1809132d507SHajimu UMEMOTO iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1); 181fe2869c8SKris Kennaway } 1828f21478bSHajimu UMEMOTO } 183fe2869c8SKris Kennaway break; 184fe2869c8SKris Kennaway 185fe2869c8SKris Kennaway default: 186fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 187fe2869c8SKris Kennaway } 188fe2869c8SKris Kennaway 189fe2869c8SKris Kennaway return 128*numBlocks; 190fe2869c8SKris Kennaway } 191fe2869c8SKris Kennaway 192fe2869c8SKris Kennaway /** 193fe2869c8SKris Kennaway * Encrypt data partitioned in octets, using RFC 2040-like padding. 194fe2869c8SKris Kennaway * 195fe2869c8SKris Kennaway * @param input data to be encrypted (octet sequence) 196fe2869c8SKris Kennaway * @param inputOctets input length in octets (not bits) 197fe2869c8SKris Kennaway * @param outBuffer encrypted output data 198fe2869c8SKris Kennaway * 199fe2869c8SKris Kennaway * @return length in octets (not bits) of the encrypted output buffer. 200fe2869c8SKris Kennaway */ 201fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 202fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 203fe2869c8SKris Kennaway int i, numBlocks, padLen; 2045129dcfcSHajimu UMEMOTO u_int8_t block[16], *iv, *cp; 205fe2869c8SKris Kennaway 206fe2869c8SKris Kennaway if (cipher == NULL || 207fe2869c8SKris Kennaway key == NULL || 208fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 209fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 210fe2869c8SKris Kennaway } 211fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 212fe2869c8SKris Kennaway return 0; /* nothing to do */ 213fe2869c8SKris Kennaway } 214fe2869c8SKris Kennaway 215fe2869c8SKris Kennaway numBlocks = inputOctets/16; 216fe2869c8SKris Kennaway 217fe2869c8SKris Kennaway switch (cipher->mode) { 218fe2869c8SKris Kennaway case MODE_ECB: 219fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2205129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 221fe2869c8SKris Kennaway input += 16; 222fe2869c8SKris Kennaway outBuffer += 16; 223fe2869c8SKris Kennaway } 224fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 225eb159f5bSHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 22627da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 2275129dcfcSHajimu UMEMOTO memcpy(block, input, 16 - padLen); 2289132d507SHajimu UMEMOTO for (cp = block + 16 - padLen; cp < block + 16; cp++) 2299132d507SHajimu UMEMOTO *cp = padLen; 2305129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 231fe2869c8SKris Kennaway break; 232fe2869c8SKris Kennaway 233fe2869c8SKris Kennaway case MODE_CBC: 234fe2869c8SKris Kennaway iv = cipher->IV; 235fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2365129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0]; 2375129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1]; 2385129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2]; 2395129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3]; 2405129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 241fe2869c8SKris Kennaway iv = outBuffer; 242fe2869c8SKris Kennaway input += 16; 243fe2869c8SKris Kennaway outBuffer += 16; 244fe2869c8SKris Kennaway } 245fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 24666476d45SHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 24727da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 248fe2869c8SKris Kennaway for (i = 0; i < 16 - padLen; i++) { 249fe2869c8SKris Kennaway block[i] = input[i] ^ iv[i]; 250fe2869c8SKris Kennaway } 251fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 252fe2869c8SKris Kennaway block[i] = (BYTE)padLen ^ iv[i]; 253fe2869c8SKris Kennaway } 2545129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 255fe2869c8SKris Kennaway break; 256fe2869c8SKris Kennaway 257fe2869c8SKris Kennaway default: 258fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 259fe2869c8SKris Kennaway } 260fe2869c8SKris Kennaway 261fe2869c8SKris Kennaway return 16*(numBlocks + 1); 262fe2869c8SKris Kennaway } 263fe2869c8SKris Kennaway 264fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 265fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 2669132d507SHajimu UMEMOTO int i, k, numBlocks; 2675129dcfcSHajimu UMEMOTO u_int8_t block[16], iv[4][4]; 268fe2869c8SKris Kennaway 269fe2869c8SKris Kennaway if (cipher == NULL || 270fe2869c8SKris Kennaway key == NULL || 271fe2869c8SKris Kennaway (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 272fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 273fe2869c8SKris Kennaway } 274fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 275fe2869c8SKris Kennaway return 0; /* nothing to do */ 276fe2869c8SKris Kennaway } 277fe2869c8SKris Kennaway 278fe2869c8SKris Kennaway numBlocks = inputLen/128; 279fe2869c8SKris Kennaway 280fe2869c8SKris Kennaway switch (cipher->mode) { 281fe2869c8SKris Kennaway case MODE_ECB: 282fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2835129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 284fe2869c8SKris Kennaway input += 16; 285fe2869c8SKris Kennaway outBuffer += 16; 286fe2869c8SKris Kennaway } 287fe2869c8SKris Kennaway break; 288fe2869c8SKris Kennaway 289fe2869c8SKris Kennaway case MODE_CBC: 2903011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */ 2915129dcfcSHajimu UMEMOTO memcpy(iv, cipher->IV, 16); 2923011d4b3SHajimu UMEMOTO #else 2935129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV )); 2945129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4)); 2955129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8)); 2965129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12)); 2973011d4b3SHajimu UMEMOTO #endif 298fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2995129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 3005129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= *((u_int32_t*)iv[0]); 3015129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= *((u_int32_t*)iv[1]); 3025129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= *((u_int32_t*)iv[2]); 3035129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= *((u_int32_t*)iv[3]); 3043011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 3055129dcfcSHajimu UMEMOTO memcpy(iv, input, 16); 3065129dcfcSHajimu UMEMOTO memcpy(outBuffer, block, 16); 3073011d4b3SHajimu UMEMOTO #else 3085129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[0]) = ((u_int32_t*)input)[0]; ((u_int32_t*)outBuffer)[0] = ((u_int32_t*)block)[0]; 3095129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[1]) = ((u_int32_t*)input)[1]; ((u_int32_t*)outBuffer)[1] = ((u_int32_t*)block)[1]; 3105129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[2]) = ((u_int32_t*)input)[2]; ((u_int32_t*)outBuffer)[2] = ((u_int32_t*)block)[2]; 3115129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[3]) = ((u_int32_t*)input)[3]; ((u_int32_t*)outBuffer)[3] = ((u_int32_t*)block)[3]; 3123011d4b3SHajimu UMEMOTO #endif 313fe2869c8SKris Kennaway input += 16; 314fe2869c8SKris Kennaway outBuffer += 16; 315fe2869c8SKris Kennaway } 316fe2869c8SKris Kennaway break; 317fe2869c8SKris Kennaway 318fe2869c8SKris Kennaway case MODE_CFB1: 3193011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */ 3205129dcfcSHajimu UMEMOTO memcpy(iv, cipher->IV, 16); 3213011d4b3SHajimu UMEMOTO #else 3225129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV)); 3235129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4)); 3245129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8)); 3255129dcfcSHajimu UMEMOTO *((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12)); 3263011d4b3SHajimu UMEMOTO #endif 327fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 328fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 3295129dcfcSHajimu UMEMOTO *((u_int32_t*) block ) = *((u_int32_t*)iv[0]); 3305129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]); 3315129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]); 3325129dcfcSHajimu UMEMOTO *((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]); 3335129dcfcSHajimu UMEMOTO rijndaelEncrypt(key->ek, key->Nr, block, 3345129dcfcSHajimu UMEMOTO block); 3359132d507SHajimu UMEMOTO iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 3369132d507SHajimu UMEMOTO iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 3379132d507SHajimu UMEMOTO iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 3389132d507SHajimu UMEMOTO iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 3399132d507SHajimu UMEMOTO iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 3409132d507SHajimu UMEMOTO iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 3419132d507SHajimu UMEMOTO iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 3429132d507SHajimu UMEMOTO iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 3439132d507SHajimu UMEMOTO iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 3449132d507SHajimu UMEMOTO iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 3459132d507SHajimu UMEMOTO iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 3469132d507SHajimu UMEMOTO iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 3479132d507SHajimu UMEMOTO iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 3489132d507SHajimu UMEMOTO iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 3499132d507SHajimu UMEMOTO iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 3509132d507SHajimu UMEMOTO iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1); 3519132d507SHajimu UMEMOTO outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 352fe2869c8SKris Kennaway } 3538f21478bSHajimu UMEMOTO } 354fe2869c8SKris Kennaway break; 355fe2869c8SKris Kennaway 356fe2869c8SKris Kennaway default: 357fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 358fe2869c8SKris Kennaway } 359fe2869c8SKris Kennaway 360fe2869c8SKris Kennaway return 128*numBlocks; 361fe2869c8SKris Kennaway } 362fe2869c8SKris Kennaway 363fe2869c8SKris Kennaway int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 364fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 365fe2869c8SKris Kennaway int i, numBlocks, padLen; 3665129dcfcSHajimu UMEMOTO u_int8_t block[16]; 3675129dcfcSHajimu UMEMOTO u_int32_t iv[4]; 368fe2869c8SKris Kennaway 369fe2869c8SKris Kennaway if (cipher == NULL || 370fe2869c8SKris Kennaway key == NULL || 371fe2869c8SKris Kennaway key->direction == DIR_ENCRYPT) { 372fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 373fe2869c8SKris Kennaway } 374fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 375fe2869c8SKris Kennaway return 0; /* nothing to do */ 376fe2869c8SKris Kennaway } 377fe2869c8SKris Kennaway if (inputOctets % 16 != 0) { 378fe2869c8SKris Kennaway return BAD_DATA; 379fe2869c8SKris Kennaway } 380fe2869c8SKris Kennaway 381fe2869c8SKris Kennaway numBlocks = inputOctets/16; 382fe2869c8SKris Kennaway 383fe2869c8SKris Kennaway switch (cipher->mode) { 384fe2869c8SKris Kennaway case MODE_ECB: 385fe2869c8SKris Kennaway /* all blocks but last */ 386fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 3875129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 388fe2869c8SKris Kennaway input += 16; 389fe2869c8SKris Kennaway outBuffer += 16; 390fe2869c8SKris Kennaway } 391fe2869c8SKris Kennaway /* last block */ 3925129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 393fe2869c8SKris Kennaway padLen = block[15]; 394fe2869c8SKris Kennaway if (padLen >= 16) { 395fe2869c8SKris Kennaway return BAD_DATA; 396fe2869c8SKris Kennaway } 397fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 398fe2869c8SKris Kennaway if (block[i] != padLen) { 399fe2869c8SKris Kennaway return BAD_DATA; 400fe2869c8SKris Kennaway } 401fe2869c8SKris Kennaway } 4025129dcfcSHajimu UMEMOTO memcpy(outBuffer, block, 16 - padLen); 403fe2869c8SKris Kennaway break; 404fe2869c8SKris Kennaway 405fe2869c8SKris Kennaway case MODE_CBC: 4065129dcfcSHajimu UMEMOTO memcpy(iv, cipher->IV, 16); 407fe2869c8SKris Kennaway /* all blocks but last */ 408fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 4095129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 4105129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= iv[0]; 4115129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= iv[1]; 4125129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= iv[2]; 4135129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= iv[3]; 4145129dcfcSHajimu UMEMOTO memcpy(iv, input, 16); 4155129dcfcSHajimu UMEMOTO memcpy(outBuffer, block, 16); 416fe2869c8SKris Kennaway input += 16; 417fe2869c8SKris Kennaway outBuffer += 16; 418fe2869c8SKris Kennaway } 419fe2869c8SKris Kennaway /* last block */ 4205129dcfcSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 4215129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= iv[0]; 4225129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= iv[1]; 4235129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= iv[2]; 4245129dcfcSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= iv[3]; 425fe2869c8SKris Kennaway padLen = block[15]; 426fe2869c8SKris Kennaway if (padLen <= 0 || padLen > 16) { 427fe2869c8SKris Kennaway return BAD_DATA; 428fe2869c8SKris Kennaway } 429fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 430fe2869c8SKris Kennaway if (block[i] != padLen) { 431fe2869c8SKris Kennaway return BAD_DATA; 432fe2869c8SKris Kennaway } 433fe2869c8SKris Kennaway } 4345129dcfcSHajimu UMEMOTO memcpy(outBuffer, block, 16 - padLen); 435fe2869c8SKris Kennaway break; 436fe2869c8SKris Kennaway 437fe2869c8SKris Kennaway default: 438fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 439fe2869c8SKris Kennaway } 440fe2869c8SKris Kennaway 441fe2869c8SKris Kennaway return 16*numBlocks - padLen; 442fe2869c8SKris Kennaway } 443