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