18f21478bSHajimu UMEMOTO /* $KAME: rijndael-api-fst.c,v 1.18 2003/07/24 15:10:30 itojun Exp $ */ 2fe2869c8SKris Kennaway 38f21478bSHajimu UMEMOTO /** 48f21478bSHajimu UMEMOTO * rijndael-api-fst.c 5fe2869c8SKris Kennaway * 68f21478bSHajimu UMEMOTO * @version 2.9 (December 2000) 7fe2869c8SKris Kennaway * 88f21478bSHajimu UMEMOTO * Optimised ANSI C code for the Rijndael cipher (now AES) 9fe2869c8SKris Kennaway * 108f21478bSHajimu UMEMOTO * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be> 118f21478bSHajimu UMEMOTO * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be> 128f21478bSHajimu UMEMOTO * @author Paulo Barreto <paulo.barreto@terra.com.br> 138f21478bSHajimu UMEMOTO * 148f21478bSHajimu UMEMOTO * This code is hereby placed in the public domain. 158f21478bSHajimu UMEMOTO * 168f21478bSHajimu UMEMOTO * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS 178f21478bSHajimu UMEMOTO * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 188f21478bSHajimu UMEMOTO * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 198f21478bSHajimu UMEMOTO * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE 208f21478bSHajimu UMEMOTO * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 218f21478bSHajimu UMEMOTO * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 228f21478bSHajimu UMEMOTO * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 238f21478bSHajimu UMEMOTO * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 248f21478bSHajimu UMEMOTO * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE 258f21478bSHajimu UMEMOTO * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 268f21478bSHajimu UMEMOTO * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 278f21478bSHajimu UMEMOTO * 288f21478bSHajimu UMEMOTO * Acknowledgements: 298f21478bSHajimu UMEMOTO * 308f21478bSHajimu UMEMOTO * We are deeply indebted to the following people for their bug reports, 318f21478bSHajimu UMEMOTO * fixes, and improvement suggestions to this implementation. Though we 328f21478bSHajimu UMEMOTO * tried to list all contributions, we apologise in advance for any 338f21478bSHajimu UMEMOTO * missing reference. 348f21478bSHajimu UMEMOTO * 358f21478bSHajimu UMEMOTO * Andrew Bales <Andrew.Bales@Honeywell.com> 368f21478bSHajimu UMEMOTO * Markus Friedl <markus.friedl@informatik.uni-erlangen.de> 378f21478bSHajimu UMEMOTO * John Skodon <skodonj@webquill.com> 38fe2869c8SKris Kennaway */ 39fe2869c8SKris Kennaway 40ad39da78SDavid E. O'Brien #include <sys/cdefs.h> 41ad39da78SDavid E. O'Brien __FBSDID("$FreeBSD$"); 42ad39da78SDavid E. O'Brien 43fe2869c8SKris Kennaway #include <sys/param.h> 4433841545SHajimu UMEMOTO #ifdef _KERNEL 4533841545SHajimu UMEMOTO #include <sys/systm.h> 4633841545SHajimu UMEMOTO #else 478f21478bSHajimu UMEMOTO #include <stdlib.h> 4833841545SHajimu UMEMOTO #include <string.h> 4933841545SHajimu UMEMOTO #endif 508f21478bSHajimu UMEMOTO 518f21478bSHajimu UMEMOTO #include <crypto/rijndael/rijndael_local.h> 52fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-alg-fst.h> 53fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-api-fst.h> 5427da1009SPoul-Henning Kamp 55fe2869c8SKris Kennaway int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) { 568f21478bSHajimu UMEMOTO u_int8_t cipherKey[RIJNDAEL_MAXKB]; 57fe2869c8SKris Kennaway 58fe2869c8SKris Kennaway if (key == NULL) { 59fe2869c8SKris Kennaway return BAD_KEY_INSTANCE; 60fe2869c8SKris Kennaway } 61fe2869c8SKris Kennaway 62fe2869c8SKris Kennaway if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) { 63fe2869c8SKris Kennaway key->direction = direction; 64fe2869c8SKris Kennaway } else { 65fe2869c8SKris Kennaway return BAD_KEY_DIR; 66fe2869c8SKris Kennaway } 67fe2869c8SKris Kennaway 68fe2869c8SKris Kennaway if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) { 69fe2869c8SKris Kennaway key->keyLen = keyLen; 70fe2869c8SKris Kennaway } else { 71fe2869c8SKris Kennaway return BAD_KEY_MAT; 72fe2869c8SKris Kennaway } 73fe2869c8SKris Kennaway 74fe2869c8SKris Kennaway if (keyMaterial != NULL) { 758f21478bSHajimu UMEMOTO memcpy(key->keyMaterial, keyMaterial, keyLen/8); 76fe2869c8SKris Kennaway } 77fe2869c8SKris Kennaway 78fe2869c8SKris Kennaway /* initialize key schedule: */ 798f21478bSHajimu UMEMOTO memcpy(cipherKey, key->keyMaterial, keyLen/8); 808f21478bSHajimu UMEMOTO if (direction == DIR_ENCRYPT) { 818f21478bSHajimu UMEMOTO key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen); 828f21478bSHajimu UMEMOTO } else { 838f21478bSHajimu UMEMOTO key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen); 84fe2869c8SKris Kennaway } 858f21478bSHajimu UMEMOTO rijndaelKeySetupEnc(key->ek, cipherKey, keyLen); 86fe2869c8SKris Kennaway return TRUE; 87fe2869c8SKris Kennaway } 88fe2869c8SKris Kennaway 89fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) { 90fe2869c8SKris Kennaway if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) { 91fe2869c8SKris Kennaway cipher->mode = mode; 92fe2869c8SKris Kennaway } else { 93fe2869c8SKris Kennaway return BAD_CIPHER_MODE; 94fe2869c8SKris Kennaway } 95fe2869c8SKris Kennaway if (IV != NULL) { 968f21478bSHajimu UMEMOTO memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE); 97fe2869c8SKris Kennaway } else { 988f21478bSHajimu UMEMOTO memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE); 99fe2869c8SKris Kennaway } 100fe2869c8SKris Kennaway return TRUE; 101fe2869c8SKris Kennaway } 102fe2869c8SKris Kennaway 103fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key, 104fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 1058f21478bSHajimu UMEMOTO int i, k, t, numBlocks; 1068f21478bSHajimu UMEMOTO u_int8_t block[16], *iv; 107fe2869c8SKris Kennaway 108fe2869c8SKris Kennaway if (cipher == NULL || 109fe2869c8SKris Kennaway key == NULL || 110fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 111fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 112fe2869c8SKris Kennaway } 113fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 114fe2869c8SKris Kennaway return 0; /* nothing to do */ 115fe2869c8SKris Kennaway } 116fe2869c8SKris Kennaway 117fe2869c8SKris Kennaway numBlocks = inputLen/128; 118fe2869c8SKris Kennaway 119fe2869c8SKris Kennaway switch (cipher->mode) { 120fe2869c8SKris Kennaway case MODE_ECB: 121fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 1228f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 123fe2869c8SKris Kennaway input += 16; 124fe2869c8SKris Kennaway outBuffer += 16; 125fe2869c8SKris Kennaway } 126fe2869c8SKris Kennaway break; 127fe2869c8SKris Kennaway 128fe2869c8SKris Kennaway case MODE_CBC: 1298f21478bSHajimu UMEMOTO iv = cipher->IV; 1308f21478bSHajimu UMEMOTO for (i = numBlocks; i > 0; i--) { 1318f21478bSHajimu UMEMOTO ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0]; 1328f21478bSHajimu UMEMOTO ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1]; 1338f21478bSHajimu UMEMOTO ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2]; 1348f21478bSHajimu UMEMOTO ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3]; 1358f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 1368f21478bSHajimu UMEMOTO iv = outBuffer; 137fe2869c8SKris Kennaway input += 16; 138fe2869c8SKris Kennaway outBuffer += 16; 139fe2869c8SKris Kennaway } 140fe2869c8SKris Kennaway break; 141fe2869c8SKris Kennaway 142fe2869c8SKris Kennaway case MODE_CFB1: 1438f21478bSHajimu UMEMOTO iv = cipher->IV; 144fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 1458f21478bSHajimu UMEMOTO memcpy(outBuffer, input, 16); 146fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 1478f21478bSHajimu UMEMOTO rijndaelEncrypt(key->ek, key->Nr, iv, block); 1488f21478bSHajimu UMEMOTO outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); 1498f21478bSHajimu UMEMOTO for (t = 0; t < 15; t++) { 1508f21478bSHajimu UMEMOTO iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 151fe2869c8SKris Kennaway } 1528f21478bSHajimu UMEMOTO iv[15] = (iv[15] << 1) | ((outBuffer[k >> 3] >> (7 - (k & 7))) & 1); 1538f21478bSHajimu UMEMOTO } 1548f21478bSHajimu UMEMOTO outBuffer += 16; 1558f21478bSHajimu UMEMOTO input += 16; 156fe2869c8SKris Kennaway } 157fe2869c8SKris Kennaway break; 158fe2869c8SKris Kennaway 159fe2869c8SKris Kennaway default: 160fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 161fe2869c8SKris Kennaway } 162fe2869c8SKris Kennaway 163fe2869c8SKris Kennaway return 128*numBlocks; 164fe2869c8SKris Kennaway } 165fe2869c8SKris Kennaway 166fe2869c8SKris Kennaway /** 167fe2869c8SKris Kennaway * Encrypt data partitioned in octets, using RFC 2040-like padding. 168fe2869c8SKris Kennaway * 169fe2869c8SKris Kennaway * @param input data to be encrypted (octet sequence) 170fe2869c8SKris Kennaway * @param inputOctets input length in octets (not bits) 171fe2869c8SKris Kennaway * @param outBuffer encrypted output data 172fe2869c8SKris Kennaway * 173fe2869c8SKris Kennaway * @return length in octets (not bits) of the encrypted output buffer. 174fe2869c8SKris Kennaway */ 175fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key, 176fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 177fe2869c8SKris Kennaway int i, numBlocks, padLen; 1788f21478bSHajimu UMEMOTO u_int8_t block[16], *iv; 179fe2869c8SKris Kennaway 180fe2869c8SKris Kennaway if (cipher == NULL || 181fe2869c8SKris Kennaway key == NULL || 182fe2869c8SKris Kennaway key->direction == DIR_DECRYPT) { 183fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 184fe2869c8SKris Kennaway } 185fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 186fe2869c8SKris Kennaway return 0; /* nothing to do */ 187fe2869c8SKris Kennaway } 188fe2869c8SKris Kennaway 189fe2869c8SKris Kennaway numBlocks = inputOctets/16; 190fe2869c8SKris Kennaway 191fe2869c8SKris Kennaway switch (cipher->mode) { 192fe2869c8SKris Kennaway case MODE_ECB: 193fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 1948f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, input, outBuffer); 195fe2869c8SKris Kennaway input += 16; 196fe2869c8SKris Kennaway outBuffer += 16; 197fe2869c8SKris Kennaway } 198fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 199eb159f5bSHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 20027da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 2018f21478bSHajimu UMEMOTO memcpy(block, input, 16 - padLen); 2028f21478bSHajimu UMEMOTO memset(block + 16 - padLen, padLen, padLen); 2038f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 204fe2869c8SKris Kennaway break; 205fe2869c8SKris Kennaway 206fe2869c8SKris Kennaway case MODE_CBC: 207fe2869c8SKris Kennaway iv = cipher->IV; 208fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2098f21478bSHajimu UMEMOTO ((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0]; 2108f21478bSHajimu UMEMOTO ((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1]; 2118f21478bSHajimu UMEMOTO ((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2]; 2128f21478bSHajimu UMEMOTO ((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3]; 2138f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 214fe2869c8SKris Kennaway iv = outBuffer; 215fe2869c8SKris Kennaway input += 16; 216fe2869c8SKris Kennaway outBuffer += 16; 217fe2869c8SKris Kennaway } 218fe2869c8SKris Kennaway padLen = 16 - (inputOctets - 16*numBlocks); 21966476d45SHajimu UMEMOTO if (padLen <= 0 || padLen > 16) 22027da1009SPoul-Henning Kamp return BAD_CIPHER_STATE; 221fe2869c8SKris Kennaway for (i = 0; i < 16 - padLen; i++) { 222fe2869c8SKris Kennaway block[i] = input[i] ^ iv[i]; 223fe2869c8SKris Kennaway } 224fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 225fe2869c8SKris Kennaway block[i] = (BYTE)padLen ^ iv[i]; 226fe2869c8SKris Kennaway } 2278f21478bSHajimu UMEMOTO rijndaelEncrypt(key->rk, key->Nr, block, outBuffer); 228fe2869c8SKris Kennaway break; 229fe2869c8SKris Kennaway 230fe2869c8SKris Kennaway default: 231fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 232fe2869c8SKris Kennaway } 233fe2869c8SKris Kennaway 234fe2869c8SKris Kennaway return 16*(numBlocks + 1); 235fe2869c8SKris Kennaway } 236fe2869c8SKris Kennaway 237fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key, 238fe2869c8SKris Kennaway BYTE *input, int inputLen, BYTE *outBuffer) { 2398f21478bSHajimu UMEMOTO int i, k, t, numBlocks; 2408f21478bSHajimu UMEMOTO u_int8_t block[16], *iv; 241fe2869c8SKris Kennaway 242fe2869c8SKris Kennaway if (cipher == NULL || 243fe2869c8SKris Kennaway key == NULL || 244fe2869c8SKris Kennaway (cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) { 245fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 246fe2869c8SKris Kennaway } 247fe2869c8SKris Kennaway if (input == NULL || inputLen <= 0) { 248fe2869c8SKris Kennaway return 0; /* nothing to do */ 249fe2869c8SKris Kennaway } 250fe2869c8SKris Kennaway 251fe2869c8SKris Kennaway numBlocks = inputLen/128; 252fe2869c8SKris Kennaway 253fe2869c8SKris Kennaway switch (cipher->mode) { 254fe2869c8SKris Kennaway case MODE_ECB: 255fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2568f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 257fe2869c8SKris Kennaway input += 16; 258fe2869c8SKris Kennaway outBuffer += 16; 259fe2869c8SKris Kennaway } 260fe2869c8SKris Kennaway break; 261fe2869c8SKris Kennaway 262fe2869c8SKris Kennaway case MODE_CBC: 2638f21478bSHajimu UMEMOTO iv = cipher->IV; 264fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2658f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 2668f21478bSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0]; 2678f21478bSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1]; 2688f21478bSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2]; 2698f21478bSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3]; 2708f21478bSHajimu UMEMOTO memcpy(cipher->IV, input, 16); 2718f21478bSHajimu UMEMOTO memcpy(outBuffer, block, 16); 272fe2869c8SKris Kennaway input += 16; 273fe2869c8SKris Kennaway outBuffer += 16; 274fe2869c8SKris Kennaway } 275fe2869c8SKris Kennaway break; 276fe2869c8SKris Kennaway 277fe2869c8SKris Kennaway case MODE_CFB1: 2788f21478bSHajimu UMEMOTO iv = cipher->IV; 279fe2869c8SKris Kennaway for (i = numBlocks; i > 0; i--) { 2808f21478bSHajimu UMEMOTO memcpy(outBuffer, input, 16); 281fe2869c8SKris Kennaway for (k = 0; k < 128; k++) { 2828f21478bSHajimu UMEMOTO rijndaelEncrypt(key->ek, key->Nr, iv, block); 2838f21478bSHajimu UMEMOTO for (t = 0; t < 15; t++) { 2848f21478bSHajimu UMEMOTO iv[t] = (iv[t] << 1) | (iv[t + 1] >> 7); 285fe2869c8SKris Kennaway } 2868f21478bSHajimu UMEMOTO iv[15] = (iv[15] << 1) | ((input[k >> 3] >> (7 - (k & 7))) & 1); 2878f21478bSHajimu UMEMOTO outBuffer[k >> 3] ^= (block[0] & 0x80U) >> (k & 7); 2888f21478bSHajimu UMEMOTO } 2898f21478bSHajimu UMEMOTO outBuffer += 16; 2908f21478bSHajimu UMEMOTO input += 16; 291fe2869c8SKris Kennaway } 292fe2869c8SKris Kennaway break; 293fe2869c8SKris Kennaway 294fe2869c8SKris Kennaway default: 295fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 296fe2869c8SKris Kennaway } 297fe2869c8SKris Kennaway 298fe2869c8SKris Kennaway return 128*numBlocks; 299fe2869c8SKris Kennaway } 300fe2869c8SKris Kennaway 301fe2869c8SKris Kennaway int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key, 302fe2869c8SKris Kennaway BYTE *input, int inputOctets, BYTE *outBuffer) { 303fe2869c8SKris Kennaway int i, numBlocks, padLen; 3048f21478bSHajimu UMEMOTO u_int8_t block[16]; 305fe2869c8SKris Kennaway 306fe2869c8SKris Kennaway if (cipher == NULL || 307fe2869c8SKris Kennaway key == NULL || 308fe2869c8SKris Kennaway key->direction == DIR_ENCRYPT) { 309fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 310fe2869c8SKris Kennaway } 311fe2869c8SKris Kennaway if (input == NULL || inputOctets <= 0) { 312fe2869c8SKris Kennaway return 0; /* nothing to do */ 313fe2869c8SKris Kennaway } 314fe2869c8SKris Kennaway if (inputOctets % 16 != 0) { 315fe2869c8SKris Kennaway return BAD_DATA; 316fe2869c8SKris Kennaway } 317fe2869c8SKris Kennaway 318fe2869c8SKris Kennaway numBlocks = inputOctets/16; 319fe2869c8SKris Kennaway 320fe2869c8SKris Kennaway switch (cipher->mode) { 321fe2869c8SKris Kennaway case MODE_ECB: 322fe2869c8SKris Kennaway /* all blocks but last */ 323fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 3248f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, outBuffer); 325fe2869c8SKris Kennaway input += 16; 326fe2869c8SKris Kennaway outBuffer += 16; 327fe2869c8SKris Kennaway } 328fe2869c8SKris Kennaway /* last block */ 3298f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 330fe2869c8SKris Kennaway padLen = block[15]; 331fe2869c8SKris Kennaway if (padLen >= 16) { 332fe2869c8SKris Kennaway return BAD_DATA; 333fe2869c8SKris Kennaway } 334fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 335fe2869c8SKris Kennaway if (block[i] != padLen) { 336fe2869c8SKris Kennaway return BAD_DATA; 337fe2869c8SKris Kennaway } 338fe2869c8SKris Kennaway } 3398f21478bSHajimu UMEMOTO memcpy(outBuffer, block, 16 - padLen); 340fe2869c8SKris Kennaway break; 341fe2869c8SKris Kennaway 342fe2869c8SKris Kennaway case MODE_CBC: 343fe2869c8SKris Kennaway /* all blocks but last */ 344fe2869c8SKris Kennaway for (i = numBlocks - 1; i > 0; i--) { 3458f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 3468f21478bSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0]; 3478f21478bSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1]; 3488f21478bSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2]; 3498f21478bSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3]; 3508f21478bSHajimu UMEMOTO memcpy(cipher->IV, input, 16); 3518f21478bSHajimu UMEMOTO memcpy(outBuffer, block, 16); 352fe2869c8SKris Kennaway input += 16; 353fe2869c8SKris Kennaway outBuffer += 16; 354fe2869c8SKris Kennaway } 355fe2869c8SKris Kennaway /* last block */ 3568f21478bSHajimu UMEMOTO rijndaelDecrypt(key->rk, key->Nr, input, block); 3578f21478bSHajimu UMEMOTO ((u_int32_t*)block)[0] ^= ((u_int32_t*)cipher->IV)[0]; 3588f21478bSHajimu UMEMOTO ((u_int32_t*)block)[1] ^= ((u_int32_t*)cipher->IV)[1]; 3598f21478bSHajimu UMEMOTO ((u_int32_t*)block)[2] ^= ((u_int32_t*)cipher->IV)[2]; 3608f21478bSHajimu UMEMOTO ((u_int32_t*)block)[3] ^= ((u_int32_t*)cipher->IV)[3]; 361fe2869c8SKris Kennaway padLen = block[15]; 362fe2869c8SKris Kennaway if (padLen <= 0 || padLen > 16) { 363fe2869c8SKris Kennaway return BAD_DATA; 364fe2869c8SKris Kennaway } 365fe2869c8SKris Kennaway for (i = 16 - padLen; i < 16; i++) { 366fe2869c8SKris Kennaway if (block[i] != padLen) { 367fe2869c8SKris Kennaway return BAD_DATA; 368fe2869c8SKris Kennaway } 369fe2869c8SKris Kennaway } 3708f21478bSHajimu UMEMOTO memcpy(outBuffer, block, 16 - padLen); 371fe2869c8SKris Kennaway break; 372fe2869c8SKris Kennaway 373fe2869c8SKris Kennaway default: 374fe2869c8SKris Kennaway return BAD_CIPHER_STATE; 375fe2869c8SKris Kennaway } 376fe2869c8SKris Kennaway 377fe2869c8SKris Kennaway return 16*numBlocks - padLen; 378fe2869c8SKris Kennaway } 379fe2869c8SKris Kennaway 380