diff --git a/deps/ncrypto/ncrypto.cc b/deps/ncrypto/ncrypto.cc index eb3533bb4623b1..fe7c6980a1e76b 100644 --- a/deps/ncrypto/ncrypto.cc +++ b/deps/ncrypto/ncrypto.cc @@ -1384,4 +1384,213 @@ DataPointer pbkdf2(const EVP_MD* md, return {}; } +// ============================================================================ + +EVPKeyPointer EVPKeyPointer::New() { + return EVPKeyPointer(EVP_PKEY_new()); +} + +EVPKeyPointer EVPKeyPointer::NewRawPublic(int id, const Buffer& data) { + if (id == 0) return {}; + return EVPKeyPointer(EVP_PKEY_new_raw_public_key(id, nullptr, data.data, data.len)); +} + +EVPKeyPointer EVPKeyPointer::NewRawPrivate(int id, const Buffer& data) { + if (id == 0) return {}; + return EVPKeyPointer(EVP_PKEY_new_raw_private_key(id, nullptr, data.data, data.len)); +} + +EVPKeyPointer::EVPKeyPointer(EVP_PKEY* pkey) : pkey_(pkey) {} + +EVPKeyPointer::EVPKeyPointer(EVPKeyPointer&& other) noexcept + : pkey_(other.release()) {} + +EVPKeyPointer& EVPKeyPointer::operator=(EVPKeyPointer&& other) noexcept { + if (this == &other) return *this; + this->~EVPKeyPointer(); + return *new (this) EVPKeyPointer(std::move(other)); +} + +EVPKeyPointer::~EVPKeyPointer() { reset(); } + +void EVPKeyPointer::reset(EVP_PKEY* pkey) { + pkey_.reset(pkey); +} + +EVP_PKEY* EVPKeyPointer::release() { + return pkey_.release(); +} + +int EVPKeyPointer::id(const EVP_PKEY* key) { + if (key == nullptr) return 0; + return EVP_PKEY_id(key); +} + +int EVPKeyPointer::base_id(const EVP_PKEY* key) { + if (key == nullptr) return 0; + return EVP_PKEY_base_id(key); +} + +int EVPKeyPointer::id() const { + return id(get()); +} + +int EVPKeyPointer::base_id() const { + return base_id(get()); +} + +int EVPKeyPointer::bits() const { + if (get() == nullptr) return 0; + return EVP_PKEY_bits(get()); +} + +size_t EVPKeyPointer::size() const { + if (get() == nullptr) return 0; + return EVP_PKEY_size(get()); +} + +EVPKeyCtxPointer EVPKeyPointer::newCtx() const { + if (!pkey_) return {}; + return EVPKeyCtxPointer(EVP_PKEY_CTX_new(get(), nullptr)); +} + +size_t EVPKeyPointer::rawPublicKeySize() const { + if (!pkey_) return 0; + size_t len = 0; + if (EVP_PKEY_get_raw_public_key(get(), nullptr, &len) == 1) return len; + return 0; +} + +size_t EVPKeyPointer::rawPrivateKeySize() const { + if (!pkey_) return 0; + size_t len = 0; + if (EVP_PKEY_get_raw_private_key(get(), nullptr, &len) == 1) return len; + return 0; +} + +DataPointer EVPKeyPointer::rawPublicKey() const { + if (!pkey_) return {}; + if (auto data = DataPointer::Alloc(rawPublicKeySize())) { + const Buffer buf = data; + size_t len = data.size(); + if (EVP_PKEY_get_raw_public_key(get(), + buf.data, + &len) != 1) return {}; + return data; + } + return {}; +} + +DataPointer EVPKeyPointer::rawPrivateKey() const { + if (!pkey_) return {}; + if (auto data = DataPointer::Alloc(rawPrivateKeySize())) { + const Buffer buf = data; + size_t len = data.size(); + if (EVP_PKEY_get_raw_private_key(get(), + buf.data, + &len) != 1) return {}; + return data; + } + return {}; +} + +BIOPointer EVPKeyPointer::derPublicKey() const { + if (!pkey_) return {}; + auto bio = BIOPointer::NewMem(); + if (!bio) return {}; + if (!i2d_PUBKEY_bio(bio.get(), get())) return {}; + return bio; +} + +namespace { +EVPKeyPointer::ParseKeyResult TryParsePublicKeyInner( + const BIOPointer& bp, + const char* name, + auto&& parse) { + if (!bp.resetBio()) { + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer::PKParseError::FAILED); + } + unsigned char* der_data; + long der_len; + + // This skips surrounding data and decodes PEM to DER. + { + MarkPopErrorOnReturn mark_pop_error_on_return; + if (PEM_bytes_read_bio(&der_data, &der_len, nullptr, name, + bp.get(), nullptr, nullptr) != 1) + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer::PKParseError::NOT_RECOGNIZED); + } + DataPointer data(der_data, der_len); + + // OpenSSL might modify the pointer, so we need to make a copy before parsing. + const unsigned char* p = der_data; + EVPKeyPointer pkey(parse(&p, der_len)); + if (!pkey) return EVPKeyPointer::ParseKeyResult(EVPKeyPointer::PKParseError::FAILED); + return EVPKeyPointer::ParseKeyResult(std::move(pkey)); +} + +EVPKeyPointer::ParseKeyResult TryParsePublicKeyPEM( + const Buffer& buffer) { + auto bp = BIOPointer::New(buffer.data, buffer.len); + if (!bp) + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer::PKParseError::FAILED); + + // Try parsing as SubjectPublicKeyInfo (SPKI) first. + if (auto ret = TryParsePublicKeyInner(bp, "PUBLIC KEY", + [](const unsigned char** p, long l) { // NOLINT(runtime/int) + return d2i_PUBKEY(nullptr, p, l); + })) { + return ret; + } + + // Maybe it is PKCS#1. + if (auto ret = TryParsePublicKeyInner(bp, "RSA PUBLIC KEY", + [](const unsigned char** p, long l) { // NOLINT(runtime/int) + return d2i_PublicKey(EVP_PKEY_RSA, nullptr, p, l); + })) { + return ret; + } + + // X.509 fallback. + if (auto ret = TryParsePublicKeyInner(bp, "CERTIFICATE", + [](const unsigned char** p, long l) { // NOLINT(runtime/int) + X509Pointer x509(d2i_X509(nullptr, p, l)); + return x509 ? X509_get_pubkey(x509.get()) : nullptr; + })) { + return ret; + }; + + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer::PKParseError::NOT_RECOGNIZED); +} +} // namespace + +EVPKeyPointer::ParseKeyResult EVPKeyPointer::TryParsePublicKey( + PKFormatType format, + PKEncodingType encoding, + const Buffer& buffer) { + if (format == PKFormatType::PEM) { + return TryParsePublicKeyPEM(buffer); + } + + if (format != PKFormatType::DER) { + return ParseKeyResult(PKParseError::FAILED); + } + + const unsigned char* start = buffer.data; + + EVP_PKEY* key = nullptr; + + if (encoding == PKEncodingType::PKCS1 && + (key = d2i_PublicKey(EVP_PKEY_RSA, nullptr, &start, buffer.len))) { + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer(key)); + } + + if (encoding == PKEncodingType::SPKI && + (key = d2i_PUBKEY(nullptr, &start, buffer.len))) { + return EVPKeyPointer::ParseKeyResult(EVPKeyPointer(key)); + } + + return ParseKeyResult(PKParseError::FAILED); +} + } // namespace ncrypto diff --git a/deps/ncrypto/ncrypto.h b/deps/ncrypto/ncrypto.h index 60bfce3ea8999e..6a77b291937a61 100644 --- a/deps/ncrypto/ncrypto.h +++ b/deps/ncrypto/ncrypto.h @@ -172,12 +172,16 @@ class MarkPopErrorOnReturn final { CryptoErrorList* errors_; }; +// TODO(@jasnell): Eventually replace with std::expected when we are able to +// bump up to c++23. template struct Result final { + const bool has_value; T value; std::optional error; - Result(T&& value) : value(std::move(value)) {} - Result(E&& error) : error(std::move(error)) {} + Result(T&& value) : has_value(true), value(std::move(value)) {} + Result(E&& error) : has_value(false), error(std::move(error)) {} + inline operator bool() const { return has_value; } }; // ============================================================================ @@ -202,7 +206,6 @@ using ECGroupPointer = DeleteFnPtr; using ECKeyPointer = DeleteFnPtr; using ECPointPointer = DeleteFnPtr; using EVPKeyCtxPointer = DeleteFnPtr; -using EVPKeyPointer = DeleteFnPtr; using EVPMDCtxPointer = DeleteFnPtr; using HMACCtxPointer = DeleteFnPtr; using NetscapeSPKIPointer = DeleteFnPtr; @@ -252,9 +255,10 @@ class DataPointer final { Buffer release(); // Returns a Buffer struct that is a view of the underlying data. - inline operator const Buffer() const { + template + inline operator const Buffer() const { return { - .data = data_, + .data = static_cast(data_), .len = len_, }; } @@ -359,6 +363,75 @@ class BignumPointer final { DeleteFnPtr bn_; }; +class EVPKeyPointer final { +public: + static EVPKeyPointer New(); + static EVPKeyPointer NewRawPublic(int id, const Buffer& data); + static EVPKeyPointer NewRawPrivate(int id, const Buffer& data); + + enum class PKEncodingType { + // RSAPublicKey / RSAPrivateKey according to PKCS#1. + PKCS1, + // PrivateKeyInfo or EncryptedPrivateKeyInfo according to PKCS#8. + PKCS8, + // SubjectPublicKeyInfo according to X.509. + SPKI, + // ECPrivateKey according to SEC1. + SEC1 + }; + + enum class PKFormatType { + DER, + PEM, + JWK + }; + + enum class PKParseError { + NOT_RECOGNIZED, + NEED_PASSPHRASE, + FAILED + }; + using ParseKeyResult = Result; + + static ParseKeyResult TryParsePublicKey( + PKFormatType format, + PKEncodingType encoding, + const Buffer& buffer); + + EVPKeyPointer() = default; + explicit EVPKeyPointer(EVP_PKEY* pkey); + EVPKeyPointer(EVPKeyPointer&& other) noexcept; + EVPKeyPointer& operator=(EVPKeyPointer&& other) noexcept; + NCRYPTO_DISALLOW_COPY(EVPKeyPointer) + ~EVPKeyPointer(); + + inline bool operator==(std::nullptr_t) const noexcept { return pkey_ == nullptr; } + inline operator bool() const { return pkey_ != nullptr; } + inline EVP_PKEY* get() const { return pkey_.get(); } + void reset(EVP_PKEY* pkey = nullptr); + EVP_PKEY* release(); + + static int id(const EVP_PKEY* key); + static int base_id(const EVP_PKEY* key); + + int id() const; + int base_id() const; + int bits() const; + size_t size() const; + + size_t rawPublicKeySize() const; + size_t rawPrivateKeySize() const; + DataPointer rawPublicKey() const; + DataPointer rawPrivateKey() const; + + BIOPointer derPublicKey() const; + + EVPKeyCtxPointer newCtx() const; + +private: + DeleteFnPtr pkey_; +}; + class DHPointer final { public: diff --git a/src/crypto/crypto_cipher.cc b/src/crypto/crypto_cipher.cc index 54c210f6dde727..f4ff63ca429e48 100644 --- a/src/crypto/crypto_cipher.cc +++ b/src/crypto/crypto_cipher.cc @@ -995,7 +995,7 @@ bool PublicKeyCipher::Cipher( const ArrayBufferOrViewContents& oaep_label, const ArrayBufferOrViewContents& data, std::unique_ptr* out) { - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + EVPKeyCtxPointer ctx = pkey.newCtx(); if (!ctx) return false; if (EVP_PKEY_cipher_init(ctx.get()) <= 0) @@ -1071,7 +1071,7 @@ void PublicKeyCipher::Cipher(const FunctionCallbackInfo& args) { if (EVP_PKEY_cipher == EVP_PKEY_decrypt && operation == PublicKeyCipher::kPrivate && padding == RSA_PKCS1_PADDING) { - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + EVPKeyCtxPointer ctx = pkey.newCtx(); CHECK(ctx); if (EVP_PKEY_decrypt_init(ctx.get()) <= 0) { diff --git a/src/crypto/crypto_common.cc b/src/crypto/crypto_common.cc index 6a967702b22df0..43a126f863779d 100644 --- a/src/crypto/crypto_common.cc +++ b/src/crypto/crypto_common.cc @@ -449,15 +449,14 @@ MaybeLocal GetEphemeralKey(Environment* env, const SSLPointer& ssl) { Local context = env->context(); crypto::EVPKeyPointer key(raw_key); - int kid = EVP_PKEY_id(key.get()); - int bits = EVP_PKEY_bits(key.get()); + int kid = key.id(); switch (kid) { case EVP_PKEY_DH: if (!Set(context, info, env->type_string(), env->dh_string()) || !Set(context, - info, - env->size_string(), - Integer::New(env->isolate(), bits))) { + info, + env->size_string(), + Integer::New(env->isolate(), key.bits()))) { return MaybeLocal(); } break; @@ -473,18 +472,16 @@ MaybeLocal GetEphemeralKey(Environment* env, const SSLPointer& ssl) { } else { curve_name = OBJ_nid2sn(kid); } - if (!Set(context, - info, - env->type_string(), - env->ecdh_string()) || + if (!Set( + context, info, env->type_string(), env->ecdh_string()) || !Set(context, - info, - env->name_string(), - OneByteString(env->isolate(), curve_name)) || + info, + env->name_string(), + OneByteString(env->isolate(), curve_name)) || !Set(context, - info, - env->size_string(), - Integer::New(env->isolate(), bits))) { + info, + env->size_string(), + Integer::New(env->isolate(), key.bits()))) { return MaybeLocal(); } } diff --git a/src/crypto/crypto_dh.cc b/src/crypto/crypto_dh.cc index e5664dfa2bc7e1..01ca96a0289d7f 100644 --- a/src/crypto/crypto_dh.cc +++ b/src/crypto/crypto_dh.cc @@ -395,7 +395,7 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) { auto dh = DHPointer::New(std::move(prime), std::move(bn_g)); if (!dh) return {}; - key_params = EVPKeyPointer(EVP_PKEY_new()); + key_params = EVPKeyPointer::New(); CHECK(key_params); CHECK_EQ(EVP_PKEY_assign_DH(key_params.get(), dh.release()), 1); } else if (int* prime_size = std::get_if(¶ms->params.prime)) { @@ -418,7 +418,7 @@ EVPKeyCtxPointer DhKeyGenTraits::Setup(DhKeyPairGenConfig* params) { UNREACHABLE(); } - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr)); + EVPKeyCtxPointer ctx = key_params.newCtx(); if (!ctx || EVP_PKEY_keygen_init(ctx.get()) <= 0) return {}; return ctx; @@ -533,7 +533,7 @@ bool DHBitsTraits::DeriveBits( Maybe GetDhKeyDetail(Environment* env, const KeyObjectData& key, Local target) { - CHECK_EQ(EVP_PKEY_id(key.GetAsymmetricKey().get()), EVP_PKEY_DH); + CHECK_EQ(key.GetAsymmetricKey().id(), EVP_PKEY_DH); return JustVoid(); } diff --git a/src/crypto/crypto_dsa.cc b/src/crypto/crypto_dsa.cc index 5d081863cf2dcd..b557de774117e4 100644 --- a/src/crypto/crypto_dsa.cc +++ b/src/crypto/crypto_dsa.cc @@ -60,7 +60,7 @@ EVPKeyCtxPointer DsaKeyGenTraits::Setup(DsaKeyPairGenConfig* params) { return EVPKeyCtxPointer(); EVPKeyPointer key_params(raw_params); - EVPKeyCtxPointer key_ctx(EVP_PKEY_CTX_new(key_params.get(), nullptr)); + EVPKeyCtxPointer key_ctx = key_params.newCtx(); if (!key_ctx || EVP_PKEY_keygen_init(key_ctx.get()) <= 0) return EVPKeyCtxPointer(); @@ -134,7 +134,7 @@ Maybe GetDsaKeyDetail(Environment* env, Mutex::ScopedLock lock(key.mutex()); const auto& m_pkey = key.GetAsymmetricKey(); - int type = EVP_PKEY_id(m_pkey.get()); + int type = m_pkey.id(); CHECK(type == EVP_PKEY_DSA); const DSA* dsa = EVP_PKEY_get0_DSA(m_pkey.get()); diff --git a/src/crypto/crypto_ec.cc b/src/crypto/crypto_ec.cc index 0c021eab60d509..d1572d66449acb 100644 --- a/src/crypto/crypto_ec.cc +++ b/src/crypto/crypto_ec.cc @@ -486,10 +486,7 @@ bool ECDHBitsTraits::DeriveBits(Environment* env, case EVP_PKEY_X25519: // Fall through case EVP_PKEY_X448: { - EVPKeyCtxPointer ctx = nullptr; - { - ctx.reset(EVP_PKEY_CTX_new(m_privkey.get(), nullptr)); - } + EVPKeyCtxPointer ctx = m_privkey.newCtx(); Mutex::ScopedLock pub_lock(params.public_.mutex()); if (EVP_PKEY_derive_init(ctx.get()) <= 0 || EVP_PKEY_derive_set_peer( @@ -568,7 +565,7 @@ EVPKeyCtxPointer EcKeyGenTraits::Setup(EcKeyPairGenConfig* params) { return EVPKeyCtxPointer(); } EVPKeyPointer key_params(raw_params); - key_ctx.reset(EVP_PKEY_CTX_new(key_params.get(), nullptr)); + key_ctx = key_params.newCtx(); } } @@ -626,29 +623,23 @@ WebCryptoKeyExportStatus EC_Raw_Export(const KeyObjectData& key_data, const EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(m_pkey.get()); - size_t len = 0; - if (ec_key == nullptr) { - typedef int (*export_fn)(const EVP_PKEY*, unsigned char*, size_t* len); - export_fn fn = nullptr; switch (key_data.GetKeyType()) { - case kKeyTypePrivate: - fn = EVP_PKEY_get_raw_private_key; + case kKeyTypePrivate: { + auto data = m_pkey.rawPrivateKey(); + if (!data) return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; + *out = ByteSource::Allocated(data.release()); break; - case kKeyTypePublic: - fn = EVP_PKEY_get_raw_public_key; + } + case kKeyTypePublic: { + auto data = m_pkey.rawPublicKey(); + if (!data) return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; + *out = ByteSource::Allocated(data.release()); break; + } case kKeyTypeSecret: UNREACHABLE(); } - CHECK_NOT_NULL(fn); - // Get the size of the raw key data - if (fn(m_pkey.get(), nullptr, &len) == 0) - return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; - ByteSource::Builder data(len); - if (fn(m_pkey.get(), data.data(), &len) == 0) - return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; - *out = std::move(data).release(len); } else { if (key_data.GetKeyType() != kKeyTypePublic) return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; @@ -657,7 +648,7 @@ WebCryptoKeyExportStatus EC_Raw_Export(const KeyObjectData& key_data, point_conversion_form_t form = POINT_CONVERSION_UNCOMPRESSED; // Get the allocated data size... - len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr); + size_t len = EC_POINT_point2oct(group, point, form, nullptr, 0, nullptr); if (len == 0) return WebCryptoKeyExportStatus::FAILED; ByteSource::Builder data(len); @@ -700,7 +691,7 @@ WebCryptoKeyExportStatus ECKeyExportTraits::DoExport( return WebCryptoKeyExportStatus::INVALID_KEY_TYPE; const auto& m_pkey = key_data.GetAsymmetricKey(); - if (EVP_PKEY_id(m_pkey.get()) != EVP_PKEY_EC) { + if (m_pkey.id() != EVP_PKEY_EC) { return PKEY_SPKI_Export(key_data, out); } else { // Ensure exported key is in uncompressed point format. @@ -730,12 +721,10 @@ WebCryptoKeyExportStatus ECKeyExportTraits::DoExport( data.size(), nullptr)); CHECK_EQ(1, EC_KEY_set_public_key(ec.get(), uncompressed.get())); - EVPKeyPointer pkey(EVP_PKEY_new()); + auto pkey = EVPKeyPointer::New(); CHECK_EQ(1, EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get())); - auto bio = BIOPointer::NewMem(); - CHECK(bio); - if (!i2d_PUBKEY_bio(bio.get(), pkey.get())) - return WebCryptoKeyExportStatus::FAILED; + auto bio = pkey.derPublicKey(); + if (!bio) return WebCryptoKeyExportStatus::FAILED; *out = ByteSource::FromBIO(bio); return WebCryptoKeyExportStatus::OK; } @@ -750,7 +739,7 @@ Maybe ExportJWKEcKey(Environment* env, Local target) { Mutex::ScopedLock lock(key.mutex()); const auto& m_pkey = key.GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); + CHECK_EQ(m_pkey.id(), EVP_PKEY_EC); const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); @@ -835,67 +824,49 @@ Maybe ExportJWKEdKey(Environment* env, Mutex::ScopedLock lock(key.mutex()); const auto& pkey = key.GetAsymmetricKey(); - const char* curve = nullptr; - switch (EVP_PKEY_id(pkey.get())) { - case EVP_PKEY_ED25519: - curve = "Ed25519"; - break; - case EVP_PKEY_ED448: - curve = "Ed448"; - break; - case EVP_PKEY_X25519: - curve = "X25519"; - break; - case EVP_PKEY_X448: - curve = "X448"; - break; - default: - UNREACHABLE(); - } - if (target->Set( - env->context(), - env->jwk_crv_string(), - OneByteString(env->isolate(), curve)).IsNothing()) { - return Nothing(); - } - - size_t len = 0; - Local encoded; - Local error; - - if (!EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &len)) - return Nothing(); - - ByteSource::Builder out(len); - - if (key.GetKeyType() == kKeyTypePrivate) { - if (!EVP_PKEY_get_raw_private_key( - pkey.get(), out.data(), &len) || - !StringBytes::Encode( - env->isolate(), out.data(), len, BASE64URL, &error) + const char* curve = ([&] { + switch (pkey.id()) { + case EVP_PKEY_ED25519: + return "Ed25519"; + case EVP_PKEY_ED448: + return "Ed448"; + case EVP_PKEY_X25519: + return "X25519"; + case EVP_PKEY_X448: + return "X448"; + default: + UNREACHABLE(); + } + })(); + + static constexpr auto trySetKey = [](Environment* env, + ncrypto::DataPointer data, + Local target, + Local key) { + Local encoded; + Local error; + if (!data) return false; + const ncrypto::Buffer out = data; + if (!StringBytes::Encode( + env->isolate(), out.data, out.len, BASE64URL, &error) .ToLocal(&encoded) || - !target->Set(env->context(), env->jwk_d_string(), encoded).IsJust()) { - if (!error.IsEmpty()) - env->isolate()->ThrowException(error); - return Nothing(); + target->Set(env->context(), key, encoded).IsNothing()) { + if (!error.IsEmpty()) env->isolate()->ThrowException(error); + return false; } - } - - if (!EVP_PKEY_get_raw_public_key( - pkey.get(), out.data(), &len) || - !StringBytes::Encode( - env->isolate(), out.data(), len, BASE64URL, &error) - .ToLocal(&encoded) || - !target->Set(env->context(), env->jwk_x_string(), encoded).IsJust()) { - if (!error.IsEmpty()) - env->isolate()->ThrowException(error); - return Nothing(); - } + return true; + }; - if (target->Set( - env->context(), - env->jwk_kty_string(), - env->jwk_okp_string()).IsNothing()) { + if (target + ->Set(env->context(), + env->jwk_crv_string(), + OneByteString(env->isolate(), curve)) + .IsNothing() || + (key.GetKeyType() == kKeyTypePrivate && + !trySetKey(env, pkey.rawPrivateKey(), target, env->jwk_d_string())) || + !trySetKey(env, pkey.rawPublicKey(), target, env->jwk_x_string()) || + target->Set(env->context(), env->jwk_kty_string(), env->jwk_okp_string()) + .IsNothing()) { return Nothing(); } @@ -959,7 +930,7 @@ KeyObjectData ImportJWKEcKey(Environment* env, } } - EVPKeyPointer pkey(EVP_PKEY_new()); + auto pkey = EVPKeyPointer::New(); CHECK_EQ(EVP_PKEY_set1_EC_KEY(pkey.get(), ec.get()), 1); return KeyObjectData::CreateAsymmetric(type, std::move(pkey)); @@ -970,7 +941,7 @@ Maybe GetEcKeyDetail(Environment* env, Local target) { Mutex::ScopedLock lock(key.mutex()); const auto& m_pkey = key.GetAsymmetricKey(); - CHECK_EQ(EVP_PKEY_id(m_pkey.get()), EVP_PKEY_EC); + CHECK_EQ(m_pkey.id(), EVP_PKEY_EC); const EC_KEY* ec = EVP_PKEY_get0_EC_KEY(m_pkey.get()); CHECK_NOT_NULL(ec); diff --git a/src/crypto/crypto_keys.cc b/src/crypto/crypto_keys.cc index 1d280ddd068835..ab307df85b6f80 100644 --- a/src/crypto/crypto_keys.cc +++ b/src/crypto/crypto_keys.cc @@ -60,8 +60,8 @@ void GetKeyFormatAndTypeFromJs( args[*offset].As()->Value()); if (args[*offset + 1]->IsInt32()) { - config->type_ = Just(static_cast( - args[*offset + 1].As()->Value())); + config->type_ = + static_cast(args[*offset + 1].As()->Value()); } else { CHECK( (context == kKeyContextInput && @@ -69,7 +69,7 @@ void GetKeyFormatAndTypeFromJs( (context == kKeyContextGenerate && config->format_ == kKeyFormatJWK)); CHECK(args[*offset + 1]->IsNullOrUndefined()); - config->type_ = Nothing(); + config->type_ = std::nullopt; } } @@ -140,22 +140,18 @@ ParseKeyResult ParsePublicKey(EVPKeyPointer* pkey, const PublicKeyEncodingConfig& config, const char* key, size_t key_len) { - if (config.format_ == kKeyFormatPEM) { - return ParsePublicKeyPEM(pkey, key, key_len); - } else { - CHECK_EQ(config.format_, kKeyFormatDER); - - const unsigned char* p = reinterpret_cast(key); - if (config.type_.ToChecked() == kKeyEncodingPKCS1) { - pkey->reset(d2i_PublicKey(EVP_PKEY_RSA, nullptr, &p, key_len)); - } else { - CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI); - pkey->reset(d2i_PUBKEY(nullptr, &p, key_len)); - } + auto res = EVPKeyPointer::TryParsePublicKey( + static_cast(config.format_), + static_cast(config.type_.value()), + ncrypto::Buffer{ + .data = reinterpret_cast(key), + .len = key_len, + }); + if (!res) return static_cast(res.error.value()); - return *pkey ? ParseKeyResult::kParseKeyOk : - ParseKeyResult::kParseKeyFailed; - } + CHECK(res.has_value); + *pkey = std::move(res.value); + return ParseKeyResult::kParseKeyOk; } bool IsASN1Sequence(const unsigned char* data, size_t size, @@ -229,10 +225,10 @@ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey, } else { CHECK_EQ(config.format_, kKeyFormatDER); - if (config.type_.ToChecked() == kKeyEncodingPKCS1) { + if (config.type_.value() == kKeyEncodingPKCS1) { const unsigned char* p = reinterpret_cast(key); pkey->reset(d2i_PrivateKey(EVP_PKEY_RSA, nullptr, &p, key_len)); - } else if (config.type_.ToChecked() == kKeyEncodingPKCS8) { + } else if (config.type_.value() == kKeyEncodingPKCS8) { auto bio = BIOPointer::New(key, key_len); if (!bio) return ParseKeyResult::kParseKeyFailed; @@ -249,7 +245,7 @@ ParseKeyResult ParsePrivateKey(EVPKeyPointer* pkey, pkey->reset(EVP_PKCS82PKEY(p8inf.get())); } } else { - CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSEC1); + CHECK_EQ(config.type_.value(), kKeyEncodingSEC1); const unsigned char* p = reinterpret_cast(key); pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len)); } @@ -318,10 +314,10 @@ MaybeLocal WritePrivateKey(Environment* env, MarkPopErrorOnReturn mark_pop_error_on_return; bool err; - PKEncodingType encoding_type = config.type_.ToChecked(); + PKEncodingType encoding_type = config.type_.value(); if (encoding_type == kKeyEncodingPKCS1) { // PKCS#1 is only permitted for RSA keys. - CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA); + CHECK_EQ(EVPKeyPointer::id(pkey), EVP_PKEY_RSA); OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(pkey); if (config.format_ == kKeyFormatPEM) { @@ -362,7 +358,7 @@ MaybeLocal WritePrivateKey(Environment* env, CHECK_EQ(encoding_type, kKeyEncodingSEC1); // SEC1 is only permitted for EC keys. - CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_EC); + CHECK_EQ(EVPKeyPointer::id(pkey), EVP_PKEY_EC); OSSL3_CONST EC_KEY* ec_key = EVP_PKEY_get0_EC_KEY(pkey); if (config.format_ == kKeyFormatPEM) { @@ -392,9 +388,9 @@ MaybeLocal WritePrivateKey(Environment* env, bool WritePublicKeyInner(OSSL3_CONST EVP_PKEY* pkey, const BIOPointer& bio, const PublicKeyEncodingConfig& config) { - if (config.type_.ToChecked() == kKeyEncodingPKCS1) { + if (config.type_.value() == kKeyEncodingPKCS1) { // PKCS#1 is only valid for RSA keys. - CHECK_EQ(EVP_PKEY_id(pkey), EVP_PKEY_RSA); + CHECK_EQ(EVPKeyPointer::id(pkey), EVP_PKEY_RSA); OSSL3_CONST RSA* rsa = EVP_PKEY_get0_RSA(pkey); if (config.format_ == kKeyFormatPEM) { // Encode PKCS#1 as PEM. @@ -405,7 +401,7 @@ bool WritePublicKeyInner(OSSL3_CONST EVP_PKEY* pkey, return i2d_RSAPublicKey_bio(bio.get(), rsa) == 1; } } else { - CHECK_EQ(config.type_.ToChecked(), kKeyEncodingSPKI); + CHECK_EQ(config.type_.value(), kKeyEncodingSPKI); if (config.format_ == kKeyFormatPEM) { // Encode SPKI as PEM. return PEM_write_bio_PUBKEY(bio.get(), pkey) == 1; @@ -480,7 +476,7 @@ Maybe ExportJWKAsymmetricKey(Environment* env, const KeyObjectData& key, Local target, bool handleRsaPss) { - switch (EVP_PKEY_id(key.GetAsymmetricKey().get())) { + switch (key.GetAsymmetricKey().id()) { case EVP_PKEY_RSA_PSS: { if (handleRsaPss) return ExportJWKRsaKey(env, key, target); break; @@ -535,7 +531,7 @@ Maybe GetSecretKeyDetail(Environment* env, Maybe GetAsymmetricKeyDetail(Environment* env, const KeyObjectData& key, Local target) { - switch (EVP_PKEY_id(key.GetAsymmetricKey().get())) { + switch (key.GetAsymmetricKey().id()) { case EVP_PKEY_RSA: // Fall through case EVP_PKEY_RSA_PSS: return GetRsaKeyDetail(env, key, target); @@ -723,32 +719,34 @@ KeyObjectData KeyObjectData::GetPublicOrPrivateKeyFromJs( type = KeyType::kKeyTypePrivate; ret = ParsePrivateKey(&pkey, config, data.data(), data.size()); } - } else { - // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are - // easy, but PKCS#1 can be a public key or a private key. - bool is_public; - switch (config.type_.ToChecked()) { - case kKeyEncodingPKCS1: - is_public = !IsRSAPrivateKey( - reinterpret_cast(data.data()), data.size()); - break; - case kKeyEncodingSPKI: - is_public = true; - break; - case kKeyEncodingPKCS8: - case kKeyEncodingSEC1: - is_public = false; - break; - default: - UNREACHABLE("Invalid key encoding type"); - } + return GetParsedKey( + type, env, std::move(pkey), ret, "Failed to read asymmetric key"); + } - if (is_public) { - ret = ParsePublicKey(&pkey, config, data.data(), data.size()); - } else { - type = KeyType::kKeyTypePrivate; - ret = ParsePrivateKey(&pkey, config, data.data(), data.size()); - } + // For DER, the type determines how to parse it. SPKI, PKCS#8 and SEC1 are + // easy, but PKCS#1 can be a public key or a private key. + bool is_public; + switch (config.type_.value()) { + case kKeyEncodingPKCS1: + is_public = !IsRSAPrivateKey( + reinterpret_cast(data.data()), data.size()); + break; + case kKeyEncodingSPKI: + is_public = true; + break; + case kKeyEncodingPKCS8: + case kKeyEncodingSEC1: + is_public = false; + break; + default: + UNREACHABLE("Invalid key encoding type"); + } + + if (is_public) { + ret = ParsePublicKey(&pkey, config, data.data(), data.size()); + } else { + type = KeyType::kKeyTypePrivate; + ret = ParsePrivateKey(&pkey, config, data.data(), data.size()); } return GetParsedKey( @@ -809,17 +807,10 @@ void KeyObjectData::MemoryInfo(MemoryTracker* tracker) const { // Fall through case kKeyTypePublic: { if (data_->asymmetric_key) { - size_t size = kSizeOf_EVP_PKEY; - size_t len = 0; - if (EVP_PKEY_get_raw_private_key( - data_->asymmetric_key.get(), nullptr, &len) == 1) { - size += len; - } - if (EVP_PKEY_get_raw_public_key( - data_->asymmetric_key.get(), nullptr, &len) == 1) { - size += len; - } - tracker->TrackFieldWithSize("key", size); + tracker->TrackFieldWithSize( + "key", + kSizeOf_EVP_PKEY + data_->asymmetric_key.rawPublicKeySize() + + data_->asymmetric_key.rawPrivateKeySize()); } break; } @@ -1047,7 +1038,7 @@ void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo& args) { return args.GetReturnValue().Set(false); } - EVPKeyPointer pkey(EVP_PKEY_new()); + auto pkey = EVPKeyPointer::New(); if (!EVP_PKEY_assign_EC_KEY(pkey.get(), eckey.get())) args.GetReturnValue().Set(false); @@ -1071,10 +1062,10 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo& args) { MarkPopErrorOnReturn mark_pop_error_on_return; - typedef EVP_PKEY* (*new_key_fn)(int, ENGINE*, const unsigned char*, size_t); - new_key_fn fn = type == kKeyTypePrivate - ? EVP_PKEY_new_raw_private_key - : EVP_PKEY_new_raw_public_key; + typedef EVPKeyPointer (*new_key_fn)( + int, const ncrypto::Buffer&); + new_key_fn fn = type == kKeyTypePrivate ? EVPKeyPointer::NewRawPrivate + : EVPKeyPointer::NewRawPublic; int id = GetOKPCurveFromName(*name); @@ -1083,9 +1074,14 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo& args) { case EVP_PKEY_X448: case EVP_PKEY_ED25519: case EVP_PKEY_ED448: { - EVPKeyPointer pkey(fn(id, nullptr, key_data.data(), key_data.size())); - if (!pkey) + auto pkey = fn(id, + ncrypto::Buffer{ + .data = key_data.data(), + .len = key_data.size(), + }); + if (!pkey) { return args.GetReturnValue().Set(false); + } key->data_ = KeyObjectData::CreateAsymmetric(type, std::move(pkey)); CHECK(key->data_); break; @@ -1171,28 +1167,27 @@ void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo& args) { } Local KeyObjectHandle::GetAsymmetricKeyType() const { - const auto& key = data_.GetAsymmetricKey(); - switch (EVP_PKEY_id(key.get())) { - case EVP_PKEY_RSA: - return env()->crypto_rsa_string(); - case EVP_PKEY_RSA_PSS: - return env()->crypto_rsa_pss_string(); - case EVP_PKEY_DSA: - return env()->crypto_dsa_string(); - case EVP_PKEY_DH: - return env()->crypto_dh_string(); - case EVP_PKEY_EC: - return env()->crypto_ec_string(); - case EVP_PKEY_ED25519: - return env()->crypto_ed25519_string(); - case EVP_PKEY_ED448: - return env()->crypto_ed448_string(); - case EVP_PKEY_X25519: - return env()->crypto_x25519_string(); - case EVP_PKEY_X448: - return env()->crypto_x448_string(); - default: - return Undefined(env()->isolate()); + switch (data_.GetAsymmetricKey().id()) { + case EVP_PKEY_RSA: + return env()->crypto_rsa_string(); + case EVP_PKEY_RSA_PSS: + return env()->crypto_rsa_pss_string(); + case EVP_PKEY_DSA: + return env()->crypto_dsa_string(); + case EVP_PKEY_DH: + return env()->crypto_dh_string(); + case EVP_PKEY_EC: + return env()->crypto_ec_string(); + case EVP_PKEY_ED25519: + return env()->crypto_ed25519_string(); + case EVP_PKEY_ED448: + return env()->crypto_ed448_string(); + case EVP_PKEY_X25519: + return env()->crypto_x25519_string(); + case EVP_PKEY_X448: + return env()->crypto_x448_string(); + default: + return Undefined(env()->isolate()); } } @@ -1208,9 +1203,9 @@ bool KeyObjectHandle::CheckEcKeyData() const { MarkPopErrorOnReturn mark_pop_error_on_return; const auto& key = data_.GetAsymmetricKey(); - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(key.get(), nullptr)); + EVPKeyCtxPointer ctx = key.newCtx(); CHECK(ctx); - CHECK_EQ(EVP_PKEY_id(key.get()), EVP_PKEY_EC); + CHECK_EQ(key.id(), EVP_PKEY_EC); if (data_.GetKeyType() == kKeyTypePrivate) { return EVP_PKEY_check(ctx.get()) == 1; @@ -1409,12 +1404,8 @@ WebCryptoKeyExportStatus PKEY_SPKI_Export(const KeyObjectData& key_data, ByteSource* out) { CHECK_EQ(key_data.GetKeyType(), kKeyTypePublic); Mutex::ScopedLock lock(key_data.mutex()); - const auto& m_pkey = key_data.GetAsymmetricKey(); - auto bio = BIOPointer::NewMem(); - CHECK(bio); - if (!i2d_PUBKEY_bio(bio.get(), m_pkey.get())) - return WebCryptoKeyExportStatus::FAILED; - + auto bio = key_data.GetAsymmetricKey().derPublicKey(); + if (!bio) return WebCryptoKeyExportStatus::FAILED; *out = ByteSource::FromBIO(bio); return WebCryptoKeyExportStatus::OK; } diff --git a/src/crypto/crypto_keys.h b/src/crypto/crypto_keys.h index efc6d583dccdea..fd7ff00b21c8e2 100644 --- a/src/crypto/crypto_keys.h +++ b/src/crypto/crypto_keys.h @@ -18,21 +18,23 @@ namespace node { namespace crypto { +// TODO(@jasnell): These static casts are temporarily while this code +// is being shifted over into ncrypto enum PKEncodingType { // RSAPublicKey / RSAPrivateKey according to PKCS#1. - kKeyEncodingPKCS1, + kKeyEncodingPKCS1 = static_cast(EVPKeyPointer::PKEncodingType::PKCS1), // PrivateKeyInfo or EncryptedPrivateKeyInfo according to PKCS#8. - kKeyEncodingPKCS8, + kKeyEncodingPKCS8 = static_cast(EVPKeyPointer::PKEncodingType::PKCS8), // SubjectPublicKeyInfo according to X.509. - kKeyEncodingSPKI, + kKeyEncodingSPKI = static_cast(EVPKeyPointer::PKEncodingType::SPKI), // ECPrivateKey according to SEC1. - kKeyEncodingSEC1 + kKeyEncodingSEC1 = static_cast(EVPKeyPointer::PKEncodingType::SEC1), }; enum PKFormatType { - kKeyFormatDER, - kKeyFormatPEM, - kKeyFormatJWK + kKeyFormatDER = static_cast(EVPKeyPointer::PKFormatType::DER), + kKeyFormatPEM = static_cast(EVPKeyPointer::PKFormatType::PEM), + kKeyFormatJWK = static_cast(EVPKeyPointer::PKFormatType::JWK), }; enum KeyType { @@ -48,16 +50,18 @@ enum KeyEncodingContext { }; enum class ParseKeyResult { + kParseKeyNotRecognized = + static_cast(EVPKeyPointer::PKParseError::NOT_RECOGNIZED), + kParseKeyNeedPassphrase = + static_cast(EVPKeyPointer::PKParseError::NEED_PASSPHRASE), + kParseKeyFailed = static_cast(EVPKeyPointer::PKParseError::FAILED), kParseKeyOk, - kParseKeyNotRecognized, - kParseKeyNeedPassphrase, - kParseKeyFailed }; struct AsymmetricKeyEncodingConfig { bool output_key_object_ = false; PKFormatType format_ = kKeyFormatDER; - v8::Maybe type_ = v8::Nothing(); + std::optional type_ = std::nullopt; }; using PublicKeyEncodingConfig = AsymmetricKeyEncodingConfig; diff --git a/src/crypto/crypto_rsa.cc b/src/crypto/crypto_rsa.cc index 02e8e24b4054af..1711ab69531cc1 100644 --- a/src/crypto/crypto_rsa.cc +++ b/src/crypto/crypto_rsa.cc @@ -203,7 +203,7 @@ WebCryptoCipherStatus RSA_Cipher(Environment* env, Mutex::ScopedLock lock(key_data.mutex()); const auto& m_pkey = key_data.GetAsymmetricKey(); - EVPKeyCtxPointer ctx(EVP_PKEY_CTX_new(m_pkey.get(), nullptr)); + EVPKeyCtxPointer ctx = m_pkey.newCtx(); if (!ctx || init(ctx.get()) <= 0) return WebCryptoCipherStatus::FAILED; @@ -360,7 +360,7 @@ Maybe ExportJWKRsaKey(Environment* env, Local target) { Mutex::ScopedLock lock(key.mutex()); const auto& m_pkey = key.GetAsymmetricKey(); - int type = EVP_PKEY_id(m_pkey.get()); + int type = m_pkey.id(); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL @@ -493,7 +493,7 @@ KeyObjectData ImportJWKRsaKey(Environment* env, } } - EVPKeyPointer pkey(EVP_PKEY_new()); + auto pkey = EVPKeyPointer::New(); CHECK_EQ(EVP_PKEY_set1_RSA(pkey.get(), rsa.get()), 1); return KeyObjectData::CreateAsymmetric(type, std::move(pkey)); @@ -507,7 +507,7 @@ Maybe GetRsaKeyDetail(Environment* env, Mutex::ScopedLock lock(key.mutex()); const auto& m_pkey = key.GetAsymmetricKey(); - int type = EVP_PKEY_id(m_pkey.get()); + int type = m_pkey.id(); CHECK(type == EVP_PKEY_RSA || type == EVP_PKEY_RSA_PSS); // TODO(tniessen): Remove the "else" branch once we drop support for OpenSSL diff --git a/src/crypto/crypto_sig.cc b/src/crypto/crypto_sig.cc index 903ab29cd7e701..0c531b9b49cac8 100644 --- a/src/crypto/crypto_sig.cc +++ b/src/crypto/crypto_sig.cc @@ -34,11 +34,11 @@ namespace crypto { namespace { bool ValidateDSAParameters(EVP_PKEY* key) { /* Validate DSA2 parameters from FIPS 186-4 */ + auto id = EVPKeyPointer::base_id(key); #if OPENSSL_VERSION_MAJOR >= 3 - if (EVP_default_properties_is_fips_enabled(nullptr) && - EVP_PKEY_DSA == EVP_PKEY_base_id(key)) { + if (EVP_default_properties_is_fips_enabled(nullptr) && EVP_PKEY_DSA == id) { #else - if (FIPS_mode() && EVP_PKEY_DSA == EVP_PKEY_base_id(key)) { + if (FIPS_mode() && EVP_PKEY_DSA == id) { #endif const DSA* dsa = EVP_PKEY_get0_DSA(key); const BIGNUM* p; @@ -60,9 +60,8 @@ bool ApplyRSAOptions(const EVPKeyPointer& pkey, EVP_PKEY_CTX* pkctx, int padding, const Maybe& salt_len) { - if (EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA || - EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA2 || - EVP_PKEY_id(pkey.get()) == EVP_PKEY_RSA_PSS) { + int id = pkey.id(); + if (id == EVP_PKEY_RSA || id == EVP_PKEY_RSA2 || id == EVP_PKEY_RSA_PSS) { if (EVP_PKEY_CTX_set_rsa_padding(pkctx, padding) <= 0) return false; if (padding == RSA_PKCS1_PSS_PADDING && salt_len.IsJust()) { @@ -85,15 +84,13 @@ std::unique_ptr Node_SignFinal(Environment* env, if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return nullptr; - int signed_sig_len = EVP_PKEY_size(pkey.get()); - CHECK_GE(signed_sig_len, 0); - size_t sig_len = static_cast(signed_sig_len); + size_t sig_len = pkey.size(); std::unique_ptr sig; { NoArrayBufferZeroFillScope no_zero_fill_scope(env->isolate_data()); sig = ArrayBuffer::NewBackingStore(env->isolate(), sig_len); } - EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + EVPKeyCtxPointer pkctx = pkey.newCtx(); if (pkctx && EVP_PKEY_sign_init(pkctx.get()) > 0 && ApplyRSAOptions(pkey, pkctx.get(), padding, pss_salt_len) && EVP_PKEY_CTX_set_signature_md(pkctx.get(), EVP_MD_CTX_md(mdctx.get())) > @@ -120,12 +117,12 @@ std::unique_ptr Node_SignFinal(Environment* env, } int GetDefaultSignPadding(const EVPKeyPointer& m_pkey) { - return EVP_PKEY_id(m_pkey.get()) == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING : - RSA_PKCS1_PADDING; + return m_pkey.id() == EVP_PKEY_RSA_PSS ? RSA_PKCS1_PSS_PADDING + : RSA_PKCS1_PADDING; } unsigned int GetBytesOfRS(const EVPKeyPointer& pkey) { - int bits, base_id = EVP_PKEY_base_id(pkey.get()); + int bits, base_id = pkey.base_id(); if (base_id == EVP_PKEY_DSA) { const DSA* dsa_key = EVP_PKEY_get0_DSA(pkey.get()); @@ -274,23 +271,12 @@ void CheckThrow(Environment* env, SignBase::Error error) { } bool IsOneShot(const EVPKeyPointer& key) { - switch (EVP_PKEY_id(key.get())) { - case EVP_PKEY_ED25519: - case EVP_PKEY_ED448: - return true; - default: - return false; - } + return key.id() == EVP_PKEY_ED25519 || key.id() == EVP_PKEY_ED448; } bool UseP1363Encoding(const EVPKeyPointer& key, const DSASigEnc& dsa_encoding) { - switch (EVP_PKEY_id(key.get())) { - case EVP_PKEY_EC: - case EVP_PKEY_DSA: - return dsa_encoding == kSigEncP1363; - default: - return false; - } + return (key.id() == EVP_PKEY_EC || key.id() == EVP_PKEY_DSA) && + dsa_encoding == kSigEncP1363; } } // namespace @@ -530,7 +516,7 @@ SignBase::Error Verify::VerifyFinal(const EVPKeyPointer& pkey, if (!EVP_DigestFinal_ex(mdctx.get(), m, &m_len)) return kSignPublicKey; - EVPKeyCtxPointer pkctx(EVP_PKEY_CTX_new(pkey.get(), nullptr)); + EVPKeyCtxPointer pkctx = pkey.newCtx(); if (pkctx) { const int init_ret = EVP_PKEY_verify_init(pkctx.get()); if (init_ret == -2) {