summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cmd/manifest.mn1
-rw-r--r--cmd/rsapoptst/rsapoptst.c183
-rw-r--r--cmd/rsapoptst/rsapoptst.gyp25
-rw-r--r--lib/nss/nss.def1
-rw-r--r--lib/pk11wrap/pk11merge.c1
-rw-r--r--lib/pk11wrap/pk11obj.c38
-rw-r--r--lib/pk11wrap/pk11pub.h4
-rw-r--r--lib/pk11wrap/secmodti.h1
-rw-r--r--nss.gyp1
-rwxr-xr-xtests/cipher/cipher.sh16
10 files changed, 230 insertions, 41 deletions
diff --git a/cmd/manifest.mn b/cmd/manifest.mn
index 153384ce1..f5e6bc236 100644
--- a/cmd/manifest.mn
+++ b/cmd/manifest.mn
@@ -63,6 +63,7 @@ NSS_SRCDIRS = \
pp \
pwdecrypt \
rsaperf \
+ rsapoptst \
sdrtest \
selfserv \
signtool \
diff --git a/cmd/rsapoptst/rsapoptst.c b/cmd/rsapoptst/rsapoptst.c
index 81ddcd6c4..800c75473 100644
--- a/cmd/rsapoptst/rsapoptst.c
+++ b/cmd/rsapoptst/rsapoptst.c
@@ -23,7 +23,7 @@ static const struct test_args test_array[] = {
{ "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, moduls" }
+ { "e_d_n", 0x10, "public exponent, private exponent, modulus" }
};
static const int test_array_size =
(sizeof(test_array) / sizeof(struct test_args));
@@ -58,6 +58,7 @@ const static CK_ATTRIBUTE rsaTemplate[] = {
{ 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 },
@@ -123,46 +124,77 @@ fail:
#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(CK_ATTRIBUTE *template, int start, int end)
+dumpTemplate(FILE *file, const CK_ATTRIBUTE *template, int start, int end)
{
- int i, j;
- for (i = 0; i < end; i++) {
+ int i;
+ for (i = start; i < end; i++) {
unsigned char cval;
CK_ULONG ulval;
- unsigned char *cpval;
+ const unsigned char *cpval;
- fprintf(stderr, "%s:", ATTR_STRING(template[i].type));
+ 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(stderr, " false");
+ fprintf(file, " false");
break;
case 1:
- fprintf(stderr, " true");
+ fprintf(file, " true");
break;
default:
- fprintf(stderr, " %d (=0x%02x,'%c')", cval, cval, cval);
+ fprintf(file, " %d (=0x%02x,'%c')", cval, cval, cval);
break;
}
break;
case sizeof(CK_ULONG):
ulval = *(CK_ULONG *)template[i].pValue;
- fprintf(stderr, " %ld (=0x%04lx)", ulval, ulval);
+ fprintf(file, " %ld (=0x%04lx)", ulval, ulval);
break;
default:
- cpval = (unsigned char *)template[i].pValue;
- for (j = 0; j < template[i].ulValueLen; j++) {
- if ((j % 16) == 0)
- fprintf(stderr, "\n ");
- fprintf(stderr, " %02x", cpval[j]);
- }
+ cpval = (const unsigned char *)template[i].pValue;
+ dumphex(file, cpval, 0, template[i].ulValueLen);
break;
}
- fprintf(stderr, "\n");
+ 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
@@ -191,6 +223,9 @@ rsaKeysAreEqual(PK11ObjectType srcType, void *src,
}
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),
@@ -204,18 +239,22 @@ rsaKeysAreEqual(PK11ObjectType srcType, void *src,
}
if (!areEqual) {
fprintf(stderr, "original key:\n");
- dumpTemplate(srcTemplate, 0, RSA_ATTRIBUTES);
+ dumpTemplate(stderr, srcTemplate, 0, RSA_ATTRIBUTES);
fprintf(stderr, "created key:\n");
- dumpTemplate(destTemplate, 0, RSA_ATTRIBUTES);
+ 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, void *pwarg)
+ int mask, int round, void *pwarg)
{
SECKEYPrivateKey *rsaPrivKey;
SECKEYPublicKey *rsaPubKey;
@@ -227,7 +266,10 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
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;
@@ -259,11 +301,15 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
tstTemplate[3].ulValueLen = sizeof(ck_false);
tstTemplate[4].pValue = &ck_false;
tstTemplate[4].ulValueLen = sizeof(ck_false);
- tstHeaderCount = 5;
+ 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,
@@ -271,10 +317,10 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
tstHeaderCount + 2, CKA_PRIME_1);
- tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
- tstHeaderCount +
- 3,
- PR_FALSE);
+ tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
if (tstPrivKey == NULL) {
fprintf(stderr, "RSA Populate failed: pubExp mod p\n");
failed = 1;
@@ -290,6 +336,7 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
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,
@@ -299,10 +346,10 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
/* test with q in the prime1 position */
tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1;
- tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
- tstHeaderCount +
- 3,
- PR_FALSE);
+ tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
if (tstPrivKey == NULL) {
fprintf(stderr, "RSA Populate failed: pubExp mod q\n");
failed = 1;
@@ -318,6 +365,7 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
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);
@@ -329,10 +377,10 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
tstTemplate[tstHeaderCount + 2].type = CKA_PRIME_1;
tstTemplate[tstHeaderCount + 1].type = CKA_PRIME_2;
- tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
- tstHeaderCount +
- 3,
- PR_FALSE);
+ tstPrivKey = PK11_CreateManagedGenericObject(slot, tstTemplate,
+ tstHeaderCount +
+ 3,
+ PR_FALSE);
if (tstPrivKey == NULL) {
fprintf(stderr, "RSA Populate failed: privExp p q\n");
failed = 1;
@@ -348,6 +396,7 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
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,
@@ -355,10 +404,10 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
copyAttribute(PK11_TypePrivKey, rsaPrivKey, tstTemplate,
tstHeaderCount + 2, CKA_PRIME_2);
- tstPrivKey = PK11_CreateGenericObject(slot, tstTemplate,
- tstHeaderCount +
- 3,
- PR_FALSE);
+ 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");
@@ -373,11 +422,12 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
if (tstPrivKey)
PK11_DestroyGenericObject(tstPrivKey);
}
- if (mask & 16) {
+ 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);
@@ -386,6 +436,7 @@ doRSAPopulateTest(unsigned int keySize, unsigned long 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,
@@ -398,9 +449,59 @@ doRSAPopulateTest(unsigned int keySize, unsigned long exponent,
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;
@@ -517,7 +618,7 @@ main(int argc, char **argv)
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, NULL);
+ ret = doRSAPopulateTest(keySize, exponent, mask, i, NULL);
if (ret != 0) {
i++;
break;
@@ -531,5 +632,9 @@ main(int argc, char **argv)
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/cmd/rsapoptst/rsapoptst.gyp b/cmd/rsapoptst/rsapoptst.gyp
new file mode 100644
index 000000000..325a10909
--- /dev/null
+++ b/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',
+ }
+}
diff --git a/lib/nss/nss.def b/lib/nss/nss.def
index c1d2b3104..4f0ade4d0 100644
--- a/lib/nss/nss.def
+++ b/lib/nss/nss.def
@@ -1125,6 +1125,7 @@ CERT_FindCertByNicknameOrEmailAddrForUsageCX;
;+};
;+NSS_3.34 { # NSS 3.34 release
;+ global:
+PK11_CreateManagedGenericObject;
SGN_NewContextWithAlgorithmID;
SEC_SignDataWithAlgorithmID;
SEC_DerSignDataWithAlgorithmID;
diff --git a/lib/pk11wrap/pk11merge.c b/lib/pk11wrap/pk11merge.c
index 8c4c5129a..d14f44c78 100644
--- a/lib/pk11wrap/pk11merge.c
+++ b/lib/pk11wrap/pk11merge.c
@@ -1258,6 +1258,7 @@ pk11_newMergeLogNode(PLArenaPool *arena,
/* initialize it */
obj->slot = slot;
obj->objectID = id;
+ obj->owner = PR_FALSE;
newLog->object = obj;
newLog->error = error;
diff --git a/lib/pk11wrap/pk11obj.c b/lib/pk11wrap/pk11obj.c
index 9e9b611e5..b97caddd4 100644
--- a/lib/pk11wrap/pk11obj.c
+++ b/lib/pk11wrap/pk11obj.c
@@ -1505,6 +1505,7 @@ PK11_FindGenericObjects(PK11SlotInfo *slot, CK_OBJECT_CLASS objClass)
/* initialize it */
obj->slot = PK11_ReferenceSlot(slot);
obj->objectID = objectIDs[i];
+ obj->owner = PR_FALSE;
obj->next = NULL;
obj->prev = NULL;
@@ -1585,6 +1586,9 @@ PK11_DestroyGenericObject(PK11GenericObject *object)
PK11_UnlinkGenericObject(object);
if (object->slot) {
+ if (object->owner) {
+ PK11_DestroyObject(object->slot, object->objectID);
+ }
PK11_FreeSlot(object->slot);
}
PORT_Free(object);
@@ -1626,8 +1630,9 @@ PK11_DestroyGenericObjects(PK11GenericObject *objects)
* Hand Create a new object and return the Generic object for our new object.
*/
PK11GenericObject *
-PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
- int count, PRBool token)
+pk11_CreateGenericObjectHelper(PK11SlotInfo *slot,
+ const CK_ATTRIBUTE *pTemplate,
+ int count, PRBool token, PRBool owner)
{
CK_OBJECT_HANDLE objectID;
PK11GenericObject *obj;
@@ -1651,11 +1656,40 @@ PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
/* initialize it */
obj->slot = PK11_ReferenceSlot(slot);
obj->objectID = objectID;
+ obj->owner = owner;
obj->next = NULL;
obj->prev = NULL;
return obj;
}
+/* This is the classic interface. Applications would call this function to
+ * create new object that would not be destroyed later. This lead to resource
+ * leaks (and thus memory leaks in the PKCS #11 module). To solve this we have
+ * a new interface that automatically marks objects created on the fly to be
+ * destroyed later.
+ * The old interface is preserved because applications like Mozilla purposefully
+ * leak the reference to be found later with PK11_FindGenericObjects. New
+ * applications should use the new interface PK11_CreateManagedGenericObject */
+PK11GenericObject *
+PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
+ int count, PRBool token)
+{
+ return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
+ PR_FALSE);
+}
+
+/* Use this interface. It will automatically destroy any temporary objects
+ * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
+ * need to be destroyed by hand with PK11_DestroyTokenObject.
+ */
+PK11GenericObject *
+PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
+ const CK_ATTRIBUTE *pTemplate, int count, PRBool token)
+{
+ return pk11_CreateGenericObjectHelper(slot, pTemplate, count, token,
+ !token);
+}
+
/*
* Change an attribute on a raw object
*/
diff --git a/lib/pk11wrap/pk11pub.h b/lib/pk11wrap/pk11pub.h
index edfe82f5a..dbd8da092 100644
--- a/lib/pk11wrap/pk11pub.h
+++ b/lib/pk11wrap/pk11pub.h
@@ -831,6 +831,10 @@ SECStatus PK11_LinkGenericObject(PK11GenericObject *list,
PK11GenericObject *object);
SECStatus PK11_DestroyGenericObjects(PK11GenericObject *object);
SECStatus PK11_DestroyGenericObject(PK11GenericObject *object);
+PK11GenericObject *PK11_CreateManagedGenericObject(PK11SlotInfo *slot,
+ const CK_ATTRIBUTE *pTemplate,
+ int count, PRBool token);
+/* deprecated */
PK11GenericObject *PK11_CreateGenericObject(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate,
int count, PRBool token);
diff --git a/lib/pk11wrap/secmodti.h b/lib/pk11wrap/secmodti.h
index 63c207929..260e6387d 100644
--- a/lib/pk11wrap/secmodti.h
+++ b/lib/pk11wrap/secmodti.h
@@ -175,6 +175,7 @@ struct PK11GenericObjectStr {
PK11GenericObject *next;
PK11SlotInfo *slot;
CK_OBJECT_HANDLE objectID;
+ PRBool owner;
};
#define MAX_TEMPL_ATTRS 16 /* maximum attributes in template */
diff --git a/nss.gyp b/nss.gyp
index a52243c1f..9e9b49f7f 100644
--- a/nss.gyp
+++ b/nss.gyp
@@ -148,6 +148,7 @@
'cmd/pk1sign/pk1sign.gyp:pk1sign',
'cmd/pp/pp.gyp:pp',
'cmd/rsaperf/rsaperf.gyp:rsaperf',
+ 'cmd/rsapoptst/rsapoptst.gyp:rsapoptst',
'cmd/sdrtest/sdrtest.gyp:sdrtest',
'cmd/selfserv/selfserv.gyp:selfserv',
'cmd/shlibsign/mangle/mangle.gyp:mangle',
diff --git a/tests/cipher/cipher.sh b/tests/cipher/cipher.sh
index 1d2561d9c..11a621815 100755
--- a/tests/cipher/cipher.sh
+++ b/tests/cipher/cipher.sh
@@ -107,6 +107,21 @@ cipher_gcm()
done < ${GCM_TXT}
}
+###################### cipher_rsa_populate ############################
+# Test the ability to reconstruct rsa private key reconstruction
+# also test the PK11GenericObject interface
+###################################################################
+cipher_rsa_populate()
+{
+ TESTNAME="RSA Reconstruct Private Keys Test"
+ echo "$SCRIPTNAME: $TESTNAME --------------------------------"
+ echo "rsapoptst -t all -r 10"
+# skip e_d_q. It isn't reliable, and can return incorrect data. e_d_q should
+# be turned off.
+ ${PROFTOOL} ${BINDIR}/rsapoptst -t e_n_p,d_n_q,d_p_q,e_d_n -r 10
+ html_msg $? 0 "$TESTNAME"
+}
+
############################## cipher_cleanup ############################
# local shell function to finish this script (no exit since it might be
# sourced)
@@ -136,5 +151,6 @@ fi
# Skip cipher_gcm if this is a softoken only build.
if [ "${NSS_BUILD_SOFTOKEN_ONLY}" != "1" ]; then
cipher_gcm
+ cipher_rsa_populate
fi
cipher_cleanup