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