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