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> 229132d507SHajimu UMEMOTO #include <sys/types.h> 2333841545SHajimu UMEMOTO #ifdef _KERNEL 2433841545SHajimu UMEMOTO #include <sys/systm.h> 2533841545SHajimu UMEMOTO #else 2633841545SHajimu UMEMOTO #include <string.h> 2733841545SHajimu UMEMOTO #endif 28fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-alg-fst.h> 29fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-api-fst.h> 309132d507SHajimu UMEMOTO #include <crypto/rijndael/rijndael_local.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) { 399132d507SHajimu UMEMOTO u8 k[RIJNDAEL_MAXKC][4]; 409132d507SHajimu UMEMOTO int i; 419132d507SHajimu UMEMOTO char *keyMat; 42fe2869c8SKris Kennaway 43fe2869c8SKris Kennaway if (key == NULL) { 44fe2869c8SKris Kennaway return BAD_KEY_INSTANCE; 45fe2869c8SKris Kennaway } 46fe2869c8SKris Kennaway 47fe2869c8SKris Kennaway if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 48fe2869c8SKris Kennaway key->direction = direction; 49fe2869c8SKris Kennaway } else { 50fe2869c8SKris Kennaway return BAD_KEY_DIR; 51fe2869c8SKris Kennaway } 52fe2869c8SKris Kennaway 53fe2869c8SKris Kennaway if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 54fe2869c8SKris Kennaway key->keyLen = keyLen; 55fe2869c8SKris Kennaway } else { 56fe2869c8SKris Kennaway return BAD_KEY_MAT; 57fe2869c8SKris Kennaway } 58fe2869c8SKris Kennaway 59fe2869c8SKris Kennaway if (keyMaterial != NULL) { 609132d507SHajimu UMEMOTO bcopy(keyMaterial, key->keyMaterial, keyLen/8); 61fe2869c8SKris Kennaway } 62fe2869c8SKris Kennaway 639132d507SHajimu UMEMOTO key->ROUNDS = keyLen/32 + 6; 649132d507SHajimu UMEMOTO 65fe2869c8SKris Kennaway /* initialize key schedule: */ 669132d507SHajimu UMEMOTO keyMat = key->keyMaterial; 679132d507SHajimu UMEMOTO for (i = 0; i < key->keyLen/8; i++) { 689132d507SHajimu UMEMOTO k[i >> 2][i & 3] = (u8)keyMat[i]; 69fe2869c8SKris Kennaway } 709132d507SHajimu UMEMOTO rijndaelKeySched(k, key->keySched, key->ROUNDS); 719132d507SHajimu UMEMOTO if (direction == DIR_DECRYPT) { 729132d507SHajimu UMEMOTO rijndaelKeyEncToDec(key->keySched, key->ROUNDS); 739132d507SHajimu UMEMOTO } 749132d507SHajimu UMEMOTO 75fe2869c8SKris Kennaway return TRUE; 76fe2869c8SKris Kennaway } 77fe2869c8SKris Kennaway 78fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 79fe2869c8SKris Kennaway if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 80fe2869c8SKris Kennaway cipher->mode = mode; 81fe2869c8SKris Kennaway } else { 82fe2869c8SKris Kennaway return BAD_CIPHER_MODE; 83fe2869c8SKris Kennaway } 84fe2869c8SKris Kennaway if (IV != NULL) { 859132d507SHajimu UMEMOTO bcopy(IV, cipher->IV, MAX_IV_SIZE); 86fe2869c8SKris Kennaway } else { 879132d507SHajimu UMEMOTO bzero(cipher->IV, MAX_IV_SIZE); 88fe2869c8SKris Kennaway } 89fe2869c8SKris Kennaway return TRUE; 90fe2869c8SKris Kennaway } 91fe2869c8SKris Kennaway 92fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 93fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 949132d507SHajimu UMEMOTO int i, k, numBlocks; 959132d507SHajimu UMEMOTO u8 block[16], iv[4][4]; 96fe2869c8SKris Kennaway 97fe2869c8SKris Kennaway if (cipher == NULL || 98fe2869c8SKris Kennaway key == NULL || 99fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 100fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 101fe2869c8SKris Kennaway } 102fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 103fe2869c8SKris Kennaway return 0; /* nothing to do */ 104fe2869c8SKris Kennaway } 105fe2869c8SKris Kennaway 106fe2869c8SKris Kennaway numBlocks = inputLen/128; 107fe2869c8SKris Kennaway 108fe2869c8SKris Kennaway switch (cipher->mode) { 109fe2869c8SKris Kennaway case MODE_ECB: 110fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 1119132d507SHajimu UMEMOTO rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 112fe2869c8SKris Kennaway input += 16; 113fe2869c8SKris Kennaway outBuffer += 16; 114fe2869c8SKris Kennaway } 115fe2869c8SKris Kennaway break; 116fe2869c8SKris Kennaway 117fe2869c8SKris Kennaway case MODE_CBC: 1183011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1199132d507SHajimu UMEMOTO bcopy(cipher->IV, block, 16); 1209132d507SHajimu UMEMOTO bcopy(input, iv, 16); 1219132d507SHajimu UMEMOTO ((u32*)block)[0] ^= ((u32*)iv)[0]; 1229132d507SHajimu UMEMOTO ((u32*)block)[1] ^= ((u32*)iv)[1]; 1239132d507SHajimu UMEMOTO ((u32*)block)[2] ^= ((u32*)iv)[2]; 1249132d507SHajimu UMEMOTO ((u32*)block)[3] ^= ((u32*)iv)[3]; 1253011d4b3SHajimu UMEMOTO #else 1269132d507SHajimu UMEMOTO ((u32*)block)[0] = ((u32*)cipher->IV)[0] ^ ((u32*)input)[0]; 1279132d507SHajimu UMEMOTO ((u32*)block)[1] = ((u32*)cipher->IV)[1] ^ ((u32*)input)[1]; 1289132d507SHajimu UMEMOTO ((u32*)block)[2] = ((u32*)cipher->IV)[2] ^ ((u32*)input)[2]; 1299132d507SHajimu UMEMOTO ((u32*)block)[3] = ((u32*)cipher->IV)[3] ^ ((u32*)input)[3]; 1303011d4b3SHajimu UMEMOTO #endif 1319132d507SHajimu UMEMOTO rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 132fe2869c8SKris Kennaway input += 16; 1339132d507SHajimu UMEMOTO for (i = numBlocks - 1; i > 0; i--) { 1349132d507SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1359132d507SHajimu UMEMOTO bcopy(outBuffer, block, 16); 1369132d507SHajimu UMEMOTO bcopy(input, iv, 16); 1379132d507SHajimu UMEMOTO ((u32*)block)[0] ^= ((u32*)iv)[0]; 1389132d507SHajimu UMEMOTO ((u32*)block)[1] ^= ((u32*)iv)[1]; 1399132d507SHajimu UMEMOTO ((u32*)block)[2] ^= ((u32*)iv)[2]; 1409132d507SHajimu UMEMOTO ((u32*)block)[3] ^= ((u32*)iv)[3]; 1419132d507SHajimu UMEMOTO #else 1429132d507SHajimu UMEMOTO ((u32*)block)[0] = ((u32*)outBuffer)[0] ^ ((u32*)input)[0]; 1439132d507SHajimu UMEMOTO ((u32*)block)[1] = ((u32*)outBuffer)[1] ^ ((u32*)input)[1]; 1449132d507SHajimu UMEMOTO ((u32*)block)[2] = ((u32*)outBuffer)[2] ^ ((u32*)input)[2]; 1459132d507SHajimu UMEMOTO ((u32*)block)[3] = ((u32*)outBuffer)[3] ^ ((u32*)input)[3]; 1469132d507SHajimu UMEMOTO #endif 147fe2869c8SKris Kennaway outBuffer += 16; 1489132d507SHajimu UMEMOTO rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 1499132d507SHajimu UMEMOTO input += 16; 150fe2869c8SKris Kennaway } 151fe2869c8SKris Kennaway break; 152fe2869c8SKris Kennaway 153fe2869c8SKris Kennaway case MODE_CFB1: 1543011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 1559132d507SHajimu UMEMOTO bcopy(cipher->IV, iv, 16); 1569132d507SHajimu UMEMOTO #else /* !STRICT_ALIGN */ 1579132d507SHajimu UMEMOTO *((u32*)iv[0]) = *((u32*)(cipher->IV )); 1589132d507SHajimu UMEMOTO *((u32*)iv[1]) = *((u32*)(cipher->IV+ 4)); 1599132d507SHajimu UMEMOTO *((u32*)iv[2]) = *((u32*)(cipher->IV+ 8)); 1609132d507SHajimu UMEMOTO *((u32*)iv[3]) = *((u32*)(cipher->IV+12)); 1619132d507SHajimu UMEMOTO #endif /* ?STRICT_ALIGN */ 162fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 163fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 1649132d507SHajimu UMEMOTO *((u32*) block ) = *((u32*)iv[0]); 1659132d507SHajimu UMEMOTO *((u32*)(block+ 4)) = *((u32*)iv[1]); 1669132d507SHajimu UMEMOTO *((u32*)(block+ 8)) = *((u32*)iv[2]); 1679132d507SHajimu UMEMOTO *((u32*)(block+12)) = *((u32*)iv[3]); 1689132d507SHajimu UMEMOTO rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 1699132d507SHajimu UMEMOTO outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 1709132d507SHajimu UMEMOTO iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 1719132d507SHajimu UMEMOTO iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 1729132d507SHajimu UMEMOTO iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 1739132d507SHajimu UMEMOTO iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 1749132d507SHajimu UMEMOTO iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 1759132d507SHajimu UMEMOTO iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 1769132d507SHajimu UMEMOTO iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 1779132d507SHajimu UMEMOTO iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 1789132d507SHajimu UMEMOTO iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 1799132d507SHajimu UMEMOTO iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 1809132d507SHajimu UMEMOTO iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 1819132d507SHajimu UMEMOTO iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 1829132d507SHajimu UMEMOTO iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 1839132d507SHajimu UMEMOTO iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 1849132d507SHajimu UMEMOTO iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 1859132d507SHajimu UMEMOTO iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1); 186fe2869c8SKris Kennaway } 1878f21478bSHajimu UMEMOTO } 188fe2869c8SKris Kennaway break; 189fe2869c8SKris Kennaway 190fe2869c8SKris Kennaway default: 191fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 192fe2869c8SKris Kennaway } 193fe2869c8SKris Kennaway 194fe2869c8SKris Kennaway return 128*numBlocks; 195fe2869c8SKris Kennaway } 196fe2869c8SKris Kennaway 197fe2869c8SKris Kennaway /** 198fe2869c8SKris Kennaway * Encrypt data partitioned in octets, using RFC 2040-like padding. 199fe2869c8SKris Kennaway * 200fe2869c8SKris Kennaway * @param input data to be encrypted (octet sequence) 201fe2869c8SKris Kennaway * @param inputOctets input length in octets (not bits) 202fe2869c8SKris Kennaway * @param outBuffer encrypted output data 203fe2869c8SKris Kennaway * 204fe2869c8SKris Kennaway * @return length in octets (not bits) of the encrypted output buffer. 205fe2869c8SKris Kennaway */ 206fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 207fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 208fe2869c8SKris Kennaway int i, numBlocks, padLen; 2099132d507SHajimu UMEMOTO u8 block[16], *iv, *cp; 210fe2869c8SKris Kennaway 211fe2869c8SKris Kennaway if (cipher == NULL || 212fe2869c8SKris Kennaway key == NULL || 213fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 214fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 215fe2869c8SKris Kennaway } 216fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 217fe2869c8SKris Kennaway return 0; /* nothing to do */ 218fe2869c8SKris Kennaway } 219fe2869c8SKris Kennaway 220fe2869c8SKris Kennaway numBlocks = inputOctets/16; 221fe2869c8SKris Kennaway 222fe2869c8SKris Kennaway switch (cipher->mode) { 223fe2869c8SKris Kennaway case MODE_ECB: 224fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2259132d507SHajimu UMEMOTO rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 226fe2869c8SKris Kennaway input += 16; 227fe2869c8SKris Kennaway outBuffer += 16; 228fe2869c8SKris Kennaway } 229fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 230eb159f5bSHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 23127da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 2329132d507SHajimu UMEMOTO bcopy(input, block, 16 - padLen); 2339132d507SHajimu UMEMOTO for (cp = block + 16 - padLen; cp < block + 16; cp++) 2349132d507SHajimu UMEMOTO *cp = padLen; 2359132d507SHajimu UMEMOTO rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 236fe2869c8SKris Kennaway break; 237fe2869c8SKris Kennaway 238fe2869c8SKris Kennaway case MODE_CBC: 239fe2869c8SKris Kennaway iv = cipher->IV; 240fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2419132d507SHajimu UMEMOTO ((u32*)block)[0] = ((u32*)input)[0] ^ ((u32*)iv)[0]; 2429132d507SHajimu UMEMOTO ((u32*)block)[1] = ((u32*)input)[1] ^ ((u32*)iv)[1]; 2439132d507SHajimu UMEMOTO ((u32*)block)[2] = ((u32*)input)[2] ^ ((u32*)iv)[2]; 2449132d507SHajimu UMEMOTO ((u32*)block)[3] = ((u32*)input)[3] ^ ((u32*)iv)[3]; 2459132d507SHajimu UMEMOTO rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 246fe2869c8SKris Kennaway iv = outBuffer; 247fe2869c8SKris Kennaway input += 16; 248fe2869c8SKris Kennaway outBuffer += 16; 249fe2869c8SKris Kennaway } 250fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 25166476d45SHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 25227da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 253fe2869c8SKris Kennaway for (i = 0; i < 16 - padLen; i++) { 254fe2869c8SKris Kennaway block[i] = input[i] ^ iv[i]; 255fe2869c8SKris Kennaway } 256fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 257fe2869c8SKris Kennaway block[i] = (BYTE)padLen ^ iv[i]; 258fe2869c8SKris Kennaway } 2599132d507SHajimu UMEMOTO rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 260fe2869c8SKris Kennaway break; 261fe2869c8SKris Kennaway 262fe2869c8SKris Kennaway default: 263fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 264fe2869c8SKris Kennaway } 265fe2869c8SKris Kennaway 266fe2869c8SKris Kennaway return 16*(numBlocks + 1); 267fe2869c8SKris Kennaway } 268fe2869c8SKris Kennaway 269fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 270fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 2719132d507SHajimu UMEMOTO int i, k, numBlocks; 2729132d507SHajimu UMEMOTO u8 block[16], iv[4][4]; 273fe2869c8SKris Kennaway 274fe2869c8SKris Kennaway if (cipher == NULL || 275fe2869c8SKris Kennaway key == NULL || 276fe2869c8SKris Kennaway (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 277fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 278fe2869c8SKris Kennaway } 279fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 280fe2869c8SKris Kennaway return 0; /* nothing to do */ 281fe2869c8SKris Kennaway } 282fe2869c8SKris Kennaway 283fe2869c8SKris Kennaway numBlocks = inputLen/128; 284fe2869c8SKris Kennaway 285fe2869c8SKris Kennaway switch (cipher->mode) { 286fe2869c8SKris Kennaway case MODE_ECB: 287fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2889132d507SHajimu UMEMOTO rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 289fe2869c8SKris Kennaway input += 16; 290fe2869c8SKris Kennaway outBuffer += 16; 291fe2869c8SKris Kennaway } 292fe2869c8SKris Kennaway break; 293fe2869c8SKris Kennaway 294fe2869c8SKris Kennaway case MODE_CBC: 2953011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */ 2969132d507SHajimu UMEMOTO bcopy(cipher->IV, iv, 16); 2973011d4b3SHajimu UMEMOTO #else 2989132d507SHajimu UMEMOTO *((u32*)iv[0]) = *((u32*)(cipher->IV )); 2999132d507SHajimu UMEMOTO *((u32*)iv[1]) = *((u32*)(cipher->IV+ 4)); 3009132d507SHajimu UMEMOTO *((u32*)iv[2]) = *((u32*)(cipher->IV+ 8)); 3019132d507SHajimu UMEMOTO *((u32*)iv[3]) = *((u32*)(cipher->IV+12)); 3023011d4b3SHajimu UMEMOTO #endif 303fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 3049132d507SHajimu UMEMOTO rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 3059132d507SHajimu UMEMOTO ((u32*)block)[0] ^= *((u32*)iv[0]); 3069132d507SHajimu UMEMOTO ((u32*)block)[1] ^= *((u32*)iv[1]); 3079132d507SHajimu UMEMOTO ((u32*)block)[2] ^= *((u32*)iv[2]); 3089132d507SHajimu UMEMOTO ((u32*)block)[3] ^= *((u32*)iv[3]); 3093011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/ 3109132d507SHajimu UMEMOTO bcopy(input, iv, 16); 3119132d507SHajimu UMEMOTO bcopy(block, outBuffer, 16); 3123011d4b3SHajimu UMEMOTO #else 3139132d507SHajimu UMEMOTO *((u32*)iv[0]) = ((u32*)input)[0]; ((u32*)outBuffer)[0] = ((u32*)block)[0]; 3149132d507SHajimu UMEMOTO *((u32*)iv[1]) = ((u32*)input)[1]; ((u32*)outBuffer)[1] = ((u32*)block)[1]; 3159132d507SHajimu UMEMOTO *((u32*)iv[2]) = ((u32*)input)[2]; ((u32*)outBuffer)[2] = ((u32*)block)[2]; 3169132d507SHajimu UMEMOTO *((u32*)iv[3]) = ((u32*)input)[3]; ((u32*)outBuffer)[3] = ((u32*)block)[3]; 3173011d4b3SHajimu UMEMOTO #endif 318fe2869c8SKris Kennaway input += 16; 319fe2869c8SKris Kennaway outBuffer += 16; 320fe2869c8SKris Kennaway } 321fe2869c8SKris Kennaway break; 322fe2869c8SKris Kennaway 323fe2869c8SKris Kennaway case MODE_CFB1: 3243011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */ 3259132d507SHajimu UMEMOTO bcopy(cipher->IV, iv, 16); 3263011d4b3SHajimu UMEMOTO #else 3279132d507SHajimu UMEMOTO *((u32*)iv[0]) = *((u32*)(cipher->IV)); 3289132d507SHajimu UMEMOTO *((u32*)iv[1]) = *((u32*)(cipher->IV+ 4)); 3299132d507SHajimu UMEMOTO *((u32*)iv[2]) = *((u32*)(cipher->IV+ 8)); 3309132d507SHajimu UMEMOTO *((u32*)iv[3]) = *((u32*)(cipher->IV+12)); 3313011d4b3SHajimu UMEMOTO #endif 332fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 333fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 3349132d507SHajimu UMEMOTO *((u32*) block ) = *((u32*)iv[0]); 3359132d507SHajimu UMEMOTO *((u32*)(block+ 4)) = *((u32*)iv[1]); 3369132d507SHajimu UMEMOTO *((u32*)(block+ 8)) = *((u32*)iv[2]); 3379132d507SHajimu UMEMOTO *((u32*)(block+12)) = *((u32*)iv[3]); 3389132d507SHajimu UMEMOTO rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 3399132d507SHajimu UMEMOTO iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 3409132d507SHajimu UMEMOTO iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 3419132d507SHajimu UMEMOTO iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 3429132d507SHajimu UMEMOTO iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 3439132d507SHajimu UMEMOTO iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 3449132d507SHajimu UMEMOTO iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 3459132d507SHajimu UMEMOTO iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 3469132d507SHajimu UMEMOTO iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 3479132d507SHajimu UMEMOTO iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 3489132d507SHajimu UMEMOTO iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 3499132d507SHajimu UMEMOTO iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 3509132d507SHajimu UMEMOTO iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 3519132d507SHajimu UMEMOTO iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 3529132d507SHajimu UMEMOTO iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 3539132d507SHajimu UMEMOTO iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 3549132d507SHajimu UMEMOTO iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1); 3559132d507SHajimu UMEMOTO outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 356fe2869c8SKris Kennaway } 3578f21478bSHajimu UMEMOTO } 358fe2869c8SKris Kennaway break; 359fe2869c8SKris Kennaway 360fe2869c8SKris Kennaway default: 361fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 362fe2869c8SKris Kennaway } 363fe2869c8SKris Kennaway 364fe2869c8SKris Kennaway return 128*numBlocks; 365fe2869c8SKris Kennaway } 366fe2869c8SKris Kennaway 367fe2869c8SKris Kennaway int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 368fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 369fe2869c8SKris Kennaway int i, numBlocks, padLen; 3709132d507SHajimu UMEMOTO u8 block[16]; 3719132d507SHajimu UMEMOTO u32 iv[4]; 372fe2869c8SKris Kennaway 373fe2869c8SKris Kennaway if (cipher == NULL || 374fe2869c8SKris Kennaway key == NULL || 375fe2869c8SKris Kennaway key->direction == DIR_ENCRYPT) { 376fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 377fe2869c8SKris Kennaway } 378fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 379fe2869c8SKris Kennaway return 0; /* nothing to do */ 380fe2869c8SKris Kennaway } 381fe2869c8SKris Kennaway if (inputOctets % 16 != 0) { 382fe2869c8SKris Kennaway return BAD_DATA; 383fe2869c8SKris Kennaway } 384fe2869c8SKris Kennaway 385fe2869c8SKris Kennaway numBlocks = inputOctets/16; 386fe2869c8SKris Kennaway 387fe2869c8SKris Kennaway switch (cipher->mode) { 388fe2869c8SKris Kennaway case MODE_ECB: 389fe2869c8SKris Kennaway /* all blocks but last */ 390fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 3919132d507SHajimu UMEMOTO rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 392fe2869c8SKris Kennaway input += 16; 393fe2869c8SKris Kennaway outBuffer += 16; 394fe2869c8SKris Kennaway } 395fe2869c8SKris Kennaway /* last block */ 3969132d507SHajimu UMEMOTO rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 397fe2869c8SKris Kennaway padLen = block[15]; 398fe2869c8SKris Kennaway if (padLen >= 16) { 399fe2869c8SKris Kennaway return BAD_DATA; 400fe2869c8SKris Kennaway } 401fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 402fe2869c8SKris Kennaway if (block[i] != padLen) { 403fe2869c8SKris Kennaway return BAD_DATA; 404fe2869c8SKris Kennaway } 405fe2869c8SKris Kennaway } 4069132d507SHajimu UMEMOTO bcopy(block, outBuffer, 16 - padLen); 407fe2869c8SKris Kennaway break; 408fe2869c8SKris Kennaway 409fe2869c8SKris Kennaway case MODE_CBC: 4109132d507SHajimu UMEMOTO bcopy(cipher->IV, iv, 16); 411fe2869c8SKris Kennaway /* all blocks but last */ 412fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 4139132d507SHajimu UMEMOTO rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 4149132d507SHajimu UMEMOTO ((u32*)block)[0] ^= iv[0]; 4159132d507SHajimu UMEMOTO ((u32*)block)[1] ^= iv[1]; 4169132d507SHajimu UMEMOTO ((u32*)block)[2] ^= iv[2]; 4179132d507SHajimu UMEMOTO ((u32*)block)[3] ^= iv[3]; 4189132d507SHajimu UMEMOTO bcopy(input, iv, 16); 4199132d507SHajimu UMEMOTO bcopy(block, outBuffer, 16); 420fe2869c8SKris Kennaway input += 16; 421fe2869c8SKris Kennaway outBuffer += 16; 422fe2869c8SKris Kennaway } 423fe2869c8SKris Kennaway /* last block */ 4249132d507SHajimu UMEMOTO rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 4259132d507SHajimu UMEMOTO ((u32*)block)[0] ^= iv[0]; 4269132d507SHajimu UMEMOTO ((u32*)block)[1] ^= iv[1]; 4279132d507SHajimu UMEMOTO ((u32*)block)[2] ^= iv[2]; 4289132d507SHajimu UMEMOTO ((u32*)block)[3] ^= iv[3]; 429fe2869c8SKris Kennaway padLen = block[15]; 430fe2869c8SKris Kennaway if (padLen <= 0 || padLen > 16) { 431fe2869c8SKris Kennaway return BAD_DATA; 432fe2869c8SKris Kennaway } 433fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 434fe2869c8SKris Kennaway if (block[i] != padLen) { 435fe2869c8SKris Kennaway return BAD_DATA; 436fe2869c8SKris Kennaway } 437fe2869c8SKris Kennaway } 4389132d507SHajimu UMEMOTO bcopy(block, outBuffer, 16 - padLen); 439fe2869c8SKris Kennaway break; 440fe2869c8SKris Kennaway 441fe2869c8SKris Kennaway default: 442fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 443fe2869c8SKris Kennaway } 444fe2869c8SKris Kennaway 445fe2869c8SKris Kennaway return 16*numBlocks - padLen; 446fe2869c8SKris Kennaway } 447fe2869c8SKris Kennaway 4489132d507SHajimu UMEMOTO #ifdef INTERMEDIATE_VALUE_KAT 4499132d507SHajimu UMEMOTO /** 4509132d507SHajimu UMEMOTO * cipherUpdateRounds: 4519132d507SHajimu UMEMOTO * 4529132d507SHajimu UMEMOTO * Encrypts/Decrypts exactly one full block a specified number of rounds. 4539132d507SHajimu UMEMOTO * Only used in the Intermediate Value Known Answer Test. 4549132d507SHajimu UMEMOTO * 4559132d507SHajimu UMEMOTO * Returns: 4569132d507SHajimu UMEMOTO * TRUE - on success 4579132d507SHajimu UMEMOTO * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized) 4589132d507SHajimu UMEMOTO */ 4599132d507SHajimu UMEMOTO int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key, 4609132d507SHajimu UMEMOTO BYTE *input, int inputLen, BYTE *outBuffer, int rounds) { 4619132d507SHajimu UMEMOTO int j; 4629132d507SHajimu UMEMOTO u8 block[4][4]; 4639132d507SHajimu UMEMOTO 4649132d507SHajimu UMEMOTO if (cipher == NULL || key == NULL) { 4659132d507SHajimu UMEMOTO return BAD_CIPHER_STATE; 4669132d507SHajimu UMEMOTO } 4679132d507SHajimu UMEMOTO 4689132d507SHajimu UMEMOTO for (j = 3; j >= 0; j--) { 4699132d507SHajimu UMEMOTO /* parse input stream into rectangular array */ 4709132d507SHajimu UMEMOTO *((u32*)block[j]) = *((u32*)(input+4*j)); 4719132d507SHajimu UMEMOTO } 4729132d507SHajimu UMEMOTO 4739132d507SHajimu UMEMOTO switch (key->direction) { 4749132d507SHajimu UMEMOTO case DIR_ENCRYPT: 4759132d507SHajimu UMEMOTO rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds); 4769132d507SHajimu UMEMOTO break; 4779132d507SHajimu UMEMOTO 4789132d507SHajimu UMEMOTO case DIR_DECRYPT: 4799132d507SHajimu UMEMOTO rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds); 4809132d507SHajimu UMEMOTO break; 4819132d507SHajimu UMEMOTO 4829132d507SHajimu UMEMOTO default: 4839132d507SHajimu UMEMOTO return BAD_KEY_DIR; 4849132d507SHajimu UMEMOTO } 4859132d507SHajimu UMEMOTO 4869132d507SHajimu UMEMOTO for (j = 3; j >= 0; j--) { 4879132d507SHajimu UMEMOTO /* parse rectangular array into output ciphertext bytes */ 4889132d507SHajimu UMEMOTO *((u32*)(outBuffer+4*j)) = *((u32*)block[j]); 4899132d507SHajimu UMEMOTO } 4909132d507SHajimu UMEMOTO 4919132d507SHajimu UMEMOTO return TRUE; 4929132d507SHajimu UMEMOTO } 4939132d507SHajimu UMEMOTO #endif /* INTERMEDIATE_VALUE_KAT */ 494