nsresult CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { ScopedCERTSubjectPublicKeyInfo spki(SECKEY_CreateSubjectPublicKeyInfo(aPubKey)); if (!spki) { return NS_ERROR_DOM_OPERATION_ERR; } // Per WebCrypto spec we must export ECDH SPKIs with the algorithm OID // id-ecDH (1.3.132.112). NSS doesn't know about that OID and there is // no way to specify the algorithm to use when exporting a public key. if (aPubKey->keyType == ecKey) { SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, &SEC_OID_DATA_EC_DH); if (rv != SECSuccess) { return NS_ERROR_DOM_OPERATION_ERR; } } const SEC_ASN1Template* tpl = SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate); ScopedSECItem spkiItem(SEC_ASN1EncodeItem(nullptr, nullptr, spki, tpl)); aRetVal.Assign(spkiItem.get()); return NS_OK; }
SECKEYPublicKey* CryptoKey::PublicKeyFromSpki(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { ScopedSECItem spkiItem(aKeyData.ToSECItem()); if (!spkiItem) { return nullptr; } ScopedCERTSubjectPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(spkiItem.get())); if (!spki) { return nullptr; } // Check for id-ecDH. Per the WebCrypto spec we must support it but NSS // does unfortunately not know about it. Let's change the algorithm to // id-ecPublicKey to make NSS happy. if (SECITEM_ItemsAreEqual(&SEC_OID_DATA_EC_DH, &spki->algorithm.algorithm)) { // Retrieve OID data for id-ecPublicKey (1.2.840.10045.2.1). SECOidData* oidData = SECOID_FindOIDByTag(SEC_OID_ANSIX962_EC_PUBLIC_KEY); if (!oidData) { return nullptr; } SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, &oidData->oid); if (rv != SECSuccess) { return nullptr; } } return SECKEY_ExtractPublicKey(spki.get()); }
nsresult CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { ScopedSECItem spkiItem(PK11_DEREncodePublicKey(aPubKey)); if (!spkiItem.get()) { return NS_ERROR_DOM_INVALID_ACCESS_ERR; } aRetVal.Assign(spkiItem.get()); return NS_OK; }
SECKEYPublicKey* CryptoKey::PublicKeyFromSpki(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { ScopedSECItem spkiItem(aKeyData.ToSECItem()); if (!spkiItem) { return nullptr; } ScopedCERTSubjectPublicKeyInfo spki(SECKEY_DecodeDERSubjectPublicKeyInfo(spkiItem.get())); if (!spki) { return nullptr; } return SECKEY_ExtractPublicKey(spki.get()); }
nsresult CryptoKey::PublicKeyToSpki(SECKEYPublicKey* aPubKey, CryptoBuffer& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { ScopedCERTSubjectPublicKeyInfo spki; // NSS doesn't support exporting DH public keys. if (aPubKey->keyType == dhKey) { // Mimic the behavior of SECKEY_CreateSubjectPublicKeyInfo() and create // a new arena for the SPKI object. ScopedPLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return NS_ERROR_DOM_OPERATION_ERR; } spki = PORT_ArenaZNew(arena, CERTSubjectPublicKeyInfo); if (!spki) { return NS_ERROR_DOM_OPERATION_ERR; } // Assign |arena| to |spki| and null the variable afterwards so that the // arena created above that holds the SPKI object is free'd when |spki| // goes out of scope, not when |arena| does. spki->arena = arena.forget(); nsresult rv = PublicDhKeyToSpki(aPubKey, spki); NS_ENSURE_SUCCESS(rv, rv); } else { spki = SECKEY_CreateSubjectPublicKeyInfo(aPubKey); if (!spki) { return NS_ERROR_DOM_OPERATION_ERR; } } // Per WebCrypto spec we must export ECDH SPKIs with the algorithm OID // id-ecDH (1.3.132.112) and DH SPKIs with OID dhKeyAgreement // (1.2.840.113549.1.3.1). NSS doesn't know about these OIDs and there is // no way to specify the algorithm to use when exporting a public key. if (aPubKey->keyType == ecKey || aPubKey->keyType == dhKey) { const SECItem* oidData = nullptr; if (aPubKey->keyType == ecKey) { oidData = &SEC_OID_DATA_EC_DH; } else if (aPubKey->keyType == dhKey) { oidData = &SEC_OID_DATA_DH_KEY_AGREEMENT; } else { MOZ_ASSERT(false); } SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, oidData); if (rv != SECSuccess) { return NS_ERROR_DOM_OPERATION_ERR; } } const SEC_ASN1Template* tpl = SEC_ASN1_GET(CERT_SubjectPublicKeyInfoTemplate); ScopedSECItem spkiItem(SEC_ASN1EncodeItem(nullptr, nullptr, spki, tpl)); aRetVal.Assign(spkiItem.get()); return NS_OK; }