diff options
-rw-r--r-- | prsa.c | 150 | ||||
-rw-r--r-- | util.c | 3 |
2 files changed, 110 insertions, 43 deletions
@@ -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; } @@ -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'); |