fipstest.c (309987B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <ctype.h> 8 9 #include "secitem.h" 10 #include "blapi.h" 11 #include "nssutil.h" 12 #include "secerr.h" 13 #include "secder.h" 14 #include "secdig.h" 15 #include "secoid.h" 16 #include "ec.h" 17 #include "hasht.h" 18 #include "lowkeyi.h" 19 #include "softoken.h" 20 #include "pkcs11t.h" 21 #define __PASTE(x, y) x##y 22 #undef CK_PKCS11_FUNCTION_INFO 23 #undef CK_NEED_ARG_LIST 24 #define CK_EXTERN extern 25 #define CK_PKCS11_FUNCTION_INFO(func) \ 26 CK_RV __PASTE(NS, func) 27 #define CK_NEED_ARG_LIST 1 28 #include "pkcs11f.h" 29 #undef CK_PKCS11_FUNCTION_INFO 30 #undef CK_NEED_ARG_LIST 31 #undef __PASTE 32 #define SSL3_RANDOM_LENGTH 32 33 34 #if 0 35 #include "../../lib/freebl/mpi/mpi.h" 36 #endif 37 #define MATCH_OPENSSL 1 38 /*#define MATCH_NIST 1 */ 39 #ifdef MATCH_NIST 40 #define VERBOSE_REASON 1 41 #endif 42 43 extern SECStatus 44 EC_DecodeParams(const SECItem *encodedParams, ECParams **ecparams); 45 extern SECStatus 46 EC_CopyParams(PLArenaPool *arena, ECParams *dstParams, 47 const ECParams *srcParams); 48 49 #define ENCRYPT 1 50 #define DECRYPT 0 51 #define BYTE unsigned char 52 #define DEFAULT_RSA_PUBLIC_EXPONENT 0x10001 53 #define RSA_MAX_TEST_MODULUS_BITS 4096 54 #define RSA_MAX_TEST_MODULUS_BYTES RSA_MAX_TEST_MODULUS_BITS / 8 55 #define RSA_MAX_TEST_EXPONENT_BYTES 8 56 #define PQG_TEST_SEED_BYTES 20 57 58 SECStatus 59 hex_to_byteval(const char *c2, unsigned char *byteval) 60 { 61 int i; 62 unsigned char offset; 63 *byteval = 0; 64 for (i = 0; i < 2; i++) { 65 if (c2[i] >= '0' && c2[i] <= '9') { 66 offset = c2[i] - '0'; 67 *byteval |= offset << 4 * (1 - i); 68 } else if (c2[i] >= 'a' && c2[i] <= 'f') { 69 offset = c2[i] - 'a'; 70 *byteval |= (offset + 10) << 4 * (1 - i); 71 } else if (c2[i] >= 'A' && c2[i] <= 'F') { 72 offset = c2[i] - 'A'; 73 *byteval |= (offset + 10) << 4 * (1 - i); 74 } else { 75 return SECFailure; 76 } 77 } 78 return SECSuccess; 79 } 80 81 SECStatus 82 byteval_to_hex(unsigned char byteval, char *c2, char a) 83 { 84 int i; 85 unsigned char offset; 86 for (i = 0; i < 2; i++) { 87 offset = (byteval >> 4 * (1 - i)) & 0x0f; 88 if (offset < 10) { 89 c2[i] = '0' + offset; 90 } else { 91 c2[i] = a + offset - 10; 92 } 93 } 94 return SECSuccess; 95 } 96 97 void 98 to_hex_str(char *str, const unsigned char *buf, unsigned int len) 99 { 100 unsigned int i; 101 for (i = 0; i < len; i++) { 102 byteval_to_hex(buf[i], &str[2 * i], 'a'); 103 } 104 str[2 * len] = '\0'; 105 } 106 107 void 108 to_hex_str_cap(char *str, const unsigned char *buf, unsigned int len) 109 { 110 unsigned int i; 111 for (i = 0; i < len; i++) { 112 byteval_to_hex(buf[i], &str[2 * i], 'A'); 113 } 114 str[2 * len] = '\0'; 115 } 116 117 /* 118 * Convert a string of hex digits (str) to an array (buf) of len bytes. 119 * Return PR_TRUE if the hex string can fit in the byte array. Return 120 * PR_FALSE if the hex string is empty or is too long. 121 */ 122 PRBool 123 from_hex_str(unsigned char *buf, unsigned int len, const char *str) 124 { 125 unsigned int nxdigit; /* number of hex digits in str */ 126 unsigned int i; /* index into buf */ 127 unsigned int j; /* index into str */ 128 129 /* count the hex digits */ 130 nxdigit = 0; 131 for (nxdigit = 0; isxdigit((unsigned char)str[nxdigit]); nxdigit++) { 132 /* empty body */ 133 } 134 if (nxdigit == 0) { 135 return PR_FALSE; 136 } 137 if (nxdigit > 2 * len) { 138 /* 139 * The input hex string is too long, but we allow it if the 140 * extra digits are leading 0's. 141 */ 142 for (j = 0; j < nxdigit - 2 * len; j++) { 143 if (str[j] != '0') { 144 return PR_FALSE; 145 } 146 } 147 /* skip leading 0's */ 148 str += nxdigit - 2 * len; 149 nxdigit = 2 * len; 150 } 151 for (i = 0, j = 0; i < len; i++) { 152 if (2 * i < 2 * len - nxdigit) { 153 /* Handle a short input as if we padded it with leading 0's. */ 154 if (2 * i + 1 < 2 * len - nxdigit) { 155 buf[i] = 0; 156 } else { 157 char tmp[2]; 158 tmp[0] = '0'; 159 tmp[1] = str[j]; 160 hex_to_byteval(tmp, &buf[i]); 161 j++; 162 } 163 } else { 164 hex_to_byteval(&str[j], &buf[i]); 165 j += 2; 166 } 167 } 168 return PR_TRUE; 169 } 170 171 SECStatus 172 tdea_encrypt_buf( 173 int mode, 174 const unsigned char *key, 175 const unsigned char *iv, 176 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 177 const unsigned char *input, unsigned int inputlen) 178 { 179 SECStatus rv = SECFailure; 180 DESContext *cx; 181 unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */ 182 unsigned int doublechecklen = 0; 183 184 cx = DES_CreateContext(key, iv, mode, PR_TRUE); 185 if (cx == NULL) { 186 goto loser; 187 } 188 rv = DES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen); 189 if (rv != SECSuccess) { 190 goto loser; 191 } 192 if (*outputlen != inputlen) { 193 goto loser; 194 } 195 DES_DestroyContext(cx, PR_TRUE); 196 cx = NULL; 197 198 /* 199 * Doublecheck our result by decrypting the ciphertext and 200 * compare the output with the input plaintext. 201 */ 202 cx = DES_CreateContext(key, iv, mode, PR_FALSE); 203 if (cx == NULL) { 204 goto loser; 205 } 206 rv = DES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 207 output, *outputlen); 208 if (rv != SECSuccess) { 209 goto loser; 210 } 211 if (doublechecklen != *outputlen) { 212 goto loser; 213 } 214 DES_DestroyContext(cx, PR_TRUE); 215 cx = NULL; 216 if (memcmp(doublecheck, input, inputlen) != 0) { 217 goto loser; 218 } 219 rv = SECSuccess; 220 221 loser: 222 if (cx != NULL) { 223 DES_DestroyContext(cx, PR_TRUE); 224 } 225 return rv; 226 } 227 228 SECStatus 229 tdea_decrypt_buf( 230 int mode, 231 const unsigned char *key, 232 const unsigned char *iv, 233 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 234 const unsigned char *input, unsigned int inputlen) 235 { 236 SECStatus rv = SECFailure; 237 DESContext *cx; 238 unsigned char doublecheck[8 * 20]; /* 1 to 20 blocks */ 239 unsigned int doublechecklen = 0; 240 241 cx = DES_CreateContext(key, iv, mode, PR_FALSE); 242 if (cx == NULL) { 243 goto loser; 244 } 245 rv = DES_Decrypt(cx, output, outputlen, maxoutputlen, 246 input, inputlen); 247 if (rv != SECSuccess) { 248 goto loser; 249 } 250 if (*outputlen != inputlen) { 251 goto loser; 252 } 253 DES_DestroyContext(cx, PR_TRUE); 254 cx = NULL; 255 256 /* 257 * Doublecheck our result by encrypting the plaintext and 258 * compare the output with the input ciphertext. 259 */ 260 cx = DES_CreateContext(key, iv, mode, PR_TRUE); 261 if (cx == NULL) { 262 goto loser; 263 } 264 rv = DES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 265 output, *outputlen); 266 if (rv != SECSuccess) { 267 goto loser; 268 } 269 if (doublechecklen != *outputlen) { 270 goto loser; 271 } 272 DES_DestroyContext(cx, PR_TRUE); 273 cx = NULL; 274 if (memcmp(doublecheck, input, inputlen) != 0) { 275 goto loser; 276 } 277 rv = SECSuccess; 278 279 loser: 280 if (cx != NULL) { 281 DES_DestroyContext(cx, PR_TRUE); 282 } 283 return rv; 284 } 285 286 /* 287 * Perform the TDEA Known Answer Test (KAT) or Multi-block Message 288 * Test (MMT) in ECB or CBC mode. The KAT (there are five types) 289 * and MMT have the same structure: given the key and IV (CBC mode 290 * only), encrypt the given plaintext or decrypt the given ciphertext. 291 * So we can handle them the same way. 292 * 293 * reqfn is the pathname of the REQUEST file. 294 * 295 * The output RESPONSE file is written to stdout. 296 */ 297 void 298 tdea_kat_mmt(char *reqfn) 299 { 300 char buf[180]; /* holds one line from the input REQUEST file. 301 * needs to be large enough to hold the longest 302 * line "CIPHERTEXT = <180 hex digits>\n". 303 */ 304 FILE *req; /* input stream from the REQUEST file */ 305 FILE *resp; /* output stream to the RESPONSE file */ 306 int i, j; 307 int mode = NSS_DES_EDE3; /* NSS_DES_EDE3 (ECB) or NSS_DES_EDE3_CBC */ 308 int crypt = DECRYPT; /* 1 means encrypt, 0 means decrypt */ 309 unsigned char key[24]; /* TDEA 3 key bundle */ 310 unsigned int numKeys = 0; 311 unsigned char iv[8]; /* for all modes except ECB */ 312 unsigned char plaintext[8 * 20]; /* 1 to 20 blocks */ 313 unsigned int plaintextlen; 314 unsigned char ciphertext[8 * 20]; /* 1 to 20 blocks */ 315 unsigned int ciphertextlen; 316 SECStatus rv; 317 318 req = fopen(reqfn, "r"); 319 resp = stdout; 320 while (fgets(buf, sizeof buf, req) != NULL) { 321 /* a comment or blank line */ 322 if (buf[0] == '#' || buf[0] == '\n') { 323 fputs(buf, resp); 324 continue; 325 } 326 /* [ENCRYPT] or [DECRYPT] */ 327 if (buf[0] == '[') { 328 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 329 crypt = ENCRYPT; 330 } else { 331 crypt = DECRYPT; 332 } 333 fputs(buf, resp); 334 continue; 335 } 336 /* NumKeys */ 337 if (strncmp(&buf[0], "NumKeys", 7) == 0) { 338 i = 7; 339 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 340 i++; 341 } 342 numKeys = buf[i]; 343 fputs(buf, resp); 344 continue; 345 } 346 /* "COUNT = x" begins a new data set */ 347 if (strncmp(buf, "COUNT", 5) == 0) { 348 /* mode defaults to ECB, if dataset has IV mode will be set CBC */ 349 mode = NSS_DES_EDE3; 350 /* zeroize the variables for the test with this data set */ 351 memset(key, 0, sizeof key); 352 memset(iv, 0, sizeof iv); 353 memset(plaintext, 0, sizeof plaintext); 354 plaintextlen = 0; 355 memset(ciphertext, 0, sizeof ciphertext); 356 ciphertextlen = 0; 357 fputs(buf, resp); 358 continue; 359 } 360 if (numKeys == 0) { 361 if (strncmp(buf, "KEYs", 4) == 0) { 362 i = 4; 363 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 364 i++; 365 } 366 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 367 hex_to_byteval(&buf[i], &key[j]); 368 key[j + 8] = key[j]; 369 key[j + 16] = key[j]; 370 } 371 fputs(buf, resp); 372 continue; 373 } 374 } else { 375 /* KEY1 = ... */ 376 if (strncmp(buf, "KEY1", 4) == 0) { 377 i = 4; 378 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 379 i++; 380 } 381 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 382 hex_to_byteval(&buf[i], &key[j]); 383 } 384 fputs(buf, resp); 385 continue; 386 } 387 /* KEY2 = ... */ 388 if (strncmp(buf, "KEY2", 4) == 0) { 389 i = 4; 390 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 391 i++; 392 } 393 for (j = 8; isxdigit((unsigned char)buf[i]); i += 2, j++) { 394 hex_to_byteval(&buf[i], &key[j]); 395 } 396 fputs(buf, resp); 397 continue; 398 } 399 /* KEY3 = ... */ 400 if (strncmp(buf, "KEY3", 4) == 0) { 401 i = 4; 402 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 403 i++; 404 } 405 for (j = 16; isxdigit((unsigned char)buf[i]); i += 2, j++) { 406 hex_to_byteval(&buf[i], &key[j]); 407 } 408 fputs(buf, resp); 409 continue; 410 } 411 } 412 413 /* IV = ... */ 414 if (strncmp(buf, "IV", 2) == 0) { 415 mode = NSS_DES_EDE3_CBC; 416 i = 2; 417 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 418 i++; 419 } 420 for (j = 0; j < sizeof iv; i += 2, j++) { 421 hex_to_byteval(&buf[i], &iv[j]); 422 } 423 fputs(buf, resp); 424 continue; 425 } 426 427 /* PLAINTEXT = ... */ 428 if (strncmp(buf, "PLAINTEXT", 9) == 0) { 429 /* sanity check */ 430 if (crypt != ENCRYPT) { 431 goto loser; 432 } 433 i = 9; 434 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 435 i++; 436 } 437 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 438 hex_to_byteval(&buf[i], &plaintext[j]); 439 } 440 plaintextlen = j; 441 rv = tdea_encrypt_buf(mode, key, 442 (mode == NSS_DES_EDE3) ? NULL : iv, 443 ciphertext, &ciphertextlen, sizeof ciphertext, 444 plaintext, plaintextlen); 445 if (rv != SECSuccess) { 446 goto loser; 447 } 448 449 fputs(buf, resp); 450 fputs("CIPHERTEXT = ", resp); 451 to_hex_str(buf, ciphertext, ciphertextlen); 452 fputs(buf, resp); 453 fputc('\n', resp); 454 continue; 455 } 456 /* CIPHERTEXT = ... */ 457 if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 458 /* sanity check */ 459 if (crypt != DECRYPT) { 460 goto loser; 461 } 462 463 i = 10; 464 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 465 i++; 466 } 467 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 468 hex_to_byteval(&buf[i], &ciphertext[j]); 469 } 470 ciphertextlen = j; 471 472 rv = tdea_decrypt_buf(mode, key, 473 (mode == NSS_DES_EDE3) ? NULL : iv, 474 plaintext, &plaintextlen, sizeof plaintext, 475 ciphertext, ciphertextlen); 476 if (rv != SECSuccess) { 477 goto loser; 478 } 479 480 fputs(buf, resp); 481 fputs("PLAINTEXT = ", resp); 482 to_hex_str(buf, plaintext, plaintextlen); 483 fputs(buf, resp); 484 fputc('\n', resp); 485 continue; 486 } 487 } 488 489 loser: 490 fclose(req); 491 } 492 493 /* 494 * Set the parity bit for the given byte 495 */ 496 BYTE 497 odd_parity(BYTE in) 498 { 499 BYTE out = in; 500 in ^= in >> 4; 501 in ^= in >> 2; 502 in ^= in >> 1; 503 return (BYTE)(out ^ !(in & 1)); 504 } 505 506 /* 507 * Generate Keys [i+1] from Key[i], PT/CT[j-2], PT/CT[j-1], and PT/CT[j] 508 * for TDEA Monte Carlo Test (MCT) in ECB and CBC modes. 509 */ 510 void 511 tdea_mct_next_keys(unsigned char *key, 512 const unsigned char *text_2, const unsigned char *text_1, 513 const unsigned char *text, unsigned int numKeys) 514 { 515 int k; 516 517 /* key1[i+1] = key1[i] xor PT/CT[j] */ 518 for (k = 0; k < 8; k++) { 519 key[k] ^= text[k]; 520 } 521 /* key2 */ 522 if (numKeys == 2 || numKeys == 3) { 523 /* key2 independent */ 524 for (k = 8; k < 16; k++) { 525 /* key2[i+1] = KEY2[i] xor PT/CT[j-1] */ 526 key[k] ^= text_1[k - 8]; 527 } 528 } else { 529 /* key2 == key 1 */ 530 for (k = 8; k < 16; k++) { 531 /* key2[i+1] = KEY2[i] xor PT/CT[j] */ 532 key[k] = key[k - 8]; 533 } 534 } 535 /* key3 */ 536 if (numKeys == 1 || numKeys == 2) { 537 /* key3 == key 1 */ 538 for (k = 16; k < 24; k++) { 539 /* key3[i+1] = KEY3[i] xor PT/CT[j] */ 540 key[k] = key[k - 16]; 541 } 542 } else { 543 /* key3 independent */ 544 for (k = 16; k < 24; k++) { 545 /* key3[i+1] = KEY3[i] xor PT/CT[j-2] */ 546 key[k] ^= text_2[k - 16]; 547 } 548 } 549 /* set the parity bits */ 550 for (k = 0; k < 24; k++) { 551 key[k] = odd_parity(key[k]); 552 } 553 } 554 555 /* 556 * Perform the Monte Carlo Test 557 * 558 * mode = NSS_DES_EDE3 or NSS_DES_EDE3_CBC 559 * crypt = ENCRYPT || DECRYPT 560 * inputtext = plaintext or Cyphertext depending on the value of crypt 561 * inputlength is expected to be size 8 bytes 562 * iv = needs to be set for NSS_DES_EDE3_CBC mode 563 * resp = is the output response file. 564 */ 565 void 566 tdea_mct_test(int mode, unsigned char *key, unsigned int numKeys, 567 unsigned int crypt, unsigned char *inputtext, 568 unsigned int inputlength, unsigned char *iv, FILE *resp) 569 { 570 571 int i, j; 572 unsigned char outputtext_1[8]; /* PT/CT[j-1] */ 573 unsigned char outputtext_2[8]; /* PT/CT[j-2] */ 574 char buf[80]; /* holds one line from the input REQUEST file. */ 575 unsigned int outputlen; 576 unsigned char outputtext[8]; 577 578 SECStatus rv; 579 580 if (mode == NSS_DES_EDE3 && iv != NULL) { 581 printf("IV must be NULL for NSS_DES_EDE3 mode"); 582 goto loser; 583 } else if (mode == NSS_DES_EDE3_CBC && iv == NULL) { 584 printf("IV must not be NULL for NSS_DES_EDE3_CBC mode"); 585 goto loser; 586 } 587 588 /* loop 400 times */ 589 for (i = 0; i < 400; i++) { 590 /* if i == 0 CV[0] = IV not necessary */ 591 /* record the count and key values and plainText */ 592 snprintf(buf, sizeof(buf), "COUNT = %d\n", i); 593 fputs(buf, resp); 594 /* Output KEY1[i] */ 595 fputs("KEY1 = ", resp); 596 to_hex_str(buf, key, 8); 597 fputs(buf, resp); 598 fputc('\n', resp); 599 /* Output KEY2[i] */ 600 fputs("KEY2 = ", resp); 601 to_hex_str(buf, &key[8], 8); 602 fputs(buf, resp); 603 fputc('\n', resp); 604 /* Output KEY3[i] */ 605 fputs("KEY3 = ", resp); 606 to_hex_str(buf, &key[16], 8); 607 fputs(buf, resp); 608 fputc('\n', resp); 609 if (mode == NSS_DES_EDE3_CBC) { 610 /* Output CV[i] */ 611 fputs("IV = ", resp); 612 to_hex_str(buf, iv, 8); 613 fputs(buf, resp); 614 fputc('\n', resp); 615 } 616 if (crypt == ENCRYPT) { 617 /* Output PT[0] */ 618 fputs("PLAINTEXT = ", resp); 619 } else { 620 /* Output CT[0] */ 621 fputs("CIPHERTEXT = ", resp); 622 } 623 624 to_hex_str(buf, inputtext, inputlength); 625 fputs(buf, resp); 626 fputc('\n', resp); 627 628 /* loop 10,000 times */ 629 for (j = 0; j < 10000; j++) { 630 631 outputlen = 0; 632 if (crypt == ENCRYPT) { 633 /* inputtext == ciphertext outputtext == plaintext*/ 634 rv = tdea_encrypt_buf(mode, key, 635 (mode == 636 NSS_DES_EDE3) 637 ? NULL 638 : iv, 639 outputtext, &outputlen, 8, 640 inputtext, 8); 641 } else { 642 /* inputtext == plaintext outputtext == ciphertext */ 643 rv = tdea_decrypt_buf(mode, key, 644 (mode == 645 NSS_DES_EDE3) 646 ? NULL 647 : iv, 648 outputtext, &outputlen, 8, 649 inputtext, 8); 650 } 651 652 if (rv != SECSuccess) { 653 goto loser; 654 } 655 if (outputlen != inputlength) { 656 goto loser; 657 } 658 659 if (mode == NSS_DES_EDE3_CBC) { 660 if (crypt == ENCRYPT) { 661 if (j == 0) { 662 /*P[j+1] = CV[0] */ 663 memcpy(inputtext, iv, 8); 664 } else { 665 /* p[j+1] = C[j-1] */ 666 memcpy(inputtext, outputtext_1, 8); 667 } 668 /* CV[j+1] = C[j] */ 669 memcpy(iv, outputtext, 8); 670 if (j != 9999) { 671 /* save C[j-1] */ 672 memcpy(outputtext_1, outputtext, 8); 673 } 674 } else { /* DECRYPT */ 675 /* CV[j+1] = C[j] */ 676 memcpy(iv, inputtext, 8); 677 /* C[j+1] = P[j] */ 678 memcpy(inputtext, outputtext, 8); 679 } 680 } else { 681 /* ECB mode PT/CT[j+1] = CT/PT[j] */ 682 memcpy(inputtext, outputtext, 8); 683 } 684 685 /* Save PT/CT[j-2] and PT/CT[j-1] */ 686 if (j == 9997) 687 memcpy(outputtext_2, outputtext, 8); 688 if (j == 9998) 689 memcpy(outputtext_1, outputtext, 8); 690 /* done at the end of the for(j) loop */ 691 } 692 693 if (crypt == ENCRYPT) { 694 /* Output CT[j] */ 695 fputs("CIPHERTEXT = ", resp); 696 } else { 697 /* Output PT[j] */ 698 fputs("PLAINTEXT = ", resp); 699 } 700 to_hex_str(buf, outputtext, 8); 701 fputs(buf, resp); 702 fputc('\n', resp); 703 704 /* Key[i+1] = Key[i] xor ... outputtext_2 == PT/CT[j-2] 705 * outputtext_1 == PT/CT[j-1] outputtext == PT/CT[j] 706 */ 707 tdea_mct_next_keys(key, outputtext_2, 708 outputtext_1, outputtext, numKeys); 709 710 if (mode == NSS_DES_EDE3_CBC) { 711 /* taken care of in the j=9999 iteration */ 712 if (crypt == ENCRYPT) { 713 /* P[i] = C[j-1] */ 714 /* CV[i] = C[j] */ 715 } else { 716 /* taken care of in the j=9999 iteration */ 717 /* CV[i] = C[j] */ 718 /* C[i] = P[j] */ 719 } 720 } else { 721 /* ECB PT/CT[i] = PT/CT[j] */ 722 memcpy(inputtext, outputtext, 8); 723 } 724 /* done at the end of the for(i) loop */ 725 fputc('\n', resp); 726 } 727 728 loser: 729 return; 730 } 731 732 /* 733 * Perform the TDEA Monte Carlo Test (MCT) in ECB/CBC modes. 734 * by gathering the input from the request file, and then 735 * calling tdea_mct_test. 736 * 737 * reqfn is the pathname of the input REQUEST file. 738 * 739 * The output RESPONSE file is written to stdout. 740 */ 741 void 742 tdea_mct(int mode, char *reqfn) 743 { 744 int i, j; 745 char buf[80]; /* holds one line from the input REQUEST file. */ 746 FILE *req; /* input stream from the REQUEST file */ 747 FILE *resp; /* output stream to the RESPONSE file */ 748 unsigned int crypt = 0; /* 1 means encrypt, 0 means decrypt */ 749 unsigned char key[24]; /* TDEA 3 key bundle */ 750 unsigned int numKeys = 0; 751 unsigned char plaintext[8]; /* PT[j] */ 752 unsigned char ciphertext[8]; /* CT[j] */ 753 unsigned char iv[8]; 754 755 /* zeroize the variables for the test with this data set */ 756 memset(key, 0, sizeof key); 757 memset(plaintext, 0, sizeof plaintext); 758 memset(ciphertext, 0, sizeof ciphertext); 759 memset(iv, 0, sizeof iv); 760 761 req = fopen(reqfn, "r"); 762 resp = stdout; 763 while (fgets(buf, sizeof buf, req) != NULL) { 764 /* a comment or blank line */ 765 if (buf[0] == '#' || buf[0] == '\n') { 766 fputs(buf, resp); 767 continue; 768 } 769 /* [ENCRYPT] or [DECRYPT] */ 770 if (buf[0] == '[') { 771 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 772 crypt = ENCRYPT; 773 } else { 774 crypt = DECRYPT; 775 } 776 fputs(buf, resp); 777 continue; 778 } 779 /* NumKeys */ 780 if (strncmp(&buf[0], "NumKeys", 7) == 0) { 781 i = 7; 782 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 783 i++; 784 } 785 numKeys = atoi(&buf[i]); 786 continue; 787 } 788 /* KEY1 = ... */ 789 if (strncmp(buf, "KEY1", 4) == 0) { 790 i = 4; 791 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 792 i++; 793 } 794 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 795 hex_to_byteval(&buf[i], &key[j]); 796 } 797 continue; 798 } 799 /* KEY2 = ... */ 800 if (strncmp(buf, "KEY2", 4) == 0) { 801 i = 4; 802 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 803 i++; 804 } 805 for (j = 8; isxdigit((unsigned char)buf[i]); i += 2, j++) { 806 hex_to_byteval(&buf[i], &key[j]); 807 } 808 continue; 809 } 810 /* KEY3 = ... */ 811 if (strncmp(buf, "KEY3", 4) == 0) { 812 i = 4; 813 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 814 i++; 815 } 816 for (j = 16; isxdigit((unsigned char)buf[i]); i += 2, j++) { 817 hex_to_byteval(&buf[i], &key[j]); 818 } 819 continue; 820 } 821 822 /* IV = ... */ 823 if (strncmp(buf, "IV", 2) == 0) { 824 i = 2; 825 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 826 i++; 827 } 828 for (j = 0; j < sizeof iv; i += 2, j++) { 829 hex_to_byteval(&buf[i], &iv[j]); 830 } 831 continue; 832 } 833 834 /* PLAINTEXT = ... */ 835 if (strncmp(buf, "PLAINTEXT", 9) == 0) { 836 837 /* sanity check */ 838 if (crypt != ENCRYPT) { 839 goto loser; 840 } 841 /* PT[0] = PT */ 842 i = 9; 843 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 844 i++; 845 } 846 for (j = 0; j < sizeof plaintext; i += 2, j++) { 847 hex_to_byteval(&buf[i], &plaintext[j]); 848 } 849 850 /* do the Monte Carlo test */ 851 if (mode == NSS_DES_EDE3) { 852 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, plaintext, sizeof plaintext, NULL, resp); 853 } else { 854 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, plaintext, sizeof plaintext, iv, resp); 855 } 856 continue; 857 } 858 /* CIPHERTEXT = ... */ 859 if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 860 /* sanity check */ 861 if (crypt != DECRYPT) { 862 goto loser; 863 } 864 /* CT[0] = CT */ 865 i = 10; 866 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 867 i++; 868 } 869 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 870 hex_to_byteval(&buf[i], &ciphertext[j]); 871 } 872 873 /* do the Monte Carlo test */ 874 if (mode == NSS_DES_EDE3) { 875 tdea_mct_test(NSS_DES_EDE3, key, numKeys, crypt, ciphertext, sizeof ciphertext, NULL, resp); 876 } else { 877 tdea_mct_test(NSS_DES_EDE3_CBC, key, numKeys, crypt, ciphertext, sizeof ciphertext, iv, resp); 878 } 879 continue; 880 } 881 } 882 883 loser: 884 fclose(req); 885 } 886 887 SECStatus 888 aes_encrypt_buf( 889 int mode, 890 const unsigned char *key, unsigned int keysize, 891 const unsigned char *iv, 892 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 893 const unsigned char *input, unsigned int inputlen) 894 { 895 SECStatus rv = SECFailure; 896 AESContext *cx; 897 unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */ 898 unsigned int doublechecklen = 0; 899 900 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16); 901 if (cx == NULL) { 902 goto loser; 903 } 904 rv = AES_Encrypt(cx, output, outputlen, maxoutputlen, input, inputlen); 905 if (rv != SECSuccess) { 906 goto loser; 907 } 908 if (*outputlen != inputlen) { 909 goto loser; 910 } 911 AES_DestroyContext(cx, PR_TRUE); 912 cx = NULL; 913 914 /* 915 * Doublecheck our result by decrypting the ciphertext and 916 * compare the output with the input plaintext. 917 */ 918 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16); 919 if (cx == NULL) { 920 goto loser; 921 } 922 rv = AES_Decrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 923 output, *outputlen); 924 if (rv != SECSuccess) { 925 goto loser; 926 } 927 if (doublechecklen != *outputlen) { 928 goto loser; 929 } 930 AES_DestroyContext(cx, PR_TRUE); 931 cx = NULL; 932 if (memcmp(doublecheck, input, inputlen) != 0) { 933 goto loser; 934 } 935 rv = SECSuccess; 936 937 loser: 938 if (cx != NULL) { 939 AES_DestroyContext(cx, PR_TRUE); 940 } 941 return rv; 942 } 943 944 SECStatus 945 aes_decrypt_buf( 946 int mode, 947 const unsigned char *key, unsigned int keysize, 948 const unsigned char *iv, 949 unsigned char *output, unsigned int *outputlen, unsigned int maxoutputlen, 950 const unsigned char *input, unsigned int inputlen) 951 { 952 SECStatus rv = SECFailure; 953 AESContext *cx; 954 unsigned char doublecheck[10 * 16]; /* 1 to 10 blocks */ 955 unsigned int doublechecklen = 0; 956 957 cx = AES_CreateContext(key, iv, mode, PR_FALSE, keysize, 16); 958 if (cx == NULL) { 959 goto loser; 960 } 961 rv = AES_Decrypt(cx, output, outputlen, maxoutputlen, 962 input, inputlen); 963 if (rv != SECSuccess) { 964 goto loser; 965 } 966 if (*outputlen != inputlen) { 967 goto loser; 968 } 969 AES_DestroyContext(cx, PR_TRUE); 970 cx = NULL; 971 972 /* 973 * Doublecheck our result by encrypting the plaintext and 974 * compare the output with the input ciphertext. 975 */ 976 cx = AES_CreateContext(key, iv, mode, PR_TRUE, keysize, 16); 977 if (cx == NULL) { 978 goto loser; 979 } 980 rv = AES_Encrypt(cx, doublecheck, &doublechecklen, sizeof doublecheck, 981 output, *outputlen); 982 if (rv != SECSuccess) { 983 goto loser; 984 } 985 if (doublechecklen != *outputlen) { 986 goto loser; 987 } 988 AES_DestroyContext(cx, PR_TRUE); 989 cx = NULL; 990 if (memcmp(doublecheck, input, inputlen) != 0) { 991 goto loser; 992 } 993 rv = SECSuccess; 994 995 loser: 996 if (cx != NULL) { 997 AES_DestroyContext(cx, PR_TRUE); 998 } 999 return rv; 1000 } 1001 /* 1002 * Perform the AES GCM tests. 1003 * 1004 * reqfn is the pathname of the REQUEST file. 1005 * 1006 * The output RESPONSE file is written to stdout. 1007 */ 1008 void 1009 aes_gcm(char *reqfn, int encrypt) 1010 { 1011 char buf[512]; /* holds one line from the input REQUEST file. 1012 * needs to be large enough to hold the longest 1013 * line "CIPHERTEXT = <320 hex digits>\n". 1014 */ 1015 FILE *aesreq; /* input stream from the REQUEST file */ 1016 FILE *aesresp; /* output stream to the RESPONSE file */ 1017 int i, j; 1018 unsigned char key[32]; /* 128, 192, or 256 bits */ 1019 unsigned int keysize = 0; 1020 unsigned char iv[128]; /* handle large gcm IV's */ 1021 unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */ 1022 unsigned int plaintextlen; 1023 unsigned char ciphertext[11 * 16]; /* 1 to 10 blocks + tag */ 1024 unsigned int ciphertextlen; 1025 unsigned char aad[11 * 16]; /* 1 to 10 blocks + tag */ 1026 unsigned int aadlen = 0; 1027 unsigned int tagbits; 1028 unsigned int taglen = 0; 1029 unsigned int ivlen; 1030 CK_NSS_GCM_PARAMS params; 1031 SECStatus rv; 1032 1033 aesreq = fopen(reqfn, "r"); 1034 aesresp = stdout; 1035 while (fgets(buf, sizeof buf, aesreq) != NULL) { 1036 /* a comment or blank line */ 1037 if (buf[0] == '#' || buf[0] == '\n') { 1038 fputs(buf, aesresp); 1039 continue; 1040 } 1041 /* [ENCRYPT] or [DECRYPT] */ 1042 if (buf[0] == '[') { 1043 if (strncmp(buf, "[Taglen", 7) == 0) { 1044 if (sscanf(buf, "[Taglen = %d]", &tagbits) != 1) { 1045 goto loser; 1046 } 1047 taglen = tagbits / 8; 1048 } 1049 if (strncmp(buf, "[IVlen", 6) == 0) { 1050 if (sscanf(buf, "[IVlen = %d]", &ivlen) != 1) { 1051 goto loser; 1052 } 1053 ivlen = ivlen / 8; 1054 } 1055 fputs(buf, aesresp); 1056 continue; 1057 } 1058 /* "COUNT = x" begins a new data set */ 1059 if (strncmp(buf, "Count", 5) == 0) { 1060 /* zeroize the variables for the test with this data set */ 1061 memset(key, 0, sizeof key); 1062 keysize = 0; 1063 memset(iv, 0, sizeof iv); 1064 memset(plaintext, 0, sizeof plaintext); 1065 plaintextlen = 0; 1066 memset(ciphertext, 0, sizeof ciphertext); 1067 ciphertextlen = 0; 1068 fputs(buf, aesresp); 1069 continue; 1070 } 1071 /* KEY = ... */ 1072 if (strncmp(buf, "Key", 3) == 0) { 1073 i = 3; 1074 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1075 i++; 1076 } 1077 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1078 hex_to_byteval(&buf[i], &key[j]); 1079 } 1080 keysize = j; 1081 fputs(buf, aesresp); 1082 continue; 1083 } 1084 /* IV = ... */ 1085 if (strncmp(buf, "IV", 2) == 0) { 1086 i = 2; 1087 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1088 i++; 1089 } 1090 for (j = 0; j < sizeof iv; i += 2, j++) { 1091 hex_to_byteval(&buf[i], &iv[j]); 1092 } 1093 fputs(buf, aesresp); 1094 continue; 1095 } 1096 /* PLAINTEXT = ... */ 1097 if (strncmp(buf, "PT", 2) == 0) { 1098 /* sanity check */ 1099 if (!encrypt) { 1100 goto loser; 1101 } 1102 1103 i = 2; 1104 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1105 i++; 1106 } 1107 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1108 hex_to_byteval(&buf[i], &plaintext[j]); 1109 } 1110 plaintextlen = j; 1111 fputs(buf, aesresp); 1112 continue; 1113 } 1114 /* CIPHERTEXT = ... */ 1115 if (strncmp(buf, "CT", 2) == 0) { 1116 /* sanity check */ 1117 if (encrypt) { 1118 goto loser; 1119 } 1120 1121 i = 2; 1122 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1123 i++; 1124 } 1125 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1126 hex_to_byteval(&buf[i], &ciphertext[j]); 1127 } 1128 ciphertextlen = j; 1129 fputs(buf, aesresp); 1130 continue; 1131 } 1132 if (strncmp(buf, "AAD", 3) == 0) { 1133 i = 3; 1134 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1135 i++; 1136 } 1137 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1138 hex_to_byteval(&buf[i], &aad[j]); 1139 } 1140 aadlen = j; 1141 fputs(buf, aesresp); 1142 if (encrypt) { 1143 if (encrypt == 2) { 1144 rv = RNG_GenerateGlobalRandomBytes(iv, ivlen); 1145 if (rv != SECSuccess) { 1146 goto loser; 1147 } 1148 } 1149 params.pIv = iv; 1150 params.ulIvLen = ivlen; 1151 params.pAAD = aad; 1152 params.ulAADLen = aadlen; 1153 params.ulTagBits = tagbits; 1154 rv = aes_encrypt_buf(NSS_AES_GCM, key, keysize, 1155 (unsigned char *)¶ms, 1156 ciphertext, &ciphertextlen, sizeof ciphertext, 1157 plaintext, plaintextlen); 1158 if (rv != SECSuccess) { 1159 goto loser; 1160 } 1161 1162 if (encrypt == 2) { 1163 fputs("IV = ", aesresp); 1164 to_hex_str(buf, iv, ivlen); 1165 fputs(buf, aesresp); 1166 fputc('\n', aesresp); 1167 } 1168 fputs("CT = ", aesresp); 1169 j = ciphertextlen - taglen; 1170 to_hex_str(buf, ciphertext, j); 1171 fputs(buf, aesresp); 1172 fputs("\nTag = ", aesresp); 1173 to_hex_str(buf, ciphertext + j, taglen); 1174 fputs(buf, aesresp); 1175 fputc('\n', aesresp); 1176 } 1177 continue; 1178 } 1179 if (strncmp(buf, "Tag", 3) == 0) { 1180 /* sanity check */ 1181 if (encrypt) { 1182 goto loser; 1183 } 1184 1185 i = 3; 1186 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1187 i++; 1188 } 1189 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1190 hex_to_byteval(&buf[i], &ciphertext[j + ciphertextlen]); 1191 } 1192 ciphertextlen += j; 1193 params.pIv = iv; 1194 params.ulIvLen = ivlen; 1195 params.pAAD = aad; 1196 params.ulAADLen = aadlen; 1197 params.ulTagBits = tagbits; 1198 rv = aes_decrypt_buf(NSS_AES_GCM, key, keysize, 1199 (unsigned char *)¶ms, 1200 plaintext, &plaintextlen, sizeof plaintext, 1201 ciphertext, ciphertextlen); 1202 fputs(buf, aesresp); 1203 if (rv != SECSuccess) { 1204 fprintf(aesresp, "FAIL\n"); 1205 } else { 1206 fputs("PT = ", aesresp); 1207 to_hex_str(buf, plaintext, plaintextlen); 1208 fputs(buf, aesresp); 1209 fputc('\n', aesresp); 1210 } 1211 continue; 1212 } 1213 } 1214 loser: 1215 fclose(aesreq); 1216 } 1217 1218 /* 1219 * Perform the AES Known Answer Test (KAT) or Multi-block Message 1220 * Test (MMT) in ECB or CBC mode. The KAT (there are four types) 1221 * and MMT have the same structure: given the key and IV (CBC mode 1222 * only), encrypt the given plaintext or decrypt the given ciphertext. 1223 * So we can handle them the same way. 1224 * 1225 * reqfn is the pathname of the REQUEST file. 1226 * 1227 * The output RESPONSE file is written to stdout. 1228 */ 1229 void 1230 aes_kat_mmt(char *reqfn) 1231 { 1232 char buf[512]; /* holds one line from the input REQUEST file. 1233 * needs to be large enough to hold the longest 1234 * line "CIPHERTEXT = <320 hex digits>\n". 1235 */ 1236 FILE *aesreq; /* input stream from the REQUEST file */ 1237 FILE *aesresp; /* output stream to the RESPONSE file */ 1238 int i, j; 1239 int mode = NSS_AES; /* NSS_AES (ECB) or NSS_AES_CBC */ 1240 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1241 unsigned char key[32]; /* 128, 192, or 256 bits */ 1242 unsigned int keysize = 0; 1243 unsigned char iv[16]; /* for all modes except ECB */ 1244 unsigned char plaintext[10 * 16]; /* 1 to 10 blocks */ 1245 unsigned int plaintextlen; 1246 unsigned char ciphertext[10 * 16]; /* 1 to 10 blocks */ 1247 unsigned int ciphertextlen; 1248 SECStatus rv; 1249 1250 aesreq = fopen(reqfn, "r"); 1251 aesresp = stdout; 1252 while (fgets(buf, sizeof buf, aesreq) != NULL) { 1253 /* a comment or blank line */ 1254 if (buf[0] == '#' || buf[0] == '\n') { 1255 fputs(buf, aesresp); 1256 continue; 1257 } 1258 /* [ENCRYPT] or [DECRYPT] */ 1259 if (buf[0] == '[') { 1260 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1261 encrypt = 1; 1262 } else { 1263 encrypt = 0; 1264 } 1265 fputs(buf, aesresp); 1266 continue; 1267 } 1268 /* "COUNT = x" begins a new data set */ 1269 if (strncmp(buf, "COUNT", 5) == 0) { 1270 mode = NSS_AES; 1271 /* zeroize the variables for the test with this data set */ 1272 memset(key, 0, sizeof key); 1273 keysize = 0; 1274 memset(iv, 0, sizeof iv); 1275 memset(plaintext, 0, sizeof plaintext); 1276 plaintextlen = 0; 1277 memset(ciphertext, 0, sizeof ciphertext); 1278 ciphertextlen = 0; 1279 fputs(buf, aesresp); 1280 continue; 1281 } 1282 /* KEY = ... */ 1283 if (strncmp(buf, "KEY", 3) == 0) { 1284 i = 3; 1285 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1286 i++; 1287 } 1288 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1289 hex_to_byteval(&buf[i], &key[j]); 1290 } 1291 keysize = j; 1292 fputs(buf, aesresp); 1293 continue; 1294 } 1295 /* IV = ... */ 1296 if (strncmp(buf, "IV", 2) == 0) { 1297 mode = NSS_AES_CBC; 1298 i = 2; 1299 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1300 i++; 1301 } 1302 for (j = 0; j < sizeof iv; i += 2, j++) { 1303 hex_to_byteval(&buf[i], &iv[j]); 1304 } 1305 fputs(buf, aesresp); 1306 continue; 1307 } 1308 /* PLAINTEXT = ... */ 1309 if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1310 /* sanity check */ 1311 if (!encrypt) { 1312 goto loser; 1313 } 1314 1315 i = 9; 1316 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1317 i++; 1318 } 1319 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1320 hex_to_byteval(&buf[i], &plaintext[j]); 1321 } 1322 plaintextlen = j; 1323 1324 rv = aes_encrypt_buf(mode, key, keysize, 1325 (mode == 1326 NSS_AES) 1327 ? NULL 1328 : iv, 1329 ciphertext, &ciphertextlen, sizeof ciphertext, 1330 plaintext, plaintextlen); 1331 if (rv != SECSuccess) { 1332 goto loser; 1333 } 1334 1335 fputs(buf, aesresp); 1336 fputs("CIPHERTEXT = ", aesresp); 1337 to_hex_str(buf, ciphertext, ciphertextlen); 1338 fputs(buf, aesresp); 1339 fputc('\n', aesresp); 1340 continue; 1341 } 1342 /* CIPHERTEXT = ... */ 1343 if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1344 /* sanity check */ 1345 if (encrypt) { 1346 goto loser; 1347 } 1348 1349 i = 10; 1350 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1351 i++; 1352 } 1353 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1354 hex_to_byteval(&buf[i], &ciphertext[j]); 1355 } 1356 ciphertextlen = j; 1357 1358 rv = aes_decrypt_buf(mode, key, keysize, 1359 (mode == 1360 NSS_AES) 1361 ? NULL 1362 : iv, 1363 plaintext, &plaintextlen, sizeof plaintext, 1364 ciphertext, ciphertextlen); 1365 if (rv != SECSuccess) { 1366 goto loser; 1367 } 1368 1369 fputs(buf, aesresp); 1370 fputs("PLAINTEXT = ", aesresp); 1371 to_hex_str(buf, plaintext, plaintextlen); 1372 fputs(buf, aesresp); 1373 fputc('\n', aesresp); 1374 continue; 1375 } 1376 } 1377 loser: 1378 fclose(aesreq); 1379 } 1380 1381 /* 1382 * Generate Key[i+1] from Key[i], CT[j-1], and CT[j] for AES Monte Carlo 1383 * Test (MCT) in ECB and CBC modes. 1384 */ 1385 void 1386 aes_mct_next_key(unsigned char *key, unsigned int keysize, 1387 const unsigned char *ciphertext_1, const unsigned char *ciphertext) 1388 { 1389 int k; 1390 1391 switch (keysize) { 1392 case 16: /* 128-bit key */ 1393 /* Key[i+1] = Key[i] xor CT[j] */ 1394 for (k = 0; k < 16; k++) { 1395 key[k] ^= ciphertext[k]; 1396 } 1397 break; 1398 case 24: /* 192-bit key */ 1399 /* 1400 * Key[i+1] = Key[i] xor (last 64-bits of 1401 * CT[j-1] || CT[j]) 1402 */ 1403 for (k = 0; k < 8; k++) { 1404 key[k] ^= ciphertext_1[k + 8]; 1405 } 1406 for (k = 8; k < 24; k++) { 1407 key[k] ^= ciphertext[k - 8]; 1408 } 1409 break; 1410 case 32: /* 256-bit key */ 1411 /* Key[i+1] = Key[i] xor (CT[j-1] || CT[j]) */ 1412 for (k = 0; k < 16; k++) { 1413 key[k] ^= ciphertext_1[k]; 1414 } 1415 for (k = 16; k < 32; k++) { 1416 key[k] ^= ciphertext[k - 16]; 1417 } 1418 break; 1419 } 1420 } 1421 1422 /* 1423 * Perform the AES Monte Carlo Test (MCT) in ECB mode. MCT exercises 1424 * our AES code in streaming mode because the plaintext or ciphertext 1425 * is generated block by block as we go, so we can't collect all the 1426 * plaintext or ciphertext in one buffer and encrypt or decrypt it in 1427 * one shot. 1428 * 1429 * reqfn is the pathname of the input REQUEST file. 1430 * 1431 * The output RESPONSE file is written to stdout. 1432 */ 1433 void 1434 aes_ecb_mct(char *reqfn) 1435 { 1436 char buf[80]; /* holds one line from the input REQUEST file. 1437 * needs to be large enough to hold the longest 1438 * line "KEY = <64 hex digits>\n". 1439 */ 1440 FILE *aesreq; /* input stream from the REQUEST file */ 1441 FILE *aesresp; /* output stream to the RESPONSE file */ 1442 int i, j; 1443 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1444 unsigned char key[32]; /* 128, 192, or 256 bits */ 1445 unsigned int keysize = 0; 1446 unsigned char plaintext[16]; /* PT[j] */ 1447 unsigned char plaintext_1[16]; /* PT[j-1] */ 1448 unsigned char ciphertext[16]; /* CT[j] */ 1449 unsigned char ciphertext_1[16]; /* CT[j-1] */ 1450 unsigned char doublecheck[16]; 1451 unsigned int outputlen; 1452 AESContext *cx = NULL; /* the operation being tested */ 1453 AESContext *cx2 = NULL; /* the inverse operation done in parallel 1454 * to doublecheck our result. 1455 */ 1456 SECStatus rv; 1457 1458 aesreq = fopen(reqfn, "r"); 1459 aesresp = stdout; 1460 while (fgets(buf, sizeof buf, aesreq) != NULL) { 1461 /* a comment or blank line */ 1462 if (buf[0] == '#' || buf[0] == '\n') { 1463 fputs(buf, aesresp); 1464 continue; 1465 } 1466 /* [ENCRYPT] or [DECRYPT] */ 1467 if (buf[0] == '[') { 1468 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1469 encrypt = 1; 1470 } else { 1471 encrypt = 0; 1472 } 1473 fputs(buf, aesresp); 1474 continue; 1475 } 1476 /* "COUNT = x" begins a new data set */ 1477 if (strncmp(buf, "COUNT", 5) == 0) { 1478 /* zeroize the variables for the test with this data set */ 1479 memset(key, 0, sizeof key); 1480 keysize = 0; 1481 memset(plaintext, 0, sizeof plaintext); 1482 memset(ciphertext, 0, sizeof ciphertext); 1483 continue; 1484 } 1485 /* KEY = ... */ 1486 if (strncmp(buf, "KEY", 3) == 0) { 1487 /* Key[0] = Key */ 1488 i = 3; 1489 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1490 i++; 1491 } 1492 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1493 hex_to_byteval(&buf[i], &key[j]); 1494 } 1495 keysize = j; 1496 continue; 1497 } 1498 /* PLAINTEXT = ... */ 1499 if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1500 /* sanity check */ 1501 if (!encrypt) { 1502 goto loser; 1503 } 1504 /* PT[0] = PT */ 1505 i = 9; 1506 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1507 i++; 1508 } 1509 for (j = 0; j < sizeof plaintext; i += 2, j++) { 1510 hex_to_byteval(&buf[i], &plaintext[j]); 1511 } 1512 1513 for (i = 0; i < 100; i++) { 1514 snprintf(buf, sizeof(buf), "COUNT = %d\n", i); 1515 fputs(buf, aesresp); 1516 /* Output Key[i] */ 1517 fputs("KEY = ", aesresp); 1518 to_hex_str(buf, key, keysize); 1519 fputs(buf, aesresp); 1520 fputc('\n', aesresp); 1521 /* Output PT[0] */ 1522 fputs("PLAINTEXT = ", aesresp); 1523 to_hex_str(buf, plaintext, sizeof plaintext); 1524 fputs(buf, aesresp); 1525 fputc('\n', aesresp); 1526 1527 cx = AES_CreateContext(key, NULL, NSS_AES, 1528 PR_TRUE, keysize, 16); 1529 if (cx == NULL) { 1530 goto loser; 1531 } 1532 /* 1533 * doublecheck our result by decrypting the result 1534 * and comparing the output with the plaintext. 1535 */ 1536 cx2 = AES_CreateContext(key, NULL, NSS_AES, 1537 PR_FALSE, keysize, 16); 1538 if (cx2 == NULL) { 1539 goto loser; 1540 } 1541 for (j = 0; j < 1000; j++) { 1542 /* Save CT[j-1] */ 1543 memcpy(ciphertext_1, ciphertext, sizeof ciphertext); 1544 1545 /* CT[j] = AES(Key[i], PT[j]) */ 1546 outputlen = 0; 1547 rv = AES_Encrypt(cx, 1548 ciphertext, &outputlen, sizeof ciphertext, 1549 plaintext, sizeof plaintext); 1550 if (rv != SECSuccess) { 1551 goto loser; 1552 } 1553 if (outputlen != sizeof plaintext) { 1554 goto loser; 1555 } 1556 1557 /* doublecheck our result */ 1558 outputlen = 0; 1559 rv = AES_Decrypt(cx2, 1560 doublecheck, &outputlen, sizeof doublecheck, 1561 ciphertext, sizeof ciphertext); 1562 if (rv != SECSuccess) { 1563 goto loser; 1564 } 1565 if (outputlen != sizeof ciphertext) { 1566 goto loser; 1567 } 1568 if (memcmp(doublecheck, plaintext, sizeof plaintext)) { 1569 goto loser; 1570 } 1571 1572 /* PT[j+1] = CT[j] */ 1573 memcpy(plaintext, ciphertext, sizeof plaintext); 1574 } 1575 AES_DestroyContext(cx, PR_TRUE); 1576 cx = NULL; 1577 AES_DestroyContext(cx2, PR_TRUE); 1578 cx2 = NULL; 1579 1580 /* Output CT[j] */ 1581 fputs("CIPHERTEXT = ", aesresp); 1582 to_hex_str(buf, ciphertext, sizeof ciphertext); 1583 fputs(buf, aesresp); 1584 fputc('\n', aesresp); 1585 1586 /* Key[i+1] = Key[i] xor ... */ 1587 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext); 1588 /* PT[0] = CT[j] */ 1589 /* done at the end of the for(j) loop */ 1590 1591 fputc('\n', aesresp); 1592 } 1593 1594 continue; 1595 } 1596 /* CIPHERTEXT = ... */ 1597 if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1598 /* sanity check */ 1599 if (encrypt) { 1600 goto loser; 1601 } 1602 /* CT[0] = CT */ 1603 i = 10; 1604 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1605 i++; 1606 } 1607 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1608 hex_to_byteval(&buf[i], &ciphertext[j]); 1609 } 1610 1611 for (i = 0; i < 100; i++) { 1612 snprintf(buf, sizeof(buf), "COUNT = %d\n", i); 1613 fputs(buf, aesresp); 1614 /* Output Key[i] */ 1615 fputs("KEY = ", aesresp); 1616 to_hex_str(buf, key, keysize); 1617 fputs(buf, aesresp); 1618 fputc('\n', aesresp); 1619 /* Output CT[0] */ 1620 fputs("CIPHERTEXT = ", aesresp); 1621 to_hex_str(buf, ciphertext, sizeof ciphertext); 1622 fputs(buf, aesresp); 1623 fputc('\n', aesresp); 1624 1625 cx = AES_CreateContext(key, NULL, NSS_AES, 1626 PR_FALSE, keysize, 16); 1627 if (cx == NULL) { 1628 goto loser; 1629 } 1630 /* 1631 * doublecheck our result by encrypting the result 1632 * and comparing the output with the ciphertext. 1633 */ 1634 cx2 = AES_CreateContext(key, NULL, NSS_AES, 1635 PR_TRUE, keysize, 16); 1636 if (cx2 == NULL) { 1637 goto loser; 1638 } 1639 for (j = 0; j < 1000; j++) { 1640 /* Save PT[j-1] */ 1641 memcpy(plaintext_1, plaintext, sizeof plaintext); 1642 1643 /* PT[j] = AES(Key[i], CT[j]) */ 1644 outputlen = 0; 1645 rv = AES_Decrypt(cx, 1646 plaintext, &outputlen, sizeof plaintext, 1647 ciphertext, sizeof ciphertext); 1648 if (rv != SECSuccess) { 1649 goto loser; 1650 } 1651 if (outputlen != sizeof ciphertext) { 1652 goto loser; 1653 } 1654 1655 /* doublecheck our result */ 1656 outputlen = 0; 1657 rv = AES_Encrypt(cx2, 1658 doublecheck, &outputlen, sizeof doublecheck, 1659 plaintext, sizeof plaintext); 1660 if (rv != SECSuccess) { 1661 goto loser; 1662 } 1663 if (outputlen != sizeof plaintext) { 1664 goto loser; 1665 } 1666 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) { 1667 goto loser; 1668 } 1669 1670 /* CT[j+1] = PT[j] */ 1671 memcpy(ciphertext, plaintext, sizeof ciphertext); 1672 } 1673 AES_DestroyContext(cx, PR_TRUE); 1674 cx = NULL; 1675 AES_DestroyContext(cx2, PR_TRUE); 1676 cx2 = NULL; 1677 1678 /* Output PT[j] */ 1679 fputs("PLAINTEXT = ", aesresp); 1680 to_hex_str(buf, plaintext, sizeof plaintext); 1681 fputs(buf, aesresp); 1682 fputc('\n', aesresp); 1683 1684 /* Key[i+1] = Key[i] xor ... */ 1685 aes_mct_next_key(key, keysize, plaintext_1, plaintext); 1686 /* CT[0] = PT[j] */ 1687 /* done at the end of the for(j) loop */ 1688 1689 fputc('\n', aesresp); 1690 } 1691 1692 continue; 1693 } 1694 } 1695 loser: 1696 if (cx != NULL) { 1697 AES_DestroyContext(cx, PR_TRUE); 1698 } 1699 if (cx2 != NULL) { 1700 AES_DestroyContext(cx2, PR_TRUE); 1701 } 1702 fclose(aesreq); 1703 } 1704 1705 /* 1706 * Perform the AES Monte Carlo Test (MCT) in CBC mode. MCT exercises 1707 * our AES code in streaming mode because the plaintext or ciphertext 1708 * is generated block by block as we go, so we can't collect all the 1709 * plaintext or ciphertext in one buffer and encrypt or decrypt it in 1710 * one shot. 1711 * 1712 * reqfn is the pathname of the input REQUEST file. 1713 * 1714 * The output RESPONSE file is written to stdout. 1715 */ 1716 void 1717 aes_cbc_mct(char *reqfn) 1718 { 1719 char buf[80]; /* holds one line from the input REQUEST file. 1720 * needs to be large enough to hold the longest 1721 * line "KEY = <64 hex digits>\n". 1722 */ 1723 FILE *aesreq; /* input stream from the REQUEST file */ 1724 FILE *aesresp; /* output stream to the RESPONSE file */ 1725 int i, j; 1726 int encrypt = 0; /* 1 means encrypt, 0 means decrypt */ 1727 unsigned char key[32]; /* 128, 192, or 256 bits */ 1728 unsigned int keysize = 0; 1729 unsigned char iv[16]; 1730 unsigned char plaintext[16]; /* PT[j] */ 1731 unsigned char plaintext_1[16]; /* PT[j-1] */ 1732 unsigned char ciphertext[16]; /* CT[j] */ 1733 unsigned char ciphertext_1[16]; /* CT[j-1] */ 1734 unsigned char doublecheck[16]; 1735 unsigned int outputlen; 1736 AESContext *cx = NULL; /* the operation being tested */ 1737 AESContext *cx2 = NULL; /* the inverse operation done in parallel 1738 * to doublecheck our result. 1739 */ 1740 SECStatus rv; 1741 1742 aesreq = fopen(reqfn, "r"); 1743 aesresp = stdout; 1744 while (fgets(buf, sizeof buf, aesreq) != NULL) { 1745 /* a comment or blank line */ 1746 if (buf[0] == '#' || buf[0] == '\n') { 1747 fputs(buf, aesresp); 1748 continue; 1749 } 1750 /* [ENCRYPT] or [DECRYPT] */ 1751 if (buf[0] == '[') { 1752 if (strncmp(&buf[1], "ENCRYPT", 7) == 0) { 1753 encrypt = 1; 1754 } else { 1755 encrypt = 0; 1756 } 1757 fputs(buf, aesresp); 1758 continue; 1759 } 1760 /* "COUNT = x" begins a new data set */ 1761 if (strncmp(buf, "COUNT", 5) == 0) { 1762 /* zeroize the variables for the test with this data set */ 1763 memset(key, 0, sizeof key); 1764 keysize = 0; 1765 memset(iv, 0, sizeof iv); 1766 memset(plaintext, 0, sizeof plaintext); 1767 memset(ciphertext, 0, sizeof ciphertext); 1768 continue; 1769 } 1770 /* KEY = ... */ 1771 if (strncmp(buf, "KEY", 3) == 0) { 1772 /* Key[0] = Key */ 1773 i = 3; 1774 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1775 i++; 1776 } 1777 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1778 hex_to_byteval(&buf[i], &key[j]); 1779 } 1780 keysize = j; 1781 continue; 1782 } 1783 /* IV = ... */ 1784 if (strncmp(buf, "IV", 2) == 0) { 1785 /* IV[0] = IV */ 1786 i = 2; 1787 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1788 i++; 1789 } 1790 for (j = 0; j < sizeof iv; i += 2, j++) { 1791 hex_to_byteval(&buf[i], &iv[j]); 1792 } 1793 continue; 1794 } 1795 /* PLAINTEXT = ... */ 1796 if (strncmp(buf, "PLAINTEXT", 9) == 0) { 1797 /* sanity check */ 1798 if (!encrypt) { 1799 goto loser; 1800 } 1801 /* PT[0] = PT */ 1802 i = 9; 1803 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1804 i++; 1805 } 1806 for (j = 0; j < sizeof plaintext; i += 2, j++) { 1807 hex_to_byteval(&buf[i], &plaintext[j]); 1808 } 1809 1810 for (i = 0; i < 100; i++) { 1811 snprintf(buf, sizeof(buf), "COUNT = %d\n", i); 1812 fputs(buf, aesresp); 1813 /* Output Key[i] */ 1814 fputs("KEY = ", aesresp); 1815 to_hex_str(buf, key, keysize); 1816 fputs(buf, aesresp); 1817 fputc('\n', aesresp); 1818 /* Output IV[i] */ 1819 fputs("IV = ", aesresp); 1820 to_hex_str(buf, iv, sizeof iv); 1821 fputs(buf, aesresp); 1822 fputc('\n', aesresp); 1823 /* Output PT[0] */ 1824 fputs("PLAINTEXT = ", aesresp); 1825 to_hex_str(buf, plaintext, sizeof plaintext); 1826 fputs(buf, aesresp); 1827 fputc('\n', aesresp); 1828 1829 cx = AES_CreateContext(key, iv, NSS_AES_CBC, 1830 PR_TRUE, keysize, 16); 1831 if (cx == NULL) { 1832 goto loser; 1833 } 1834 /* 1835 * doublecheck our result by decrypting the result 1836 * and comparing the output with the plaintext. 1837 */ 1838 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC, 1839 PR_FALSE, keysize, 16); 1840 if (cx2 == NULL) { 1841 goto loser; 1842 } 1843 /* CT[-1] = IV[i] */ 1844 memcpy(ciphertext, iv, sizeof ciphertext); 1845 for (j = 0; j < 1000; j++) { 1846 /* Save CT[j-1] */ 1847 memcpy(ciphertext_1, ciphertext, sizeof ciphertext); 1848 /* 1849 * If ( j=0 ) 1850 * CT[j] = AES(Key[i], IV[i], PT[j]) 1851 * PT[j+1] = IV[i] (= CT[j-1]) 1852 * Else 1853 * CT[j] = AES(Key[i], PT[j]) 1854 * PT[j+1] = CT[j-1] 1855 */ 1856 outputlen = 0; 1857 rv = AES_Encrypt(cx, 1858 ciphertext, &outputlen, sizeof ciphertext, 1859 plaintext, sizeof plaintext); 1860 if (rv != SECSuccess) { 1861 goto loser; 1862 } 1863 if (outputlen != sizeof plaintext) { 1864 goto loser; 1865 } 1866 1867 /* doublecheck our result */ 1868 outputlen = 0; 1869 rv = AES_Decrypt(cx2, 1870 doublecheck, &outputlen, sizeof doublecheck, 1871 ciphertext, sizeof ciphertext); 1872 if (rv != SECSuccess) { 1873 goto loser; 1874 } 1875 if (outputlen != sizeof ciphertext) { 1876 goto loser; 1877 } 1878 if (memcmp(doublecheck, plaintext, sizeof plaintext)) { 1879 goto loser; 1880 } 1881 1882 memcpy(plaintext, ciphertext_1, sizeof plaintext); 1883 } 1884 AES_DestroyContext(cx, PR_TRUE); 1885 cx = NULL; 1886 AES_DestroyContext(cx2, PR_TRUE); 1887 cx2 = NULL; 1888 1889 /* Output CT[j] */ 1890 fputs("CIPHERTEXT = ", aesresp); 1891 to_hex_str(buf, ciphertext, sizeof ciphertext); 1892 fputs(buf, aesresp); 1893 fputc('\n', aesresp); 1894 1895 /* Key[i+1] = Key[i] xor ... */ 1896 aes_mct_next_key(key, keysize, ciphertext_1, ciphertext); 1897 /* IV[i+1] = CT[j] */ 1898 memcpy(iv, ciphertext, sizeof iv); 1899 /* PT[0] = CT[j-1] */ 1900 /* done at the end of the for(j) loop */ 1901 1902 fputc('\n', aesresp); 1903 } 1904 1905 continue; 1906 } 1907 /* CIPHERTEXT = ... */ 1908 if (strncmp(buf, "CIPHERTEXT", 10) == 0) { 1909 /* sanity check */ 1910 if (encrypt) { 1911 goto loser; 1912 } 1913 /* CT[0] = CT */ 1914 i = 10; 1915 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 1916 i++; 1917 } 1918 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 1919 hex_to_byteval(&buf[i], &ciphertext[j]); 1920 } 1921 1922 for (i = 0; i < 100; i++) { 1923 snprintf(buf, sizeof(buf), "COUNT = %d\n", i); 1924 fputs(buf, aesresp); 1925 /* Output Key[i] */ 1926 fputs("KEY = ", aesresp); 1927 to_hex_str(buf, key, keysize); 1928 fputs(buf, aesresp); 1929 fputc('\n', aesresp); 1930 /* Output IV[i] */ 1931 fputs("IV = ", aesresp); 1932 to_hex_str(buf, iv, sizeof iv); 1933 fputs(buf, aesresp); 1934 fputc('\n', aesresp); 1935 /* Output CT[0] */ 1936 fputs("CIPHERTEXT = ", aesresp); 1937 to_hex_str(buf, ciphertext, sizeof ciphertext); 1938 fputs(buf, aesresp); 1939 fputc('\n', aesresp); 1940 1941 cx = AES_CreateContext(key, iv, NSS_AES_CBC, 1942 PR_FALSE, keysize, 16); 1943 if (cx == NULL) { 1944 goto loser; 1945 } 1946 /* 1947 * doublecheck our result by encrypting the result 1948 * and comparing the output with the ciphertext. 1949 */ 1950 cx2 = AES_CreateContext(key, iv, NSS_AES_CBC, 1951 PR_TRUE, keysize, 16); 1952 if (cx2 == NULL) { 1953 goto loser; 1954 } 1955 /* PT[-1] = IV[i] */ 1956 memcpy(plaintext, iv, sizeof plaintext); 1957 for (j = 0; j < 1000; j++) { 1958 /* Save PT[j-1] */ 1959 memcpy(plaintext_1, plaintext, sizeof plaintext); 1960 /* 1961 * If ( j=0 ) 1962 * PT[j] = AES(Key[i], IV[i], CT[j]) 1963 * CT[j+1] = IV[i] (= PT[j-1]) 1964 * Else 1965 * PT[j] = AES(Key[i], CT[j]) 1966 * CT[j+1] = PT[j-1] 1967 */ 1968 outputlen = 0; 1969 rv = AES_Decrypt(cx, 1970 plaintext, &outputlen, sizeof plaintext, 1971 ciphertext, sizeof ciphertext); 1972 if (rv != SECSuccess) { 1973 goto loser; 1974 } 1975 if (outputlen != sizeof ciphertext) { 1976 goto loser; 1977 } 1978 1979 /* doublecheck our result */ 1980 outputlen = 0; 1981 rv = AES_Encrypt(cx2, 1982 doublecheck, &outputlen, sizeof doublecheck, 1983 plaintext, sizeof plaintext); 1984 if (rv != SECSuccess) { 1985 goto loser; 1986 } 1987 if (outputlen != sizeof plaintext) { 1988 goto loser; 1989 } 1990 if (memcmp(doublecheck, ciphertext, sizeof ciphertext)) { 1991 goto loser; 1992 } 1993 1994 memcpy(ciphertext, plaintext_1, sizeof ciphertext); 1995 } 1996 AES_DestroyContext(cx, PR_TRUE); 1997 cx = NULL; 1998 AES_DestroyContext(cx2, PR_TRUE); 1999 cx2 = NULL; 2000 2001 /* Output PT[j] */ 2002 fputs("PLAINTEXT = ", aesresp); 2003 to_hex_str(buf, plaintext, sizeof plaintext); 2004 fputs(buf, aesresp); 2005 fputc('\n', aesresp); 2006 2007 /* Key[i+1] = Key[i] xor ... */ 2008 aes_mct_next_key(key, keysize, plaintext_1, plaintext); 2009 /* IV[i+1] = PT[j] */ 2010 memcpy(iv, plaintext, sizeof iv); 2011 /* CT[0] = PT[j-1] */ 2012 /* done at the end of the for(j) loop */ 2013 2014 fputc('\n', aesresp); 2015 } 2016 2017 continue; 2018 } 2019 } 2020 loser: 2021 if (cx != NULL) { 2022 AES_DestroyContext(cx, PR_TRUE); 2023 } 2024 if (cx2 != NULL) { 2025 AES_DestroyContext(cx2, PR_TRUE); 2026 } 2027 fclose(aesreq); 2028 } 2029 2030 void 2031 write_compact_string(FILE *out, unsigned char *hash, unsigned int len) 2032 { 2033 unsigned int i; 2034 int j, count = 0, last = -1, z = 0; 2035 long start = ftell(out); 2036 for (i = 0; i < len; i++) { 2037 for (j = 7; j >= 0; j--) { 2038 if (last < 0) { 2039 last = (hash[i] & (1 << j)) ? 1 : 0; 2040 fprintf(out, "%d ", last); 2041 count = 1; 2042 } else if (hash[i] & (1 << j)) { 2043 if (last) { 2044 count++; 2045 } else { 2046 last = 0; 2047 fprintf(out, "%d ", count); 2048 count = 1; 2049 z++; 2050 } 2051 } else { 2052 if (!last) { 2053 count++; 2054 } else { 2055 last = 1; 2056 fprintf(out, "%d ", count); 2057 count = 1; 2058 z++; 2059 } 2060 } 2061 } 2062 } 2063 fprintf(out, "^\n"); 2064 fseek(out, start, SEEK_SET); 2065 fprintf(out, "%d ", z); 2066 fseek(out, 0, SEEK_END); 2067 } 2068 2069 int 2070 get_next_line(FILE *req, char *key, char *val, FILE *rsp) 2071 { 2072 int ignore = 0; 2073 char *writeto = key; 2074 int w = 0; 2075 int c; 2076 while ((c = fgetc(req)) != EOF) { 2077 if (ignore) { 2078 fprintf(rsp, "%c", c); 2079 if (c == '\n') 2080 return ignore; 2081 } else if (c == '\n') { 2082 break; 2083 } else if (c == '#') { 2084 ignore = 1; 2085 fprintf(rsp, "%c", c); 2086 } else if (c == '=') { 2087 writeto[w] = '\0'; 2088 w = 0; 2089 writeto = val; 2090 } else if (c == ' ' || c == '[' || c == ']') { 2091 continue; 2092 } else { 2093 writeto[w++] = c; 2094 } 2095 } 2096 writeto[w] = '\0'; 2097 return (c == EOF) ? -1 : ignore; 2098 } 2099 2100 typedef struct curveNameTagPairStr { 2101 char *curveName; 2102 SECOidTag curveOidTag; 2103 } CurveNameTagPair; 2104 2105 #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP192R1 2106 /* #define DEFAULT_CURVE_OID_TAG SEC_OID_SECG_EC_SECP160R1 */ 2107 2108 static CurveNameTagPair nameTagPair[] = { 2109 { "sect163k1", SEC_OID_SECG_EC_SECT163K1 }, 2110 { "nistk163", SEC_OID_SECG_EC_SECT163K1 }, 2111 { "sect163r1", SEC_OID_SECG_EC_SECT163R1 }, 2112 { "sect163r2", SEC_OID_SECG_EC_SECT163R2 }, 2113 { "nistb163", SEC_OID_SECG_EC_SECT163R2 }, 2114 { "sect193r1", SEC_OID_SECG_EC_SECT193R1 }, 2115 { "sect193r2", SEC_OID_SECG_EC_SECT193R2 }, 2116 { "sect233k1", SEC_OID_SECG_EC_SECT233K1 }, 2117 { "nistk233", SEC_OID_SECG_EC_SECT233K1 }, 2118 { "sect233r1", SEC_OID_SECG_EC_SECT233R1 }, 2119 { "nistb233", SEC_OID_SECG_EC_SECT233R1 }, 2120 { "sect239k1", SEC_OID_SECG_EC_SECT239K1 }, 2121 { "sect283k1", SEC_OID_SECG_EC_SECT283K1 }, 2122 { "nistk283", SEC_OID_SECG_EC_SECT283K1 }, 2123 { "sect283r1", SEC_OID_SECG_EC_SECT283R1 }, 2124 { "nistb283", SEC_OID_SECG_EC_SECT283R1 }, 2125 { "sect409k1", SEC_OID_SECG_EC_SECT409K1 }, 2126 { "nistk409", SEC_OID_SECG_EC_SECT409K1 }, 2127 { "sect409r1", SEC_OID_SECG_EC_SECT409R1 }, 2128 { "nistb409", SEC_OID_SECG_EC_SECT409R1 }, 2129 { "sect571k1", SEC_OID_SECG_EC_SECT571K1 }, 2130 { "nistk571", SEC_OID_SECG_EC_SECT571K1 }, 2131 { "sect571r1", SEC_OID_SECG_EC_SECT571R1 }, 2132 { "nistb571", SEC_OID_SECG_EC_SECT571R1 }, 2133 { "secp160k1", SEC_OID_SECG_EC_SECP160K1 }, 2134 { "secp160r1", SEC_OID_SECG_EC_SECP160R1 }, 2135 { "secp160r2", SEC_OID_SECG_EC_SECP160R2 }, 2136 { "secp192k1", SEC_OID_SECG_EC_SECP192K1 }, 2137 { "secp192r1", SEC_OID_SECG_EC_SECP192R1 }, 2138 { "nistp192", SEC_OID_SECG_EC_SECP192R1 }, 2139 { "secp224k1", SEC_OID_SECG_EC_SECP224K1 }, 2140 { "secp224r1", SEC_OID_SECG_EC_SECP224R1 }, 2141 { "nistp224", SEC_OID_SECG_EC_SECP224R1 }, 2142 { "secp256k1", SEC_OID_SECG_EC_SECP256K1 }, 2143 { "secp256r1", SEC_OID_SECG_EC_SECP256R1 }, 2144 { "nistp256", SEC_OID_SECG_EC_SECP256R1 }, 2145 { "secp384r1", SEC_OID_SECG_EC_SECP384R1 }, 2146 { "nistp384", SEC_OID_SECG_EC_SECP384R1 }, 2147 { "secp521r1", SEC_OID_SECG_EC_SECP521R1 }, 2148 { "nistp521", SEC_OID_SECG_EC_SECP521R1 }, 2149 2150 { "prime192v1", SEC_OID_ANSIX962_EC_PRIME192V1 }, 2151 { "prime192v2", SEC_OID_ANSIX962_EC_PRIME192V2 }, 2152 { "prime192v3", SEC_OID_ANSIX962_EC_PRIME192V3 }, 2153 { "prime239v1", SEC_OID_ANSIX962_EC_PRIME239V1 }, 2154 { "prime239v2", SEC_OID_ANSIX962_EC_PRIME239V2 }, 2155 { "prime239v3", SEC_OID_ANSIX962_EC_PRIME239V3 }, 2156 2157 { "c2pnb163v1", SEC_OID_ANSIX962_EC_C2PNB163V1 }, 2158 { "c2pnb163v2", SEC_OID_ANSIX962_EC_C2PNB163V2 }, 2159 { "c2pnb163v3", SEC_OID_ANSIX962_EC_C2PNB163V3 }, 2160 { "c2pnb176v1", SEC_OID_ANSIX962_EC_C2PNB176V1 }, 2161 { "c2tnb191v1", SEC_OID_ANSIX962_EC_C2TNB191V1 }, 2162 { "c2tnb191v2", SEC_OID_ANSIX962_EC_C2TNB191V2 }, 2163 { "c2tnb191v3", SEC_OID_ANSIX962_EC_C2TNB191V3 }, 2164 { "c2onb191v4", SEC_OID_ANSIX962_EC_C2ONB191V4 }, 2165 { "c2onb191v5", SEC_OID_ANSIX962_EC_C2ONB191V5 }, 2166 { "c2pnb208w1", SEC_OID_ANSIX962_EC_C2PNB208W1 }, 2167 { "c2tnb239v1", SEC_OID_ANSIX962_EC_C2TNB239V1 }, 2168 { "c2tnb239v2", SEC_OID_ANSIX962_EC_C2TNB239V2 }, 2169 { "c2tnb239v3", SEC_OID_ANSIX962_EC_C2TNB239V3 }, 2170 { "c2onb239v4", SEC_OID_ANSIX962_EC_C2ONB239V4 }, 2171 { "c2onb239v5", SEC_OID_ANSIX962_EC_C2ONB239V5 }, 2172 { "c2pnb272w1", SEC_OID_ANSIX962_EC_C2PNB272W1 }, 2173 { "c2pnb304w1", SEC_OID_ANSIX962_EC_C2PNB304W1 }, 2174 { "c2tnb359v1", SEC_OID_ANSIX962_EC_C2TNB359V1 }, 2175 { "c2pnb368w1", SEC_OID_ANSIX962_EC_C2PNB368W1 }, 2176 { "c2tnb431r1", SEC_OID_ANSIX962_EC_C2TNB431R1 }, 2177 2178 { "secp112r1", SEC_OID_SECG_EC_SECP112R1 }, 2179 { "secp112r2", SEC_OID_SECG_EC_SECP112R2 }, 2180 { "secp128r1", SEC_OID_SECG_EC_SECP128R1 }, 2181 { "secp128r2", SEC_OID_SECG_EC_SECP128R2 }, 2182 2183 { "sect113r1", SEC_OID_SECG_EC_SECT113R1 }, 2184 { "sect113r2", SEC_OID_SECG_EC_SECT113R2 }, 2185 { "sect131r1", SEC_OID_SECG_EC_SECT131R1 }, 2186 { "sect131r2", SEC_OID_SECG_EC_SECT131R2 }, 2187 }; 2188 2189 static SECItem * 2190 getECParams(const char *curve) 2191 { 2192 SECItem *ecparams; 2193 SECOidData *oidData = NULL; 2194 SECOidTag curveOidTag = SEC_OID_UNKNOWN; /* default */ 2195 int i, numCurves; 2196 2197 if (curve != NULL) { 2198 numCurves = sizeof(nameTagPair) / sizeof(CurveNameTagPair); 2199 for (i = 0; ((i < numCurves) && (curveOidTag == SEC_OID_UNKNOWN)); 2200 i++) { 2201 if (PL_strcmp(curve, nameTagPair[i].curveName) == 0) 2202 curveOidTag = nameTagPair[i].curveOidTag; 2203 } 2204 } 2205 2206 /* Return NULL if curve name is not recognized */ 2207 if ((curveOidTag == SEC_OID_UNKNOWN) || 2208 (oidData = SECOID_FindOIDByTag(curveOidTag)) == NULL) { 2209 fprintf(stderr, "Unrecognized elliptic curve %s\n", curve); 2210 return NULL; 2211 } 2212 2213 ecparams = SECITEM_AllocItem(NULL, NULL, (2 + oidData->oid.len)); 2214 2215 /* 2216 * ecparams->data needs to contain the ASN encoding of an object ID (OID) 2217 * representing the named curve. The actual OID is in 2218 * oidData->oid.data so we simply prepend 0x06 and OID length 2219 */ 2220 ecparams->data[0] = SEC_ASN1_OBJECT_ID; 2221 ecparams->data[1] = oidData->oid.len; 2222 memcpy(ecparams->data + 2, oidData->oid.data, oidData->oid.len); 2223 2224 return ecparams; 2225 } 2226 2227 /* 2228 * HASH_ functions are available to full NSS apps and internally inside 2229 * freebl, but not exported to users of freebl. Create short stubs to 2230 * replace the functionality for fipstest. 2231 */ 2232 SECStatus 2233 fips_hashBuf(HASH_HashType type, unsigned char *hashBuf, 2234 unsigned char *msg, int len) 2235 { 2236 SECStatus rv = SECFailure; 2237 2238 switch (type) { 2239 case HASH_AlgSHA1: 2240 rv = SHA1_HashBuf(hashBuf, msg, len); 2241 break; 2242 case HASH_AlgSHA224: 2243 rv = SHA224_HashBuf(hashBuf, msg, len); 2244 break; 2245 case HASH_AlgSHA256: 2246 rv = SHA256_HashBuf(hashBuf, msg, len); 2247 break; 2248 case HASH_AlgSHA384: 2249 rv = SHA384_HashBuf(hashBuf, msg, len); 2250 break; 2251 case HASH_AlgSHA512: 2252 rv = SHA512_HashBuf(hashBuf, msg, len); 2253 break; 2254 default: 2255 break; 2256 } 2257 return rv; 2258 } 2259 2260 int 2261 fips_hashLen(HASH_HashType type) 2262 { 2263 int len = 0; 2264 2265 switch (type) { 2266 case HASH_AlgSHA1: 2267 len = SHA1_LENGTH; 2268 break; 2269 case HASH_AlgSHA224: 2270 len = SHA224_LENGTH; 2271 break; 2272 case HASH_AlgSHA256: 2273 len = SHA256_LENGTH; 2274 break; 2275 case HASH_AlgSHA384: 2276 len = SHA384_LENGTH; 2277 break; 2278 case HASH_AlgSHA512: 2279 len = SHA512_LENGTH; 2280 break; 2281 default: 2282 break; 2283 } 2284 return len; 2285 } 2286 2287 SECOidTag 2288 fips_hashOid(HASH_HashType type) 2289 { 2290 SECOidTag oid = SEC_OID_UNKNOWN; 2291 2292 switch (type) { 2293 case HASH_AlgSHA1: 2294 oid = SEC_OID_SHA1; 2295 break; 2296 case HASH_AlgSHA224: 2297 oid = SEC_OID_SHA224; 2298 break; 2299 case HASH_AlgSHA256: 2300 oid = SEC_OID_SHA256; 2301 break; 2302 case HASH_AlgSHA384: 2303 oid = SEC_OID_SHA384; 2304 break; 2305 case HASH_AlgSHA512: 2306 oid = SEC_OID_SHA512; 2307 break; 2308 default: 2309 break; 2310 } 2311 return oid; 2312 } 2313 2314 HASH_HashType 2315 sha_get_hashType(int hashbits) 2316 { 2317 HASH_HashType hashType = HASH_AlgNULL; 2318 2319 switch (hashbits) { 2320 case 1: 2321 case (SHA1_LENGTH * PR_BITS_PER_BYTE): 2322 hashType = HASH_AlgSHA1; 2323 break; 2324 case (SHA224_LENGTH * PR_BITS_PER_BYTE): 2325 hashType = HASH_AlgSHA224; 2326 break; 2327 case (SHA256_LENGTH * PR_BITS_PER_BYTE): 2328 hashType = HASH_AlgSHA256; 2329 break; 2330 case (SHA384_LENGTH * PR_BITS_PER_BYTE): 2331 hashType = HASH_AlgSHA384; 2332 break; 2333 case (SHA512_LENGTH * PR_BITS_PER_BYTE): 2334 hashType = HASH_AlgSHA512; 2335 break; 2336 default: 2337 break; 2338 } 2339 return hashType; 2340 } 2341 2342 HASH_HashType 2343 hash_string_to_hashType(const char *src) 2344 { 2345 HASH_HashType shaAlg = HASH_AlgNULL; 2346 if (strncmp(src, "SHA-1", 5) == 0) { 2347 shaAlg = HASH_AlgSHA1; 2348 } else if (strncmp(src, "SHA-224", 7) == 0) { 2349 shaAlg = HASH_AlgSHA224; 2350 } else if (strncmp(src, "SHA-256", 7) == 0) { 2351 shaAlg = HASH_AlgSHA256; 2352 } else if (strncmp(src, "SHA-384", 7) == 0) { 2353 shaAlg = HASH_AlgSHA384; 2354 } else if (strncmp(src, "SHA-512", 7) == 0) { 2355 shaAlg = HASH_AlgSHA512; 2356 } else if (strncmp(src, "SHA1", 4) == 0) { 2357 shaAlg = HASH_AlgSHA1; 2358 } else if (strncmp(src, "SHA224", 6) == 0) { 2359 shaAlg = HASH_AlgSHA224; 2360 } else if (strncmp(src, "SHA256", 6) == 0) { 2361 shaAlg = HASH_AlgSHA256; 2362 } else if (strncmp(src, "SHA384", 6) == 0) { 2363 shaAlg = HASH_AlgSHA384; 2364 } else if (strncmp(src, "SHA512", 6) == 0) { 2365 shaAlg = HASH_AlgSHA512; 2366 } 2367 return shaAlg; 2368 } 2369 2370 /* 2371 * Perform the ECDSA Key Pair Generation Test. 2372 * 2373 * reqfn is the pathname of the REQUEST file. 2374 * 2375 * The output RESPONSE file is written to stdout. 2376 */ 2377 void 2378 ecdsa_keypair_test(char *reqfn) 2379 { 2380 char buf[256]; /* holds one line from the input REQUEST file 2381 * or to the output RESPONSE file. 2382 * needs to be large enough to hold the longest 2383 * line "Qx = <144 hex digits>\n". 2384 */ 2385 FILE *ecdsareq; /* input stream from the REQUEST file */ 2386 FILE *ecdsaresp; /* output stream to the RESPONSE file */ 2387 char curve[16]; /* "nistxddd" */ 2388 ECParams *ecparams = NULL; 2389 int N; 2390 int i; 2391 unsigned int len; 2392 2393 ecdsareq = fopen(reqfn, "r"); 2394 ecdsaresp = stdout; 2395 strcpy(curve, "nist"); 2396 while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 2397 /* a comment or blank line */ 2398 if (buf[0] == '#' || buf[0] == '\n') { 2399 fputs(buf, ecdsaresp); 2400 continue; 2401 } 2402 /* [X-ddd] */ 2403 if (buf[0] == '[') { 2404 const char *src; 2405 char *dst; 2406 SECItem *encodedparams; 2407 2408 if (buf[1] == 'B') { 2409 fputs(buf, ecdsaresp); 2410 continue; 2411 } 2412 if (ecparams) { 2413 PORT_FreeArena(ecparams->arena, PR_FALSE); 2414 ecparams = NULL; 2415 } 2416 2417 src = &buf[1]; 2418 dst = &curve[4]; 2419 *dst++ = tolower((unsigned char)*src); 2420 src += 2; /* skip the hyphen */ 2421 *dst++ = *src++; 2422 *dst++ = *src++; 2423 *dst++ = *src++; 2424 *dst = '\0'; 2425 encodedparams = getECParams(curve); 2426 if (encodedparams == NULL) { 2427 fprintf(stderr, "Unknown curve %s.", curve); 2428 goto loser; 2429 } 2430 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 2431 fprintf(stderr, "Curve %s not supported.\n", curve); 2432 goto loser; 2433 } 2434 SECITEM_FreeItem(encodedparams, PR_TRUE); 2435 fputs(buf, ecdsaresp); 2436 continue; 2437 } 2438 /* N = x */ 2439 if (buf[0] == 'N') { 2440 if (sscanf(buf, "N = %d", &N) != 1) { 2441 goto loser; 2442 } 2443 for (i = 0; i < N; i++) { 2444 ECPrivateKey *ecpriv; 2445 2446 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { 2447 goto loser; 2448 } 2449 fputs("d = ", ecdsaresp); 2450 to_hex_str(buf, ecpriv->privateValue.data, 2451 ecpriv->privateValue.len); 2452 fputs(buf, ecdsaresp); 2453 fputc('\n', ecdsaresp); 2454 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) != 2455 SECSuccess) { 2456 goto loser; 2457 } 2458 len = ecpriv->publicValue.len; 2459 if (len % 2 == 0) { 2460 goto loser; 2461 } 2462 len = (len - 1) / 2; 2463 if (ecpriv->publicValue.data[0] != 2464 EC_POINT_FORM_UNCOMPRESSED) { 2465 goto loser; 2466 } 2467 fputs("Qx = ", ecdsaresp); 2468 to_hex_str(buf, &ecpriv->publicValue.data[1], len); 2469 fputs(buf, ecdsaresp); 2470 fputc('\n', ecdsaresp); 2471 fputs("Qy = ", ecdsaresp); 2472 to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len); 2473 fputs(buf, ecdsaresp); 2474 fputc('\n', ecdsaresp); 2475 fputc('\n', ecdsaresp); 2476 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 2477 } 2478 continue; 2479 } 2480 } 2481 loser: 2482 if (ecparams) { 2483 PORT_FreeArena(ecparams->arena, PR_FALSE); 2484 ecparams = NULL; 2485 } 2486 fclose(ecdsareq); 2487 } 2488 2489 /* 2490 * Perform the ECDSA Public Key Validation Test. 2491 * 2492 * reqfn is the pathname of the REQUEST file. 2493 * 2494 * The output RESPONSE file is written to stdout. 2495 */ 2496 void 2497 ecdsa_pkv_test(char *reqfn) 2498 { 2499 char buf[256]; /* holds one line from the input REQUEST file. 2500 * needs to be large enough to hold the longest 2501 * line "Qx = <144 hex digits>\n". 2502 */ 2503 FILE *ecdsareq; /* input stream from the REQUEST file */ 2504 FILE *ecdsaresp; /* output stream to the RESPONSE file */ 2505 char curve[16]; /* "nistxddd" */ 2506 ECParams *ecparams = NULL; 2507 SECItem pubkey; 2508 unsigned int i; 2509 unsigned int len = 0; 2510 PRBool keyvalid = PR_TRUE; 2511 2512 ecdsareq = fopen(reqfn, "r"); 2513 ecdsaresp = stdout; 2514 strcpy(curve, "nist"); 2515 pubkey.data = NULL; 2516 while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 2517 /* a comment or blank line */ 2518 if (buf[0] == '#' || buf[0] == '\n') { 2519 fputs(buf, ecdsaresp); 2520 continue; 2521 } 2522 /* [X-ddd] */ 2523 if (buf[0] == '[') { 2524 const char *src; 2525 char *dst; 2526 SECItem *encodedparams; 2527 2528 src = &buf[1]; 2529 dst = &curve[4]; 2530 *dst++ = tolower((unsigned char)*src); 2531 src += 2; /* skip the hyphen */ 2532 *dst++ = *src++; 2533 *dst++ = *src++; 2534 *dst++ = *src++; 2535 *dst = '\0'; 2536 if (ecparams != NULL) { 2537 PORT_FreeArena(ecparams->arena, PR_FALSE); 2538 ecparams = NULL; 2539 } 2540 encodedparams = getECParams(curve); 2541 if (encodedparams == NULL) { 2542 fprintf(stderr, "Unknown curve %s.", curve); 2543 goto loser; 2544 } 2545 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 2546 fprintf(stderr, "Curve %s not supported.\n", curve); 2547 goto loser; 2548 } 2549 SECITEM_FreeItem(encodedparams, PR_TRUE); 2550 len = (ecparams->fieldID.size + 7) >> 3; 2551 if (pubkey.data != NULL) { 2552 PORT_Free(pubkey.data); 2553 pubkey.data = NULL; 2554 } 2555 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(ecparams)); 2556 if (pubkey.data == NULL) { 2557 goto loser; 2558 } 2559 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; 2560 fputs(buf, ecdsaresp); 2561 continue; 2562 } 2563 /* Qx = ... */ 2564 if (strncmp(buf, "Qx", 2) == 0) { 2565 fputs(buf, ecdsaresp); 2566 i = 2; 2567 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2568 i++; 2569 } 2570 keyvalid = from_hex_str(&pubkey.data[1], len, &buf[i]); 2571 continue; 2572 } 2573 /* Qy = ... */ 2574 if (strncmp(buf, "Qy", 2) == 0) { 2575 fputs(buf, ecdsaresp); 2576 if (!keyvalid) { 2577 fputs("Result = F\n", ecdsaresp); 2578 continue; 2579 } 2580 i = 2; 2581 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2582 i++; 2583 } 2584 keyvalid = from_hex_str(&pubkey.data[1 + len], len, &buf[i]); 2585 if (!keyvalid) { 2586 fputs("Result = F\n", ecdsaresp); 2587 continue; 2588 } 2589 if (EC_ValidatePublicKey(ecparams, &pubkey) == SECSuccess) { 2590 fputs("Result = P\n", ecdsaresp); 2591 } else if (PORT_GetError() == SEC_ERROR_BAD_KEY) { 2592 fputs("Result = F\n", ecdsaresp); 2593 } else { 2594 goto loser; 2595 } 2596 continue; 2597 } 2598 } 2599 loser: 2600 if (ecparams != NULL) { 2601 PORT_FreeArena(ecparams->arena, PR_FALSE); 2602 } 2603 if (pubkey.data != NULL) { 2604 PORT_Free(pubkey.data); 2605 } 2606 fclose(ecdsareq); 2607 } 2608 2609 /* 2610 * Perform the ECDSA Signature Generation Test. 2611 * 2612 * reqfn is the pathname of the REQUEST file. 2613 * 2614 * The output RESPONSE file is written to stdout. 2615 */ 2616 void 2617 ecdsa_siggen_test(char *reqfn) 2618 { 2619 char buf[1024]; /* holds one line from the input REQUEST file 2620 * or to the output RESPONSE file. 2621 * needs to be large enough to hold the longest 2622 * line "Msg = <256 hex digits>\n". 2623 */ 2624 FILE *ecdsareq; /* input stream from the REQUEST file */ 2625 FILE *ecdsaresp; /* output stream to the RESPONSE file */ 2626 char curve[16]; /* "nistxddd" */ 2627 ECParams *ecparams = NULL; 2628 int i, j; 2629 unsigned int len; 2630 unsigned char msg[512]; /* message to be signed (<= 128 bytes) */ 2631 unsigned int msglen; 2632 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 2633 unsigned int shaLength = 0; /* length of SHA */ 2634 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */ 2635 unsigned char sig[2 * MAX_ECKEY_LEN]; 2636 SECItem signature, digest; 2637 2638 ecdsareq = fopen(reqfn, "r"); 2639 ecdsaresp = stdout; 2640 strcpy(curve, "nist"); 2641 while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 2642 /* a comment or blank line */ 2643 if (buf[0] == '#' || buf[0] == '\n') { 2644 fputs(buf, ecdsaresp); 2645 continue; 2646 } 2647 /* [X-ddd] */ 2648 if (buf[0] == '[') { 2649 const char *src; 2650 char *dst; 2651 SECItem *encodedparams; 2652 2653 src = &buf[1]; 2654 dst = &curve[4]; 2655 *dst++ = tolower((unsigned char)*src); 2656 src += 2; /* skip the hyphen */ 2657 *dst++ = *src++; 2658 *dst++ = *src++; 2659 *dst++ = *src++; 2660 *dst = '\0'; 2661 src++; /* skip the comma */ 2662 /* set the SHA Algorithm */ 2663 shaAlg = hash_string_to_hashType(src); 2664 if (shaAlg == HASH_AlgNULL) { 2665 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); 2666 goto loser; 2667 } 2668 if (ecparams != NULL) { 2669 PORT_FreeArena(ecparams->arena, PR_FALSE); 2670 ecparams = NULL; 2671 } 2672 encodedparams = getECParams(curve); 2673 if (encodedparams == NULL) { 2674 fprintf(stderr, "Unknown curve %s.", curve); 2675 goto loser; 2676 } 2677 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 2678 fprintf(stderr, "Curve %s not supported.\n", curve); 2679 goto loser; 2680 } 2681 SECITEM_FreeItem(encodedparams, PR_TRUE); 2682 fputs(buf, ecdsaresp); 2683 continue; 2684 } 2685 /* Msg = ... */ 2686 if (strncmp(buf, "Msg", 3) == 0) { 2687 ECPrivateKey *ecpriv; 2688 2689 i = 3; 2690 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2691 i++; 2692 } 2693 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 2694 hex_to_byteval(&buf[i], &msg[j]); 2695 } 2696 msglen = j; 2697 shaLength = fips_hashLen(shaAlg); 2698 if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) { 2699 if (shaLength == 0) { 2700 fprintf(ecdsaresp, "ERROR: SHAAlg not defined."); 2701 } 2702 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x", 2703 shaLength == 160 ? 1 : shaLength); 2704 goto loser; 2705 } 2706 fputs(buf, ecdsaresp); 2707 2708 if (EC_NewKey(ecparams, &ecpriv) != SECSuccess) { 2709 goto loser; 2710 } 2711 if (EC_ValidatePublicKey(ecparams, &ecpriv->publicValue) != 2712 SECSuccess) { 2713 goto loser; 2714 } 2715 len = ecpriv->publicValue.len; 2716 if (len % 2 == 0) { 2717 goto loser; 2718 } 2719 len = (len - 1) / 2; 2720 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { 2721 goto loser; 2722 } 2723 fputs("Qx = ", ecdsaresp); 2724 to_hex_str(buf, &ecpriv->publicValue.data[1], len); 2725 fputs(buf, ecdsaresp); 2726 fputc('\n', ecdsaresp); 2727 fputs("Qy = ", ecdsaresp); 2728 to_hex_str(buf, &ecpriv->publicValue.data[1 + len], len); 2729 fputs(buf, ecdsaresp); 2730 fputc('\n', ecdsaresp); 2731 2732 digest.type = siBuffer; 2733 digest.data = sha; 2734 digest.len = shaLength; 2735 signature.type = siBuffer; 2736 signature.data = sig; 2737 signature.len = sizeof sig; 2738 if (ECDSA_SignDigest(ecpriv, &signature, &digest) != SECSuccess) { 2739 goto loser; 2740 } 2741 len = signature.len; 2742 if (len % 2 != 0) { 2743 goto loser; 2744 } 2745 len = len / 2; 2746 fputs("R = ", ecdsaresp); 2747 to_hex_str(buf, &signature.data[0], len); 2748 fputs(buf, ecdsaresp); 2749 fputc('\n', ecdsaresp); 2750 fputs("S = ", ecdsaresp); 2751 to_hex_str(buf, &signature.data[len], len); 2752 fputs(buf, ecdsaresp); 2753 fputc('\n', ecdsaresp); 2754 2755 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 2756 continue; 2757 } 2758 } 2759 loser: 2760 if (ecparams != NULL) { 2761 PORT_FreeArena(ecparams->arena, PR_FALSE); 2762 } 2763 fclose(ecdsareq); 2764 } 2765 2766 /* 2767 * Perform the ECDSA Signature Verification Test. 2768 * 2769 * reqfn is the pathname of the REQUEST file. 2770 * 2771 * The output RESPONSE file is written to stdout. 2772 */ 2773 void 2774 ecdsa_sigver_test(char *reqfn) 2775 { 2776 char buf[1024]; /* holds one line from the input REQUEST file. 2777 * needs to be large enough to hold the longest 2778 * line "Msg = <256 hex digits>\n". 2779 */ 2780 FILE *ecdsareq; /* input stream from the REQUEST file */ 2781 FILE *ecdsaresp; /* output stream to the RESPONSE file */ 2782 char curve[16]; /* "nistxddd" */ 2783 ECPublicKey ecpub; 2784 unsigned int i, j; 2785 unsigned int flen = 0; /* length in bytes of the field size */ 2786 unsigned int olen = 0; /* length in bytes of the base point order */ 2787 unsigned char msg[512]; /* message that was signed (<= 128 bytes) */ 2788 unsigned int msglen = 0; 2789 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 2790 unsigned int shaLength = 0; /* length of SHA */ 2791 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */ 2792 unsigned char sig[2 * MAX_ECKEY_LEN]; 2793 SECItem signature, digest; 2794 PRBool keyvalid = PR_TRUE; 2795 PRBool sigvalid = PR_TRUE; 2796 2797 ecdsareq = fopen(reqfn, "r"); 2798 ecdsaresp = stdout; 2799 ecpub.ecParams.arena = NULL; 2800 strcpy(curve, "nist"); 2801 while (fgets(buf, sizeof buf, ecdsareq) != NULL) { 2802 /* a comment or blank line */ 2803 if (buf[0] == '#' || buf[0] == '\n') { 2804 fputs(buf, ecdsaresp); 2805 continue; 2806 } 2807 /* [X-ddd] */ 2808 if (buf[0] == '[') { 2809 const char *src; 2810 char *dst; 2811 SECItem *encodedparams; 2812 ECParams *ecparams; 2813 2814 src = &buf[1]; 2815 dst = &curve[4]; 2816 *dst++ = tolower((unsigned char)*src); 2817 src += 2; /* skip the hyphen */ 2818 *dst++ = *src++; 2819 *dst++ = *src++; 2820 *dst++ = *src++; 2821 *dst = '\0'; 2822 src++; /* skip the comma */ 2823 /* set the SHA Algorithm */ 2824 shaAlg = hash_string_to_hashType(src); 2825 if (shaAlg == HASH_AlgNULL) { 2826 fprintf(ecdsaresp, "ERROR: Unable to find SHAAlg type"); 2827 goto loser; 2828 } 2829 encodedparams = getECParams(curve); 2830 if (encodedparams == NULL) { 2831 fprintf(stderr, "Unknown curve %s.", curve); 2832 goto loser; 2833 } 2834 if (EC_DecodeParams(encodedparams, &ecparams) != SECSuccess) { 2835 fprintf(stderr, "Curve %s not supported.\n", curve); 2836 goto loser; 2837 } 2838 SECITEM_FreeItem(encodedparams, PR_TRUE); 2839 if (ecpub.ecParams.arena != NULL) { 2840 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); 2841 } 2842 ecpub.ecParams.arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 2843 if (ecpub.ecParams.arena == NULL) { 2844 goto loser; 2845 } 2846 if (EC_CopyParams(ecpub.ecParams.arena, &ecpub.ecParams, ecparams) != 2847 SECSuccess) { 2848 goto loser; 2849 } 2850 PORT_FreeArena(ecparams->arena, PR_FALSE); 2851 flen = (ecpub.ecParams.fieldID.size + 7) >> 3; 2852 olen = ecpub.ecParams.order.len; 2853 if (2 * olen > sizeof sig) { 2854 goto loser; 2855 } 2856 ecpub.publicValue.type = siBuffer; 2857 ecpub.publicValue.data = NULL; 2858 ecpub.publicValue.len = 0; 2859 SECITEM_AllocItem(ecpub.ecParams.arena, 2860 &ecpub.publicValue, 2 * flen + 1); 2861 if (ecpub.publicValue.data == NULL) { 2862 goto loser; 2863 } 2864 ecpub.publicValue.data[0] = EC_POINT_FORM_UNCOMPRESSED; 2865 fputs(buf, ecdsaresp); 2866 continue; 2867 } 2868 /* Msg = ... */ 2869 if (strncmp(buf, "Msg", 3) == 0) { 2870 i = 3; 2871 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2872 i++; 2873 } 2874 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 2875 hex_to_byteval(&buf[i], &msg[j]); 2876 } 2877 msglen = j; 2878 shaLength = fips_hashLen(shaAlg); 2879 if (fips_hashBuf(shaAlg, sha, msg, msglen) != SECSuccess) { 2880 if (shaLength == 0) { 2881 fprintf(ecdsaresp, "ERROR: SHAAlg not defined."); 2882 } 2883 fprintf(ecdsaresp, "ERROR: Unable to generate SHA%x", 2884 shaLength == 160 ? 1 : shaLength); 2885 goto loser; 2886 } 2887 fputs(buf, ecdsaresp); 2888 2889 digest.type = siBuffer; 2890 digest.data = sha; 2891 digest.len = shaLength; 2892 2893 continue; 2894 } 2895 /* Qx = ... */ 2896 if (strncmp(buf, "Qx", 2) == 0) { 2897 fputs(buf, ecdsaresp); 2898 i = 2; 2899 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2900 i++; 2901 } 2902 keyvalid = from_hex_str(&ecpub.publicValue.data[1], flen, 2903 &buf[i]); 2904 continue; 2905 } 2906 /* Qy = ... */ 2907 if (strncmp(buf, "Qy", 2) == 0) { 2908 fputs(buf, ecdsaresp); 2909 if (!keyvalid) { 2910 continue; 2911 } 2912 i = 2; 2913 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2914 i++; 2915 } 2916 keyvalid = from_hex_str(&ecpub.publicValue.data[1 + flen], flen, 2917 &buf[i]); 2918 if (!keyvalid) { 2919 continue; 2920 } 2921 if (EC_ValidatePublicKey(&ecpub.ecParams, &ecpub.publicValue) != 2922 SECSuccess) { 2923 if (PORT_GetError() == SEC_ERROR_BAD_KEY) { 2924 keyvalid = PR_FALSE; 2925 } else { 2926 goto loser; 2927 } 2928 } 2929 continue; 2930 } 2931 /* R = ... */ 2932 if (buf[0] == 'R') { 2933 fputs(buf, ecdsaresp); 2934 i = 1; 2935 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2936 i++; 2937 } 2938 sigvalid = from_hex_str(sig, olen, &buf[i]); 2939 continue; 2940 } 2941 /* S = ... */ 2942 if (buf[0] == 'S') { 2943 fputs(buf, ecdsaresp); 2944 i = 1; 2945 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 2946 i++; 2947 } 2948 if (sigvalid) { 2949 sigvalid = from_hex_str(&sig[olen], olen, &buf[i]); 2950 } 2951 signature.type = siBuffer; 2952 signature.data = sig; 2953 signature.len = 2 * olen; 2954 2955 if (!keyvalid || !sigvalid) { 2956 fputs("Result = F\n", ecdsaresp); 2957 } else if (ECDSA_VerifyDigest(&ecpub, &signature, &digest) == 2958 SECSuccess) { 2959 fputs("Result = P\n", ecdsaresp); 2960 } else { 2961 fputs("Result = F\n", ecdsaresp); 2962 } 2963 continue; 2964 } 2965 } 2966 loser: 2967 if (ecpub.ecParams.arena != NULL) { 2968 PORT_FreeArena(ecpub.ecParams.arena, PR_FALSE); 2969 } 2970 fclose(ecdsareq); 2971 } 2972 2973 /* 2974 * Perform the ECDH Functional Test. 2975 * 2976 * reqfn is the pathname of the REQUEST file. 2977 * 2978 * The output RESPONSE file is written to stdout. 2979 */ 2980 #define MAX_ECC_PARAMS 256 2981 void 2982 ecdh_functional(char *reqfn, PRBool response) 2983 { 2984 char buf[256]; /* holds one line from the input REQUEST file. 2985 * needs to be large enough to hold the longest 2986 * line "Qx = <144 hex digits>\n". 2987 */ 2988 FILE *ecdhreq; /* input stream from the REQUEST file */ 2989 FILE *ecdhresp; /* output stream to the RESPONSE file */ 2990 char curve[16]; /* "nistxddd" */ 2991 unsigned char hashBuf[HASH_LENGTH_MAX]; 2992 ECParams *ecparams[MAX_ECC_PARAMS] = { NULL }; 2993 ECPrivateKey *ecpriv = NULL; 2994 ECParams *current_ecparams = NULL; 2995 SECItem pubkey; 2996 SECItem ZZ; 2997 unsigned int i; 2998 unsigned int len = 0; 2999 unsigned int uit_len = 0; 3000 int current_curve = -1; 3001 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ 3002 3003 ecdhreq = fopen(reqfn, "r"); 3004 ecdhresp = stdout; 3005 strcpy(curve, "nist"); 3006 pubkey.data = NULL; 3007 while (fgets(buf, sizeof buf, ecdhreq) != NULL) { 3008 /* a comment or blank line */ 3009 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 3010 fputs(buf, ecdhresp); 3011 continue; 3012 } 3013 if (buf[0] == '[') { 3014 /* [Ex] */ 3015 if (buf[1] == 'E' && buf[3] == ']') { 3016 current_curve = buf[2] - 'A'; 3017 fputs(buf, ecdhresp); 3018 continue; 3019 } 3020 /* [Curve selected: x-nnn */ 3021 if (strncmp(buf, "[Curve ", 7) == 0) { 3022 const char *src; 3023 char *dst; 3024 SECItem *encodedparams; 3025 3026 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { 3027 fprintf(stderr, "No curve type defined\n"); 3028 goto loser; 3029 } 3030 3031 src = &buf[1]; 3032 /* skip passed the colon */ 3033 while (*src && *src != ':') 3034 src++; 3035 if (*src != ':') { 3036 fprintf(stderr, 3037 "No colon in curve selected statement\n%s", buf); 3038 goto loser; 3039 } 3040 src++; 3041 /* skip to the first non-space */ 3042 while (*src && *src == ' ') 3043 src++; 3044 dst = &curve[4]; 3045 *dst++ = tolower((unsigned char)*src); 3046 src += 2; /* skip the hyphen */ 3047 *dst++ = *src++; 3048 *dst++ = *src++; 3049 *dst++ = *src++; 3050 *dst = '\0'; 3051 if (ecparams[current_curve] != NULL) { 3052 PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); 3053 ecparams[current_curve] = NULL; 3054 } 3055 encodedparams = getECParams(curve); 3056 if (encodedparams == NULL) { 3057 fprintf(stderr, "Unknown curve %s.", curve); 3058 goto loser; 3059 } 3060 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) { 3061 fprintf(stderr, "Curve %s not supported.\n", curve); 3062 goto loser; 3063 } 3064 SECITEM_FreeItem(encodedparams, PR_TRUE); 3065 fputs(buf, ecdhresp); 3066 continue; 3067 } 3068 /* [Ex - SHAxxx] */ 3069 if (buf[1] == 'E' && buf[3] == ' ') { 3070 const char *src; 3071 current_curve = buf[2] - 'A'; 3072 if ((current_curve < 0) || (current_curve > 256)) { 3073 fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); 3074 goto loser; 3075 } 3076 current_ecparams = ecparams[current_curve]; 3077 if (current_ecparams == NULL) { 3078 fprintf(stderr, "no curve defined for type %c defined\n", 3079 buf[2]); 3080 goto loser; 3081 } 3082 /* skip passed the colon */ 3083 src = &buf[1]; 3084 while (*src && *src != '-') 3085 src++; 3086 if (*src != '-') { 3087 fprintf(stderr, 3088 "No data in curve selected statement\n%s", buf); 3089 goto loser; 3090 } 3091 src++; 3092 /* skip to the first non-space */ 3093 while (*src && *src == ' ') 3094 src++; 3095 hash = hash_string_to_hashType(src); 3096 if (hash == HASH_AlgNULL) { 3097 fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); 3098 goto loser; 3099 } 3100 fputs(buf, ecdhresp); 3101 continue; 3102 } 3103 fputs(buf, ecdhresp); 3104 continue; 3105 } 3106 /* COUNT = ... */ 3107 if (strncmp(buf, "COUNT", 5) == 0) { 3108 fputs(buf, ecdhresp); 3109 if (current_ecparams == NULL) { 3110 fprintf(stderr, "no curve defined for type %c defined\n", 3111 buf[2]); 3112 goto loser; 3113 } 3114 len = (current_ecparams->fieldID.size + 7) >> 3; 3115 if (pubkey.data != NULL) { 3116 PORT_Free(pubkey.data); 3117 pubkey.data = NULL; 3118 } 3119 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); 3120 if (pubkey.data == NULL) { 3121 goto loser; 3122 } 3123 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; 3124 continue; 3125 } 3126 /* QeCAVSx = ... */ 3127 if (strncmp(buf, "QeCAVSx", 7) == 0) { 3128 fputs(buf, ecdhresp); 3129 i = 7; 3130 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3131 i++; 3132 } 3133 from_hex_str(&pubkey.data[1], len, &buf[i]); 3134 continue; 3135 } 3136 /* QeCAVSy = ... */ 3137 if (strncmp(buf, "QeCAVSy", 7) == 0) { 3138 fputs(buf, ecdhresp); 3139 i = 7; 3140 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3141 i++; 3142 } 3143 from_hex_str(&pubkey.data[1 + len], len, &buf[i]); 3144 if (current_ecparams == NULL) { 3145 fprintf(stderr, "no curve defined\n"); 3146 goto loser; 3147 } 3148 /* validate CAVS public key */ 3149 if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { 3150 fprintf(stderr, "BAD key detected\n"); 3151 goto loser; 3152 } 3153 3154 /* generate ECC key pair */ 3155 if (EC_NewKey(current_ecparams, &ecpriv) != SECSuccess) { 3156 fprintf(stderr, "Failed to generate new key\n"); 3157 goto loser; 3158 } 3159 /* validate UIT generated public key */ 3160 if (EC_ValidatePublicKey(current_ecparams, &ecpriv->publicValue) != 3161 SECSuccess) { 3162 fprintf(stderr, "generate key did not validate\n"); 3163 goto loser; 3164 } 3165 /* output UIT public key */ 3166 uit_len = ecpriv->publicValue.len; 3167 if (uit_len % 2 == 0) { 3168 fprintf(stderr, "generate key had invalid public value len\n"); 3169 goto loser; 3170 } 3171 uit_len = (uit_len - 1) / 2; 3172 if (ecpriv->publicValue.data[0] != EC_POINT_FORM_UNCOMPRESSED) { 3173 fprintf(stderr, "generate key was compressed\n"); 3174 goto loser; 3175 } 3176 fputs("deIUT = ", ecdhresp); 3177 to_hex_str(buf, ecpriv->privateValue.data, ecpriv->privateValue.len); 3178 fputs(buf, ecdhresp); 3179 fputc('\n', ecdhresp); 3180 fputs("QeIUTx = ", ecdhresp); 3181 to_hex_str(buf, &ecpriv->publicValue.data[1], uit_len); 3182 fputs(buf, ecdhresp); 3183 fputc('\n', ecdhresp); 3184 fputs("QeIUTy = ", ecdhresp); 3185 to_hex_str(buf, &ecpriv->publicValue.data[1 + uit_len], uit_len); 3186 fputs(buf, ecdhresp); 3187 fputc('\n', ecdhresp); 3188 /* ECDH */ 3189 if (ECDH_Derive(&pubkey, current_ecparams, &ecpriv->privateValue, 3190 PR_FALSE, &ZZ) != SECSuccess) { 3191 fprintf(stderr, "Derive failed\n"); 3192 goto loser; 3193 } 3194 /* output hash of ZZ */ 3195 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { 3196 fprintf(stderr, "hash of derived key failed\n"); 3197 goto loser; 3198 } 3199 SECITEM_FreeItem(&ZZ, PR_FALSE); 3200 fputs("HashZZ = ", ecdhresp); 3201 to_hex_str(buf, hashBuf, fips_hashLen(hash)); 3202 fputs(buf, ecdhresp); 3203 fputc('\n', ecdhresp); 3204 fputc('\n', ecdhresp); 3205 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 3206 ecpriv = NULL; 3207 continue; 3208 } 3209 } 3210 loser: 3211 if (ecpriv != NULL) { 3212 PORT_FreeArena(ecpriv->ecParams.arena, PR_TRUE); 3213 } 3214 for (i = 0; i < MAX_ECC_PARAMS; i++) { 3215 if (ecparams[i] != NULL) { 3216 PORT_FreeArena(ecparams[i]->arena, PR_FALSE); 3217 ecparams[i] = NULL; 3218 } 3219 } 3220 if (pubkey.data != NULL) { 3221 PORT_Free(pubkey.data); 3222 } 3223 fclose(ecdhreq); 3224 } 3225 3226 /* 3227 * Perform the ECDH Validity Test. 3228 * 3229 * reqfn is the pathname of the REQUEST file. 3230 * 3231 * The output RESPONSE file is written to stdout. 3232 */ 3233 void 3234 ecdh_verify(char *reqfn, PRBool response) 3235 { 3236 char buf[256]; /* holds one line from the input REQUEST file. 3237 * needs to be large enough to hold the longest 3238 * line "Qx = <144 hex digits>\n". 3239 */ 3240 FILE *ecdhreq; /* input stream from the REQUEST file */ 3241 FILE *ecdhresp; /* output stream to the RESPONSE file */ 3242 char curve[16]; /* "nistxddd" */ 3243 unsigned char hashBuf[HASH_LENGTH_MAX]; 3244 unsigned char cavsHashBuf[HASH_LENGTH_MAX]; 3245 unsigned char private_data[MAX_ECKEY_LEN]; 3246 ECParams *ecparams[MAX_ECC_PARAMS] = { NULL }; 3247 ECParams *current_ecparams = NULL; 3248 SECItem pubkey; 3249 SECItem ZZ; 3250 SECItem private_value; 3251 unsigned int i; 3252 unsigned int len = 0; 3253 int current_curve = -1; 3254 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ 3255 3256 ecdhreq = fopen(reqfn, "r"); 3257 ecdhresp = stdout; 3258 strcpy(curve, "nist"); 3259 pubkey.data = NULL; 3260 while (fgets(buf, sizeof buf, ecdhreq) != NULL) { 3261 /* a comment or blank line */ 3262 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 3263 fputs(buf, ecdhresp); 3264 continue; 3265 } 3266 if (buf[0] == '[') { 3267 /* [Ex] */ 3268 if (buf[1] == 'E' && buf[3] == ']') { 3269 current_curve = buf[2] - 'A'; 3270 fputs(buf, ecdhresp); 3271 continue; 3272 } 3273 /* [Curve selected: x-nnn */ 3274 if (strncmp(buf, "[Curve ", 7) == 0) { 3275 const char *src; 3276 char *dst; 3277 SECItem *encodedparams; 3278 3279 if ((current_curve < 0) || (current_curve > MAX_ECC_PARAMS)) { 3280 fprintf(stderr, "No curve type defined\n"); 3281 goto loser; 3282 } 3283 3284 src = &buf[1]; 3285 /* skip passed the colon */ 3286 while (*src && *src != ':') 3287 src++; 3288 if (*src != ':') { 3289 fprintf(stderr, 3290 "No colon in curve selected statement\n%s", buf); 3291 goto loser; 3292 } 3293 src++; 3294 /* skip to the first non-space */ 3295 while (*src && *src == ' ') 3296 src++; 3297 dst = &curve[4]; 3298 *dst++ = tolower((unsigned char)*src); 3299 src += 2; /* skip the hyphen */ 3300 *dst++ = *src++; 3301 *dst++ = *src++; 3302 *dst++ = *src++; 3303 *dst = '\0'; 3304 if (ecparams[current_curve] != NULL) { 3305 PORT_FreeArena(ecparams[current_curve]->arena, PR_FALSE); 3306 ecparams[current_curve] = NULL; 3307 } 3308 encodedparams = getECParams(curve); 3309 if (encodedparams == NULL) { 3310 fprintf(stderr, "Unknown curve %s.\n", curve); 3311 goto loser; 3312 } 3313 if (EC_DecodeParams(encodedparams, &ecparams[current_curve]) != SECSuccess) { 3314 fprintf(stderr, "Curve %s not supported.\n", curve); 3315 goto loser; 3316 } 3317 SECITEM_FreeItem(encodedparams, PR_TRUE); 3318 fputs(buf, ecdhresp); 3319 continue; 3320 } 3321 /* [Ex - SHAxxx] */ 3322 if (buf[1] == 'E' && buf[3] == ' ') { 3323 const char *src; 3324 current_curve = buf[2] - 'A'; 3325 if ((current_curve < 0) || (current_curve > 256)) { 3326 fprintf(stderr, "bad curve type defined (%c)\n", buf[2]); 3327 goto loser; 3328 } 3329 current_ecparams = ecparams[current_curve]; 3330 if (current_ecparams == NULL) { 3331 fprintf(stderr, "no curve defined for type %c defined\n", 3332 buf[2]); 3333 goto loser; 3334 } 3335 /* skip passed the colon */ 3336 src = &buf[1]; 3337 while (*src && *src != '-') 3338 src++; 3339 if (*src != '-') { 3340 fprintf(stderr, 3341 "No data in curve selected statement\n%s", buf); 3342 goto loser; 3343 } 3344 src++; 3345 /* skip to the first non-space */ 3346 while (*src && *src == ' ') 3347 src++; 3348 hash = hash_string_to_hashType(src); 3349 if (hash == HASH_AlgNULL) { 3350 fprintf(ecdhresp, "ERROR: Unable to find SHAAlg type"); 3351 goto loser; 3352 } 3353 fputs(buf, ecdhresp); 3354 continue; 3355 } 3356 fputs(buf, ecdhresp); 3357 continue; 3358 } 3359 /* COUNT = ... */ 3360 if (strncmp(buf, "COUNT", 5) == 0) { 3361 fputs(buf, ecdhresp); 3362 if (current_ecparams == NULL) { 3363 fprintf(stderr, "no curve defined for type %c defined\n", 3364 buf[2]); 3365 goto loser; 3366 } 3367 len = (current_ecparams->fieldID.size + 7) >> 3; 3368 if (pubkey.data != NULL) { 3369 PORT_Free(pubkey.data); 3370 pubkey.data = NULL; 3371 } 3372 SECITEM_AllocItem(NULL, &pubkey, EC_GetPointSize(current_ecparams)); 3373 if (pubkey.data == NULL) { 3374 goto loser; 3375 } 3376 pubkey.data[0] = EC_POINT_FORM_UNCOMPRESSED; 3377 continue; 3378 } 3379 /* QeCAVSx = ... */ 3380 if (strncmp(buf, "QeCAVSx", 7) == 0) { 3381 fputs(buf, ecdhresp); 3382 i = 7; 3383 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3384 i++; 3385 } 3386 from_hex_str(&pubkey.data[1], len, &buf[i]); 3387 continue; 3388 } 3389 /* QeCAVSy = ... */ 3390 if (strncmp(buf, "QeCAVSy", 7) == 0) { 3391 fputs(buf, ecdhresp); 3392 i = 7; 3393 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3394 i++; 3395 } 3396 from_hex_str(&pubkey.data[1 + len], len, &buf[i]); 3397 continue; 3398 } 3399 if (strncmp(buf, "deIUT", 5) == 0) { 3400 fputs(buf, ecdhresp); 3401 i = 5; 3402 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3403 i++; 3404 } 3405 from_hex_str(private_data, len, &buf[i]); 3406 private_value.data = private_data; 3407 private_value.len = len; 3408 continue; 3409 } 3410 if (strncmp(buf, "QeIUTx", 6) == 0) { 3411 fputs(buf, ecdhresp); 3412 continue; 3413 } 3414 if (strncmp(buf, "QeIUTy", 6) == 0) { 3415 fputs(buf, ecdhresp); 3416 continue; 3417 } 3418 if ((strncmp(buf, "CAVSHashZZ", 10) == 0) || 3419 (strncmp(buf, "HashZZ", 6) == 0)) { 3420 fputs(buf, ecdhresp); 3421 i = (buf[0] == 'C') ? 10 : 6; 3422 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3423 i++; 3424 } 3425 from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); 3426 if (current_ecparams == NULL) { 3427 fprintf(stderr, "no curve defined for type defined\n"); 3428 goto loser; 3429 } 3430 /* validate CAVS public key */ 3431 if (EC_ValidatePublicKey(current_ecparams, &pubkey) != SECSuccess) { 3432 #ifdef VERBOSE_REASON 3433 fprintf(ecdhresp, "Result = F # key didn't validate\n"); 3434 #else 3435 fprintf(ecdhresp, "Result = F\n"); 3436 #endif 3437 continue; 3438 } 3439 3440 /* ECDH */ 3441 if (ECDH_Derive(&pubkey, current_ecparams, &private_value, 3442 PR_FALSE, &ZZ) != SECSuccess) { 3443 #ifdef VERBOSE_REASON 3444 fprintf(ecdhresp, "Result = F # derive failure\n"); 3445 #else 3446 fprintf(ecdhresp, "Result = F\n"); 3447 #endif 3448 continue; 3449 } 3450 /* output ZZ */ 3451 #ifndef MATCH_OPENSSL 3452 fputs("Z = ", ecdhresp); 3453 to_hex_str(buf, ZZ.data, ZZ.len); 3454 fputs(buf, ecdhresp); 3455 fputc('\n', ecdhresp); 3456 #endif 3457 3458 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { 3459 fprintf(stderr, "hash of derived key failed\n"); 3460 goto loser; 3461 } 3462 SECITEM_FreeItem(&ZZ, PR_FALSE); 3463 #ifndef MATCH_NIST 3464 fputs("IUTHashZZ = ", ecdhresp); 3465 to_hex_str(buf, hashBuf, fips_hashLen(hash)); 3466 fputs(buf, ecdhresp); 3467 fputc('\n', ecdhresp); 3468 #endif 3469 if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { 3470 #ifdef VERBOSE_REASON 3471 fprintf(ecdhresp, "Result = F # hash doesn't match\n"); 3472 #else 3473 fprintf(ecdhresp, "Result = F\n"); 3474 #endif 3475 } else { 3476 fprintf(ecdhresp, "Result = P\n"); 3477 } 3478 #ifndef MATCH_OPENSSL 3479 fputc('\n', ecdhresp); 3480 #endif 3481 continue; 3482 } 3483 } 3484 loser: 3485 for (i = 0; i < MAX_ECC_PARAMS; i++) { 3486 if (ecparams[i] != NULL) { 3487 PORT_FreeArena(ecparams[i]->arena, PR_FALSE); 3488 ecparams[i] = NULL; 3489 } 3490 } 3491 if (pubkey.data != NULL) { 3492 PORT_Free(pubkey.data); 3493 } 3494 fclose(ecdhreq); 3495 } 3496 3497 /* 3498 * Perform the DH Functional Test. 3499 * 3500 * reqfn is the pathname of the REQUEST file. 3501 * 3502 * The output RESPONSE file is written to stdout. 3503 */ 3504 #define MAX_ECC_PARAMS 256 3505 void 3506 dh_functional(char *reqfn, PRBool response) 3507 { 3508 char buf[1024]; /* holds one line from the input REQUEST file. 3509 * needs to be large enough to hold the longest 3510 * line "YephCAVS = <512 hex digits>\n". 3511 */ 3512 FILE *dhreq; /* input stream from the REQUEST file */ 3513 FILE *dhresp; /* output stream to the RESPONSE file */ 3514 unsigned char hashBuf[HASH_LENGTH_MAX]; 3515 DSAPrivateKey *dsapriv = NULL; 3516 PQGParams pqg = { 0 }; 3517 unsigned char pubkeydata[DSA_MAX_P_BITS / 8]; 3518 SECItem pubkey; 3519 SECItem ZZ; 3520 unsigned int i, j; 3521 unsigned int pgySize; 3522 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ 3523 3524 dhreq = fopen(reqfn, "r"); 3525 dhresp = stdout; 3526 while (fgets(buf, sizeof buf, dhreq) != NULL) { 3527 /* a comment or blank line */ 3528 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 3529 fputs(buf, dhresp); 3530 continue; 3531 } 3532 if (buf[0] == '[') { 3533 /* [Fx - SHAxxx] */ 3534 if (buf[1] == 'F' && buf[3] == ' ') { 3535 const char *src; 3536 /* skip passed the colon */ 3537 src = &buf[1]; 3538 while (*src && *src != '-') 3539 src++; 3540 if (*src != '-') { 3541 fprintf(stderr, "No hash specified\n%s", buf); 3542 goto loser; 3543 } 3544 src++; 3545 /* skip to the first non-space */ 3546 while (*src && *src == ' ') 3547 src++; 3548 hash = hash_string_to_hashType(src); 3549 if (hash == HASH_AlgNULL) { 3550 fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); 3551 goto loser; 3552 } 3553 /* clear the PQG parameters */ 3554 if (pqg.prime.data) { /* P */ 3555 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 3556 } 3557 if (pqg.subPrime.data) { /* Q */ 3558 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 3559 } 3560 if (pqg.base.data) { /* G */ 3561 SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 3562 } 3563 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ 3564 SECITEM_AllocItem(NULL, &pqg.prime, pgySize); 3565 SECITEM_AllocItem(NULL, &pqg.base, pgySize); 3566 pqg.prime.len = pqg.base.len = pgySize; 3567 3568 /* set q to the max allows */ 3569 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8); 3570 pqg.subPrime.len = DSA_MAX_Q_BITS / 8; 3571 fputs(buf, dhresp); 3572 continue; 3573 } 3574 fputs(buf, dhresp); 3575 continue; 3576 } 3577 if (buf[0] == 'P') { 3578 i = 1; 3579 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3580 i++; 3581 } 3582 for (j = 0; j < pqg.prime.len; i += 2, j++) { 3583 if (!isxdigit((unsigned char)buf[i])) { 3584 pqg.prime.len = j; 3585 break; 3586 } 3587 hex_to_byteval(&buf[i], &pqg.prime.data[j]); 3588 } 3589 3590 fputs(buf, dhresp); 3591 continue; 3592 } 3593 3594 /* Q = ... */ 3595 if (buf[0] == 'Q') { 3596 i = 1; 3597 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3598 i++; 3599 } 3600 for (j = 0; j < pqg.subPrime.len; i += 2, j++) { 3601 if (!isxdigit((unsigned char)buf[i])) { 3602 pqg.subPrime.len = j; 3603 break; 3604 } 3605 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); 3606 } 3607 3608 fputs(buf, dhresp); 3609 continue; 3610 } 3611 3612 /* G = ... */ 3613 if (buf[0] == 'G') { 3614 i = 1; 3615 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3616 i++; 3617 } 3618 for (j = 0; j < pqg.base.len; i += 2, j++) { 3619 if (!isxdigit((unsigned char)buf[i])) { 3620 pqg.base.len = j; 3621 break; 3622 } 3623 hex_to_byteval(&buf[i], &pqg.base.data[j]); 3624 } 3625 3626 fputs(buf, dhresp); 3627 continue; 3628 } 3629 3630 /* COUNT = ... */ 3631 if (strncmp(buf, "COUNT", 5) == 0) { 3632 fputs(buf, dhresp); 3633 continue; 3634 } 3635 3636 /* YephemCAVS = ... */ 3637 if (strncmp(buf, "YephemCAVS", 10) == 0) { 3638 fputs(buf, dhresp); 3639 i = 10; 3640 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3641 i++; 3642 } 3643 from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); 3644 pubkey.data = pubkeydata; 3645 pubkey.len = pqg.prime.len; 3646 3647 /* generate FCC key pair, nist uses pqg rather then pg, 3648 * so use DSA to generate the key */ 3649 if (DSA_NewKey(&pqg, &dsapriv) != SECSuccess) { 3650 fprintf(stderr, "Failed to generate new key\n"); 3651 goto loser; 3652 } 3653 fputs("XephemIUT = ", dhresp); 3654 to_hex_str(buf, dsapriv->privateValue.data, dsapriv->privateValue.len); 3655 fputs(buf, dhresp); 3656 fputc('\n', dhresp); 3657 fputs("YephemIUT = ", dhresp); 3658 to_hex_str(buf, dsapriv->publicValue.data, dsapriv->publicValue.len); 3659 fputs(buf, dhresp); 3660 fputc('\n', dhresp); 3661 /* DH */ 3662 if (DH_Derive(&pubkey, &pqg.prime, &dsapriv->privateValue, 3663 &ZZ, pqg.prime.len) != SECSuccess) { 3664 fprintf(stderr, "Derive failed\n"); 3665 goto loser; 3666 } 3667 /* output hash of ZZ */ 3668 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { 3669 fprintf(stderr, "hash of derived key failed\n"); 3670 goto loser; 3671 } 3672 SECITEM_FreeItem(&ZZ, PR_FALSE); 3673 fputs("HashZZ = ", dhresp); 3674 to_hex_str(buf, hashBuf, fips_hashLen(hash)); 3675 fputs(buf, dhresp); 3676 fputc('\n', dhresp); 3677 fputc('\n', dhresp); 3678 PORT_FreeArena(dsapriv->params.arena, PR_TRUE); 3679 dsapriv = NULL; 3680 continue; 3681 } 3682 } 3683 loser: 3684 if (dsapriv != NULL) { 3685 PORT_FreeArena(dsapriv->params.arena, PR_TRUE); 3686 } 3687 fclose(dhreq); 3688 } 3689 3690 /* 3691 * Perform the DH Validity Test. 3692 * 3693 * reqfn is the pathname of the REQUEST file. 3694 * 3695 * The output RESPONSE file is written to stdout. 3696 */ 3697 void 3698 dh_verify(char *reqfn, PRBool response) 3699 { 3700 char buf[1024]; /* holds one line from the input REQUEST file. 3701 * needs to be large enough to hold the longest 3702 * line "YephCAVS = <512 hex digits>\n". 3703 */ 3704 FILE *dhreq; /* input stream from the REQUEST file */ 3705 FILE *dhresp; /* output stream to the RESPONSE file */ 3706 unsigned char hashBuf[HASH_LENGTH_MAX]; 3707 unsigned char cavsHashBuf[HASH_LENGTH_MAX]; 3708 PQGParams pqg = { 0 }; 3709 unsigned char pubkeydata[DSA_MAX_P_BITS / 8]; 3710 unsigned char privkeydata[DSA_MAX_P_BITS / 8]; 3711 SECItem pubkey; 3712 SECItem privkey; 3713 SECItem ZZ; 3714 unsigned int i, j; 3715 unsigned int pgySize; 3716 HASH_HashType hash = HASH_AlgNULL; /* type of SHA Alg */ 3717 3718 dhreq = fopen(reqfn, "r"); 3719 dhresp = stdout; 3720 while (fgets(buf, sizeof buf, dhreq) != NULL) { 3721 /* a comment or blank line */ 3722 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 3723 fputs(buf, dhresp); 3724 continue; 3725 } 3726 if (buf[0] == '[') { 3727 /* [Fx - SHAxxx] */ 3728 if (buf[1] == 'F' && buf[3] == ' ') { 3729 const char *src; 3730 /* skip passed the colon */ 3731 src = &buf[1]; 3732 while (*src && *src != '-') 3733 src++; 3734 if (*src != '-') { 3735 fprintf(stderr, "No hash specified\n%s", buf); 3736 goto loser; 3737 } 3738 src++; 3739 /* skip to the first non-space */ 3740 while (*src && *src == ' ') 3741 src++; 3742 hash = hash_string_to_hashType(src); 3743 if (hash == HASH_AlgNULL) { 3744 fprintf(dhresp, "ERROR: Unable to find SHAAlg type"); 3745 goto loser; 3746 } 3747 /* clear the PQG parameters */ 3748 if (pqg.prime.data) { /* P */ 3749 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 3750 } 3751 if (pqg.subPrime.data) { /* Q */ 3752 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 3753 } 3754 if (pqg.base.data) { /* G */ 3755 SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 3756 } 3757 pgySize = DSA_MAX_P_BITS / 8; /* change if more key sizes are supported in CAVS */ 3758 SECITEM_AllocItem(NULL, &pqg.prime, pgySize); 3759 SECITEM_AllocItem(NULL, &pqg.base, pgySize); 3760 pqg.prime.len = pqg.base.len = pgySize; 3761 3762 /* set q to the max allows */ 3763 SECITEM_AllocItem(NULL, &pqg.subPrime, DSA_MAX_Q_BITS / 8); 3764 pqg.subPrime.len = DSA_MAX_Q_BITS / 8; 3765 fputs(buf, dhresp); 3766 continue; 3767 } 3768 fputs(buf, dhresp); 3769 continue; 3770 } 3771 if (buf[0] == 'P') { 3772 i = 1; 3773 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3774 i++; 3775 } 3776 for (j = 0; j < pqg.prime.len; i += 2, j++) { 3777 if (!isxdigit((unsigned char)buf[i])) { 3778 pqg.prime.len = j; 3779 break; 3780 } 3781 hex_to_byteval(&buf[i], &pqg.prime.data[j]); 3782 } 3783 3784 fputs(buf, dhresp); 3785 continue; 3786 } 3787 3788 /* Q = ... */ 3789 if (buf[0] == 'Q') { 3790 i = 1; 3791 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3792 i++; 3793 } 3794 for (j = 0; j < pqg.subPrime.len; i += 2, j++) { 3795 if (!isxdigit((unsigned char)buf[i])) { 3796 pqg.subPrime.len = j; 3797 break; 3798 } 3799 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); 3800 } 3801 3802 fputs(buf, dhresp); 3803 continue; 3804 } 3805 3806 /* G = ... */ 3807 if (buf[0] == 'G') { 3808 i = 1; 3809 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3810 i++; 3811 } 3812 for (j = 0; j < pqg.base.len; i += 2, j++) { 3813 if (!isxdigit((unsigned char)buf[i])) { 3814 pqg.base.len = j; 3815 break; 3816 } 3817 hex_to_byteval(&buf[i], &pqg.base.data[j]); 3818 } 3819 3820 fputs(buf, dhresp); 3821 continue; 3822 } 3823 3824 /* COUNT = ... */ 3825 if (strncmp(buf, "COUNT", 5) == 0) { 3826 fputs(buf, dhresp); 3827 continue; 3828 } 3829 3830 /* YephemCAVS = ... */ 3831 if (strncmp(buf, "YephemCAVS", 10) == 0) { 3832 fputs(buf, dhresp); 3833 i = 10; 3834 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3835 i++; 3836 } 3837 from_hex_str(pubkeydata, pqg.prime.len, &buf[i]); 3838 pubkey.data = pubkeydata; 3839 pubkey.len = pqg.prime.len; 3840 continue; 3841 } 3842 /* XephemUIT = ... */ 3843 if (strncmp(buf, "XephemIUT", 9) == 0) { 3844 fputs(buf, dhresp); 3845 i = 9; 3846 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3847 i++; 3848 } 3849 from_hex_str(privkeydata, pqg.subPrime.len, &buf[i]); 3850 privkey.data = privkeydata; 3851 privkey.len = pqg.subPrime.len; 3852 continue; 3853 } 3854 /* YephemUIT = ... */ 3855 if (strncmp(buf, "YephemIUT", 9) == 0) { 3856 fputs(buf, dhresp); 3857 continue; 3858 } 3859 /* CAVSHashZZ = ... */ 3860 if ((strncmp(buf, "CAVSHashZZ", 10) == 0) || 3861 (strncmp(buf, "HashZZ", 6) == 0)) { 3862 fputs(buf, dhresp); 3863 i = buf[0] == 'C' ? 10 : 6; 3864 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 3865 i++; 3866 } 3867 from_hex_str(cavsHashBuf, fips_hashLen(hash), &buf[i]); 3868 /* do the DH operation*/ 3869 if (DH_Derive(&pubkey, &pqg.prime, &privkey, 3870 &ZZ, pqg.prime.len) != SECSuccess) { 3871 fprintf(stderr, "Derive failed\n"); 3872 goto loser; 3873 } 3874 /* output ZZ */ 3875 #ifndef MATCH_OPENSSL 3876 fputs("Z = ", dhresp); 3877 to_hex_str(buf, ZZ.data, ZZ.len); 3878 fputs(buf, dhresp); 3879 fputc('\n', dhresp); 3880 #endif 3881 if (fips_hashBuf(hash, hashBuf, ZZ.data, ZZ.len) != SECSuccess) { 3882 fprintf(stderr, "hash of derived key failed\n"); 3883 goto loser; 3884 } 3885 SECITEM_FreeItem(&ZZ, PR_FALSE); 3886 #ifndef MATCH_NIST 3887 fputs("IUTHashZZ = ", dhresp); 3888 to_hex_str(buf, hashBuf, fips_hashLen(hash)); 3889 fputs(buf, dhresp); 3890 fputc('\n', dhresp); 3891 #endif 3892 if (memcmp(hashBuf, cavsHashBuf, fips_hashLen(hash)) != 0) { 3893 fprintf(dhresp, "Result = F\n"); 3894 } else { 3895 fprintf(dhresp, "Result = P\n"); 3896 } 3897 #ifndef MATCH_OPENSSL 3898 fputc('\n', dhresp); 3899 #endif 3900 continue; 3901 } 3902 } 3903 loser: 3904 fclose(dhreq); 3905 } 3906 3907 PRBool 3908 isblankline(char *b) 3909 { 3910 while (isspace((unsigned char)*b)) 3911 b++; 3912 if ((*b == '\n') || (*b == 0)) { 3913 return PR_TRUE; 3914 } 3915 return PR_FALSE; 3916 } 3917 3918 static int debug = 0; 3919 3920 /* 3921 * Perform the Hash_DRBG (CAVS) for the RNG algorithm 3922 * 3923 * reqfn is the pathname of the REQUEST file. 3924 * 3925 * The output RESPONSE file is written to stdout. 3926 */ 3927 void 3928 drbg(char *reqfn) 3929 { 3930 char buf[2000]; /* test case has some very long lines, returned bits 3931 * as high as 800 bytes (6400 bits). That 1600 byte 3932 * plus a tag */ 3933 char buf2[2000]; 3934 FILE *rngreq; /* input stream from the REQUEST file */ 3935 FILE *rngresp; /* output stream to the RESPONSE file */ 3936 3937 unsigned int i, j; 3938 #ifdef HANDLE_PREDICTION_RESISTANCE 3939 PRBool predictionResistance = PR_FALSE; 3940 #endif 3941 unsigned char *nonce = NULL; 3942 int nonceLen = 0; 3943 unsigned char *personalizationString = NULL; 3944 int personalizationStringLen = 0; 3945 unsigned char *additionalInput = NULL; 3946 int additionalInputLen = 0; 3947 unsigned char *entropyInput = NULL; 3948 int entropyInputLen = 0; 3949 unsigned char *predictedreturn_bytes = NULL; 3950 unsigned char *return_bytes = NULL; 3951 int return_bytes_len = 0; 3952 enum { NONE, 3953 INSTANTIATE, 3954 GENERATE, 3955 RESEED, 3956 RESULT } command = 3957 NONE; 3958 PRBool genResult = PR_FALSE; 3959 SECStatus rv; 3960 3961 rngreq = fopen(reqfn, "r"); 3962 rngresp = stdout; 3963 while (fgets(buf, sizeof buf, rngreq) != NULL) { 3964 switch (command) { 3965 case INSTANTIATE: 3966 if (debug) { 3967 fputs("# PRNGTEST_Instantiate(", rngresp); 3968 to_hex_str(buf2, entropyInput, entropyInputLen); 3969 fputs(buf2, rngresp); 3970 fprintf(rngresp, ",%d,", entropyInputLen); 3971 to_hex_str(buf2, nonce, nonceLen); 3972 fputs(buf2, rngresp); 3973 fprintf(rngresp, ",%d,", nonceLen); 3974 to_hex_str(buf2, personalizationString, 3975 personalizationStringLen); 3976 fputs(buf2, rngresp); 3977 fprintf(rngresp, ",%d)\n", personalizationStringLen); 3978 } 3979 rv = PRNGTEST_Instantiate(entropyInput, entropyInputLen, 3980 nonce, nonceLen, 3981 personalizationString, 3982 personalizationStringLen); 3983 if (rv != SECSuccess) { 3984 goto loser; 3985 } 3986 break; 3987 3988 case GENERATE: 3989 case RESULT: 3990 memset(return_bytes, 0, return_bytes_len); 3991 if (debug) { 3992 fputs("# PRNGTEST_Generate(returnbytes", rngresp); 3993 fprintf(rngresp, ",%d,", return_bytes_len); 3994 to_hex_str(buf2, additionalInput, additionalInputLen); 3995 fputs(buf2, rngresp); 3996 fprintf(rngresp, ",%d)\n", additionalInputLen); 3997 } 3998 rv = PRNGTEST_Generate((PRUint8 *)return_bytes, 3999 return_bytes_len, 4000 (PRUint8 *)additionalInput, 4001 additionalInputLen); 4002 if (rv != SECSuccess) { 4003 goto loser; 4004 } 4005 4006 if (command == RESULT) { 4007 fputs("ReturnedBits = ", rngresp); 4008 to_hex_str(buf2, return_bytes, return_bytes_len); 4009 fputs(buf2, rngresp); 4010 fputc('\n', rngresp); 4011 if (debug) { 4012 fputs("# PRNGTEST_Uninstantiate()\n", rngresp); 4013 } 4014 rv = PRNGTEST_Uninstantiate(); 4015 if (rv != SECSuccess) { 4016 goto loser; 4017 } 4018 } else if (debug) { 4019 fputs("#ReturnedBits = ", rngresp); 4020 to_hex_str(buf2, return_bytes, return_bytes_len); 4021 fputs(buf2, rngresp); 4022 fputc('\n', rngresp); 4023 } 4024 4025 memset(additionalInput, 0, additionalInputLen); 4026 break; 4027 4028 case RESEED: 4029 if (entropyInput || additionalInput) { 4030 if (debug) { 4031 fputs("# PRNGTEST_Reseed(", rngresp); 4032 fprintf(rngresp, ",%d,", return_bytes_len); 4033 to_hex_str(buf2, entropyInput, entropyInputLen); 4034 fputs(buf2, rngresp); 4035 fprintf(rngresp, ",%d,", entropyInputLen); 4036 to_hex_str(buf2, additionalInput, additionalInputLen); 4037 fputs(buf2, rngresp); 4038 fprintf(rngresp, ",%d)\n", additionalInputLen); 4039 } 4040 rv = PRNGTEST_Reseed(entropyInput, entropyInputLen, 4041 additionalInput, additionalInputLen); 4042 if (rv != SECSuccess) { 4043 goto loser; 4044 } 4045 } 4046 memset(entropyInput, 0, entropyInputLen); 4047 memset(additionalInput, 0, additionalInputLen); 4048 break; 4049 case NONE: 4050 break; 4051 } 4052 command = NONE; 4053 4054 /* a comment or blank line */ 4055 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 4056 fputs(buf, rngresp); 4057 continue; 4058 } 4059 4060 /* [Hash - SHA256] */ 4061 if (strncmp(buf, "[SHA-256]", 9) == 0) { 4062 fputs(buf, rngresp); 4063 continue; 4064 } 4065 4066 if (strncmp(buf, "[PredictionResistance", 21) == 0) { 4067 #ifdef HANDLE_PREDICTION_RESISTANCE 4068 i = 21; 4069 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4070 i++; 4071 } 4072 if (strncmp(buf, "False", 5) == 0) { 4073 predictionResistance = PR_FALSE; 4074 } else { 4075 predictionResistance = PR_TRUE; 4076 } 4077 #endif 4078 4079 fputs(buf, rngresp); 4080 continue; 4081 } 4082 4083 if (strncmp(buf, "[ReturnedBitsLen", 16) == 0) { 4084 if (return_bytes) { 4085 PORT_ZFree(return_bytes, return_bytes_len); 4086 return_bytes = NULL; 4087 } 4088 if (predictedreturn_bytes) { 4089 PORT_ZFree(predictedreturn_bytes, return_bytes_len); 4090 predictedreturn_bytes = NULL; 4091 } 4092 return_bytes_len = 0; 4093 if (sscanf(buf, "[ReturnedBitsLen = %d]", &return_bytes_len) != 1) { 4094 goto loser; 4095 } 4096 return_bytes_len = return_bytes_len / 8; 4097 if (return_bytes_len > 0) { 4098 return_bytes = PORT_Alloc(return_bytes_len); 4099 predictedreturn_bytes = PORT_Alloc(return_bytes_len); 4100 } 4101 fputs(buf, rngresp); 4102 continue; 4103 } 4104 4105 if (strncmp(buf, "[EntropyInputLen", 16) == 0) { 4106 if (entropyInput) { 4107 PORT_ZFree(entropyInput, entropyInputLen); 4108 entropyInput = NULL; 4109 entropyInputLen = 0; 4110 } 4111 if (sscanf(buf, "[EntropyInputLen = %d]", &entropyInputLen) != 1) { 4112 goto loser; 4113 } 4114 entropyInputLen = entropyInputLen / 8; 4115 if (entropyInputLen > 0) { 4116 entropyInput = PORT_Alloc(entropyInputLen); 4117 } 4118 fputs(buf, rngresp); 4119 continue; 4120 } 4121 4122 if (strncmp(buf, "[NonceLen", 9) == 0) { 4123 if (nonce) { 4124 PORT_ZFree(nonce, nonceLen); 4125 nonce = NULL; 4126 nonceLen = 0; 4127 } 4128 4129 if (sscanf(buf, "[NonceLen = %d]", &nonceLen) != 1) { 4130 goto loser; 4131 } 4132 nonceLen = nonceLen / 8; 4133 if (nonceLen > 0) { 4134 nonce = PORT_Alloc(nonceLen); 4135 } 4136 fputs(buf, rngresp); 4137 continue; 4138 } 4139 4140 if (strncmp(buf, "[PersonalizationStringLen", 16) == 0) { 4141 if (personalizationString) { 4142 PORT_ZFree(personalizationString, personalizationStringLen); 4143 personalizationString = NULL; 4144 personalizationStringLen = 0; 4145 } 4146 4147 if (sscanf(buf, "[PersonalizationStringLen = %d]", &personalizationStringLen) != 1) { 4148 goto loser; 4149 } 4150 personalizationStringLen = personalizationStringLen / 8; 4151 if (personalizationStringLen > 0) { 4152 personalizationString = PORT_Alloc(personalizationStringLen); 4153 } 4154 fputs(buf, rngresp); 4155 4156 continue; 4157 } 4158 4159 if (strncmp(buf, "[AdditionalInputLen", 16) == 0) { 4160 if (additionalInput) { 4161 PORT_ZFree(additionalInput, additionalInputLen); 4162 additionalInput = NULL; 4163 additionalInputLen = 0; 4164 } 4165 4166 if (sscanf(buf, "[AdditionalInputLen = %d]", &additionalInputLen) != 1) { 4167 goto loser; 4168 } 4169 additionalInputLen = additionalInputLen / 8; 4170 if (additionalInputLen > 0) { 4171 additionalInput = PORT_Alloc(additionalInputLen); 4172 } 4173 fputs(buf, rngresp); 4174 continue; 4175 } 4176 4177 if (strncmp(buf, "COUNT", 5) == 0) { 4178 /* zeroize the variables for the test with this data set */ 4179 if (entropyInput) { 4180 memset(entropyInput, 0, entropyInputLen); 4181 } 4182 if (nonce) { 4183 memset(nonce, 0, nonceLen); 4184 } 4185 if (personalizationString) { 4186 memset(personalizationString, 0, personalizationStringLen); 4187 } 4188 if (additionalInput) { 4189 memset(additionalInput, 0, additionalInputLen); 4190 } 4191 genResult = PR_FALSE; 4192 4193 fputs(buf, rngresp); 4194 continue; 4195 } 4196 4197 /* EntropyInputReseed = ... */ 4198 if (strncmp(buf, "EntropyInputReseed", 18) == 0) { 4199 if (entropyInput) { 4200 memset(entropyInput, 0, entropyInputLen); 4201 i = 18; 4202 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4203 i++; 4204 } 4205 4206 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<entropyInputLen*/ 4207 hex_to_byteval(&buf[i], &entropyInput[j]); 4208 } 4209 } 4210 fputs(buf, rngresp); 4211 continue; 4212 } 4213 4214 /* AttionalInputReseed = ... */ 4215 if (strncmp(buf, "AdditionalInputReseed", 21) == 0) { 4216 if (additionalInput) { 4217 memset(additionalInput, 0, additionalInputLen); 4218 i = 21; 4219 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4220 i++; 4221 } 4222 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/ 4223 hex_to_byteval(&buf[i], &additionalInput[j]); 4224 } 4225 } 4226 command = RESEED; 4227 fputs(buf, rngresp); 4228 continue; 4229 } 4230 4231 /* Entropy input = ... */ 4232 if (strncmp(buf, "EntropyInput", 12) == 0) { 4233 i = 12; 4234 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4235 i++; 4236 } 4237 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<entropyInputLen*/ 4238 hex_to_byteval(&buf[i], &entropyInput[j]); 4239 } 4240 fputs(buf, rngresp); 4241 continue; 4242 } 4243 4244 /* nouce = ... */ 4245 if (strncmp(buf, "Nonce", 5) == 0) { 4246 i = 5; 4247 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4248 i++; 4249 } 4250 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<nonceLen*/ 4251 hex_to_byteval(&buf[i], &nonce[j]); 4252 } 4253 fputs(buf, rngresp); 4254 continue; 4255 } 4256 4257 /* Personalization string = ... */ 4258 if (strncmp(buf, "PersonalizationString", 21) == 0) { 4259 if (personalizationString) { 4260 i = 21; 4261 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4262 i++; 4263 } 4264 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<personalizationStringLen*/ 4265 hex_to_byteval(&buf[i], &personalizationString[j]); 4266 } 4267 } 4268 fputs(buf, rngresp); 4269 command = INSTANTIATE; 4270 continue; 4271 } 4272 4273 /* Additional input = ... */ 4274 if (strncmp(buf, "AdditionalInput", 15) == 0) { 4275 if (additionalInput) { 4276 i = 15; 4277 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4278 i++; 4279 } 4280 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/ 4281 hex_to_byteval(&buf[i], &additionalInput[j]); 4282 } 4283 } 4284 if (genResult) { 4285 command = RESULT; 4286 } else { 4287 command = GENERATE; 4288 genResult = PR_TRUE; /* next time generate result */ 4289 } 4290 fputs(buf, rngresp); 4291 continue; 4292 } 4293 4294 /* Returned bits = ... */ 4295 if (strncmp(buf, "ReturnedBits", 12) == 0) { 4296 i = 12; 4297 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4298 i++; 4299 } 4300 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { /*j<additionalInputLen*/ 4301 hex_to_byteval(&buf[i], &predictedreturn_bytes[j]); 4302 } 4303 4304 if (memcmp(return_bytes, 4305 predictedreturn_bytes, return_bytes_len) != 0) { 4306 if (debug) { 4307 fprintf(rngresp, "# Generate failed:\n"); 4308 fputs("# predicted=", rngresp); 4309 to_hex_str(buf, predictedreturn_bytes, 4310 return_bytes_len); 4311 fputs(buf, rngresp); 4312 fputs("\n# actual = ", rngresp); 4313 fputs(buf2, rngresp); 4314 fputc('\n', rngresp); 4315 4316 } else { 4317 fprintf(stderr, "Generate failed:\n"); 4318 fputs(" predicted=", stderr); 4319 to_hex_str(buf, predictedreturn_bytes, 4320 return_bytes_len); 4321 fputs(buf, stderr); 4322 fputs("\n actual = ", stderr); 4323 fputs(buf2, stderr); 4324 fputc('\n', stderr); 4325 } 4326 } 4327 memset(predictedreturn_bytes, 0, return_bytes_len); 4328 4329 continue; 4330 } 4331 } 4332 loser: 4333 if (predictedreturn_bytes) { 4334 PORT_Free(predictedreturn_bytes); 4335 } 4336 if (return_bytes) { 4337 PORT_Free(return_bytes); 4338 } 4339 if (additionalInput) { 4340 PORT_Free(additionalInput); 4341 } 4342 if (personalizationString) { 4343 PORT_Free(personalizationString); 4344 } 4345 if (nonce) { 4346 PORT_Free(nonce); 4347 } 4348 if (entropyInput) { 4349 PORT_Free(entropyInput); 4350 } 4351 fclose(rngreq); 4352 } 4353 4354 /* 4355 * Perform the RNG Variable Seed Test (VST) for the RNG algorithm 4356 * "DSA - Generation of X", used both as specified and as a generic 4357 * purpose RNG. The presence of "Q = ..." in the REQUEST file 4358 * indicates we are using the algorithm as specified. 4359 * 4360 * reqfn is the pathname of the REQUEST file. 4361 * 4362 * The output RESPONSE file is written to stdout. 4363 */ 4364 void 4365 rng_vst(char *reqfn) 4366 { 4367 char buf[256]; /* holds one line from the input REQUEST file. 4368 * needs to be large enough to hold the longest 4369 * line "XSeed = <128 hex digits>\n". 4370 */ 4371 FILE *rngreq; /* input stream from the REQUEST file */ 4372 FILE *rngresp; /* output stream to the RESPONSE file */ 4373 unsigned int i, j; 4374 unsigned char Q[DSA1_SUBPRIME_LEN]; 4375 PRBool hasQ = PR_FALSE; 4376 unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */ 4377 unsigned char XKey[512 / 8]; 4378 unsigned char XSeed[512 / 8]; 4379 unsigned char GENX[DSA1_SIGNATURE_LEN]; 4380 unsigned char DSAX[DSA1_SUBPRIME_LEN]; 4381 SECStatus rv; 4382 4383 rngreq = fopen(reqfn, "r"); 4384 rngresp = stdout; 4385 while (fgets(buf, sizeof buf, rngreq) != NULL) { 4386 /* a comment or blank line */ 4387 if (buf[0] == '#' || buf[0] == '\n') { 4388 fputs(buf, rngresp); 4389 continue; 4390 } 4391 /* [Xchange - SHA1] */ 4392 if (buf[0] == '[') { 4393 fputs(buf, rngresp); 4394 continue; 4395 } 4396 /* Q = ... */ 4397 if (buf[0] == 'Q') { 4398 i = 1; 4399 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4400 i++; 4401 } 4402 for (j = 0; j < sizeof Q; i += 2, j++) { 4403 hex_to_byteval(&buf[i], &Q[j]); 4404 } 4405 fputs(buf, rngresp); 4406 hasQ = PR_TRUE; 4407 continue; 4408 } 4409 /* "COUNT = x" begins a new data set */ 4410 if (strncmp(buf, "COUNT", 5) == 0) { 4411 /* zeroize the variables for the test with this data set */ 4412 b = 0; 4413 memset(XKey, 0, sizeof XKey); 4414 memset(XSeed, 0, sizeof XSeed); 4415 fputs(buf, rngresp); 4416 continue; 4417 } 4418 /* b = ... */ 4419 if (buf[0] == 'b') { 4420 i = 1; 4421 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4422 i++; 4423 } 4424 b = atoi(&buf[i]); 4425 if (b < 160 || b > 512 || b % 8 != 0) { 4426 goto loser; 4427 } 4428 fputs(buf, rngresp); 4429 continue; 4430 } 4431 /* XKey = ... */ 4432 if (strncmp(buf, "XKey", 4) == 0) { 4433 i = 4; 4434 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4435 i++; 4436 } 4437 for (j = 0; j < b / 8; i += 2, j++) { 4438 hex_to_byteval(&buf[i], &XKey[j]); 4439 } 4440 fputs(buf, rngresp); 4441 continue; 4442 } 4443 /* XSeed = ... */ 4444 if (strncmp(buf, "XSeed", 5) == 0) { 4445 i = 5; 4446 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4447 i++; 4448 } 4449 for (j = 0; j < b / 8; i += 2, j++) { 4450 hex_to_byteval(&buf[i], &XSeed[j]); 4451 } 4452 fputs(buf, rngresp); 4453 4454 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); 4455 if (rv != SECSuccess) { 4456 goto loser; 4457 } 4458 fputs("X = ", rngresp); 4459 if (hasQ) { 4460 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); 4461 if (rv != SECSuccess) { 4462 goto loser; 4463 } 4464 to_hex_str(buf, DSAX, sizeof DSAX); 4465 } else { 4466 to_hex_str(buf, GENX, sizeof GENX); 4467 } 4468 fputs(buf, rngresp); 4469 fputc('\n', rngresp); 4470 continue; 4471 } 4472 } 4473 loser: 4474 fclose(rngreq); 4475 } 4476 4477 /* 4478 * Perform the RNG Monte Carlo Test (MCT) for the RNG algorithm 4479 * "DSA - Generation of X", used both as specified and as a generic 4480 * purpose RNG. The presence of "Q = ..." in the REQUEST file 4481 * indicates we are using the algorithm as specified. 4482 * 4483 * reqfn is the pathname of the REQUEST file. 4484 * 4485 * The output RESPONSE file is written to stdout. 4486 */ 4487 void 4488 rng_mct(char *reqfn) 4489 { 4490 char buf[256]; /* holds one line from the input REQUEST file. 4491 * needs to be large enough to hold the longest 4492 * line "XSeed = <128 hex digits>\n". 4493 */ 4494 FILE *rngreq; /* input stream from the REQUEST file */ 4495 FILE *rngresp; /* output stream to the RESPONSE file */ 4496 unsigned int i, j; 4497 unsigned char Q[DSA1_SUBPRIME_LEN]; 4498 PRBool hasQ = PR_FALSE; 4499 unsigned int b = 0; /* 160 <= b <= 512, b is a multiple of 8 */ 4500 unsigned char XKey[512 / 8]; 4501 unsigned char XSeed[512 / 8]; 4502 unsigned char GENX[2 * SHA1_LENGTH]; 4503 unsigned char DSAX[DSA1_SUBPRIME_LEN]; 4504 SECStatus rv; 4505 4506 rngreq = fopen(reqfn, "r"); 4507 rngresp = stdout; 4508 while (fgets(buf, sizeof buf, rngreq) != NULL) { 4509 /* a comment or blank line */ 4510 if (buf[0] == '#' || buf[0] == '\n') { 4511 fputs(buf, rngresp); 4512 continue; 4513 } 4514 /* [Xchange - SHA1] */ 4515 if (buf[0] == '[') { 4516 fputs(buf, rngresp); 4517 continue; 4518 } 4519 /* Q = ... */ 4520 if (buf[0] == 'Q') { 4521 i = 1; 4522 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4523 i++; 4524 } 4525 for (j = 0; j < sizeof Q; i += 2, j++) { 4526 hex_to_byteval(&buf[i], &Q[j]); 4527 } 4528 fputs(buf, rngresp); 4529 hasQ = PR_TRUE; 4530 continue; 4531 } 4532 /* "COUNT = x" begins a new data set */ 4533 if (strncmp(buf, "COUNT", 5) == 0) { 4534 /* zeroize the variables for the test with this data set */ 4535 b = 0; 4536 memset(XKey, 0, sizeof XKey); 4537 memset(XSeed, 0, sizeof XSeed); 4538 fputs(buf, rngresp); 4539 continue; 4540 } 4541 /* b = ... */ 4542 if (buf[0] == 'b') { 4543 i = 1; 4544 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4545 i++; 4546 } 4547 b = atoi(&buf[i]); 4548 if (b < 160 || b > 512 || b % 8 != 0) { 4549 goto loser; 4550 } 4551 fputs(buf, rngresp); 4552 continue; 4553 } 4554 /* XKey = ... */ 4555 if (strncmp(buf, "XKey", 4) == 0) { 4556 i = 4; 4557 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4558 i++; 4559 } 4560 for (j = 0; j < b / 8; i += 2, j++) { 4561 hex_to_byteval(&buf[i], &XKey[j]); 4562 } 4563 fputs(buf, rngresp); 4564 continue; 4565 } 4566 /* XSeed = ... */ 4567 if (strncmp(buf, "XSeed", 5) == 0) { 4568 unsigned int k; 4569 i = 5; 4570 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4571 i++; 4572 } 4573 for (j = 0; j < b / 8; i += 2, j++) { 4574 hex_to_byteval(&buf[i], &XSeed[j]); 4575 } 4576 fputs(buf, rngresp); 4577 4578 for (k = 0; k < 10000; k++) { 4579 rv = FIPS186Change_GenerateX(XKey, XSeed, GENX); 4580 if (rv != SECSuccess) { 4581 goto loser; 4582 } 4583 } 4584 fputs("X = ", rngresp); 4585 if (hasQ) { 4586 rv = FIPS186Change_ReduceModQForDSA(GENX, Q, DSAX); 4587 if (rv != SECSuccess) { 4588 goto loser; 4589 } 4590 to_hex_str(buf, DSAX, sizeof DSAX); 4591 } else { 4592 to_hex_str(buf, GENX, sizeof GENX); 4593 } 4594 fputs(buf, rngresp); 4595 fputc('\n', rngresp); 4596 continue; 4597 } 4598 } 4599 loser: 4600 fclose(rngreq); 4601 } 4602 4603 /* 4604 * Calculate the SHA Message Digest 4605 * 4606 * MD = Message digest 4607 * MDLen = length of Message Digest and SHA_Type 4608 * msg = message to digest 4609 * msgLen = length of message to digest 4610 */ 4611 SECStatus 4612 sha_calcMD(unsigned char *MD, unsigned int MDLen, unsigned char *msg, unsigned int msgLen) 4613 { 4614 HASH_HashType hashType = sha_get_hashType(MDLen * PR_BITS_PER_BYTE); 4615 4616 return fips_hashBuf(hashType, MD, msg, msgLen); 4617 } 4618 4619 /* 4620 * Perform the SHA Monte Carlo Test 4621 * 4622 * MDLen = length of Message Digest and SHA_Type 4623 * seed = input seed value 4624 * resp = is the output response file. 4625 */ 4626 SECStatus 4627 sha_mct_test(unsigned int MDLen, unsigned char *seed, FILE *resp) 4628 { 4629 int i, j; 4630 unsigned int msgLen = MDLen * 3; 4631 unsigned char MD_i3[HASH_LENGTH_MAX]; /* MD[i-3] */ 4632 unsigned char MD_i2[HASH_LENGTH_MAX]; /* MD[i-2] */ 4633 unsigned char MD_i1[HASH_LENGTH_MAX]; /* MD[i-1] */ 4634 unsigned char MD_i[HASH_LENGTH_MAX]; /* MD[i] */ 4635 unsigned char msg[HASH_LENGTH_MAX * 3]; 4636 char buf[HASH_LENGTH_MAX * 2 + 1]; /* MAX buf MD_i as a hex string */ 4637 4638 for (j = 0; j < 100; j++) { 4639 /* MD_0 = MD_1 = MD_2 = seed */ 4640 memcpy(MD_i3, seed, MDLen); 4641 memcpy(MD_i2, seed, MDLen); 4642 memcpy(MD_i1, seed, MDLen); 4643 4644 for (i = 3; i < 1003; i++) { 4645 /* Mi = MD[i-3] || MD [i-2] || MD [i-1] */ 4646 memcpy(msg, MD_i3, MDLen); 4647 memcpy(&msg[MDLen], MD_i2, MDLen); 4648 memcpy(&msg[MDLen * 2], MD_i1, MDLen); 4649 4650 /* MDi = SHA(Msg) */ 4651 if (sha_calcMD(MD_i, MDLen, 4652 msg, msgLen) != SECSuccess) { 4653 return SECFailure; 4654 } 4655 4656 /* save MD[i-3] MD[i-2] MD[i-1] */ 4657 memcpy(MD_i3, MD_i2, MDLen); 4658 memcpy(MD_i2, MD_i1, MDLen); 4659 memcpy(MD_i1, MD_i, MDLen); 4660 } 4661 4662 /* seed = MD_i */ 4663 memcpy(seed, MD_i, MDLen); 4664 4665 snprintf(buf, sizeof(buf), "COUNT = %d\n", j); 4666 fputs(buf, resp); 4667 4668 /* output MD_i */ 4669 fputs("MD = ", resp); 4670 to_hex_str(buf, MD_i, MDLen); 4671 fputs(buf, resp); 4672 fputc('\n', resp); 4673 } 4674 4675 return SECSuccess; 4676 } 4677 4678 /* 4679 * Perform the SHA Tests. 4680 * 4681 * reqfn is the pathname of the input REQUEST file. 4682 * 4683 * The output RESPONSE file is written to stdout. 4684 */ 4685 void 4686 sha_test(char *reqfn) 4687 { 4688 unsigned int i, j; 4689 unsigned int MDlen = 0; /* the length of the Message Digest in Bytes */ 4690 unsigned int msgLen = 0; /* the length of the input Message in Bytes */ 4691 unsigned char *msg = NULL; /* holds the message to digest.*/ 4692 size_t bufSize = 256 * 128; /*MAX buffer size */ 4693 char *buf = NULL; /* holds one line from the input REQUEST file.*/ 4694 unsigned char seed[HASH_LENGTH_MAX]; /* max size of seed 64 bytes */ 4695 unsigned char MD[HASH_LENGTH_MAX]; /* message digest */ 4696 4697 FILE *req = NULL; /* input stream from the REQUEST file */ 4698 FILE *resp; /* output stream to the RESPONSE file */ 4699 4700 buf = PORT_ZAlloc(bufSize); 4701 if (buf == NULL) { 4702 goto loser; 4703 } 4704 4705 /* zeroize the variables for the test with this data set */ 4706 memset(seed, 0, sizeof seed); 4707 4708 req = fopen(reqfn, "r"); 4709 resp = stdout; 4710 while (fgets(buf, bufSize, req) != NULL) { 4711 4712 /* a comment or blank line */ 4713 if (buf[0] == '#' || buf[0] == '\n') { 4714 fputs(buf, resp); 4715 continue; 4716 } 4717 /* [L = Length of the Message Digest and sha_type */ 4718 if (buf[0] == '[') { 4719 if (strncmp(&buf[1], "L ", 1) == 0) { 4720 i = 2; 4721 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4722 i++; 4723 } 4724 MDlen = atoi(&buf[i]); 4725 fputs(buf, resp); 4726 continue; 4727 } 4728 } 4729 /* Len = Length of the Input Message Length ... */ 4730 if (strncmp(buf, "Len", 3) == 0) { 4731 i = 3; 4732 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4733 i++; 4734 } 4735 if (msg) { 4736 PORT_ZFree(msg, msgLen); 4737 msg = NULL; 4738 } 4739 msgLen = atoi(&buf[i]); /* in bits */ 4740 if (msgLen % 8 != 0) { 4741 fprintf(stderr, "SHA tests are incorrectly configured for " 4742 "BIT oriented implementations\n"); 4743 goto loser; 4744 } 4745 msgLen = msgLen / 8; /* convert to bytes */ 4746 fputs(buf, resp); 4747 msg = PORT_ZAlloc(msgLen); 4748 if (msg == NULL && msgLen != 0) { 4749 goto loser; 4750 } 4751 continue; 4752 } 4753 /* MSG = ... */ 4754 if (strncmp(buf, "Msg", 3) == 0) { 4755 i = 3; 4756 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4757 i++; 4758 } 4759 for (j = 0; j < msgLen; i += 2, j++) { 4760 hex_to_byteval(&buf[i], &msg[j]); 4761 } 4762 fputs(buf, resp); 4763 /* calculate the Message Digest */ 4764 memset(MD, 0, sizeof MD); 4765 if (sha_calcMD(MD, MDlen, 4766 msg, msgLen) != SECSuccess) { 4767 goto loser; 4768 } 4769 4770 fputs("MD = ", resp); 4771 to_hex_str(buf, MD, MDlen); 4772 fputs(buf, resp); 4773 fputc('\n', resp); 4774 4775 continue; 4776 } 4777 /* Seed = ... */ 4778 if (strncmp(buf, "Seed", 4) == 0) { 4779 i = 4; 4780 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4781 i++; 4782 } 4783 for (j = 0; j < sizeof seed; i += 2, j++) { 4784 hex_to_byteval(&buf[i], &seed[j]); 4785 } 4786 4787 fputs(buf, resp); 4788 fputc('\n', resp); 4789 4790 /* do the Monte Carlo test */ 4791 if (sha_mct_test(MDlen, seed, resp) != SECSuccess) { 4792 goto loser; 4793 } 4794 4795 continue; 4796 } 4797 } 4798 loser: 4799 if (req) { 4800 fclose(req); 4801 } 4802 if (buf) { 4803 PORT_ZFree(buf, bufSize); 4804 } 4805 if (msg) { 4806 PORT_ZFree(msg, msgLen); 4807 } 4808 } 4809 4810 /****************************************************/ 4811 /* HMAC SHA-X calc */ 4812 /* hmac_computed - the computed HMAC */ 4813 /* hmac_length - the length of the computed HMAC */ 4814 /* secret_key - secret key to HMAC */ 4815 /* secret_key_length - length of secret key, */ 4816 /* message - message to HMAC */ 4817 /* message_length - length ofthe message */ 4818 /****************************************************/ 4819 static SECStatus 4820 hmac_calc(unsigned char *hmac_computed, 4821 const unsigned int hmac_length, 4822 const unsigned char *secret_key, 4823 const unsigned int secret_key_length, 4824 const unsigned char *message, 4825 const unsigned int message_length, 4826 const HASH_HashType hashAlg) 4827 { 4828 SECStatus hmac_status = SECFailure; 4829 HMACContext *cx = NULL; 4830 SECHashObject *hashObj = NULL; 4831 unsigned int bytes_hashed = 0; 4832 4833 hashObj = (SECHashObject *)HASH_GetRawHashObject(hashAlg); 4834 4835 if (!hashObj) 4836 return (SECFailure); 4837 4838 cx = HMAC_Create(hashObj, secret_key, 4839 secret_key_length, 4840 PR_TRUE); /* PR_TRUE for in FIPS mode */ 4841 4842 if (cx == NULL) 4843 return (SECFailure); 4844 4845 HMAC_Begin(cx); 4846 HMAC_Update(cx, message, message_length); 4847 hmac_status = HMAC_Finish(cx, hmac_computed, &bytes_hashed, 4848 hmac_length); 4849 4850 HMAC_Destroy(cx, PR_TRUE); 4851 4852 return (hmac_status); 4853 } 4854 4855 /* 4856 * Perform the HMAC Tests. 4857 * 4858 * reqfn is the pathname of the input REQUEST file. 4859 * 4860 * The output RESPONSE file is written to stdout. 4861 */ 4862 void 4863 hmac_test(char *reqfn) 4864 { 4865 unsigned int i, j; 4866 size_t bufSize = 400; /* MAX buffer size */ 4867 char *buf = NULL; /* holds one line from the input REQUEST file.*/ 4868 unsigned int keyLen = 0; /* Key Length */ 4869 unsigned char key[200]; /* key MAX size = 184 */ 4870 unsigned int msgLen = 128; /* the length of the input */ 4871 /* Message is always 128 Bytes */ 4872 unsigned char *msg = NULL; /* holds the message to digest.*/ 4873 unsigned int HMACLen = 0; /* the length of the HMAC Bytes */ 4874 unsigned int TLen = 0; /* the length of the requested */ 4875 /* truncated HMAC Bytes */ 4876 unsigned char HMAC[HASH_LENGTH_MAX]; /* computed HMAC */ 4877 unsigned char expectedHMAC[HASH_LENGTH_MAX]; /* for .fax files that have */ 4878 /* supplied known answer */ 4879 HASH_HashType hash_alg = HASH_AlgNULL; /* HMAC type */ 4880 4881 FILE *req = NULL; /* input stream from the REQUEST file */ 4882 FILE *resp; /* output stream to the RESPONSE file */ 4883 4884 buf = PORT_ZAlloc(bufSize); 4885 if (buf == NULL) { 4886 goto loser; 4887 } 4888 msg = PORT_ZAlloc(msgLen); 4889 if (msg == NULL) { 4890 goto loser; 4891 } 4892 4893 req = fopen(reqfn, "r"); 4894 resp = stdout; 4895 while (fgets(buf, bufSize, req) != NULL) { 4896 if (strncmp(buf, "Mac", 3) == 0) { 4897 i = 3; 4898 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4899 i++; 4900 } 4901 memset(expectedHMAC, 0, HASH_LENGTH_MAX); 4902 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 4903 hex_to_byteval(&buf[i], &expectedHMAC[j]); 4904 } 4905 if (memcmp(HMAC, expectedHMAC, TLen) != 0) { 4906 fprintf(stderr, "Generate failed:\n"); 4907 fputs(" expected=", stderr); 4908 to_hex_str(buf, expectedHMAC, 4909 TLen); 4910 fputs(buf, stderr); 4911 fputs("\n generated=", stderr); 4912 to_hex_str(buf, HMAC, 4913 TLen); 4914 fputs(buf, stderr); 4915 fputc('\n', stderr); 4916 } 4917 } 4918 4919 /* a comment or blank line */ 4920 if (buf[0] == '#' || buf[0] == '\n') { 4921 fputs(buf, resp); 4922 continue; 4923 } 4924 /* [L = Length of the MAC and HASH_type */ 4925 if (buf[0] == '[') { 4926 if (strncmp(&buf[1], "L ", 1) == 0) { 4927 i = 2; 4928 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4929 i++; 4930 } 4931 /* HMACLen will get reused for Tlen */ 4932 HMACLen = atoi(&buf[i]); 4933 hash_alg = sha_get_hashType(HMACLen * PR_BITS_PER_BYTE); 4934 if (hash_alg == HASH_AlgNULL) { 4935 goto loser; 4936 } 4937 fputs(buf, resp); 4938 continue; 4939 } 4940 } 4941 /* Count = test iteration number*/ 4942 if (strncmp(buf, "Count ", 5) == 0) { 4943 /* count can just be put into resp file */ 4944 fputs(buf, resp); 4945 /* zeroize the variables for the test with this data set */ 4946 keyLen = 0; 4947 TLen = 0; 4948 memset(key, 0, sizeof key); 4949 memset(msg, 0, msgLen); 4950 memset(HMAC, 0, sizeof HMAC); 4951 continue; 4952 } 4953 /* KLen = Length of the Input Secret Key ... */ 4954 if (strncmp(buf, "Klen", 4) == 0) { 4955 i = 4; 4956 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4957 i++; 4958 } 4959 keyLen = atoi(&buf[i]); /* in bytes */ 4960 fputs(buf, resp); 4961 continue; 4962 } 4963 /* key = the secret key for the key to MAC */ 4964 if (strncmp(buf, "Key", 3) == 0) { 4965 i = 3; 4966 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4967 i++; 4968 } 4969 for (j = 0; j < keyLen; i += 2, j++) { 4970 hex_to_byteval(&buf[i], &key[j]); 4971 } 4972 fputs(buf, resp); 4973 } 4974 /* TLen = Length of the calculated HMAC */ 4975 if (strncmp(buf, "Tlen", 4) == 0) { 4976 i = 4; 4977 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4978 i++; 4979 } 4980 TLen = atoi(&buf[i]); /* in bytes */ 4981 fputs(buf, resp); 4982 continue; 4983 } 4984 /* MSG = to HMAC always 128 bytes for these tests */ 4985 if (strncmp(buf, "Msg", 3) == 0) { 4986 i = 3; 4987 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 4988 i++; 4989 } 4990 for (j = 0; j < msgLen; i += 2, j++) { 4991 hex_to_byteval(&buf[i], &msg[j]); 4992 } 4993 fputs(buf, resp); 4994 /* calculate the HMAC and output */ 4995 if (hmac_calc(HMAC, HMACLen, key, keyLen, 4996 msg, msgLen, hash_alg) != SECSuccess) { 4997 goto loser; 4998 } 4999 fputs("Mac = ", resp); 5000 to_hex_str(buf, HMAC, TLen); 5001 fputs(buf, resp); 5002 fputc('\n', resp); 5003 continue; 5004 } 5005 } 5006 loser: 5007 if (req) { 5008 fclose(req); 5009 } 5010 if (buf) { 5011 PORT_ZFree(buf, bufSize); 5012 } 5013 if (msg) { 5014 PORT_ZFree(msg, msgLen); 5015 } 5016 } 5017 5018 /* 5019 * Perform the DSA Key Pair Generation Test. 5020 * 5021 * reqfn is the pathname of the REQUEST file. 5022 * 5023 * The output RESPONSE file is written to stdout. 5024 */ 5025 void 5026 dsa_keypair_test(char *reqfn) 5027 { 5028 char buf[800]; /* holds one line from the input REQUEST file 5029 * or to the output RESPONSE file. 5030 * 800 to hold (384 public key (x2 for HEX) + 1'\n' 5031 */ 5032 FILE *dsareq; /* input stream from the REQUEST file */ 5033 FILE *dsaresp; /* output stream to the RESPONSE file */ 5034 int count; 5035 int N; 5036 int L; 5037 int i; 5038 PQGParams *pqg = NULL; 5039 PQGVerify *vfy = NULL; 5040 PRBool use_dsa1 = PR_FALSE; 5041 int keySizeIndex; /* index for valid key sizes */ 5042 5043 dsareq = fopen(reqfn, "r"); 5044 dsaresp = stdout; 5045 while (fgets(buf, sizeof buf, dsareq) != NULL) { 5046 /* a comment or blank line */ 5047 if (buf[0] == '#' || buf[0] == '\n') { 5048 fputs(buf, dsaresp); 5049 continue; 5050 } 5051 5052 /* [Mod = x] */ 5053 if (buf[0] == '[') { 5054 if (pqg != NULL) { 5055 PQG_DestroyParams(pqg); 5056 pqg = NULL; 5057 } 5058 if (vfy != NULL) { 5059 PQG_DestroyVerify(vfy); 5060 vfy = NULL; 5061 } 5062 5063 if (sscanf(buf, "[mod = L=%d, N=%d]", &L, &N) != 2) { 5064 use_dsa1 = PR_TRUE; 5065 if (sscanf(buf, "[mod = %d]", &L) != 1) { 5066 goto loser; 5067 } 5068 } 5069 fputs(buf, dsaresp); 5070 fputc('\n', dsaresp); 5071 5072 if (use_dsa1) { 5073 /************************************************************* 5074 * PQG_ParamGenSeedLen doesn't take a key size, it takes an 5075 * index that points to a valid key size. 5076 */ 5077 keySizeIndex = PQG_PBITS_TO_INDEX(L); 5078 if (keySizeIndex == -1 || L < 512 || L > 1024) { 5079 fprintf(dsaresp, 5080 "DSA key size must be a multiple of 64 between 512 " 5081 "and 1024, inclusive"); 5082 goto loser; 5083 } 5084 5085 /* Generate the parameters P, Q, and G */ 5086 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 5087 &pqg, &vfy) != 5088 SECSuccess) { 5089 fprintf(dsaresp, 5090 "ERROR: Unable to generate PQG parameters"); 5091 goto loser; 5092 } 5093 } else { 5094 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) { 5095 fprintf(dsaresp, 5096 "ERROR: Unable to generate PQG parameters"); 5097 goto loser; 5098 } 5099 } 5100 5101 /* output P, Q, and G */ 5102 to_hex_str(buf, pqg->prime.data, pqg->prime.len); 5103 fprintf(dsaresp, "P = %s\n", buf); 5104 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 5105 fprintf(dsaresp, "Q = %s\n", buf); 5106 to_hex_str(buf, pqg->base.data, pqg->base.len); 5107 fprintf(dsaresp, "G = %s\n\n", buf); 5108 continue; 5109 } 5110 /* N = ...*/ 5111 if (buf[0] == 'N') { 5112 5113 if (sscanf(buf, "N = %d", &count) != 1) { 5114 goto loser; 5115 } 5116 /* Generate a DSA key, and output the key pair for N times */ 5117 for (i = 0; i < count; i++) { 5118 DSAPrivateKey *dsakey = NULL; 5119 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { 5120 fprintf(dsaresp, "ERROR: Unable to generate DSA key"); 5121 goto loser; 5122 } 5123 to_hex_str(buf, dsakey->privateValue.data, 5124 dsakey->privateValue.len); 5125 fprintf(dsaresp, "X = %s\n", buf); 5126 to_hex_str(buf, dsakey->publicValue.data, 5127 dsakey->publicValue.len); 5128 fprintf(dsaresp, "Y = %s\n\n", buf); 5129 PORT_FreeArena(dsakey->params.arena, PR_TRUE); 5130 dsakey = NULL; 5131 } 5132 continue; 5133 } 5134 } 5135 loser: 5136 fclose(dsareq); 5137 } 5138 5139 /* 5140 * pqg generation type 5141 */ 5142 typedef enum { 5143 FIPS186_1, /* Generate/Verify P,Q & G according to FIPS 186-1 */ 5144 A_1_2_1, /* Generate Provable P & Q */ 5145 A_1_1_3, /* Verify Probable P & Q */ 5146 A_1_2_2, /* Verify Provable P & Q */ 5147 A_2_1, /* Generate Unverifiable G */ 5148 A_2_2, /* Assure Unverifiable G */ 5149 A_2_3, /* Generate Verifiable G */ 5150 A_2_4 /* Verify Verifiable G */ 5151 } dsa_pqg_type; 5152 5153 /* 5154 * Perform the DSA Domain Parameter Validation Test. 5155 * 5156 * reqfn is the pathname of the REQUEST file. 5157 * 5158 * The output RESPONSE file is written to stdout. 5159 */ 5160 void 5161 dsa_pqgver_test(char *reqfn) 5162 { 5163 char buf[800]; /* holds one line from the input REQUEST file 5164 * or to the output RESPONSE file. 5165 * 800 to hold (384 public key (x2 for HEX) + P = ... 5166 */ 5167 FILE *dsareq; /* input stream from the REQUEST file */ 5168 FILE *dsaresp; /* output stream to the RESPONSE file */ 5169 int N; 5170 int L; 5171 unsigned int i, j; 5172 PQGParams pqg; 5173 PQGVerify vfy; 5174 unsigned int pghSize = 0; /* size for p, g, and h */ 5175 dsa_pqg_type type = FIPS186_1; 5176 5177 dsareq = fopen(reqfn, "r"); 5178 dsaresp = stdout; 5179 memset(&pqg, 0, sizeof(pqg)); 5180 memset(&vfy, 0, sizeof(vfy)); 5181 5182 while (fgets(buf, sizeof buf, dsareq) != NULL) { 5183 /* a comment or blank line */ 5184 if (buf[0] == '#' || buf[0] == '\n') { 5185 fputs(buf, dsaresp); 5186 continue; 5187 } 5188 5189 /* [A.xxxxx ] */ 5190 if (buf[0] == '[' && buf[1] == 'A') { 5191 5192 if (strncmp(&buf[1], "A.1.1.3", 7) == 0) { 5193 type = A_1_1_3; 5194 } else if (strncmp(&buf[1], "A.2.2", 5) == 0) { 5195 type = A_2_2; 5196 } else if (strncmp(&buf[1], "A.2.4", 5) == 0) { 5197 type = A_2_4; 5198 } else if (strncmp(&buf[1], "A.1.2.2", 7) == 0) { 5199 type = A_1_2_2; 5200 /* validate our output from PQGGEN */ 5201 } else if (strncmp(&buf[1], "A.1.1.2", 7) == 0) { 5202 type = A_2_4; /* validate PQ and G together */ 5203 } else { 5204 fprintf(stderr, "Unknown dsa ver test %s\n", &buf[1]); 5205 exit(1); 5206 } 5207 5208 fputs(buf, dsaresp); 5209 continue; 5210 } 5211 5212 /* [Mod = x] */ 5213 if (buf[0] == '[') { 5214 5215 if (type == FIPS186_1) { 5216 N = 160; 5217 if (sscanf(buf, "[mod = %d]", &L) != 1) { 5218 goto loser; 5219 } 5220 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) { 5221 goto loser; 5222 } 5223 5224 if (pqg.prime.data) { /* P */ 5225 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 5226 } 5227 if (pqg.subPrime.data) { /* Q */ 5228 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 5229 } 5230 if (pqg.base.data) { /* G */ 5231 SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 5232 } 5233 if (vfy.seed.data) { /* seed */ 5234 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); 5235 } 5236 if (vfy.h.data) { /* H */ 5237 SECITEM_ZfreeItem(&vfy.h, PR_FALSE); 5238 } 5239 5240 fputs(buf, dsaresp); 5241 5242 /*calculate the size of p, g, and h then allocate items */ 5243 pghSize = L / 8; 5244 5245 pqg.base.data = vfy.h.data = NULL; 5246 vfy.seed.len = pqg.base.len = vfy.h.len = 0; 5247 SECITEM_AllocItem(NULL, &pqg.prime, pghSize); 5248 SECITEM_AllocItem(NULL, &vfy.seed, pghSize * 3); 5249 if (type == A_2_2) { 5250 SECITEM_AllocItem(NULL, &vfy.h, pghSize); 5251 vfy.h.len = pghSize; 5252 } else if (type == A_2_4) { 5253 SECITEM_AllocItem(NULL, &vfy.h, 1); 5254 vfy.h.len = 1; 5255 } 5256 pqg.prime.len = pghSize; 5257 /* q is always N bits */ 5258 SECITEM_AllocItem(NULL, &pqg.subPrime, N / 8); 5259 pqg.subPrime.len = N / 8; 5260 vfy.counter = -1; 5261 5262 continue; 5263 } 5264 /* P = ... */ 5265 if (buf[0] == 'P') { 5266 i = 1; 5267 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5268 i++; 5269 } 5270 for (j = 0; j < pqg.prime.len; i += 2, j++) { 5271 hex_to_byteval(&buf[i], &pqg.prime.data[j]); 5272 } 5273 5274 fputs(buf, dsaresp); 5275 continue; 5276 } 5277 5278 /* Q = ... */ 5279 if (buf[0] == 'Q') { 5280 i = 1; 5281 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5282 i++; 5283 } 5284 for (j = 0; j < pqg.subPrime.len; i += 2, j++) { 5285 hex_to_byteval(&buf[i], &pqg.subPrime.data[j]); 5286 } 5287 5288 fputs(buf, dsaresp); 5289 continue; 5290 } 5291 5292 /* G = ... */ 5293 if (buf[0] == 'G') { 5294 i = 1; 5295 if (pqg.base.data) { 5296 SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 5297 } 5298 SECITEM_AllocItem(NULL, &pqg.base, pghSize); 5299 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5300 i++; 5301 } 5302 for (j = 0; j < pqg.base.len; i += 2, j++) { 5303 hex_to_byteval(&buf[i], &pqg.base.data[j]); 5304 } 5305 5306 fputs(buf, dsaresp); 5307 continue; 5308 } 5309 5310 /* Seed = ... or domain_parameter_seed = ... */ 5311 if (strncmp(buf, "Seed", 4) == 0) { 5312 i = 4; 5313 } else if (strncmp(buf, "domain_parameter_seed", 21) == 0) { 5314 i = 21; 5315 } else if (strncmp(buf, "firstseed", 9) == 0) { 5316 i = 9; 5317 } else { 5318 i = 0; 5319 } 5320 if (i) { 5321 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5322 i++; 5323 } 5324 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 5325 hex_to_byteval(&buf[i], &vfy.seed.data[j]); 5326 } 5327 vfy.seed.len = j; 5328 5329 fputs(buf, dsaresp); 5330 if (type == A_2_4) { 5331 SECStatus result; 5332 5333 /* Verify the Parameters */ 5334 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 5335 if (rv != SECSuccess) { 5336 goto loser; 5337 } 5338 if (result == SECSuccess) { 5339 fprintf(dsaresp, "Result = P\n"); 5340 } else { 5341 fprintf(dsaresp, "Result = F\n"); 5342 } 5343 } 5344 continue; 5345 } 5346 if ((strncmp(buf, "pseed", 5) == 0) || 5347 (strncmp(buf, "qseed", 5) == 0)) { 5348 i = 5; 5349 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5350 i++; 5351 } 5352 for (j = vfy.seed.len; isxdigit((unsigned char)buf[i]); i += 2, j++) { 5353 hex_to_byteval(&buf[i], &vfy.seed.data[j]); 5354 } 5355 vfy.seed.len = j; 5356 fputs(buf, dsaresp); 5357 5358 continue; 5359 } 5360 if (strncmp(buf, "index", 4) == 0) { 5361 i = 5; 5362 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5363 i++; 5364 } 5365 hex_to_byteval(&buf[i], &vfy.h.data[0]); 5366 vfy.h.len = 1; 5367 fputs(buf, dsaresp); 5368 } 5369 5370 /* c = ... or counter=*/ 5371 if (buf[0] == 'c') { 5372 if (strncmp(buf, "counter", 7) == 0) { 5373 if (sscanf(buf, "counter = %u", &vfy.counter) != 1) { 5374 goto loser; 5375 } 5376 } else { 5377 if (sscanf(buf, "c = %u", &vfy.counter) != 1) { 5378 goto loser; 5379 } 5380 } 5381 5382 fputs(buf, dsaresp); 5383 if (type == A_1_1_3) { 5384 SECStatus result; 5385 /* only verify P and Q, we have everything now. do it */ 5386 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 5387 if (rv != SECSuccess) { 5388 goto loser; 5389 } 5390 if (result == SECSuccess) { 5391 fprintf(dsaresp, "Result = P\n"); 5392 } else { 5393 fprintf(dsaresp, "Result = F\n"); 5394 } 5395 fprintf(dsaresp, "\n"); 5396 } 5397 continue; 5398 } 5399 if (strncmp(buf, "pgen_counter", 12) == 0) { 5400 if (sscanf(buf, "pgen_counter = %u", &vfy.counter) != 1) { 5401 goto loser; 5402 } 5403 fputs(buf, dsaresp); 5404 continue; 5405 } 5406 if (strncmp(buf, "qgen_counter", 12) == 0) { 5407 fputs(buf, dsaresp); 5408 if (type == A_1_2_2) { 5409 SECStatus result; 5410 /* only verify P and Q, we have everything now. do it */ 5411 SECStatus rv = PQG_VerifyParams(&pqg, &vfy, &result); 5412 if (rv != SECSuccess) { 5413 goto loser; 5414 } 5415 if (result == SECSuccess) { 5416 fprintf(dsaresp, "Result = P\n"); 5417 } else { 5418 fprintf(dsaresp, "Result = F\n"); 5419 } 5420 fprintf(dsaresp, "\n"); 5421 } 5422 continue; 5423 } 5424 /* H = ... */ 5425 if (buf[0] == 'H') { 5426 SECStatus rv, result = SECFailure; 5427 5428 i = 1; 5429 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5430 i++; 5431 } 5432 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 5433 hex_to_byteval(&buf[i], &vfy.h.data[j]); 5434 } 5435 vfy.h.len = j; 5436 fputs(buf, dsaresp); 5437 5438 /* this should be a byte value. Remove the leading zeros. If 5439 * it doesn't reduce to a byte, PQG_VerifyParams will catch it 5440 if (type == A_2_2) { 5441 data_save = vfy.h.data; 5442 while(vfy.h.data[0] && (vfy.h.len > 1)) { 5443 vfy.h.data++; 5444 vfy.h.len--; 5445 } 5446 } */ 5447 5448 /* Verify the Parameters */ 5449 rv = PQG_VerifyParams(&pqg, &vfy, &result); 5450 if (rv != SECSuccess) { 5451 goto loser; 5452 } 5453 if (result == SECSuccess) { 5454 fprintf(dsaresp, "Result = P\n"); 5455 } else { 5456 fprintf(dsaresp, "Result = F\n"); 5457 } 5458 fprintf(dsaresp, "\n"); 5459 continue; 5460 } 5461 } 5462 loser: 5463 fclose(dsareq); 5464 if (pqg.prime.data) { /* P */ 5465 SECITEM_ZfreeItem(&pqg.prime, PR_FALSE); 5466 } 5467 if (pqg.subPrime.data) { /* Q */ 5468 SECITEM_ZfreeItem(&pqg.subPrime, PR_FALSE); 5469 } 5470 if (pqg.base.data) { /* G */ 5471 SECITEM_ZfreeItem(&pqg.base, PR_FALSE); 5472 } 5473 if (vfy.seed.data) { /* seed */ 5474 SECITEM_ZfreeItem(&vfy.seed, PR_FALSE); 5475 } 5476 if (vfy.h.data) { /* H */ 5477 SECITEM_ZfreeItem(&vfy.h, PR_FALSE); 5478 } 5479 } 5480 5481 /* 5482 * Perform the DSA Public Key Validation Test. 5483 * 5484 * reqfn is the pathname of the REQUEST file. 5485 * 5486 * The output RESPONSE file is written to stdout. 5487 */ 5488 void 5489 dsa_pqggen_test(char *reqfn) 5490 { 5491 char buf[800]; /* holds one line from the input REQUEST file 5492 * or to the output RESPONSE file. 5493 * 800 to hold seed = (384 public key (x2 for HEX) 5494 */ 5495 FILE *dsareq; /* input stream from the REQUEST file */ 5496 FILE *dsaresp; /* output stream to the RESPONSE file */ 5497 int count; /* number of times to generate parameters */ 5498 int N; 5499 int L; 5500 int i; 5501 unsigned int j; 5502 int output_g = 1; 5503 PQGParams *pqg = NULL; 5504 PQGVerify *vfy = NULL; 5505 unsigned int keySizeIndex = 0; 5506 dsa_pqg_type type = FIPS186_1; 5507 5508 dsareq = fopen(reqfn, "r"); 5509 dsaresp = stdout; 5510 while (fgets(buf, sizeof buf, dsareq) != NULL) { 5511 /* a comment or blank line */ 5512 if (buf[0] == '#' || buf[0] == '\n') { 5513 fputs(buf, dsaresp); 5514 continue; 5515 } 5516 5517 /* [A.xxxxx ] */ 5518 if (buf[0] == '[' && buf[1] == 'A') { 5519 if (strncmp(&buf[1], "A.1.1.2", 7) == 0) { 5520 fprintf(stderr, "NSS does Generate Probablistic Primes\n"); 5521 exit(1); 5522 } else if (strncmp(&buf[1], "A.2.1", 5) == 0) { 5523 type = A_1_2_1; 5524 output_g = 1; 5525 exit(1); 5526 } else if (strncmp(&buf[1], "A.2.3", 5) == 0) { 5527 fprintf(stderr, "NSS only Generates G with P&Q\n"); 5528 exit(1); 5529 } else if (strncmp(&buf[1], "A.1.2.1", 7) == 0) { 5530 type = A_1_2_1; 5531 output_g = 0; 5532 } else { 5533 fprintf(stderr, "Unknown dsa pqggen test %s\n", &buf[1]); 5534 exit(1); 5535 } 5536 fputs(buf, dsaresp); 5537 continue; 5538 } 5539 5540 /* [Mod = ... ] */ 5541 if (buf[0] == '[') { 5542 5543 if (type == FIPS186_1) { 5544 N = 160; 5545 if (sscanf(buf, "[mod = %d]", &L) != 1) { 5546 goto loser; 5547 } 5548 } else if (sscanf(buf, "[mod = L=%d, N=%d", &L, &N) != 2) { 5549 goto loser; 5550 } 5551 5552 fputs(buf, dsaresp); 5553 fputc('\n', dsaresp); 5554 5555 if (type == FIPS186_1) { 5556 /************************************************************ 5557 * PQG_ParamGenSeedLen doesn't take a key size, it takes an 5558 * index that points to a valid key size. 5559 */ 5560 keySizeIndex = PQG_PBITS_TO_INDEX(L); 5561 if (keySizeIndex == -1 || L < 512 || L > 1024) { 5562 fprintf(dsaresp, 5563 "DSA key size must be a multiple of 64 between 512 " 5564 "and 1024, inclusive"); 5565 goto loser; 5566 } 5567 } 5568 continue; 5569 } 5570 /* N = ... */ 5571 if (buf[0] == 'N') { 5572 if (strncmp(buf, "Num", 3) == 0) { 5573 if (sscanf(buf, "Num = %d", &count) != 1) { 5574 goto loser; 5575 } 5576 } else if (sscanf(buf, "N = %d", &count) != 1) { 5577 goto loser; 5578 } 5579 for (i = 0; i < count; i++) { 5580 SECStatus rv; 5581 5582 if (type == FIPS186_1) { 5583 rv = PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 5584 &pqg, &vfy); 5585 } else { 5586 rv = PQG_ParamGenV2(L, N, N, &pqg, &vfy); 5587 } 5588 if (rv != SECSuccess) { 5589 fprintf(dsaresp, 5590 "ERROR: Unable to generate PQG parameters"); 5591 goto loser; 5592 } 5593 to_hex_str(buf, pqg->prime.data, pqg->prime.len); 5594 fprintf(dsaresp, "P = %s\n", buf); 5595 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 5596 fprintf(dsaresp, "Q = %s\n", buf); 5597 if (output_g) { 5598 to_hex_str(buf, pqg->base.data, pqg->base.len); 5599 fprintf(dsaresp, "G = %s\n", buf); 5600 } 5601 if (type == FIPS186_1) { 5602 to_hex_str(buf, vfy->seed.data, vfy->seed.len); 5603 fprintf(dsaresp, "Seed = %s\n", buf); 5604 fprintf(dsaresp, "c = %d\n", vfy->counter); 5605 to_hex_str(buf, vfy->h.data, vfy->h.len); 5606 fputs("H = ", dsaresp); 5607 for (j = vfy->h.len; j < pqg->prime.len; j++) { 5608 fprintf(dsaresp, "00"); 5609 } 5610 fprintf(dsaresp, "%s\n", buf); 5611 } else { 5612 unsigned int seedlen = vfy->seed.len / 2; 5613 unsigned int pgen_counter = vfy->counter >> 16; 5614 unsigned int qgen_counter = vfy->counter & 0xffff; 5615 /*fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); */ 5616 to_hex_str(buf, vfy->seed.data, seedlen); 5617 fprintf(dsaresp, "pseed = %s\n", buf); 5618 to_hex_str(buf, vfy->seed.data + seedlen, seedlen); 5619 fprintf(dsaresp, "qseed = %s\n", buf); 5620 fprintf(dsaresp, "pgen_counter = %d\n", pgen_counter); 5621 fprintf(dsaresp, "qgen_counter = %d\n", qgen_counter); 5622 if (output_g) { 5623 to_hex_str(buf, vfy->seed.data, vfy->seed.len); 5624 fprintf(dsaresp, "domain_parameter_seed = %s\n", buf); 5625 fprintf(dsaresp, "index = %02x\n", vfy->h.data[0]); 5626 } 5627 } 5628 fputc('\n', dsaresp); 5629 if (pqg != NULL) { 5630 PQG_DestroyParams(pqg); 5631 pqg = NULL; 5632 } 5633 if (vfy != NULL) { 5634 PQG_DestroyVerify(vfy); 5635 vfy = NULL; 5636 } 5637 } 5638 5639 continue; 5640 } 5641 } 5642 loser: 5643 fclose(dsareq); 5644 if (pqg != NULL) { 5645 PQG_DestroyParams(pqg); 5646 } 5647 if (vfy != NULL) { 5648 PQG_DestroyVerify(vfy); 5649 } 5650 } 5651 5652 /* 5653 * Perform the DSA Signature Generation Test. 5654 * 5655 * reqfn is the pathname of the REQUEST file. 5656 * 5657 * The output RESPONSE file is written to stdout. 5658 */ 5659 void 5660 dsa_siggen_test(char *reqfn) 5661 { 5662 char buf[800]; /* holds one line from the input REQUEST file 5663 * or to the output RESPONSE file. 5664 * max for Msg = .... 5665 */ 5666 FILE *dsareq; /* input stream from the REQUEST file */ 5667 FILE *dsaresp; /* output stream to the RESPONSE file */ 5668 int modulus; 5669 int L; 5670 int N; 5671 int i, j; 5672 PRBool use_dsa1 = PR_FALSE; 5673 PQGParams *pqg = NULL; 5674 PQGVerify *vfy = NULL; 5675 DSAPrivateKey *dsakey = NULL; 5676 int keySizeIndex; /* index for valid key sizes */ 5677 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */ 5678 unsigned char sig[DSA_MAX_SIGNATURE_LEN]; 5679 SECItem digest, signature; 5680 HASH_HashType hashType = HASH_AlgNULL; 5681 int hashNum = 0; 5682 5683 dsareq = fopen(reqfn, "r"); 5684 dsaresp = stdout; 5685 5686 while (fgets(buf, sizeof buf, dsareq) != NULL) { 5687 /* a comment or blank line */ 5688 if (buf[0] == '#' || buf[0] == '\n') { 5689 fputs(buf, dsaresp); 5690 continue; 5691 } 5692 5693 /* [Mod = x] */ 5694 if (buf[0] == '[') { 5695 if (pqg != NULL) { 5696 PQG_DestroyParams(pqg); 5697 pqg = NULL; 5698 } 5699 if (vfy != NULL) { 5700 PQG_DestroyVerify(vfy); 5701 vfy = NULL; 5702 } 5703 if (dsakey != NULL) { 5704 PORT_FreeArena(dsakey->params.arena, PR_TRUE); 5705 dsakey = NULL; 5706 } 5707 5708 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N, 5709 &hashNum) != 3) { 5710 use_dsa1 = PR_TRUE; 5711 hashNum = 1; 5712 if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 5713 goto loser; 5714 } 5715 } 5716 fputs(buf, dsaresp); 5717 fputc('\n', dsaresp); 5718 5719 /**************************************************************** 5720 * PQG_ParamGenSeedLen doesn't take a key size, it takes an index 5721 * that points to a valid key size. 5722 */ 5723 if (use_dsa1) { 5724 keySizeIndex = PQG_PBITS_TO_INDEX(modulus); 5725 if (keySizeIndex == -1 || modulus < 512 || modulus > 1024) { 5726 fprintf(dsaresp, 5727 "DSA key size must be a multiple of 64 between 512 " 5728 "and 1024, inclusive"); 5729 goto loser; 5730 } 5731 /* Generate PQG and output PQG */ 5732 if (PQG_ParamGenSeedLen(keySizeIndex, PQG_TEST_SEED_BYTES, 5733 &pqg, &vfy) != 5734 SECSuccess) { 5735 fprintf(dsaresp, 5736 "ERROR: Unable to generate PQG parameters"); 5737 goto loser; 5738 } 5739 } else { 5740 if (PQG_ParamGenV2(L, N, N, &pqg, &vfy) != SECSuccess) { 5741 fprintf(dsaresp, 5742 "ERROR: Unable to generate PQG parameters"); 5743 goto loser; 5744 } 5745 } 5746 to_hex_str(buf, pqg->prime.data, pqg->prime.len); 5747 fprintf(dsaresp, "P = %s\n", buf); 5748 to_hex_str(buf, pqg->subPrime.data, pqg->subPrime.len); 5749 fprintf(dsaresp, "Q = %s\n", buf); 5750 to_hex_str(buf, pqg->base.data, pqg->base.len); 5751 fprintf(dsaresp, "G = %s\n", buf); 5752 5753 /* create DSA Key */ 5754 if (DSA_NewKey(pqg, &dsakey) != SECSuccess) { 5755 fprintf(dsaresp, "ERROR: Unable to generate DSA key"); 5756 goto loser; 5757 } 5758 5759 hashType = sha_get_hashType(hashNum); 5760 if (hashType == HASH_AlgNULL) { 5761 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum); 5762 goto loser; 5763 } 5764 continue; 5765 } 5766 5767 /* Msg = ... */ 5768 if (strncmp(buf, "Msg", 3) == 0) { 5769 unsigned char msg[128]; /* MAX msg 128 */ 5770 unsigned int len = 0; 5771 5772 if (hashType == HASH_AlgNULL) { 5773 fprintf(dsaresp, "ERROR: Hash Alg not set"); 5774 goto loser; 5775 } 5776 5777 memset(hashBuf, 0, sizeof hashBuf); 5778 memset(sig, 0, sizeof sig); 5779 5780 i = 3; 5781 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5782 i++; 5783 } 5784 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 5785 hex_to_byteval(&buf[i], &msg[j]); 5786 } 5787 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) { 5788 fprintf(dsaresp, "ERROR: Unable to generate SHA% digest", 5789 hashNum); 5790 goto loser; 5791 } 5792 5793 digest.type = siBuffer; 5794 digest.data = hashBuf; 5795 digest.len = fips_hashLen(hashType); 5796 signature.type = siBuffer; 5797 signature.data = sig; 5798 signature.len = sizeof sig; 5799 5800 if (DSA_SignDigest(dsakey, &signature, &digest) != SECSuccess) { 5801 fprintf(dsaresp, "ERROR: Unable to generate DSA signature"); 5802 goto loser; 5803 } 5804 len = signature.len; 5805 if (len % 2 != 0) { 5806 goto loser; 5807 } 5808 len = len / 2; 5809 5810 /* output the orginal Msg, and generated Y, R, and S */ 5811 fputs(buf, dsaresp); 5812 to_hex_str(buf, dsakey->publicValue.data, 5813 dsakey->publicValue.len); 5814 fprintf(dsaresp, "Y = %s\n", buf); 5815 to_hex_str(buf, &signature.data[0], len); 5816 fprintf(dsaresp, "R = %s\n", buf); 5817 to_hex_str(buf, &signature.data[len], len); 5818 fprintf(dsaresp, "S = %s\n", buf); 5819 fputc('\n', dsaresp); 5820 continue; 5821 } 5822 } 5823 loser: 5824 fclose(dsareq); 5825 if (pqg != NULL) { 5826 PQG_DestroyParams(pqg); 5827 pqg = NULL; 5828 } 5829 if (vfy != NULL) { 5830 PQG_DestroyVerify(vfy); 5831 vfy = NULL; 5832 } 5833 if (dsakey) { 5834 PORT_FreeArena(dsakey->params.arena, PR_TRUE); 5835 dsakey = NULL; 5836 } 5837 } 5838 5839 /* 5840 * Perform the DSA Signature Verification Test. 5841 * 5842 * reqfn is the pathname of the REQUEST file. 5843 * 5844 * The output RESPONSE file is written to stdout. 5845 */ 5846 void 5847 dsa_sigver_test(char *reqfn) 5848 { 5849 char buf[800]; /* holds one line from the input REQUEST file 5850 * or to the output RESPONSE file. 5851 * max for Msg = .... 5852 */ 5853 FILE *dsareq; /* input stream from the REQUEST file */ 5854 FILE *dsaresp; /* output stream to the RESPONSE file */ 5855 int L; 5856 int N; 5857 unsigned int i, j; 5858 SECItem digest, signature; 5859 DSAPublicKey pubkey; 5860 unsigned int pgySize; /* size for p, g, and y */ 5861 unsigned char hashBuf[HASH_LENGTH_MAX]; /* SHA-x hash (160-512 bits) */ 5862 unsigned char sig[DSA_MAX_SIGNATURE_LEN]; 5863 HASH_HashType hashType = HASH_AlgNULL; 5864 int hashNum = 0; 5865 5866 dsareq = fopen(reqfn, "r"); 5867 dsaresp = stdout; 5868 memset(&pubkey, 0, sizeof(pubkey)); 5869 5870 while (fgets(buf, sizeof buf, dsareq) != NULL) { 5871 /* a comment or blank line */ 5872 if (buf[0] == '#' || buf[0] == '\n') { 5873 fputs(buf, dsaresp); 5874 continue; 5875 } 5876 5877 /* [Mod = x] */ 5878 if (buf[0] == '[') { 5879 5880 if (sscanf(buf, "[mod = L=%d, N=%d, SHA-%d]", &L, &N, 5881 &hashNum) != 3) { 5882 N = 160; 5883 hashNum = 1; 5884 if (sscanf(buf, "[mod = %d]", &L) != 1) { 5885 goto loser; 5886 } 5887 } 5888 5889 if (pubkey.params.prime.data) { /* P */ 5890 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); 5891 } 5892 if (pubkey.params.subPrime.data) { /* Q */ 5893 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); 5894 } 5895 if (pubkey.params.base.data) { /* G */ 5896 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); 5897 } 5898 if (pubkey.publicValue.data) { /* Y */ 5899 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); 5900 } 5901 fputs(buf, dsaresp); 5902 5903 /* calculate the size of p, g, and y then allocate items */ 5904 pgySize = L / 8; 5905 SECITEM_AllocItem(NULL, &pubkey.params.prime, pgySize); 5906 SECITEM_AllocItem(NULL, &pubkey.params.base, pgySize); 5907 SECITEM_AllocItem(NULL, &pubkey.publicValue, pgySize); 5908 pubkey.params.prime.len = pubkey.params.base.len = pgySize; 5909 pubkey.publicValue.len = pgySize; 5910 5911 /* q always N/8 bytes */ 5912 SECITEM_AllocItem(NULL, &pubkey.params.subPrime, N / 8); 5913 pubkey.params.subPrime.len = N / 8; 5914 5915 hashType = sha_get_hashType(hashNum); 5916 if (hashType == HASH_AlgNULL) { 5917 fprintf(dsaresp, "ERROR: invalid hash (SHA-%d)", hashNum); 5918 goto loser; 5919 } 5920 5921 continue; 5922 } 5923 /* P = ... */ 5924 if (buf[0] == 'P') { 5925 i = 1; 5926 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5927 i++; 5928 } 5929 memset(pubkey.params.prime.data, 0, pubkey.params.prime.len); 5930 for (j = 0; j < pubkey.params.prime.len; i += 2, j++) { 5931 hex_to_byteval(&buf[i], &pubkey.params.prime.data[j]); 5932 } 5933 5934 fputs(buf, dsaresp); 5935 continue; 5936 } 5937 5938 /* Q = ... */ 5939 if (buf[0] == 'Q') { 5940 i = 1; 5941 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5942 i++; 5943 } 5944 memset(pubkey.params.subPrime.data, 0, pubkey.params.subPrime.len); 5945 for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) { 5946 hex_to_byteval(&buf[i], &pubkey.params.subPrime.data[j]); 5947 } 5948 5949 fputs(buf, dsaresp); 5950 continue; 5951 } 5952 5953 /* G = ... */ 5954 if (buf[0] == 'G') { 5955 i = 1; 5956 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5957 i++; 5958 } 5959 memset(pubkey.params.base.data, 0, pubkey.params.base.len); 5960 for (j = 0; j < pubkey.params.base.len; i += 2, j++) { 5961 hex_to_byteval(&buf[i], &pubkey.params.base.data[j]); 5962 } 5963 5964 fputs(buf, dsaresp); 5965 continue; 5966 } 5967 5968 /* Msg = ... */ 5969 if (strncmp(buf, "Msg", 3) == 0) { 5970 unsigned char msg[128]; /* MAX msg 128 */ 5971 memset(hashBuf, 0, sizeof hashBuf); 5972 5973 if (hashType == HASH_AlgNULL) { 5974 fprintf(dsaresp, "ERROR: Hash Alg not set"); 5975 goto loser; 5976 } 5977 5978 i = 3; 5979 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5980 i++; 5981 } 5982 for (j = 0; isxdigit((unsigned char)buf[i]); i += 2, j++) { 5983 hex_to_byteval(&buf[i], &msg[j]); 5984 } 5985 if (fips_hashBuf(hashType, hashBuf, msg, j) != SECSuccess) { 5986 fprintf(dsaresp, "ERROR: Unable to generate SHA-%d digest", 5987 hashNum); 5988 goto loser; 5989 } 5990 5991 fputs(buf, dsaresp); 5992 continue; 5993 } 5994 5995 /* Y = ... */ 5996 if (buf[0] == 'Y') { 5997 i = 1; 5998 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 5999 i++; 6000 } 6001 memset(pubkey.publicValue.data, 0, pubkey.params.subPrime.len); 6002 for (j = 0; j < pubkey.publicValue.len; i += 2, j++) { 6003 hex_to_byteval(&buf[i], &pubkey.publicValue.data[j]); 6004 } 6005 6006 fputs(buf, dsaresp); 6007 continue; 6008 } 6009 6010 /* R = ... */ 6011 if (buf[0] == 'R') { 6012 memset(sig, 0, sizeof sig); 6013 i = 1; 6014 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6015 i++; 6016 } 6017 for (j = 0; j < pubkey.params.subPrime.len; i += 2, j++) { 6018 hex_to_byteval(&buf[i], &sig[j]); 6019 } 6020 6021 fputs(buf, dsaresp); 6022 continue; 6023 } 6024 6025 /* S = ... */ 6026 if (buf[0] == 'S') { 6027 if (hashType == HASH_AlgNULL) { 6028 fprintf(dsaresp, "ERROR: Hash Alg not set"); 6029 goto loser; 6030 } 6031 6032 i = 1; 6033 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6034 i++; 6035 } 6036 for (j = pubkey.params.subPrime.len; 6037 j < pubkey.params.subPrime.len * 2; i += 2, j++) { 6038 hex_to_byteval(&buf[i], &sig[j]); 6039 } 6040 fputs(buf, dsaresp); 6041 6042 digest.type = siBuffer; 6043 digest.data = hashBuf; 6044 digest.len = fips_hashLen(hashType); 6045 signature.type = siBuffer; 6046 signature.data = sig; 6047 signature.len = pubkey.params.subPrime.len * 2; 6048 6049 if (DSA_VerifyDigest(&pubkey, &signature, &digest) == SECSuccess) { 6050 fprintf(dsaresp, "Result = P\n"); 6051 } else { 6052 fprintf(dsaresp, "Result = F\n"); 6053 } 6054 fprintf(dsaresp, "\n"); 6055 continue; 6056 } 6057 } 6058 loser: 6059 fclose(dsareq); 6060 if (pubkey.params.prime.data) { /* P */ 6061 SECITEM_ZfreeItem(&pubkey.params.prime, PR_FALSE); 6062 } 6063 if (pubkey.params.subPrime.data) { /* Q */ 6064 SECITEM_ZfreeItem(&pubkey.params.subPrime, PR_FALSE); 6065 } 6066 if (pubkey.params.base.data) { /* G */ 6067 SECITEM_ZfreeItem(&pubkey.params.base, PR_FALSE); 6068 } 6069 if (pubkey.publicValue.data) { /* Y */ 6070 SECITEM_ZfreeItem(&pubkey.publicValue, PR_FALSE); 6071 } 6072 } 6073 6074 static void 6075 pad(unsigned char *buf, int pad_len, unsigned char *src, int src_len) 6076 { 6077 int offset = 0; 6078 /* this shouldn't happen, fail right away rather than produce bad output */ 6079 if (pad_len < src_len) { 6080 fprintf(stderr, "data bigger than expected! %d > %d\n", src_len, pad_len); 6081 exit(1); 6082 } 6083 6084 offset = pad_len - src_len; 6085 memset(buf, 0, offset); 6086 memcpy(buf + offset, src, src_len); 6087 return; 6088 } 6089 6090 /* 6091 * Perform the DSA Key Pair Generation Test. 6092 * 6093 * reqfn is the pathname of the REQUEST file. 6094 * 6095 * The output RESPONSE file is written to stdout. 6096 */ 6097 void 6098 rsa_keypair_test(char *reqfn) 6099 { 6100 char buf[800]; /* holds one line from the input REQUEST file 6101 * or to the output RESPONSE file. 6102 * 800 to hold (384 public key (x2 for HEX) + 1'\n' 6103 */ 6104 unsigned char buf2[400]; /* can't need more then 1/2 buf length */ 6105 FILE *rsareq; /* input stream from the REQUEST file */ 6106 FILE *rsaresp; /* output stream to the RESPONSE file */ 6107 int count; 6108 int i; 6109 int keySize = 1; /* key size in bits*/ 6110 int len = 0; /* key size in bytes */ 6111 int len2 = 0; /* key size in bytes/2 (prime size) */ 6112 SECItem e; 6113 unsigned char default_e[] = { 0x1, 0x0, 0x1 }; 6114 6115 e.data = default_e; 6116 e.len = sizeof(default_e); 6117 6118 rsareq = fopen(reqfn, "r"); 6119 rsaresp = stdout; 6120 while (fgets(buf, sizeof buf, rsareq) != NULL) { 6121 /* a comment or blank line */ 6122 if (buf[0] == '#' || buf[0] == '\n') { 6123 fputs(buf, rsaresp); 6124 continue; 6125 } 6126 6127 /* [Mod = x] */ 6128 if (buf[0] == '[') { 6129 if (buf[1] == 'm') { 6130 if (sscanf(buf, "[mod = %d]", &keySize) != 1) { 6131 goto loser; 6132 } 6133 len = keySize / 8; 6134 len2 = keySize / 16; 6135 } 6136 fputs(buf, rsaresp); 6137 continue; 6138 } 6139 /* N = ...*/ 6140 if (buf[0] == 'N') { 6141 6142 if (sscanf(buf, "N = %d", &count) != 1) { 6143 goto loser; 6144 } 6145 6146 /* Generate a DSA key, and output the key pair for N times */ 6147 for (i = 0; i < count; i++) { 6148 RSAPrivateKey *rsakey = NULL; 6149 if ((rsakey = RSA_NewKey(keySize, &e)) == NULL) { 6150 fprintf(rsaresp, "ERROR: Unable to generate RSA key"); 6151 goto loser; 6152 } 6153 pad(buf2, len, rsakey->publicExponent.data, 6154 rsakey->publicExponent.len); 6155 to_hex_str(buf, buf2, len); 6156 fprintf(rsaresp, "e = %s\n", buf); 6157 pad(buf2, len2, rsakey->prime1.data, 6158 rsakey->prime1.len); 6159 to_hex_str(buf, buf2, len2); 6160 fprintf(rsaresp, "p = %s\n", buf); 6161 pad(buf2, len2, rsakey->prime2.data, 6162 rsakey->prime2.len); 6163 to_hex_str(buf, buf2, len2); 6164 fprintf(rsaresp, "q = %s\n", buf); 6165 pad(buf2, len, rsakey->modulus.data, 6166 rsakey->modulus.len); 6167 to_hex_str(buf, buf2, len); 6168 fprintf(rsaresp, "n = %s\n", buf); 6169 pad(buf2, len, rsakey->privateExponent.data, 6170 rsakey->privateExponent.len); 6171 to_hex_str(buf, buf2, len); 6172 fprintf(rsaresp, "d = %s\n", buf); 6173 fprintf(rsaresp, "\n"); 6174 PORT_FreeArena(rsakey->arena, PR_TRUE); 6175 rsakey = NULL; 6176 } 6177 continue; 6178 } 6179 } 6180 loser: 6181 fclose(rsareq); 6182 } 6183 6184 /* 6185 * Perform the RSA Signature Generation Test. 6186 * 6187 * reqfn is the pathname of the REQUEST file. 6188 * 6189 * The output RESPONSE file is written to stdout. 6190 */ 6191 void 6192 rsa_siggen_test(char *reqfn) 6193 { 6194 char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 1]; 6195 /* buf holds one line from the input REQUEST file 6196 * or to the output RESPONSE file. 6197 * 2x for HEX output + 1 for \n 6198 */ 6199 FILE *rsareq; /* input stream from the REQUEST file */ 6200 FILE *rsaresp; /* output stream to the RESPONSE file */ 6201 int i, j; 6202 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 6203 unsigned int shaLength = 0; /* length of SHA */ 6204 HASH_HashType shaAlg = HASH_AlgNULL; /* type of SHA Alg */ 6205 SECOidTag shaOid = SEC_OID_UNKNOWN; 6206 int modulus; /* the Modulus size */ 6207 int publicExponent = DEFAULT_RSA_PUBLIC_EXPONENT; 6208 SECItem pe = { 0, 0, 0 }; 6209 unsigned char pubEx[4]; 6210 int peCount = 0; 6211 6212 RSAPrivateKey *rsaBlapiPrivKey = NULL; /* holds RSA private and 6213 * public keys */ 6214 RSAPublicKey *rsaBlapiPublicKey = NULL; /* hold RSA public key */ 6215 6216 rsareq = fopen(reqfn, "r"); 6217 rsaresp = stdout; 6218 6219 /* calculate the exponent */ 6220 for (i = 0; i < 4; i++) { 6221 if (peCount || (publicExponent & 6222 ((unsigned long)0xff000000L >> (i * 6223 8)))) { 6224 pubEx[peCount] = 6225 (unsigned char)((publicExponent >> (3 - i) * 8) & 0xff); 6226 peCount++; 6227 } 6228 } 6229 pe.len = peCount; 6230 pe.data = &pubEx[0]; 6231 pe.type = siBuffer; 6232 6233 while (fgets(buf, sizeof buf, rsareq) != NULL) { 6234 /* a comment or blank line */ 6235 if (buf[0] == '#' || buf[0] == '\n') { 6236 fputs(buf, rsaresp); 6237 continue; 6238 } 6239 6240 /* [mod = ...] */ 6241 if (buf[0] == '[') { 6242 6243 if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 6244 goto loser; 6245 } 6246 if (modulus > RSA_MAX_TEST_MODULUS_BITS) { 6247 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n"); 6248 goto loser; 6249 } 6250 6251 fputs(buf, rsaresp); 6252 6253 if (rsaBlapiPrivKey != NULL) { 6254 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); 6255 rsaBlapiPrivKey = NULL; 6256 rsaBlapiPublicKey = NULL; 6257 } 6258 6259 rsaBlapiPrivKey = RSA_NewKey(modulus, &pe); 6260 if (rsaBlapiPrivKey == NULL) { 6261 fprintf(rsaresp, "Error unable to create RSA key\n"); 6262 goto loser; 6263 } 6264 6265 to_hex_str(buf, rsaBlapiPrivKey->modulus.data, 6266 rsaBlapiPrivKey->modulus.len); 6267 fprintf(rsaresp, "\nn = %s\n\n", buf); 6268 to_hex_str(buf, rsaBlapiPrivKey->publicExponent.data, 6269 rsaBlapiPrivKey->publicExponent.len); 6270 fprintf(rsaresp, "e = %s\n", buf); 6271 /* convert private key to public key. Memory 6272 * is freed with private key's arena */ 6273 rsaBlapiPublicKey = (RSAPublicKey *)PORT_ArenaAlloc( 6274 rsaBlapiPrivKey->arena, 6275 sizeof(RSAPublicKey)); 6276 6277 rsaBlapiPublicKey->modulus.len = rsaBlapiPrivKey->modulus.len; 6278 rsaBlapiPublicKey->modulus.data = rsaBlapiPrivKey->modulus.data; 6279 rsaBlapiPublicKey->publicExponent.len = 6280 rsaBlapiPrivKey->publicExponent.len; 6281 rsaBlapiPublicKey->publicExponent.data = 6282 rsaBlapiPrivKey->publicExponent.data; 6283 continue; 6284 } 6285 6286 /* SHAAlg = ... */ 6287 if (strncmp(buf, "SHAAlg", 6) == 0) { 6288 i = 6; 6289 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6290 i++; 6291 } 6292 /* set the SHA Algorithm */ 6293 shaAlg = hash_string_to_hashType(&buf[i]); 6294 if (shaAlg == HASH_AlgNULL) { 6295 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); 6296 goto loser; 6297 } 6298 fputs(buf, rsaresp); 6299 continue; 6300 } 6301 /* Msg = ... */ 6302 if (strncmp(buf, "Msg", 3) == 0) { 6303 6304 unsigned char msg[128]; /* MAX msg 128 */ 6305 unsigned int rsa_bytes_signed; 6306 unsigned char rsa_computed_signature[RSA_MAX_TEST_MODULUS_BYTES]; 6307 SECStatus rv = SECFailure; 6308 NSSLOWKEYPublicKey *rsa_public_key; 6309 NSSLOWKEYPrivateKey *rsa_private_key; 6310 NSSLOWKEYPrivateKey low_RSA_private_key = { NULL, 6311 NSSLOWKEYRSAKey }; 6312 NSSLOWKEYPublicKey low_RSA_public_key = { NULL, 6313 NSSLOWKEYRSAKey }; 6314 6315 low_RSA_private_key.u.rsa = *rsaBlapiPrivKey; 6316 low_RSA_public_key.u.rsa = *rsaBlapiPublicKey; 6317 6318 rsa_private_key = &low_RSA_private_key; 6319 rsa_public_key = &low_RSA_public_key; 6320 6321 memset(sha, 0, sizeof sha); 6322 memset(msg, 0, sizeof msg); 6323 rsa_bytes_signed = 0; 6324 memset(rsa_computed_signature, 0, sizeof rsa_computed_signature); 6325 6326 i = 3; 6327 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6328 i++; 6329 } 6330 for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof(msg); i += 2, j++) { 6331 hex_to_byteval(&buf[i], &msg[j]); 6332 } 6333 shaLength = fips_hashLen(shaAlg); 6334 if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) { 6335 if (shaLength == 0) { 6336 fprintf(rsaresp, "ERROR: SHAAlg not defined."); 6337 } 6338 fprintf(rsaresp, "ERROR: Unable to generate SHA%x", 6339 shaLength == 160 ? 1 : shaLength); 6340 goto loser; 6341 } 6342 shaOid = fips_hashOid(shaAlg); 6343 6344 /* Perform RSA signature with the RSA private key. */ 6345 rv = RSA_HashSign(shaOid, 6346 rsa_private_key, 6347 rsa_computed_signature, 6348 &rsa_bytes_signed, 6349 nsslowkey_PrivateModulusLen(rsa_private_key), 6350 sha, 6351 shaLength); 6352 6353 if (rv != SECSuccess) { 6354 fprintf(rsaresp, "ERROR: RSA_HashSign failed"); 6355 goto loser; 6356 } 6357 6358 /* Output the signature */ 6359 fputs(buf, rsaresp); 6360 to_hex_str(buf, rsa_computed_signature, rsa_bytes_signed); 6361 fprintf(rsaresp, "S = %s\n", buf); 6362 6363 /* Perform RSA verification with the RSA public key. */ 6364 rv = RSA_HashCheckSign(shaOid, 6365 rsa_public_key, 6366 rsa_computed_signature, 6367 rsa_bytes_signed, 6368 sha, 6369 shaLength); 6370 if (rv != SECSuccess) { 6371 fprintf(rsaresp, "ERROR: RSA_HashCheckSign failed"); 6372 goto loser; 6373 } 6374 continue; 6375 } 6376 } 6377 loser: 6378 fclose(rsareq); 6379 6380 if (rsaBlapiPrivKey != NULL) { 6381 /* frees private and public key */ 6382 PORT_FreeArena(rsaBlapiPrivKey->arena, PR_TRUE); 6383 rsaBlapiPrivKey = NULL; 6384 rsaBlapiPublicKey = NULL; 6385 } 6386 } 6387 /* 6388 * Perform the RSA Signature Verification Test. 6389 * 6390 * reqfn is the pathname of the REQUEST file. 6391 * 6392 * The output RESPONSE file is written to stdout. 6393 */ 6394 void 6395 rsa_sigver_test(char *reqfn) 6396 { 6397 char buf[2 * RSA_MAX_TEST_MODULUS_BYTES + 7]; 6398 /* buf holds one line from the input REQUEST file 6399 * or to the output RESPONSE file. 6400 * s = 2x for HEX output + 1 for \n 6401 */ 6402 FILE *rsareq; /* input stream from the REQUEST file */ 6403 FILE *rsaresp; /* output stream to the RESPONSE file */ 6404 int i, j; 6405 unsigned char sha[HASH_LENGTH_MAX]; /* SHA digest */ 6406 unsigned int shaLength = 0; /* actual length of the digest */ 6407 HASH_HashType shaAlg = HASH_AlgNULL; 6408 SECOidTag shaOid = SEC_OID_UNKNOWN; 6409 int modulus = 0; /* the Modulus size */ 6410 unsigned char signature[513]; /* largest signature size + '\n' */ 6411 unsigned int signatureLength = 0; /* actual length of the signature */ 6412 PRBool keyvalid = PR_TRUE; 6413 6414 RSAPublicKey rsaBlapiPublicKey; /* hold RSA public key */ 6415 6416 rsareq = fopen(reqfn, "r"); 6417 rsaresp = stdout; 6418 memset(&rsaBlapiPublicKey, 0, sizeof(RSAPublicKey)); 6419 6420 while (fgets(buf, sizeof buf, rsareq) != NULL) { 6421 /* a comment or blank line */ 6422 if (buf[0] == '#' || buf[0] == '\n') { 6423 fputs(buf, rsaresp); 6424 continue; 6425 } 6426 6427 /* [Mod = ...] */ 6428 if (buf[0] == '[') { 6429 unsigned int flen; /* length in bytes of the field size */ 6430 6431 if (rsaBlapiPublicKey.modulus.data) { /* n */ 6432 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); 6433 } 6434 if (sscanf(buf, "[mod = %d]", &modulus) != 1) { 6435 goto loser; 6436 } 6437 6438 if (modulus > RSA_MAX_TEST_MODULUS_BITS) { 6439 fprintf(rsaresp, "ERROR: modulus greater than test maximum\n"); 6440 goto loser; 6441 } 6442 6443 fputs(buf, rsaresp); 6444 6445 signatureLength = flen = modulus / 8; 6446 6447 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.modulus, flen); 6448 if (rsaBlapiPublicKey.modulus.data == NULL) { 6449 goto loser; 6450 } 6451 continue; 6452 } 6453 6454 /* n = ... modulus */ 6455 if (buf[0] == 'n') { 6456 i = 1; 6457 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6458 i++; 6459 } 6460 keyvalid = from_hex_str(&rsaBlapiPublicKey.modulus.data[0], 6461 rsaBlapiPublicKey.modulus.len, 6462 &buf[i]); 6463 6464 if (!keyvalid) { 6465 fprintf(rsaresp, "ERROR: rsa_sigver n not valid.\n"); 6466 goto loser; 6467 } 6468 fputs(buf, rsaresp); 6469 continue; 6470 } 6471 6472 /* SHAAlg = ... */ 6473 if (strncmp(buf, "SHAAlg", 6) == 0) { 6474 i = 6; 6475 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6476 i++; 6477 } 6478 /* set the SHA Algorithm */ 6479 shaAlg = hash_string_to_hashType(&buf[i]); 6480 if (shaAlg == HASH_AlgNULL) { 6481 fprintf(rsaresp, "ERROR: Unable to find SHAAlg type"); 6482 goto loser; 6483 } 6484 fputs(buf, rsaresp); 6485 continue; 6486 } 6487 6488 /* e = ... public Key */ 6489 if (buf[0] == 'e') { 6490 unsigned char data[RSA_MAX_TEST_EXPONENT_BYTES]; 6491 unsigned char t; 6492 6493 memset(data, 0, sizeof data); 6494 6495 if (rsaBlapiPublicKey.publicExponent.data) { /* e */ 6496 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); 6497 } 6498 6499 i = 1; 6500 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6501 i++; 6502 } 6503 /* skip leading zero's */ 6504 while (isxdigit((unsigned char)buf[i])) { 6505 hex_to_byteval(&buf[i], &t); 6506 if (t == 0) { 6507 i += 2; 6508 } else 6509 break; 6510 } 6511 6512 /* get the exponent */ 6513 for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof data; i += 2, j++) { 6514 hex_to_byteval(&buf[i], &data[j]); 6515 } 6516 6517 if (j == 0) { 6518 j = 1; 6519 } /* to handle 1 byte length exponents */ 6520 6521 SECITEM_AllocItem(NULL, &rsaBlapiPublicKey.publicExponent, j); 6522 if (rsaBlapiPublicKey.publicExponent.data == NULL) { 6523 goto loser; 6524 } 6525 6526 for (i = 0; i < j; i++) { 6527 rsaBlapiPublicKey.publicExponent.data[i] = data[i]; 6528 } 6529 6530 fputs(buf, rsaresp); 6531 continue; 6532 } 6533 6534 /* Msg = ... */ 6535 if (strncmp(buf, "Msg", 3) == 0) { 6536 unsigned char msg[128]; /* MAX msg 128 */ 6537 6538 memset(sha, 0, sizeof sha); 6539 memset(msg, 0, sizeof msg); 6540 6541 i = 3; 6542 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6543 i++; 6544 } 6545 6546 for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof msg; i += 2, j++) { 6547 hex_to_byteval(&buf[i], &msg[j]); 6548 } 6549 6550 shaLength = fips_hashLen(shaAlg); 6551 if (fips_hashBuf(shaAlg, sha, msg, j) != SECSuccess) { 6552 if (shaLength == 0) { 6553 fprintf(rsaresp, "ERROR: SHAAlg not defined."); 6554 } 6555 fprintf(rsaresp, "ERROR: Unable to generate SHA%x", 6556 shaLength == 160 ? 1 : shaLength); 6557 goto loser; 6558 } 6559 6560 fputs(buf, rsaresp); 6561 continue; 6562 } 6563 6564 /* S = ... */ 6565 if (buf[0] == 'S') { 6566 SECStatus rv = SECFailure; 6567 NSSLOWKEYPublicKey *rsa_public_key; 6568 NSSLOWKEYPublicKey low_RSA_public_key = { NULL, 6569 NSSLOWKEYRSAKey }; 6570 6571 /* convert to a low RSA public key */ 6572 low_RSA_public_key.u.rsa = rsaBlapiPublicKey; 6573 rsa_public_key = &low_RSA_public_key; 6574 6575 memset(signature, 0, sizeof(signature)); 6576 i = 1; 6577 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6578 i++; 6579 } 6580 6581 for (j = 0; isxdigit((unsigned char)buf[i]) && j < sizeof signature; i += 2, j++) { 6582 hex_to_byteval(&buf[i], &signature[j]); 6583 } 6584 6585 signatureLength = j; 6586 fputs(buf, rsaresp); 6587 6588 shaOid = fips_hashOid(shaAlg); 6589 6590 /* Perform RSA verification with the RSA public key. */ 6591 rv = RSA_HashCheckSign(shaOid, 6592 rsa_public_key, 6593 signature, 6594 signatureLength, 6595 sha, 6596 shaLength); 6597 if (rv == SECSuccess) { 6598 fputs("Result = P\n", rsaresp); 6599 } else { 6600 fputs("Result = F\n", rsaresp); 6601 } 6602 continue; 6603 } 6604 } 6605 loser: 6606 fclose(rsareq); 6607 if (rsaBlapiPublicKey.modulus.data) { /* n */ 6608 SECITEM_ZfreeItem(&rsaBlapiPublicKey.modulus, PR_FALSE); 6609 } 6610 if (rsaBlapiPublicKey.publicExponent.data) { /* e */ 6611 SECITEM_ZfreeItem(&rsaBlapiPublicKey.publicExponent, PR_FALSE); 6612 } 6613 } 6614 6615 void 6616 tls(char *reqfn) 6617 { 6618 char buf[256]; /* holds one line from the input REQUEST file. 6619 * needs to be large enough to hold the longest 6620 * line "XSeed = <128 hex digits>\n". 6621 */ 6622 unsigned char *pms = NULL; 6623 int pms_len; 6624 unsigned char *master_secret = NULL; 6625 unsigned char *key_block = NULL; 6626 int key_block_len; 6627 unsigned char serverHello_random[SSL3_RANDOM_LENGTH]; 6628 unsigned char clientHello_random[SSL3_RANDOM_LENGTH]; 6629 unsigned char server_random[SSL3_RANDOM_LENGTH]; 6630 unsigned char client_random[SSL3_RANDOM_LENGTH]; 6631 FILE *tlsreq = NULL; /* input stream from the REQUEST file */ 6632 FILE *tlsresp; /* output stream to the RESPONSE file */ 6633 unsigned int i, j; 6634 CK_SLOT_ID slotList[10]; 6635 CK_SLOT_ID slotID; 6636 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]); 6637 CK_ULONG count; 6638 static const CK_C_INITIALIZE_ARGS pk11args = { 6639 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, 6640 (void *)"flags=readOnly,noCertDB,noModDB", NULL 6641 }; 6642 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY; 6643 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET; 6644 static CK_BBOOL ck_true = CK_TRUE; 6645 static CK_ULONG one = 1; 6646 CK_ATTRIBUTE create_template[] = { 6647 { CKA_VALUE, NULL, 0 }, 6648 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 6649 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 6650 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 6651 }; 6652 CK_ULONG create_template_count = 6653 sizeof(create_template) / sizeof(create_template[0]); 6654 CK_ATTRIBUTE derive_template[] = { 6655 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 6656 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 6657 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 6658 { CKA_VALUE_LEN, &one, sizeof(one) }, 6659 }; 6660 CK_ULONG derive_template_count = 6661 sizeof(derive_template) / sizeof(derive_template[0]); 6662 CK_ATTRIBUTE master_template = { CKA_VALUE, NULL, 0 }; 6663 CK_ATTRIBUTE kb1_template = { CKA_VALUE, NULL, 0 }; 6664 CK_ATTRIBUTE kb2_template = { CKA_VALUE, NULL, 0 }; 6665 6666 CK_MECHANISM master_mech = { CKM_TLS_MASTER_KEY_DERIVE, NULL, 0 }; 6667 CK_MECHANISM key_block_mech = { CKM_TLS_KEY_AND_MAC_DERIVE, NULL, 0 }; 6668 CK_TLS12_MASTER_KEY_DERIVE_PARAMS master_params; 6669 CK_TLS12_KEY_MAT_PARAMS key_block_params; 6670 CK_SSL3_KEY_MAT_OUT key_material; 6671 CK_RV crv; 6672 6673 /* set up PKCS #11 parameters */ 6674 master_params.prfHashMechanism = CKM_SHA256; 6675 master_params.pVersion = NULL; 6676 master_params.RandomInfo.pClientRandom = clientHello_random; 6677 master_params.RandomInfo.ulClientRandomLen = sizeof(clientHello_random); 6678 master_params.RandomInfo.pServerRandom = serverHello_random; 6679 master_params.RandomInfo.ulServerRandomLen = sizeof(serverHello_random); 6680 master_mech.pParameter = (void *)&master_params; 6681 master_mech.ulParameterLen = sizeof(master_params); 6682 key_block_params.prfHashMechanism = CKM_SHA256; 6683 key_block_params.ulMacSizeInBits = 0; 6684 key_block_params.ulKeySizeInBits = 0; 6685 key_block_params.ulIVSizeInBits = 0; 6686 key_block_params.bIsExport = PR_FALSE; /* ignored anyway for TLS mech */ 6687 key_block_params.RandomInfo.pClientRandom = client_random; 6688 key_block_params.RandomInfo.ulClientRandomLen = sizeof(client_random); 6689 key_block_params.RandomInfo.pServerRandom = server_random; 6690 key_block_params.RandomInfo.ulServerRandomLen = sizeof(server_random); 6691 key_block_params.pReturnedKeyMaterial = &key_material; 6692 key_block_mech.pParameter = (void *)&key_block_params; 6693 key_block_mech.ulParameterLen = sizeof(key_block_params); 6694 6695 crv = NSC_Initialize((CK_VOID_PTR)&pk11args); 6696 if (crv != CKR_OK) { 6697 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); 6698 goto loser; 6699 } 6700 count = slotListCount; 6701 crv = NSC_GetSlotList(PR_TRUE, slotList, &count); 6702 if (crv != CKR_OK) { 6703 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv); 6704 goto loser; 6705 } 6706 if ((count > slotListCount) || count < 1) { 6707 fprintf(stderr, 6708 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n", 6709 (int)count, (int)slotListCount); 6710 goto loser; 6711 } 6712 slotID = slotList[0]; 6713 tlsreq = fopen(reqfn, "r"); 6714 tlsresp = stdout; 6715 while (fgets(buf, sizeof buf, tlsreq) != NULL) { 6716 /* a comment or blank line */ 6717 if (buf[0] == '#' || buf[0] == '\n') { 6718 fputs(buf, tlsresp); 6719 continue; 6720 } 6721 /* [Xchange - SHA1] */ 6722 if (buf[0] == '[') { 6723 if (strncmp(buf, "[TLS", 4) == 0) { 6724 if (buf[7] == '0') { 6725 /* CK_SSL3_MASTER_KEY_DERIVE_PARAMS is a subset of 6726 * CK_TLS12_MASTER_KEY_DERIVE_PARAMS and 6727 * CK_SSL3_KEY_MAT_PARAMS is a subset of 6728 * CK_TLS12_KEY_MAT_PARAMS. The latter params have 6729 * an extra prfHashMechanism field at the end. */ 6730 master_mech.mechanism = CKM_TLS_MASTER_KEY_DERIVE; 6731 key_block_mech.mechanism = CKM_TLS_KEY_AND_MAC_DERIVE; 6732 master_mech.ulParameterLen = sizeof(CK_SSL3_MASTER_KEY_DERIVE_PARAMS); 6733 key_block_mech.ulParameterLen = sizeof(CK_SSL3_KEY_MAT_PARAMS); 6734 } else if (buf[7] == '2') { 6735 if (strncmp(&buf[10], "SHA-1", 5) == 0) { 6736 master_params.prfHashMechanism = CKM_SHA_1; 6737 key_block_params.prfHashMechanism = CKM_SHA_1; 6738 } else if (strncmp(&buf[10], "SHA-224", 7) == 0) { 6739 master_params.prfHashMechanism = CKM_SHA224; 6740 key_block_params.prfHashMechanism = CKM_SHA224; 6741 } else if (strncmp(&buf[10], "SHA-256", 7) == 0) { 6742 master_params.prfHashMechanism = CKM_SHA256; 6743 key_block_params.prfHashMechanism = CKM_SHA256; 6744 } else if (strncmp(&buf[10], "SHA-384", 7) == 0) { 6745 master_params.prfHashMechanism = CKM_SHA384; 6746 key_block_params.prfHashMechanism = CKM_SHA384; 6747 } else if (strncmp(&buf[10], "SHA-512", 7) == 0) { 6748 master_params.prfHashMechanism = CKM_SHA512; 6749 key_block_params.prfHashMechanism = CKM_SHA512; 6750 } else { 6751 fprintf(tlsresp, "ERROR: Unable to find prf Hash type"); 6752 goto loser; 6753 } 6754 master_mech.mechanism = CKM_TLS12_MASTER_KEY_DERIVE; 6755 key_block_mech.mechanism = CKM_TLS12_KEY_AND_MAC_DERIVE; 6756 master_mech.ulParameterLen = sizeof(master_params); 6757 key_block_mech.ulParameterLen = sizeof(key_block_params); 6758 } else { 6759 fprintf(stderr, "Unknown TLS type %x\n", 6760 (unsigned int)buf[0]); 6761 goto loser; 6762 } 6763 } 6764 if (strncmp(buf, "[pre-master", 11) == 0) { 6765 if (sscanf(buf, "[pre-master secret length = %d]", 6766 &pms_len) != 1) { 6767 goto loser; 6768 } 6769 pms_len = pms_len / 8; 6770 pms = malloc(pms_len); 6771 master_secret = malloc(pms_len); 6772 create_template[0].pValue = pms; 6773 create_template[0].ulValueLen = pms_len; 6774 master_template.pValue = master_secret; 6775 master_template.ulValueLen = pms_len; 6776 } 6777 if (strncmp(buf, "[key", 4) == 0) { 6778 if (sscanf(buf, "[key block length = %d]", &key_block_len) != 1) { 6779 goto loser; 6780 } 6781 key_block_params.ulKeySizeInBits = 8; 6782 key_block_params.ulIVSizeInBits = key_block_len / 2 - 8; 6783 key_block_len = key_block_len / 8; 6784 key_block = malloc(key_block_len); 6785 kb1_template.pValue = &key_block[0]; 6786 kb1_template.ulValueLen = 1; 6787 kb2_template.pValue = &key_block[1]; 6788 kb2_template.ulValueLen = 1; 6789 key_material.pIVClient = &key_block[2]; 6790 key_material.pIVServer = &key_block[2 + key_block_len / 2 - 1]; 6791 } 6792 fputs(buf, tlsresp); 6793 continue; 6794 } 6795 /* "COUNT = x" begins a new data set */ 6796 if (strncmp(buf, "COUNT", 5) == 0) { 6797 /* zeroize the variables for the test with this data set */ 6798 memset(pms, 0, pms_len); 6799 memset(master_secret, 0, pms_len); 6800 memset(key_block, 0, key_block_len); 6801 fputs(buf, tlsresp); 6802 continue; 6803 } 6804 /* pre_master_secret = ... */ 6805 if (strncmp(buf, "pre_master_secret", 17) == 0) { 6806 i = 17; 6807 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6808 i++; 6809 } 6810 for (j = 0; j < pms_len; i += 2, j++) { 6811 hex_to_byteval(&buf[i], &pms[j]); 6812 } 6813 fputs(buf, tlsresp); 6814 continue; 6815 } 6816 /* serverHello_random = ... */ 6817 if (strncmp(buf, "serverHello_random", 18) == 0) { 6818 i = 18; 6819 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6820 i++; 6821 } 6822 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) { 6823 hex_to_byteval(&buf[i], &serverHello_random[j]); 6824 } 6825 fputs(buf, tlsresp); 6826 continue; 6827 } 6828 /* clientHello_random = ... */ 6829 if (strncmp(buf, "clientHello_random", 18) == 0) { 6830 i = 18; 6831 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6832 i++; 6833 } 6834 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) { 6835 hex_to_byteval(&buf[i], &clientHello_random[j]); 6836 } 6837 fputs(buf, tlsresp); 6838 continue; 6839 } 6840 /* server_random = ... */ 6841 if (strncmp(buf, "server_random", 13) == 0) { 6842 i = 13; 6843 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6844 i++; 6845 } 6846 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) { 6847 hex_to_byteval(&buf[i], &server_random[j]); 6848 } 6849 fputs(buf, tlsresp); 6850 continue; 6851 } 6852 /* client_random = ... */ 6853 if (strncmp(buf, "client_random", 13) == 0) { 6854 CK_SESSION_HANDLE session; 6855 CK_OBJECT_HANDLE pms_handle; 6856 CK_OBJECT_HANDLE master_handle; 6857 CK_OBJECT_HANDLE fake_handle; 6858 i = 13; 6859 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 6860 i++; 6861 } 6862 for (j = 0; j < SSL3_RANDOM_LENGTH; i += 2, j++) { 6863 hex_to_byteval(&buf[i], &client_random[j]); 6864 } 6865 fputs(buf, tlsresp); 6866 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session); 6867 if (crv != CKR_OK) { 6868 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", 6869 (unsigned int)crv); 6870 goto loser; 6871 } 6872 crv = NSC_CreateObject(session, create_template, 6873 create_template_count, &pms_handle); 6874 if (crv != CKR_OK) { 6875 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n", 6876 (unsigned int)crv); 6877 goto loser; 6878 } 6879 crv = NSC_DeriveKey(session, &master_mech, pms_handle, 6880 derive_template, derive_template_count - 1, 6881 &master_handle); 6882 if (crv != CKR_OK) { 6883 fprintf(stderr, "NSC_DeriveKey(master) failed crv=0x%x\n", 6884 (unsigned int)crv); 6885 goto loser; 6886 } 6887 crv = NSC_GetAttributeValue(session, master_handle, 6888 &master_template, 1); 6889 if (crv != CKR_OK) { 6890 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n", 6891 (unsigned int)crv); 6892 goto loser; 6893 } 6894 fputs("master_secret = ", tlsresp); 6895 to_hex_str(buf, master_secret, pms_len); 6896 fputs(buf, tlsresp); 6897 fputc('\n', tlsresp); 6898 crv = NSC_DeriveKey(session, &key_block_mech, master_handle, 6899 derive_template, derive_template_count, &fake_handle); 6900 if (crv != CKR_OK) { 6901 fprintf(stderr, 6902 "NSC_DeriveKey(keyblock) failed crv=0x%x\n", 6903 (unsigned int)crv); 6904 goto loser; 6905 } 6906 crv = NSC_GetAttributeValue(session, key_material.hClientKey, 6907 &kb1_template, 1); 6908 if (crv != CKR_OK) { 6909 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n", 6910 (unsigned int)crv); 6911 goto loser; 6912 } 6913 crv = NSC_GetAttributeValue(session, key_material.hServerKey, 6914 &kb2_template, 1); 6915 if (crv != CKR_OK) { 6916 fprintf(stderr, "NSC_GetAttribute failed crv=0x%x\n", 6917 (unsigned int)crv); 6918 goto loser; 6919 } 6920 fputs("key_block = ", tlsresp); 6921 to_hex_str(buf, key_block, key_block_len); 6922 fputs(buf, tlsresp); 6923 fputc('\n', tlsresp); 6924 crv = NSC_CloseSession(session); 6925 continue; 6926 } 6927 } 6928 loser: 6929 NSC_Finalize(NULL); 6930 if (pms) 6931 free(pms); 6932 if (master_secret) 6933 free(master_secret); 6934 if (key_block) 6935 free(key_block); 6936 if (tlsreq) 6937 fclose(tlsreq); 6938 } 6939 6940 void 6941 ikev1(char *reqfn) 6942 { 6943 char buf[4096]; /* holds one line from the input REQUEST file. 6944 * needs to be large enough to hold the longest 6945 * line "g^xy = <2048 hex digits>\n". 6946 */ 6947 unsigned char *gxy = NULL; 6948 int gxy_len; 6949 unsigned char *Ni = NULL; 6950 int Ni_len; 6951 unsigned char *Nr = NULL; 6952 int Nr_len; 6953 unsigned char CKYi[8]; 6954 int CKYi_len; 6955 unsigned char CKYr[8]; 6956 int CKYr_len; 6957 unsigned int i, j; 6958 FILE *ikereq = NULL; /* input stream from the REQUEST file */ 6959 FILE *ikeresp; /* output stream to the RESPONSE file */ 6960 6961 CK_SLOT_ID slotList[10]; 6962 CK_SLOT_ID slotID; 6963 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]); 6964 CK_ULONG count; 6965 static const CK_C_INITIALIZE_ARGS pk11args = { 6966 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, 6967 (void *)"flags=readOnly,noCertDB,noModDB", NULL 6968 }; 6969 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY; 6970 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET; 6971 static CK_BBOOL ck_true = CK_TRUE; 6972 static CK_ULONG keyLen = 1; 6973 CK_ATTRIBUTE gxy_template[] = { 6974 { CKA_VALUE, NULL, 0 }, /* must be first */ 6975 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 6976 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 6977 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 6978 }; 6979 CK_ULONG gxy_template_count = 6980 sizeof(gxy_template) / sizeof(gxy_template[0]); 6981 CK_ATTRIBUTE derive_template[] = { 6982 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 6983 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 6984 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 6985 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */ 6986 }; 6987 CK_ULONG derive_template_count = 6988 sizeof(derive_template) / sizeof(derive_template[0]); 6989 CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 }; 6990 CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 }; 6991 CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 }; 6992 CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 }; 6993 unsigned char skeyid_secret[HASH_LENGTH_MAX]; 6994 unsigned char skeyid_d_secret[HASH_LENGTH_MAX]; 6995 unsigned char skeyid_a_secret[HASH_LENGTH_MAX]; 6996 unsigned char skeyid_e_secret[HASH_LENGTH_MAX]; 6997 6998 CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 }; 6999 CK_MECHANISM ike1_mech = { CKM_IKE1_PRF_DERIVE, NULL, 0 }; 7000 CK_IKE_PRF_DERIVE_PARAMS ike_prf; 7001 CK_IKE1_PRF_DERIVE_PARAMS ike1_prf; 7002 CK_RV crv; 7003 7004 /* set up PKCS #11 parameters */ 7005 ike_prf.bDataAsKey = PR_TRUE; 7006 ike_prf.bRekey = PR_FALSE; 7007 ike_prf.hNewKey = CK_INVALID_HANDLE; 7008 CKYi_len = sizeof(CKYi); 7009 CKYr_len = sizeof(CKYr); 7010 ike1_prf.pCKYi = CKYi; 7011 ike1_prf.ulCKYiLen = CKYi_len; 7012 ike1_prf.pCKYr = CKYr; 7013 ike1_prf.ulCKYrLen = CKYr_len; 7014 ike_mech.pParameter = &ike_prf; 7015 ike_mech.ulParameterLen = sizeof(ike_prf); 7016 ike1_mech.pParameter = &ike1_prf; 7017 ike1_mech.ulParameterLen = sizeof(ike1_prf); 7018 skeyid_template.pValue = skeyid_secret; 7019 skeyid_template.ulValueLen = HASH_LENGTH_MAX; 7020 skeyid_d_template.pValue = skeyid_d_secret; 7021 skeyid_d_template.ulValueLen = HASH_LENGTH_MAX; 7022 skeyid_a_template.pValue = skeyid_a_secret; 7023 skeyid_a_template.ulValueLen = HASH_LENGTH_MAX; 7024 skeyid_e_template.pValue = skeyid_e_secret; 7025 skeyid_e_template.ulValueLen = HASH_LENGTH_MAX; 7026 7027 crv = NSC_Initialize((CK_VOID_PTR)&pk11args); 7028 if (crv != CKR_OK) { 7029 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); 7030 goto loser; 7031 } 7032 count = slotListCount; 7033 crv = NSC_GetSlotList(PR_TRUE, slotList, &count); 7034 if (crv != CKR_OK) { 7035 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv); 7036 goto loser; 7037 } 7038 if ((count > slotListCount) || count < 1) { 7039 fprintf(stderr, 7040 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n", 7041 (int)count, (int)slotListCount); 7042 goto loser; 7043 } 7044 slotID = slotList[0]; 7045 ikereq = fopen(reqfn, "r"); 7046 ikeresp = stdout; 7047 while (fgets(buf, sizeof buf, ikereq) != NULL) { 7048 /* a comment or blank line */ 7049 if (buf[0] == '#' || buf[0] == '\n') { 7050 fputs(buf, ikeresp); 7051 continue; 7052 } 7053 /* [.....] */ 7054 if (buf[0] == '[') { 7055 if (strncmp(buf, "[SHA-1]", 7) == 0) { 7056 ike_prf.prfMechanism = CKM_SHA_1_HMAC; 7057 ike1_prf.prfMechanism = CKM_SHA_1_HMAC; 7058 } 7059 if (strncmp(buf, "[SHA-224]", 9) == 0) { 7060 ike_prf.prfMechanism = CKM_SHA224_HMAC; 7061 ike1_prf.prfMechanism = CKM_SHA224_HMAC; 7062 } 7063 if (strncmp(buf, "[SHA-256]", 9) == 0) { 7064 ike_prf.prfMechanism = CKM_SHA256_HMAC; 7065 ike1_prf.prfMechanism = CKM_SHA256_HMAC; 7066 } 7067 if (strncmp(buf, "[SHA-384]", 9) == 0) { 7068 ike_prf.prfMechanism = CKM_SHA384_HMAC; 7069 ike1_prf.prfMechanism = CKM_SHA384_HMAC; 7070 } 7071 if (strncmp(buf, "[SHA-512]", 9) == 0) { 7072 ike_prf.prfMechanism = CKM_SHA512_HMAC; 7073 ike1_prf.prfMechanism = CKM_SHA512_HMAC; 7074 } 7075 if (strncmp(buf, "[AES-XCBC", 9) == 0) { 7076 ike_prf.prfMechanism = CKM_AES_XCBC_MAC; 7077 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC; 7078 } 7079 if (strncmp(buf, "[g^xy", 5) == 0) { 7080 if (sscanf(buf, "[g^xy length = %d]", 7081 &gxy_len) != 1) { 7082 goto loser; 7083 } 7084 gxy_len = gxy_len / 8; 7085 if (gxy) 7086 free(gxy); 7087 gxy = malloc(gxy_len); 7088 gxy_template[0].pValue = gxy; 7089 gxy_template[0].ulValueLen = gxy_len; 7090 } 7091 if (strncmp(buf, "[Ni", 3) == 0) { 7092 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) { 7093 goto loser; 7094 } 7095 Ni_len = Ni_len / 8; 7096 if (Ni) 7097 free(Ni); 7098 Ni = malloc(Ni_len); 7099 ike_prf.pNi = Ni; 7100 ike_prf.ulNiLen = Ni_len; 7101 } 7102 if (strncmp(buf, "[Nr", 3) == 0) { 7103 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) { 7104 goto loser; 7105 } 7106 Nr_len = Nr_len / 8; 7107 if (Nr) 7108 free(Nr); 7109 Nr = malloc(Nr_len); 7110 ike_prf.pNr = Nr; 7111 ike_prf.ulNrLen = Nr_len; 7112 } 7113 fputs(buf, ikeresp); 7114 continue; 7115 } 7116 /* "COUNT = x" begins a new data set */ 7117 if (strncmp(buf, "COUNT", 5) == 0) { 7118 /* zeroize the variables for the test with this data set */ 7119 memset(gxy, 0, gxy_len); 7120 memset(Ni, 0, Ni_len); 7121 memset(Nr, 0, Nr_len); 7122 memset(CKYi, 0, CKYi_len); 7123 memset(CKYr, 0, CKYr_len); 7124 fputs(buf, ikeresp); 7125 continue; 7126 } 7127 /* Ni = ... */ 7128 if (strncmp(buf, "Ni", 2) == 0) { 7129 i = 2; 7130 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7131 i++; 7132 } 7133 for (j = 0; j < Ni_len; i += 2, j++) { 7134 hex_to_byteval(&buf[i], &Ni[j]); 7135 } 7136 fputs(buf, ikeresp); 7137 continue; 7138 } 7139 /* Nr = ... */ 7140 if (strncmp(buf, "Nr", 2) == 0) { 7141 i = 2; 7142 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7143 i++; 7144 } 7145 for (j = 0; j < Nr_len; i += 2, j++) { 7146 hex_to_byteval(&buf[i], &Nr[j]); 7147 } 7148 fputs(buf, ikeresp); 7149 continue; 7150 } 7151 /* CKYi = ... */ 7152 if (strncmp(buf, "CKY_I", 5) == 0) { 7153 i = 5; 7154 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7155 i++; 7156 } 7157 for (j = 0; j < CKYi_len; i += 2, j++) { 7158 hex_to_byteval(&buf[i], &CKYi[j]); 7159 } 7160 fputs(buf, ikeresp); 7161 continue; 7162 } 7163 /* CKYr = ... */ 7164 if (strncmp(buf, "CKY_R", 5) == 0) { 7165 i = 5; 7166 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7167 i++; 7168 } 7169 for (j = 0; j < CKYr_len; i += 2, j++) { 7170 hex_to_byteval(&buf[i], &CKYr[j]); 7171 } 7172 fputs(buf, ikeresp); 7173 continue; 7174 } 7175 /* g^xy = ... */ 7176 if (strncmp(buf, "g^xy", 4) == 0) { 7177 CK_SESSION_HANDLE session; 7178 CK_OBJECT_HANDLE gxy_handle; 7179 CK_OBJECT_HANDLE skeyid_handle; 7180 CK_OBJECT_HANDLE skeyid_d_handle; 7181 CK_OBJECT_HANDLE skeyid_a_handle; 7182 CK_OBJECT_HANDLE skeyid_e_handle; 7183 i = 4; 7184 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7185 i++; 7186 } 7187 for (j = 0; j < gxy_len; i += 2, j++) { 7188 hex_to_byteval(&buf[i], &gxy[j]); 7189 } 7190 fputs(buf, ikeresp); 7191 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session); 7192 if (crv != CKR_OK) { 7193 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", 7194 (unsigned int)crv); 7195 goto loser; 7196 } 7197 crv = NSC_CreateObject(session, gxy_template, 7198 gxy_template_count, &gxy_handle); 7199 if (crv != CKR_OK) { 7200 fprintf(stderr, "NSC_CreateObject failed crv=0x%x\n", 7201 (unsigned int)crv); 7202 goto loser; 7203 } 7204 /* get the skeyid key */ 7205 crv = NSC_DeriveKey(session, &ike_mech, gxy_handle, 7206 derive_template, derive_template_count - 1, 7207 &skeyid_handle); 7208 if (crv != CKR_OK) { 7209 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n", 7210 (unsigned int)crv); 7211 goto loser; 7212 } 7213 skeyid_template.ulValueLen = HASH_LENGTH_MAX; 7214 crv = NSC_GetAttributeValue(session, skeyid_handle, 7215 &skeyid_template, 1); 7216 if (crv != CKR_OK) { 7217 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n", 7218 (unsigned int)crv); 7219 goto loser; 7220 } 7221 /* use the length of the skeyid to set the target length of all the 7222 * other keys */ 7223 keyLen = skeyid_template.ulValueLen; 7224 ike1_prf.hKeygxy = gxy_handle; 7225 ike1_prf.bHasPrevKey = PR_FALSE; 7226 ike1_prf.keyNumber = 0; 7227 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7228 derive_template, derive_template_count, 7229 &skeyid_d_handle); 7230 if (crv != CKR_OK) { 7231 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n", 7232 (unsigned int)crv); 7233 goto loser; 7234 } 7235 7236 ike1_prf.hKeygxy = gxy_handle; 7237 ike1_prf.bHasPrevKey = CK_TRUE; 7238 ike1_prf.hPrevKey = skeyid_d_handle; 7239 ike1_prf.keyNumber = 1; 7240 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7241 derive_template, derive_template_count, 7242 &skeyid_a_handle); 7243 if (crv != CKR_OK) { 7244 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n", 7245 (unsigned int)crv); 7246 goto loser; 7247 } 7248 ike1_prf.hKeygxy = gxy_handle; 7249 ike1_prf.bHasPrevKey = CK_TRUE; 7250 ike1_prf.hPrevKey = skeyid_a_handle; 7251 ike1_prf.keyNumber = 2; 7252 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7253 derive_template, derive_template_count, 7254 &skeyid_e_handle); 7255 if (crv != CKR_OK) { 7256 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n", 7257 (unsigned int)crv); 7258 goto loser; 7259 } 7260 fputs("SKEYID = ", ikeresp); 7261 to_hex_str(buf, skeyid_secret, keyLen); 7262 fputs(buf, ikeresp); 7263 fputc('\n', ikeresp); 7264 7265 skeyid_d_template.ulValueLen = keyLen; 7266 crv = NSC_GetAttributeValue(session, skeyid_d_handle, 7267 &skeyid_d_template, 1); 7268 if (crv != CKR_OK) { 7269 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n", 7270 (unsigned int)crv); 7271 goto loser; 7272 } 7273 fputs("SKEYID_d = ", ikeresp); 7274 to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen); 7275 fputs(buf, ikeresp); 7276 fputc('\n', ikeresp); 7277 7278 skeyid_a_template.ulValueLen = keyLen; 7279 crv = NSC_GetAttributeValue(session, skeyid_a_handle, 7280 &skeyid_a_template, 1); 7281 if (crv != CKR_OK) { 7282 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n", 7283 (unsigned int)crv); 7284 goto loser; 7285 } 7286 fputs("SKEYID_a = ", ikeresp); 7287 to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen); 7288 fputs(buf, ikeresp); 7289 fputc('\n', ikeresp); 7290 7291 skeyid_e_template.ulValueLen = keyLen; 7292 crv = NSC_GetAttributeValue(session, skeyid_e_handle, 7293 &skeyid_e_template, 1); 7294 if (crv != CKR_OK) { 7295 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n", 7296 (unsigned int)crv); 7297 goto loser; 7298 } 7299 fputs("SKEYID_e = ", ikeresp); 7300 to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen); 7301 fputs(buf, ikeresp); 7302 fputc('\n', ikeresp); 7303 7304 crv = NSC_CloseSession(session); 7305 continue; 7306 } 7307 } 7308 loser: 7309 NSC_Finalize(NULL); 7310 if (gxy) 7311 free(gxy); 7312 if (Ni) 7313 free(Ni); 7314 if (Nr) 7315 free(Nr); 7316 if (ikereq) 7317 fclose(ikereq); 7318 } 7319 7320 void 7321 ikev1_psk(char *reqfn) 7322 { 7323 char buf[4096]; /* holds one line from the input REQUEST file. 7324 * needs to be large enough to hold the longest 7325 * line "g^xy = <2048 hex digits>\n". 7326 */ 7327 unsigned char *gxy = NULL; 7328 int gxy_len; 7329 unsigned char *Ni = NULL; 7330 int Ni_len; 7331 unsigned char *Nr = NULL; 7332 int Nr_len; 7333 unsigned char CKYi[8]; 7334 int CKYi_len; 7335 unsigned char CKYr[8]; 7336 int CKYr_len; 7337 unsigned char *psk = NULL; 7338 int psk_len; 7339 unsigned int i, j; 7340 FILE *ikereq = NULL; /* input stream from the REQUEST file */ 7341 FILE *ikeresp; /* output stream to the RESPONSE file */ 7342 7343 CK_SLOT_ID slotList[10]; 7344 CK_SLOT_ID slotID; 7345 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]); 7346 CK_ULONG count; 7347 static const CK_C_INITIALIZE_ARGS pk11args = { 7348 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, 7349 (void *)"flags=readOnly,noCertDB,noModDB", NULL 7350 }; 7351 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY; 7352 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET; 7353 static CK_BBOOL ck_true = CK_TRUE; 7354 static CK_ULONG keyLen = 1; 7355 CK_ATTRIBUTE gxy_template[] = { 7356 { CKA_VALUE, NULL, 0 }, /* must be first */ 7357 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7358 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7359 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7360 }; 7361 CK_ULONG gxy_template_count = 7362 sizeof(gxy_template) / sizeof(gxy_template[0]); 7363 CK_ATTRIBUTE psk_template[] = { 7364 { CKA_VALUE, NULL, 0 }, /* must be first */ 7365 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7366 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7367 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7368 }; 7369 CK_ULONG psk_template_count = 7370 sizeof(psk_template) / sizeof(psk_template[0]); 7371 CK_ATTRIBUTE derive_template[] = { 7372 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7373 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7374 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7375 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, /* must be last */ 7376 }; 7377 CK_ULONG derive_template_count = 7378 sizeof(derive_template) / sizeof(derive_template[0]); 7379 CK_ATTRIBUTE skeyid_template = { CKA_VALUE, NULL, 0 }; 7380 CK_ATTRIBUTE skeyid_d_template = { CKA_VALUE, NULL, 0 }; 7381 CK_ATTRIBUTE skeyid_a_template = { CKA_VALUE, NULL, 0 }; 7382 CK_ATTRIBUTE skeyid_e_template = { CKA_VALUE, NULL, 0 }; 7383 unsigned char skeyid_secret[HASH_LENGTH_MAX]; 7384 unsigned char skeyid_d_secret[HASH_LENGTH_MAX]; 7385 unsigned char skeyid_a_secret[HASH_LENGTH_MAX]; 7386 unsigned char skeyid_e_secret[HASH_LENGTH_MAX]; 7387 7388 CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 }; 7389 CK_MECHANISM ike1_mech = { CKM_IKE1_PRF_DERIVE, NULL, 0 }; 7390 CK_IKE_PRF_DERIVE_PARAMS ike_prf; 7391 CK_IKE1_PRF_DERIVE_PARAMS ike1_prf; 7392 CK_RV crv; 7393 7394 /* set up PKCS #11 parameters */ 7395 ike_prf.bDataAsKey = PR_FALSE; 7396 ike_prf.bRekey = PR_FALSE; 7397 ike_prf.hNewKey = CK_INVALID_HANDLE; 7398 CKYi_len = 8; 7399 CKYr_len = 8; 7400 ike1_prf.pCKYi = CKYi; 7401 ike1_prf.ulCKYiLen = CKYi_len; 7402 ike1_prf.pCKYr = CKYr; 7403 ike1_prf.ulCKYrLen = CKYr_len; 7404 ike_mech.pParameter = &ike_prf; 7405 ike_mech.ulParameterLen = sizeof(ike_prf); 7406 ike1_mech.pParameter = &ike1_prf; 7407 ike1_mech.ulParameterLen = sizeof(ike1_prf); 7408 skeyid_template.pValue = skeyid_secret; 7409 skeyid_template.ulValueLen = HASH_LENGTH_MAX; 7410 skeyid_d_template.pValue = skeyid_d_secret; 7411 skeyid_d_template.ulValueLen = HASH_LENGTH_MAX; 7412 skeyid_a_template.pValue = skeyid_a_secret; 7413 skeyid_a_template.ulValueLen = HASH_LENGTH_MAX; 7414 skeyid_e_template.pValue = skeyid_e_secret; 7415 skeyid_e_template.ulValueLen = HASH_LENGTH_MAX; 7416 7417 crv = NSC_Initialize((CK_VOID_PTR)&pk11args); 7418 if (crv != CKR_OK) { 7419 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); 7420 goto loser; 7421 } 7422 count = slotListCount; 7423 crv = NSC_GetSlotList(PR_TRUE, slotList, &count); 7424 if (crv != CKR_OK) { 7425 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv); 7426 goto loser; 7427 } 7428 if ((count > slotListCount) || count < 1) { 7429 fprintf(stderr, 7430 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n", 7431 (int)count, (int)slotListCount); 7432 goto loser; 7433 } 7434 slotID = slotList[0]; 7435 ikereq = fopen(reqfn, "r"); 7436 ikeresp = stdout; 7437 while (fgets(buf, sizeof buf, ikereq) != NULL) { 7438 /* a comment or blank line */ 7439 if (buf[0] == '#' || buf[0] == '\n') { 7440 fputs(buf, ikeresp); 7441 continue; 7442 } 7443 /* [.....] */ 7444 if (buf[0] == '[') { 7445 if (strncmp(buf, "[SHA-1]", 7) == 0) { 7446 ike_prf.prfMechanism = CKM_SHA_1_HMAC; 7447 ike1_prf.prfMechanism = CKM_SHA_1_HMAC; 7448 } 7449 if (strncmp(buf, "[SHA-224]", 9) == 0) { 7450 ike_prf.prfMechanism = CKM_SHA224_HMAC; 7451 ike1_prf.prfMechanism = CKM_SHA224_HMAC; 7452 } 7453 if (strncmp(buf, "[SHA-256]", 9) == 0) { 7454 ike_prf.prfMechanism = CKM_SHA256_HMAC; 7455 ike1_prf.prfMechanism = CKM_SHA256_HMAC; 7456 } 7457 if (strncmp(buf, "[SHA-384]", 9) == 0) { 7458 ike_prf.prfMechanism = CKM_SHA384_HMAC; 7459 ike1_prf.prfMechanism = CKM_SHA384_HMAC; 7460 } 7461 if (strncmp(buf, "[SHA-512]", 9) == 0) { 7462 ike_prf.prfMechanism = CKM_SHA512_HMAC; 7463 ike1_prf.prfMechanism = CKM_SHA512_HMAC; 7464 } 7465 if (strncmp(buf, "[AES-XCBC", 9) == 0) { 7466 ike_prf.prfMechanism = CKM_AES_XCBC_MAC; 7467 ike1_prf.prfMechanism = CKM_AES_XCBC_MAC; 7468 } 7469 if (strncmp(buf, "[g^xy", 5) == 0) { 7470 if (sscanf(buf, "[g^xy length = %d]", 7471 &gxy_len) != 1) { 7472 goto loser; 7473 } 7474 gxy_len = gxy_len / 8; 7475 if (gxy) 7476 free(gxy); 7477 gxy = malloc(gxy_len); 7478 gxy_template[0].pValue = gxy; 7479 gxy_template[0].ulValueLen = gxy_len; 7480 } 7481 if (strncmp(buf, "[pre-shared-key", 15) == 0) { 7482 if (sscanf(buf, "[pre-shared-key length = %d]", 7483 &psk_len) != 1) { 7484 goto loser; 7485 } 7486 psk_len = psk_len / 8; 7487 if (psk) 7488 free(psk); 7489 psk = malloc(psk_len); 7490 psk_template[0].pValue = psk; 7491 psk_template[0].ulValueLen = psk_len; 7492 } 7493 if (strncmp(buf, "[Ni", 3) == 0) { 7494 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) { 7495 goto loser; 7496 } 7497 Ni_len = Ni_len / 8; 7498 if (Ni) 7499 free(Ni); 7500 Ni = malloc(Ni_len); 7501 ike_prf.pNi = Ni; 7502 ike_prf.ulNiLen = Ni_len; 7503 } 7504 if (strncmp(buf, "[Nr", 3) == 0) { 7505 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) { 7506 goto loser; 7507 } 7508 Nr_len = Nr_len / 8; 7509 if (Nr) 7510 free(Nr); 7511 Nr = malloc(Nr_len); 7512 ike_prf.pNr = Nr; 7513 ike_prf.ulNrLen = Nr_len; 7514 } 7515 fputs(buf, ikeresp); 7516 continue; 7517 } 7518 /* "COUNT = x" begins a new data set */ 7519 if (strncmp(buf, "COUNT", 5) == 0) { 7520 /* zeroize the variables for the test with this data set */ 7521 memset(gxy, 0, gxy_len); 7522 memset(Ni, 0, Ni_len); 7523 memset(Nr, 0, Nr_len); 7524 memset(CKYi, 0, CKYi_len); 7525 memset(CKYr, 0, CKYr_len); 7526 fputs(buf, ikeresp); 7527 continue; 7528 } 7529 /* Ni = ... */ 7530 if (strncmp(buf, "Ni", 2) == 0) { 7531 i = 2; 7532 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7533 i++; 7534 } 7535 for (j = 0; j < Ni_len; i += 2, j++) { 7536 hex_to_byteval(&buf[i], &Ni[j]); 7537 } 7538 fputs(buf, ikeresp); 7539 continue; 7540 } 7541 /* Nr = ... */ 7542 if (strncmp(buf, "Nr", 2) == 0) { 7543 i = 2; 7544 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7545 i++; 7546 } 7547 for (j = 0; j < Nr_len; i += 2, j++) { 7548 hex_to_byteval(&buf[i], &Nr[j]); 7549 } 7550 fputs(buf, ikeresp); 7551 continue; 7552 } 7553 /* CKYi = ... */ 7554 if (strncmp(buf, "CKY_I", 5) == 0) { 7555 i = 5; 7556 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7557 i++; 7558 } 7559 for (j = 0; j < CKYi_len; i += 2, j++) { 7560 hex_to_byteval(&buf[i], &CKYi[j]); 7561 } 7562 fputs(buf, ikeresp); 7563 continue; 7564 } 7565 /* CKYr = ... */ 7566 if (strncmp(buf, "CKY_R", 5) == 0) { 7567 i = 5; 7568 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7569 i++; 7570 } 7571 for (j = 0; j < CKYr_len; i += 2, j++) { 7572 hex_to_byteval(&buf[i], &CKYr[j]); 7573 } 7574 fputs(buf, ikeresp); 7575 continue; 7576 } 7577 /* g^xy = ... */ 7578 if (strncmp(buf, "g^xy", 4) == 0) { 7579 i = 4; 7580 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7581 i++; 7582 } 7583 for (j = 0; j < gxy_len; i += 2, j++) { 7584 hex_to_byteval(&buf[i], &gxy[j]); 7585 } 7586 fputs(buf, ikeresp); 7587 continue; 7588 } 7589 /* pre-shared-key = ... */ 7590 if (strncmp(buf, "pre-shared-key", 14) == 0) { 7591 CK_SESSION_HANDLE session; 7592 CK_OBJECT_HANDLE gxy_handle; 7593 CK_OBJECT_HANDLE psk_handle; 7594 CK_OBJECT_HANDLE skeyid_handle; 7595 CK_OBJECT_HANDLE skeyid_d_handle; 7596 CK_OBJECT_HANDLE skeyid_a_handle; 7597 CK_OBJECT_HANDLE skeyid_e_handle; 7598 i = 14; 7599 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7600 i++; 7601 } 7602 for (j = 0; j < psk_len; i += 2, j++) { 7603 hex_to_byteval(&buf[i], &psk[j]); 7604 } 7605 fputs(buf, ikeresp); 7606 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session); 7607 if (crv != CKR_OK) { 7608 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", 7609 (unsigned int)crv); 7610 goto loser; 7611 } 7612 crv = NSC_CreateObject(session, psk_template, 7613 psk_template_count, &psk_handle); 7614 if (crv != CKR_OK) { 7615 fprintf(stderr, "NSC_CreateObject(psk) failed crv=0x%x\n", 7616 (unsigned int)crv); 7617 goto loser; 7618 } 7619 crv = NSC_CreateObject(session, gxy_template, 7620 gxy_template_count, &gxy_handle); 7621 if (crv != CKR_OK) { 7622 fprintf(stderr, "NSC_CreateObject(gxy) failed crv=0x%x\n", 7623 (unsigned int)crv); 7624 goto loser; 7625 } 7626 /* get the skeyid key */ 7627 crv = NSC_DeriveKey(session, &ike_mech, psk_handle, 7628 derive_template, derive_template_count - 1, 7629 &skeyid_handle); 7630 if (crv != CKR_OK) { 7631 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n", 7632 (unsigned int)crv); 7633 goto loser; 7634 } 7635 skeyid_template.ulValueLen = HASH_LENGTH_MAX; 7636 crv = NSC_GetAttributeValue(session, skeyid_handle, 7637 &skeyid_template, 1); 7638 if (crv != CKR_OK) { 7639 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n", 7640 (unsigned int)crv); 7641 goto loser; 7642 } 7643 /* use the length of the skeyid to set the target length of all the 7644 * other keys */ 7645 keyLen = skeyid_template.ulValueLen; 7646 ike1_prf.hKeygxy = gxy_handle; 7647 ike1_prf.bHasPrevKey = PR_FALSE; 7648 ike1_prf.keyNumber = 0; 7649 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7650 derive_template, derive_template_count, 7651 &skeyid_d_handle); 7652 if (crv != CKR_OK) { 7653 fprintf(stderr, "NSC_DeriveKey(skeyid_d) failed crv=0x%x\n", 7654 (unsigned int)crv); 7655 goto loser; 7656 } 7657 7658 ike1_prf.hKeygxy = gxy_handle; 7659 ike1_prf.bHasPrevKey = CK_TRUE; 7660 ike1_prf.hPrevKey = skeyid_d_handle; 7661 ike1_prf.keyNumber = 1; 7662 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7663 derive_template, derive_template_count, 7664 &skeyid_a_handle); 7665 if (crv != CKR_OK) { 7666 fprintf(stderr, "NSC_DeriveKey(skeyid_a) failed crv=0x%x\n", 7667 (unsigned int)crv); 7668 goto loser; 7669 } 7670 ike1_prf.hKeygxy = gxy_handle; 7671 ike1_prf.bHasPrevKey = CK_TRUE; 7672 ike1_prf.hPrevKey = skeyid_a_handle; 7673 ike1_prf.keyNumber = 2; 7674 crv = NSC_DeriveKey(session, &ike1_mech, skeyid_handle, 7675 derive_template, derive_template_count, 7676 &skeyid_e_handle); 7677 if (crv != CKR_OK) { 7678 fprintf(stderr, "NSC_DeriveKey(skeyid_e) failed crv=0x%x\n", 7679 (unsigned int)crv); 7680 goto loser; 7681 } 7682 fputs("SKEYID = ", ikeresp); 7683 to_hex_str(buf, skeyid_secret, keyLen); 7684 fputs(buf, ikeresp); 7685 fputc('\n', ikeresp); 7686 7687 skeyid_d_template.ulValueLen = keyLen; 7688 crv = NSC_GetAttributeValue(session, skeyid_d_handle, 7689 &skeyid_d_template, 1); 7690 if (crv != CKR_OK) { 7691 fprintf(stderr, "NSC_GetAttribute(skeyid_d) failed crv=0x%x\n", 7692 (unsigned int)crv); 7693 goto loser; 7694 } 7695 fputs("SKEYID_d = ", ikeresp); 7696 to_hex_str(buf, skeyid_d_secret, skeyid_d_template.ulValueLen); 7697 fputs(buf, ikeresp); 7698 fputc('\n', ikeresp); 7699 7700 skeyid_a_template.ulValueLen = keyLen; 7701 crv = NSC_GetAttributeValue(session, skeyid_a_handle, 7702 &skeyid_a_template, 1); 7703 if (crv != CKR_OK) { 7704 fprintf(stderr, "NSC_GetAttribute(skeyid_a) failed crv=0x%x\n", 7705 (unsigned int)crv); 7706 goto loser; 7707 } 7708 fputs("SKEYID_a = ", ikeresp); 7709 to_hex_str(buf, skeyid_a_secret, skeyid_a_template.ulValueLen); 7710 fputs(buf, ikeresp); 7711 fputc('\n', ikeresp); 7712 7713 skeyid_e_template.ulValueLen = keyLen; 7714 crv = NSC_GetAttributeValue(session, skeyid_e_handle, 7715 &skeyid_e_template, 1); 7716 if (crv != CKR_OK) { 7717 fprintf(stderr, "NSC_GetAttribute(skeyid_e) failed crv=0x%x\n", 7718 (unsigned int)crv); 7719 goto loser; 7720 } 7721 fputs("SKEYID_e = ", ikeresp); 7722 to_hex_str(buf, skeyid_e_secret, skeyid_e_template.ulValueLen); 7723 fputs(buf, ikeresp); 7724 fputc('\n', ikeresp); 7725 7726 crv = NSC_CloseSession(session); 7727 continue; 7728 } 7729 } 7730 loser: 7731 NSC_Finalize(NULL); 7732 if (psk) 7733 free(psk); 7734 if (gxy) 7735 free(gxy); 7736 if (Ni) 7737 free(Ni); 7738 if (Nr) 7739 free(Nr); 7740 if (ikereq) 7741 fclose(ikereq); 7742 } 7743 7744 void 7745 ikev2(char *reqfn) 7746 { 7747 char buf[4096]; /* holds one line from the input REQUEST file. 7748 * needs to be large enough to hold the longest 7749 * line "g^xy = <2048 hex digits>\n". 7750 */ 7751 unsigned char *gir = NULL; 7752 unsigned char *gir_new = NULL; 7753 int gir_len; 7754 unsigned char *Ni = NULL; 7755 int Ni_len; 7756 unsigned char *Nr = NULL; 7757 int Nr_len; 7758 unsigned char *SPIi = NULL; 7759 int SPIi_len = 8; 7760 unsigned char *SPIr = NULL; 7761 int SPIr_len = 8; 7762 unsigned char *DKM = NULL; 7763 int DKM_len; 7764 unsigned char *DKM_child = NULL; 7765 int DKM_child_len; 7766 unsigned char *seed_data = NULL; 7767 int seed_data_len = 0; 7768 unsigned int i, j; 7769 FILE *ikereq = NULL; /* input stream from the REQUEST file */ 7770 FILE *ikeresp; /* output stream to the RESPONSE file */ 7771 7772 CK_SLOT_ID slotList[10]; 7773 CK_SLOT_ID slotID; 7774 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]); 7775 CK_ULONG count; 7776 static const CK_C_INITIALIZE_ARGS pk11args = { 7777 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, 7778 (void *)"flags=readOnly,noCertDB,noModDB", NULL 7779 }; 7780 static CK_OBJECT_CLASS ck_secret = CKO_SECRET_KEY; 7781 static CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET; 7782 static CK_BBOOL ck_true = CK_TRUE; 7783 static CK_ULONG keyLen = 1; 7784 CK_ATTRIBUTE gir_template[] = { 7785 { CKA_VALUE, NULL, 0 }, 7786 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7787 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7788 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7789 }; 7790 CK_ULONG gir_template_count = 7791 sizeof(gir_template) / sizeof(gir_template[0]); 7792 CK_ATTRIBUTE gir_new_template[] = { 7793 { CKA_VALUE, NULL, 0 }, 7794 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7795 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7796 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7797 }; 7798 CK_ULONG gir_new_template_count = 7799 sizeof(gir_new_template) / sizeof(gir_new_template[0]); 7800 CK_ATTRIBUTE derive_template[] = { 7801 { CKA_CLASS, &ck_secret, sizeof(ck_secret) }, 7802 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 7803 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 7804 { CKA_VALUE_LEN, &keyLen, sizeof(keyLen) }, 7805 }; 7806 CK_ULONG derive_template_count = 7807 sizeof(derive_template) / sizeof(derive_template[0]); 7808 CK_ATTRIBUTE skeyseed_template = { CKA_VALUE, NULL, 0 }; 7809 CK_ATTRIBUTE dkm_template = { CKA_VALUE, NULL, 0 }; 7810 CK_ATTRIBUTE dkm_child_template = { CKA_VALUE, NULL, 0 }; 7811 unsigned char skeyseed_secret[HASH_LENGTH_MAX]; 7812 7813 CK_MECHANISM ike_mech = { CKM_IKE_PRF_DERIVE, NULL, 0 }; 7814 CK_MECHANISM ike2_mech = { CKM_IKE2_PRF_PLUS_DERIVE, NULL, 0 }; 7815 CK_MECHANISM subset_mech = { CKM_EXTRACT_KEY_FROM_KEY, NULL, 0 }; 7816 CK_IKE_PRF_DERIVE_PARAMS ike_prf; 7817 CK_IKE2_PRF_PLUS_DERIVE_PARAMS ike2_prf; 7818 CK_EXTRACT_PARAMS subset_params; 7819 CK_RV crv; 7820 7821 /* set up PKCS #11 parameters */ 7822 ike_mech.pParameter = &ike_prf; 7823 ike_mech.ulParameterLen = sizeof(ike_prf); 7824 ike2_mech.pParameter = &ike2_prf; 7825 ike2_mech.ulParameterLen = sizeof(ike2_prf); 7826 subset_mech.pParameter = &subset_params; 7827 subset_mech.ulParameterLen = sizeof(subset_params); 7828 subset_params = 0; 7829 skeyseed_template.pValue = skeyseed_secret; 7830 skeyseed_template.ulValueLen = HASH_LENGTH_MAX; 7831 7832 crv = NSC_Initialize((CK_VOID_PTR)&pk11args); 7833 if (crv != CKR_OK) { 7834 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); 7835 goto loser; 7836 } 7837 count = slotListCount; 7838 crv = NSC_GetSlotList(PR_TRUE, slotList, &count); 7839 if (crv != CKR_OK) { 7840 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv); 7841 goto loser; 7842 } 7843 if ((count > slotListCount) || count < 1) { 7844 fprintf(stderr, 7845 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n", 7846 (int)count, (int)slotListCount); 7847 goto loser; 7848 } 7849 slotID = slotList[0]; 7850 ikereq = fopen(reqfn, "r"); 7851 ikeresp = stdout; 7852 while (fgets(buf, sizeof buf, ikereq) != NULL) { 7853 /* a comment or blank line */ 7854 if (buf[0] == '#' || buf[0] == '\n') { 7855 fputs(buf, ikeresp); 7856 continue; 7857 } 7858 /* [.....] */ 7859 if (buf[0] == '[') { 7860 if (strncmp(buf, "[SHA-1]", 7) == 0) { 7861 ike_prf.prfMechanism = CKM_SHA_1_HMAC; 7862 ike2_prf.prfMechanism = CKM_SHA_1_HMAC; 7863 } 7864 if (strncmp(buf, "[SHA-224]", 9) == 0) { 7865 ike_prf.prfMechanism = CKM_SHA224_HMAC; 7866 ike2_prf.prfMechanism = CKM_SHA224_HMAC; 7867 } 7868 if (strncmp(buf, "[SHA-256]", 9) == 0) { 7869 ike_prf.prfMechanism = CKM_SHA256_HMAC; 7870 ike2_prf.prfMechanism = CKM_SHA256_HMAC; 7871 } 7872 if (strncmp(buf, "[SHA-384]", 9) == 0) { 7873 ike_prf.prfMechanism = CKM_SHA384_HMAC; 7874 ike2_prf.prfMechanism = CKM_SHA384_HMAC; 7875 } 7876 if (strncmp(buf, "[SHA-512]", 9) == 0) { 7877 ike_prf.prfMechanism = CKM_SHA512_HMAC; 7878 ike2_prf.prfMechanism = CKM_SHA512_HMAC; 7879 } 7880 if (strncmp(buf, "[AES-XCBC", 9) == 0) { 7881 ike_prf.prfMechanism = CKM_AES_XCBC_MAC; 7882 ike2_prf.prfMechanism = CKM_AES_XCBC_MAC; 7883 } 7884 if (strncmp(buf, "[g^ir", 5) == 0) { 7885 if (sscanf(buf, "[g^ir length = %d]", 7886 &gir_len) != 1) { 7887 goto loser; 7888 } 7889 gir_len = gir_len / 8; 7890 if (gir) 7891 free(gir); 7892 if (gir_new) 7893 free(gir_new); 7894 gir = malloc(gir_len); 7895 gir_new = malloc(gir_len); 7896 gir_template[0].pValue = gir; 7897 gir_template[0].ulValueLen = gir_len; 7898 gir_new_template[0].pValue = gir_new; 7899 gir_new_template[0].ulValueLen = gir_len; 7900 } 7901 if (strncmp(buf, "[Ni", 3) == 0) { 7902 if (sscanf(buf, "[Ni length = %d]", &Ni_len) != 1) { 7903 goto loser; 7904 } 7905 Ni_len = Ni_len / 8; 7906 } 7907 if (strncmp(buf, "[Nr", 3) == 0) { 7908 if (sscanf(buf, "[Nr length = %d]", &Nr_len) != 1) { 7909 goto loser; 7910 } 7911 Nr_len = Nr_len / 8; 7912 } 7913 if (strncmp(buf, "[DKM", 4) == 0) { 7914 if (sscanf(buf, "[DKM length = %d]", 7915 &DKM_len) != 1) { 7916 goto loser; 7917 } 7918 DKM_len = DKM_len / 8; 7919 if (DKM) 7920 free(DKM); 7921 DKM = malloc(DKM_len); 7922 dkm_template.pValue = DKM; 7923 dkm_template.ulValueLen = DKM_len; 7924 } 7925 if (strncmp(buf, "[Child SA DKM", 13) == 0) { 7926 if (sscanf(buf, "[Child SA DKM length = %d]", 7927 &DKM_child_len) != 1) { 7928 goto loser; 7929 } 7930 DKM_child_len = DKM_child_len / 8; 7931 if (DKM_child) 7932 free(DKM_child); 7933 DKM_child = malloc(DKM_child_len); 7934 dkm_child_template.pValue = DKM_child; 7935 dkm_child_template.ulValueLen = DKM_child_len; 7936 } 7937 fputs(buf, ikeresp); 7938 continue; 7939 } 7940 /* "COUNT = x" begins a new data set */ 7941 if (strncmp(buf, "COUNT", 5) == 0) { 7942 /* zeroize the variables for the test with this data set */ 7943 int new_seed_len = Ni_len + Nr_len + SPIi_len + SPIr_len; 7944 if (seed_data_len != new_seed_len) { 7945 if (seed_data) 7946 free(seed_data); 7947 seed_data_len = new_seed_len; 7948 seed_data = malloc(seed_data_len); 7949 Ni = seed_data; 7950 Nr = &seed_data[Ni_len]; 7951 SPIi = &seed_data[Ni_len + Nr_len]; 7952 SPIr = &seed_data[new_seed_len - SPIr_len]; 7953 ike_prf.pNi = Ni; 7954 ike_prf.ulNiLen = Ni_len; 7955 ike_prf.pNr = Nr; 7956 ike_prf.ulNrLen = Nr_len; 7957 ike2_prf.pSeedData = seed_data; 7958 } 7959 memset(gir, 0, gir_len); 7960 memset(gir_new, 0, gir_len); 7961 memset(seed_data, 0, seed_data_len); 7962 fputs(buf, ikeresp); 7963 continue; 7964 } 7965 /* Ni = ... */ 7966 if (strncmp(buf, "Ni", 2) == 0) { 7967 i = 2; 7968 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7969 i++; 7970 } 7971 for (j = 0; j < Ni_len; i += 2, j++) { 7972 hex_to_byteval(&buf[i], &Ni[j]); 7973 } 7974 fputs(buf, ikeresp); 7975 continue; 7976 } 7977 /* Nr = ... */ 7978 if (strncmp(buf, "Nr", 2) == 0) { 7979 i = 2; 7980 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7981 i++; 7982 } 7983 for (j = 0; j < Nr_len; i += 2, j++) { 7984 hex_to_byteval(&buf[i], &Nr[j]); 7985 } 7986 fputs(buf, ikeresp); 7987 continue; 7988 } 7989 /* g^ir (new) = ... */ 7990 if (strncmp(buf, "g^ir (new)", 10) == 0) { 7991 i = 10; 7992 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 7993 i++; 7994 } 7995 for (j = 0; j < gir_len; i += 2, j++) { 7996 hex_to_byteval(&buf[i], &gir_new[j]); 7997 } 7998 fputs(buf, ikeresp); 7999 continue; 8000 } 8001 /* g^ir = ... */ 8002 if (strncmp(buf, "g^ir", 4) == 0) { 8003 i = 4; 8004 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 8005 i++; 8006 } 8007 for (j = 0; j < gir_len; i += 2, j++) { 8008 hex_to_byteval(&buf[i], &gir[j]); 8009 } 8010 fputs(buf, ikeresp); 8011 continue; 8012 } 8013 /* SPIi = ... */ 8014 if (strncmp(buf, "SPIi", 4) == 0) { 8015 i = 4; 8016 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 8017 i++; 8018 } 8019 for (j = 0; j < SPIi_len; i += 2, j++) { 8020 hex_to_byteval(&buf[i], &SPIi[j]); 8021 } 8022 fputs(buf, ikeresp); 8023 continue; 8024 } 8025 /* SPIr = ... */ 8026 if (strncmp(buf, "SPIr", 4) == 0) { 8027 CK_SESSION_HANDLE session; 8028 CK_OBJECT_HANDLE gir_handle; 8029 CK_OBJECT_HANDLE gir_new_handle; 8030 CK_OBJECT_HANDLE skeyseed_handle; 8031 CK_OBJECT_HANDLE sk_d_handle; 8032 CK_OBJECT_HANDLE skeyseed_new_handle; 8033 CK_OBJECT_HANDLE dkm_handle; 8034 CK_OBJECT_HANDLE dkm_child_handle; 8035 i = 4; 8036 while (isspace((unsigned char)buf[i]) || buf[i] == '=') { 8037 i++; 8038 } 8039 for (j = 0; j < SPIr_len; i += 2, j++) { 8040 hex_to_byteval(&buf[i], &SPIr[j]); 8041 } 8042 fputs(buf, ikeresp); 8043 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session); 8044 if (crv != CKR_OK) { 8045 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", 8046 (unsigned int)crv); 8047 goto loser; 8048 } 8049 crv = NSC_CreateObject(session, gir_template, 8050 gir_template_count, &gir_handle); 8051 if (crv != CKR_OK) { 8052 fprintf(stderr, "NSC_CreateObject (g^ir) failed crv=0x%x\n", 8053 (unsigned int)crv); 8054 goto loser; 8055 } 8056 crv = NSC_CreateObject(session, gir_new_template, 8057 gir_new_template_count, &gir_new_handle); 8058 if (crv != CKR_OK) { 8059 fprintf(stderr, "NSC_CreateObject (g^ir new) failed crv=0x%x\n", 8060 (unsigned int)crv); 8061 goto loser; 8062 } 8063 /* get the SKEYSEED key */ 8064 ike_prf.bDataAsKey = CK_TRUE; 8065 ike_prf.bRekey = CK_FALSE; 8066 ike_prf.hNewKey = CK_INVALID_HANDLE; 8067 crv = NSC_DeriveKey(session, &ike_mech, gir_handle, 8068 derive_template, derive_template_count - 1, 8069 &skeyseed_handle); 8070 if (crv != CKR_OK) { 8071 fprintf(stderr, "NSC_DeriveKey(skeyid) failed crv=0x%x\n", 8072 (unsigned int)crv); 8073 goto loser; 8074 } 8075 skeyseed_template.ulValueLen = HASH_LENGTH_MAX; 8076 crv = NSC_GetAttributeValue(session, skeyseed_handle, 8077 &skeyseed_template, 1); 8078 if (crv != CKR_OK) { 8079 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n", 8080 (unsigned int)crv); 8081 goto loser; 8082 } 8083 fputs("SKEYSEED = ", ikeresp); 8084 to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen); 8085 fputs(buf, ikeresp); 8086 fputc('\n', ikeresp); 8087 8088 /* get DKM */ 8089 keyLen = DKM_len; 8090 ike2_prf.bHasSeedKey = CK_FALSE; 8091 ike2_prf.hSeedKey = CK_INVALID_HANDLE; 8092 ike2_prf.ulSeedDataLen = seed_data_len; 8093 crv = NSC_DeriveKey(session, &ike2_mech, skeyseed_handle, 8094 derive_template, derive_template_count, 8095 &dkm_handle); 8096 if (crv != CKR_OK) { 8097 fprintf(stderr, "NSC_DeriveKey(DKM) failed crv=0x%x\n", 8098 (unsigned int)crv); 8099 goto loser; 8100 } 8101 crv = NSC_GetAttributeValue(session, dkm_handle, 8102 &dkm_template, 1); 8103 if (crv != CKR_OK) { 8104 fprintf(stderr, "NSC_GetAttribute(DKM) failed crv=0x%x\n", 8105 (unsigned int)crv); 8106 goto loser; 8107 } 8108 fputs("DKM = ", ikeresp); 8109 to_hex_str(buf, DKM, DKM_len); 8110 fputs(buf, ikeresp); 8111 fputc('\n', ikeresp); 8112 8113 /* get the sk_d from the DKM */ 8114 keyLen = skeyseed_template.ulValueLen; 8115 crv = NSC_DeriveKey(session, &subset_mech, dkm_handle, 8116 derive_template, derive_template_count, 8117 &sk_d_handle); 8118 if (crv != CKR_OK) { 8119 fprintf(stderr, "NSC_DeriveKey(sk_d) failed crv=0x%x\n", 8120 (unsigned int)crv); 8121 goto loser; 8122 } 8123 8124 /* get DKM child */ 8125 keyLen = DKM_child_len; 8126 ike2_prf.bHasSeedKey = CK_FALSE; 8127 ike2_prf.hSeedKey = CK_INVALID_HANDLE; 8128 ike2_prf.ulSeedDataLen = Ni_len + Nr_len; 8129 crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle, 8130 derive_template, derive_template_count, 8131 &dkm_child_handle); 8132 if (crv != CKR_OK) { 8133 fprintf(stderr, "NSC_DeriveKey(DKM Child SA) failed crv=0x%x\n", 8134 (unsigned int)crv); 8135 goto loser; 8136 } 8137 crv = NSC_GetAttributeValue(session, dkm_child_handle, 8138 &dkm_child_template, 1); 8139 if (crv != CKR_OK) { 8140 fprintf(stderr, "NSC_GetAttribute(DKM Child SA) failed crv=0x%x\n", 8141 (unsigned int)crv); 8142 goto loser; 8143 } 8144 fputs("DKM(Child SA) = ", ikeresp); 8145 to_hex_str(buf, DKM_child, DKM_child_len); 8146 fputs(buf, ikeresp); 8147 fputc('\n', ikeresp); 8148 8149 /* get DKM child D-H*/ 8150 keyLen = DKM_child_len; 8151 ike2_prf.bHasSeedKey = CK_TRUE; 8152 ike2_prf.hSeedKey = gir_new_handle; 8153 ike2_prf.ulSeedDataLen = Ni_len + Nr_len; 8154 crv = NSC_DeriveKey(session, &ike2_mech, sk_d_handle, 8155 derive_template, derive_template_count, 8156 &dkm_child_handle); 8157 if (crv != CKR_OK) { 8158 fprintf(stderr, "NSC_DeriveKey(DKM Child SA D-H) failed crv=0x%x\n", 8159 (unsigned int)crv); 8160 goto loser; 8161 } 8162 crv = NSC_GetAttributeValue(session, dkm_child_handle, 8163 &dkm_child_template, 1); 8164 if (crv != CKR_OK) { 8165 fprintf(stderr, "NSC_GetAttribute(DKM Child SA D-H) failed crv=0x%x\n", 8166 (unsigned int)crv); 8167 goto loser; 8168 } 8169 fputs("DKM(Child SA D-H) = ", ikeresp); 8170 to_hex_str(buf, DKM_child, DKM_child_len); 8171 fputs(buf, ikeresp); 8172 fputc('\n', ikeresp); 8173 8174 /* get SKEYSEED(rekey) */ 8175 ike_prf.bDataAsKey = CK_FALSE; 8176 ike_prf.bRekey = CK_TRUE; 8177 ike_prf.hNewKey = gir_new_handle; 8178 crv = NSC_DeriveKey(session, &ike_mech, sk_d_handle, 8179 derive_template, derive_template_count - 1, 8180 &skeyseed_new_handle); 8181 if (crv != CKR_OK) { 8182 fprintf(stderr, "NSC_DeriveKey(skeyid rekey) failed crv=0x%x\n", 8183 (unsigned int)crv); 8184 goto loser; 8185 } 8186 skeyseed_template.ulValueLen = HASH_LENGTH_MAX; 8187 crv = NSC_GetAttributeValue(session, skeyseed_new_handle, 8188 &skeyseed_template, 1); 8189 if (crv != CKR_OK) { 8190 fprintf(stderr, "NSC_GetAttribute(skeyid) failed crv=0x%x\n", 8191 (unsigned int)crv); 8192 goto loser; 8193 } 8194 fputs("SKEYSEED(rekey) = ", ikeresp); 8195 to_hex_str(buf, skeyseed_secret, skeyseed_template.ulValueLen); 8196 fputs(buf, ikeresp); 8197 fputc('\n', ikeresp); 8198 8199 crv = NSC_CloseSession(session); 8200 continue; 8201 } 8202 } 8203 loser: 8204 NSC_Finalize(NULL); 8205 if (gir) 8206 free(gir); 8207 if (gir_new) 8208 free(gir_new); 8209 if (seed_data) 8210 free(seed_data); 8211 if (DKM) 8212 free(DKM); 8213 if (DKM_child) 8214 free(DKM_child); 8215 if (ikereq) 8216 fclose(ikereq); 8217 } 8218 8219 void 8220 kbkdf(char *path) 8221 { 8222 /* == Parser data == */ 8223 char buf[610]; /* holds one line from the input REQUEST file. Needs to 8224 * be large enough to hold the longest line: 8225 * "KO = <600 hex digits>\n". */ 8226 CK_ULONG L; 8227 unsigned char KI[64]; 8228 unsigned int KI_len = 64; 8229 unsigned char KO[300]; 8230 unsigned int KO_len = 300; 8231 /* This is used only with feedback mode. */ 8232 unsigned char IV[64]; 8233 unsigned int IV_len = 64; 8234 /* These are only used in counter mode with counter location as 8235 * MIDDLE_FIXED. */ 8236 unsigned char BeforeFixedInputData[50]; 8237 unsigned int BeforeFixedInputData_len = 50; 8238 unsigned char AfterFixedInputData[10]; 8239 unsigned int AfterFixedInputData_len = 10; 8240 /* These are used with every KDF type. */ 8241 unsigned char FixedInputData[60]; 8242 unsigned int FixedInputData_len = 60; 8243 8244 /* Counter locations: 8245 * 8246 * 0: not used 8247 * 1: beginning 8248 * 2: middle 8249 * 3: end */ 8250 int ctr_location = 0; 8251 CK_ULONG counter_bitlen = 0; 8252 8253 size_t buf_offset; 8254 size_t offset; 8255 8256 FILE *kbkdf_req = NULL; 8257 FILE *kbkdf_resp = NULL; 8258 8259 /* == PKCS#11 data == */ 8260 CK_RV crv; 8261 8262 CK_SLOT_ID slotList[10]; 8263 CK_SLOT_ID slotID; 8264 CK_ULONG slotListCount = sizeof(slotList) / sizeof(slotList[0]); 8265 CK_ULONG slotCount = 0; 8266 8267 CK_MECHANISM kdf = { 0 }; 8268 8269 CK_MECHANISM_TYPE prf_mech = 0; 8270 CK_BBOOL ck_true = CK_TRUE; 8271 8272 /* We never need more than 3 data parameters. */ 8273 CK_PRF_DATA_PARAM dataParams[3]; 8274 CK_ULONG dataParams_len = 3; 8275 8276 CK_SP800_108_COUNTER_FORMAT iterator = { CK_FALSE, 0 }; 8277 8278 CK_SP800_108_KDF_PARAMS kdfParams = { 0 }; 8279 CK_SP800_108_FEEDBACK_KDF_PARAMS feedbackParams = { 0 }; 8280 8281 CK_OBJECT_CLASS ck_secret_key = CKO_SECRET_KEY; 8282 CK_KEY_TYPE ck_generic = CKK_GENERIC_SECRET; 8283 8284 CK_ATTRIBUTE prf_template[] = { 8285 { CKA_VALUE, &KI, sizeof(KI) }, 8286 { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) }, 8287 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 8288 { CKA_DERIVE, &ck_true, sizeof(ck_true) } 8289 }; 8290 CK_ULONG prf_template_count = sizeof(prf_template) / sizeof(prf_template[0]); 8291 8292 CK_ATTRIBUTE derive_template[] = { 8293 { CKA_CLASS, &ck_secret_key, sizeof(ck_secret_key) }, 8294 { CKA_KEY_TYPE, &ck_generic, sizeof(ck_generic) }, 8295 { CKA_DERIVE, &ck_true, sizeof(ck_true) }, 8296 { CKA_VALUE_LEN, &L, sizeof(L) } 8297 }; 8298 CK_ULONG derive_template_count = sizeof(derive_template) / sizeof(derive_template[0]); 8299 8300 CK_ATTRIBUTE output_key = { CKA_VALUE, KO, KO_len }; 8301 8302 const CK_C_INITIALIZE_ARGS pk11args = { 8303 NULL, NULL, NULL, NULL, CKF_LIBRARY_CANT_CREATE_OS_THREADS, 8304 (void *)"flags=readOnly,noCertDB,noModDB", NULL 8305 }; 8306 8307 /* == Start up PKCS#11 == */ 8308 crv = NSC_Initialize((CK_VOID_PTR)&pk11args); 8309 if (crv != CKR_OK) { 8310 fprintf(stderr, "NSC_Initialize failed crv=0x%x\n", (unsigned int)crv); 8311 goto done; 8312 } 8313 8314 slotCount = slotListCount; 8315 crv = NSC_GetSlotList(PR_TRUE, slotList, &slotCount); 8316 if (crv != CKR_OK) { 8317 fprintf(stderr, "NSC_GetSlotList failed crv=0x%x\n", (unsigned int)crv); 8318 goto done; 8319 } 8320 if ((slotCount > slotListCount) || slotCount < 1) { 8321 fprintf(stderr, 8322 "NSC_GetSlotList returned too many or too few slots: %d slots max=%d min=1\n", 8323 (int)slotCount, (int)slotListCount); 8324 goto done; 8325 } 8326 slotID = slotList[0]; 8327 8328 /* == Start parsing the file == */ 8329 kbkdf_req = fopen(path, "r"); 8330 kbkdf_resp = stdout; 8331 8332 while (fgets(buf, sizeof buf, kbkdf_req) != NULL) { 8333 /* If we have a comment, check if it tells us the type of KDF to use. 8334 * This differs per-file, so we have to parse it. */ 8335 if (buf[0] == '#' || buf[0] == '\n' || buf[0] == '\r') { 8336 if (strncmp(buf, "# KDF Mode Supported: Counter Mode", 34) == 0) { 8337 kdf.mechanism = CKM_SP800_108_COUNTER_KDF; 8338 } 8339 if (strncmp(buf, "# KDF Mode Supported: Feedback Mode", 35) == 0) { 8340 kdf.mechanism = CKM_SP800_108_FEEDBACK_KDF; 8341 } 8342 if (strncmp(buf, "# KDF Mode Supported: DblPipeline Mode", 38) == 0) { 8343 kdf.mechanism = CKM_SP800_108_DOUBLE_PIPELINE_KDF; 8344 } 8345 8346 fputs(buf, kbkdf_resp); 8347 continue; 8348 } 8349 8350 /* [....] - context directive */ 8351 if (buf[0] == '[') { 8352 /* PRF begins each new section. */ 8353 if (strncmp(buf, "[PRF=CMAC_AES128]", 17) == 0) { 8354 prf_mech = CKM_AES_CMAC; 8355 KI_len = 16; 8356 } else if (strncmp(buf, "[PRF=CMAC_AES192]", 17) == 0) { 8357 prf_mech = CKM_AES_CMAC; 8358 KI_len = 24; 8359 } else if (strncmp(buf, "[PRF=CMAC_AES256]", 17) == 0) { 8360 prf_mech = CKM_AES_CMAC; 8361 KI_len = 32; 8362 } else if (strncmp(buf, "[PRF=HMAC_SHA1]", 15) == 0) { 8363 prf_mech = CKM_SHA_1_HMAC; 8364 KI_len = 20; 8365 } else if (strncmp(buf, "[PRF=HMAC_SHA224]", 17) == 0) { 8366 prf_mech = CKM_SHA224_HMAC; 8367 KI_len = 28; 8368 } else if (strncmp(buf, "[PRF=HMAC_SHA256]", 17) == 0) { 8369 prf_mech = CKM_SHA256_HMAC; 8370 KI_len = 32; 8371 } else if (strncmp(buf, "[PRF=HMAC_SHA384]", 17) == 0) { 8372 prf_mech = CKM_SHA384_HMAC; 8373 KI_len = 48; 8374 } else if (strncmp(buf, "[PRF=HMAC_SHA512]", 17) == 0) { 8375 prf_mech = CKM_SHA512_HMAC; 8376 KI_len = 64; 8377 } else if (strncmp(buf, "[PRF=", 5) == 0) { 8378 fprintf(stderr, "Invalid or unsupported PRF mechanism: %s\n", buf); 8379 goto done; 8380 } 8381 8382 /* Then comes counter, if present. */ 8383 if (strncmp(buf, "[CTRLOCATION=BEFORE_FIXED]", 26) == 0 || 8384 strncmp(buf, "[CTRLOCATION=BEFORE_ITER]", 24) == 0) { 8385 ctr_location = 1; 8386 } 8387 if (strncmp(buf, "[CTRLOCATION=MIDDLE_FIXED]", 26) == 0 || 8388 strncmp(buf, "[CTRLOCATION=AFTER_ITER]", 24) == 0) { 8389 ctr_location = 2; 8390 } 8391 if (strncmp(buf, "[CTRLOCATION=AFTER_FIXED]", 25) == 0) { 8392 ctr_location = 3; 8393 } 8394 8395 /* If counter is present, then we need to know its size. */ 8396 if (strncmp(buf, "[RLEN=", 6) == 0) { 8397 if (sscanf(buf, "[RLEN=%lu_BITS]", &counter_bitlen) != 1) { 8398 goto done; 8399 } 8400 } 8401 8402 fputs(buf, kbkdf_resp); 8403 continue; 8404 } 8405 8406 /* Each test contains a counter, an output length L, an input key KI, 8407 * maybe an initialization vector IV, one of a couple of fixed data 8408 * buffers, and finally the output key KO. */ 8409 8410 /* First comes COUNT. */ 8411 if (strncmp(buf, "COUNT=", 6) == 0) { 8412 /* Clear all out data fields on each test. */ 8413 memset(KI, 0, sizeof KI); 8414 memset(KO, 0, sizeof KO); 8415 memset(IV, 0, sizeof IV); 8416 memset(BeforeFixedInputData, 0, sizeof BeforeFixedInputData); 8417 memset(AfterFixedInputData, 0, sizeof AfterFixedInputData); 8418 memset(FixedInputData, 0, sizeof FixedInputData); 8419 8420 /* Then reset lengths except KI: it was determined by PRF 8421 * selection above. */ 8422 KO_len = 0; 8423 IV_len = 0; 8424 BeforeFixedInputData_len = 0; 8425 AfterFixedInputData_len = 0; 8426 FixedInputData_len = 0; 8427 8428 fputs(buf, kbkdf_resp); 8429 continue; 8430 } 8431 8432 /* Then comes L. */ 8433 if (strncmp(buf, "L = ", 4) == 0) { 8434 if (sscanf(buf, "L = %lu", &L) != 1) { 8435 goto done; 8436 } 8437 8438 if ((L % 8) != 0) { 8439 fprintf(stderr, "Assumption that L was length in bits incorrect: %lu - %s", L, buf); 8440 fprintf(stderr, "Note that NSS only supports byte-aligned outputs and not bit-aligned outputs.\n"); 8441 goto done; 8442 } 8443 8444 L = L / 8; 8445 8446 fputs(buf, kbkdf_resp); 8447 continue; 8448 } 8449 8450 /* Then comes KI. */ 8451 if (strncmp(buf, "KI = ", 5) == 0) { 8452 buf_offset = 5; 8453 8454 for (offset = 0; offset < KI_len; offset++, buf_offset += 2) { 8455 hex_to_byteval(buf + buf_offset, KI + offset); 8456 } 8457 8458 fputs(buf, kbkdf_resp); 8459 continue; 8460 } 8461 8462 /* Then comes IVlen and IV, if present. */ 8463 if (strncmp(buf, "IVlen = ", 8) == 0) { 8464 if (sscanf(buf, "IVlen = %u", &IV_len) != 1) { 8465 goto done; 8466 } 8467 8468 if ((IV_len % 8) != 0) { 8469 fprintf(stderr, "Assumption that IV_len was length in bits incorrect: %u - %s. ", IV_len, buf); 8470 fprintf(stderr, "Note that NSS only supports byte-aligned inputs and not bit-aligned inputs.\n"); 8471 goto done; 8472 } 8473 8474 /* Need the IV length in bytes, not bits. */ 8475 IV_len = IV_len / 8; 8476 8477 fputs(buf, kbkdf_resp); 8478 continue; 8479 } 8480 if (strncmp(buf, "IV = ", 5) == 0) { 8481 buf_offset = 5; 8482 8483 for (offset = 0; offset < IV_len; offset++, buf_offset += 2) { 8484 hex_to_byteval(buf + buf_offset, IV + offset); 8485 } 8486 8487 fputs(buf, kbkdf_resp); 8488 continue; 8489 } 8490 8491 /* We might have DataBeforeCtr and DataAfterCtr if present. */ 8492 if (strncmp(buf, "DataBeforeCtrLen = ", 19) == 0) { 8493 if (sscanf(buf, "DataBeforeCtrLen = %u", &BeforeFixedInputData_len) != 1) { 8494 goto done; 8495 } 8496 8497 fputs(buf, kbkdf_resp); 8498 continue; 8499 } 8500 if (strncmp(buf, "DataBeforeCtrData = ", 20) == 0) { 8501 buf_offset = 20; 8502 8503 for (offset = 0; offset < BeforeFixedInputData_len; offset++, buf_offset += 2) { 8504 hex_to_byteval(buf + buf_offset, BeforeFixedInputData + offset); 8505 } 8506 8507 fputs(buf, kbkdf_resp); 8508 continue; 8509 } 8510 if (strncmp(buf, "DataAfterCtrLen = ", 18) == 0) { 8511 if (sscanf(buf, "DataAfterCtrLen = %u", &AfterFixedInputData_len) != 1) { 8512 goto done; 8513 } 8514 8515 fputs(buf, kbkdf_resp); 8516 continue; 8517 } 8518 if (strncmp(buf, "DataAfterCtrData = ", 19) == 0) { 8519 buf_offset = 19; 8520 8521 for (offset = 0; offset < AfterFixedInputData_len; offset++, buf_offset += 2) { 8522 hex_to_byteval(buf + buf_offset, AfterFixedInputData + offset); 8523 } 8524 8525 fputs(buf, kbkdf_resp); 8526 continue; 8527 } 8528 8529 /* Otherwise, we might have FixedInputData, if present. */ 8530 if (strncmp(buf, "FixedInputDataByteLen = ", 24) == 0) { 8531 if (sscanf(buf, "FixedInputDataByteLen = %u", &FixedInputData_len) != 1) { 8532 goto done; 8533 } 8534 8535 fputs(buf, kbkdf_resp); 8536 continue; 8537 } 8538 if (strncmp(buf, "FixedInputData = ", 17) == 0) { 8539 buf_offset = 17; 8540 8541 for (offset = 0; offset < FixedInputData_len; offset++, buf_offset += 2) { 8542 hex_to_byteval(buf + buf_offset, FixedInputData + offset); 8543 } 8544 8545 fputs(buf, kbkdf_resp); 8546 continue; 8547 } 8548 8549 /* Finally, run the KBKDF calculation when KO is passed. */ 8550 if (strncmp(buf, "KO = ", 5) == 0) { 8551 CK_SESSION_HANDLE session; 8552 CK_OBJECT_HANDLE prf_key; 8553 CK_OBJECT_HANDLE derived_key; 8554 8555 /* Open the session. */ 8556 crv = NSC_OpenSession(slotID, 0, NULL, NULL, &session); 8557 if (crv != CKR_OK) { 8558 fprintf(stderr, "NSC_OpenSession failed crv=0x%x\n", (unsigned int)crv); 8559 goto done; 8560 } 8561 8562 /* Create the PRF key object. */ 8563 prf_template[0].ulValueLen = KI_len; 8564 crv = NSC_CreateObject(session, prf_template, prf_template_count, &prf_key); 8565 if (crv != CKR_OK) { 8566 fprintf(stderr, "NSC_CreateObject (prf_key) failed crv=0x%x\n", (unsigned int)crv); 8567 goto done; 8568 } 8569 8570 /* Set up the KDF parameters. */ 8571 if (kdf.mechanism == CKM_SP800_108_COUNTER_KDF) { 8572 /* Counter operates in one of three ways: counter before fixed 8573 * input data, counter between fixed input data, and counter 8574 * after fixed input data. In all cases, we have an iterator. 8575 */ 8576 iterator.ulWidthInBits = counter_bitlen; 8577 8578 if (ctr_location == 0 || ctr_location > 3) { 8579 fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n"); 8580 goto done; 8581 } else if (ctr_location == 1) { 8582 /* Counter before */ 8583 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE; 8584 dataParams[0].pValue = &iterator; 8585 dataParams[0].ulValueLen = sizeof(iterator); 8586 8587 dataParams[1].type = CK_SP800_108_BYTE_ARRAY; 8588 dataParams[1].pValue = FixedInputData; 8589 dataParams[1].ulValueLen = FixedInputData_len; 8590 8591 dataParams_len = 2; 8592 } else if (ctr_location == 2) { 8593 /* Counter between */ 8594 dataParams[0].type = CK_SP800_108_BYTE_ARRAY; 8595 dataParams[0].pValue = BeforeFixedInputData; 8596 dataParams[0].ulValueLen = BeforeFixedInputData_len; 8597 8598 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE; 8599 dataParams[1].pValue = &iterator; 8600 dataParams[1].ulValueLen = sizeof(iterator); 8601 8602 dataParams[2].type = CK_SP800_108_BYTE_ARRAY; 8603 dataParams[2].pValue = AfterFixedInputData; 8604 dataParams[2].ulValueLen = AfterFixedInputData_len; 8605 8606 dataParams_len = 3; 8607 } else { 8608 /* Counter after */ 8609 dataParams[0].type = CK_SP800_108_BYTE_ARRAY; 8610 dataParams[0].pValue = FixedInputData; 8611 dataParams[0].ulValueLen = FixedInputData_len; 8612 8613 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE; 8614 dataParams[1].pValue = &iterator; 8615 dataParams[1].ulValueLen = sizeof(iterator); 8616 8617 dataParams_len = 2; 8618 } 8619 } else if (kdf.mechanism == CKM_SP800_108_FEEDBACK_KDF || kdf.mechanism == CKM_SP800_108_DOUBLE_PIPELINE_KDF) { 8620 /* When counter_bitlen != 0, we have an optional counter. */ 8621 if (counter_bitlen != 0) { 8622 iterator.ulWidthInBits = counter_bitlen; 8623 8624 if (ctr_location == 0 || ctr_location > 3) { 8625 fprintf(stderr, "Expected ctr_location != 0 for Counter Mode KDF but got 0.\n"); 8626 goto done; 8627 } else if (ctr_location == 1) { 8628 /* Counter before */ 8629 dataParams[0].type = CK_SP800_108_OPTIONAL_COUNTER; 8630 dataParams[0].pValue = &iterator; 8631 dataParams[0].ulValueLen = sizeof(iterator); 8632 8633 dataParams[1].type = CK_SP800_108_ITERATION_VARIABLE; 8634 dataParams[1].pValue = NULL; 8635 dataParams[1].ulValueLen = 0; 8636 8637 dataParams[2].type = CK_SP800_108_BYTE_ARRAY; 8638 dataParams[2].pValue = FixedInputData; 8639 dataParams[2].ulValueLen = FixedInputData_len; 8640 8641 dataParams_len = 3; 8642 } else if (ctr_location == 2) { 8643 /* Counter between */ 8644 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE; 8645 dataParams[0].pValue = NULL; 8646 dataParams[0].ulValueLen = 0; 8647 8648 dataParams[1].type = CK_SP800_108_OPTIONAL_COUNTER; 8649 dataParams[1].pValue = &iterator; 8650 dataParams[1].ulValueLen = sizeof(iterator); 8651 8652 dataParams[2].type = CK_SP800_108_BYTE_ARRAY; 8653 dataParams[2].pValue = FixedInputData; 8654 dataParams[2].ulValueLen = FixedInputData_len; 8655 8656 dataParams_len = 3; 8657 } else { 8658 /* Counter after */ 8659 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE; 8660 dataParams[0].pValue = NULL; 8661 dataParams[0].ulValueLen = 0; 8662 8663 dataParams[1].type = CK_SP800_108_BYTE_ARRAY; 8664 dataParams[1].pValue = FixedInputData; 8665 dataParams[1].ulValueLen = FixedInputData_len; 8666 8667 dataParams[2].type = CK_SP800_108_OPTIONAL_COUNTER; 8668 dataParams[2].pValue = &iterator; 8669 dataParams[2].ulValueLen = sizeof(iterator); 8670 8671 dataParams_len = 3; 8672 } 8673 } else { 8674 dataParams[0].type = CK_SP800_108_ITERATION_VARIABLE; 8675 dataParams[0].pValue = NULL; 8676 dataParams[0].ulValueLen = 0; 8677 8678 dataParams[1].type = CK_SP800_108_BYTE_ARRAY; 8679 dataParams[1].pValue = FixedInputData; 8680 dataParams[1].ulValueLen = FixedInputData_len; 8681 8682 dataParams_len = 2; 8683 } 8684 } 8685 8686 if (kdf.mechanism != CKM_SP800_108_FEEDBACK_KDF) { 8687 kdfParams.prfType = prf_mech; 8688 kdfParams.ulNumberOfDataParams = dataParams_len; 8689 kdfParams.pDataParams = dataParams; 8690 8691 kdf.pParameter = &kdfParams; 8692 kdf.ulParameterLen = sizeof(kdfParams); 8693 } else { 8694 feedbackParams.prfType = prf_mech; 8695 feedbackParams.ulNumberOfDataParams = dataParams_len; 8696 feedbackParams.pDataParams = dataParams; 8697 feedbackParams.ulIVLen = IV_len; 8698 if (IV_len == 0) { 8699 feedbackParams.pIV = NULL; 8700 } else { 8701 feedbackParams.pIV = IV; 8702 } 8703 8704 kdf.pParameter = &feedbackParams; 8705 kdf.ulParameterLen = sizeof(feedbackParams); 8706 } 8707 8708 crv = NSC_DeriveKey(session, &kdf, prf_key, derive_template, derive_template_count, &derived_key); 8709 if (crv != CKR_OK) { 8710 fprintf(stderr, "NSC_DeriveKey(derived_key) failed crv=0x%x\n", (unsigned int)crv); 8711 goto done; 8712 } 8713 8714 crv = NSC_GetAttributeValue(session, derived_key, &output_key, 1); 8715 if (crv != CKR_OK) { 8716 fprintf(stderr, "NSC_GetAttribute(derived_value) failed crv=0x%x\n", (unsigned int)crv); 8717 goto done; 8718 } 8719 8720 fputs("KO = ", kbkdf_resp); 8721 to_hex_str(buf, KO, output_key.ulValueLen); 8722 fputs(buf, kbkdf_resp); 8723 fputs("\r\n", kbkdf_resp); 8724 8725 continue; 8726 } 8727 } 8728 8729 done: 8730 if (kbkdf_req != NULL) { 8731 fclose(kbkdf_req); 8732 } 8733 if (kbkdf_resp != stdout && kbkdf_resp != NULL) { 8734 fclose(kbkdf_resp); 8735 } 8736 8737 return; 8738 } 8739 8740 int 8741 main(int argc, char **argv) 8742 { 8743 if (argc < 2) 8744 exit(-1); 8745 8746 RNG_RNGInit(); 8747 SECOID_Init(); 8748 8749 /*************/ 8750 /* TDEA */ 8751 /*************/ 8752 if (strcmp(argv[1], "tdea") == 0) { 8753 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */ 8754 if (strcmp(argv[2], "kat") == 0) { 8755 /* Known Answer Test (KAT) */ 8756 tdea_kat_mmt(argv[4]); 8757 } else if (strcmp(argv[2], "mmt") == 0) { 8758 /* Multi-block Message Test (MMT) */ 8759 tdea_kat_mmt(argv[4]); 8760 } else if (strcmp(argv[2], "mct") == 0) { 8761 /* Monte Carlo Test (MCT) */ 8762 if (strcmp(argv[3], "ecb") == 0) { 8763 /* ECB mode */ 8764 tdea_mct(NSS_DES_EDE3, argv[4]); 8765 } else if (strcmp(argv[3], "cbc") == 0) { 8766 /* CBC mode */ 8767 tdea_mct(NSS_DES_EDE3_CBC, argv[4]); 8768 } 8769 } 8770 /*************/ 8771 /* AES */ 8772 /*************/ 8773 } else if (strcmp(argv[1], "aes") == 0) { 8774 /* argv[2]=kat|mmt|mct argv[3]=ecb|cbc argv[4]=<test name>.req */ 8775 if (strcmp(argv[2], "kat") == 0) { 8776 /* Known Answer Test (KAT) */ 8777 aes_kat_mmt(argv[4]); 8778 } else if (strcmp(argv[2], "mmt") == 0) { 8779 /* Multi-block Message Test (MMT) */ 8780 aes_kat_mmt(argv[4]); 8781 } else if (strcmp(argv[2], "gcm") == 0) { 8782 if (strcmp(argv[3], "decrypt") == 0) { 8783 aes_gcm(argv[4], 0); 8784 } else if (strcmp(argv[3], "encrypt_extiv") == 0) { 8785 aes_gcm(argv[4], 1); 8786 } else if (strcmp(argv[3], "encrypt_intiv") == 0) { 8787 aes_gcm(argv[4], 2); 8788 } 8789 } else if (strcmp(argv[2], "mct") == 0) { 8790 /* Monte Carlo Test (MCT) */ 8791 if (strcmp(argv[3], "ecb") == 0) { 8792 /* ECB mode */ 8793 aes_ecb_mct(argv[4]); 8794 } else if (strcmp(argv[3], "cbc") == 0) { 8795 /* CBC mode */ 8796 aes_cbc_mct(argv[4]); 8797 } 8798 } 8799 /*************/ 8800 /* SHA */ 8801 /*************/ 8802 } else if (strcmp(argv[1], "sha") == 0) { 8803 sha_test(argv[2]); 8804 /*************/ 8805 /* RSA */ 8806 /*************/ 8807 } else if (strcmp(argv[1], "rsa") == 0) { 8808 /* argv[2]=siggen|sigver */ 8809 /* argv[3]=<test name>.req */ 8810 if (strcmp(argv[2], "siggen") == 0) { 8811 /* Signature Generation Test */ 8812 rsa_siggen_test(argv[3]); 8813 } else if (strcmp(argv[2], "sigver") == 0) { 8814 /* Signature Verification Test */ 8815 rsa_sigver_test(argv[3]); 8816 } else if (strcmp(argv[2], "keypair") == 0) { 8817 /* Key Pair Generation Test */ 8818 rsa_keypair_test(argv[3]); 8819 } 8820 /*************/ 8821 /* HMAC */ 8822 /*************/ 8823 } else if (strcmp(argv[1], "hmac") == 0) { 8824 hmac_test(argv[2]); 8825 /*************/ 8826 /* DSA */ 8827 /*************/ 8828 } else if (strcmp(argv[1], "dsa") == 0) { 8829 /* argv[2]=keypair|pqggen|pqgver|siggen|sigver */ 8830 /* argv[3]=<test name>.req */ 8831 if (strcmp(argv[2], "keypair") == 0) { 8832 /* Key Pair Generation Test */ 8833 dsa_keypair_test(argv[3]); 8834 } else if (strcmp(argv[2], "pqggen") == 0) { 8835 /* Domain Parameter Generation Test */ 8836 dsa_pqggen_test(argv[3]); 8837 } else if (strcmp(argv[2], "pqgver") == 0) { 8838 /* Domain Parameter Validation Test */ 8839 dsa_pqgver_test(argv[3]); 8840 } else if (strcmp(argv[2], "siggen") == 0) { 8841 /* Signature Generation Test */ 8842 dsa_siggen_test(argv[3]); 8843 } else if (strcmp(argv[2], "sigver") == 0) { 8844 /* Signature Verification Test */ 8845 dsa_sigver_test(argv[3]); 8846 } 8847 /*************/ 8848 /* ECDSA */ 8849 /*************/ 8850 } else if (strcmp(argv[1], "ecdsa") == 0) { 8851 /* argv[2]=keypair|pkv|siggen|sigver argv[3]=<test name>.req */ 8852 if (strcmp(argv[2], "keypair") == 0) { 8853 /* Key Pair Generation Test */ 8854 ecdsa_keypair_test(argv[3]); 8855 } else if (strcmp(argv[2], "pkv") == 0) { 8856 /* Public Key Validation Test */ 8857 ecdsa_pkv_test(argv[3]); 8858 } else if (strcmp(argv[2], "siggen") == 0) { 8859 /* Signature Generation Test */ 8860 ecdsa_siggen_test(argv[3]); 8861 } else if (strcmp(argv[2], "sigver") == 0) { 8862 /* Signature Verification Test */ 8863 ecdsa_sigver_test(argv[3]); 8864 } 8865 /*************/ 8866 /* ECDH */ 8867 /*************/ 8868 } else if (strcmp(argv[1], "ecdh") == 0) { 8869 /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */ 8870 if (strcmp(argv[2], "init-func") == 0) { 8871 ecdh_functional(argv[3], 0); 8872 } else if (strcmp(argv[2], "resp-func") == 0) { 8873 ecdh_functional(argv[3], 1); 8874 } else if (strcmp(argv[2], "init-verify") == 0) { 8875 ecdh_verify(argv[3], 0); 8876 } else if (strcmp(argv[2], "resp-verify") == 0) { 8877 ecdh_verify(argv[3], 1); 8878 } 8879 /*************/ 8880 /* DH */ 8881 /*************/ 8882 } else if (strcmp(argv[1], "dh") == 0) { 8883 /* argv[2]={init|resp}-{func|verify} argv[3]=<test name>.req */ 8884 if (strcmp(argv[2], "init-func") == 0) { 8885 dh_functional(argv[3], 0); 8886 } else if (strcmp(argv[2], "resp-func") == 0) { 8887 dh_functional(argv[3], 1); 8888 } else if (strcmp(argv[2], "init-verify") == 0) { 8889 dh_verify(argv[3], 0); 8890 } else if (strcmp(argv[2], "resp-verify") == 0) { 8891 dh_verify(argv[3], 1); 8892 } 8893 /*************/ 8894 /* RNG */ 8895 /*************/ 8896 } else if (strcmp(argv[1], "rng") == 0) { 8897 /* argv[2]=vst|mct argv[3]=<test name>.req */ 8898 if (strcmp(argv[2], "vst") == 0) { 8899 /* Variable Seed Test */ 8900 rng_vst(argv[3]); 8901 } else if (strcmp(argv[2], "mct") == 0) { 8902 /* Monte Carlo Test */ 8903 rng_mct(argv[3]); 8904 } 8905 } else if (strcmp(argv[1], "drbg") == 0) { 8906 /* Variable Seed Test */ 8907 drbg(argv[2]); 8908 } else if (strcmp(argv[1], "ddrbg") == 0) { 8909 debug = 1; 8910 drbg(argv[2]); 8911 } else if (strcmp(argv[1], "tls") == 0) { 8912 tls(argv[2]); 8913 } else if (strcmp(argv[1], "ikev1") == 0) { 8914 ikev1(argv[2]); 8915 } else if (strcmp(argv[1], "ikev1-psk") == 0) { 8916 ikev1_psk(argv[2]); 8917 } else if (strcmp(argv[1], "ikev2") == 0) { 8918 ikev2(argv[2]); 8919 } else if (strcmp(argv[1], "kbkdf") == 0) { 8920 kbkdf(argv[2]); 8921 } 8922 return 0; 8923 }