1 /*---------------------------------------------
2 NIST DES Modes of Operation Validation System
5 Based on the AES Validation Suite, which was:
8 20250 Century Blvd, Suite 300
11 ----------------------------------------------*/
19 #include <openssl/des.h>
20 #include <openssl/evp.h>
21 #include <openssl/fips.h>
22 #include <openssl/err.h>
25 /*#define AES_BLOCK_SIZE 16*/
29 /*-----------------------------------------------*/
31 int DESTest(EVP_CIPHER_CTX *ctx,
32 char *amode, int akeysz, unsigned char *aKey,
34 int dir, /* 0 = decrypt, 1 = encrypt */
35 unsigned char *out, unsigned char *in, int len)
37 const EVP_CIPHER *cipher = NULL;
41 memset(ctx, 0, sizeof(EVP_CIPHER_CTX));
43 if (strcasecmp(amode, "CBC") == 0)
45 else if (strcasecmp(amode, "ECB") == 0)
47 else if (strcasecmp(amode, "CFB64") == 0)
49 else if (strncasecmp(amode, "OFB", 3) == 0)
51 else if(!strcasecmp(amode,"CFB1"))
53 else if(!strcasecmp(amode,"CFB8"))
57 printf("Unknown mode: %s\n", amode);
60 if (akeysz != 64 && akeysz != 192)
62 printf("Invalid key size: %d\n", akeysz);
74 cipher=EVP_des_ede3_cbc();
80 cipher=EVP_des_ede3_ecb();
83 cipher=EVP_des_cfb64();
86 cipher=EVP_des_ede3_cfb64();
92 cipher=EVP_des_ede3_ofb();
95 cipher=EVP_des_cfb1();
98 cipher=EVP_des_ede3_cfb1();
101 cipher=EVP_des_cfb8();
104 cipher=EVP_des_ede3_cfb8();
107 printf("Didn't handle mode %d\n",kt);
110 if(!EVP_CipherInit(ctx, cipher, aKey, iVec, dir))
112 ERR_print_errors_fp(stderr);
115 EVP_Cipher(ctx, out, in, len);
120 /*-----------------------------------------------*/
122 int hex2bin(char *in, int len, unsigned char *out)
127 for (n1 = 0, n2 = 0; n1 < len; )
129 if ((in[n1] >= '0') && (in[n1] <= '9'))
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;
144 if ((in[n1] >= '0') && (in[n1] <= '9'))
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;
157 /*-----------------------------------------------*/
159 int bin2hex(unsigned char *in, int len, char *out)
164 for (n1 = 0, n2 = 0; n1 < len; ++n1)
169 out[n2++] = ch + '0';
171 out[n2++] = ch - 10 + 'a';
175 out[n2++] = ch + '0';
177 out[n2++] = ch - 10 + 'a';
182 /* NB: this return the number of _bits_ read */
183 int bint2bin(const char *in, int len, unsigned char *out)
188 for(n=0 ; n < len ; ++n)
190 out[n/8]|=(0x80 >> (n%8));
194 int bin2bint(const unsigned char *in,int len,char *out)
198 for(n=0 ; n < len ; ++n)
199 out[n]=(in[n/8]&(0x80 >> (n%8))) ? '1' : '0';
203 /*-----------------------------------------------*/
205 void PrintValue(char *tag, unsigned char *val, int len)
210 olen = bin2hex(val, len, obuf);
211 printf("%s = %.*s\n", tag, olen, obuf);
215 void DebugValue(char *tag, unsigned char *val, int len)
219 olen = bin2hex(val, len, obuf);
220 printf("%s = %.*s\n", tag, olen, obuf);
223 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode)
229 olen=bin2bint(val,len,obuf);
231 olen=bin2hex(val,len,obuf);
233 fprintf(rfp, "%s = %.*s\n", tag, olen, obuf);
235 printf("%s = %.*s\n", tag, olen, obuf);
239 void shiftin(unsigned char *dst,unsigned char *src,int nbits)
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 */
249 for(n=0 ; n < 3*8 ; ++n)
250 dst[n]=(dst[n] << (nbits%8))|(dst[n+1] >> (8-nbits%8));
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};
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,
265 unsigned char nk[4*8]; /* longest key+8 */
266 unsigned char text0[8];
268 for (imode=0 ; imode < 6 ; ++imode)
269 if(!strcmp(amode,t_mode[imode]))
273 printf("Unrecognized mode: %s\n", amode);
277 for(i=0 ; i < 400 ; ++i)
283 unsigned char old_iv[8];
285 fprintf(rfp,"\nCOUNT = %d\n",i);
287 OutputValue("KEY",akey,8,rfp,0);
289 for(n=0 ; n < kp ; ++n)
291 fprintf(rfp,"KEY%d",n+1);
292 OutputValue("",akey+n*8,8,rfp,0);
296 OutputValue("IV",ivec,8,rfp,0);
297 OutputValue(t_tag[dir^1],text,len,rfp,imode == CFB1);
299 /* compensate for endianness */
303 memcpy(text0,text,8);
305 for(j=0 ; j < 10000 ; ++j)
307 unsigned char old_text[8];
309 memcpy(old_text,text,8);
312 memcpy(old_iv,ivec,8);
313 DESTest(&ctx,amode,akeysz,akey,ivec,dir,text,text,len);
317 memcpy(old_iv,ctx.iv,8);
318 EVP_Cipher(&ctx,text,text,len);
322 OutputValue(t_tag[dir],text,len,rfp,imode == CFB1);
323 /* memcpy(ivec,text,8); */
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);
333 if(!dir && (imode == CFB1 || imode == CFB8 || imode == CFB64))
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];
341 for(n=0 ; n < 8 ; ++n)
343 for(n=0 ; n < 8 ; ++n)
345 for(n=0 ; n < 8 ; ++n)
348 memcpy(&akey[2*8],akey,8);
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);
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?) */
360 for(n=0 ; n < 8 ; ++n)
361 text[n]=text0[n]^old_iv[n];
365 int proc_file(char *rqfile)
367 char afn[256], rfn[256];
368 FILE *afp = NULL, *rfp = NULL;
370 int ilen, len, ret = 0;
372 char atest[100] = "";
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];
382 if (!rqfile || !(*rqfile))
384 printf("No req file\n");
389 if ((afp = fopen(afn, "r")) == NULL)
391 printf("Cannot open file: %s, %s\n",
392 afn, strerror(errno));
396 rp=strstr(rfn,"req/");
399 rp = strstr(rfn, ".req");
400 memcpy(rp, ".rsp", 4);
401 if ((rfp = fopen(rfn, "w")) == NULL)
403 printf("Cannot open file: %s, %s\n",
404 rfn, strerror(errno));
409 while (!err && (fgets(ibuf, sizeof(ibuf), afp)) != NULL)
412 /* printf("step=%d ibuf=%s",step,ibuf);*/
413 if(step == 3 && !strcmp(amode,"ECB"))
415 memset(iVec, 0, sizeof(iVec));
416 step = (dir)? 4: 5; /* no ivec for ECB */
420 case 0: /* read preamble */
422 { /* end of preamble */
425 printf("Missing Mode\n");
434 else if (ibuf[0] != '#')
436 printf("Invalid preamble item: %s\n", ibuf);
440 { /* process preamble */
441 char *xp, *pp = ibuf+2;
444 { /* insert current time & date */
445 time_t rtim = time(0);
446 fprintf(rfp, "# %s", ctime(&rtim));
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))
458 if(!strncmp(pp,"DES ",4))
460 else if(!strncmp(pp,"TDES ",5))
462 xp = strchr(pp, ' ');
464 strncpy(atest, pp, n);
467 xp = strrchr(pp, ' '); /* get mode" */
469 strncpy(amode, xp+1, n);
471 /* amode[3] = '\0'; */
472 printf("Test=%s, Mode=%s\n",atest,amode);
478 case 1: /* [ENCRYPT] | [DECRYPT] */
485 if (strncasecmp(ibuf, "[ENCRYPT]", 9) == 0)
487 else if (strncasecmp(ibuf, "[DECRYPT]", 9) == 0)
491 printf("Invalid keyword: %s\n", ibuf);
499 printf("Missing ENCRYPT/DECRYPT keyword\n");
505 case 2: /* KEY = xxxx */
511 if(!strncasecmp(ibuf,"COUNT = ",8))
516 if(!strncasecmp(ibuf,"COUNT=",6))
521 if(!strncasecmp(ibuf,"NumKeys = ",10))
523 numkeys=atoi(ibuf+10);
528 if(!strncasecmp(ibuf,"KEY = ",6))
531 len = hex2bin((char*)ibuf+6, strlen(ibuf+6)-1, aKey);
534 printf("Invalid KEY\n");
538 PrintValue("KEY", aKey, len);
541 else if(!strncasecmp(ibuf,"KEYs = ",7))
544 len=hex2bin(ibuf+7,strlen(ibuf+7)-1,aKey);
547 printf("Invalid KEY\n");
551 memcpy(aKey+8,aKey,8);
552 memcpy(aKey+16,aKey,8);
554 PrintValue("KEYs",aKey,len);
557 else if(!strncasecmp(ibuf,"KEY",3))
562 len=hex2bin(ibuf+7,strlen(ibuf+7)-1,aKey+n*8);
565 printf("Invalid KEY\n");
570 PrintValue(ibuf,aKey,len);
576 printf("Missing KEY\n");
581 case 3: /* IV = xxxx */
583 if (strncasecmp(ibuf, "IV = ", 5) != 0)
585 printf("Missing IV\n");
590 len = hex2bin((char*)ibuf+5, strlen(ibuf+5)-1, iVec);
593 printf("Invalid IV\n");
597 PrintValue("IV", iVec, len);
602 case 4: /* PLAINTEXT = xxxx */
604 if (strncasecmp(ibuf, "PLAINTEXT = ", 12) != 0)
606 printf("Missing PLAINTEXT\n");
611 int nn = strlen(ibuf+12);
612 if(!strcmp(amode,"CFB1"))
613 len=bint2bin(ibuf+12,nn-1,plaintext);
615 len=hex2bin(ibuf+12, nn-1,plaintext);
618 printf("Invalid PLAINTEXT: %s", ibuf+12);
622 if (len >= sizeof(plaintext))
624 printf("Buffer overflow\n");
626 PrintValue("PLAINTEXT", (unsigned char*)plaintext, len);
627 if (strcmp(atest, "Monte") == 0) /* Monte Carlo Test */
629 do_mct(amode,akeysz,numkeys,aKey,iVec,dir,plaintext,len,rfp);
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"));
644 case 5: /* CIPHERTEXT = xxxx */
646 if (strncasecmp(ibuf, "CIPHERTEXT = ", 13) != 0)
648 printf("Missing KEY\n");
653 if(!strcmp(amode,"CFB1"))
654 len=bint2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
656 len = hex2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
659 printf("Invalid CIPHERTEXT\n");
664 PrintValue("CIPHERTEXT", ciphertext, len);
665 if (strcmp(atest, "Monte") == 0) /* Monte Carlo Test */
667 do_mct(amode, akeysz, numkeys, aKey, iVec,
668 dir, ciphertext, len, rfp);
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"));
687 printf("Missing terminator\n");
689 else if (strcmp(atest, "MCT") != 0)
690 { /* MCT already added terminating nl */
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:
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)
715 char *rqlist = "req.txt";
717 char fn[250] = "", rfn[256] = "";
718 int f_opt = 0, d_opt = 1;
721 if(!FIPS_mode_set(1,argv[0]))
723 ERR_load_crypto_strings();
724 ERR_print_errors(BIO_new_fp(stderr,BIO_NOCLOSE));
728 ERR_load_crypto_strings();
731 if (strcasecmp(argv[1], "-d") == 0)
735 else if (strcasecmp(argv[1], "-f") == 0)
742 printf("Invalid parameter: %s\n", argv[1]);
747 printf("Missing parameter\n");
756 { /* list of files (directory) */
757 if (!(fp = fopen(rqlist, "r")))
759 printf("Cannot open req list file\n");
762 while (fgets(fn, sizeof(fn), fp))
766 printf("Processing: %s\n", rfn);
769 printf(">>> Processing failed for: %s <<<\n", rfn);
775 else /* single file */
777 printf("Processing: %s\n", fn);
780 printf(">>> Processing failed for: %s <<<\n", fn);