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>
24 //#define AES_BLOCK_SIZE 16
28 /*-----------------------------------------------*/
30 int DESTest(EVP_CIPHER_CTX *ctx,
31 char *amode, int akeysz, unsigned char *aKey,
33 int dir, /* 0 = decrypt, 1 = encrypt */
34 unsigned char *out, unsigned char *in, int len)
36 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);
64 printf("Invalid key size: %d\n", akeysz);
79 cipher=EVP_des_cfb64();
85 cipher=EVP_des_cfb1();
88 cipher=EVP_des_cfb8();
91 printf("Didn't handle mode %d\n",kt);
94 if(!EVP_CipherInit(ctx, cipher, aKey, iVec, dir))
96 ERR_print_errors_fp(stderr);
99 EVP_Cipher(ctx, out, in, len);
105 /*-----------------------------------------------*/
107 int hex2bin(char *in, int len, unsigned char *out)
112 for (n1 = 0, n2 = 0; n1 < len; )
114 if ((in[n1] >= '0') && (in[n1] <= '9'))
116 else if ((in[n1] >= 'A') && (in[n1] <= 'F'))
117 ch = in[n1++] - 'A' + 10;
118 else if ((in[n1] >= 'a') && (in[n1] <= 'f'))
119 ch = in[n1++] - 'a' + 10;
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;
142 /*-----------------------------------------------*/
144 int bin2hex(unsigned char *in, int len, char *out)
149 for (n1 = 0, n2 = 0; n1 < len; ++n1)
154 out[n2++] = ch + '0';
156 out[n2++] = ch - 10 + 'a';
160 out[n2++] = ch + '0';
162 out[n2++] = ch - 10 + 'a';
167 /* NB: this return the number of _bits_ read */
168 int bint2bin(const char *in, int len, unsigned char *out)
173 for(n=0 ; n < len ; ++n)
175 out[n/8]|=(0x80 >> (n%8));
179 int bin2bint(const unsigned char *in,int len,char *out)
183 for(n=0 ; n < len ; ++n)
184 out[n]=(in[n/8]&(0x80 >> (n%8))) ? '1' : '0';
188 /*-----------------------------------------------*/
190 void PrintValue(char *tag, unsigned char *val, int len)
195 olen = bin2hex(val, len, obuf);
196 printf("%s = %.*s\n", tag, olen, obuf);
200 void DebugValue(char *tag, unsigned char *val, int len)
204 olen = bin2hex(val, len, obuf);
205 printf("%s = %.*s\n", tag, olen, obuf);
208 void OutputValue(char *tag, unsigned char *val, int len, FILE *rfp,int bitmode)
214 olen=bin2bint(val,len,obuf);
216 olen=bin2hex(val,len,obuf);
218 fprintf(rfp, "%s = %.*s\n", tag, olen, obuf);
220 printf("%s = %.*s\n", tag, olen, obuf);
224 void shiftin(unsigned char *dst,unsigned char *src,int nbits)
228 /* move the bytes... */
229 memmove(dst,dst+nbits/8,8-nbits/8);
230 /* append new data */
231 memcpy(dst+8-nbits/8,src,(nbits+7)/8);
232 /* left shift the bits */
234 for(n=0 ; n < 8 ; ++n)
235 dst[n]=(dst[n] << (nbits%8))|(dst[n+1] >> (8-nbits%8));
238 /*-----------------------------------------------*/
239 char *t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"};
240 char *t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"};
241 enum Mode {CBC, ECB, OFB, CFB1, CFB8, CFB64};
242 int Sizes[6]={64,0,64,1,8,64};
243 enum XCrypt {XDECRYPT, XENCRYPT};
245 void do_mct(char *amode,
246 int akeysz, unsigned char *akey,unsigned char *ivec,
247 int dir, unsigned char *text, int len,
251 unsigned char nk[16]; // double size to make the bitshift easier
253 for (imode=0 ; imode < 6 ; ++imode)
254 if(!strcmp(amode,t_mode[imode]))
258 printf("Unrecognized mode: %s\n", amode);
262 for(i=0 ; i < 400 ; ++i)
267 unsigned char old_iv[8];
269 fprintf(rfp,"\nCOUNT = %d\n",i);
270 OutputValue("KEY",akey,akeysz/8,rfp,0);
272 OutputValue("IV",ivec,8,rfp,0);
273 OutputValue(t_tag[dir^1],text,len,rfp,imode == CFB1);
275 /* compensate for endianness */
279 for(j=0 ; j < 10000 ; ++j)
283 memcpy(old_iv,ivec,8);
284 DESTest(&ctx,amode,akeysz,akey,ivec,dir,text,text,len);
288 memcpy(old_iv,ctx.iv,8);
289 EVP_Cipher(&ctx,text,text,len);
293 OutputValue(t_tag[dir],text,len,rfp,imode == CFB1);
294 // memcpy(ivec,text,8);
296 // DebugValue("iv",ctx.iv,8);
297 /* accumulate material for the next key */
298 shiftin(nk,text,Sizes[imode]);
299 // DebugValue("nk",nk,8);
300 if(imode == CFB1 || imode == CFB8 || imode == CBC)
301 memcpy(text,old_iv,8);
303 for(n=0 ; n < 8 ; ++n)
305 memcpy(ivec,ctx.iv,8);
309 int proc_file(char *rqfile)
311 char afn[256], rfn[256];
312 FILE *afp = NULL, *rfp = NULL;
314 int ilen, len, ret = 0;
317 char atest[100] = "";
319 unsigned char iVec[20], aKey[40];
320 int dir = -1, err = 0, step = 0;
321 unsigned char plaintext[2048];
322 unsigned char ciphertext[2048];
326 if (!rqfile || !(*rqfile))
328 printf("No req file\n");
333 if ((afp = fopen(afn, "r")) == NULL)
335 printf("Cannot open file: %s, %s\n",
336 afn, strerror(errno));
340 rp=strstr(rfn,"req/");
343 rp = strstr(rfn, ".req");
344 memcpy(rp, ".rsp", 4);
345 if ((rfp = fopen(rfn, "w")) == NULL)
347 printf("Cannot open file: %s, %s\n",
348 rfn, strerror(errno));
353 while (!err && (fgets(ibuf, sizeof(ibuf), afp)) != NULL)
356 // printf("step=%d ibuf=%s",step,ibuf);
359 case 0: /* read preamble */
361 { /* end of preamble */
362 if ((*algo == '\0') ||
366 printf("Missing Algorithm, Mode or KeySize (%s/%s/%d)\n",
376 else if (ibuf[0] != '#')
378 printf("Invalid preamble item: %s\n", ibuf);
382 { /* process preamble */
383 char *xp, *pp = ibuf+2;
386 { /* insert current time & date */
387 time_t rtim = time(0);
388 fprintf(rfp, "# %s", ctime(&rtim));
393 if(!strncmp(pp,"INVERSE ",8) || !strncmp(pp,"DES ",4)
394 || !strncmp(pp,"PERMUTATION ",12)
395 || !strncmp(pp,"SUBSTITUTION ",13)
396 || !strncmp(pp,"VARIABLE ",9))
400 if(!strncmp(pp,"DES ",4))
402 xp = strchr(pp, ' ');
404 strncpy(atest, pp, n);
407 xp = strrchr(pp, ' '); /* get mode" */
409 strncpy(amode, xp+1, n);
411 /* amode[3] = '\0'; */
412 printf("Test = %s, Mode = %s\n", atest, amode);
414 else if(!strncmp(pp,"State :",7))
420 case 1: /* [ENCRYPT] | [DECRYPT] */
427 if (strncasecmp(ibuf, "[ENCRYPT]", 9) == 0)
429 else if (strncasecmp(ibuf, "[DECRYPT]", 9) == 0)
433 printf("Invalid keyword: %s\n", ibuf);
441 printf("Missing ENCRYPT/DECRYPT keyword\n");
447 case 2: /* KEY = xxxx */
451 if(!strncasecmp(ibuf,"COUNT = ",8))
454 if (strncasecmp(ibuf, "KEY = ", 6) != 0)
456 printf("Missing KEY\n");
461 len = hex2bin((char*)ibuf+6, strlen(ibuf+6)-1, aKey);
464 printf("Invalid KEY\n");
468 PrintValue("KEY", aKey, len);
469 if (strcmp(amode, "ECB") == 0)
471 memset(iVec, 0, sizeof(iVec));
472 step = (dir)? 4: 5; /* no ivec for ECB */
479 case 3: /* IV = xxxx */
481 if (strncasecmp(ibuf, "IV = ", 5) != 0)
483 printf("Missing IV\n");
488 len = hex2bin((char*)ibuf+5, strlen(ibuf+5)-1, iVec);
491 printf("Invalid IV\n");
495 PrintValue("IV", iVec, len);
500 case 4: /* PLAINTEXT = xxxx */
502 if (strncasecmp(ibuf, "PLAINTEXT = ", 12) != 0)
504 printf("Missing PLAINTEXT\n");
509 int nn = strlen(ibuf+12);
510 if(!strcmp(amode,"CFB1"))
511 len=bint2bin(ibuf+12,nn-1,plaintext);
513 len=hex2bin(ibuf+12, nn-1,plaintext);
516 printf("Invalid PLAINTEXT: %s", ibuf+12);
520 if (len >= sizeof(plaintext))
522 printf("Buffer overflow\n");
524 PrintValue("PLAINTEXT", (unsigned char*)plaintext, len);
525 if (strcmp(atest, "Monte") == 0) /* Monte Carlo Test */
527 do_mct(amode,akeysz,aKey,iVec,dir,plaintext,len,rfp);
532 ret = DESTest(&ctx, amode, akeysz, aKey, iVec,
533 dir, /* 0 = decrypt, 1 = encrypt */
534 ciphertext, plaintext, len);
535 OutputValue("CIPHERTEXT",ciphertext,len,rfp,
536 !strcmp(amode,"CFB1"));
542 case 5: /* CIPHERTEXT = xxxx */
544 if (strncasecmp(ibuf, "CIPHERTEXT = ", 13) != 0)
546 printf("Missing KEY\n");
551 if(!strcmp(amode,"CFB1"))
552 len=bint2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
554 len = hex2bin(ibuf+13,strlen(ibuf+13)-1,ciphertext);
557 printf("Invalid CIPHERTEXT\n");
562 PrintValue("CIPHERTEXT", ciphertext, len);
563 if (strcmp(atest, "Monte") == 0) /* Monte Carlo Test */
565 do_mct(amode, akeysz, aKey, iVec,
566 dir, ciphertext, len, rfp);
571 ret = DESTest(&ctx, amode, akeysz, aKey, iVec,
572 dir, /* 0 = decrypt, 1 = encrypt */
573 plaintext, ciphertext, len);
574 OutputValue("PLAINTEXT",(unsigned char *)plaintext,len,rfp,
575 !strcmp(amode,"CFB1"));
585 printf("Missing terminator\n");
587 else if (strcmp(atest, "MCT") != 0)
588 { /* MCT already added terminating nl */
602 /*--------------------------------------------------
603 Processes either a single file or
604 a set of files whose names are passed in a file.
605 A single file is specified as:
607 A set of files is specified as:
608 aes_test -d xxxxx.xxx
609 The default is: -d req.txt
610 --------------------------------------------------*/
611 int main(int argc, char **argv)
613 char *rqlist = "req.txt";
615 char fn[250] = "", rfn[256] = "";
616 int f_opt = 0, d_opt = 1;
621 ERR_load_crypto_strings();
624 if (strcasecmp(argv[1], "-d") == 0)
628 else if (strcasecmp(argv[1], "-f") == 0)
635 printf("Invalid parameter: %s\n", argv[1]);
640 printf("Missing parameter\n");
649 { /* list of files (directory) */
650 if (!(fp = fopen(rqlist, "r")))
652 printf("Cannot open req list file\n");
655 while (fgets(fn, sizeof(fn), fp))
659 printf("Processing: %s\n", rfn);
662 printf(">>> Processing failed for: %s <<<\n", rfn);
668 else /* single file */
670 printf("Processing: %s\n", fn);
673 printf(">>> Processing failed for: %s <<<\n", fn);