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