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