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