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