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 76int 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 91static 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 132static 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 140static 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/*-----------------------------------------------*/ 155char *t_tag[2] = {"PLAINTEXT", "CIPHERTEXT"}; 156char *t_mode[6] = {"CBC","ECB","OFB","CFB1","CFB8","CFB64"}; 157enum Mode {CBC, ECB, OFB, CFB1, CFB8, CFB64}; 158int Sizes[6]={64,64,64,1,8,64}; 159 160static 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 267static 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--------------------------------------------------*/ 626int 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 703