SECStatus PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue, PRBool isPerm, PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk, void *wincx) { SECStatus rv = SECFailure; SECKEYRawPrivateKey *lpk = NULL; const SEC_ASN1Template *keyTemplate, *paramTemplate; void *paramDest = NULL; PLArenaPool *arena = NULL; arena = PORT_NewArena(2048); if (!arena) { return SECFailure; } /* need to change this to use RSA/DSA keys */ lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYRawPrivateKey)); if (lpk == NULL) { goto loser; } lpk->arena = arena; switch (SECOID_GetAlgorithmTag(&pki->algorithm)) { case SEC_OID_PKCS1_RSA_ENCRYPTION: prepare_rsa_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_RSAPrivateKeyExportTemplate; paramTemplate = NULL; paramDest = NULL; lpk->keyType = rsaKey; break; case SEC_OID_ANSIX9_DSA_SIGNATURE: prepare_dsa_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_DSAPrivateKeyExportTemplate; paramTemplate = SECKEY_PQGParamsTemplate; paramDest = &(lpk->u.dsa.params); lpk->keyType = dsaKey; break; case SEC_OID_X942_DIFFIE_HELMAN_KEY: if (!publicValue) { goto loser; } prepare_dh_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_DHPrivateKeyExportTemplate; paramTemplate = NULL; paramDest = NULL; lpk->keyType = dhKey; break; case SEC_OID_ANSIX962_EC_PUBLIC_KEY: prepare_ec_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_ECPrivateKeyExportTemplate; paramTemplate = NULL; paramDest = NULL; lpk->keyType = ecKey; break; default: keyTemplate = NULL; paramTemplate = NULL; paramDest = NULL; break; } if (!keyTemplate) { goto loser; } /* decode the private key and any algorithm parameters */ rv = SEC_QuickDERDecodeItem(arena, lpk, keyTemplate, &pki->privateKey); if (rv != SECSuccess) { goto loser; } if (lpk->keyType == ecKey) { /* Convert length in bits to length in bytes. */ lpk->u.ec.publicValue.len >>= 3; /* Always override curveOID, we're ignoring any given value. */ rv = SECITEM_CopyItem(arena, &lpk->u.ec.curveOID, &pki->algorithm.parameters); if (rv != SECSuccess) { goto loser; } }
SECStatus PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue, PRBool isPerm, PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk, void *wincx) { CK_KEY_TYPE keyType = CKK_RSA; SECStatus rv = SECFailure; SECKEYRawPrivateKey *lpk = NULL; const SEC_ASN1Template *keyTemplate, *paramTemplate; void *paramDest = NULL; PRArenaPool *arena; arena = PORT_NewArena(2048); if(!arena) { return SECFailure; } /* need to change this to use RSA/DSA keys */ lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena, sizeof(SECKEYRawPrivateKey)); if(lpk == NULL) { goto loser; } lpk->arena = arena; switch(SECOID_GetAlgorithmTag(&pki->algorithm)) { case SEC_OID_PKCS1_RSA_ENCRYPTION: prepare_rsa_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_RSAPrivateKeyExportTemplate; paramTemplate = NULL; paramDest = NULL; lpk->keyType = rsaKey; keyType = CKK_RSA; break; case SEC_OID_ANSIX9_DSA_SIGNATURE: prepare_dsa_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_DSAPrivateKeyExportTemplate; paramTemplate = SECKEY_PQGParamsTemplate; paramDest = &(lpk->u.dsa.params); lpk->keyType = dsaKey; keyType = CKK_DSA; break; case SEC_OID_X942_DIFFIE_HELMAN_KEY: if(!publicValue) { goto loser; } prepare_dh_priv_key_export_for_asn1(lpk); keyTemplate = SECKEY_DHPrivateKeyExportTemplate; paramTemplate = NULL; paramDest = NULL; lpk->keyType = dhKey; keyType = CKK_DH; break; default: keyTemplate = NULL; paramTemplate = NULL; paramDest = NULL; break; } if(!keyTemplate) { goto loser; } /* decode the private key and any algorithm parameters */ rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey); if(rv != SECSuccess) { goto loser; } if(paramDest && paramTemplate) { rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate, &(pki->algorithm.parameters)); if(rv != SECSuccess) { goto loser; } } rv = PK11_ImportAndReturnPrivateKey(slot,lpk,nickname,publicValue, isPerm, isPrivate, keyUsage, privk, wincx); loser: if (lpk!= NULL) { PORT_FreeArena(arena, PR_TRUE); } return rv; }
/* * 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; }