1 /* ====================================================================
2 * Copyright (c) 2004 The OpenSSL Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
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
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/)"
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.
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.
30 * 6. Redistributions of any form whatsoever must retain the following
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
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.
49 /*---------------------------------------------
50 NIST DES Modes of Operation Validation System
53 Based on the AES Validation Suite, which was:
54 Donated to OpenSSL by:
56 20250 Century Blvd, Suite 300
59 ----------------------------------------------*/
67 #include <openssl/des.h>
68 #include <openssl/evp.h>
69 #include <openssl/fips.h>
70 #include <openssl/err.h>
73 /*#define AES_BLOCK_SIZE 16*/
77 /*-----------------------------------------------*/
79 int DESTest(EVP_CIPHER_CTX
*ctx
,
80 char *amode
, int akeysz
, unsigned char *aKey
,
82 int dir
, /* 0 = decrypt, 1 = encrypt */
83 unsigned char *out
, unsigned char *in
, int len
)
85 const EVP_CIPHER
*cipher
= NULL
;
89 memset(ctx
, 0, sizeof(EVP_CIPHER_CTX
));
91 if (strcasecmp(amode
, "CBC") == 0)
93 else if (strcasecmp(amode
, "ECB") == 0)
95 else if (strcasecmp(amode
, "CFB64") == 0)
97 else if (strncasecmp(amode
, "OFB", 3) == 0)
99 else if(!strcasecmp(amode
,"CFB1"))
101 else if(!strcasecmp(amode
,"CFB8"))
105 printf("Unknown mode: %s\n", amode
);
108 if (akeysz
!= 64 && akeysz
!= 192)
110 printf("Invalid key size: %d\n", akeysz
);
119 cipher
=EVP_des_cbc();
122 cipher
=EVP_des_ede3_cbc();
125 cipher
=EVP_des_ecb();
128 cipher
=EVP_des_ede3_ecb();
131 cipher
=EVP_des_cfb64();
134 cipher
=EVP_des_ede3_cfb64();
137 cipher
=EVP_des_ofb();
140 cipher
=EVP_des_ede3_ofb();
143 cipher
=EVP_des_cfb1();
146 cipher
=EVP_des_ede3_cfb1();
149 cipher
=EVP_des_cfb8();
152 cipher
=EVP_des_ede3_cfb8();
155 printf("Didn't handle mode %d\n",kt
);
158 if(!EVP_CipherInit(ctx
, cipher
, aKey
, iVec
, dir
))
160 ERR_print_errors_fp(stderr
);
163 EVP_Cipher(ctx
, out
, in
, len
);
168 /*-----------------------------------------------*/
170 int hex2bin(char *in
, int len
, unsigned char *out
)
175 for (n1
= 0, n2
= 0; n1
< len
; )
177 if ((in
[n1
] >= '0') && (in
[n1
] <= '9'))
179 else if ((in
[n1
] >= 'A') && (in
[n1
] <= 'F'))
180 ch
= in
[n1
++] - 'A' + 10;
181 else if ((in
[n1
] >= 'a') && (in
[n1
] <= 'f'))
182 ch
= in
[n1
++] - 'a' + 10;
192 if ((in
[n1
] >= '0') && (in
[n1
] <= '9'))
194 else if ((in
[n1
] >= 'A') && (in
[n1
] <= 'F'))
195 ch
= in
[n1
++] - 'A' + 10;
196 else if ((in
[n1
] >= 'a') && (in
[n1
] <= 'f'))
197 ch
= in
[n1
++] - 'a' + 10;
205 /*-----------------------------------------------*/
207 int bin2hex(unsigned char *in
, int len
, char *out
)
212 for (n1
= 0, n2
= 0; n1
< len
; ++n1
)
217 out
[n2
++] = ch
+ '0';
219 out
[n2
++] = ch
- 10 + 'a';
223 out
[n2
++] = ch
+ '0';
225 out
[n2
++] = ch
- 10 + 'a';
230 /* NB: this return the number of _bits_ read */
231 int bint2bin(const char *in
, int len
, unsigned char *out
)
236 for(n
=0 ; n
< len
; ++n
)
238 out
[n
/8]|=(0x80 >> (n
%8));
242 int bin2bint(const unsigned char *in
,int len
,char *out
)
246 for(n
=0 ; n
< len
; ++n
)
247 out
[n
]=(in
[n
/8]&(0x80 >> (n
%8))) ? '1' : '0';
251 /*-----------------------------------------------*/
253 void PrintValue(char *tag
, unsigned char *val
, int len
)
258 olen
= bin2hex(val
, len
, obuf
);
259 printf("%s = %.*s\n", tag
, olen
, obuf
);
263 void DebugValue(char *tag
, unsigned char *val
, int len
)
267 olen
= bin2hex(val
, len
, obuf
);
268 printf("%s = %.*s\n", tag
, olen
, obuf
);
271 void OutputValue(char *tag
, unsigned char *val
, int len
, FILE *rfp
,int bitmode
)
277 olen
=bin2bint(val
,len
,obuf
);
279 olen
=bin2hex(val
,len
,obuf
);
281 fprintf(rfp
, "%s = %.*s\n", tag
, olen
, obuf
);
283 printf("%s = %.*s\n", tag
, olen
, obuf
);
287 void shiftin(unsigned char *dst
,unsigned char *src
,int nbits
)
291 /* move the bytes... */
292 memmove(dst
,dst
+nbits
/8,3*8-nbits
/8);
293 /* append new data */
294 memcpy(dst
+3*8-nbits
/8,src
,(nbits
+7)/8);
295 /* left shift the bits */
297 for(n
=0 ; n
< 3*8 ; ++n
)
298 dst
[n
]=(dst
[n
] << (nbits
%8))|(dst
[n
+1] >> (8-nbits
%8));
301 /*-----------------------------------------------*/
302 char *t_tag
[2] = {"PLAINTEXT", "CIPHERTEXT"};
303 char *t_mode
[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"};
304 enum Mode
{CBC
, ECB
, OFB
, CFB1
, CFB8
, CFB64
};
305 int Sizes
[6]={64,64,64,1,8,64};
307 void do_mct(char *amode
,
308 int akeysz
, int numkeys
, unsigned char *akey
,unsigned char *ivec
,
309 int dir
, unsigned char *text
, int len
,
313 unsigned char nk
[4*8]; /* longest key+8 */
314 unsigned char text0
[8];
316 for (imode
=0 ; imode
< 6 ; ++imode
)
317 if(!strcmp(amode
,t_mode
[imode
]))
321 printf("Unrecognized mode: %s\n", amode
);
325 for(i
=0 ; i
< 400 ; ++i
)
331 unsigned char old_iv
[8];
333 fprintf(rfp
,"\nCOUNT = %d\n",i
);
335 OutputValue("KEY",akey
,8,rfp
,0);
337 for(n
=0 ; n
< kp
; ++n
)
339 fprintf(rfp
,"KEY%d",n
+1);
340 OutputValue("",akey
+n
*8,8,rfp
,0);
344 OutputValue("IV",ivec
,8,rfp
,0);
345 OutputValue(t_tag
[dir
^1],text
,len
,rfp
,imode
== CFB1
);
347 /* compensate for endianness */
351 memcpy(text0
,text
,8);
353 for(j
=0 ; j
< 10000 ; ++j
)
355 unsigned char old_text
[8];
357 memcpy(old_text
,text
,8);
360 memcpy(old_iv
,ivec
,8);
361 DESTest(&ctx
,amode
,akeysz
,akey
,ivec
,dir
,text
,text
,len
);
365 memcpy(old_iv
,ctx
.iv
,8);
366 EVP_Cipher(&ctx
,text
,text
,len
);
370 OutputValue(t_tag
[dir
],text
,len
,rfp
,imode
== CFB1
);
371 /* memcpy(ivec,text,8); */
373 /* DebugValue("iv",ctx.iv,8); */
374 /* accumulate material for the next key */
375 shiftin(nk
,text
,Sizes
[imode
]);
376 /* DebugValue("nk",nk,24);*/
377 if((dir
&& (imode
== CFB1
|| imode
== CFB8
|| imode
== CFB64
378 || imode
== CBC
)) || imode
== OFB
)
379 memcpy(text
,old_iv
,8);
381 if(!dir
&& (imode
== CFB1
|| imode
== CFB8
|| imode
== CFB64
))
383 /* the test specifies using the output of the raw DES operation
384 which we don't have, so reconstruct it... */
385 for(n
=0 ; n
< 8 ; ++n
)
386 text
[n
]^=old_text
[n
];
389 for(n
=0 ; n
< 8 ; ++n
)
391 for(n
=0 ; n
< 8 ; ++n
)
393 for(n
=0 ; n
< 8 ; ++n
)
396 memcpy(&akey
[2*8],akey
,8);
398 memcpy(&akey
[8],akey
,8);
399 DES_set_odd_parity((DES_cblock
*)akey
);
400 DES_set_odd_parity((DES_cblock
*)(akey
+8));
401 DES_set_odd_parity((DES_cblock
*)(akey
+16));
402 memcpy(ivec
,ctx
.iv
,8);
404 /* pointless exercise - the final text doesn't depend on the
405 initial text in OFB mode, so who cares what it is? (Who
406 designed these tests?) */
408 for(n
=0 ; n
< 8 ; ++n
)
409 text
[n
]=text0
[n
]^old_iv
[n
];
413 int proc_file(char *rqfile
)
415 char afn
[256], rfn
[256];
416 FILE *afp
= NULL
, *rfp
= NULL
;
418 int ilen
, len
, ret
= 0;
420 char atest
[100] = "";
422 unsigned char iVec
[20], aKey
[40];
423 int dir
= -1, err
= 0, step
= 0;
424 unsigned char plaintext
[2048];
425 unsigned char ciphertext
[2048];
430 if (!rqfile
|| !(*rqfile
))
432 printf("No req file\n");
437 if ((afp
= fopen(afn
, "r")) == NULL
)
439 printf("Cannot open file: %s, %s\n",
440 afn
, strerror(errno
));
444 rp
=strstr(rfn
,"req/");
447 rp
= strstr(rfn
, ".req");
448 memcpy(rp
, ".rsp", 4);
449 if ((rfp
= fopen(rfn
, "w")) == NULL
)
451 printf("Cannot open file: %s, %s\n",
452 rfn
, strerror(errno
));
457 while (!err
&& (fgets(ibuf
, sizeof(ibuf
), afp
)) != NULL
)
460 /* printf("step=%d ibuf=%s",step,ibuf);*/
461 if(step
== 3 && !strcmp(amode
,"ECB"))
463 memset(iVec
, 0, sizeof(iVec
));
464 step
= (dir
)? 4: 5; /* no ivec for ECB */
468 case 0: /* read preamble */
470 { /* end of preamble */
473 printf("Missing Mode\n");
482 else if (ibuf
[0] != '#')
484 printf("Invalid preamble item: %s\n", ibuf
);
488 { /* process preamble */
489 char *xp
, *pp
= ibuf
+2;
492 { /* insert current time & date */
493 time_t rtim
= time(0);
494 fprintf(rfp
, "# %s", ctime(&rtim
));
499 if(!strncmp(pp
,"INVERSE ",8) || !strncmp(pp
,"DES ",4)
500 || !strncmp(pp
,"TDES ",5)
501 || !strncmp(pp
,"PERMUTATION ",12)
502 || !strncmp(pp
,"SUBSTITUTION ",13)
503 || !strncmp(pp
,"VARIABLE ",9))
506 if(!strncmp(pp
,"DES ",4))
508 else if(!strncmp(pp
,"TDES ",5))
510 xp
= strchr(pp
, ' ');
512 strncpy(atest
, pp
, n
);
515 xp
= strrchr(pp
, ' '); /* get mode" */
517 strncpy(amode
, xp
+1, n
);
519 /* amode[3] = '\0'; */
520 printf("Test=%s, Mode=%s\n",atest
,amode
);
526 case 1: /* [ENCRYPT] | [DECRYPT] */
533 if (strncasecmp(ibuf
, "[ENCRYPT]", 9) == 0)
535 else if (strncasecmp(ibuf
, "[DECRYPT]", 9) == 0)
539 printf("Invalid keyword: %s\n", ibuf
);
547 printf("Missing ENCRYPT/DECRYPT keyword\n");
553 case 2: /* KEY = xxxx */
559 if(!strncasecmp(ibuf
,"COUNT = ",8))
564 if(!strncasecmp(ibuf
,"COUNT=",6))
569 if(!strncasecmp(ibuf
,"NumKeys = ",10))
571 numkeys
=atoi(ibuf
+10);
576 if(!strncasecmp(ibuf
,"KEY = ",6))
579 len
= hex2bin((char*)ibuf
+6, strlen(ibuf
+6)-1, aKey
);
582 printf("Invalid KEY\n");
586 PrintValue("KEY", aKey
, len
);
589 else if(!strncasecmp(ibuf
,"KEYs = ",7))
592 len
=hex2bin(ibuf
+7,strlen(ibuf
+7)-1,aKey
);
595 printf("Invalid KEY\n");
599 memcpy(aKey
+8,aKey
,8);
600 memcpy(aKey
+16,aKey
,8);
602 PrintValue("KEYs",aKey
,len
);
605 else if(!strncasecmp(ibuf
,"KEY",3))
610 len
=hex2bin(ibuf
+7,strlen(ibuf
+7)-1,aKey
+n
*8);
613 printf("Invalid KEY\n");
618 PrintValue(ibuf
,aKey
,len
);
624 printf("Missing KEY\n");
629 case 3: /* IV = xxxx */
631 if (strncasecmp(ibuf
, "IV = ", 5) != 0)
633 printf("Missing IV\n");
638 len
= hex2bin((char*)ibuf
+5, strlen(ibuf
+5)-1, iVec
);
641 printf("Invalid IV\n");
645 PrintValue("IV", iVec
, len
);
650 case 4: /* PLAINTEXT = xxxx */
652 if (strncasecmp(ibuf
, "PLAINTEXT = ", 12) != 0)
654 printf("Missing PLAINTEXT\n");
659 int nn
= strlen(ibuf
+12);
660 if(!strcmp(amode
,"CFB1"))
661 len
=bint2bin(ibuf
+12,nn
-1,plaintext
);
663 len
=hex2bin(ibuf
+12, nn
-1,plaintext
);
666 printf("Invalid PLAINTEXT: %s", ibuf
+12);
670 if (len
>= sizeof(plaintext
))
672 printf("Buffer overflow\n");
674 PrintValue("PLAINTEXT", (unsigned char*)plaintext
, len
);
675 if (strcmp(atest
, "Monte") == 0) /* Monte Carlo Test */
677 do_mct(amode
,akeysz
,numkeys
,aKey
,iVec
,dir
,plaintext
,len
,rfp
);
682 ret
= DESTest(&ctx
, amode
, akeysz
, aKey
, iVec
,
683 dir
, /* 0 = decrypt, 1 = encrypt */
684 ciphertext
, plaintext
, len
);
685 OutputValue("CIPHERTEXT",ciphertext
,len
,rfp
,
686 !strcmp(amode
,"CFB1"));
692 case 5: /* CIPHERTEXT = xxxx */
694 if (strncasecmp(ibuf
, "CIPHERTEXT = ", 13) != 0)
696 printf("Missing KEY\n");
701 if(!strcmp(amode
,"CFB1"))
702 len
=bint2bin(ibuf
+13,strlen(ibuf
+13)-1,ciphertext
);
704 len
= hex2bin(ibuf
+13,strlen(ibuf
+13)-1,ciphertext
);
707 printf("Invalid CIPHERTEXT\n");
712 PrintValue("CIPHERTEXT", ciphertext
, len
);
713 if (strcmp(atest
, "Monte") == 0) /* Monte Carlo Test */
715 do_mct(amode
, akeysz
, numkeys
, aKey
, iVec
,
716 dir
, ciphertext
, len
, rfp
);
721 ret
= DESTest(&ctx
, amode
, akeysz
, aKey
, iVec
,
722 dir
, /* 0 = decrypt, 1 = encrypt */
723 plaintext
, ciphertext
, len
);
724 OutputValue("PLAINTEXT",(unsigned char *)plaintext
,len
,rfp
,
725 !strcmp(amode
,"CFB1"));
735 printf("Missing terminator\n");
737 else if (strcmp(atest
, "MCT") != 0)
738 { /* MCT already added terminating nl */
752 /*--------------------------------------------------
753 Processes either a single file or
754 a set of files whose names are passed in a file.
755 A single file is specified as:
757 A set of files is specified as:
758 aes_test -d xxxxx.xxx
759 The default is: -d req.txt
760 --------------------------------------------------*/
761 int main(int argc
, char **argv
)
763 char *rqlist
= "req.txt";
765 char fn
[250] = "", rfn
[256] = "";
766 int f_opt
= 0, d_opt
= 1;
769 if(!FIPS_mode_set(1,argv
[0]))
771 ERR_load_crypto_strings();
772 ERR_print_errors(BIO_new_fp(stderr
,BIO_NOCLOSE
));
776 ERR_load_crypto_strings();
779 if (strcasecmp(argv
[1], "-d") == 0)
783 else if (strcasecmp(argv
[1], "-f") == 0)
790 printf("Invalid parameter: %s\n", argv
[1]);
795 printf("Missing parameter\n");
804 { /* list of files (directory) */
805 if (!(fp
= fopen(rqlist
, "r")))
807 printf("Cannot open req list file\n");
810 while (fgets(fn
, sizeof(fn
), fp
))
814 printf("Processing: %s\n", rfn
);
817 printf(">>> Processing failed for: %s <<<\n", rfn
);
823 else /* single file */
825 printf("Processing: %s\n", fn
);
828 printf(">>> Processing failed for: %s <<<\n", fn
);