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 
18fe2869c8SKris Kennaway #include <sys/param.h>
1933841545SHajimu UMEMOTO #ifdef _KERNEL
2033841545SHajimu UMEMOTO #include <sys/systm.h>
2133841545SHajimu UMEMOTO #else
2233841545SHajimu UMEMOTO #include <string.h>
2333841545SHajimu UMEMOTO #endif
245129dcfcSHajimu UMEMOTO 
255129dcfcSHajimu UMEMOTO #include <crypto/rijndael/rijndael_local.h>
26fe2869c8SKris Kennaway #include <crypto/rijndael/rijndael-api-fst.h>
279132d507SHajimu UMEMOTO 
289132d507SHajimu UMEMOTO #ifndef TRUE
299132d507SHajimu UMEMOTO #define TRUE 1
309132d507SHajimu UMEMOTO #endif
319132d507SHajimu UMEMOTO 
32d3d79e96SJohn Baldwin typedef uint8_t	BYTE;
3327da1009SPoul-Henning Kamp 
rijndael_makeKey(keyInstance * key,BYTE direction,int keyLen,const char * keyMaterial)34133cdd9eSDag-Erling Smørgrav int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen,
35133cdd9eSDag-Erling Smørgrav 	const char *keyMaterial) {
36fe2869c8SKris Kennaway 
37fe2869c8SKris Kennaway 	if (key == NULL) {
38fe2869c8SKris Kennaway 		return BAD_KEY_INSTANCE;
39fe2869c8SKris Kennaway 	}
40fe2869c8SKris Kennaway 
41fe2869c8SKris Kennaway 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
42fe2869c8SKris Kennaway 		key->direction = direction;
43fe2869c8SKris Kennaway 	} else {
44fe2869c8SKris Kennaway 		return BAD_KEY_DIR;
45fe2869c8SKris Kennaway 	}
46fe2869c8SKris Kennaway 
47fe2869c8SKris Kennaway 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
48fe2869c8SKris Kennaway 		key->keyLen = keyLen;
49fe2869c8SKris Kennaway 	} else {
50fe2869c8SKris Kennaway 		return BAD_KEY_MAT;
51fe2869c8SKris Kennaway 	}
52fe2869c8SKris Kennaway 
53fe2869c8SKris Kennaway 	if (keyMaterial != NULL) {
545129dcfcSHajimu UMEMOTO 		memcpy(key->keyMaterial, keyMaterial, keyLen/8);
55fe2869c8SKris Kennaway 	}
56fe2869c8SKris Kennaway 
57fe2869c8SKris Kennaway 	/* initialize key schedule: */
585129dcfcSHajimu UMEMOTO 	if (direction == DIR_ENCRYPT) {
5907024904SConrad Meyer 		key->Nr = rijndaelKeySetupEnc(key->rk, key->keyMaterial, keyLen);
605129dcfcSHajimu UMEMOTO 	} else {
6107024904SConrad Meyer 		key->Nr = rijndaelKeySetupDec(key->rk, key->keyMaterial, keyLen);
62fe2869c8SKris Kennaway 	}
6307024904SConrad Meyer 	rijndaelKeySetupEnc(key->ek, key->keyMaterial, keyLen);
64fe2869c8SKris Kennaway 	return TRUE;
65fe2869c8SKris Kennaway }
66fe2869c8SKris Kennaway 
rijndael_cipherInit(cipherInstance * cipher,BYTE mode,char * IV)67fe2869c8SKris Kennaway int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
68fe2869c8SKris Kennaway 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
69fe2869c8SKris Kennaway 		cipher->mode = mode;
70fe2869c8SKris Kennaway 	} else {
71fe2869c8SKris Kennaway 		return BAD_CIPHER_MODE;
72fe2869c8SKris Kennaway 	}
73fe2869c8SKris Kennaway 	if (IV != NULL) {
745129dcfcSHajimu UMEMOTO 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
75fe2869c8SKris Kennaway 	} else {
765129dcfcSHajimu UMEMOTO 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
77fe2869c8SKris Kennaway 	}
78fe2869c8SKris Kennaway 	return TRUE;
79fe2869c8SKris Kennaway }
80fe2869c8SKris Kennaway 
rijndael_blockEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputLen,BYTE * outBuffer)81fe2869c8SKris Kennaway int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
82133cdd9eSDag-Erling Smørgrav 		const BYTE *input, int inputLen, BYTE *outBuffer) {
839132d507SHajimu UMEMOTO 	int i, k, numBlocks;
84d3d79e96SJohn Baldwin 	uint8_t block[16], iv[4][4];
85fe2869c8SKris Kennaway 
86fe2869c8SKris Kennaway 	if (cipher == NULL ||
87fe2869c8SKris Kennaway 		key == NULL ||
88fe2869c8SKris Kennaway 		key->direction == DIR_DECRYPT) {
89fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
90fe2869c8SKris Kennaway 	}
91fe2869c8SKris Kennaway 	if (input == NULL || inputLen <= 0) {
92fe2869c8SKris Kennaway 		return 0; /* nothing to do */
93fe2869c8SKris Kennaway 	}
94fe2869c8SKris Kennaway 
95fe2869c8SKris Kennaway 	numBlocks = inputLen/128;
96fe2869c8SKris Kennaway 
97fe2869c8SKris Kennaway 	switch (cipher->mode) {
98fe2869c8SKris Kennaway 	case MODE_ECB:
99fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
1005129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
101fe2869c8SKris Kennaway 			input += 16;
102fe2869c8SKris Kennaway 			outBuffer += 16;
103fe2869c8SKris Kennaway 		}
104fe2869c8SKris Kennaway 		break;
105fe2869c8SKris Kennaway 
106fe2869c8SKris Kennaway 	case MODE_CBC:
1073011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1085129dcfcSHajimu UMEMOTO 		memcpy(block, cipher->IV, 16);
1095129dcfcSHajimu UMEMOTO 		memcpy(iv, input, 16);
110d3d79e96SJohn Baldwin 		((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];
111d3d79e96SJohn Baldwin 		((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];
112d3d79e96SJohn Baldwin 		((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];
113d3d79e96SJohn Baldwin 		((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];
1143011d4b3SHajimu UMEMOTO #else
115d3d79e96SJohn Baldwin 		((uint32_t*)block)[0] = ((uint32_t*)cipher->IV)[0] ^ ((uint32_t*)input)[0];
116d3d79e96SJohn Baldwin 		((uint32_t*)block)[1] = ((uint32_t*)cipher->IV)[1] ^ ((uint32_t*)input)[1];
117d3d79e96SJohn Baldwin 		((uint32_t*)block)[2] = ((uint32_t*)cipher->IV)[2] ^ ((uint32_t*)input)[2];
118d3d79e96SJohn Baldwin 		((uint32_t*)block)[3] = ((uint32_t*)cipher->IV)[3] ^ ((uint32_t*)input)[3];
1193011d4b3SHajimu UMEMOTO #endif
1205129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
121fe2869c8SKris Kennaway 		input += 16;
1229132d507SHajimu UMEMOTO 		for (i = numBlocks - 1; i > 0; i--) {
1239132d507SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1245129dcfcSHajimu UMEMOTO 			memcpy(block, outBuffer, 16);
1255129dcfcSHajimu UMEMOTO 			memcpy(iv, input, 16);
126d3d79e96SJohn Baldwin 			((uint32_t*)block)[0] ^= ((uint32_t*)iv)[0];
127d3d79e96SJohn Baldwin 			((uint32_t*)block)[1] ^= ((uint32_t*)iv)[1];
128d3d79e96SJohn Baldwin 			((uint32_t*)block)[2] ^= ((uint32_t*)iv)[2];
129d3d79e96SJohn Baldwin 			((uint32_t*)block)[3] ^= ((uint32_t*)iv)[3];
1309132d507SHajimu UMEMOTO #else
131d3d79e96SJohn Baldwin 			((uint32_t*)block)[0] = ((uint32_t*)outBuffer)[0] ^ ((uint32_t*)input)[0];
132d3d79e96SJohn Baldwin 			((uint32_t*)block)[1] = ((uint32_t*)outBuffer)[1] ^ ((uint32_t*)input)[1];
133d3d79e96SJohn Baldwin 			((uint32_t*)block)[2] = ((uint32_t*)outBuffer)[2] ^ ((uint32_t*)input)[2];
134d3d79e96SJohn Baldwin 			((uint32_t*)block)[3] = ((uint32_t*)outBuffer)[3] ^ ((uint32_t*)input)[3];
1359132d507SHajimu UMEMOTO #endif
136fe2869c8SKris Kennaway 			outBuffer += 16;
1375129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
1389132d507SHajimu UMEMOTO 			input += 16;
139fe2869c8SKris Kennaway 		}
140fe2869c8SKris Kennaway 		break;
141fe2869c8SKris Kennaway 
142fe2869c8SKris Kennaway 	case MODE_CFB1:
1433011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
1445129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
1459132d507SHajimu UMEMOTO #else  /* !STRICT_ALIGN */
146d3d79e96SJohn Baldwin 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV   ));
147d3d79e96SJohn Baldwin 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
148d3d79e96SJohn Baldwin 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
149d3d79e96SJohn Baldwin 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
1509132d507SHajimu UMEMOTO #endif /* ?STRICT_ALIGN */
151fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
152fe2869c8SKris Kennaway 			for (k = 0; k < 128; k++) {
153d3d79e96SJohn Baldwin 				*((uint32_t*) block    ) = *((uint32_t*)iv[0]);
154d3d79e96SJohn Baldwin 				*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);
155d3d79e96SJohn Baldwin 				*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);
156d3d79e96SJohn Baldwin 				*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);
1575129dcfcSHajimu UMEMOTO 				rijndaelEncrypt(key->ek, key->Nr, block,
1585129dcfcSHajimu UMEMOTO 				    block);
1599132d507SHajimu UMEMOTO 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
1609132d507SHajimu UMEMOTO 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
1619132d507SHajimu UMEMOTO 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
1629132d507SHajimu UMEMOTO 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
1639132d507SHajimu UMEMOTO 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
1649132d507SHajimu UMEMOTO 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
1659132d507SHajimu UMEMOTO 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
1669132d507SHajimu UMEMOTO 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
1679132d507SHajimu UMEMOTO 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
1689132d507SHajimu UMEMOTO 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
1699132d507SHajimu UMEMOTO 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
1709132d507SHajimu UMEMOTO 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
1719132d507SHajimu UMEMOTO 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
1729132d507SHajimu UMEMOTO 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
1739132d507SHajimu UMEMOTO 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
1749132d507SHajimu UMEMOTO 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
1759132d507SHajimu UMEMOTO 				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
176fe2869c8SKris Kennaway 			}
1778f21478bSHajimu UMEMOTO 		}
178fe2869c8SKris Kennaway 		break;
179fe2869c8SKris Kennaway 
180fe2869c8SKris Kennaway 	default:
181fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
182fe2869c8SKris Kennaway 	}
183fe2869c8SKris Kennaway 
18407024904SConrad Meyer 	explicit_bzero(block, sizeof(block));
185fe2869c8SKris Kennaway 	return 128*numBlocks;
186fe2869c8SKris Kennaway }
187fe2869c8SKris Kennaway 
188fe2869c8SKris Kennaway /**
189fe2869c8SKris Kennaway  * Encrypt data partitioned in octets, using RFC 2040-like padding.
190fe2869c8SKris Kennaway  *
191fe2869c8SKris Kennaway  * @param   input           data to be encrypted (octet sequence)
192fe2869c8SKris Kennaway  * @param   inputOctets		input length in octets (not bits)
193fe2869c8SKris Kennaway  * @param   outBuffer       encrypted output data
194fe2869c8SKris Kennaway  *
195fe2869c8SKris Kennaway  * @return	length in octets (not bits) of the encrypted output buffer.
196fe2869c8SKris Kennaway  */
rijndael_padEncrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)197fe2869c8SKris Kennaway int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
198133cdd9eSDag-Erling Smørgrav 		const BYTE *input, int inputOctets, BYTE *outBuffer) {
199fe2869c8SKris Kennaway 	int i, numBlocks, padLen;
200d3d79e96SJohn Baldwin 	uint8_t block[16], *iv, *cp;
201fe2869c8SKris Kennaway 
202fe2869c8SKris Kennaway 	if (cipher == NULL ||
203fe2869c8SKris Kennaway 		key == NULL ||
204fe2869c8SKris Kennaway 		key->direction == DIR_DECRYPT) {
205fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
206fe2869c8SKris Kennaway 	}
207fe2869c8SKris Kennaway 	if (input == NULL || inputOctets <= 0) {
208fe2869c8SKris Kennaway 		return 0; /* nothing to do */
209fe2869c8SKris Kennaway 	}
210fe2869c8SKris Kennaway 
211fe2869c8SKris Kennaway 	numBlocks = inputOctets/16;
212fe2869c8SKris Kennaway 
213fe2869c8SKris Kennaway 	switch (cipher->mode) {
214fe2869c8SKris Kennaway 	case MODE_ECB:
215fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2165129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
217fe2869c8SKris Kennaway 			input += 16;
218fe2869c8SKris Kennaway 			outBuffer += 16;
219fe2869c8SKris Kennaway 		}
220fe2869c8SKris Kennaway 		padLen = 16 - (inputOctets - 16*numBlocks);
221eb159f5bSHajimu UMEMOTO 		if (padLen <= 0 || padLen > 16)
22227da1009SPoul-Henning Kamp 			return BAD_CIPHER_STATE;
2235129dcfcSHajimu UMEMOTO 		memcpy(block, input, 16 - padLen);
2249132d507SHajimu UMEMOTO 		for (cp = block + 16 - padLen; cp < block + 16; cp++)
2259132d507SHajimu UMEMOTO 			*cp = padLen;
2265129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
227fe2869c8SKris Kennaway 		break;
228fe2869c8SKris Kennaway 
229fe2869c8SKris Kennaway 	case MODE_CBC:
230fe2869c8SKris Kennaway 		iv = cipher->IV;
231fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
232d3d79e96SJohn Baldwin 			((uint32_t*)block)[0] = ((const uint32_t*)input)[0] ^ ((uint32_t*)iv)[0];
233d3d79e96SJohn Baldwin 			((uint32_t*)block)[1] = ((const uint32_t*)input)[1] ^ ((uint32_t*)iv)[1];
234d3d79e96SJohn Baldwin 			((uint32_t*)block)[2] = ((const uint32_t*)input)[2] ^ ((uint32_t*)iv)[2];
235d3d79e96SJohn Baldwin 			((uint32_t*)block)[3] = ((const uint32_t*)input)[3] ^ ((uint32_t*)iv)[3];
2365129dcfcSHajimu UMEMOTO 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
237fe2869c8SKris Kennaway 			iv = outBuffer;
238fe2869c8SKris Kennaway 			input += 16;
239fe2869c8SKris Kennaway 			outBuffer += 16;
240fe2869c8SKris Kennaway 		}
241fe2869c8SKris Kennaway 		padLen = 16 - (inputOctets - 16*numBlocks);
24266476d45SHajimu UMEMOTO 		if (padLen <= 0 || padLen > 16)
24327da1009SPoul-Henning Kamp 			return BAD_CIPHER_STATE;
244fe2869c8SKris Kennaway 		for (i = 0; i < 16 - padLen; i++) {
245fe2869c8SKris Kennaway 			block[i] = input[i] ^ iv[i];
246fe2869c8SKris Kennaway 		}
247fe2869c8SKris Kennaway 		for (i = 16 - padLen; i < 16; i++) {
248fe2869c8SKris Kennaway 			block[i] = (BYTE)padLen ^ iv[i];
249fe2869c8SKris Kennaway 		}
2505129dcfcSHajimu UMEMOTO 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
251fe2869c8SKris Kennaway 		break;
252fe2869c8SKris Kennaway 
253fe2869c8SKris Kennaway 	default:
254fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
255fe2869c8SKris Kennaway 	}
256fe2869c8SKris Kennaway 
25707024904SConrad Meyer 	explicit_bzero(block, sizeof(block));
258fe2869c8SKris Kennaway 	return 16*(numBlocks + 1);
259fe2869c8SKris Kennaway }
260fe2869c8SKris Kennaway 
rijndael_blockDecrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputLen,BYTE * outBuffer)261fe2869c8SKris Kennaway int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
262133cdd9eSDag-Erling Smørgrav 		const BYTE *input, int inputLen, BYTE *outBuffer) {
2639132d507SHajimu UMEMOTO 	int i, k, numBlocks;
264d3d79e96SJohn Baldwin 	uint8_t block[16], iv[4][4];
265fe2869c8SKris Kennaway 
266fe2869c8SKris Kennaway 	if (cipher == NULL ||
267fe2869c8SKris Kennaway 		key == NULL ||
268fe2869c8SKris Kennaway 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
269fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
270fe2869c8SKris Kennaway 	}
271fe2869c8SKris Kennaway 	if (input == NULL || inputLen <= 0) {
272fe2869c8SKris Kennaway 		return 0; /* nothing to do */
273fe2869c8SKris Kennaway 	}
274fe2869c8SKris Kennaway 
275fe2869c8SKris Kennaway 	numBlocks = inputLen/128;
276fe2869c8SKris Kennaway 
277fe2869c8SKris Kennaway 	switch (cipher->mode) {
278fe2869c8SKris Kennaway 	case MODE_ECB:
279fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2805129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
281fe2869c8SKris Kennaway 			input += 16;
282fe2869c8SKris Kennaway 			outBuffer += 16;
283fe2869c8SKris Kennaway 		}
284fe2869c8SKris Kennaway 		break;
285fe2869c8SKris Kennaway 
286fe2869c8SKris Kennaway 	case MODE_CBC:
2873011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */
2885129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
2893011d4b3SHajimu UMEMOTO #else
290d3d79e96SJohn Baldwin 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV   ));
291d3d79e96SJohn Baldwin 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
292d3d79e96SJohn Baldwin 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
293d3d79e96SJohn Baldwin 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
2943011d4b3SHajimu UMEMOTO #endif
295fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
2965129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, block);
297d3d79e96SJohn Baldwin 			((uint32_t*)block)[0] ^= *((uint32_t*)iv[0]);
298d3d79e96SJohn Baldwin 			((uint32_t*)block)[1] ^= *((uint32_t*)iv[1]);
299d3d79e96SJohn Baldwin 			((uint32_t*)block)[2] ^= *((uint32_t*)iv[2]);
300d3d79e96SJohn Baldwin 			((uint32_t*)block)[3] ^= *((uint32_t*)iv[3]);
3013011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN*/
3025129dcfcSHajimu UMEMOTO 			memcpy(iv, input, 16);
3035129dcfcSHajimu UMEMOTO 			memcpy(outBuffer, block, 16);
3043011d4b3SHajimu UMEMOTO #else
305d3d79e96SJohn Baldwin 			*((uint32_t*)iv[0]) = ((uint32_t*)input)[0]; ((uint32_t*)outBuffer)[0] = ((uint32_t*)block)[0];
306d3d79e96SJohn Baldwin 			*((uint32_t*)iv[1]) = ((uint32_t*)input)[1]; ((uint32_t*)outBuffer)[1] = ((uint32_t*)block)[1];
307d3d79e96SJohn Baldwin 			*((uint32_t*)iv[2]) = ((uint32_t*)input)[2]; ((uint32_t*)outBuffer)[2] = ((uint32_t*)block)[2];
308d3d79e96SJohn Baldwin 			*((uint32_t*)iv[3]) = ((uint32_t*)input)[3]; ((uint32_t*)outBuffer)[3] = ((uint32_t*)block)[3];
3093011d4b3SHajimu UMEMOTO #endif
310fe2869c8SKris Kennaway 			input += 16;
311fe2869c8SKris Kennaway 			outBuffer += 16;
312fe2869c8SKris Kennaway 		}
313fe2869c8SKris Kennaway 		break;
314fe2869c8SKris Kennaway 
315fe2869c8SKris Kennaway 	case MODE_CFB1:
3163011d4b3SHajimu UMEMOTO #if 1 /*STRICT_ALIGN */
3175129dcfcSHajimu UMEMOTO 		memcpy(iv, cipher->IV, 16);
3183011d4b3SHajimu UMEMOTO #else
319d3d79e96SJohn Baldwin 		*((uint32_t*)iv[0]) = *((uint32_t*)(cipher->IV));
320d3d79e96SJohn Baldwin 		*((uint32_t*)iv[1]) = *((uint32_t*)(cipher->IV+ 4));
321d3d79e96SJohn Baldwin 		*((uint32_t*)iv[2]) = *((uint32_t*)(cipher->IV+ 8));
322d3d79e96SJohn Baldwin 		*((uint32_t*)iv[3]) = *((uint32_t*)(cipher->IV+12));
3233011d4b3SHajimu UMEMOTO #endif
324fe2869c8SKris Kennaway 		for (i = numBlocks; i > 0; i--) {
325fe2869c8SKris Kennaway 			for (k = 0; k < 128; k++) {
326d3d79e96SJohn Baldwin 				*((uint32_t*) block    ) = *((uint32_t*)iv[0]);
327d3d79e96SJohn Baldwin 				*((uint32_t*)(block+ 4)) = *((uint32_t*)iv[1]);
328d3d79e96SJohn Baldwin 				*((uint32_t*)(block+ 8)) = *((uint32_t*)iv[2]);
329d3d79e96SJohn Baldwin 				*((uint32_t*)(block+12)) = *((uint32_t*)iv[3]);
3305129dcfcSHajimu UMEMOTO 				rijndaelEncrypt(key->ek, key->Nr, block,
3315129dcfcSHajimu UMEMOTO 				    block);
3329132d507SHajimu UMEMOTO 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
3339132d507SHajimu UMEMOTO 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
3349132d507SHajimu UMEMOTO 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
3359132d507SHajimu UMEMOTO 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
3369132d507SHajimu UMEMOTO 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
3379132d507SHajimu UMEMOTO 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
3389132d507SHajimu UMEMOTO 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
3399132d507SHajimu UMEMOTO 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
3409132d507SHajimu UMEMOTO 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
3419132d507SHajimu UMEMOTO 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
3429132d507SHajimu UMEMOTO 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
3439132d507SHajimu UMEMOTO 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
3449132d507SHajimu UMEMOTO 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
3459132d507SHajimu UMEMOTO 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
3469132d507SHajimu UMEMOTO 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
3479132d507SHajimu UMEMOTO 				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
3489132d507SHajimu UMEMOTO 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
349fe2869c8SKris Kennaway 			}
3508f21478bSHajimu UMEMOTO 		}
351fe2869c8SKris Kennaway 		break;
352fe2869c8SKris Kennaway 
353fe2869c8SKris Kennaway 	default:
354fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
355fe2869c8SKris Kennaway 	}
356fe2869c8SKris Kennaway 
35707024904SConrad Meyer 	explicit_bzero(block, sizeof(block));
358fe2869c8SKris Kennaway 	return 128*numBlocks;
359fe2869c8SKris Kennaway }
360fe2869c8SKris Kennaway 
rijndael_padDecrypt(cipherInstance * cipher,keyInstance * key,const BYTE * input,int inputOctets,BYTE * outBuffer)361fe2869c8SKris Kennaway int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
362133cdd9eSDag-Erling Smørgrav 		const BYTE *input, int inputOctets, BYTE *outBuffer) {
36307024904SConrad Meyer 	int i, numBlocks, padLen, rval;
364d3d79e96SJohn Baldwin 	uint8_t block[16];
365d3d79e96SJohn Baldwin 	uint32_t iv[4];
366fe2869c8SKris Kennaway 
367fe2869c8SKris Kennaway 	if (cipher == NULL ||
368fe2869c8SKris Kennaway 		key == NULL ||
369fe2869c8SKris Kennaway 		key->direction == DIR_ENCRYPT) {
370fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
371fe2869c8SKris Kennaway 	}
372fe2869c8SKris Kennaway 	if (input == NULL || inputOctets <= 0) {
373fe2869c8SKris Kennaway 		return 0; /* nothing to do */
374fe2869c8SKris Kennaway 	}
375fe2869c8SKris Kennaway 	if (inputOctets % 16 != 0) {
376fe2869c8SKris Kennaway 		return BAD_DATA;
377fe2869c8SKris Kennaway 	}
378fe2869c8SKris Kennaway 
379fe2869c8SKris Kennaway 	numBlocks = inputOctets/16;
380fe2869c8SKris Kennaway 
381fe2869c8SKris Kennaway 	switch (cipher->mode) {
382fe2869c8SKris Kennaway 	case MODE_ECB:
383fe2869c8SKris Kennaway 		/* all blocks but last */
384fe2869c8SKris Kennaway 		for (i = numBlocks - 1; i > 0; i--) {
3855129dcfcSHajimu UMEMOTO 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
386fe2869c8SKris Kennaway 			input += 16;
387fe2869c8SKris Kennaway 			outBuffer += 16;
388fe2869c8SKris Kennaway 		}
389fe2869c8SKris Kennaway 		/* last block */
3905129dcfcSHajimu UMEMOTO 		rijndaelDecrypt(key->rk, key->Nr, input, block);
391fe2869c8SKris Kennaway 		padLen = block[15];
392fe2869c8SKris Kennaway 		if (padLen >= 16) {
39307024904SConrad Meyer 			rval = BAD_DATA;
39407024904SConrad Meyer 			goto out;
395fe2869c8SKris Kennaway 		}
396fe2869c8SKris Kennaway 		for (i = 16 - padLen; i < 16; i++) {
397fe2869c8SKris Kennaway 			if (block[i] != padLen) {
39807024904SConrad Meyer 				rval = BAD_DATA;
39907024904SConrad Meyer 				goto out;
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);
410d3d79e96SJohn Baldwin 			((uint32_t*)block)[0] ^= iv[0];
411d3d79e96SJohn Baldwin 			((uint32_t*)block)[1] ^= iv[1];
412d3d79e96SJohn Baldwin 			((uint32_t*)block)[2] ^= iv[2];
413d3d79e96SJohn Baldwin 			((uint32_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);
421d3d79e96SJohn Baldwin 		((uint32_t*)block)[0] ^= iv[0];
422d3d79e96SJohn Baldwin 		((uint32_t*)block)[1] ^= iv[1];
423d3d79e96SJohn Baldwin 		((uint32_t*)block)[2] ^= iv[2];
424d3d79e96SJohn Baldwin 		((uint32_t*)block)[3] ^= iv[3];
425fe2869c8SKris Kennaway 		padLen = block[15];
426fe2869c8SKris Kennaway 		if (padLen <= 0 || padLen > 16) {
42707024904SConrad Meyer 			rval = BAD_DATA;
42807024904SConrad Meyer 			goto out;
429fe2869c8SKris Kennaway 		}
430fe2869c8SKris Kennaway 		for (i = 16 - padLen; i < 16; i++) {
431fe2869c8SKris Kennaway 			if (block[i] != padLen) {
43207024904SConrad Meyer 				rval = BAD_DATA;
43307024904SConrad Meyer 				goto out;
434fe2869c8SKris Kennaway 			}
435fe2869c8SKris Kennaway 		}
4365129dcfcSHajimu UMEMOTO 		memcpy(outBuffer, block, 16 - padLen);
437fe2869c8SKris Kennaway 		break;
438fe2869c8SKris Kennaway 
439fe2869c8SKris Kennaway 	default:
440fe2869c8SKris Kennaway 		return BAD_CIPHER_STATE;
441fe2869c8SKris Kennaway 	}
442fe2869c8SKris Kennaway 
44307024904SConrad Meyer 	rval = 16*numBlocks - padLen;
44407024904SConrad Meyer 
44507024904SConrad Meyer out:
44607024904SConrad Meyer 	explicit_bzero(block, sizeof(block));
44707024904SConrad Meyer 	return rval;
448fe2869c8SKris Kennaway }
449