rsapoptst.c (21736B)
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 "plgetopt.h" 8 #include "nss.h" 9 #include "secutil.h" 10 #include "pk11table.h" 11 #include "secmodt.h" 12 #include "pk11pub.h" 13 14 struct test_args { 15 char *arg; 16 int mask_value; 17 char *description; 18 }; 19 20 static const struct test_args test_array[] = { 21 { "all", 0x1f, "run all the tests" }, 22 { "e_n_p", 0x01, "public exponent, modulus, prime1" }, 23 { "d_n_q", 0x02, "private exponent, modulus, prime2" }, 24 { "d_p_q", 0x04, "private exponent, prime1, prime2" }, 25 { "e_d_q", 0x08, "public exponent, private exponent, prime2" }, 26 { "e_d_n", 0x10, "public exponent, private exponent, modulus" } 27 }; 28 static const int test_array_size = 29 (sizeof(test_array) / sizeof(struct test_args)); 30 31 static void 32 Usage(char *progName) 33 { 34 int i; 35 #define PRINTUSAGE(subject, option, predicate) \ 36 fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate); 37 fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n " 38 "Test creating RSA private keys from Partial components\n", 39 progName); 40 PRINTUSAGE("", "-k", "key size (in bit)"); 41 PRINTUSAGE("", "-e", "rsa public exponent"); 42 PRINTUSAGE("", "-r", "number times to repeat the test"); 43 PRINTUSAGE("", "-t", "run the specified tests"); 44 for (i = 0; i < test_array_size; i++) { 45 PRINTUSAGE("", test_array[i].arg, test_array[i].description); 46 } 47 fprintf(stderr, "\n"); 48 } 49 50 /* 51 * Test the RSA populate command to see that it can really build 52 * keys from it's components. 53 */ 54 55 const static CK_ATTRIBUTE rsaTemplate[] = { 56 { CKA_CLASS, NULL, 0 }, 57 { CKA_KEY_TYPE, NULL, 0 }, 58 { CKA_TOKEN, NULL, 0 }, 59 { CKA_SENSITIVE, NULL, 0 }, 60 { CKA_PRIVATE, NULL, 0 }, 61 { CKA_ID, NULL, 0 }, 62 { CKA_MODULUS, NULL, 0 }, 63 { CKA_PUBLIC_EXPONENT, NULL, 0 }, 64 { CKA_PRIVATE_EXPONENT, NULL, 0 }, 65 { CKA_PRIME_1, NULL, 0 }, 66 { CKA_PRIME_2, NULL, 0 }, 67 { CKA_EXPONENT_1, NULL, 0 }, 68 { CKA_EXPONENT_2, NULL, 0 }, 69 { CKA_COEFFICIENT, NULL, 0 }, 70 }; 71 72 #define RSA_SIZE (sizeof(rsaTemplate)) 73 #define RSA_ATTRIBUTES (sizeof(rsaTemplate) / sizeof(CK_ATTRIBUTE)) 74 75 static void 76 resetTemplate(CK_ATTRIBUTE *attribute, int start, int end) 77 { 78 int i; 79 for (i = start; i < end; i++) { 80 if (attribute[i].pValue) { 81 PORT_Free(attribute[i].pValue); 82 } 83 attribute[i].pValue = NULL; 84 attribute[i].ulValueLen = 0; 85 } 86 } 87 88 static SECStatus 89 copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template, 90 int offset, CK_ATTRIBUTE_TYPE attrType) 91 { 92 SECItem attributeItem = { 0, 0, 0 }; 93 SECStatus rv; 94 95 rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem); 96 if (rv != SECSuccess) { 97 return rv; 98 } 99 template[offset].type = attrType; 100 template[offset].pValue = attributeItem.data; 101 template[offset].ulValueLen = attributeItem.len; 102 return SECSuccess; 103 } 104 105 static SECStatus 106 readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template, 107 int start, int end) 108 { 109 int i; 110 SECStatus rv; 111 112 for (i = start; i < end; i++) { 113 rv = copyAttribute(objType, object, template, i, template[i].type); 114 if (rv != SECSuccess) { 115 goto fail; 116 } 117 } 118 return SECSuccess; 119 120 fail: 121 resetTemplate(template, start, i); 122 return rv; 123 } 124 125 #define ATTR_STRING(x) getNameFromAttribute(x) 126 127 static void 128 dumphex(FILE *file, const unsigned char *cpval, int start, int end) 129 { 130 int i; 131 for (i = start; i < end; i++) { 132 if ((i % 16) == 0) 133 fprintf(file, "\n "); 134 fprintf(file, " %02x", cpval[i]); 135 } 136 return; 137 } 138 139 void 140 dumpTemplate(FILE *file, const CK_ATTRIBUTE *template, int start, int end) 141 { 142 int i; 143 for (i = start; i < end; i++) { 144 unsigned char cval; 145 CK_ULONG ulval; 146 const unsigned char *cpval; 147 148 fprintf(file, "%s:", ATTR_STRING(template[i].type)); 149 switch (template[i].ulValueLen) { 150 case 1: 151 cval = *(unsigned char *)template[i].pValue; 152 switch (cval) { 153 case 0: 154 fprintf(file, " false"); 155 break; 156 case 1: 157 fprintf(file, " true"); 158 break; 159 default: 160 fprintf(file, " %d (=0x%02x,'%c')", cval, cval, cval); 161 break; 162 } 163 break; 164 case sizeof(CK_ULONG): 165 ulval = *(CK_ULONG *)template[i].pValue; 166 fprintf(file, " %ld (=0x%04lx)", ulval, ulval); 167 break; 168 default: 169 cpval = (const unsigned char *)template[i].pValue; 170 dumphex(file, cpval, 0, template[i].ulValueLen); 171 break; 172 } 173 fprintf(file, "\n"); 174 } 175 } 176 177 void 178 dumpItem(FILE *file, const SECItem *item) 179 { 180 const unsigned char *cpval; 181 182 if (item == NULL) { 183 fprintf(file, " pNULL "); 184 return; 185 } 186 if (item->data == NULL) { 187 fprintf(file, " NULL "); 188 return; 189 } 190 if (item->len == 0) { 191 fprintf(file, " Empty "); 192 return; 193 } 194 cpval = item->data; 195 dumphex(file, cpval, 0, item->len); 196 fprintf(file, " "); 197 return; 198 } 199 200 PRBool 201 rsaKeysAreEqual(PK11ObjectType srcType, void *src, 202 PK11ObjectType destType, void *dest) 203 { 204 205 CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES]; 206 CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES]; 207 PRBool areEqual = PR_TRUE; 208 SECStatus rv; 209 int i; 210 211 memcpy(srcTemplate, rsaTemplate, RSA_SIZE); 212 memcpy(destTemplate, rsaTemplate, RSA_SIZE); 213 214 rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES); 215 if (rv != SECSuccess) { 216 printf("Could read source key\n"); 217 return PR_FALSE; 218 } 219 rv = readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES); 220 if (rv != SECSuccess) { 221 printf("Could read dest key\n"); 222 return PR_FALSE; 223 } 224 225 for (i = 0; i < RSA_ATTRIBUTES; i++) { 226 if (srcTemplate[i].type == CKA_ID) { 227 continue; /* we purposefully make the CKA_ID different */ 228 } 229 if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) { 230 printf("key->%s not equal src_len = %ld, dest_len=%ld\n", 231 ATTR_STRING(srcTemplate[i].type), 232 srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen); 233 areEqual = 0; 234 } else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue, 235 destTemplate[i].ulValueLen) != 0) { 236 printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type)); 237 areEqual = 0; 238 } 239 } 240 if (!areEqual) { 241 fprintf(stderr, "original key:\n"); 242 dumpTemplate(stderr, srcTemplate, 0, RSA_ATTRIBUTES); 243 fprintf(stderr, "created key:\n"); 244 dumpTemplate(stderr, destTemplate, 0, RSA_ATTRIBUTES); 245 } 246 resetTemplate(srcTemplate, 0, RSA_ATTRIBUTES); 247 resetTemplate(destTemplate, 0, RSA_ATTRIBUTES); 248 return areEqual; 249 } 250 251 static int exp_exp_prime_fail_count = 0; 252 253 #define LEAK_ID 0xf 254 255 static int 256 doRSAPopulateTest(unsigned int keySize, unsigned long exponent, 257 int mask, int round, void *pwarg) 258 { 259 SECKEYPrivateKey *rsaPrivKey; 260 SECKEYPublicKey *rsaPubKey; 261 PK11GenericObject *tstPrivKey; 262 CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES]; 263 int tstHeaderCount; 264 PK11SlotInfo *slot = NULL; 265 PK11RSAGenParams rsaParams; 266 CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; 267 CK_KEY_TYPE key_type = CKK_RSA; 268 CK_BBOOL ck_false = CK_FALSE; 269 CK_BYTE cka_id[2] = { 0, 0 }; 270 int failed = 0; 271 int leak_found; /* did we find the expected leak */ 272 int expect_leak = 0; /* are we expecting a leak? */ 273 274 rsaParams.pe = exponent; 275 rsaParams.keySizeInBits = keySize; 276 277 slot = PK11_GetInternalSlot(); 278 if (slot == NULL) { 279 fprintf(stderr, "Couldn't get the internal slot for the test \n"); 280 return -1; 281 } 282 283 rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, 284 &rsaParams, &rsaPubKey, PR_FALSE, 285 PR_FALSE, pwarg); 286 if (rsaPrivKey == NULL) { 287 fprintf(stderr, "RSA Key Gen failed"); 288 PK11_FreeSlot(slot); 289 return -1; 290 } 291 292 memcpy(tstTemplate, rsaTemplate, RSA_SIZE); 293 294 tstTemplate[0].pValue = &obj_class; 295 tstTemplate[0].ulValueLen = sizeof(obj_class); 296 tstTemplate[1].pValue = &key_type; 297 tstTemplate[1].ulValueLen = sizeof(key_type); 298 tstTemplate[2].pValue = &ck_false; 299 tstTemplate[2].ulValueLen = sizeof(ck_false); 300 tstTemplate[3].pValue = &ck_false; 301 tstTemplate[3].ulValueLen = sizeof(ck_false); 302 tstTemplate[4].pValue = &ck_false; 303 tstTemplate[4].ulValueLen = sizeof(ck_false); 304 tstTemplate[5].pValue = &cka_id[0]; 305 tstTemplate[5].ulValueLen = sizeof(cka_id); 306 tstHeaderCount = 6; 307 cka_id[0] = round; 308 309 if (mask & 1) { 310 printf("%s\n", test_array[1].description); 311 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 312 cka_id[1] = 0; 313 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 314 tstHeaderCount, CKA_PUBLIC_EXPONENT); 315 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 316 tstHeaderCount + 1, CKA_MODULUS); 317 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 318 tstHeaderCount + 2, CKA_PRIME_1); 319 320 tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, 321 tstHeaderCount + 322 3, 323 PR_FALSE); 324 if (tstPrivKey == NULL) { 325 fprintf(stderr, "RSA Populate failed: pubExp mod p\n"); 326 failed = 1; 327 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 328 PK11_TypeGeneric, tstPrivKey)) { 329 fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n"); 330 failed = 1; 331 } 332 if (tstPrivKey) 333 PK11_DestroyGenericObject(tstPrivKey); 334 } 335 if (mask & 2) { 336 printf("%s\n", test_array[2].description); 337 /* test the basic2 case, public exponent, modulus, prime2 */ 338 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 339 cka_id[1] = 1; 340 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 341 tstHeaderCount, CKA_PUBLIC_EXPONENT); 342 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 343 tstHeaderCount + 1, CKA_MODULUS); 344 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 345 tstHeaderCount + 2, CKA_PRIME_2); 346 /* test with q in the prime1 position */ 347 tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1; 348 349 tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, 350 tstHeaderCount + 351 3, 352 PR_FALSE); 353 if (tstPrivKey == NULL) { 354 fprintf(stderr, "RSA Populate failed: pubExp mod q\n"); 355 failed = 1; 356 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 357 PK11_TypeGeneric, tstPrivKey)) { 358 fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n"); 359 failed = 1; 360 } 361 if (tstPrivKey) 362 PK11_DestroyGenericObject(tstPrivKey); 363 } 364 if (mask & 4) { 365 printf("%s\n", test_array[3].description); 366 /* test the medium case, private exponent, prime1, prime2 */ 367 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 368 cka_id[1] = 2; 369 370 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 371 tstHeaderCount, CKA_PRIVATE_EXPONENT); 372 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 373 tstHeaderCount + 1, CKA_PRIME_1); 374 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 375 tstHeaderCount + 2, CKA_PRIME_2); 376 /* test with p & q swapped. Underlying code should swap these back */ 377 tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1; 378 tstTemplate[tstHeaderCount + 1].type = CKA_PRIME_2; 379 380 tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, 381 tstHeaderCount + 382 3, 383 PR_FALSE); 384 if (tstPrivKey == NULL) { 385 fprintf(stderr, "RSA Populate failed: privExp p q\n"); 386 failed = 1; 387 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 388 PK11_TypeGeneric, tstPrivKey)) { 389 fprintf(stderr, "RSA Populate key mismatch: privExp p q\n"); 390 failed = 1; 391 } 392 if (tstPrivKey) 393 PK11_DestroyGenericObject(tstPrivKey); 394 } 395 if (mask & 8) { 396 printf("%s\n", test_array[4].description); 397 /* test the advanced case, public exponent, private exponent, prime2 */ 398 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 399 cka_id[1] = 3; 400 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 401 tstHeaderCount, CKA_PRIVATE_EXPONENT); 402 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 403 tstHeaderCount + 1, CKA_PUBLIC_EXPONENT); 404 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 405 tstHeaderCount + 2, CKA_PRIME_2); 406 407 tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, 408 tstHeaderCount + 409 3, 410 PR_FALSE); 411 if (tstPrivKey == NULL) { 412 fprintf(stderr, "RSA Populate failed: pubExp privExp q\n"); 413 fprintf(stderr, " this is expected periodically. It means we\n"); 414 fprintf(stderr, " had more than one key that meets the " 415 "specification\n"); 416 exp_exp_prime_fail_count++; 417 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 418 PK11_TypeGeneric, tstPrivKey)) { 419 fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n"); 420 failed = 1; 421 } 422 if (tstPrivKey) 423 PK11_DestroyGenericObject(tstPrivKey); 424 } 425 if (mask & 0x10) { 426 printf("%s\n", test_array[5].description); 427 /* test the advanced case2, public exponent, private exponent, modulus 428 */ 429 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 430 cka_id[1] = LEAK_ID; 431 432 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 433 tstHeaderCount, CKA_PRIVATE_EXPONENT); 434 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 435 tstHeaderCount + 1, CKA_PUBLIC_EXPONENT); 436 copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, 437 tstHeaderCount + 2, CKA_MODULUS); 438 439 /* purposefully use the old version. This will create a leak */ 440 tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, 441 tstHeaderCount + 442 3, 443 PR_FALSE); 444 if (tstPrivKey == NULL) { 445 fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n"); 446 failed = 1; 447 } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, 448 PK11_TypeGeneric, tstPrivKey)) { 449 fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n"); 450 failed = 1; 451 } 452 expect_leak = 1; 453 if (tstPrivKey) 454 PK11_DestroyGenericObject(tstPrivKey); 455 } 456 resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); 457 SECKEY_DestroyPrivateKey(rsaPrivKey); 458 SECKEY_DestroyPublicKey(rsaPubKey); 459 460 /* make sure we didn't leak */ 461 leak_found = 0; 462 tstPrivKey = PK11_FindGenericObjects(slot, CKO_PRIVATE_KEY); 463 if (tstPrivKey) { 464 SECStatus rv; 465 PK11GenericObject *thisKey; 466 int i; 467 468 fprintf(stderr, "Leaking keys...\n"); 469 for (i = 0, thisKey = tstPrivKey; thisKey; i++, 470 thisKey = PK11_GetNextGenericObject(thisKey)) { 471 SECItem id = { 0, NULL, 0 }; 472 473 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisKey, 474 CKA_ID, &id); 475 if (rv != SECSuccess) { 476 fprintf(stderr, "Key %d: couldn't read CKA_ID: %s\n", 477 i, PORT_ErrorToString(PORT_GetError())); 478 continue; 479 } 480 fprintf(stderr, "id = { "); 481 dumpItem(stderr, &id); 482 fprintf(stderr, "};"); 483 if (id.data[1] == LEAK_ID) { 484 fprintf(stderr, " ---> leak expected\n"); 485 if (id.data[0] == round) 486 leak_found = 1; 487 } else { 488 if (id.len != sizeof(cka_id)) { 489 fprintf(stderr, 490 " ---> ERROR unexpected leak in generated key\n"); 491 } else { 492 fprintf(stderr, 493 " ---> ERROR unexpected leak in constructed key\n"); 494 } 495 failed = 1; 496 } 497 SECITEM_FreeItem(&id, PR_FALSE); 498 } 499 PK11_DestroyGenericObjects(tstPrivKey); 500 } 501 if (expect_leak && !leak_found) { 502 fprintf(stderr, "ERROR expected leak not found\n"); 503 failed = 1; 504 } 505 506 PK11_FreeSlot(slot); 507 return failed ? -1 : 0; 508 } 509 510 /* populate options */ 511 enum { 512 opt_Exponent = 0, 513 opt_KeySize, 514 opt_Repeat, 515 opt_Tests 516 }; 517 518 static secuCommandFlag populate_options[] = { 519 { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE }, 520 { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE }, 521 { /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE }, 522 { /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE }, 523 }; 524 525 int 526 is_delimiter(char c) 527 { 528 if ((c == '+') || (c == ',') || (c == '|')) { 529 return 1; 530 } 531 return 0; 532 } 533 534 int 535 parse_tests(char *test_string) 536 { 537 int mask = 0; 538 int i; 539 540 while (*test_string) { 541 if (is_delimiter(*test_string)) { 542 test_string++; 543 } 544 for (i = 0; i < test_array_size; i++) { 545 char *arg = test_array[i].arg; 546 int len = strlen(arg); 547 if (strncmp(test_string, arg, len) == 0) { 548 test_string += len; 549 mask |= test_array[i].mask_value; 550 break; 551 } 552 } 553 if (i == test_array_size) { 554 break; 555 } 556 } 557 return mask; 558 } 559 560 int 561 main(int argc, char **argv) 562 { 563 unsigned int keySize = 1024; 564 unsigned long exponent = 65537; 565 int i, repeat = 1, ret = 0; 566 SECStatus rv = SECFailure; 567 secuCommand populateArgs; 568 char *progName; 569 int mask = 0xff; 570 571 populateArgs.numCommands = 0; 572 populateArgs.numOptions = sizeof(populate_options) / 573 sizeof(secuCommandFlag); 574 populateArgs.commands = NULL; 575 populateArgs.options = populate_options; 576 577 progName = strrchr(argv[0], '/'); 578 if (!progName) 579 progName = strrchr(argv[0], '\\'); 580 progName = progName ? progName + 1 : argv[0]; 581 582 rv = NSS_NoDB_Init(NULL); 583 if (rv != SECSuccess) { 584 SECU_PrintPRandOSError(progName); 585 return -1; 586 } 587 588 rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs); 589 if (rv == SECFailure) { 590 fprintf(stderr, "%s: command line parsing error!\n", progName); 591 Usage(progName); 592 return -1; 593 } 594 rv = SECFailure; 595 596 if (populateArgs.options[opt_KeySize].activated) { 597 keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg); 598 } 599 if (populateArgs.options[opt_Repeat].activated) { 600 repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg); 601 } 602 if (populateArgs.options[opt_Exponent].activated) { 603 exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg); 604 } 605 if (populateArgs.options[opt_Tests].activated) { 606 char *test_string = populateArgs.options[opt_Tests].arg; 607 mask = PORT_Atoi(test_string); 608 if (mask == 0) { 609 mask = parse_tests(test_string); 610 } 611 if (mask == 0) { 612 Usage(progName); 613 return -1; 614 } 615 } 616 617 exp_exp_prime_fail_count = 0; 618 for (i = 0; i < repeat; i++) { 619 printf("Running RSA Populate test run %d\n", i); 620 ret = doRSAPopulateTest(keySize, exponent, mask, i, NULL); 621 if (ret != 0) { 622 i++; 623 break; 624 } 625 } 626 if (ret != 0) { 627 fprintf(stderr, "RSA Populate test round %d: FAILED\n", i); 628 } 629 if (repeat > 1) { 630 printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n", 631 exp_exp_prime_fail_count, i, 632 (((double)exp_exp_prime_fail_count) * 100.0) / (double)i); 633 } 634 if (NSS_Shutdown() != SECSuccess) { 635 fprintf(stderr, "Shutdown failed\n"); 636 ret = -1; 637 } 638 return ret; 639 }