Changes to make AES algorithm test work via EVP.
[oweals/openssl.git] / fips-1.0 / des / fips_desmovs.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 DES Modes of Operation Validation System
51   Test Program
52
53   Based on the AES Validation Suite, which was:
54   Donated to OpenSSL by:
55   V-ONE Corporation
56   20250 Century Blvd, Suite 300
57   Germantown, MD 20874
58   U.S.A.
59   ----------------------------------------------*/
60
61 #include <stdio.h>
62 #include <stdlib.h>
63 #include <string.h>
64 #include <errno.h>
65 #include <assert.h>
66 #include <ctype.h>
67
68 #include <openssl/des.h>
69 #include <openssl/evp.h>
70 #include <openssl/fips.h>
71 #include <openssl/err.h>
72 #include "e_os.h"
73
74 #ifndef OPENSSL_FIPS
75
76 int main(int argc, char *argv[])
77 {
78     printf("No FIPS DES support\n");
79     return(0);
80 }
81
82 #else
83
84 #include "fips_utl.h"
85
86 #define DES_BLOCK_SIZE 8
87
88 #define VERBOSE 0
89
90 typedef struct
91         {
92         DES_key_schedule ks1, ks2, ks3;
93         unsigned char tiv[DES_BLOCK_SIZE];
94         int dir, cmode, cbits, num, akeysz;
95         } DES_CTX;
96
97 /*-----------------------------------------------*/
98
99 int DES_Cipher(DES_CTX *ctx,
100                 unsigned char *out,
101                 unsigned char *in,
102                 int inl)
103         {
104
105         unsigned long len = inl;
106
107         DES_cblock *iv = (DES_cblock *)ctx->tiv;
108
109         switch(ctx->cmode)
110                 {
111                 case EVP_CIPH_ECB_MODE:
112                 while (len > 0)
113                         {
114                         if (ctx->akeysz == 64)
115                                 DES_ecb_encrypt((DES_cblock *)in,
116                                                 (DES_cblock *)out,
117                                                         &ctx->ks1, ctx->dir);
118                         else
119                                 DES_ecb3_encrypt((const_DES_cblock *)in,
120                                         (DES_cblock *)out,
121                                         &ctx->ks1,
122                                         &ctx->ks2,
123                                         &ctx->ks3,
124                                         ctx->dir);
125                         in += DES_BLOCK_SIZE;
126                         out += DES_BLOCK_SIZE;
127                         len -= DES_BLOCK_SIZE;
128                         }
129                 break;
130
131                 case EVP_CIPH_CBC_MODE:
132                 if (ctx->akeysz == 64)
133                         DES_ncbc_encrypt(in, out, len, &ctx->ks1, iv, ctx->dir);
134                 else
135                         DES_ede3_cbc_encrypt(in, out, len,
136                                 &ctx->ks1, &ctx->ks2, &ctx->ks3,
137                                 iv, ctx->dir);
138                 break;
139
140                 case EVP_CIPH_CFB_MODE:
141 #if 0
142                 if (ctx->cbits == 1)
143                         {
144                         if (ctx->akeysz == 64)
145                                 DES_cfb64_encrypt(in, out, len,
146                                                 &ctx->ks1, iv,
147                                                 &ctx->num, ctx->dir);
148                         else
149                                 DES_ede3_cfb64_encrypt(in, out, len,
150                                                 &ctx->ks1,
151                                                 &ctx->ks2,
152                                                 &ctx->ks3, iv,
153                                                 &ctx->num, ctx->dir);
154                         }
155                 else
156 #endif
157                 if (ctx->cbits == 8)
158                         {
159                         if (ctx->akeysz == 64)
160                                 DES_cfb_encrypt(in, out, 8, len,
161                                                 &ctx->ks1, iv, ctx->dir);
162                         else
163                                 DES_ede3_cfb_encrypt(in, out, 8, len,
164                                                 &ctx->ks1,
165                                                 &ctx->ks2,
166                                                 &ctx->ks3, iv, ctx->dir);
167                         }
168                 else if (ctx->cbits == 64)
169                         {
170                         if (ctx->akeysz == 64)
171                                 DES_cfb64_encrypt(in, out, len,
172                                                 &ctx->ks1, iv,
173                                                 &ctx->num, ctx->dir);
174                         else
175                                 DES_ede3_cfb64_encrypt(in, out, len,
176                                                 &ctx->ks1,
177                                                 &ctx->ks2,
178                                                 &ctx->ks3, iv,
179                                                 &ctx->num, ctx->dir);
180                         }
181                 break;
182
183                 case EVP_CIPH_OFB_MODE:
184                 if (ctx->akeysz == 64)
185                         DES_ofb64_encrypt(in, out, len, &ctx->ks1, iv,
186                                                                 &ctx->num);
187                 else
188                         DES_ede3_ofb64_encrypt(in, out, len,
189                                         &ctx->ks1, &ctx->ks2, &ctx->ks3,
190                                         iv, &ctx->num);
191
192                 break;
193
194                 default:
195                 return 0;
196
197                 }
198
199         return 1;
200
201         }
202
203 int DESTest(DES_CTX *ctx,
204             char *amode, int akeysz, unsigned char *aKey, 
205             unsigned char *iVec, 
206             int dir,  /* 0 = decrypt, 1 = encrypt */
207             unsigned char *out, unsigned char *in, int len)
208     {
209     DES_cblock *deskey = (DES_cblock *)aKey;
210     ctx->cmode = -1;
211     ctx->cbits = -1;
212     ctx->dir = dir;
213     ctx->num = 0;
214
215     if (strcasecmp(amode, "CBC") == 0)
216         ctx->cmode = EVP_CIPH_CBC_MODE;
217     else if (strcasecmp(amode, "ECB") == 0)
218         ctx->cmode = EVP_CIPH_ECB_MODE;
219     else if (strcasecmp(amode, "CFB64") == 0)
220         {
221         ctx->cbits = 64;
222         ctx->cmode = EVP_CIPH_CFB_MODE;
223         }
224     else if (strncasecmp(amode, "OFB", 3) == 0)
225         ctx->cmode = EVP_CIPH_OFB_MODE;
226 #if 0
227     else if(!strcasecmp(amode,"CFB1"))
228         {
229         ctx->cbits = 1;
230         ctx->cmode = EVP_CIPH_CFB_MODE;
231         }
232 #endif
233     else if(!strcasecmp(amode,"CFB8"))
234         {
235         ctx->cbits = 8;
236         ctx->cmode = EVP_CIPH_CFB_MODE;
237         }
238     else
239         {
240         printf("Unknown mode: %s\n", amode);
241         EXIT(1);
242         }
243     if (akeysz != 64 && akeysz != 192)
244         {
245         printf("Invalid key size: %d\n", akeysz);
246         EXIT(1);
247         }
248     else
249         {
250         ctx->akeysz = akeysz;
251         DES_set_key_unchecked(deskey, &ctx->ks1);
252         if(ctx->akeysz == 192)
253                 {
254                 DES_set_key_unchecked(deskey + 1, &ctx->ks2);
255                 DES_set_key_unchecked(deskey + 2, &ctx->ks3);
256                 }
257         if (iVec)
258                 memcpy(ctx->tiv, iVec, DES_BLOCK_SIZE);
259         DES_Cipher(ctx, out, in, len);
260         }
261     return 1;
262     }
263
264 void DebugValue(char *tag, unsigned char *val, int len)
265     {
266     char obuf[2048];
267     int olen;
268     olen = bin2hex(val, len, obuf);
269     printf("%s = %.*s\n", tag, olen, obuf);
270     }
271
272 void shiftin(unsigned char *dst,unsigned char *src,int nbits)
273     {
274     int n;
275
276     /* move the bytes... */
277     memmove(dst,dst+nbits/8,3*8-nbits/8);
278     /* append new data */
279     memcpy(dst+3*8-nbits/8,src,(nbits+7)/8);
280     /* left shift the bits */
281     if(nbits%8)
282         for(n=0 ; n < 3*8 ; ++n)
283             dst[n]=(dst[n] << (nbits%8))|(dst[n+1] >> (8-nbits%8));
284     }   
285
286 /*-----------------------------------------------*/
287 char *t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"};
288 char *t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"};
289 enum Mode {CBC, ECB, OFB, CFB1, CFB8, CFB64};
290 int Sizes[6]={64,64,64,1,8,64};
291
292 void do_mct(char *amode, 
293             int akeysz, int numkeys, unsigned char *akey,unsigned char *ivec,
294             int dir, unsigned char *text, int len,
295             FILE *rfp)
296     {
297     int i,imode;
298     unsigned char nk[4*8]; /* longest key+8 */
299     unsigned char text0[8];
300
301     for (imode=0 ; imode < 6 ; ++imode)
302         if(!strcmp(amode,t_mode[imode]))
303             break;
304     if (imode == 6)
305         { 
306         printf("Unrecognized mode: %s\n", amode);
307         EXIT(1);
308         }
309
310     for(i=0 ; i < 400 ; ++i)
311         {
312         int j;
313         int n;
314         DES_CTX ctx;
315         int kp=akeysz/64;
316         unsigned char old_iv[8];
317
318         fprintf(rfp,"\nCOUNT = %d\n",i);
319         if(kp == 1)
320             OutputValue("KEY",akey,8,rfp,0);
321         else
322             for(n=0 ; n < kp ; ++n)
323                 {
324                 fprintf(rfp,"KEY%d",n+1);
325                 OutputValue("",akey+n*8,8,rfp,0);
326                 }
327
328         if(imode != ECB)
329             OutputValue("IV",ivec,8,rfp,0);
330         OutputValue(t_tag[dir^1],text,len,rfp,imode == CFB1);
331
332         /* compensate for endianness */
333         if(imode == CFB1)
334             text[0]<<=7;
335
336         memcpy(text0,text,8);
337
338         for(j=0 ; j < 10000 ; ++j)
339             {
340             unsigned char old_text[8];
341
342             memcpy(old_text,text,8);
343             if(j == 0)
344                 {
345                 memcpy(old_iv,ivec,8);
346                 DESTest(&ctx,amode,akeysz,akey,ivec,dir,text,text,len);
347                 }
348             else
349                 {
350                 memcpy(old_iv,ctx.tiv,8);
351                 DES_Cipher(&ctx,text,text,len);
352                 }
353             if(j == 9999)
354                 {
355                 OutputValue(t_tag[dir],text,len,rfp,imode == CFB1);
356                 /*              memcpy(ivec,text,8); */
357                 }
358             /*      DebugValue("iv",ctx.iv,8); */
359             /* accumulate material for the next key */
360             shiftin(nk,text,Sizes[imode]);
361             /*      DebugValue("nk",nk,24);*/
362             if((dir && (imode == CFB1 || imode == CFB8 || imode == CFB64
363                         || imode == CBC)) || imode == OFB)
364                 memcpy(text,old_iv,8);
365
366             if(!dir && (imode == CFB1 || imode == CFB8 || imode == CFB64))
367                 {
368                 /* the test specifies using the output of the raw DES operation
369                    which we don't have, so reconstruct it... */
370                 for(n=0 ; n < 8 ; ++n)
371                     text[n]^=old_text[n];
372                 }
373             }
374         for(n=0 ; n < 8 ; ++n)
375             akey[n]^=nk[16+n];
376         for(n=0 ; n < 8 ; ++n)
377             akey[8+n]^=nk[8+n];
378         for(n=0 ; n < 8 ; ++n)
379             akey[16+n]^=nk[n];
380         if(numkeys < 3)
381             memcpy(&akey[2*8],akey,8);
382         if(numkeys < 2)
383             memcpy(&akey[8],akey,8);
384         DES_set_odd_parity((DES_cblock *)akey);
385         DES_set_odd_parity((DES_cblock *)(akey+8));
386         DES_set_odd_parity((DES_cblock *)(akey+16));
387         memcpy(ivec,ctx.tiv,8);
388
389         /* pointless exercise - the final text doesn't depend on the
390            initial text in OFB mode, so who cares what it is? (Who
391            designed these tests?) */
392         if(imode == OFB)
393             for(n=0 ; n < 8 ; ++n)
394                 text[n]=text0[n]^old_iv[n];
395         }
396     }
397     
398 int proc_file(char *rqfile)
399     {
400     char afn[256], rfn[256];
401     FILE *afp = NULL, *rfp = NULL;
402     char ibuf[2048], tbuf[2048];
403     int ilen, len, ret = 0;
404     char amode[8] = "";
405     char atest[100] = "";
406     int akeysz=0;
407     unsigned char iVec[20], aKey[40];
408     int dir = -1, err = 0, step = 0;
409     unsigned char plaintext[2048];
410     unsigned char ciphertext[2048];
411     char *rp;
412     DES_CTX ctx;
413     int numkeys=1;
414
415     if (!rqfile || !(*rqfile))
416         {
417         printf("No req file\n");
418         return -1;
419         }
420     strcpy(afn, rqfile);
421
422     if ((afp = fopen(afn, "r")) == NULL)
423         {
424         printf("Cannot open file: %s, %s\n", 
425                afn, strerror(errno));
426         return -1;
427         }
428     strcpy(rfn,afn);
429     rp=strstr(rfn,"req/");
430 #ifdef OPENSSL_SYS_WIN32
431     if (!rp)
432         rp=strstr(rfn,"req\\");
433 #endif
434     assert(rp);
435     memcpy(rp,"rsp",3);
436     rp = strstr(rfn, ".req");
437     memcpy(rp, ".rsp", 4);
438     if ((rfp = fopen(rfn, "w")) == NULL)
439         {
440         printf("Cannot open file: %s, %s\n", 
441                rfn, strerror(errno));
442         fclose(afp);
443         afp = NULL;
444         return -1;
445         }
446     while (!err && (fgets(ibuf, sizeof(ibuf), afp)) != NULL)
447         {
448         tidy_line(tbuf, ibuf);
449         ilen = strlen(ibuf);
450         /*      printf("step=%d ibuf=%s",step,ibuf);*/
451         if(step == 3 && !strcmp(amode,"ECB"))
452             {
453             memset(iVec, 0, sizeof(iVec));
454             step = (dir)? 4: 5;  /* no ivec for ECB */
455             }
456         switch (step)
457             {
458         case 0:  /* read preamble */
459             if (ibuf[0] == '\n')
460                 { /* end of preamble */
461                 if (*amode == '\0')
462                     {
463                     printf("Missing Mode\n");
464                     err = 1;
465                     }
466                 else
467                     {
468                     fputs(ibuf, rfp);
469                     ++ step;
470                     }
471                 }
472             else if (ibuf[0] != '#')
473                 {
474                 printf("Invalid preamble item: %s\n", ibuf);
475                 err = 1;
476                 }
477             else
478                 { /* process preamble */
479                 char *xp, *pp = ibuf+2;
480                 int n;
481                 if(*amode)
482                     { /* insert current time & date */
483                     time_t rtim = time(0);
484                     fprintf(rfp, "# %s", ctime(&rtim));
485                     }
486                 else
487                     {
488                     fputs(ibuf, rfp);
489                     if(!strncmp(pp,"INVERSE ",8) || !strncmp(pp,"DES ",4)
490                        || !strncmp(pp,"TDES ",5)
491                        || !strncmp(pp,"PERMUTATION ",12)
492                        || !strncmp(pp,"SUBSTITUTION ",13)
493                        || !strncmp(pp,"VARIABLE ",9))
494                         {
495                         /* get test type */
496                         if(!strncmp(pp,"DES ",4))
497                             pp+=4;
498                         else if(!strncmp(pp,"TDES ",5))
499                             pp+=5;
500                         xp = strchr(pp, ' ');
501                         n = xp-pp;
502                         strncpy(atest, pp, n);
503                         atest[n] = '\0';
504                         /* get mode */
505                         xp = strrchr(pp, ' '); /* get mode" */
506                         n = strlen(xp+1)-1;
507                         strncpy(amode, xp+1, n);
508                         amode[n] = '\0';
509                         /* amode[3] = '\0'; */
510                         printf("Test=%s, Mode=%s\n",atest,amode);
511                         }
512                     }
513                 }
514             break;
515
516         case 1:  /* [ENCRYPT] | [DECRYPT] */
517             if(ibuf[0] == '\n')
518                 break;
519             if (ibuf[0] == '[')
520                 {
521                 fputs(ibuf, rfp);
522                 ++step;
523                 if (strncasecmp(ibuf, "[ENCRYPT]", 9) == 0)
524                     dir = 1;
525                 else if (strncasecmp(ibuf, "[DECRYPT]", 9) == 0)
526                     dir = 0;
527                 else
528                     {
529                     printf("Invalid keyword: %s\n", ibuf);
530                     err = 1;
531                     }
532                 break;
533                 }
534             else if (dir == -1)
535                 {
536                 err = 1;
537                 printf("Missing ENCRYPT/DECRYPT keyword\n");
538                 break;
539                 }
540             else 
541                 step = 2;
542
543         case 2: /* KEY = xxxx */
544             if(*ibuf == '\n')
545                 {
546                 fputs(ibuf, rfp);
547                 break;
548                 }
549             if(!strncasecmp(ibuf,"COUNT = ",8))
550                 {
551                 fputs(ibuf, rfp);
552                 break;
553                 }
554             if(!strncasecmp(ibuf,"COUNT=",6))
555                 {
556                 fputs(ibuf, rfp);
557                 break;
558                 }
559             if(!strncasecmp(ibuf,"NumKeys = ",10))
560                 {
561                 numkeys=atoi(ibuf+10);
562                 break;
563                 }
564           
565             fputs(ibuf, rfp);
566             if(!strncasecmp(ibuf,"KEY = ",6))
567                 {
568                 akeysz=64;
569                 len = hex2bin((char*)ibuf+6, aKey);
570                 if (len < 0)
571                     {
572                     printf("Invalid KEY\n");
573                     err=1;
574                     break;
575                     }
576                 PrintValue("KEY", aKey, len);
577                 ++step;
578                 }
579             else if(!strncasecmp(ibuf,"KEYs = ",7))
580                 {
581                 akeysz=64*3;
582                 len=hex2bin(ibuf+7,aKey);
583                 if(len != 8)
584                     {
585                     printf("Invalid KEY\n");
586                     err=1;
587                     break;
588                     }
589                 memcpy(aKey+8,aKey,8);
590                 memcpy(aKey+16,aKey,8);
591                 ibuf[4]='\0';
592                 PrintValue("KEYs",aKey,len);
593                 ++step;
594                 }
595             else if(!strncasecmp(ibuf,"KEY",3))
596                 {
597                 int n=ibuf[3]-'1';
598
599                 akeysz=64*3;
600                 len=hex2bin(ibuf+7,aKey+n*8);
601                 if(len != 8)
602                     {
603                     printf("Invalid KEY\n");
604                     err=1;
605                     break;
606                     }
607                 ibuf[4]='\0';
608                 PrintValue(ibuf,aKey,len);
609                 if(n == 2)
610                     ++step;
611                 }
612             else
613                 {
614                 printf("Missing KEY\n");
615                 err = 1;
616                 }
617             break;
618
619         case 3: /* IV = xxxx */
620             fputs(ibuf, rfp);
621             if (strncasecmp(ibuf, "IV = ", 5) != 0)
622                 {
623                 printf("Missing IV\n");
624                 err = 1;
625                 }
626             else
627                 {
628                 len = hex2bin((char*)ibuf+5, iVec);
629                 if (len < 0)
630                     {
631                     printf("Invalid IV\n");
632                     err =1;
633                     break;
634                     }
635                 PrintValue("IV", iVec, len);
636                 step = (dir)? 4: 5;
637                 }
638             break;
639
640         case 4: /* PLAINTEXT = xxxx */
641             fputs(ibuf, rfp);
642             if (strncasecmp(ibuf, "PLAINTEXT = ", 12) != 0)
643                 {
644                 printf("Missing PLAINTEXT\n");
645                 err = 1;
646                 }
647             else
648                 {
649                 int nn = strlen(ibuf+12);
650                 if(!strcmp(amode,"CFB1"))
651                     len=bint2bin(ibuf+12,nn-1,plaintext);
652                 else
653                     len=hex2bin(ibuf+12, plaintext);
654                 if (len < 0)
655                     {
656                     printf("Invalid PLAINTEXT: %s", ibuf+12);
657                     err =1;
658                     break;
659                     }
660                 if (len >= sizeof(plaintext))
661                     {
662                     printf("Buffer overflow\n");
663                     }
664                 PrintValue("PLAINTEXT", (unsigned char*)plaintext, len);
665                 if (strcmp(atest, "Monte") == 0)  /* Monte Carlo Test */
666                     {
667                     do_mct(amode,akeysz,numkeys,aKey,iVec,dir,plaintext,len,rfp);
668                     }
669                 else
670                     {
671                     assert(dir == 1);
672                     ret = DESTest(&ctx, amode, akeysz, aKey, iVec, 
673                                   dir,  /* 0 = decrypt, 1 = encrypt */
674                                   ciphertext, plaintext, len);
675                     OutputValue("CIPHERTEXT",ciphertext,len,rfp,
676                                 !strcmp(amode,"CFB1"));
677                     }
678                 step = 6;
679                 }
680             break;
681
682         case 5: /* CIPHERTEXT = xxxx */
683             fputs(ibuf, rfp);
684             if (strncasecmp(ibuf, "CIPHERTEXT = ", 13) != 0)
685                 {
686                 printf("Missing KEY\n");
687                 err = 1;
688                 }
689             else
690                 {
691                 if(!strcmp(amode,"CFB1"))
692                     len=bint2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
693                 else
694                     len = hex2bin(ibuf+13,ciphertext);
695                 if (len < 0)
696                     {
697                     printf("Invalid CIPHERTEXT\n");
698                     err =1;
699                     break;
700                     }
701                 
702                 PrintValue("CIPHERTEXT", ciphertext, len);
703                 if (strcmp(atest, "Monte") == 0)  /* Monte Carlo Test */
704                     {
705                     do_mct(amode, akeysz, numkeys, aKey, iVec, 
706                            dir, ciphertext, len, rfp);
707                     }
708                 else
709                     {
710                     assert(dir == 0);
711                     ret = DESTest(&ctx, amode, akeysz, aKey, iVec, 
712                                   dir,  /* 0 = decrypt, 1 = encrypt */
713                                   plaintext, ciphertext, len);
714                     OutputValue("PLAINTEXT",(unsigned char *)plaintext,len,rfp,
715                                 !strcmp(amode,"CFB1"));
716                     }
717                 step = 6;
718                 }
719             break;
720
721         case 6:
722             if (ibuf[0] != '\n')
723                 {
724                 err = 1;
725                 printf("Missing terminator\n");
726                 }
727             else if (strcmp(atest, "MCT") != 0)
728                 { /* MCT already added terminating nl */
729                 fputs(ibuf, rfp);
730                 }
731             step = 1;
732             break;
733             }
734         }
735     if (rfp)
736         fclose(rfp);
737     if (afp)
738         fclose(afp);
739     return err;
740     }
741
742 /*--------------------------------------------------
743   Processes either a single file or 
744   a set of files whose names are passed in a file.
745   A single file is specified as:
746     aes_test -f xxx.req
747   A set of files is specified as:
748     aes_test -d xxxxx.xxx
749   The default is: -d req.txt
750 --------------------------------------------------*/
751 int main(int argc, char **argv)
752     {
753     char *rqlist = "req.txt";
754     FILE *fp = NULL;
755     char fn[250] = "", rfn[256] = "";
756     int f_opt = 0, d_opt = 1;
757
758 #ifdef OPENSSL_FIPS
759     if(!FIPS_mode_set(1))
760         {
761         do_print_errors();
762         EXIT(1);
763         }
764 #endif
765     if (argc > 1)
766         {
767         if (strcasecmp(argv[1], "-d") == 0)
768             {
769             d_opt = 1;
770             }
771         else if (strcasecmp(argv[1], "-f") == 0)
772             {
773             f_opt = 1;
774             d_opt = 0;
775             }
776         else
777             {
778             printf("Invalid parameter: %s\n", argv[1]);
779             return 0;
780             }
781         if (argc < 3)
782             {
783             printf("Missing parameter\n");
784             return 0;
785             }
786         if (d_opt)
787             rqlist = argv[2];
788         else
789             strcpy(fn, argv[2]);
790         }
791     if (d_opt)
792         { /* list of files (directory) */
793         if (!(fp = fopen(rqlist, "r")))
794             {
795             printf("Cannot open req list file\n");
796             return -1;
797             }
798         while (fgets(fn, sizeof(fn), fp))
799             {
800             strtok(fn, "\r\n");
801             strcpy(rfn, fn);
802             printf("Processing: %s\n", rfn);
803             if (proc_file(rfn))
804                 {
805                 printf(">>> Processing failed for: %s <<<\n", rfn);
806                 EXIT(1);
807                 }
808             }
809         fclose(fp);
810         }
811     else /* single file */
812         {
813         printf("Processing: %s\n", fn);
814         if (proc_file(fn))
815             {
816             printf(">>> Processing failed for: %s <<<\n", fn);
817             }
818         }
819     EXIT(0);
820     return 0;
821     }
822
823 #endif