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