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