nss/0001-Add-support-for-PKCS-8-encoded-private-keys.patch

238 lines
8.5 KiB
Diff
Raw Normal View History

From 8bd0a0427e034262ff982fed98ca5e8c623165db Mon Sep 17 00:00:00 2001
From: Rich Megginson <rmeggins@redhat.com>
Date: Mon, 12 Jul 2010 16:31:01 -0600
Subject: [PATCH] Add support for PKCS#8 encoded private keys
The code supports PKCS#1 encoded RSA private keys that begin with the
BEGIN RSA PRIVATE KEY header in PEM files. This patch adds support for
RSA private keys encoded in PEM files that begin with the header
BEGIN PRIVATE KEY which are in PKCS#8 format.
---
prsa.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++------------------
util.c | 3 +-
2 files changed, 110 insertions(+), 43 deletions(-)
diff --git a/prsa.c b/prsa.c
index 5b2f379..8d4fb92 100644
--- a/mozilla/security/nss/lib/ckfw/pem/prsa.c
+++ b/mozilla/security/nss/lib/ckfw/pem/prsa.c
@@ -63,6 +63,35 @@ const SEC_ASN1Template pem_RSAPrivateKeyTemplate[] = {
{0}
};
+static const SEC_ASN1Template pem_AttributeTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYAttribute) },
+ { SEC_ASN1_OBJECT_ID, offsetof(NSSLOWKEYAttribute, attrType) },
+ { SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(NSSLOWKEYAttribute, attrValue),
+ SEC_ASN1_SUB(SEC_AnyTemplate) },
+ { 0 }
+};
+
+static const SEC_ASN1Template pem_SetOfAttributeTemplate[] = {
+ { SEC_ASN1_SET_OF, 0, pem_AttributeTemplate },
+};
+
+const SEC_ASN1Template pem_PrivateKeyInfoTemplate[] = {
+ { SEC_ASN1_SEQUENCE,
+ 0, NULL, sizeof(NSSLOWKEYPrivateKeyInfo) },
+ { SEC_ASN1_INTEGER,
+ offsetof(NSSLOWKEYPrivateKeyInfo,version) },
+ { SEC_ASN1_INLINE | SEC_ASN1_XTRN,
+ offsetof(NSSLOWKEYPrivateKeyInfo,algorithm),
+ SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
+ { SEC_ASN1_OCTET_STRING,
+ offsetof(NSSLOWKEYPrivateKeyInfo,privateKey) },
+ { SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
+ offsetof(NSSLOWKEYPrivateKeyInfo, attributes),
+ pem_SetOfAttributeTemplate },
+ { 0 }
+};
+
/* Declarations */
SECStatus pem_RSA_Sign(pemLOWKEYPrivateKey * key, unsigned char *output,
unsigned int *outputLen, unsigned int maxOutputLen,
@@ -116,6 +145,79 @@ pem_DestroyPrivateKey(pemLOWKEYPrivateKey * privk)
nss_ZFreeIf(privk);
}
+/* decode and parse the rawkey into the lpk structure */
+static pemLOWKEYPrivateKey *
+pem_getPrivateKey(PLArenaPool *arena, SECItem *rawkey, CK_RV * pError, NSSItem *modulus)
+{
+ pemLOWKEYPrivateKey *lpk = NULL;
+ SECStatus rv = SECFailure;
+ NSSLOWKEYPrivateKeyInfo *pki = NULL;
+ SECItem *keysrc = NULL;
+
+ /* make sure SECOID is initialized - not sure why we have to do this outside of nss_Init */
+ if (SECSuccess != (rv = SECOID_Init())) {
+ *pError = CKR_GENERAL_ERROR;
+ return NULL; /* wha???? */
+ }
+
+ pki = (NSSLOWKEYPrivateKeyInfo*)PORT_ArenaZAlloc(arena,
+ sizeof(NSSLOWKEYPrivateKeyInfo));
+ if(!pki) {
+ *pError = CKR_HOST_MEMORY;
+ goto done;
+ }
+
+ /* let's first see if this is a "raw" RSA private key or an RSA private key in PKCS#8 format */
+ rv = SEC_ASN1DecodeItem(arena, pki, pem_PrivateKeyInfoTemplate, rawkey);
+ if (rv != SECSuccess) {
+ /* not PKCS#8 - assume it's a "raw" RSA private key */
+ keysrc = rawkey;
+ } else if (SECOID_GetAlgorithmTag(&pki->algorithm) == SEC_OID_PKCS1_RSA_ENCRYPTION) {
+ keysrc = &pki->privateKey;
+ } else { /* unsupported */
+ *pError = CKR_FUNCTION_NOT_SUPPORTED;
+ goto done;
+ }
+
+ lpk = (pemLOWKEYPrivateKey *) nss_ZAlloc(NULL,
+ sizeof(pemLOWKEYPrivateKey));
+ if (lpk == NULL) {
+ *pError = CKR_HOST_MEMORY;
+ goto done;
+ }
+
+ lpk->arena = arena;
+ lpk->keyType = pemLOWKEYRSAKey;
+ prepare_low_rsa_priv_key_for_asn1(lpk);
+
+ /* I don't know what this is supposed to accomplish. We free the old
+ modulus data and set it again, making a copy of the new data.
+ But we just allocated a new empty key structure above with
+ nss_ZAlloc. So lpk->u.rsa.modulus.data is NULL and
+ lpk->u.rsa.modulus.len. If the intention is to free the old
+ modulus data, why not just set it to NULL after freeing? Why
+ go through this unnecessary and confusing copying code?
+ */
+ if (modulus) {
+ nss_ZFreeIf(modulus->data);
+ modulus->data = (void *) nss_ZAlloc(NULL, lpk->u.rsa.modulus.len);
+ modulus->size = lpk->u.rsa.modulus.len;
+ nsslibc_memcpy(modulus->data, lpk->u.rsa.modulus.data,
+ lpk->u.rsa.modulus.len);
+ }
+
+ /* decode the private key and any algorithm parameters */
+ rv = SEC_QuickDERDecodeItem(arena, lpk, pem_RSAPrivateKeyTemplate,
+ keysrc);
+
+ if (rv != SECSuccess) {
+ goto done;
+ }
+
+done:
+ return lpk;
+}
+
void
pem_PopulateModulusExponent(pemInternalObject * io)
{
@@ -123,7 +225,7 @@ pem_PopulateModulusExponent(pemInternalObject * io)
const NSSItem *keyType = pem_FetchAttribute(io, CKA_KEY_TYPE);
pemLOWKEYPrivateKey *lpk = NULL;
PLArenaPool *arena;
- SECStatus rv;
+ CK_RV pError = 0;
/* make sure we have the right objects */
if (((const NSSItem *) NULL == classItem) ||
@@ -140,26 +242,12 @@ pem_PopulateModulusExponent(pemInternalObject * io)
return;
}
- lpk = (pemLOWKEYPrivateKey *) nss_ZAlloc(NULL,
- sizeof(pemLOWKEYPrivateKey));
+ lpk = pem_getPrivateKey(arena, io->u.key.key.privateKey, &pError, NULL);
if (lpk == NULL) {
PORT_FreeArena(arena, PR_FALSE);
return;
}
- lpk->arena = arena;
- lpk->keyType = pemLOWKEYRSAKey;
- prepare_low_rsa_priv_key_for_asn1(lpk);
-
- /* decode the private key and any algorithm parameters */
- rv = SEC_QuickDERDecodeItem(arena, lpk, pem_RSAPrivateKeyTemplate,
- io->u.key.key.privateKey);
-
- if (rv != SECSuccess) {
- PORT_FreeArena(arena, PR_FALSE);
- return;
- }
-
nss_ZFreeIf(io->u.key.key.modulus.data);
io->u.key.key.modulus.data =
(void *) nss_ZAlloc(NULL, lpk->u.rsa.modulus.len);
@@ -252,13 +340,6 @@ pem_mdCryptoOperationRSAPriv_Create
pemInternalCryptoOperationRSAPriv *iOperation;
pemLOWKEYPrivateKey *lpk = NULL;
PLArenaPool *arena;
- SECStatus rv;
-
- arena = PORT_NewArena(2048);
- if (!arena) {
- *pError = CKR_HOST_MEMORY;
- return (NSSCKMDCryptoOperation *) NULL;
- }
/* make sure we have the right objects */
if (((const NSSItem *) NULL == classItem) ||
@@ -271,30 +352,15 @@ pem_mdCryptoOperationRSAPriv_Create
return (NSSCKMDCryptoOperation *) NULL;
}
- lpk = (pemLOWKEYPrivateKey *) nss_ZAlloc(NULL,
- sizeof (pemLOWKEYPrivateKey));
- if (lpk == NULL) {
+ arena = PORT_NewArena(2048);
+ if (!arena) {
*pError = CKR_HOST_MEMORY;
return (NSSCKMDCryptoOperation *) NULL;
}
- lpk->arena = arena;
- lpk->keyType = pemLOWKEYRSAKey;
- prepare_low_rsa_priv_key_for_asn1(lpk);
- nss_ZFreeIf(iKey->u.key.key.modulus.data);
- iKey->u.key.key.modulus.data =
- (void *) nss_ZAlloc(NULL, lpk->u.rsa.modulus.len);
- iKey->u.key.key.modulus.size = lpk->u.rsa.modulus.len;
- nsslibc_memcpy(iKey->u.key.key.modulus.data, lpk->u.rsa.modulus.data,
- lpk->u.rsa.modulus.len);
-
- /* decode the private key and any algorithm parameters */
- rv = SEC_QuickDERDecodeItem(arena, lpk, pem_RSAPrivateKeyTemplate,
- iKey->u.key.key.privateKey);
-
- if (rv != SECSuccess) {
+ lpk = pem_getPrivateKey(arena, iKey->u.key.key.privateKey, pError, &iKey->u.key.key.modulus);
+ if (lpk == NULL) {
PORT_FreeArena(arena, PR_FALSE);
- *pError = CKR_HOST_MEMORY;
return (NSSCKMDCryptoOperation *) NULL;
}
diff --git a/util.c b/util.c
index a6ca094..d02ee87 100644
--- a/mozilla/security/nss/lib/ckfw/pem/util.c
+++ b/mozilla/security/nss/lib/ckfw/pem/util.c
@@ -164,7 +164,8 @@ ReadDERFromFile(SECItem *** derlist, char *filename, PRBool ascii,
int key = 0;
while ((asc) && ((body = strstr(asc, "-----BEGIN")) != NULL)) {
key = 0;
- if (strncmp(body, "-----BEGIN RSA PRIVATE KEY", 25) == 0) {
+ if ((strncmp(body, "-----BEGIN RSA PRIVATE KEY", 25) == 0) ||
+ (strncmp(body, "-----BEGIN PRIVATE KEY", 21) == 0)) {
key = 1;
c = body;
body = strchr(body, '\n');
--
1.5.5.6