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