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