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