Implement PK11_ExportDERPrivateKeyInfo, PK11_ExportPrivKeyInfo, and
authorWan-Teh Chang <wtc@google.com>
Tue, 01 Apr 2014 15:54:33 -0700
changeset 11104 a751a5146718ee9d6fb43e7d0cea470c7dfa2856
parent 11103 05b6c5bad4e478877f0acd59ebbd0327c00a93c8
child 11105 84ec42d1a6bc68611596bc9808a1aaf70ed03888
push id353
push userwtc@google.com
push dateTue, 01 Apr 2014 22:54:38 +0000
Implement PK11_ExportDERPrivateKeyInfo, PK11_ExportPrivKeyInfo, and PK11_ExportPrivateKeyInfo (was exported but not implemented). r=eroman,sleevi.
lib/nss/nss.def
lib/pk11wrap/pk11akey.c
lib/pk11wrap/pk11pk12.c
lib/pk11wrap/pk11pub.h
--- a/lib/nss/nss.def
+++ b/lib/nss/nss.def
@@ -1040,8 +1040,15 @@ CERT_AddCertToListHead;
 ;+NSS_3.15.4 { 	# NSS 3.15.4 release
 ;+    global:
 CERT_ForcePostMethodForOCSP;
 CERT_GetSubjectNameDigest;
 CERT_GetSubjectPublicKeyDigest;
 ;+    local:
 ;+       *;
 ;+};
+;+NSS_3.16.1 { 	# NSS 3.16.1 release
+;+    global:
+PK11_ExportDERPrivateKeyInfo;
+PK11_ExportPrivKeyInfo;
+;+    local:
+;+       *;
+;+};
--- a/lib/pk11wrap/pk11akey.c
+++ b/lib/pk11wrap/pk11akey.c
@@ -1708,17 +1708,23 @@ done:
     }
 
     return rv;
 }
 
 SECKEYPrivateKeyInfo *
 PK11_ExportPrivateKeyInfo(CERTCertificate *cert, void *wincx)
 {
-    return NULL;
+    SECKEYPrivateKeyInfo *pki = NULL;
+    SECKEYPrivateKey     *pk  = PK11_FindKeyByAnyCert(cert, wincx);
+    if (pk != NULL) {
+	pki = PK11_ExportPrivKeyInfo(pk, wincx);
+	SECKEY_DestroyPrivateKey(pk);
+    }
+    return pki;
 }
 
 SECKEYEncryptedPrivateKeyInfo * 
 PK11_ExportEncryptedPrivKeyInfo(
    PK11SlotInfo     *slot,      /* optional, encrypt key in this slot */
    SECOidTag         algTag,    /* encrypt key with this algorithm */
    SECItem          *pwitem,    /* password for PBE encryption */
    SECKEYPrivateKey *pk,        /* encrypt this private key */
--- a/lib/pk11wrap/pk11pk12.c
+++ b/lib/pk11wrap/pk11pk12.c
@@ -13,16 +13,17 @@
 #include "secmodi.h"
 #include "pkcs11.h"
 #include "pk11func.h"
 #include "secitem.h"
 #include "key.h"
 #include "secoid.h"
 #include "secasn1.h"
 #include "secerr.h"
+#include "prerror.h"
 
 
 
 /* These data structures should move to a common .h file shared between the
  * wrappers and the pkcs 12 code. */
 
 /*
 ** RSA Raw Private Key structures
@@ -511,8 +512,117 @@ PK11_ImportPrivateKeyInfo(PK11SlotInfo *
 	SECItem *nickname, SECItem *publicValue, PRBool isPerm, 
 	PRBool isPrivate, unsigned int keyUsage, void *wincx) 
 {
     return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
 	publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
 
 }
 
+SECItem *
+PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
+{
+    SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
+    SECItem *derPKI;
+
+    if (!pki) {
+        return NULL;
+    }
+    derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki,
+                                SECKEY_PrivateKeyInfoTemplate);
+    SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);
+    return derPKI;
+}
+
+static PRBool
+ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
+              PLArenaPool *arena, SECItem *output)
+{
+    SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type,
+                                      arena, output);
+    return rv == SECSuccess;
+}
+
+/*
+ * The caller is responsible for freeing the return value by passing it to
+ * SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE).
+ */
+SECKEYPrivateKeyInfo *
+PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
+{
+    /* PrivateKeyInfo version (always zero) */
+    const unsigned char pkiVersion = 0;
+    /* RSAPrivateKey version (always zero) */
+    const unsigned char rsaVersion = 0;
+    PLArenaPool *arena = NULL;
+    SECKEYRawPrivateKey rawKey;
+    SECKEYPrivateKeyInfo *pki;
+    SECItem *encoded;
+    SECStatus rv;
+
+    if (pk->keyType != rsaKey) {
+        PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
+        goto loser;
+    }
+
+    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+        goto loser;
+    }
+    memset(&rawKey, 0, sizeof(rawKey));
+    rawKey.keyType = pk->keyType;
+    rawKey.u.rsa.version.type = siUnsignedInteger;
+    rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
+    if (!rawKey.u.rsa.version.data) {
+        goto loser;
+    }
+    rawKey.u.rsa.version.data[0] = rsaVersion;
+    rawKey.u.rsa.version.len = 1;
+
+    /* Read the component attributes of the private key */
+    prepare_rsa_priv_key_export_for_asn1(&rawKey);
+    if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) ||
+        !ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena,
+                       &rawKey.u.rsa.publicExponent) ||
+        !ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena,
+                       &rawKey.u.rsa.privateExponent) ||
+        !ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) ||
+        !ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) ||
+        !ReadAttribute(pk, CKA_EXPONENT_1, arena,
+                       &rawKey.u.rsa.exponent1) ||
+        !ReadAttribute(pk, CKA_EXPONENT_2, arena,
+                       &rawKey.u.rsa.exponent2) ||
+        !ReadAttribute(pk, CKA_COEFFICIENT, arena,
+                       &rawKey.u.rsa.coefficient)) {
+        goto loser;
+    }
+
+    pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo);
+    if (!pki) {
+        goto loser;
+    }
+    encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey,
+                                 SECKEY_RSAPrivateKeyExportTemplate);
+    if (!encoded) {
+        goto loser;
+    }
+    rv = SECOID_SetAlgorithmID(arena, &pki->algorithm,
+                               SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
+    if (rv != SECSuccess) {
+        goto loser;
+    }
+    pki->version.type = siUnsignedInteger;
+    pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
+    if (!pki->version.data) {
+        goto loser;
+    }
+    pki->version.data[0] = pkiVersion;
+    pki->version.len = 1;
+    pki->arena = arena;
+
+    return pki;
+
+loser:
+    if (arena) {
+        PORT_FreeArena(arena, PR_TRUE);
+    }
+    return NULL;
+}
--- a/lib/pk11wrap/pk11pub.h
+++ b/lib/pk11wrap/pk11pub.h
@@ -554,16 +554,19 @@ SECStatus PK11_ImportEncryptedPrivateKey
 		SECItem *nickname, SECItem *publicValue, PRBool isPerm,
 		PRBool isPrivate, KeyType type, 
 		unsigned int usage, void *wincx);
 SECStatus PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, 
 		SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem, 
 		SECItem *nickname, SECItem *publicValue, PRBool isPerm,
 		PRBool isPrivate, KeyType type, 
 		unsigned int usage, SECKEYPrivateKey** privk, void *wincx);
+SECItem *PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx);
+SECKEYPrivateKeyInfo *PK11_ExportPrivKeyInfo(
+		SECKEYPrivateKey *pk, void *wincx);
 SECKEYPrivateKeyInfo *PK11_ExportPrivateKeyInfo(
 		CERTCertificate *cert, void *wincx);
 SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivKeyInfo(
 		PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
 		SECKEYPrivateKey *pk, int iteration, void *wincx);
 SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivateKeyInfo(
 		PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
 		CERTCertificate *cert, int iteration, void *wincx);