UniqueSECKEYPublicKey CryptoKey::PublicDhKeyFromRaw(CryptoBuffer& aKeyData, const CryptoBuffer& aPrime, const CryptoBuffer& aGenerator, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECKEYPublicKey* key = PORT_ArenaZNew(arena.get(), SECKEYPublicKey); if (!key) { return nullptr; } key->keyType = dhKey; key->pkcs11Slot = nullptr; key->pkcs11ID = CK_INVALID_HANDLE; // Set DH public key params. if (!aPrime.ToSECItem(arena.get(), &key->u.dh.prime) || !aGenerator.ToSECItem(arena.get(), &key->u.dh.base) || !aKeyData.ToSECItem(arena.get(), &key->u.dh.publicValue)) { return nullptr; } key->u.dh.prime.type = siUnsignedInteger; key->u.dh.base.type = siUnsignedInteger; key->u.dh.publicValue.type = siUnsignedInteger; return UniqueSECKEYPublicKey(SECKEY_CopyPublicKey(key)); }
UniqueSECKEYPrivateKey CryptoKey::PrivateKeyFromPkcs8(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { UniquePK11SlotInfo slot(PK11_GetInternalSlot()); if (!slot) { return nullptr; } UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECItem pkcs8Item = { siBuffer, nullptr, 0 }; if (!aKeyData.ToSECItem(arena.get(), &pkcs8Item)) { return nullptr; } // Allow everything, we enforce usage ourselves unsigned int usage = KU_ALL; SECKEYPrivateKey* privKey; SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey( slot.get(), &pkcs8Item, nullptr, nullptr, false, false, usage, &privKey, nullptr); if (rv == SECFailure) { return nullptr; } return UniqueSECKEYPrivateKey(privKey); }
UniqueSECKEYPublicKey CryptoKey::PublicKeyFromSpki(CryptoBuffer& aKeyData, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECItem spkiItem = { siBuffer, nullptr, 0 }; if (!aKeyData.ToSECItem(arena.get(), &spkiItem)) { return nullptr; } UniqueCERTSubjectPublicKeyInfo spki( SECKEY_DecodeDERSubjectPublicKeyInfo(&spkiItem)); if (!spki) { return nullptr; } bool isECDHAlgorithm = SECITEM_ItemsAreEqual(&SEC_OID_DATA_EC_DH, &spki->algorithm.algorithm); bool isDHAlgorithm = SECITEM_ItemsAreEqual(&SEC_OID_DATA_DH_KEY_AGREEMENT, &spki->algorithm.algorithm); // Check for |id-ecDH| and |dhKeyAgreement|. Per the WebCrypto spec we must // support these OIDs but NSS does unfortunately not know about them. Let's // change the algorithm to |id-ecPublicKey| or |dhPublicKey| to make NSS happy. if (isECDHAlgorithm || isDHAlgorithm) { SECOidTag oid = SEC_OID_UNKNOWN; if (isECDHAlgorithm) { oid = SEC_OID_ANSIX962_EC_PUBLIC_KEY; } else if (isDHAlgorithm) { oid = SEC_OID_X942_DIFFIE_HELMAN_KEY; } else { MOZ_ASSERT(false); } SECOidData* oidData = SECOID_FindOIDByTag(oid); if (!oidData) { return nullptr; } SECStatus rv = SECITEM_CopyItem(spki->arena, &spki->algorithm.algorithm, &oidData->oid); if (rv != SECSuccess) { return nullptr; } } UniqueSECKEYPublicKey tmp(SECKEY_ExtractPublicKey(spki.get())); if (!tmp.get() || !PublicKeyValid(tmp.get())) { return nullptr; } return UniqueSECKEYPublicKey(SECKEY_CopyPublicKey(tmp.get())); }
UniqueSECKEYPublicKey CryptoKey::PublicECKeyFromRaw(CryptoBuffer& aKeyData, const nsString& aNamedCurve, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { UniquePLArenaPool arena(PORT_NewArena(DER_DEFAULT_CHUNKSIZE)); if (!arena) { return nullptr; } SECItem rawItem = { siBuffer, nullptr, 0 }; if (!aKeyData.ToSECItem(arena.get(), &rawItem)) { return nullptr; } uint32_t flen; if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P256)) { flen = 32; // bytes } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P384)) { flen = 48; // bytes } else if (aNamedCurve.EqualsLiteral(WEBCRYPTO_NAMED_CURVE_P521)) { flen = 66; // bytes } else { return nullptr; } // Check length of uncompressed point coordinates. There are 2 field elements // and a leading point form octet (which must EC_POINT_FORM_UNCOMPRESSED). if (rawItem.len != (2 * flen + 1)) { return nullptr; } // No support for compressed points. if (rawItem.data[0] != EC_POINT_FORM_UNCOMPRESSED) { return nullptr; } return CreateECPublicKey(&rawItem, aNamedCurve); }