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