xref: /freebsd/sys/crypto/rijndael/rijndael-api-fst.c (revision 5129dcfce73c22ff1b0517daffd21ec5191430ab)
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>
2233841545SHajimu UMEMOTO #ifdef _KERNEL
2333841545SHajimu UMEMOTO #include <sys/systm.h>
2433841545SHajimu UMEMOTO #else
2533841545SHajimu UMEMOTO #include <string.h>
2633841545SHajimu UMEMOTO #endif
275129dcfcSHajimu UMEMOTO 
285129dcfcSHajimu UMEMOTO #include <crypto/rijndael/rijndael_local.h>
29fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-alg-fst.h>
30fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-api-fst.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) {
395129dcfcSHajimu UMEMOTO 	u_int8_t cipherKey[RIJNDAEL_MAXKB];
40fe2869c8SKris Kennaway 
41fe2869c8SKris Kennaway 	if (key == NULL) {
42fe2869c8SKris Kennaway 		return BAD_KEY_INSTANCE;
43fe2869c8SKris Kennaway 	}
44fe2869c8SKris Kennaway 
45fe2869c8SKris Kennaway 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
46fe2869c8SKris Kennaway 		key->direction = direction;
47fe2869c8SKris Kennaway 	} else {
48fe2869c8SKris Kennaway 		return BAD_KEY_DIR;
49fe2869c8SKris Kennaway 	}
50fe2869c8SKris Kennaway 
51fe2869c8SKris Kennaway 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
52fe2869c8SKris Kennaway 		key->keyLen = keyLen;
53fe2869c8SKris Kennaway 	} else {
54fe2869c8SKris Kennaway 		return BAD_KEY_MAT;
55fe2869c8SKris Kennaway 	}
56fe2869c8SKris Kennaway 
57fe2869c8SKris Kennaway 	if (keyMaterial != NULL) {
585129dcfcSHajimu UMEMOTO 		memcpy(key->keyMaterial, keyMaterial, keyLen/8);
59fe2869c8SKris Kennaway 	}
60fe2869c8SKris Kennaway 
61fe2869c8SKris Kennaway 	/* initialize key schedule: */
625129dcfcSHajimu UMEMOTO 	memcpy(cipherKey, key->keyMaterial, keyLen/8);
635129dcfcSHajimu UMEMOTO 	if (direction == DIR_ENCRYPT) {
645129dcfcSHajimu UMEMOTO 		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
655129dcfcSHajimu UMEMOTO 	} else {
665129dcfcSHajimu UMEMOTO 		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
67fe2869c8SKris Kennaway 	}
685129dcfcSHajimu UMEMOTO 	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
69fe2869c8SKris Kennaway 	return TRUE;
70fe2869c8SKris Kennaway }
71fe2869c8SKris Kennaway 
72fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
73fe2869c8SKris Kennaway 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
74fe2869c8SKris Kennaway 		cipher->mode = mode;
75fe2869c8SKris Kennaway 	} else {
76fe2869c8SKris Kennaway 		return BAD_CIPHER_MODE;
77fe2869c8SKris Kennaway 	}
78fe2869c8SKris Kennaway 	if (IV != NULL) {
795129dcfcSHajimu UMEMOTO 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
80fe2869c8SKris Kennaway 	} else {
815129dcfcSHajimu UMEMOTO 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
82fe2869c8SKris Kennaway 	}
83fe2869c8SKris Kennaway 	return TRUE;
84fe2869c8SKris Kennaway }
85fe2869c8SKris Kennaway 
86fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
87fe2869c8SKris Kennaway 		BYTE *input, int inputLen, BYTE *outBuffer) {
889132d507SHajimu UMEMOTO 	int i, k, numBlocks;
895129dcfcSHajimu UMEMOTO 	u_int8_t block[16], iv[4][4];
90fe2869c8SKris Kennaway 
91fe2869c8SKris Kennaway 	if (cipher == NULL ||
92fe2869c8SKris Kennaway 		key == NULL ||
93fe2869c8SKris Kennaway 		key->direction == DIR_DECRYPT) {
94fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
95fe2869c8SKris Kennaway 	}
96fe2869c8SKris Kennaway 	if (input == NULL || inputLen <= 0) {
97fe2869c8SKris Kennaway 		return 0; /* nothing to do */
98fe2869c8SKris Kennaway 	}
99fe2869c8SKris Kennaway 
100fe2869c8SKris Kennaway 	numBlocks = inputLen/128;
101fe2869c8SKris Kennaway 
102fe2869c8SKris Kennaway 	switch (cipher->mode) {
103fe2869c8SKris Kennaway 	case MODE_ECB:
104fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
1055129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
106fe2869c8SKris Kennaway 			input += 16;
107fe2869c8SKris Kennaway 			outBuffer += 16;
108fe2869c8SKris Kennaway 		}
109fe2869c8SKris Kennaway 		break;
110fe2869c8SKris Kennaway 
111fe2869c8SKris Kennaway 	case MODE_CBC:
1123011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1135129dcfcSHajimu UMEMOTO 		memcpy(block, cipher->IV, 16);
1145129dcfcSHajimu UMEMOTO 		memcpy(iv, input, 16);
1155129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0];
1165129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1];
1175129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2];
1185129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3];
1193011d4b3SHajimu UMEMOTO #else
1205129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[0] = ((u_int32_t*)cipher->IV)[0] ^ ((u_int32_t*)input)[0];
1215129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[1] = ((u_int32_t*)cipher->IV)[1] ^ ((u_int32_t*)input)[1];
1225129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[2] = ((u_int32_t*)cipher->IV)[2] ^ ((u_int32_t*)input)[2];
1235129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[3] = ((u_int32_t*)cipher->IV)[3] ^ ((u_int32_t*)input)[3];
1243011d4b3SHajimu UMEMOTO #endif
1255129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
126fe2869c8SKris Kennaway 		input += 16;
1279132d507SHajimu UMEMOTO 		for (i = numBlocks - 1; i > 0; i--) {
1289132d507SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1295129dcfcSHajimu UMEMOTO 			memcpy(block, outBuffer, 16);
1305129dcfcSHajimu UMEMOTO 			memcpy(iv, input, 16);
1315129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0];
1325129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1];
1335129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2];
1345129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3];
1359132d507SHajimu UMEMOTO #else
1365129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[0] = ((u_int32_t*)outBuffer)[0] ^ ((u_int32_t*)input)[0];
1375129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[1] = ((u_int32_t*)outBuffer)[1] ^ ((u_int32_t*)input)[1];
1385129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[2] = ((u_int32_t*)outBuffer)[2] ^ ((u_int32_t*)input)[2];
1395129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[3] = ((u_int32_t*)outBuffer)[3] ^ ((u_int32_t*)input)[3];
1409132d507SHajimu UMEMOTO #endif
141fe2869c8SKris Kennaway 			outBuffer += 16;
1425129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
1439132d507SHajimu UMEMOTO 			input += 16;
144fe2869c8SKris Kennaway 		}
145fe2869c8SKris Kennaway 		break;
146fe2869c8SKris Kennaway 
147fe2869c8SKris Kennaway 	case MODE_CFB1:
1483011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1495129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
1509132d507SHajimu UMEMOTO #else  /* !STRICT_ALIGN */
1515129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV   ));
1525129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
1535129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
1545129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
1559132d507SHajimu UMEMOTO #endif /* ?STRICT_ALIGN */
156fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
157fe2869c8SKris Kennaway 			for (k = 0; k < 128; k++) {
1585129dcfcSHajimu UMEMOTO 				*((u_int32_t*) block    ) = *((u_int32_t*)iv[0]);
1595129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]);
1605129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]);
1615129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]);
1625129dcfcSHajimu UMEMOTO 				rijndaelEncrypt(key->ek, key->Nr, block,
1635129dcfcSHajimu UMEMOTO 				    block);
1649132d507SHajimu UMEMOTO 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
1659132d507SHajimu UMEMOTO 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
1669132d507SHajimu UMEMOTO 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
1679132d507SHajimu UMEMOTO 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
1689132d507SHajimu UMEMOTO 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
1699132d507SHajimu UMEMOTO 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
1709132d507SHajimu UMEMOTO 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
1719132d507SHajimu UMEMOTO 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
1729132d507SHajimu UMEMOTO 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
1739132d507SHajimu UMEMOTO 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
1749132d507SHajimu UMEMOTO 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
1759132d507SHajimu UMEMOTO 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
1769132d507SHajimu UMEMOTO 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
1779132d507SHajimu UMEMOTO 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
1789132d507SHajimu UMEMOTO 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
1799132d507SHajimu UMEMOTO 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
1809132d507SHajimu UMEMOTO 				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
181fe2869c8SKris Kennaway 			}
1828f21478bSHajimu UMEMOTO 		}
183fe2869c8SKris Kennaway 		break;
184fe2869c8SKris Kennaway 
185fe2869c8SKris Kennaway 	default:
186fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
187fe2869c8SKris Kennaway 	}
188fe2869c8SKris Kennaway 
189fe2869c8SKris Kennaway 	return 128*numBlocks;
190fe2869c8SKris Kennaway }
191fe2869c8SKris Kennaway 
192fe2869c8SKris Kennaway /**
193fe2869c8SKris Kennaway  * Encrypt data partitioned in octets, using RFC 2040-like padding.
194fe2869c8SKris Kennaway  *
195fe2869c8SKris Kennaway  * @param   input           data to be encrypted (octet sequence)
196fe2869c8SKris Kennaway  * @param   inputOctets		input length in octets (not bits)
197fe2869c8SKris Kennaway  * @param   outBuffer       encrypted output data
198fe2869c8SKris Kennaway  *
199fe2869c8SKris Kennaway  * @return	length in octets (not bits) of the encrypted output buffer.
200fe2869c8SKris Kennaway  */
201fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
202fe2869c8SKris Kennaway 		BYTE *input, int inputOctets, BYTE *outBuffer) {
203fe2869c8SKris Kennaway 	int i, numBlocks, padLen;
2045129dcfcSHajimu UMEMOTO 	u_int8_t block[16], *iv, *cp;
205fe2869c8SKris Kennaway 
206fe2869c8SKris Kennaway 	if (cipher == NULL ||
207fe2869c8SKris Kennaway 		key == NULL ||
208fe2869c8SKris Kennaway 		key->direction == DIR_DECRYPT) {
209fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
210fe2869c8SKris Kennaway 	}
211fe2869c8SKris Kennaway 	if (input == NULL || inputOctets <= 0) {
212fe2869c8SKris Kennaway 		return 0; /* nothing to do */
213fe2869c8SKris Kennaway 	}
214fe2869c8SKris Kennaway 
215fe2869c8SKris Kennaway 	numBlocks = inputOctets/16;
216fe2869c8SKris Kennaway 
217fe2869c8SKris Kennaway 	switch (cipher->mode) {
218fe2869c8SKris Kennaway 	case MODE_ECB:
219fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2205129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
221fe2869c8SKris Kennaway 			input += 16;
222fe2869c8SKris Kennaway 			outBuffer += 16;
223fe2869c8SKris Kennaway 		}
224fe2869c8SKris Kennaway 		padLen = 16 - (inputOctets - 16*numBlocks);
225eb159f5bSHajimu UMEMOTO 		if (padLen <= 0 || padLen > 16)
22627da1009SPoul-Henning Kamp 			return BAD_CIPHER_STATE;
2275129dcfcSHajimu UMEMOTO 		memcpy(block, input, 16 - padLen);
2289132d507SHajimu UMEMOTO 		for (cp = block + 16 - padLen; cp < block + 16; cp++)
2299132d507SHajimu UMEMOTO 			*cp = padLen;
2305129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
231fe2869c8SKris Kennaway 		break;
232fe2869c8SKris Kennaway 
233fe2869c8SKris Kennaway 	case MODE_CBC:
234fe2869c8SKris Kennaway 		iv = cipher->IV;
235fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2365129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0];
2375129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1];
2385129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2];
2395129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3];
2405129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
241fe2869c8SKris Kennaway 			iv = outBuffer;
242fe2869c8SKris Kennaway 			input += 16;
243fe2869c8SKris Kennaway 			outBuffer += 16;
244fe2869c8SKris Kennaway 		}
245fe2869c8SKris Kennaway 		padLen = 16 - (inputOctets - 16*numBlocks);
24666476d45SHajimu UMEMOTO 		if (padLen <= 0 || padLen > 16)
24727da1009SPoul-Henning Kamp 			return BAD_CIPHER_STATE;
248fe2869c8SKris Kennaway 		for (i = 0; i < 16 - padLen; i++) {
249fe2869c8SKris Kennaway 			block[i] = input[i] ^ iv[i];
250fe2869c8SKris Kennaway 		}
251fe2869c8SKris Kennaway 		for (i = 16 - padLen; i < 16; i++) {
252fe2869c8SKris Kennaway 			block[i] = (BYTE)padLen ^ iv[i];
253fe2869c8SKris Kennaway 		}
2545129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
255fe2869c8SKris Kennaway 		break;
256fe2869c8SKris Kennaway 
257fe2869c8SKris Kennaway 	default:
258fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
259fe2869c8SKris Kennaway 	}
260fe2869c8SKris Kennaway 
261fe2869c8SKris Kennaway 	return 16*(numBlocks + 1);
262fe2869c8SKris Kennaway }
263fe2869c8SKris Kennaway 
264fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
265fe2869c8SKris Kennaway 		BYTE *input, int inputLen, BYTE *outBuffer) {
2669132d507SHajimu UMEMOTO 	int i, k, numBlocks;
2675129dcfcSHajimu UMEMOTO 	u_int8_t block[16], iv[4][4];
268fe2869c8SKris Kennaway 
269fe2869c8SKris Kennaway 	if (cipher == NULL ||
270fe2869c8SKris Kennaway 		key == NULL ||
271fe2869c8SKris Kennaway 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
272fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
273fe2869c8SKris Kennaway 	}
274fe2869c8SKris Kennaway 	if (input == NULL || inputLen <= 0) {
275fe2869c8SKris Kennaway 		return 0; /* nothing to do */
276fe2869c8SKris Kennaway 	}
277fe2869c8SKris Kennaway 
278fe2869c8SKris Kennaway 	numBlocks = inputLen/128;
279fe2869c8SKris Kennaway 
280fe2869c8SKris Kennaway 	switch (cipher->mode) {
281fe2869c8SKris Kennaway 	case MODE_ECB:
282fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2835129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
284fe2869c8SKris Kennaway 			input += 16;
285fe2869c8SKris Kennaway 			outBuffer += 16;
286fe2869c8SKris Kennaway 		}
287fe2869c8SKris Kennaway 		break;
288fe2869c8SKris Kennaway 
289fe2869c8SKris Kennaway 	case MODE_CBC:
2903011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */
2915129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
2923011d4b3SHajimu UMEMOTO #else
2935129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV   ));
2945129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
2955129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
2965129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
2973011d4b3SHajimu UMEMOTO #endif
298fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2995129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, block);
3005129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[0] ^= *((u_int32_t*)iv[0]);
3015129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[1] ^= *((u_int32_t*)iv[1]);
3025129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[2] ^= *((u_int32_t*)iv[2]);
3035129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[3] ^= *((u_int32_t*)iv[3]);
3043011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
3055129dcfcSHajimu UMEMOTO 			memcpy(iv, input, 16);
3065129dcfcSHajimu UMEMOTO 			memcpy(outBuffer, block, 16);
3073011d4b3SHajimu UMEMOTO #else
3085129dcfcSHajimu UMEMOTO 			*((u_int32_t*)iv[0]) = ((u_int32_t*)input)[0]; ((u_int32_t*)outBuffer)[0] = ((u_int32_t*)block)[0];
3095129dcfcSHajimu UMEMOTO 			*((u_int32_t*)iv[1]) = ((u_int32_t*)input)[1]; ((u_int32_t*)outBuffer)[1] = ((u_int32_t*)block)[1];
3105129dcfcSHajimu UMEMOTO 			*((u_int32_t*)iv[2]) = ((u_int32_t*)input)[2]; ((u_int32_t*)outBuffer)[2] = ((u_int32_t*)block)[2];
3115129dcfcSHajimu UMEMOTO 			*((u_int32_t*)iv[3]) = ((u_int32_t*)input)[3]; ((u_int32_t*)outBuffer)[3] = ((u_int32_t*)block)[3];
3123011d4b3SHajimu UMEMOTO #endif
313fe2869c8SKris Kennaway 			input += 16;
314fe2869c8SKris Kennaway 			outBuffer += 16;
315fe2869c8SKris Kennaway 		}
316fe2869c8SKris Kennaway 		break;
317fe2869c8SKris Kennaway 
318fe2869c8SKris Kennaway 	case MODE_CFB1:
3193011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */
3205129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
3213011d4b3SHajimu UMEMOTO #else
3225129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV));
3235129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
3245129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
3255129dcfcSHajimu UMEMOTO 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
3263011d4b3SHajimu UMEMOTO #endif
327fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
328fe2869c8SKris Kennaway 			for (k = 0; k < 128; k++) {
3295129dcfcSHajimu UMEMOTO 				*((u_int32_t*) block    ) = *((u_int32_t*)iv[0]);
3305129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]);
3315129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]);
3325129dcfcSHajimu UMEMOTO 				*((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]);
3335129dcfcSHajimu UMEMOTO 				rijndaelEncrypt(key->ek, key->Nr, block,
3345129dcfcSHajimu UMEMOTO 				    block);
3359132d507SHajimu UMEMOTO 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
3369132d507SHajimu UMEMOTO 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
3379132d507SHajimu UMEMOTO 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
3389132d507SHajimu UMEMOTO 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
3399132d507SHajimu UMEMOTO 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
3409132d507SHajimu UMEMOTO 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
3419132d507SHajimu UMEMOTO 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
3429132d507SHajimu UMEMOTO 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
3439132d507SHajimu UMEMOTO 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
3449132d507SHajimu UMEMOTO 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
3459132d507SHajimu UMEMOTO 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
3469132d507SHajimu UMEMOTO 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
3479132d507SHajimu UMEMOTO 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
3489132d507SHajimu UMEMOTO 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
3499132d507SHajimu UMEMOTO 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
3509132d507SHajimu UMEMOTO 				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
3519132d507SHajimu UMEMOTO 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
352fe2869c8SKris Kennaway 			}
3538f21478bSHajimu UMEMOTO 		}
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;
3665129dcfcSHajimu UMEMOTO 	u_int8_t block[16];
3675129dcfcSHajimu UMEMOTO 	u_int32_t 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--) {
3875129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
388fe2869c8SKris Kennaway 			input += 16;
389fe2869c8SKris Kennaway 			outBuffer += 16;
390fe2869c8SKris Kennaway 		}
391fe2869c8SKris Kennaway 		/* last block */
3925129dcfcSHajimu UMEMOTO 		rijndaelDecrypt(key->rk, key->Nr, input, block);
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 		}
4025129dcfcSHajimu UMEMOTO 		memcpy(outBuffer, block, 16 - padLen);
403fe2869c8SKris Kennaway 		break;
404fe2869c8SKris Kennaway 
405fe2869c8SKris Kennaway 	case MODE_CBC:
4065129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
407fe2869c8SKris Kennaway 		/* all blocks but last */
408fe2869c8SKris Kennaway 		for (i = numBlocks - 1; i > 0; i--) {
4095129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, block);
4105129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[0] ^= iv[0];
4115129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[1] ^= iv[1];
4125129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[2] ^= iv[2];
4135129dcfcSHajimu UMEMOTO 			((u_int32_t*)block)[3] ^= iv[3];
4145129dcfcSHajimu UMEMOTO 			memcpy(iv, input, 16);
4155129dcfcSHajimu UMEMOTO 			memcpy(outBuffer, block, 16);
416fe2869c8SKris Kennaway 			input += 16;
417fe2869c8SKris Kennaway 			outBuffer += 16;
418fe2869c8SKris Kennaway 		}
419fe2869c8SKris Kennaway 		/* last block */
4205129dcfcSHajimu UMEMOTO 		rijndaelDecrypt(key->rk, key->Nr, input, block);
4215129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[0] ^= iv[0];
4225129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[1] ^= iv[1];
4235129dcfcSHajimu UMEMOTO 		((u_int32_t*)block)[2] ^= iv[2];
4245129dcfcSHajimu UMEMOTO 		((u_int32_t*)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 		}
4345129dcfcSHajimu UMEMOTO 		memcpy(outBuffer, block, 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 }
443