133841545SHajimu UMEMOTO /* $KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $ */ 2fe2869c8SKris Kennaway 3fe2869c8SKris Kennaway /* 4fe2869c8SKris Kennaway * rijndael-api-fst.c v2.3 April '2000 5fe2869c8SKris Kennaway * 6fe2869c8SKris Kennaway * Optimised ANSI C code 7fe2869c8SKris Kennaway * 8fe2869c8SKris Kennaway * authors: v1.0: Antoon Bosselaers 9fe2869c8SKris Kennaway * v2.0: Vincent Rijmen 10fe2869c8SKris Kennaway * v2.1: Vincent Rijmen 11fe2869c8SKris Kennaway * v2.2: Vincent Rijmen 12fe2869c8SKris Kennaway * v2.3: Paulo Barreto 13fe2869c8SKris Kennaway * v2.4: Vincent Rijmen 14fe2869c8SKris Kennaway * 15fe2869c8SKris Kennaway * 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> 22fe2869c8SKris Kennaway #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> 30fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael_local.h> 31fe2869c8SKris Kennaway 3227da1009SPoul-Henning Kamp #ifndef TRUE 3327da1009SPoul-Henning Kamp #define TRUE 1 3427da1009SPoul-Henning Kamp #endif 3527da1009SPoul-Henning Kamp 36fe2869c8SKris Kennaway int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { 37fe2869c8SKris Kennaway word8 k[MAXKC][4]; 38fe2869c8SKris Kennaway int i; 39fe2869c8SKris Kennaway char *keyMat; 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) { 5833841545SHajimu UMEMOTO bcopy(keyMaterial, key->keyMaterial, keyLen/8); 59fe2869c8SKris Kennaway } 60fe2869c8SKris Kennaway 61fe2869c8SKris Kennaway key->ROUNDS = keyLen/32 + 6; 62fe2869c8SKris Kennaway 63fe2869c8SKris Kennaway /* initialize key schedule: */ 64fe2869c8SKris Kennaway keyMat = key->keyMaterial; 65fe2869c8SKris Kennaway for (i = 0; i < key->keyLen/8; i++) { 66fe2869c8SKris Kennaway k[i >> 2][i & 3] = (word8)keyMat[i]; 67fe2869c8SKris Kennaway } 68fe2869c8SKris Kennaway rijndaelKeySched(k, key->keySched, key->ROUNDS); 69fe2869c8SKris Kennaway if (direction == DIR_DECRYPT) { 70fe2869c8SKris Kennaway rijndaelKeyEncToDec(key->keySched, key->ROUNDS); 71fe2869c8SKris Kennaway } 72fe2869c8SKris Kennaway 73fe2869c8SKris Kennaway return TRUE; 74fe2869c8SKris Kennaway } 75fe2869c8SKris Kennaway 76fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 77fe2869c8SKris Kennaway if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 78fe2869c8SKris Kennaway cipher->mode = mode; 79fe2869c8SKris Kennaway } else { 80fe2869c8SKris Kennaway return BAD_CIPHER_MODE; 81fe2869c8SKris Kennaway } 82fe2869c8SKris Kennaway if (IV != NULL) { 83fe2869c8SKris Kennaway bcopy(IV, cipher->IV, MAX_IV_SIZE); 84fe2869c8SKris Kennaway } else { 85fe2869c8SKris Kennaway bzero(cipher->IV, MAX_IV_SIZE); 86fe2869c8SKris Kennaway } 87fe2869c8SKris Kennaway return TRUE; 88fe2869c8SKris Kennaway } 89fe2869c8SKris Kennaway 90fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 91fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 92fe2869c8SKris Kennaway int i, k, numBlocks; 93fe2869c8SKris Kennaway word8 block[16], iv[4][4]; 94fe2869c8SKris Kennaway 95fe2869c8SKris Kennaway if (cipher == NULL || 96fe2869c8SKris Kennaway key == NULL || 97fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 98fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 99fe2869c8SKris Kennaway } 100fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 101fe2869c8SKris Kennaway return 0; /* nothing to do */ 102fe2869c8SKris Kennaway } 103fe2869c8SKris Kennaway 104fe2869c8SKris Kennaway numBlocks = inputLen/128; 105fe2869c8SKris Kennaway 106fe2869c8SKris Kennaway switch (cipher->mode) { 107fe2869c8SKris Kennaway case MODE_ECB: 108fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 109fe2869c8SKris Kennaway rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 110fe2869c8SKris Kennaway input += 16; 111fe2869c8SKris Kennaway outBuffer += 16; 112fe2869c8SKris Kennaway } 113fe2869c8SKris Kennaway break; 114fe2869c8SKris Kennaway 115fe2869c8SKris Kennaway case MODE_CBC: 116fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN*/ 117fe2869c8SKris Kennaway bcopy(cipher->IV, block, 16); 118fe2869c8SKris Kennaway bcopy(input, iv, 16); 119fe2869c8SKris Kennaway ((word32*)block)[0] ^= ((word32*)iv)[0]; 120fe2869c8SKris Kennaway ((word32*)block)[1] ^= ((word32*)iv)[1]; 121fe2869c8SKris Kennaway ((word32*)block)[2] ^= ((word32*)iv)[2]; 122fe2869c8SKris Kennaway ((word32*)block)[3] ^= ((word32*)iv)[3]; 123fe2869c8SKris Kennaway #else 124fe2869c8SKris Kennaway ((word32*)block)[0] = ((word32*)cipher->IV)[0] ^ ((word32*)input)[0]; 125fe2869c8SKris Kennaway ((word32*)block)[1] = ((word32*)cipher->IV)[1] ^ ((word32*)input)[1]; 126fe2869c8SKris Kennaway ((word32*)block)[2] = ((word32*)cipher->IV)[2] ^ ((word32*)input)[2]; 127fe2869c8SKris Kennaway ((word32*)block)[3] = ((word32*)cipher->IV)[3] ^ ((word32*)input)[3]; 128fe2869c8SKris Kennaway #endif 129fe2869c8SKris Kennaway rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 130fe2869c8SKris Kennaway input += 16; 131fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 132fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN*/ 133fe2869c8SKris Kennaway bcopy(outBuffer, block, 16); 134db491696SSUZUKI Shinsuke bcopy(input, iv, 16); 135fe2869c8SKris Kennaway ((word32*)block)[0] ^= ((word32*)iv)[0]; 136fe2869c8SKris Kennaway ((word32*)block)[1] ^= ((word32*)iv)[1]; 137fe2869c8SKris Kennaway ((word32*)block)[2] ^= ((word32*)iv)[2]; 138fe2869c8SKris Kennaway ((word32*)block)[3] ^= ((word32*)iv)[3]; 139fe2869c8SKris Kennaway #else 140fe2869c8SKris Kennaway ((word32*)block)[0] = ((word32*)outBuffer)[0] ^ ((word32*)input)[0]; 141fe2869c8SKris Kennaway ((word32*)block)[1] = ((word32*)outBuffer)[1] ^ ((word32*)input)[1]; 142fe2869c8SKris Kennaway ((word32*)block)[2] = ((word32*)outBuffer)[2] ^ ((word32*)input)[2]; 143fe2869c8SKris Kennaway ((word32*)block)[3] = ((word32*)outBuffer)[3] ^ ((word32*)input)[3]; 144fe2869c8SKris Kennaway #endif 145fe2869c8SKris Kennaway outBuffer += 16; 146fe2869c8SKris Kennaway rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 147fe2869c8SKris Kennaway input += 16; 148fe2869c8SKris Kennaway } 149fe2869c8SKris Kennaway break; 150fe2869c8SKris Kennaway 151fe2869c8SKris Kennaway case MODE_CFB1: 152fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN*/ 153fe2869c8SKris Kennaway bcopy(cipher->IV, iv, 16); 154fe2869c8SKris Kennaway #else /* !STRICT_ALIGN */ 155fe2869c8SKris Kennaway *((word32*)iv[0]) = *((word32*)(cipher->IV )); 156fe2869c8SKris Kennaway *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 157fe2869c8SKris Kennaway *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 158fe2869c8SKris Kennaway *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 159fe2869c8SKris Kennaway #endif /* ?STRICT_ALIGN */ 160fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 161fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 162fe2869c8SKris Kennaway *((word32*) block ) = *((word32*)iv[0]); 163fe2869c8SKris Kennaway *((word32*)(block+ 4)) = *((word32*)iv[1]); 164fe2869c8SKris Kennaway *((word32*)(block+ 8)) = *((word32*)iv[2]); 165fe2869c8SKris Kennaway *((word32*)(block+12)) = *((word32*)iv[3]); 166fe2869c8SKris Kennaway rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 167fe2869c8SKris Kennaway outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 168fe2869c8SKris Kennaway iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 169fe2869c8SKris Kennaway iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 170fe2869c8SKris Kennaway iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 171fe2869c8SKris Kennaway iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 172fe2869c8SKris Kennaway iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 173fe2869c8SKris Kennaway iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 174fe2869c8SKris Kennaway iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 175fe2869c8SKris Kennaway iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 176fe2869c8SKris Kennaway iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 177fe2869c8SKris Kennaway iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 178fe2869c8SKris Kennaway iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 179fe2869c8SKris Kennaway iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 180fe2869c8SKris Kennaway iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 181fe2869c8SKris Kennaway iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 182fe2869c8SKris Kennaway iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 183fe2869c8SKris Kennaway iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1); 184fe2869c8SKris Kennaway } 185fe2869c8SKris Kennaway } 186fe2869c8SKris Kennaway break; 187fe2869c8SKris Kennaway 188fe2869c8SKris Kennaway default: 189fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 190fe2869c8SKris Kennaway } 191fe2869c8SKris Kennaway 192fe2869c8SKris Kennaway return 128*numBlocks; 193fe2869c8SKris Kennaway } 194fe2869c8SKris Kennaway 195fe2869c8SKris Kennaway /** 196fe2869c8SKris Kennaway * Encrypt data partitioned in octets, using RFC 2040-like padding. 197fe2869c8SKris Kennaway * 198fe2869c8SKris Kennaway * @param input data to be encrypted (octet sequence) 199fe2869c8SKris Kennaway * @param inputOctets input length in octets (not bits) 200fe2869c8SKris Kennaway * @param outBuffer encrypted output data 201fe2869c8SKris Kennaway * 202fe2869c8SKris Kennaway * @return length in octets (not bits) of the encrypted output buffer. 203fe2869c8SKris Kennaway */ 204fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 205fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 206fe2869c8SKris Kennaway int i, numBlocks, padLen; 207fe2869c8SKris Kennaway word8 block[16], *iv, *cp; 208fe2869c8SKris Kennaway 209fe2869c8SKris Kennaway if (cipher == NULL || 210fe2869c8SKris Kennaway key == NULL || 211fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 212fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 213fe2869c8SKris Kennaway } 214fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 215fe2869c8SKris Kennaway return 0; /* nothing to do */ 216fe2869c8SKris Kennaway } 217fe2869c8SKris Kennaway 218fe2869c8SKris Kennaway numBlocks = inputOctets/16; 219fe2869c8SKris Kennaway 220fe2869c8SKris Kennaway switch (cipher->mode) { 221fe2869c8SKris Kennaway case MODE_ECB: 222fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 223fe2869c8SKris Kennaway rijndaelEncrypt(input, outBuffer, key->keySched, key->ROUNDS); 224fe2869c8SKris Kennaway input += 16; 225fe2869c8SKris Kennaway outBuffer += 16; 226fe2869c8SKris Kennaway } 227fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 228eb159f5bSHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 22927da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 230fe2869c8SKris Kennaway bcopy(input, block, 16 - padLen); 231fe2869c8SKris Kennaway for (cp = block + 16 - padLen; cp < block + 16; cp++) 232fe2869c8SKris Kennaway *cp = padLen; 233fe2869c8SKris Kennaway rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 234fe2869c8SKris Kennaway break; 235fe2869c8SKris Kennaway 236fe2869c8SKris Kennaway case MODE_CBC: 237fe2869c8SKris Kennaway iv = cipher->IV; 238fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 239fe2869c8SKris Kennaway ((word32*)block)[0] = ((word32*)input)[0] ^ ((word32*)iv)[0]; 240fe2869c8SKris Kennaway ((word32*)block)[1] = ((word32*)input)[1] ^ ((word32*)iv)[1]; 241fe2869c8SKris Kennaway ((word32*)block)[2] = ((word32*)input)[2] ^ ((word32*)iv)[2]; 242fe2869c8SKris Kennaway ((word32*)block)[3] = ((word32*)input)[3] ^ ((word32*)iv)[3]; 243fe2869c8SKris Kennaway rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 244fe2869c8SKris Kennaway iv = outBuffer; 245fe2869c8SKris Kennaway input += 16; 246fe2869c8SKris Kennaway outBuffer += 16; 247fe2869c8SKris Kennaway } 248fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 24966476d45SHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 25027da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 251fe2869c8SKris Kennaway for (i = 0; i < 16 - padLen; i++) { 252fe2869c8SKris Kennaway block[i] = input[i] ^ iv[i]; 253fe2869c8SKris Kennaway } 254fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 255fe2869c8SKris Kennaway block[i] = (BYTE)padLen ^ iv[i]; 256fe2869c8SKris Kennaway } 257fe2869c8SKris Kennaway rijndaelEncrypt(block, outBuffer, key->keySched, key->ROUNDS); 258fe2869c8SKris Kennaway break; 259fe2869c8SKris Kennaway 260fe2869c8SKris Kennaway default: 261fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 262fe2869c8SKris Kennaway } 263fe2869c8SKris Kennaway 264fe2869c8SKris Kennaway return 16*(numBlocks + 1); 265fe2869c8SKris Kennaway } 266fe2869c8SKris Kennaway 267fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 268fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 269fe2869c8SKris Kennaway int i, k, numBlocks; 270fe2869c8SKris Kennaway word8 block[16], iv[4][4]; 271fe2869c8SKris Kennaway 272fe2869c8SKris Kennaway if (cipher == NULL || 273fe2869c8SKris Kennaway key == NULL || 274fe2869c8SKris Kennaway (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 275fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 276fe2869c8SKris Kennaway } 277fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 278fe2869c8SKris Kennaway return 0; /* nothing to do */ 279fe2869c8SKris Kennaway } 280fe2869c8SKris Kennaway 281fe2869c8SKris Kennaway numBlocks = inputLen/128; 282fe2869c8SKris Kennaway 283fe2869c8SKris Kennaway switch (cipher->mode) { 284fe2869c8SKris Kennaway case MODE_ECB: 285fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 286fe2869c8SKris Kennaway rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 287fe2869c8SKris Kennaway input += 16; 288fe2869c8SKris Kennaway outBuffer += 16; 289fe2869c8SKris Kennaway } 290fe2869c8SKris Kennaway break; 291fe2869c8SKris Kennaway 292fe2869c8SKris Kennaway case MODE_CBC: 293fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN */ 294fe2869c8SKris Kennaway bcopy(cipher->IV, iv, 16); 295fe2869c8SKris Kennaway #else 296fe2869c8SKris Kennaway *((word32*)iv[0]) = *((word32*)(cipher->IV )); 297fe2869c8SKris Kennaway *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 298fe2869c8SKris Kennaway *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 299fe2869c8SKris Kennaway *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 300fe2869c8SKris Kennaway #endif 301fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 302fe2869c8SKris Kennaway rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 303fe2869c8SKris Kennaway ((word32*)block)[0] ^= *((word32*)iv[0]); 304fe2869c8SKris Kennaway ((word32*)block)[1] ^= *((word32*)iv[1]); 305fe2869c8SKris Kennaway ((word32*)block)[2] ^= *((word32*)iv[2]); 306fe2869c8SKris Kennaway ((word32*)block)[3] ^= *((word32*)iv[3]); 307fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN*/ 308fe2869c8SKris Kennaway bcopy(input, iv, 16); 309fe2869c8SKris Kennaway bcopy(block, outBuffer, 16); 310fe2869c8SKris Kennaway #else 311fe2869c8SKris Kennaway *((word32*)iv[0]) = ((word32*)input)[0]; ((word32*)outBuffer)[0] = ((word32*)block)[0]; 312fe2869c8SKris Kennaway *((word32*)iv[1]) = ((word32*)input)[1]; ((word32*)outBuffer)[1] = ((word32*)block)[1]; 313fe2869c8SKris Kennaway *((word32*)iv[2]) = ((word32*)input)[2]; ((word32*)outBuffer)[2] = ((word32*)block)[2]; 314fe2869c8SKris Kennaway *((word32*)iv[3]) = ((word32*)input)[3]; ((word32*)outBuffer)[3] = ((word32*)block)[3]; 315fe2869c8SKris Kennaway #endif 316fe2869c8SKris Kennaway input += 16; 317fe2869c8SKris Kennaway outBuffer += 16; 318fe2869c8SKris Kennaway } 319fe2869c8SKris Kennaway break; 320fe2869c8SKris Kennaway 321fe2869c8SKris Kennaway case MODE_CFB1: 322fe2869c8SKris Kennaway #if 1 /*STRICT_ALIGN */ 323fe2869c8SKris Kennaway bcopy(cipher->IV, iv, 16); 324fe2869c8SKris Kennaway #else 325fe2869c8SKris Kennaway *((word32*)iv[0]) = *((word32*)(cipher->IV)); 326fe2869c8SKris Kennaway *((word32*)iv[1]) = *((word32*)(cipher->IV+ 4)); 327fe2869c8SKris Kennaway *((word32*)iv[2]) = *((word32*)(cipher->IV+ 8)); 328fe2869c8SKris Kennaway *((word32*)iv[3]) = *((word32*)(cipher->IV+12)); 329fe2869c8SKris Kennaway #endif 330fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 331fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 332fe2869c8SKris Kennaway *((word32*) block ) = *((word32*)iv[0]); 333fe2869c8SKris Kennaway *((word32*)(block+ 4)) = *((word32*)iv[1]); 334fe2869c8SKris Kennaway *((word32*)(block+ 8)) = *((word32*)iv[2]); 335fe2869c8SKris Kennaway *((word32*)(block+12)) = *((word32*)iv[3]); 336fe2869c8SKris Kennaway rijndaelEncrypt(block, block, key->keySched, key->ROUNDS); 337fe2869c8SKris Kennaway iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7); 338fe2869c8SKris Kennaway iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7); 339fe2869c8SKris Kennaway iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7); 340fe2869c8SKris Kennaway iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7); 341fe2869c8SKris Kennaway iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7); 342fe2869c8SKris Kennaway iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7); 343fe2869c8SKris Kennaway iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7); 344fe2869c8SKris Kennaway iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7); 345fe2869c8SKris Kennaway iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7); 346fe2869c8SKris Kennaway iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7); 347fe2869c8SKris Kennaway iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7); 348fe2869c8SKris Kennaway iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7); 349fe2869c8SKris Kennaway iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7); 350fe2869c8SKris Kennaway iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7); 351fe2869c8SKris Kennaway iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7); 352fe2869c8SKris Kennaway iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1); 353fe2869c8SKris Kennaway outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7); 354fe2869c8SKris Kennaway } 355fe2869c8SKris Kennaway } 356fe2869c8SKris Kennaway break; 357fe2869c8SKris Kennaway 358fe2869c8SKris Kennaway default: 359fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 360fe2869c8SKris Kennaway } 361fe2869c8SKris Kennaway 362fe2869c8SKris Kennaway return 128*numBlocks; 363fe2869c8SKris Kennaway } 364fe2869c8SKris Kennaway 365fe2869c8SKris Kennaway int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 366fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 367fe2869c8SKris Kennaway int i, numBlocks, padLen; 368fe2869c8SKris Kennaway word8 block[16]; 369fe2869c8SKris Kennaway word32 iv[4]; 370fe2869c8SKris Kennaway 371fe2869c8SKris Kennaway if (cipher == NULL || 372fe2869c8SKris Kennaway key == NULL || 373fe2869c8SKris Kennaway key->direction == DIR_ENCRYPT) { 374fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 375fe2869c8SKris Kennaway } 376fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 377fe2869c8SKris Kennaway return 0; /* nothing to do */ 378fe2869c8SKris Kennaway } 379fe2869c8SKris Kennaway if (inputOctets % 16 != 0) { 380fe2869c8SKris Kennaway return BAD_DATA; 381fe2869c8SKris Kennaway } 382fe2869c8SKris Kennaway 383fe2869c8SKris Kennaway numBlocks = inputOctets/16; 384fe2869c8SKris Kennaway 385fe2869c8SKris Kennaway switch (cipher->mode) { 386fe2869c8SKris Kennaway case MODE_ECB: 387fe2869c8SKris Kennaway /* all blocks but last */ 388fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 389fe2869c8SKris Kennaway rijndaelDecrypt(input, outBuffer, key->keySched, key->ROUNDS); 390fe2869c8SKris Kennaway input += 16; 391fe2869c8SKris Kennaway outBuffer += 16; 392fe2869c8SKris Kennaway } 393fe2869c8SKris Kennaway /* last block */ 394fe2869c8SKris Kennaway rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 395fe2869c8SKris Kennaway padLen = block[15]; 396fe2869c8SKris Kennaway if (padLen >= 16) { 397fe2869c8SKris Kennaway return BAD_DATA; 398fe2869c8SKris Kennaway } 399fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 400fe2869c8SKris Kennaway if (block[i] != padLen) { 401fe2869c8SKris Kennaway return BAD_DATA; 402fe2869c8SKris Kennaway } 403fe2869c8SKris Kennaway } 404fe2869c8SKris Kennaway bcopy(block, outBuffer, 16 - padLen); 405fe2869c8SKris Kennaway break; 406fe2869c8SKris Kennaway 407fe2869c8SKris Kennaway case MODE_CBC: 408fe2869c8SKris Kennaway bcopy(cipher->IV, iv, 16); 409fe2869c8SKris Kennaway /* all blocks but last */ 410fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 411fe2869c8SKris Kennaway rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 412fe2869c8SKris Kennaway ((word32*)block)[0] ^= iv[0]; 413fe2869c8SKris Kennaway ((word32*)block)[1] ^= iv[1]; 414fe2869c8SKris Kennaway ((word32*)block)[2] ^= iv[2]; 415fe2869c8SKris Kennaway ((word32*)block)[3] ^= iv[3]; 416fe2869c8SKris Kennaway bcopy(input, iv, 16); 417fe2869c8SKris Kennaway bcopy(block, outBuffer, 16); 418fe2869c8SKris Kennaway input += 16; 419fe2869c8SKris Kennaway outBuffer += 16; 420fe2869c8SKris Kennaway } 421fe2869c8SKris Kennaway /* last block */ 422fe2869c8SKris Kennaway rijndaelDecrypt(input, block, key->keySched, key->ROUNDS); 423fe2869c8SKris Kennaway ((word32*)block)[0] ^= iv[0]; 424fe2869c8SKris Kennaway ((word32*)block)[1] ^= iv[1]; 425fe2869c8SKris Kennaway ((word32*)block)[2] ^= iv[2]; 426fe2869c8SKris Kennaway ((word32*)block)[3] ^= iv[3]; 427fe2869c8SKris Kennaway padLen = block[15]; 428fe2869c8SKris Kennaway if (padLen <= 0 || padLen > 16) { 429fe2869c8SKris Kennaway return BAD_DATA; 430fe2869c8SKris Kennaway } 431fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 432fe2869c8SKris Kennaway if (block[i] != padLen) { 433fe2869c8SKris Kennaway return BAD_DATA; 434fe2869c8SKris Kennaway } 435fe2869c8SKris Kennaway } 436fe2869c8SKris Kennaway bcopy(block, outBuffer, 16 - padLen); 437fe2869c8SKris Kennaway break; 438fe2869c8SKris Kennaway 439fe2869c8SKris Kennaway default: 440fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 441fe2869c8SKris Kennaway } 442fe2869c8SKris Kennaway 443fe2869c8SKris Kennaway return 16*numBlocks - padLen; 444fe2869c8SKris Kennaway } 445fe2869c8SKris Kennaway 446fe2869c8SKris Kennaway #ifdef INTERMEDIATE_VALUE_KAT 447fe2869c8SKris Kennaway /** 448fe2869c8SKris Kennaway * cipherUpdateRounds: 449fe2869c8SKris Kennaway * 450fe2869c8SKris Kennaway * Encrypts/Decrypts exactly one full block a specified number of rounds. 451fe2869c8SKris Kennaway * Only used in the Intermediate Value Known Answer Test. 452fe2869c8SKris Kennaway * 453fe2869c8SKris Kennaway * Returns: 454fe2869c8SKris Kennaway * TRUE - on success 455fe2869c8SKris Kennaway * BAD_CIPHER_STATE - cipher in bad state (e.g., not initialized) 456fe2869c8SKris Kennaway */ 457fe2869c8SKris Kennaway int rijndael_cipherUpdateRounds(cipherInstance *cipher, keyInstance *key, 458fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer, int rounds) { 459fe2869c8SKris Kennaway int j; 460fe2869c8SKris Kennaway word8 block[4][4]; 461fe2869c8SKris Kennaway 462fe2869c8SKris Kennaway if (cipher == NULL || key == NULL) { 463fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 464fe2869c8SKris Kennaway } 465fe2869c8SKris Kennaway 466fe2869c8SKris Kennaway for (j = 3; j >= 0; j--) { 467fe2869c8SKris Kennaway /* parse input stream into rectangular array */ 468fe2869c8SKris Kennaway *((word32*)block[j]) = *((word32*)(input+4*j)); 469fe2869c8SKris Kennaway } 470fe2869c8SKris Kennaway 471fe2869c8SKris Kennaway switch (key->direction) { 472fe2869c8SKris Kennaway case DIR_ENCRYPT: 473fe2869c8SKris Kennaway rijndaelEncryptRound(block, key->keySched, key->ROUNDS, rounds); 474fe2869c8SKris Kennaway break; 475fe2869c8SKris Kennaway 476fe2869c8SKris Kennaway case DIR_DECRYPT: 477fe2869c8SKris Kennaway rijndaelDecryptRound(block, key->keySched, key->ROUNDS, rounds); 478fe2869c8SKris Kennaway break; 479fe2869c8SKris Kennaway 480fe2869c8SKris Kennaway default: 481fe2869c8SKris Kennaway return BAD_KEY_DIR; 482fe2869c8SKris Kennaway } 483fe2869c8SKris Kennaway 484fe2869c8SKris Kennaway for (j = 3; j >= 0; j--) { 485fe2869c8SKris Kennaway /* parse rectangular array into output ciphertext bytes */ 486fe2869c8SKris Kennaway *((word32*)(outBuffer+4*j)) = *((word32*)block[j]); 487fe2869c8SKris Kennaway } 488fe2869c8SKris Kennaway 489fe2869c8SKris Kennaway return TRUE; 490fe2869c8SKris Kennaway } 491fe2869c8SKris Kennaway #endif /* INTERMEDIATE_VALUE_KAT */ 492