1*86d7f5d3SJohn Marino /*	$FreeBSD: src/sys/crypto/rijndael/rijndael-api-fst.c,v 1.12 2005/03/11 16:26:10 ume Exp $	*/
2*86d7f5d3SJohn Marino /*	$KAME: rijndael-api-fst.c,v 1.10 2001/05/27 09:34:18 itojun Exp $	*/
3*86d7f5d3SJohn Marino 
4*86d7f5d3SJohn Marino /*
5*86d7f5d3SJohn Marino  * rijndael-api-fst.c   v2.3   April '2000
6*86d7f5d3SJohn Marino  *
7*86d7f5d3SJohn Marino  * Optimised ANSI C code
8*86d7f5d3SJohn Marino  *
9*86d7f5d3SJohn Marino  * authors: v1.0: Antoon Bosselaers
10*86d7f5d3SJohn Marino  *          v2.0: Vincent Rijmen
11*86d7f5d3SJohn Marino  *          v2.1: Vincent Rijmen
12*86d7f5d3SJohn Marino  *          v2.2: Vincent Rijmen
13*86d7f5d3SJohn Marino  *          v2.3: Paulo Barreto
14*86d7f5d3SJohn Marino  *          v2.4: Vincent Rijmen
15*86d7f5d3SJohn Marino  *
16*86d7f5d3SJohn Marino  * This code is placed in the public domain.
17*86d7f5d3SJohn Marino  */
18*86d7f5d3SJohn Marino 
19*86d7f5d3SJohn Marino #include <sys/param.h>
20*86d7f5d3SJohn Marino #ifdef _KERNEL
21*86d7f5d3SJohn Marino #include <sys/systm.h>
22*86d7f5d3SJohn Marino #else
23*86d7f5d3SJohn Marino #include <string.h>
24*86d7f5d3SJohn Marino #endif
25*86d7f5d3SJohn Marino 
26*86d7f5d3SJohn Marino #include <crypto/rijndael/rijndael_local.h>
27*86d7f5d3SJohn Marino #include <crypto/rijndael/rijndael-api-fst.h>
28*86d7f5d3SJohn Marino 
29*86d7f5d3SJohn Marino #ifndef TRUE
30*86d7f5d3SJohn Marino #define TRUE 1
31*86d7f5d3SJohn Marino #endif
32*86d7f5d3SJohn Marino 
33*86d7f5d3SJohn Marino typedef u_int8_t	BYTE;
34*86d7f5d3SJohn Marino 
rijndael_makeKey(keyInstance * key,BYTE direction,int keyLen,char * keyMaterial)35*86d7f5d3SJohn Marino int rijndael_makeKey(keyInstance *key, BYTE direction, int keyLen, char *keyMaterial) {
36*86d7f5d3SJohn Marino 	u_int8_t cipherKey[RIJNDAEL_MAXKB];
37*86d7f5d3SJohn Marino 
38*86d7f5d3SJohn Marino 	if (key == NULL) {
39*86d7f5d3SJohn Marino 		return BAD_KEY_INSTANCE;
40*86d7f5d3SJohn Marino 	}
41*86d7f5d3SJohn Marino 
42*86d7f5d3SJohn Marino 	if ((direction == DIR_ENCRYPT) || (direction == DIR_DECRYPT)) {
43*86d7f5d3SJohn Marino 		key->direction = direction;
44*86d7f5d3SJohn Marino 	} else {
45*86d7f5d3SJohn Marino 		return BAD_KEY_DIR;
46*86d7f5d3SJohn Marino 	}
47*86d7f5d3SJohn Marino 
48*86d7f5d3SJohn Marino 	if ((keyLen == 128) || (keyLen == 192) || (keyLen == 256)) {
49*86d7f5d3SJohn Marino 		key->keyLen = keyLen;
50*86d7f5d3SJohn Marino 	} else {
51*86d7f5d3SJohn Marino 		return BAD_KEY_MAT;
52*86d7f5d3SJohn Marino 	}
53*86d7f5d3SJohn Marino 
54*86d7f5d3SJohn Marino 	if (keyMaterial != NULL) {
55*86d7f5d3SJohn Marino 		memcpy(key->keyMaterial, keyMaterial, keyLen/8);
56*86d7f5d3SJohn Marino 	}
57*86d7f5d3SJohn Marino 
58*86d7f5d3SJohn Marino 	/* initialize key schedule: */
59*86d7f5d3SJohn Marino 	memcpy(cipherKey, key->keyMaterial, keyLen/8);
60*86d7f5d3SJohn Marino 	if (direction == DIR_ENCRYPT) {
61*86d7f5d3SJohn Marino 		key->Nr = rijndaelKeySetupEnc(key->rk, cipherKey, keyLen);
62*86d7f5d3SJohn Marino 	} else {
63*86d7f5d3SJohn Marino 		key->Nr = rijndaelKeySetupDec(key->rk, cipherKey, keyLen);
64*86d7f5d3SJohn Marino 	}
65*86d7f5d3SJohn Marino 	rijndaelKeySetupEnc(key->ek, cipherKey, keyLen);
66*86d7f5d3SJohn Marino 	return TRUE;
67*86d7f5d3SJohn Marino }
68*86d7f5d3SJohn Marino 
rijndael_cipherInit(cipherInstance * cipher,BYTE mode,char * IV)69*86d7f5d3SJohn Marino int rijndael_cipherInit(cipherInstance *cipher, BYTE mode, char *IV) {
70*86d7f5d3SJohn Marino 	if ((mode == MODE_ECB) || (mode == MODE_CBC) || (mode == MODE_CFB1)) {
71*86d7f5d3SJohn Marino 		cipher->mode = mode;
72*86d7f5d3SJohn Marino 	} else {
73*86d7f5d3SJohn Marino 		return BAD_CIPHER_MODE;
74*86d7f5d3SJohn Marino 	}
75*86d7f5d3SJohn Marino 	if (IV != NULL) {
76*86d7f5d3SJohn Marino 		memcpy(cipher->IV, IV, RIJNDAEL_MAX_IV_SIZE);
77*86d7f5d3SJohn Marino 	} else {
78*86d7f5d3SJohn Marino 		memset(cipher->IV, 0, RIJNDAEL_MAX_IV_SIZE);
79*86d7f5d3SJohn Marino 	}
80*86d7f5d3SJohn Marino 	return TRUE;
81*86d7f5d3SJohn Marino }
82*86d7f5d3SJohn Marino 
rijndael_blockEncrypt(cipherInstance * cipher,keyInstance * key,BYTE * input,int inputLen,BYTE * outBuffer)83*86d7f5d3SJohn Marino int rijndael_blockEncrypt(cipherInstance *cipher, keyInstance *key,
84*86d7f5d3SJohn Marino 		BYTE *input, int inputLen, BYTE *outBuffer) {
85*86d7f5d3SJohn Marino 	int i, k, numBlocks;
86*86d7f5d3SJohn Marino 	u_int8_t block[16], iv[4][4];
87*86d7f5d3SJohn Marino 
88*86d7f5d3SJohn Marino 	if (cipher == NULL ||
89*86d7f5d3SJohn Marino 		key == NULL ||
90*86d7f5d3SJohn Marino 		key->direction == DIR_DECRYPT) {
91*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
92*86d7f5d3SJohn Marino 	}
93*86d7f5d3SJohn Marino 	if (input == NULL || inputLen <= 0) {
94*86d7f5d3SJohn Marino 		return 0; /* nothing to do */
95*86d7f5d3SJohn Marino 	}
96*86d7f5d3SJohn Marino 
97*86d7f5d3SJohn Marino 	numBlocks = inputLen/128;
98*86d7f5d3SJohn Marino 
99*86d7f5d3SJohn Marino 	switch (cipher->mode) {
100*86d7f5d3SJohn Marino 	case MODE_ECB:
101*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
102*86d7f5d3SJohn Marino 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
103*86d7f5d3SJohn Marino 			input += 16;
104*86d7f5d3SJohn Marino 			outBuffer += 16;
105*86d7f5d3SJohn Marino 		}
106*86d7f5d3SJohn Marino 		break;
107*86d7f5d3SJohn Marino 
108*86d7f5d3SJohn Marino 	case MODE_CBC:
109*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN*/
110*86d7f5d3SJohn Marino 		memcpy(block, cipher->IV, 16);
111*86d7f5d3SJohn Marino 		memcpy(iv, input, 16);
112*86d7f5d3SJohn Marino 		((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0];
113*86d7f5d3SJohn Marino 		((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1];
114*86d7f5d3SJohn Marino 		((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2];
115*86d7f5d3SJohn Marino 		((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3];
116*86d7f5d3SJohn Marino #else
117*86d7f5d3SJohn Marino 		((u_int32_t*)block)[0] = ((u_int32_t*)cipher->IV)[0] ^ ((u_int32_t*)input)[0];
118*86d7f5d3SJohn Marino 		((u_int32_t*)block)[1] = ((u_int32_t*)cipher->IV)[1] ^ ((u_int32_t*)input)[1];
119*86d7f5d3SJohn Marino 		((u_int32_t*)block)[2] = ((u_int32_t*)cipher->IV)[2] ^ ((u_int32_t*)input)[2];
120*86d7f5d3SJohn Marino 		((u_int32_t*)block)[3] = ((u_int32_t*)cipher->IV)[3] ^ ((u_int32_t*)input)[3];
121*86d7f5d3SJohn Marino #endif
122*86d7f5d3SJohn Marino 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
123*86d7f5d3SJohn Marino 		input += 16;
124*86d7f5d3SJohn Marino 		for (i = numBlocks - 1; i > 0; i--) {
125*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN*/
126*86d7f5d3SJohn Marino 			memcpy(block, outBuffer, 16);
127*86d7f5d3SJohn Marino 			memcpy(iv, input, 16);
128*86d7f5d3SJohn Marino 			((u_int32_t*)block)[0] ^= ((u_int32_t*)iv)[0];
129*86d7f5d3SJohn Marino 			((u_int32_t*)block)[1] ^= ((u_int32_t*)iv)[1];
130*86d7f5d3SJohn Marino 			((u_int32_t*)block)[2] ^= ((u_int32_t*)iv)[2];
131*86d7f5d3SJohn Marino 			((u_int32_t*)block)[3] ^= ((u_int32_t*)iv)[3];
132*86d7f5d3SJohn Marino #else
133*86d7f5d3SJohn Marino 			((u_int32_t*)block)[0] = ((u_int32_t*)outBuffer)[0] ^ ((u_int32_t*)input)[0];
134*86d7f5d3SJohn Marino 			((u_int32_t*)block)[1] = ((u_int32_t*)outBuffer)[1] ^ ((u_int32_t*)input)[1];
135*86d7f5d3SJohn Marino 			((u_int32_t*)block)[2] = ((u_int32_t*)outBuffer)[2] ^ ((u_int32_t*)input)[2];
136*86d7f5d3SJohn Marino 			((u_int32_t*)block)[3] = ((u_int32_t*)outBuffer)[3] ^ ((u_int32_t*)input)[3];
137*86d7f5d3SJohn Marino #endif
138*86d7f5d3SJohn Marino 			outBuffer += 16;
139*86d7f5d3SJohn Marino 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
140*86d7f5d3SJohn Marino 			input += 16;
141*86d7f5d3SJohn Marino 		}
142*86d7f5d3SJohn Marino 		break;
143*86d7f5d3SJohn Marino 
144*86d7f5d3SJohn Marino 	case MODE_CFB1:
145*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN*/
146*86d7f5d3SJohn Marino 		memcpy(iv, cipher->IV, 16);
147*86d7f5d3SJohn Marino #else  /* !STRICT_ALIGN */
148*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV   ));
149*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
150*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
151*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
152*86d7f5d3SJohn Marino #endif /* ?STRICT_ALIGN */
153*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
154*86d7f5d3SJohn Marino 			for (k = 0; k < 128; k++) {
155*86d7f5d3SJohn Marino 				*((u_int32_t*) block    ) = *((u_int32_t*)iv[0]);
156*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]);
157*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]);
158*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]);
159*86d7f5d3SJohn Marino 				rijndaelEncrypt(key->ek, key->Nr, block,
160*86d7f5d3SJohn Marino 				    block);
161*86d7f5d3SJohn Marino 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
162*86d7f5d3SJohn Marino 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
163*86d7f5d3SJohn Marino 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
164*86d7f5d3SJohn Marino 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
165*86d7f5d3SJohn Marino 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
166*86d7f5d3SJohn Marino 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
167*86d7f5d3SJohn Marino 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
168*86d7f5d3SJohn Marino 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
169*86d7f5d3SJohn Marino 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
170*86d7f5d3SJohn Marino 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
171*86d7f5d3SJohn Marino 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
172*86d7f5d3SJohn Marino 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
173*86d7f5d3SJohn Marino 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
174*86d7f5d3SJohn Marino 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
175*86d7f5d3SJohn Marino 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
176*86d7f5d3SJohn Marino 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
177*86d7f5d3SJohn Marino 				iv[3][3] = (iv[3][3] << 1) | ((outBuffer[k/8] >> (7-(k&7))) & 1);
178*86d7f5d3SJohn Marino 			}
179*86d7f5d3SJohn Marino 		}
180*86d7f5d3SJohn Marino 		break;
181*86d7f5d3SJohn Marino 
182*86d7f5d3SJohn Marino 	default:
183*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
184*86d7f5d3SJohn Marino 	}
185*86d7f5d3SJohn Marino 
186*86d7f5d3SJohn Marino 	return 128*numBlocks;
187*86d7f5d3SJohn Marino }
188*86d7f5d3SJohn Marino 
189*86d7f5d3SJohn Marino /**
190*86d7f5d3SJohn Marino  * Encrypt data partitioned in octets, using RFC 2040-like padding.
191*86d7f5d3SJohn Marino  *
192*86d7f5d3SJohn Marino  * @param   input           data to be encrypted (octet sequence)
193*86d7f5d3SJohn Marino  * @param   inputOctets		input length in octets (not bits)
194*86d7f5d3SJohn Marino  * @param   outBuffer       encrypted output data
195*86d7f5d3SJohn Marino  *
196*86d7f5d3SJohn Marino  * @return	length in octets (not bits) of the encrypted output buffer.
197*86d7f5d3SJohn Marino  */
rijndael_padEncrypt(cipherInstance * cipher,keyInstance * key,BYTE * input,int inputOctets,BYTE * outBuffer)198*86d7f5d3SJohn Marino int rijndael_padEncrypt(cipherInstance *cipher, keyInstance *key,
199*86d7f5d3SJohn Marino 		BYTE *input, int inputOctets, BYTE *outBuffer) {
200*86d7f5d3SJohn Marino 	int i, numBlocks, padLen;
201*86d7f5d3SJohn Marino 	u_int8_t block[16], *iv, *cp;
202*86d7f5d3SJohn Marino 
203*86d7f5d3SJohn Marino 	if (cipher == NULL ||
204*86d7f5d3SJohn Marino 		key == NULL ||
205*86d7f5d3SJohn Marino 		key->direction == DIR_DECRYPT) {
206*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
207*86d7f5d3SJohn Marino 	}
208*86d7f5d3SJohn Marino 	if (input == NULL || inputOctets <= 0) {
209*86d7f5d3SJohn Marino 		return 0; /* nothing to do */
210*86d7f5d3SJohn Marino 	}
211*86d7f5d3SJohn Marino 
212*86d7f5d3SJohn Marino 	numBlocks = inputOctets/16;
213*86d7f5d3SJohn Marino 
214*86d7f5d3SJohn Marino 	switch (cipher->mode) {
215*86d7f5d3SJohn Marino 	case MODE_ECB:
216*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
217*86d7f5d3SJohn Marino 			rijndaelEncrypt(key->rk, key->Nr, input, outBuffer);
218*86d7f5d3SJohn Marino 			input += 16;
219*86d7f5d3SJohn Marino 			outBuffer += 16;
220*86d7f5d3SJohn Marino 		}
221*86d7f5d3SJohn Marino 		padLen = 16 - (inputOctets - 16*numBlocks);
222*86d7f5d3SJohn Marino 		if (padLen <= 0 || padLen > 16)
223*86d7f5d3SJohn Marino 			return BAD_CIPHER_STATE;
224*86d7f5d3SJohn Marino 		memcpy(block, input, 16 - padLen);
225*86d7f5d3SJohn Marino 		for (cp = block + 16 - padLen; cp < block + 16; cp++)
226*86d7f5d3SJohn Marino 			*cp = padLen;
227*86d7f5d3SJohn Marino 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
228*86d7f5d3SJohn Marino 		break;
229*86d7f5d3SJohn Marino 
230*86d7f5d3SJohn Marino 	case MODE_CBC:
231*86d7f5d3SJohn Marino 		iv = cipher->IV;
232*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
233*86d7f5d3SJohn Marino 			((u_int32_t*)block)[0] = ((u_int32_t*)input)[0] ^ ((u_int32_t*)iv)[0];
234*86d7f5d3SJohn Marino 			((u_int32_t*)block)[1] = ((u_int32_t*)input)[1] ^ ((u_int32_t*)iv)[1];
235*86d7f5d3SJohn Marino 			((u_int32_t*)block)[2] = ((u_int32_t*)input)[2] ^ ((u_int32_t*)iv)[2];
236*86d7f5d3SJohn Marino 			((u_int32_t*)block)[3] = ((u_int32_t*)input)[3] ^ ((u_int32_t*)iv)[3];
237*86d7f5d3SJohn Marino 			rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
238*86d7f5d3SJohn Marino 			iv = outBuffer;
239*86d7f5d3SJohn Marino 			input += 16;
240*86d7f5d3SJohn Marino 			outBuffer += 16;
241*86d7f5d3SJohn Marino 		}
242*86d7f5d3SJohn Marino 		padLen = 16 - (inputOctets - 16*numBlocks);
243*86d7f5d3SJohn Marino 		if (padLen <= 0 || padLen > 16)
244*86d7f5d3SJohn Marino 			return BAD_CIPHER_STATE;
245*86d7f5d3SJohn Marino 		for (i = 0; i < 16 - padLen; i++) {
246*86d7f5d3SJohn Marino 			block[i] = input[i] ^ iv[i];
247*86d7f5d3SJohn Marino 		}
248*86d7f5d3SJohn Marino 		for (i = 16 - padLen; i < 16; i++) {
249*86d7f5d3SJohn Marino 			block[i] = (BYTE)padLen ^ iv[i];
250*86d7f5d3SJohn Marino 		}
251*86d7f5d3SJohn Marino 		rijndaelEncrypt(key->rk, key->Nr, block, outBuffer);
252*86d7f5d3SJohn Marino 		break;
253*86d7f5d3SJohn Marino 
254*86d7f5d3SJohn Marino 	default:
255*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
256*86d7f5d3SJohn Marino 	}
257*86d7f5d3SJohn Marino 
258*86d7f5d3SJohn Marino 	return 16*(numBlocks + 1);
259*86d7f5d3SJohn Marino }
260*86d7f5d3SJohn Marino 
rijndael_blockDecrypt(cipherInstance * cipher,keyInstance * key,BYTE * input,int inputLen,BYTE * outBuffer)261*86d7f5d3SJohn Marino int rijndael_blockDecrypt(cipherInstance *cipher, keyInstance *key,
262*86d7f5d3SJohn Marino 		BYTE *input, int inputLen, BYTE *outBuffer) {
263*86d7f5d3SJohn Marino 	int i, k, numBlocks;
264*86d7f5d3SJohn Marino 	u_int8_t block[16], iv[4][4];
265*86d7f5d3SJohn Marino 
266*86d7f5d3SJohn Marino 	if (cipher == NULL ||
267*86d7f5d3SJohn Marino 		key == NULL ||
268*86d7f5d3SJohn Marino 		(cipher->mode != MODE_CFB1 && key->direction == DIR_ENCRYPT)) {
269*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
270*86d7f5d3SJohn Marino 	}
271*86d7f5d3SJohn Marino 	if (input == NULL || inputLen <= 0) {
272*86d7f5d3SJohn Marino 		return 0; /* nothing to do */
273*86d7f5d3SJohn Marino 	}
274*86d7f5d3SJohn Marino 
275*86d7f5d3SJohn Marino 	numBlocks = inputLen/128;
276*86d7f5d3SJohn Marino 
277*86d7f5d3SJohn Marino 	switch (cipher->mode) {
278*86d7f5d3SJohn Marino 	case MODE_ECB:
279*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
280*86d7f5d3SJohn Marino 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
281*86d7f5d3SJohn Marino 			input += 16;
282*86d7f5d3SJohn Marino 			outBuffer += 16;
283*86d7f5d3SJohn Marino 		}
284*86d7f5d3SJohn Marino 		break;
285*86d7f5d3SJohn Marino 
286*86d7f5d3SJohn Marino 	case MODE_CBC:
287*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN */
288*86d7f5d3SJohn Marino 		memcpy(iv, cipher->IV, 16);
289*86d7f5d3SJohn Marino #else
290*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV   ));
291*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
292*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
293*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
294*86d7f5d3SJohn Marino #endif
295*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
296*86d7f5d3SJohn Marino 			rijndaelDecrypt(key->rk, key->Nr, input, block);
297*86d7f5d3SJohn Marino 			((u_int32_t*)block)[0] ^= *((u_int32_t*)iv[0]);
298*86d7f5d3SJohn Marino 			((u_int32_t*)block)[1] ^= *((u_int32_t*)iv[1]);
299*86d7f5d3SJohn Marino 			((u_int32_t*)block)[2] ^= *((u_int32_t*)iv[2]);
300*86d7f5d3SJohn Marino 			((u_int32_t*)block)[3] ^= *((u_int32_t*)iv[3]);
301*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN*/
302*86d7f5d3SJohn Marino 			memcpy(iv, input, 16);
303*86d7f5d3SJohn Marino 			memcpy(outBuffer, block, 16);
304*86d7f5d3SJohn Marino #else
305*86d7f5d3SJohn Marino 			*((u_int32_t*)iv[0]) = ((u_int32_t*)input)[0]; ((u_int32_t*)outBuffer)[0] = ((u_int32_t*)block)[0];
306*86d7f5d3SJohn Marino 			*((u_int32_t*)iv[1]) = ((u_int32_t*)input)[1]; ((u_int32_t*)outBuffer)[1] = ((u_int32_t*)block)[1];
307*86d7f5d3SJohn Marino 			*((u_int32_t*)iv[2]) = ((u_int32_t*)input)[2]; ((u_int32_t*)outBuffer)[2] = ((u_int32_t*)block)[2];
308*86d7f5d3SJohn Marino 			*((u_int32_t*)iv[3]) = ((u_int32_t*)input)[3]; ((u_int32_t*)outBuffer)[3] = ((u_int32_t*)block)[3];
309*86d7f5d3SJohn Marino #endif
310*86d7f5d3SJohn Marino 			input += 16;
311*86d7f5d3SJohn Marino 			outBuffer += 16;
312*86d7f5d3SJohn Marino 		}
313*86d7f5d3SJohn Marino 		break;
314*86d7f5d3SJohn Marino 
315*86d7f5d3SJohn Marino 	case MODE_CFB1:
316*86d7f5d3SJohn Marino #if 1 /*STRICT_ALIGN */
317*86d7f5d3SJohn Marino 		memcpy(iv, cipher->IV, 16);
318*86d7f5d3SJohn Marino #else
319*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[0]) = *((u_int32_t*)(cipher->IV));
320*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[1]) = *((u_int32_t*)(cipher->IV+ 4));
321*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[2]) = *((u_int32_t*)(cipher->IV+ 8));
322*86d7f5d3SJohn Marino 		*((u_int32_t*)iv[3]) = *((u_int32_t*)(cipher->IV+12));
323*86d7f5d3SJohn Marino #endif
324*86d7f5d3SJohn Marino 		for (i = numBlocks; i > 0; i--) {
325*86d7f5d3SJohn Marino 			for (k = 0; k < 128; k++) {
326*86d7f5d3SJohn Marino 				*((u_int32_t*) block    ) = *((u_int32_t*)iv[0]);
327*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+ 4)) = *((u_int32_t*)iv[1]);
328*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+ 8)) = *((u_int32_t*)iv[2]);
329*86d7f5d3SJohn Marino 				*((u_int32_t*)(block+12)) = *((u_int32_t*)iv[3]);
330*86d7f5d3SJohn Marino 				rijndaelEncrypt(key->ek, key->Nr, block,
331*86d7f5d3SJohn Marino 				    block);
332*86d7f5d3SJohn Marino 				iv[0][0] = (iv[0][0] << 1) | (iv[0][1] >> 7);
333*86d7f5d3SJohn Marino 				iv[0][1] = (iv[0][1] << 1) | (iv[0][2] >> 7);
334*86d7f5d3SJohn Marino 				iv[0][2] = (iv[0][2] << 1) | (iv[0][3] >> 7);
335*86d7f5d3SJohn Marino 				iv[0][3] = (iv[0][3] << 1) | (iv[1][0] >> 7);
336*86d7f5d3SJohn Marino 				iv[1][0] = (iv[1][0] << 1) | (iv[1][1] >> 7);
337*86d7f5d3SJohn Marino 				iv[1][1] = (iv[1][1] << 1) | (iv[1][2] >> 7);
338*86d7f5d3SJohn Marino 				iv[1][2] = (iv[1][2] << 1) | (iv[1][3] >> 7);
339*86d7f5d3SJohn Marino 				iv[1][3] = (iv[1][3] << 1) | (iv[2][0] >> 7);
340*86d7f5d3SJohn Marino 				iv[2][0] = (iv[2][0] << 1) | (iv[2][1] >> 7);
341*86d7f5d3SJohn Marino 				iv[2][1] = (iv[2][1] << 1) | (iv[2][2] >> 7);
342*86d7f5d3SJohn Marino 				iv[2][2] = (iv[2][2] << 1) | (iv[2][3] >> 7);
343*86d7f5d3SJohn Marino 				iv[2][3] = (iv[2][3] << 1) | (iv[3][0] >> 7);
344*86d7f5d3SJohn Marino 				iv[3][0] = (iv[3][0] << 1) | (iv[3][1] >> 7);
345*86d7f5d3SJohn Marino 				iv[3][1] = (iv[3][1] << 1) | (iv[3][2] >> 7);
346*86d7f5d3SJohn Marino 				iv[3][2] = (iv[3][2] << 1) | (iv[3][3] >> 7);
347*86d7f5d3SJohn Marino 				iv[3][3] = (iv[3][3] << 1) | ((input[k/8] >> (7-(k&7))) & 1);
348*86d7f5d3SJohn Marino 				outBuffer[k/8] ^= (block[0] & 0x80) >> (k & 7);
349*86d7f5d3SJohn Marino 			}
350*86d7f5d3SJohn Marino 		}
351*86d7f5d3SJohn Marino 		break;
352*86d7f5d3SJohn Marino 
353*86d7f5d3SJohn Marino 	default:
354*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
355*86d7f5d3SJohn Marino 	}
356*86d7f5d3SJohn Marino 
357*86d7f5d3SJohn Marino 	return 128*numBlocks;
358*86d7f5d3SJohn Marino }
359*86d7f5d3SJohn Marino 
rijndael_padDecrypt(cipherInstance * cipher,keyInstance * key,BYTE * input,int inputOctets,BYTE * outBuffer)360*86d7f5d3SJohn Marino int rijndael_padDecrypt(cipherInstance *cipher, keyInstance *key,
361*86d7f5d3SJohn Marino 		BYTE *input, int inputOctets, BYTE *outBuffer) {
362*86d7f5d3SJohn Marino 	int i, numBlocks, padLen;
363*86d7f5d3SJohn Marino 	u_int8_t block[16];
364*86d7f5d3SJohn Marino 	u_int32_t iv[4];
365*86d7f5d3SJohn Marino 
366*86d7f5d3SJohn Marino 	if (cipher == NULL ||
367*86d7f5d3SJohn Marino 		key == NULL ||
368*86d7f5d3SJohn Marino 		key->direction == DIR_ENCRYPT) {
369*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
370*86d7f5d3SJohn Marino 	}
371*86d7f5d3SJohn Marino 	if (input == NULL || inputOctets <= 0) {
372*86d7f5d3SJohn Marino 		return 0; /* nothing to do */
373*86d7f5d3SJohn Marino 	}
374*86d7f5d3SJohn Marino 	if (inputOctets % 16 != 0) {
375*86d7f5d3SJohn Marino 		return BAD_DATA;
376*86d7f5d3SJohn Marino 	}
377*86d7f5d3SJohn Marino 
378*86d7f5d3SJohn Marino 	numBlocks = inputOctets/16;
379*86d7f5d3SJohn Marino 
380*86d7f5d3SJohn Marino 	switch (cipher->mode) {
381*86d7f5d3SJohn Marino 	case MODE_ECB:
382*86d7f5d3SJohn Marino 		/* all blocks but last */
383*86d7f5d3SJohn Marino 		for (i = numBlocks - 1; i > 0; i--) {
384*86d7f5d3SJohn Marino 			rijndaelDecrypt(key->rk, key->Nr, input, outBuffer);
385*86d7f5d3SJohn Marino 			input += 16;
386*86d7f5d3SJohn Marino 			outBuffer += 16;
387*86d7f5d3SJohn Marino 		}
388*86d7f5d3SJohn Marino 		/* last block */
389*86d7f5d3SJohn Marino 		rijndaelDecrypt(key->rk, key->Nr, input, block);
390*86d7f5d3SJohn Marino 		padLen = block[15];
391*86d7f5d3SJohn Marino 		if (padLen >= 16) {
392*86d7f5d3SJohn Marino 			return BAD_DATA;
393*86d7f5d3SJohn Marino 		}
394*86d7f5d3SJohn Marino 		for (i = 16 - padLen; i < 16; i++) {
395*86d7f5d3SJohn Marino 			if (block[i] != padLen) {
396*86d7f5d3SJohn Marino 				return BAD_DATA;
397*86d7f5d3SJohn Marino 			}
398*86d7f5d3SJohn Marino 		}
399*86d7f5d3SJohn Marino 		memcpy(outBuffer, block, 16 - padLen);
400*86d7f5d3SJohn Marino 		break;
401*86d7f5d3SJohn Marino 
402*86d7f5d3SJohn Marino 	case MODE_CBC:
403*86d7f5d3SJohn Marino 		memcpy(iv, cipher->IV, 16);
404*86d7f5d3SJohn Marino 		/* all blocks but last */
405*86d7f5d3SJohn Marino 		for (i = numBlocks - 1; i > 0; i--) {
406*86d7f5d3SJohn Marino 			rijndaelDecrypt(key->rk, key->Nr, input, block);
407*86d7f5d3SJohn Marino 			((u_int32_t*)block)[0] ^= iv[0];
408*86d7f5d3SJohn Marino 			((u_int32_t*)block)[1] ^= iv[1];
409*86d7f5d3SJohn Marino 			((u_int32_t*)block)[2] ^= iv[2];
410*86d7f5d3SJohn Marino 			((u_int32_t*)block)[3] ^= iv[3];
411*86d7f5d3SJohn Marino 			memcpy(iv, input, 16);
412*86d7f5d3SJohn Marino 			memcpy(outBuffer, block, 16);
413*86d7f5d3SJohn Marino 			input += 16;
414*86d7f5d3SJohn Marino 			outBuffer += 16;
415*86d7f5d3SJohn Marino 		}
416*86d7f5d3SJohn Marino 		/* last block */
417*86d7f5d3SJohn Marino 		rijndaelDecrypt(key->rk, key->Nr, input, block);
418*86d7f5d3SJohn Marino 		((u_int32_t*)block)[0] ^= iv[0];
419*86d7f5d3SJohn Marino 		((u_int32_t*)block)[1] ^= iv[1];
420*86d7f5d3SJohn Marino 		((u_int32_t*)block)[2] ^= iv[2];
421*86d7f5d3SJohn Marino 		((u_int32_t*)block)[3] ^= iv[3];
422*86d7f5d3SJohn Marino 		padLen = block[15];
423*86d7f5d3SJohn Marino 		if (padLen <= 0 || padLen > 16) {
424*86d7f5d3SJohn Marino 			return BAD_DATA;
425*86d7f5d3SJohn Marino 		}
426*86d7f5d3SJohn Marino 		for (i = 16 - padLen; i < 16; i++) {
427*86d7f5d3SJohn Marino 			if (block[i] != padLen) {
428*86d7f5d3SJohn Marino 				return BAD_DATA;
429*86d7f5d3SJohn Marino 			}
430*86d7f5d3SJohn Marino 		}
431*86d7f5d3SJohn Marino 		memcpy(outBuffer, block, 16 - padLen);
432*86d7f5d3SJohn Marino 		break;
433*86d7f5d3SJohn Marino 
434*86d7f5d3SJohn Marino 	default:
435*86d7f5d3SJohn Marino 		return BAD_CIPHER_STATE;
436*86d7f5d3SJohn Marino 	}
437*86d7f5d3SJohn Marino 
438*86d7f5d3SJohn Marino 	return 16*numBlocks - padLen;
439*86d7f5d3SJohn Marino }
440