1 /* LibTomCrypt, modular cryptographic library -- Tom St Denis
2 *
3 * LibTomCrypt is a library that provides various cryptographic
4 * algorithms in a highly modular and flexible manner.
5 *
6 * The library is free for all purposes without any express
7 * guarantee it works.
8 *
9 * Tom St Denis, tomstdenis@gmail.com, http://libtom.org
10 */
11
12 /* AES implementation by Tom St Denis
13 *
14 * Derived from the Public Domain source code by
15
16 ---
17 * rijndael-alg-fst.c
18 *
19 * @version 3.0 (December 2000)
20 *
21 * Optimised ANSI C code for the Rijndael cipher (now AES)
22 *
23 * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
24 * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
25 * @author Paulo Barreto <paulo.barreto@terra.com.br>
26 ---
27 */
28 /**
29 @file aes.c
30 Implementation of AES
31 */
32
33 #include "tomcrypt.h"
34
35 #ifdef LTC_RIJNDAEL
36
37 #ifndef ENCRYPT_ONLY
38
39 #define SETUP rijndael_setup
40 #define ECB_ENC rijndael_ecb_encrypt
41 #define ECB_DEC rijndael_ecb_decrypt
42 #define ECB_DONE rijndael_done
43 #define ECB_TEST rijndael_test
44 #define ECB_KS rijndael_keysize
45
46 const struct ltc_cipher_descriptor rijndael_desc =
47 {
48 "rijndael",
49 6,
50 16, 32, 16, 10,
51 SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,
52 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
53 };
54
55 const struct ltc_cipher_descriptor aes_desc =
56 {
57 "aes",
58 6,
59 16, 32, 16, 10,
60 SETUP, ECB_ENC, ECB_DEC, ECB_TEST, ECB_DONE, ECB_KS,
61 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
62 };
63
64 #else
65
66 #define SETUP rijndael_enc_setup
67 #define ECB_ENC rijndael_enc_ecb_encrypt
68 #define ECB_KS rijndael_enc_keysize
69 #define ECB_DONE rijndael_enc_done
70
71 const struct ltc_cipher_descriptor rijndael_enc_desc =
72 {
73 "rijndael",
74 6,
75 16, 32, 16, 10,
76 SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,
77 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
78 };
79
80 const struct ltc_cipher_descriptor aes_enc_desc =
81 {
82 "aes",
83 6,
84 16, 32, 16, 10,
85 SETUP, ECB_ENC, NULL, NULL, ECB_DONE, ECB_KS,
86 NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
87 };
88
89 #endif
90
91 #define __LTC_AES_TAB_C__
92 #include "aes_tab.c"
93
setup_mix(ulong32 temp)94 static ulong32 setup_mix(ulong32 temp)
95 {
96 return (Te4_3[byte(temp, 2)]) ^
97 (Te4_2[byte(temp, 1)]) ^
98 (Te4_1[byte(temp, 0)]) ^
99 (Te4_0[byte(temp, 3)]);
100 }
101
102 #ifndef ENCRYPT_ONLY
103 #ifdef LTC_SMALL_CODE
setup_mix2(ulong32 temp)104 static ulong32 setup_mix2(ulong32 temp)
105 {
106 return Td0(255 & Te4[byte(temp, 3)]) ^
107 Td1(255 & Te4[byte(temp, 2)]) ^
108 Td2(255 & Te4[byte(temp, 1)]) ^
109 Td3(255 & Te4[byte(temp, 0)]);
110 }
111 #endif
112 #endif
113
114 /**
115 Initialize the AES (Rijndael) block cipher
116 @param key The symmetric key you wish to pass
117 @param keylen The key length in bytes
118 @param num_rounds The number of rounds desired (0 for default)
119 @param skey The key in as scheduled by this function.
120 @return CRYPT_OK if successful
121 */
SETUP(const unsigned char * key,int keylen,int num_rounds,symmetric_key * skey)122 int SETUP(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
123 {
124 int i;
125 ulong32 temp, *rk;
126 #ifndef ENCRYPT_ONLY
127 ulong32 *rrk;
128 #endif
129 LTC_ARGCHK(key != NULL);
130 LTC_ARGCHK(skey != NULL);
131
132 if (keylen != 16 && keylen != 24 && keylen != 32) {
133 return CRYPT_INVALID_KEYSIZE;
134 }
135
136 if (num_rounds != 0 && num_rounds != (10 + ((keylen/8)-2)*2)) {
137 return CRYPT_INVALID_ROUNDS;
138 }
139
140 skey->rijndael.Nr = 10 + ((keylen/8)-2)*2;
141
142 /* setup the forward key */
143 i = 0;
144 rk = skey->rijndael.eK;
145 LOAD32H(rk[0], key );
146 LOAD32H(rk[1], key + 4);
147 LOAD32H(rk[2], key + 8);
148 LOAD32H(rk[3], key + 12);
149 if (keylen == 16) {
150 for (;;) {
151 temp = rk[3];
152 rk[4] = rk[0] ^ setup_mix(temp) ^ rcon[i];
153 rk[5] = rk[1] ^ rk[4];
154 rk[6] = rk[2] ^ rk[5];
155 rk[7] = rk[3] ^ rk[6];
156 if (++i == 10) {
157 break;
158 }
159 rk += 4;
160 }
161 } else if (keylen == 24) {
162 LOAD32H(rk[4], key + 16);
163 LOAD32H(rk[5], key + 20);
164 for (;;) {
165 #ifdef _MSC_VER
166 temp = skey->rijndael.eK[rk - skey->rijndael.eK + 5];
167 #else
168 temp = rk[5];
169 #endif
170 rk[ 6] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
171 rk[ 7] = rk[ 1] ^ rk[ 6];
172 rk[ 8] = rk[ 2] ^ rk[ 7];
173 rk[ 9] = rk[ 3] ^ rk[ 8];
174 if (++i == 8) {
175 break;
176 }
177 rk[10] = rk[ 4] ^ rk[ 9];
178 rk[11] = rk[ 5] ^ rk[10];
179 rk += 6;
180 }
181 } else if (keylen == 32) {
182 LOAD32H(rk[4], key + 16);
183 LOAD32H(rk[5], key + 20);
184 LOAD32H(rk[6], key + 24);
185 LOAD32H(rk[7], key + 28);
186 for (;;) {
187 #ifdef _MSC_VER
188 temp = skey->rijndael.eK[rk - skey->rijndael.eK + 7];
189 #else
190 temp = rk[7];
191 #endif
192 rk[ 8] = rk[ 0] ^ setup_mix(temp) ^ rcon[i];
193 rk[ 9] = rk[ 1] ^ rk[ 8];
194 rk[10] = rk[ 2] ^ rk[ 9];
195 rk[11] = rk[ 3] ^ rk[10];
196 if (++i == 7) {
197 break;
198 }
199 temp = rk[11];
200 rk[12] = rk[ 4] ^ setup_mix(RORc(temp, 8));
201 rk[13] = rk[ 5] ^ rk[12];
202 rk[14] = rk[ 6] ^ rk[13];
203 rk[15] = rk[ 7] ^ rk[14];
204 rk += 8;
205 }
206 } else {
207 /* this can't happen */
208 /* coverity[dead_error_line] */
209 return CRYPT_ERROR;
210 }
211
212 #ifndef ENCRYPT_ONLY
213 /* setup the inverse key now */
214 rk = skey->rijndael.dK;
215 rrk = skey->rijndael.eK + (28 + keylen) - 4;
216
217 /* apply the inverse MixColumn transform to all round keys but the first and the last: */
218 /* copy first */
219 *rk++ = *rrk++;
220 *rk++ = *rrk++;
221 *rk++ = *rrk++;
222 *rk = *rrk;
223 rk -= 3; rrk -= 3;
224
225 for (i = 1; i < skey->rijndael.Nr; i++) {
226 rrk -= 4;
227 rk += 4;
228 #ifdef LTC_SMALL_CODE
229 temp = rrk[0];
230 rk[0] = setup_mix2(temp);
231 temp = rrk[1];
232 rk[1] = setup_mix2(temp);
233 temp = rrk[2];
234 rk[2] = setup_mix2(temp);
235 temp = rrk[3];
236 rk[3] = setup_mix2(temp);
237 #else
238 temp = rrk[0];
239 rk[0] =
240 Tks0[byte(temp, 3)] ^
241 Tks1[byte(temp, 2)] ^
242 Tks2[byte(temp, 1)] ^
243 Tks3[byte(temp, 0)];
244 temp = rrk[1];
245 rk[1] =
246 Tks0[byte(temp, 3)] ^
247 Tks1[byte(temp, 2)] ^
248 Tks2[byte(temp, 1)] ^
249 Tks3[byte(temp, 0)];
250 temp = rrk[2];
251 rk[2] =
252 Tks0[byte(temp, 3)] ^
253 Tks1[byte(temp, 2)] ^
254 Tks2[byte(temp, 1)] ^
255 Tks3[byte(temp, 0)];
256 temp = rrk[3];
257 rk[3] =
258 Tks0[byte(temp, 3)] ^
259 Tks1[byte(temp, 2)] ^
260 Tks2[byte(temp, 1)] ^
261 Tks3[byte(temp, 0)];
262 #endif
263
264 }
265
266 /* copy last */
267 rrk -= 4;
268 rk += 4;
269 *rk++ = *rrk++;
270 *rk++ = *rrk++;
271 *rk++ = *rrk++;
272 *rk = *rrk;
273 #endif /* ENCRYPT_ONLY */
274
275 return CRYPT_OK;
276 }
277
278 /**
279 Encrypts a block of text with AES
280 @param pt The input plaintext (16 bytes)
281 @param ct The output ciphertext (16 bytes)
282 @param skey The key as scheduled
283 @return CRYPT_OK if successful
284 */
285 #ifdef LTC_CLEAN_STACK
_rijndael_ecb_encrypt(const unsigned char * pt,unsigned char * ct,symmetric_key * skey)286 static int _rijndael_ecb_encrypt(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
287 #else
288 int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
289 #endif
290 {
291 ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
292 int Nr, r;
293
294 LTC_ARGCHK(pt != NULL);
295 LTC_ARGCHK(ct != NULL);
296 LTC_ARGCHK(skey != NULL);
297
298 Nr = skey->rijndael.Nr;
299 rk = skey->rijndael.eK;
300
301 /*
302 * map byte array block to cipher state
303 * and add initial round key:
304 */
305 LOAD32H(s0, pt ); s0 ^= rk[0];
306 LOAD32H(s1, pt + 4); s1 ^= rk[1];
307 LOAD32H(s2, pt + 8); s2 ^= rk[2];
308 LOAD32H(s3, pt + 12); s3 ^= rk[3];
309
310 #ifdef LTC_SMALL_CODE
311
312 for (r = 0; ; r++) {
313 rk += 4;
314 t0 =
315 Te0(byte(s0, 3)) ^
316 Te1(byte(s1, 2)) ^
317 Te2(byte(s2, 1)) ^
318 Te3(byte(s3, 0)) ^
319 rk[0];
320 t1 =
321 Te0(byte(s1, 3)) ^
322 Te1(byte(s2, 2)) ^
323 Te2(byte(s3, 1)) ^
324 Te3(byte(s0, 0)) ^
325 rk[1];
326 t2 =
327 Te0(byte(s2, 3)) ^
328 Te1(byte(s3, 2)) ^
329 Te2(byte(s0, 1)) ^
330 Te3(byte(s1, 0)) ^
331 rk[2];
332 t3 =
333 Te0(byte(s3, 3)) ^
334 Te1(byte(s0, 2)) ^
335 Te2(byte(s1, 1)) ^
336 Te3(byte(s2, 0)) ^
337 rk[3];
338 if (r == Nr-2) {
339 break;
340 }
341 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
342 }
343 rk += 4;
344
345 #else
346
347 /*
348 * Nr - 1 full rounds:
349 */
350 r = Nr >> 1;
351 for (;;) {
352 t0 =
353 Te0(byte(s0, 3)) ^
354 Te1(byte(s1, 2)) ^
355 Te2(byte(s2, 1)) ^
356 Te3(byte(s3, 0)) ^
357 rk[4];
358 t1 =
359 Te0(byte(s1, 3)) ^
360 Te1(byte(s2, 2)) ^
361 Te2(byte(s3, 1)) ^
362 Te3(byte(s0, 0)) ^
363 rk[5];
364 t2 =
365 Te0(byte(s2, 3)) ^
366 Te1(byte(s3, 2)) ^
367 Te2(byte(s0, 1)) ^
368 Te3(byte(s1, 0)) ^
369 rk[6];
370 t3 =
371 Te0(byte(s3, 3)) ^
372 Te1(byte(s0, 2)) ^
373 Te2(byte(s1, 1)) ^
374 Te3(byte(s2, 0)) ^
375 rk[7];
376
377 rk += 8;
378 if (--r == 0) {
379 break;
380 }
381
382 s0 =
383 Te0(byte(t0, 3)) ^
384 Te1(byte(t1, 2)) ^
385 Te2(byte(t2, 1)) ^
386 Te3(byte(t3, 0)) ^
387 rk[0];
388 s1 =
389 Te0(byte(t1, 3)) ^
390 Te1(byte(t2, 2)) ^
391 Te2(byte(t3, 1)) ^
392 Te3(byte(t0, 0)) ^
393 rk[1];
394 s2 =
395 Te0(byte(t2, 3)) ^
396 Te1(byte(t3, 2)) ^
397 Te2(byte(t0, 1)) ^
398 Te3(byte(t1, 0)) ^
399 rk[2];
400 s3 =
401 Te0(byte(t3, 3)) ^
402 Te1(byte(t0, 2)) ^
403 Te2(byte(t1, 1)) ^
404 Te3(byte(t2, 0)) ^
405 rk[3];
406 }
407
408 #endif
409
410 /*
411 * apply last round and
412 * map cipher state to byte array block:
413 */
414 s0 =
415 (Te4_3[byte(t0, 3)]) ^
416 (Te4_2[byte(t1, 2)]) ^
417 (Te4_1[byte(t2, 1)]) ^
418 (Te4_0[byte(t3, 0)]) ^
419 rk[0];
420 STORE32H(s0, ct);
421 s1 =
422 (Te4_3[byte(t1, 3)]) ^
423 (Te4_2[byte(t2, 2)]) ^
424 (Te4_1[byte(t3, 1)]) ^
425 (Te4_0[byte(t0, 0)]) ^
426 rk[1];
427 STORE32H(s1, ct+4);
428 s2 =
429 (Te4_3[byte(t2, 3)]) ^
430 (Te4_2[byte(t3, 2)]) ^
431 (Te4_1[byte(t0, 1)]) ^
432 (Te4_0[byte(t1, 0)]) ^
433 rk[2];
434 STORE32H(s2, ct+8);
435 s3 =
436 (Te4_3[byte(t3, 3)]) ^
437 (Te4_2[byte(t0, 2)]) ^
438 (Te4_1[byte(t1, 1)]) ^
439 (Te4_0[byte(t2, 0)]) ^
440 rk[3];
441 STORE32H(s3, ct+12);
442
443 return CRYPT_OK;
444 }
445
446 #ifdef LTC_CLEAN_STACK
ECB_ENC(const unsigned char * pt,unsigned char * ct,symmetric_key * skey)447 int ECB_ENC(const unsigned char *pt, unsigned char *ct, symmetric_key *skey)
448 {
449 int err = _rijndael_ecb_encrypt(pt, ct, skey);
450 burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
451 return err;
452 }
453 #endif
454
455 #ifndef ENCRYPT_ONLY
456
457 /**
458 Decrypts a block of text with AES
459 @param ct The input ciphertext (16 bytes)
460 @param pt The output plaintext (16 bytes)
461 @param skey The key as scheduled
462 @return CRYPT_OK if successful
463 */
464 #ifdef LTC_CLEAN_STACK
_rijndael_ecb_decrypt(const unsigned char * ct,unsigned char * pt,symmetric_key * skey)465 static int _rijndael_ecb_decrypt(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
466 #else
467 int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
468 #endif
469 {
470 ulong32 s0, s1, s2, s3, t0, t1, t2, t3, *rk;
471 int Nr, r;
472
473 LTC_ARGCHK(pt != NULL);
474 LTC_ARGCHK(ct != NULL);
475 LTC_ARGCHK(skey != NULL);
476
477 Nr = skey->rijndael.Nr;
478 rk = skey->rijndael.dK;
479
480 /*
481 * map byte array block to cipher state
482 * and add initial round key:
483 */
484 LOAD32H(s0, ct ); s0 ^= rk[0];
485 LOAD32H(s1, ct + 4); s1 ^= rk[1];
486 LOAD32H(s2, ct + 8); s2 ^= rk[2];
487 LOAD32H(s3, ct + 12); s3 ^= rk[3];
488
489 #ifdef LTC_SMALL_CODE
490 for (r = 0; ; r++) {
491 rk += 4;
492 t0 =
493 Td0(byte(s0, 3)) ^
494 Td1(byte(s3, 2)) ^
495 Td2(byte(s2, 1)) ^
496 Td3(byte(s1, 0)) ^
497 rk[0];
498 t1 =
499 Td0(byte(s1, 3)) ^
500 Td1(byte(s0, 2)) ^
501 Td2(byte(s3, 1)) ^
502 Td3(byte(s2, 0)) ^
503 rk[1];
504 t2 =
505 Td0(byte(s2, 3)) ^
506 Td1(byte(s1, 2)) ^
507 Td2(byte(s0, 1)) ^
508 Td3(byte(s3, 0)) ^
509 rk[2];
510 t3 =
511 Td0(byte(s3, 3)) ^
512 Td1(byte(s2, 2)) ^
513 Td2(byte(s1, 1)) ^
514 Td3(byte(s0, 0)) ^
515 rk[3];
516 if (r == Nr-2) {
517 break;
518 }
519 s0 = t0; s1 = t1; s2 = t2; s3 = t3;
520 }
521 rk += 4;
522
523 #else
524
525 /*
526 * Nr - 1 full rounds:
527 */
528 r = Nr >> 1;
529 for (;;) {
530
531 t0 =
532 Td0(byte(s0, 3)) ^
533 Td1(byte(s3, 2)) ^
534 Td2(byte(s2, 1)) ^
535 Td3(byte(s1, 0)) ^
536 rk[4];
537 t1 =
538 Td0(byte(s1, 3)) ^
539 Td1(byte(s0, 2)) ^
540 Td2(byte(s3, 1)) ^
541 Td3(byte(s2, 0)) ^
542 rk[5];
543 t2 =
544 Td0(byte(s2, 3)) ^
545 Td1(byte(s1, 2)) ^
546 Td2(byte(s0, 1)) ^
547 Td3(byte(s3, 0)) ^
548 rk[6];
549 t3 =
550 Td0(byte(s3, 3)) ^
551 Td1(byte(s2, 2)) ^
552 Td2(byte(s1, 1)) ^
553 Td3(byte(s0, 0)) ^
554 rk[7];
555
556 rk += 8;
557 if (--r == 0) {
558 break;
559 }
560
561
562 s0 =
563 Td0(byte(t0, 3)) ^
564 Td1(byte(t3, 2)) ^
565 Td2(byte(t2, 1)) ^
566 Td3(byte(t1, 0)) ^
567 rk[0];
568 s1 =
569 Td0(byte(t1, 3)) ^
570 Td1(byte(t0, 2)) ^
571 Td2(byte(t3, 1)) ^
572 Td3(byte(t2, 0)) ^
573 rk[1];
574 s2 =
575 Td0(byte(t2, 3)) ^
576 Td1(byte(t1, 2)) ^
577 Td2(byte(t0, 1)) ^
578 Td3(byte(t3, 0)) ^
579 rk[2];
580 s3 =
581 Td0(byte(t3, 3)) ^
582 Td1(byte(t2, 2)) ^
583 Td2(byte(t1, 1)) ^
584 Td3(byte(t0, 0)) ^
585 rk[3];
586 }
587 #endif
588
589 /*
590 * apply last round and
591 * map cipher state to byte array block:
592 */
593 s0 =
594 (Td4[byte(t0, 3)] & 0xff000000) ^
595 (Td4[byte(t3, 2)] & 0x00ff0000) ^
596 (Td4[byte(t2, 1)] & 0x0000ff00) ^
597 (Td4[byte(t1, 0)] & 0x000000ff) ^
598 rk[0];
599 STORE32H(s0, pt);
600 s1 =
601 (Td4[byte(t1, 3)] & 0xff000000) ^
602 (Td4[byte(t0, 2)] & 0x00ff0000) ^
603 (Td4[byte(t3, 1)] & 0x0000ff00) ^
604 (Td4[byte(t2, 0)] & 0x000000ff) ^
605 rk[1];
606 STORE32H(s1, pt+4);
607 s2 =
608 (Td4[byte(t2, 3)] & 0xff000000) ^
609 (Td4[byte(t1, 2)] & 0x00ff0000) ^
610 (Td4[byte(t0, 1)] & 0x0000ff00) ^
611 (Td4[byte(t3, 0)] & 0x000000ff) ^
612 rk[2];
613 STORE32H(s2, pt+8);
614 s3 =
615 (Td4[byte(t3, 3)] & 0xff000000) ^
616 (Td4[byte(t2, 2)] & 0x00ff0000) ^
617 (Td4[byte(t1, 1)] & 0x0000ff00) ^
618 (Td4[byte(t0, 0)] & 0x000000ff) ^
619 rk[3];
620 STORE32H(s3, pt+12);
621
622 return CRYPT_OK;
623 }
624
625
626 #ifdef LTC_CLEAN_STACK
ECB_DEC(const unsigned char * ct,unsigned char * pt,symmetric_key * skey)627 int ECB_DEC(const unsigned char *ct, unsigned char *pt, symmetric_key *skey)
628 {
629 int err = _rijndael_ecb_decrypt(ct, pt, skey);
630 burn_stack(sizeof(unsigned long)*8 + sizeof(unsigned long*) + sizeof(int)*2);
631 return err;
632 }
633 #endif
634
635 /**
636 Performs a self-test of the AES block cipher
637 @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
638 */
ECB_TEST(void)639 int ECB_TEST(void)
640 {
641 #ifndef LTC_TEST
642 return CRYPT_NOP;
643 #else
644 int err;
645 static const struct {
646 int keylen;
647 unsigned char key[32], pt[16], ct[16];
648 } tests[] = {
649 { 16,
650 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
651 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f },
652 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
653 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
654 { 0x69, 0xc4, 0xe0, 0xd8, 0x6a, 0x7b, 0x04, 0x30,
655 0xd8, 0xcd, 0xb7, 0x80, 0x70, 0xb4, 0xc5, 0x5a }
656 }, {
657 24,
658 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
659 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
660 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
661 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
662 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
663 { 0xdd, 0xa9, 0x7c, 0xa4, 0x86, 0x4c, 0xdf, 0xe0,
664 0x6e, 0xaf, 0x70, 0xa0, 0xec, 0x0d, 0x71, 0x91 }
665 }, {
666 32,
667 { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
668 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
669 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
670 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f },
671 { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
672 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff },
673 { 0x8e, 0xa2, 0xb7, 0xca, 0x51, 0x67, 0x45, 0xbf,
674 0xea, 0xfc, 0x49, 0x90, 0x4b, 0x49, 0x60, 0x89 }
675 }
676 };
677
678 symmetric_key key;
679 unsigned char tmp[2][16];
680 int i, y;
681
682 for (i = 0; i < (int)(sizeof(tests)/sizeof(tests[0])); i++) {
683 zeromem(&key, sizeof(key));
684 if ((err = rijndael_setup(tests[i].key, tests[i].keylen, 0, &key)) != CRYPT_OK) {
685 return err;
686 }
687
688 rijndael_ecb_encrypt(tests[i].pt, tmp[0], &key);
689 rijndael_ecb_decrypt(tmp[0], tmp[1], &key);
690 if (XMEMCMP(tmp[0], tests[i].ct, 16) || XMEMCMP(tmp[1], tests[i].pt, 16)) {
691 #if 0
692 printf("\n\nTest %d failed\n", i);
693 if (XMEMCMP(tmp[0], tests[i].ct, 16)) {
694 printf("CT: ");
695 for (i = 0; i < 16; i++) {
696 printf("%02x ", tmp[0][i]);
697 }
698 printf("\n");
699 } else {
700 printf("PT: ");
701 for (i = 0; i < 16; i++) {
702 printf("%02x ", tmp[1][i]);
703 }
704 printf("\n");
705 }
706 #endif
707 return CRYPT_FAIL_TESTVECTOR;
708 }
709
710 /* now see if we can encrypt all zero bytes 1000 times, decrypt and come back where we started */
711 for (y = 0; y < 16; y++) tmp[0][y] = 0;
712 for (y = 0; y < 1000; y++) rijndael_ecb_encrypt(tmp[0], tmp[0], &key);
713 for (y = 0; y < 1000; y++) rijndael_ecb_decrypt(tmp[0], tmp[0], &key);
714 for (y = 0; y < 16; y++) if (tmp[0][y] != 0) return CRYPT_FAIL_TESTVECTOR;
715 }
716 return CRYPT_OK;
717 #endif
718 }
719
720 #endif /* ENCRYPT_ONLY */
721
722
723 /** Terminate the context
724 @param skey The scheduled key
725 */
ECB_DONE(symmetric_key * skey)726 void ECB_DONE(symmetric_key *skey)
727 {
728 LTC_UNUSED_PARAM(skey);
729 }
730
731
732 /**
733 Gets suitable key size
734 @param keysize [in/out] The length of the recommended key (in bytes). This function will store the suitable size back in this variable.
735 @return CRYPT_OK if the input key size is acceptable.
736 */
ECB_KS(int * keysize)737 int ECB_KS(int *keysize)
738 {
739 LTC_ARGCHK(keysize != NULL);
740
741 if (*keysize < 16)
742 return CRYPT_INVALID_KEYSIZE;
743 if (*keysize < 24) {
744 *keysize = 16;
745 return CRYPT_OK;
746 } else if (*keysize < 32) {
747 *keysize = 24;
748 return CRYPT_OK;
749 } else {
750 *keysize = 32;
751 return CRYPT_OK;
752 }
753 }
754
755 #endif
756
757
758 /* $Source$ */
759 /* $Revision$ */
760 /* $Date$ */
761