| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include "plgetopt.h" |
| #include "nss.h" |
| #include "secutil.h" |
| #include "pk11table.h" |
| #include "secmodt.h" |
| #include "pk11pub.h" |
| |
| struct test_args { |
| char *arg; |
| int mask_value; |
| char *description; |
| }; |
| |
| static const struct test_args test_array[] = { |
| { "all", 0x1f, "run all the tests" }, |
| { "e_n_p", 0x01, "public exponent, modulus, prime1" }, |
| { "d_n_q", 0x02, "private exponent, modulus, prime2" }, |
| { "d_p_q", 0x04, "private exponent, prime1, prime2" }, |
| { "e_d_q", 0x08, "public exponent, private exponent, prime2" }, |
| { "e_d_n", 0x10, "public exponent, private exponent, modulus" } |
| }; |
| static const int test_array_size = |
| (sizeof(test_array) / sizeof(struct test_args)); |
| |
| static void |
| Usage(char *progName) |
| { |
| int i; |
| #define PRINTUSAGE(subject, option, predicate) \ |
| fprintf(stderr, "%10s %s\t%s\n", subject, option, predicate); |
| fprintf(stderr, "%s [-k keysize] [-e exp] [-r rounds] [-t tests]\n " |
| "Test creating RSA private keys from Partial components\n", |
| progName); |
| PRINTUSAGE("", "-k", "key size (in bit)"); |
| PRINTUSAGE("", "-e", "rsa public exponent"); |
| PRINTUSAGE("", "-r", "number times to repeat the test"); |
| PRINTUSAGE("", "-t", "run the specified tests"); |
| for (i = 0; i < test_array_size; i++) { |
| PRINTUSAGE("", test_array[i].arg, test_array[i].description); |
| } |
| fprintf(stderr, "\n"); |
| } |
| |
| /* |
| * Test the RSA populate command to see that it can really build |
| * keys from it's components. |
| */ |
| |
| const static CK_ATTRIBUTE rsaTemplate[] = { |
| { CKA_CLASS, NULL, 0 }, |
| { CKA_KEY_TYPE, NULL, 0 }, |
| { CKA_TOKEN, NULL, 0 }, |
| { CKA_SENSITIVE, NULL, 0 }, |
| { CKA_PRIVATE, NULL, 0 }, |
| { CKA_ID, NULL, 0 }, |
| { CKA_MODULUS, NULL, 0 }, |
| { CKA_PUBLIC_EXPONENT, NULL, 0 }, |
| { CKA_PRIVATE_EXPONENT, NULL, 0 }, |
| { CKA_PRIME_1, NULL, 0 }, |
| { CKA_PRIME_2, NULL, 0 }, |
| { CKA_EXPONENT_1, NULL, 0 }, |
| { CKA_EXPONENT_2, NULL, 0 }, |
| { CKA_COEFFICIENT, NULL, 0 }, |
| }; |
| |
| #define RSA_SIZE (sizeof(rsaTemplate)) |
| #define RSA_ATTRIBUTES (sizeof(rsaTemplate) / sizeof(CK_ATTRIBUTE)) |
| |
| static void |
| resetTemplate(CK_ATTRIBUTE *attribute, int start, int end) |
| { |
| int i; |
| for (i = start; i < end; i++) { |
| if (attribute[i].pValue) { |
| PORT_Free(attribute[i].pValue); |
| } |
| attribute[i].pValue = NULL; |
| attribute[i].ulValueLen = 0; |
| } |
| } |
| |
| static SECStatus |
| copyAttribute(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template, |
| int offset, CK_ATTRIBUTE_TYPE attrType) |
| { |
| SECItem attributeItem = { 0, 0, 0 }; |
| SECStatus rv; |
| |
| rv = PK11_ReadRawAttribute(objType, object, attrType, &attributeItem); |
| if (rv != SECSuccess) { |
| return rv; |
| } |
| template[offset].type = attrType; |
| template[offset].pValue = attributeItem.data; |
| template[offset].ulValueLen = attributeItem.len; |
| return SECSuccess; |
| } |
| |
| static SECStatus |
| readKey(PK11ObjectType objType, void *object, CK_ATTRIBUTE *template, |
| int start, int end) |
| { |
| int i; |
| SECStatus rv; |
| |
| for (i = start; i < end; i++) { |
| rv = copyAttribute(objType, object, template, i, template[i].type); |
| if (rv != SECSuccess) { |
| goto fail; |
| } |
| } |
| return SECSuccess; |
| |
| fail: |
| resetTemplate(template, start, i); |
| return rv; |
| } |
| |
| #define ATTR_STRING(x) getNameFromAttribute(x) |
| |
| static void |
| dumphex(FILE *file, const unsigned char *cpval, int start, int end) |
| { |
| int i; |
| for (i = start; i < end; i++) { |
| if ((i % 16) == 0) |
| fprintf(file, "\n "); |
| fprintf(file, " %02x", cpval[i]); |
| } |
| return; |
| } |
| |
| void |
| dumpTemplate(FILE *file, const CK_ATTRIBUTE *template, int start, int end) |
| { |
| int i; |
| for (i = start; i < end; i++) { |
| unsigned char cval; |
| CK_ULONG ulval; |
| const unsigned char *cpval; |
| |
| fprintf(file, "%s:", ATTR_STRING(template[i].type)); |
| switch (template[i].ulValueLen) { |
| case 1: |
| cval = *(unsigned char *)template[i].pValue; |
| switch (cval) { |
| case 0: |
| fprintf(file, " false"); |
| break; |
| case 1: |
| fprintf(file, " true"); |
| break; |
| default: |
| fprintf(file, " %d (=0x%02x,'%c')", cval, cval, cval); |
| break; |
| } |
| break; |
| case sizeof(CK_ULONG): |
| ulval = *(CK_ULONG *)template[i].pValue; |
| fprintf(file, " %ld (=0x%04lx)", ulval, ulval); |
| break; |
| default: |
| cpval = (const unsigned char *)template[i].pValue; |
| dumphex(file, cpval, 0, template[i].ulValueLen); |
| break; |
| } |
| fprintf(file, "\n"); |
| } |
| } |
| |
| void |
| dumpItem(FILE *file, const SECItem *item) |
| { |
| const unsigned char *cpval; |
| |
| if (item == NULL) { |
| fprintf(file, " pNULL "); |
| return; |
| } |
| if (item->data == NULL) { |
| fprintf(file, " NULL "); |
| return; |
| } |
| if (item->len == 0) { |
| fprintf(file, " Empty "); |
| return; |
| } |
| cpval = item->data; |
| dumphex(file, cpval, 0, item->len); |
| fprintf(file, " "); |
| return; |
| } |
| |
| PRBool |
| rsaKeysAreEqual(PK11ObjectType srcType, void *src, |
| PK11ObjectType destType, void *dest) |
| { |
| |
| CK_ATTRIBUTE srcTemplate[RSA_ATTRIBUTES]; |
| CK_ATTRIBUTE destTemplate[RSA_ATTRIBUTES]; |
| PRBool areEqual = PR_TRUE; |
| SECStatus rv; |
| int i; |
| |
| memcpy(srcTemplate, rsaTemplate, RSA_SIZE); |
| memcpy(destTemplate, rsaTemplate, RSA_SIZE); |
| |
| rv = readKey(srcType, src, srcTemplate, 0, RSA_ATTRIBUTES); |
| if (rv != SECSuccess) { |
| printf("Could read source key\n"); |
| return PR_FALSE; |
| } |
| rv = readKey(destType, dest, destTemplate, 0, RSA_ATTRIBUTES); |
| if (rv != SECSuccess) { |
| printf("Could read dest key\n"); |
| return PR_FALSE; |
| } |
| |
| for (i = 0; i < RSA_ATTRIBUTES; i++) { |
| if (srcTemplate[i].type == CKA_ID) { |
| continue; /* we purposefully make the CKA_ID different */ |
| } |
| if (srcTemplate[i].ulValueLen != destTemplate[i].ulValueLen) { |
| printf("key->%s not equal src_len = %ld, dest_len=%ld\n", |
| ATTR_STRING(srcTemplate[i].type), |
| srcTemplate[i].ulValueLen, destTemplate[i].ulValueLen); |
| areEqual = 0; |
| } else if (memcmp(srcTemplate[i].pValue, destTemplate[i].pValue, |
| destTemplate[i].ulValueLen) != 0) { |
| printf("key->%s not equal.\n", ATTR_STRING(srcTemplate[i].type)); |
| areEqual = 0; |
| } |
| } |
| if (!areEqual) { |
| fprintf(stderr, "original key:\n"); |
| dumpTemplate(stderr, srcTemplate, 0, RSA_ATTRIBUTES); |
| fprintf(stderr, "created key:\n"); |
| dumpTemplate(stderr, destTemplate, 0, RSA_ATTRIBUTES); |
| } |
| resetTemplate(srcTemplate, 0, RSA_ATTRIBUTES); |
| resetTemplate(destTemplate, 0, RSA_ATTRIBUTES); |
| return areEqual; |
| } |
| |
| static int exp_exp_prime_fail_count = 0; |
| |
| #define LEAK_ID 0xf |
| |
| static int |
| doRSAPopulateTest(unsigned int keySize, unsigned long exponent, |
| int mask, int round, void *pwarg) |
| { |
| SECKEYPrivateKey *rsaPrivKey; |
| SECKEYPublicKey *rsaPubKey; |
| PK11GenericObject *tstPrivKey; |
| CK_ATTRIBUTE tstTemplate[RSA_ATTRIBUTES]; |
| int tstHeaderCount; |
| PK11SlotInfo *slot = NULL; |
| PK11RSAGenParams rsaParams; |
| CK_OBJECT_CLASS obj_class = CKO_PRIVATE_KEY; |
| CK_KEY_TYPE key_type = CKK_RSA; |
| CK_BBOOL ck_false = CK_FALSE; |
| CK_BYTE cka_id[2] = { 0, 0 }; |
| int failed = 0; |
| int leak_found; /* did we find the expected leak */ |
| int expect_leak = 0; /* are we expecting a leak? */ |
| |
| rsaParams.pe = exponent; |
| rsaParams.keySizeInBits = keySize; |
| |
| slot = PK11_GetInternalSlot(); |
| if (slot == NULL) { |
| fprintf(stderr, "Couldn't get the internal slot for the test \n"); |
| return -1; |
| } |
| |
| rsaPrivKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN, |
| &rsaParams, &rsaPubKey, PR_FALSE, |
| PR_FALSE, pwarg); |
| if (rsaPrivKey == NULL) { |
| fprintf(stderr, "RSA Key Gen failed"); |
| PK11_FreeSlot(slot); |
| return -1; |
| } |
| |
| memcpy(tstTemplate, rsaTemplate, RSA_SIZE); |
| |
| tstTemplate[0].pValue = &obj_class; |
| tstTemplate[0].ulValueLen = sizeof(obj_class); |
| tstTemplate[1].pValue = &key_type; |
| tstTemplate[1].ulValueLen = sizeof(key_type); |
| tstTemplate[2].pValue = &ck_false; |
| tstTemplate[2].ulValueLen = sizeof(ck_false); |
| tstTemplate[3].pValue = &ck_false; |
| tstTemplate[3].ulValueLen = sizeof(ck_false); |
| tstTemplate[4].pValue = &ck_false; |
| tstTemplate[4].ulValueLen = sizeof(ck_false); |
| tstTemplate[5].pValue = &cka_id[0]; |
| tstTemplate[5].ulValueLen = sizeof(cka_id); |
| tstHeaderCount = 6; |
| cka_id[0] = round; |
| |
| if (mask & 1) { |
| printf("%s\n", test_array[1].description); |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| cka_id[1] = 0; |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount, CKA_PUBLIC_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 1, CKA_MODULUS); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 2, CKA_PRIME_1); |
| |
| tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, |
| tstHeaderCount + |
| 3, |
| PR_FALSE); |
| if (tstPrivKey == NULL) { |
| fprintf(stderr, "RSA Populate failed: pubExp mod p\n"); |
| failed = 1; |
| } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, |
| PK11_TypeGeneric, tstPrivKey)) { |
| fprintf(stderr, "RSA Populate key mismatch: pubExp mod p\n"); |
| failed = 1; |
| } |
| if (tstPrivKey) |
| PK11_DestroyGenericObject(tstPrivKey); |
| } |
| if (mask & 2) { |
| printf("%s\n", test_array[2].description); |
| /* test the basic2 case, public exponent, modulus, prime2 */ |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| cka_id[1] = 1; |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount, CKA_PUBLIC_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 1, CKA_MODULUS); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 2, CKA_PRIME_2); |
| /* test with q in the prime1 position */ |
| tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1; |
| |
| tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, |
| tstHeaderCount + |
| 3, |
| PR_FALSE); |
| if (tstPrivKey == NULL) { |
| fprintf(stderr, "RSA Populate failed: pubExp mod q\n"); |
| failed = 1; |
| } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, |
| PK11_TypeGeneric, tstPrivKey)) { |
| fprintf(stderr, "RSA Populate key mismatch: pubExp mod q\n"); |
| failed = 1; |
| } |
| if (tstPrivKey) |
| PK11_DestroyGenericObject(tstPrivKey); |
| } |
| if (mask & 4) { |
| printf("%s\n", test_array[3].description); |
| /* test the medium case, private exponent, prime1, prime2 */ |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| cka_id[1] = 2; |
| |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount, CKA_PRIVATE_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 1, CKA_PRIME_1); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 2, CKA_PRIME_2); |
| /* test with p & q swapped. Underlying code should swap these back */ |
| tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1; |
| tstTemplate[tstHeaderCount + 1].type = CKA_PRIME_2; |
| |
| tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, |
| tstHeaderCount + |
| 3, |
| PR_FALSE); |
| if (tstPrivKey == NULL) { |
| fprintf(stderr, "RSA Populate failed: privExp p q\n"); |
| failed = 1; |
| } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, |
| PK11_TypeGeneric, tstPrivKey)) { |
| fprintf(stderr, "RSA Populate key mismatch: privExp p q\n"); |
| failed = 1; |
| } |
| if (tstPrivKey) |
| PK11_DestroyGenericObject(tstPrivKey); |
| } |
| if (mask & 8) { |
| printf("%s\n", test_array[4].description); |
| /* test the advanced case, public exponent, private exponent, prime2 */ |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| cka_id[1] = 3; |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount, CKA_PRIVATE_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 1, CKA_PUBLIC_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 2, CKA_PRIME_2); |
| |
| tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate, |
| tstHeaderCount + |
| 3, |
| PR_FALSE); |
| if (tstPrivKey == NULL) { |
| fprintf(stderr, "RSA Populate failed: pubExp privExp q\n"); |
| fprintf(stderr, " this is expected periodically. It means we\n"); |
| fprintf(stderr, " had more than one key that meets the " |
| "specification\n"); |
| exp_exp_prime_fail_count++; |
| } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, |
| PK11_TypeGeneric, tstPrivKey)) { |
| fprintf(stderr, "RSA Populate key mismatch: pubExp privExp q\n"); |
| failed = 1; |
| } |
| if (tstPrivKey) |
| PK11_DestroyGenericObject(tstPrivKey); |
| } |
| if (mask & 0x10) { |
| printf("%s\n", test_array[5].description); |
| /* test the advanced case2, public exponent, private exponent, modulus |
| */ |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| cka_id[1] = LEAK_ID; |
| |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount, CKA_PRIVATE_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 1, CKA_PUBLIC_EXPONENT); |
| copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate, |
| tstHeaderCount + 2, CKA_MODULUS); |
| |
| /* purposefully use the old version. This will create a leak */ |
| tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate, |
| tstHeaderCount + |
| 3, |
| PR_FALSE); |
| if (tstPrivKey == NULL) { |
| fprintf(stderr, "RSA Populate failed: pubExp privExp mod\n"); |
| failed = 1; |
| } else if (!rsaKeysAreEqual(PK11_TypePrivKey, rsaPrivKey, |
| PK11_TypeGeneric, tstPrivKey)) { |
| fprintf(stderr, "RSA Populate key mismatch: pubExp privExp mod\n"); |
| failed = 1; |
| } |
| expect_leak = 1; |
| if (tstPrivKey) |
| PK11_DestroyGenericObject(tstPrivKey); |
| } |
| resetTemplate(tstTemplate, tstHeaderCount, RSA_ATTRIBUTES); |
| SECKEY_DestroyPrivateKey(rsaPrivKey); |
| SECKEY_DestroyPublicKey(rsaPubKey); |
| |
| /* make sure we didn't leak */ |
| leak_found = 0; |
| tstPrivKey = PK11_FindGenericObjects(slot, CKO_PRIVATE_KEY); |
| if (tstPrivKey) { |
| SECStatus rv; |
| PK11GenericObject *thisKey; |
| int i; |
| |
| fprintf(stderr, "Leaking keys...\n"); |
| for (i = 0, thisKey = tstPrivKey; thisKey; i++, |
| thisKey = PK11_GetNextGenericObject(thisKey)) { |
| SECItem id = { 0, NULL, 0 }; |
| |
| rv = PK11_ReadRawAttribute(PK11_TypeGeneric, thisKey, |
| CKA_ID, &id); |
| if (rv != SECSuccess) { |
| fprintf(stderr, "Key %d: couldn't read CKA_ID: %s\n", |
| i, PORT_ErrorToString(PORT_GetError())); |
| continue; |
| } |
| fprintf(stderr, "id = { "); |
| dumpItem(stderr, &id); |
| fprintf(stderr, "};"); |
| if (id.data[1] == LEAK_ID) { |
| fprintf(stderr, " ---> leak expected\n"); |
| if (id.data[0] == round) |
| leak_found = 1; |
| } else { |
| if (id.len != sizeof(cka_id)) { |
| fprintf(stderr, |
| " ---> ERROR unexpected leak in generated key\n"); |
| } else { |
| fprintf(stderr, |
| " ---> ERROR unexpected leak in constructed key\n"); |
| } |
| failed = 1; |
| } |
| SECITEM_FreeItem(&id, PR_FALSE); |
| } |
| PK11_DestroyGenericObjects(tstPrivKey); |
| } |
| if (expect_leak && !leak_found) { |
| fprintf(stderr, "ERROR expected leak not found\n"); |
| failed = 1; |
| } |
| |
| PK11_FreeSlot(slot); |
| return failed ? -1 : 0; |
| } |
| |
| /* populate options */ |
| enum { |
| opt_Exponent = 0, |
| opt_KeySize, |
| opt_Repeat, |
| opt_Tests |
| }; |
| |
| static secuCommandFlag populate_options[] = |
| { |
| { /* opt_Exponent */ 'e', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_KeySize */ 'k', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_Repeat */ 'r', PR_TRUE, 0, PR_FALSE }, |
| { /* opt_Tests */ 't', PR_TRUE, 0, PR_FALSE }, |
| }; |
| |
| int |
| is_delimiter(char c) |
| { |
| if ((c == '+') || (c == ',') || (c == '|')) { |
| return 1; |
| } |
| return 0; |
| } |
| |
| int |
| parse_tests(char *test_string) |
| { |
| int mask = 0; |
| int i; |
| |
| while (*test_string) { |
| if (is_delimiter(*test_string)) { |
| test_string++; |
| } |
| for (i = 0; i < test_array_size; i++) { |
| char *arg = test_array[i].arg; |
| int len = strlen(arg); |
| if (strncmp(test_string, arg, len) == 0) { |
| test_string += len; |
| mask |= test_array[i].mask_value; |
| break; |
| } |
| } |
| if (i == test_array_size) { |
| break; |
| } |
| } |
| return mask; |
| } |
| |
| int |
| main(int argc, char **argv) |
| { |
| unsigned int keySize = 1024; |
| unsigned long exponent = 65537; |
| int i, repeat = 1, ret = 0; |
| SECStatus rv = SECFailure; |
| secuCommand populateArgs; |
| char *progName; |
| int mask = 0xff; |
| |
| populateArgs.numCommands = 0; |
| populateArgs.numOptions = sizeof(populate_options) / |
| sizeof(secuCommandFlag); |
| populateArgs.commands = NULL; |
| populateArgs.options = populate_options; |
| |
| progName = strrchr(argv[0], '/'); |
| if (!progName) |
| progName = strrchr(argv[0], '\\'); |
| progName = progName ? progName + 1 : argv[0]; |
| |
| rv = NSS_NoDB_Init(NULL); |
| if (rv != SECSuccess) { |
| SECU_PrintPRandOSError(progName); |
| return -1; |
| } |
| |
| rv = SECU_ParseCommandLine(argc, argv, progName, &populateArgs); |
| if (rv == SECFailure) { |
| fprintf(stderr, "%s: command line parsing error!\n", progName); |
| Usage(progName); |
| return -1; |
| } |
| rv = SECFailure; |
| |
| if (populateArgs.options[opt_KeySize].activated) { |
| keySize = PORT_Atoi(populateArgs.options[opt_KeySize].arg); |
| } |
| if (populateArgs.options[opt_Repeat].activated) { |
| repeat = PORT_Atoi(populateArgs.options[opt_Repeat].arg); |
| } |
| if (populateArgs.options[opt_Exponent].activated) { |
| exponent = PORT_Atoi(populateArgs.options[opt_Exponent].arg); |
| } |
| if (populateArgs.options[opt_Tests].activated) { |
| char *test_string = populateArgs.options[opt_Tests].arg; |
| mask = PORT_Atoi(test_string); |
| if (mask == 0) { |
| mask = parse_tests(test_string); |
| } |
| if (mask == 0) { |
| Usage(progName); |
| return -1; |
| } |
| } |
| |
| exp_exp_prime_fail_count = 0; |
| for (i = 0; i < repeat; i++) { |
| printf("Running RSA Populate test run %d\n", i); |
| ret = doRSAPopulateTest(keySize, exponent, mask, i, NULL); |
| if (ret != 0) { |
| i++; |
| break; |
| } |
| } |
| if (ret != 0) { |
| fprintf(stderr, "RSA Populate test round %d: FAILED\n", i); |
| } |
| if (repeat > 1) { |
| printf(" pub priv prime test: %d failures out of %d runs (%f %%)\n", |
| exp_exp_prime_fail_count, i, |
| (((double)exp_exp_prime_fail_count) * 100.0) / (double)i); |
| } |
| if (NSS_Shutdown() != SECSuccess) { |
| fprintf(stderr, "Shutdown failed\n"); |
| ret = -1; |
| } |
| return ret; |
| } |