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