summaryrefslogtreecommitdiffstats
path: root/security/nss/cmd/rsapoptst
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 01:47:29 +0000
commit0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d (patch)
treea31f07c9bcca9d56ce61e9a1ffd30ef350d513aa /security/nss/cmd/rsapoptst
parentInitial commit. (diff)
downloadfirefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.tar.xz
firefox-esr-0ebf5bdf043a27fd3dfb7f92e0cb63d88954c44d.zip
Adding upstream version 115.8.0esr.upstream/115.8.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'security/nss/cmd/rsapoptst')
-rw-r--r--security/nss/cmd/rsapoptst/Makefile54
-rw-r--r--security/nss/cmd/rsapoptst/manifest.mn16
-rw-r--r--security/nss/cmd/rsapoptst/rsapoptst.c639
-rw-r--r--security/nss/cmd/rsapoptst/rsapoptst.gyp25
4 files changed, 734 insertions, 0 deletions
diff --git a/security/nss/cmd/rsapoptst/Makefile b/security/nss/cmd/rsapoptst/Makefile
new file mode 100644
index 0000000000..a5e83efdfa
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/Makefile
@@ -0,0 +1,54 @@
+#! gmake
+#
+# 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/.
+
+#######################################################################
+# (1) Include initial platform-independent assignments (MANDATORY). #
+#######################################################################
+
+include manifest.mn
+#MKPROG = purify -cache-dir=/u/mcgreer/pcache -best-effort \
+# -always-use-cache-dir $(CC)
+
+#######################################################################
+# (2) Include "global" configuration information. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/config.mk
+
+#######################################################################
+# (3) Include "component" configuration information. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (4) Include "local" platform-dependent assignments (OPTIONAL). #
+#######################################################################
+
+include ../platlibs.mk
+
+#EXTRA_SHARED_LIBS += \
+# -L/usr/lib \
+# -lposix4 \
+# $(NULL)
+
+#######################################################################
+# (5) Execute "global" rules. (OPTIONAL) #
+#######################################################################
+
+include $(CORE_DEPTH)/coreconf/rules.mk
+
+#######################################################################
+# (6) Execute "component" rules. (OPTIONAL) #
+#######################################################################
+
+
+
+#######################################################################
+# (7) Execute "local" rules. (OPTIONAL). #
+#######################################################################
+
+include ../platrules.mk
diff --git a/security/nss/cmd/rsapoptst/manifest.mn b/security/nss/cmd/rsapoptst/manifest.mn
new file mode 100644
index 0000000000..ddf561e575
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/manifest.mn
@@ -0,0 +1,16 @@
+#
+# 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/.
+CORE_DEPTH = ../..
+
+MODULE = nss
+
+REQUIRES = seccmd dbm softoken
+
+PROGRAM = rsapoptst
+
+CSRCS = \
+ rsapoptst.c \
+ $(NULL)
+
diff --git a/security/nss/cmd/rsapoptst/rsapoptst.c b/security/nss/cmd/rsapoptst/rsapoptst.c
new file mode 100644
index 0000000000..4b9618e3b0
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/rsapoptst.c
@@ -0,0 +1,639 @@
+/* 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;
+}
diff --git a/security/nss/cmd/rsapoptst/rsapoptst.gyp b/security/nss/cmd/rsapoptst/rsapoptst.gyp
new file mode 100644
index 0000000000..325a109095
--- /dev/null
+++ b/security/nss/cmd/rsapoptst/rsapoptst.gyp
@@ -0,0 +1,25 @@
+# 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/.
+{
+ 'includes': [
+ '../../coreconf/config.gypi',
+ '../../cmd/platlibs.gypi'
+ ],
+ 'targets': [
+ {
+ 'target_name': 'rsapoptst',
+ 'type': 'executable',
+ 'sources': [
+ 'rsapoptst.c'
+ ],
+ 'dependencies': [
+ '<(DEPTH)/exports.gyp:dbm_exports',
+ '<(DEPTH)/exports.gyp:nss_exports',
+ ]
+ }
+ ],
+ 'variables': {
+ 'module': 'nss',
+ }
+}