For FIPS algorithm test utilities use our own version of strcasecmp and
[openssl.git] / fips / aes / fips_aesavs.c
1 /* ====================================================================
2  * Copyright (c) 2004 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer. 
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  *
48  */
49 /*---------------------------------------------
50   NIST AES Algorithm Validation Suite
51   Test Program
52
53   Donated to OpenSSL by:
54   V-ONE Corporation
55   20250 Century Blvd, Suite 300
56   Germantown, MD 20874
57   U.S.A.
58   ----------------------------------------------*/
59
60 #define OPENSSL_FIPSAPI
61
62 #include <stdio.h>
63 #include <stdlib.h>
64 #include <string.h>
65 #include <errno.h>
66 #include <assert.h>
67 #include <ctype.h>
68 #include <openssl/aes.h>
69 #include <openssl/evp.h>
70 #include <openssl/bn.h>
71
72 #include <openssl/err.h>
73 #include "e_os.h"
74
75 #ifndef OPENSSL_FIPS
76
77 int main(int argc, char *argv[])
78 {
79     printf("No FIPS AES support\n");
80     return(0);
81 }
82
83 #else
84
85 #include <openssl/fips.h>
86 #include "fips_utl.h"
87
88 #define AES_BLOCK_SIZE 16
89
90 #define VERBOSE 0
91
92 /*-----------------------------------------------*/
93
94 static int AESTest(EVP_CIPHER_CTX *ctx,
95             char *amode, int akeysz, unsigned char *aKey, 
96             unsigned char *iVec, 
97             int dir,  /* 0 = decrypt, 1 = encrypt */
98             unsigned char *plaintext, unsigned char *ciphertext, int len)
99     {
100     const EVP_CIPHER *cipher = NULL;
101
102     if (strcasecmp(amode, "CBC") == 0)
103         {
104         switch (akeysz)
105                 {
106                 case 128:
107                 cipher = EVP_aes_128_cbc();
108                 break;
109
110                 case 192:
111                 cipher = EVP_aes_192_cbc();
112                 break;
113
114                 case 256:
115                 cipher = EVP_aes_256_cbc();
116                 break;
117                 }
118
119         }
120     else if (strcasecmp(amode, "ECB") == 0)
121         {
122         switch (akeysz)
123                 {
124                 case 128:
125                 cipher = EVP_aes_128_ecb();
126                 break;
127
128                 case 192:
129                 cipher = EVP_aes_192_ecb();
130                 break;
131
132                 case 256:
133                 cipher = EVP_aes_256_ecb();
134                 break;
135                 }
136         }
137     else if (strcasecmp(amode, "CFB128") == 0)
138         {
139         switch (akeysz)
140                 {
141                 case 128:
142                 cipher = EVP_aes_128_cfb128();
143                 break;
144
145                 case 192:
146                 cipher = EVP_aes_192_cfb128();
147                 break;
148
149                 case 256:
150                 cipher = EVP_aes_256_cfb128();
151                 break;
152                 }
153
154         }
155     else if (fips_strncasecmp(amode, "OFB", 3) == 0)
156         {
157         switch (akeysz)
158                 {
159                 case 128:
160                 cipher = EVP_aes_128_ofb();
161                 break;
162
163                 case 192:
164                 cipher = EVP_aes_192_ofb();
165                 break;
166
167                 case 256:
168                 cipher = EVP_aes_256_ofb();
169                 break;
170                 }
171         }
172     else if(!strcasecmp(amode,"CFB1"))
173         {
174         switch (akeysz)
175                 {
176                 case 128:
177                 cipher = EVP_aes_128_cfb1();
178                 break;
179
180                 case 192:
181                 cipher = EVP_aes_192_cfb1();
182                 break;
183
184                 case 256:
185                 cipher = EVP_aes_256_cfb1();
186                 break;
187                 }
188         }
189     else if(!strcasecmp(amode,"CFB8"))
190         {
191         switch (akeysz)
192                 {
193                 case 128:
194                 cipher = EVP_aes_128_cfb8();
195                 break;
196
197                 case 192:
198                 cipher = EVP_aes_192_cfb8();
199                 break;
200
201                 case 256:
202                 cipher = EVP_aes_256_cfb8();
203                 break;
204                 }
205         }
206     else
207         {
208         printf("Unknown mode: %s\n", amode);
209         return 0;
210         }
211     if (!cipher)
212         {
213         printf("Invalid key size: %d\n", akeysz);
214         return 0; 
215         }
216     if (FIPS_cipherinit(ctx, cipher, aKey, iVec, dir) <= 0)
217         return 0;
218     if(!strcasecmp(amode,"CFB1"))
219         M_EVP_CIPHER_CTX_set_flags(ctx, EVP_CIPH_FLAG_LENGTH_BITS);
220     if (dir)
221                 FIPS_cipher(ctx, ciphertext, plaintext, len);
222         else
223                 FIPS_cipher(ctx, plaintext, ciphertext, len);
224     return 1;
225     }
226
227 /*-----------------------------------------------*/
228 char *t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"};
229 char *t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB128"};
230 enum Mode {CBC, ECB, OFB, CFB1, CFB8, CFB128};
231 enum XCrypt {XDECRYPT, XENCRYPT};
232
233 /*=============================*/
234 /*  Monte Carlo Tests          */
235 /*-----------------------------*/
236
237 /*#define gb(a,b) (((a)[(b)/8] >> ((b)%8))&1)*/
238 /*#define sb(a,b,v) ((a)[(b)/8]=((a)[(b)/8]&~(1 << ((b)%8)))|(!!(v) << ((b)%8)))*/
239
240 #define gb(a,b) (((a)[(b)/8] >> (7-(b)%8))&1)
241 #define sb(a,b,v) ((a)[(b)/8]=((a)[(b)/8]&~(1 << (7-(b)%8)))|(!!(v) << (7-(b)%8)))
242
243 static int do_mct(char *amode, 
244            int akeysz, unsigned char *aKey,unsigned char *iVec,
245            int dir, unsigned char *text, int len,
246            FILE *rfp)
247     {
248     int ret = 0;
249     unsigned char key[101][32];
250     unsigned char iv[101][AES_BLOCK_SIZE];
251     unsigned char ptext[1001][32];
252     unsigned char ctext[1001][32];
253     unsigned char ciphertext[64+4];
254     int i, j, n, n1, n2;
255     int imode = 0, nkeysz = akeysz/8;
256     EVP_CIPHER_CTX ctx;
257     FIPS_cipher_ctx_init(&ctx);
258
259     if (len > 32)
260         {
261         printf("\n>>>> Length exceeds 32 for %s %d <<<<\n\n", 
262                amode, akeysz);
263         return -1;
264         }
265     for (imode = 0; imode < 6; ++imode)
266         if (strcmp(amode, t_mode[imode]) == 0)
267             break;
268     if (imode == 6)
269         { 
270         printf("Unrecognized mode: %s\n", amode);
271         return -1;
272         }
273
274     memcpy(key[0], aKey, nkeysz);
275     if (iVec)
276         memcpy(iv[0], iVec, AES_BLOCK_SIZE);
277     if (dir == XENCRYPT)
278         memcpy(ptext[0], text, len);
279     else
280         memcpy(ctext[0], text, len);
281     for (i = 0; i < 100; ++i)
282         {
283         /* printf("Iteration %d\n", i); */
284         if (i > 0)
285             {
286             fprintf(rfp,"COUNT = %d\n",i);
287             OutputValue("KEY",key[i],nkeysz,rfp,0);
288             if (imode != ECB)  /* ECB */
289                 OutputValue("IV",iv[i],AES_BLOCK_SIZE,rfp,0);
290             /* Output Ciphertext | Plaintext */
291             OutputValue(t_tag[dir^1],dir ? ptext[0] : ctext[0],len,rfp,
292                         imode == CFB1);
293             }
294         for (j = 0; j < 1000; ++j)
295             {
296             switch (imode)
297                 {
298             case ECB:
299                 if (j == 0)
300                     { /* set up encryption */
301                     ret = AESTest(&ctx, amode, akeysz, key[i], NULL, 
302                                   dir,  /* 0 = decrypt, 1 = encrypt */
303                                   ptext[j], ctext[j], len);
304                     if (dir == XENCRYPT)
305                         memcpy(ptext[j+1], ctext[j], len);
306                     else
307                         memcpy(ctext[j+1], ptext[j], len);
308                     }
309                 else
310                     {
311                     if (dir == XENCRYPT)
312                         {
313                         FIPS_cipher(&ctx, ctext[j], ptext[j], len);
314                         memcpy(ptext[j+1], ctext[j], len);
315                         }
316                     else
317                         {
318                         FIPS_cipher(&ctx, ptext[j], ctext[j], len);
319                         memcpy(ctext[j+1], ptext[j], len);
320                         }
321                     }
322                 break;
323
324             case CBC:
325             case OFB:  
326             case CFB128:
327                 if (j == 0)
328                     {
329                     ret = AESTest(&ctx, amode, akeysz, key[i], iv[i], 
330                                   dir,  /* 0 = decrypt, 1 = encrypt */
331                                   ptext[j], ctext[j], len);
332                     if (dir == XENCRYPT)
333                         memcpy(ptext[j+1], iv[i], len);
334                     else
335                         memcpy(ctext[j+1], iv[i], len);
336                     }
337                 else
338                     {
339                     if (dir == XENCRYPT)
340                         {
341                         FIPS_cipher(&ctx, ctext[j], ptext[j], len);
342                         memcpy(ptext[j+1], ctext[j-1], len);
343                         }
344                     else
345                         {
346                         FIPS_cipher(&ctx, ptext[j], ctext[j], len);
347                         memcpy(ctext[j+1], ptext[j-1], len);
348                         }
349                     }
350                 break;
351
352             case CFB8:
353                 if (j == 0)
354                     {
355                     ret = AESTest(&ctx, amode, akeysz, key[i], iv[i], 
356                                   dir,  /* 0 = decrypt, 1 = encrypt */
357                                   ptext[j], ctext[j], len);
358                     }
359                 else
360                     {
361                     if (dir == XENCRYPT)
362                         FIPS_cipher(&ctx, ctext[j], ptext[j], len);
363                     else
364                         FIPS_cipher(&ctx, ptext[j], ctext[j], len);
365                     }
366                 if (dir == XENCRYPT)
367                     {
368                     if (j < 16)
369                         memcpy(ptext[j+1], &iv[i][j], len);
370                     else
371                         memcpy(ptext[j+1], ctext[j-16], len);
372                     }
373                 else
374                     {
375                     if (j < 16)
376                         memcpy(ctext[j+1], &iv[i][j], len);
377                     else
378                         memcpy(ctext[j+1], ptext[j-16], len);
379                     }
380                 break;
381
382             case CFB1:
383                 if(j == 0)
384                     {
385 #if 0
386                     /* compensate for wrong endianness of input file */
387                     if(i == 0)
388                         ptext[0][0]<<=7;
389 #endif
390                     ret = AESTest(&ctx,amode,akeysz,key[i],iv[i],dir,
391                                 ptext[j], ctext[j], len);
392                     }
393                 else
394                     {
395                     if (dir == XENCRYPT)
396                         FIPS_cipher(&ctx, ctext[j], ptext[j], len);
397                     else
398                         FIPS_cipher(&ctx, ptext[j], ctext[j], len);
399
400                     }
401                 if(dir == XENCRYPT)
402                     {
403                     if(j < 128)
404                         sb(ptext[j+1],0,gb(iv[i],j));
405                     else
406                         sb(ptext[j+1],0,gb(ctext[j-128],0));
407                     }
408                 else
409                     {
410                     if(j < 128)
411                         sb(ctext[j+1],0,gb(iv[i],j));
412                     else
413                         sb(ctext[j+1],0,gb(ptext[j-128],0));
414                     }
415                 break;
416                 }
417             }
418         --j; /* reset to last of range */
419         /* Output Ciphertext | Plaintext */
420         OutputValue(t_tag[dir],dir ? ctext[j] : ptext[j],len,rfp,
421                     imode == CFB1);
422         fprintf(rfp, "\n");  /* add separator */
423
424         /* Compute next KEY */
425         if (dir == XENCRYPT)
426             {
427             if (imode == CFB8)
428                 { /* ct = CT[j-15] || CT[j-14] || ... || CT[j] */
429                 for (n1 = 0, n2 = nkeysz-1; n1 < nkeysz; ++n1, --n2)
430                     ciphertext[n1] = ctext[j-n2][0];
431                 }
432             else if(imode == CFB1)
433                 {
434                 for(n1=0,n2=akeysz-1 ; n1 < akeysz ; ++n1,--n2)
435                     sb(ciphertext,n1,gb(ctext[j-n2],0));
436                 }
437             else
438                 switch (akeysz)
439                     {
440                 case 128:
441                     memcpy(ciphertext, ctext[j], 16);
442                     break;
443                 case 192:
444                     memcpy(ciphertext, ctext[j-1]+8, 8);
445                     memcpy(ciphertext+8, ctext[j], 16);
446                     break;
447                 case 256:
448                     memcpy(ciphertext, ctext[j-1], 16);
449                     memcpy(ciphertext+16, ctext[j], 16);
450                     break;
451                     }
452             }
453         else
454             {
455             if (imode == CFB8)
456                 { /* ct = CT[j-15] || CT[j-14] || ... || CT[j] */
457                 for (n1 = 0, n2 = nkeysz-1; n1 < nkeysz; ++n1, --n2)
458                     ciphertext[n1] = ptext[j-n2][0];
459                 }
460             else if(imode == CFB1)
461                 {
462                 for(n1=0,n2=akeysz-1 ; n1 < akeysz ; ++n1,--n2)
463                     sb(ciphertext,n1,gb(ptext[j-n2],0));
464                 }
465             else
466                 switch (akeysz)
467                     {
468                 case 128:
469                     memcpy(ciphertext, ptext[j], 16);
470                     break;
471                 case 192:
472                     memcpy(ciphertext, ptext[j-1]+8, 8);
473                     memcpy(ciphertext+8, ptext[j], 16);
474                     break;
475                 case 256:
476                     memcpy(ciphertext, ptext[j-1], 16);
477                     memcpy(ciphertext+16, ptext[j], 16);
478                     break;
479                     }
480             }
481         /* Compute next key: Key[i+1] = Key[i] xor ct */
482         for (n = 0; n < nkeysz; ++n)
483             key[i+1][n] = key[i][n] ^ ciphertext[n];
484         
485         /* Compute next IV and text */
486         if (dir == XENCRYPT)
487             {
488             switch (imode)
489                 {
490             case ECB:
491                 memcpy(ptext[0], ctext[j], AES_BLOCK_SIZE);
492                 break;
493             case CBC:
494             case OFB:
495             case CFB128:
496                 memcpy(iv[i+1], ctext[j], AES_BLOCK_SIZE);
497                 memcpy(ptext[0], ctext[j-1], AES_BLOCK_SIZE);
498                 break;
499             case CFB8:
500                 /* IV[i+1] = ct */
501                 for (n1 = 0, n2 = 15; n1 < 16; ++n1, --n2)
502                     iv[i+1][n1] = ctext[j-n2][0];
503                 ptext[0][0] = ctext[j-16][0];
504                 break;
505             case CFB1:
506                 for(n1=0,n2=127 ; n1 < 128 ; ++n1,--n2)
507                     sb(iv[i+1],n1,gb(ctext[j-n2],0));
508                 ptext[0][0]=ctext[j-128][0]&0x80;
509                 break;
510                 }
511             }
512         else
513             {
514             switch (imode)
515                 {
516             case ECB:
517                 memcpy(ctext[0], ptext[j], AES_BLOCK_SIZE);
518                 break;
519             case CBC:
520             case OFB:
521             case CFB128:
522                 memcpy(iv[i+1], ptext[j], AES_BLOCK_SIZE);
523                 memcpy(ctext[0], ptext[j-1], AES_BLOCK_SIZE);
524                 break;
525             case CFB8:
526                 for (n1 = 0, n2 = 15; n1 < 16; ++n1, --n2)
527                     iv[i+1][n1] = ptext[j-n2][0];
528                 ctext[0][0] = ptext[j-16][0];
529                 break;
530             case CFB1:
531                 for(n1=0,n2=127 ; n1 < 128 ; ++n1,--n2)
532                     sb(iv[i+1],n1,gb(ptext[j-n2],0));
533                 ctext[0][0]=ptext[j-128][0]&0x80;
534                 break;
535                 }
536             }
537         }
538     
539     return ret;
540     }
541
542 /*================================================*/
543 /*----------------------------
544   # Config info for v-one
545   # AESVS MMT test data for ECB
546   # State : Encrypt and Decrypt
547   # Key Length : 256
548   # Fri Aug 30 04:07:22 PM
549   ----------------------------*/
550
551 static int proc_file(char *rqfile, char *rspfile)
552     {
553     char afn[256], rfn[256];
554     FILE *afp = NULL, *rfp = NULL;
555     char ibuf[2048];
556     char tbuf[2048];
557     int ilen, len, ret = 0;
558     char algo[8] = "";
559     char amode[8] = "";
560     char atest[8] = "";
561     int akeysz = 0;
562     unsigned char iVec[20], aKey[40];
563     int dir = -1, err = 0, step = 0;
564     unsigned char plaintext[2048];
565     unsigned char ciphertext[2048];
566     char *rp;
567     EVP_CIPHER_CTX ctx;
568     FIPS_cipher_ctx_init(&ctx);
569
570     if (!rqfile || !(*rqfile))
571         {
572         printf("No req file\n");
573         return -1;
574         }
575     strcpy(afn, rqfile);
576
577     if ((afp = fopen(afn, "r")) == NULL)
578         {
579         printf("Cannot open file: %s, %s\n", 
580                afn, strerror(errno));
581         return -1;
582         }
583     if (!rspfile)
584         {
585         strcpy(rfn,afn);
586         rp=strstr(rfn,"req/");
587 #ifdef OPENSSL_SYS_WIN32
588         if (!rp)
589             rp=strstr(rfn,"req\\");
590 #endif
591         assert(rp);
592         memcpy(rp,"rsp",3);
593         rp = strstr(rfn, ".req");
594         memcpy(rp, ".rsp", 4);
595         rspfile = rfn;
596         }
597     if ((rfp = fopen(rspfile, "w")) == NULL)
598         {
599         printf("Cannot open file: %s, %s\n", 
600                rfn, strerror(errno));
601         fclose(afp);
602         afp = NULL;
603         return -1;
604         }
605     while (!err && (fgets(ibuf, sizeof(ibuf), afp)) != NULL)
606         {
607         tidy_line(tbuf, ibuf);
608         ilen = strlen(ibuf);
609         /*      printf("step=%d ibuf=%s",step,ibuf); */
610         switch (step)
611             {
612         case 0:  /* read preamble */
613             if (ibuf[0] == '\n')
614                 { /* end of preamble */
615                 if ((*algo == '\0') ||
616                     (*amode == '\0') ||
617                     (akeysz == 0))
618                     {
619                     printf("Missing Algorithm, Mode or KeySize (%s/%s/%d)\n",
620                            algo,amode,akeysz);
621                     err = 1;
622                     }
623                 else
624                     {
625                     fputs(ibuf, rfp);
626                     ++ step;
627                     }
628                 }
629             else if (ibuf[0] != '#')
630                 {
631                 printf("Invalid preamble item: %s\n", ibuf);
632                 err = 1;
633                 }
634             else
635                 { /* process preamble */
636                 char *xp, *pp = ibuf+2;
637                 int n;
638                 if (akeysz)
639                     { /* insert current time & date */
640                     time_t rtim = time(0);
641                     fprintf(rfp, "# %s", ctime(&rtim));
642                     }
643                 else
644                     {
645                     fputs(ibuf, rfp);
646                     if (strncmp(pp, "AESVS ", 6) == 0)
647                         {
648                         strcpy(algo, "AES");
649                         /* get test type */
650                         pp += 6;
651                         xp = strchr(pp, ' ');
652                         n = xp-pp;
653                         strncpy(atest, pp, n);
654                         atest[n] = '\0';
655                         /* get mode */
656                         xp = strrchr(pp, ' '); /* get mode" */
657                         n = strlen(xp+1)-1;
658                         strncpy(amode, xp+1, n);
659                         amode[n] = '\0';
660                         /* amode[3] = '\0'; */
661                         if (VERBOSE)
662                                 printf("Test = %s, Mode = %s\n", atest, amode);
663                         }
664                     else if (fips_strncasecmp(pp, "Key Length : ", 13) == 0)
665                         {
666                         akeysz = atoi(pp+13);
667                         if (VERBOSE)
668                                 printf("Key size = %d\n", akeysz);
669                         }
670                     }
671                 }
672             break;
673
674         case 1:  /* [ENCRYPT] | [DECRYPT] */
675             if (ibuf[0] == '[')
676                 {
677                 fputs(ibuf, rfp);
678                 ++step;
679                 if (fips_strncasecmp(ibuf, "[ENCRYPT]", 9) == 0)
680                     dir = 1;
681                 else if (fips_strncasecmp(ibuf, "[DECRYPT]", 9) == 0)
682                     dir = 0;
683                 else
684                     {
685                     printf("Invalid keyword: %s\n", ibuf);
686                     err = 1;
687                     }
688                 break;
689                 }
690             else if (dir == -1)
691                 {
692                 err = 1;
693                 printf("Missing ENCRYPT/DECRYPT keyword\n");
694                 break;
695                 }
696             else 
697                 step = 2;
698
699         case 2: /* KEY = xxxx */
700             fputs(ibuf, rfp);
701             if(*ibuf == '\n')
702                 break;
703             if(!fips_strncasecmp(ibuf,"COUNT = ",8))
704                 break;
705
706             if (fips_strncasecmp(ibuf, "KEY = ", 6) != 0)
707                 {
708                 printf("Missing KEY\n");
709                 err = 1;
710                 }
711             else
712                 {
713                 len = hex2bin((char*)ibuf+6, aKey);
714                 if (len < 0)
715                     {
716                     printf("Invalid KEY\n");
717                     err =1;
718                     break;
719                     }
720                 PrintValue("KEY", aKey, len);
721                 if (strcmp(amode, "ECB") == 0)
722                     {
723                     memset(iVec, 0, sizeof(iVec));
724                     step = (dir)? 4: 5;  /* no ivec for ECB */
725                     }
726                 else
727                     ++step;
728                 }
729             break;
730
731         case 3: /* IV = xxxx */
732             fputs(ibuf, rfp);
733             if (fips_strncasecmp(ibuf, "IV = ", 5) != 0)
734                 {
735                 printf("Missing IV\n");
736                 err = 1;
737                 }
738             else
739                 {
740                 len = hex2bin((char*)ibuf+5, iVec);
741                 if (len < 0)
742                     {
743                     printf("Invalid IV\n");
744                     err =1;
745                     break;
746                     }
747                 PrintValue("IV", iVec, len);
748                 step = (dir)? 4: 5;
749                 }
750             break;
751
752         case 4: /* PLAINTEXT = xxxx */
753             fputs(ibuf, rfp);
754             if (fips_strncasecmp(ibuf, "PLAINTEXT = ", 12) != 0)
755                 {
756                 printf("Missing PLAINTEXT\n");
757                 err = 1;
758                 }
759             else
760                 {
761                 int nn = strlen(ibuf+12);
762                 if(!strcmp(amode,"CFB1"))
763                     len=bint2bin(ibuf+12,nn-1,plaintext);
764                 else
765                     len=hex2bin(ibuf+12, plaintext);
766                 if (len < 0)
767                     {
768                     printf("Invalid PLAINTEXT: %s", ibuf+12);
769                     err =1;
770                     break;
771                     }
772                 if (len >= (int)sizeof(plaintext))
773                     {
774                     printf("Buffer overflow\n");
775                     }
776                 PrintValue("PLAINTEXT", (unsigned char*)plaintext, len);
777                 if (strcmp(atest, "MCT") == 0)  /* Monte Carlo Test */
778                     {
779                     if(do_mct(amode, akeysz, aKey, iVec, 
780                               dir, (unsigned char*)plaintext, len, 
781                               rfp) < 0)
782                         EXIT(1);
783                     }
784                 else
785                     {
786                     ret = AESTest(&ctx, amode, akeysz, aKey, iVec, 
787                                   dir,  /* 0 = decrypt, 1 = encrypt */
788                                   plaintext, ciphertext, len);
789                     OutputValue("CIPHERTEXT",ciphertext,len,rfp,
790                                 !strcmp(amode,"CFB1"));
791                     }
792                 step = 6;
793                 }
794             break;
795
796         case 5: /* CIPHERTEXT = xxxx */
797             fputs(ibuf, rfp);
798             if (fips_strncasecmp(ibuf, "CIPHERTEXT = ", 13) != 0)
799                 {
800                 printf("Missing KEY\n");
801                 err = 1;
802                 }
803             else
804                 {
805                 if(!strcmp(amode,"CFB1"))
806                     len=bint2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
807                 else
808                     len = hex2bin(ibuf+13,ciphertext);
809                 if (len < 0)
810                     {
811                     printf("Invalid CIPHERTEXT\n");
812                     err =1;
813                     break;
814                     }
815
816                 PrintValue("CIPHERTEXT", ciphertext, len);
817                 if (strcmp(atest, "MCT") == 0)  /* Monte Carlo Test */
818                     {
819                     do_mct(amode, akeysz, aKey, iVec, 
820                            dir, ciphertext, len, rfp);
821                     }
822                 else
823                     {
824                     ret = AESTest(&ctx, amode, akeysz, aKey, iVec, 
825                                   dir,  /* 0 = decrypt, 1 = encrypt */
826                                   plaintext, ciphertext, len);
827                     OutputValue("PLAINTEXT",(unsigned char *)plaintext,len,rfp,
828                                 !strcmp(amode,"CFB1"));
829                     }
830                 step = 6;
831                 }
832             break;
833
834         case 6:
835             if (ibuf[0] != '\n')
836                 {
837                 err = 1;
838                 printf("Missing terminator\n");
839                 }
840             else if (strcmp(atest, "MCT") != 0)
841                 { /* MCT already added terminating nl */
842                 fputs(ibuf, rfp);
843                 }
844             step = 1;
845             break;
846             }
847         }
848     if (rfp)
849         fclose(rfp);
850     if (afp)
851         fclose(afp);
852     return err;
853     }
854
855 /*--------------------------------------------------
856   Processes either a single file or 
857   a set of files whose names are passed in a file.
858   A single file is specified as:
859     aes_test -f xxx.req
860   A set of files is specified as:
861     aes_test -d xxxxx.xxx
862   The default is: -d req.txt
863 --------------------------------------------------*/
864 int main(int argc, char **argv)
865     {
866     char *rqlist = "req.txt", *rspfile = NULL;
867     FILE *fp = NULL;
868     char fn[250] = "", rfn[256] = "";
869     int f_opt = 0, d_opt = 1;
870     fips_algtest_init();
871
872     if (argc > 1)
873         {
874         if (strcasecmp(argv[1], "-d") == 0)
875             {
876             d_opt = 1;
877             }
878         else if (strcasecmp(argv[1], "-f") == 0)
879             {
880             f_opt = 1;
881             d_opt = 0;
882             }
883         else
884             {
885             printf("Invalid parameter: %s\n", argv[1]);
886             return 0;
887             }
888         if (argc < 3)
889             {
890             printf("Missing parameter\n");
891             return 0;
892             }
893         if (d_opt)
894             rqlist = argv[2];
895         else
896             {
897             strcpy(fn, argv[2]);
898             rspfile = argv[3];
899             }
900         }
901     if (d_opt)
902         { /* list of files (directory) */
903         if (!(fp = fopen(rqlist, "r")))
904             {
905             printf("Cannot open req list file\n");
906             return -1;
907             }
908         while (fgets(fn, sizeof(fn), fp))
909             {
910             strtok(fn, "\r\n");
911             strcpy(rfn, fn);
912             if (VERBOSE)
913                 printf("Processing: %s\n", rfn);
914             if (proc_file(rfn, rspfile))
915                 {
916                 printf(">>> Processing failed for: %s <<<\n", rfn);
917                 EXIT(1);
918                 }
919             }
920         fclose(fp);
921         }
922     else /* single file */
923         {
924         if (VERBOSE)
925             printf("Processing: %s\n", fn);
926         if (proc_file(fn, rspfile))
927             {
928             printf(">>> Processing failed for: %s <<<\n", fn);
929             }
930         }
931     EXIT(0);
932     return 0;
933     }
934
935 #endif