CngKey CngKey::Import(const ConstBuf& mb, CngKeyBlobFormat format) { const byte *p = mb.P; EVP_PKEY *impl = 0; EC_KEY *ec_key; switch (format) { case CngKeyBlobFormat::OSslEccPrivateBlob: //!!!SslCheck(::d2i_ECPrivateKey((EC_KEY**)&impl, &p, mb.m_len)); impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::d2i_ECPrivateKey(&impl->pkey.ec, &p, mb.Size)); break; case CngKeyBlobFormat::OSslEccPrivateBignum: { impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; OpensslBn bn = OpensslBn::FromBinary(mb); EcPoint ecPoint(::EC_KEY_get0_group(ec_key)); ecPoint.Mul(bn); SslCheck(::EC_KEY_set_private_key(ec_key, bn)); SslCheck(::EC_KEY_set_public_key(ec_key, ecPoint)); } break; case CngKeyBlobFormat::OSslEccPublicBlob: //!!!SslCheck(impl = ::d2i_PublicKey(EVP_PKEY_EC, &impl, &p, mb.m_len)); impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::o2i_ECPublicKey(&impl->pkey.ec, &p, mb.Size)); break; case CngKeyBlobFormat::OSslEccPublicCompressedBlob: impl = ::EVP_PKEY_new(); SslCheck(::EVP_PKEY_set_type(impl, EVP_PKEY_EC)); SslCheck(ec_key = ::EC_KEY_new_by_curve_name(NID_secp256k1)); impl->pkey.ec = ec_key; SslCheck(::o2i_ECPublicKey(&impl->pkey.ec, &p, mb.Size)); ::EC_KEY_set_conv_form(impl->pkey.ec, POINT_CONVERSION_COMPRESSED); break; default: Throw(E_INVALIDARG); } return CngKey(impl); }
nsresult CryptoKey::PrivateKeyToJwk(SECKEYPrivateKey* aPrivKey, JsonWebKey& aRetVal, const nsNSSShutDownPreventionLock& /*proofOfLock*/) { switch (aPrivKey->keyType) { case rsaKey: { aRetVal.mN.Construct(); aRetVal.mE.Construct(); aRetVal.mD.Construct(); aRetVal.mP.Construct(); aRetVal.mQ.Construct(); aRetVal.mDp.Construct(); aRetVal.mDq.Construct(); aRetVal.mQi.Construct(); if (!ReadAndEncodeAttribute(aPrivKey, CKA_MODULUS, aRetVal.mN) || !ReadAndEncodeAttribute(aPrivKey, CKA_PUBLIC_EXPONENT, aRetVal.mE) || !ReadAndEncodeAttribute(aPrivKey, CKA_PRIVATE_EXPONENT, aRetVal.mD) || !ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_1, aRetVal.mP) || !ReadAndEncodeAttribute(aPrivKey, CKA_PRIME_2, aRetVal.mQ) || !ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_1, aRetVal.mDp) || !ReadAndEncodeAttribute(aPrivKey, CKA_EXPONENT_2, aRetVal.mDq) || !ReadAndEncodeAttribute(aPrivKey, CKA_COEFFICIENT, aRetVal.mQi)) { return NS_ERROR_DOM_OPERATION_ERR; } aRetVal.mKty = NS_LITERAL_STRING(JWK_TYPE_RSA); return NS_OK; } case ecKey: { // Read EC params. ScopedSECItem params(::SECITEM_AllocItem(nullptr, nullptr, 0)); SECStatus rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey, CKA_EC_PARAMS, params); if (rv != SECSuccess) { return NS_ERROR_DOM_OPERATION_ERR; } // Read public point Q. ScopedSECItem ecPoint(::SECITEM_AllocItem(nullptr, nullptr, 0)); rv = PK11_ReadRawAttribute(PK11_TypePrivKey, aPrivKey, CKA_EC_POINT, ecPoint); if (rv != SECSuccess) { return NS_ERROR_DOM_OPERATION_ERR; } if (!ECKeyToJwk(PK11_TypePrivKey, aPrivKey, params, ecPoint, aRetVal)) { return NS_ERROR_DOM_OPERATION_ERR; } aRetVal.mD.Construct(); // Read private value. if (!ReadAndEncodeAttribute(aPrivKey, CKA_VALUE, aRetVal.mD)) { return NS_ERROR_DOM_OPERATION_ERR; } return NS_OK; } default: return NS_ERROR_DOM_NOT_SUPPORTED_ERR; } }