src: move evp stuff to ncrypto

PR-URL: https://github.com/nodejs/node/pull/54911
Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com>
This commit is contained in:
James M Snell 2024-09-12 09:55:29 -07:00
parent 6a6c957be7
commit c4681d55ae
11 changed files with 492 additions and 262 deletions

View File

@ -1425,4 +1425,213 @@ DataPointer pbkdf2(const EVP_MD* md,
return {};
}
// ============================================================================
EVPKeyPointer EVPKeyPointer::New() {
return EVPKeyPointer(EVP_PKEY_new());
}
EVPKeyPointer EVPKeyPointer::NewRawPublic(int id, const Buffer<const unsigned char>& 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<const unsigned char>& 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<unsigned char> 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<unsigned char> 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<const unsigned char>& 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<const unsigned char>& 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

View File

@ -172,12 +172,16 @@ private:
CryptoErrorList* errors_;
};
// TODO(@jasnell): Eventually replace with std::expected when we are able to
// bump up to c++23.
template <typename T, typename E>
struct Result final {
const bool has_value;
T value;
std::optional<E> 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<EC_GROUP, EC_GROUP_free>;
using ECKeyPointer = DeleteFnPtr<EC_KEY, EC_KEY_free>;
using ECPointPointer = DeleteFnPtr<EC_POINT, EC_POINT_free>;
using EVPKeyCtxPointer = DeleteFnPtr<EVP_PKEY_CTX, EVP_PKEY_CTX_free>;
using EVPKeyPointer = DeleteFnPtr<EVP_PKEY, EVP_PKEY_free>;
using EVPMDCtxPointer = DeleteFnPtr<EVP_MD_CTX, EVP_MD_CTX_free>;
using HMACCtxPointer = DeleteFnPtr<HMAC_CTX, HMAC_CTX_free>;
using NetscapeSPKIPointer = DeleteFnPtr<NETSCAPE_SPKI, NETSCAPE_SPKI_free>;
@ -252,9 +255,10 @@ class DataPointer final {
Buffer<void> release();
// Returns a Buffer struct that is a view of the underlying data.
inline operator const Buffer<void>() const {
template <typename T = void>
inline operator const Buffer<T>() const {
return {
.data = data_,
.data = static_cast<T*>(data_),
.len = len_,
};
}
@ -359,6 +363,75 @@ class BignumPointer final {
DeleteFnPtr<BIGNUM, BN_clear_free> bn_;
};
class EVPKeyPointer final {
public:
static EVPKeyPointer New();
static EVPKeyPointer NewRawPublic(int id, const Buffer<const unsigned char>& data);
static EVPKeyPointer NewRawPrivate(int id, const Buffer<const unsigned char>& 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<EVPKeyPointer, PKParseError>;
static ParseKeyResult TryParsePublicKey(
PKFormatType format,
PKEncodingType encoding,
const Buffer<const unsigned char>& 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<EVP_PKEY, EVP_PKEY_free> pkey_;
};
class DHPointer final {
public:

View File

@ -995,7 +995,7 @@ bool PublicKeyCipher::Cipher(
const ArrayBufferOrViewContents<unsigned char>& oaep_label,
const ArrayBufferOrViewContents<unsigned char>& data,
std::unique_ptr<BackingStore>* 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<Value>& 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) {

View File

@ -449,15 +449,14 @@ MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
Local<Context> 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<String>(context, info, env->type_string(), env->dh_string()) ||
!Set<Integer>(context,
info,
env->size_string(),
Integer::New(env->isolate(), bits))) {
info,
env->size_string(),
Integer::New(env->isolate(), key.bits()))) {
return MaybeLocal<Object>();
}
break;
@ -473,18 +472,16 @@ MaybeLocal<Object> GetEphemeralKey(Environment* env, const SSLPointer& ssl) {
} else {
curve_name = OBJ_nid2sn(kid);
}
if (!Set<String>(context,
info,
env->type_string(),
env->ecdh_string()) ||
if (!Set<String>(
context, info, env->type_string(), env->ecdh_string()) ||
!Set<String>(context,
info,
env->name_string(),
OneByteString(env->isolate(), curve_name)) ||
info,
env->name_string(),
OneByteString(env->isolate(), curve_name)) ||
!Set<Integer>(context,
info,
env->size_string(),
Integer::New(env->isolate(), bits))) {
info,
env->size_string(),
Integer::New(env->isolate(), key.bits()))) {
return MaybeLocal<Object>();
}
}

View File

@ -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<int>(&params->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<void> GetDhKeyDetail(Environment* env,
const KeyObjectData& key,
Local<Object> target) {
CHECK_EQ(EVP_PKEY_id(key.GetAsymmetricKey().get()), EVP_PKEY_DH);
CHECK_EQ(key.GetAsymmetricKey().id(), EVP_PKEY_DH);
return JustVoid();
}

View File

@ -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<void> 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());

View File

@ -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<unsigned char>(), &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<void> ExportJWKEcKey(Environment* env,
Local<Object> 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<void> 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<void>();
}
size_t len = 0;
Local<Value> encoded;
Local<Value> error;
if (!EVP_PKEY_get_raw_public_key(pkey.get(), nullptr, &len))
return Nothing<void>();
ByteSource::Builder out(len);
if (key.GetKeyType() == kKeyTypePrivate) {
if (!EVP_PKEY_get_raw_private_key(
pkey.get(), out.data<unsigned char>(), &len) ||
!StringBytes::Encode(
env->isolate(), out.data<const char>(), len, BASE64URL, &error)
.ToLocal(&encoded) ||
!target->Set(env->context(), env->jwk_d_string(), encoded).IsJust()) {
if (!error.IsEmpty())
env->isolate()->ThrowException(error);
return Nothing<void>();
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();
}
}
})();
if (!EVP_PKEY_get_raw_public_key(
pkey.get(), out.data<unsigned char>(), &len) ||
!StringBytes::Encode(
env->isolate(), out.data<const char>(), len, BASE64URL, &error)
.ToLocal(&encoded) ||
!target->Set(env->context(), env->jwk_x_string(), encoded).IsJust()) {
if (!error.IsEmpty())
env->isolate()->ThrowException(error);
return Nothing<void>();
}
static constexpr auto trySetKey = [](Environment* env,
ncrypto::DataPointer data,
Local<Object> target,
Local<String> key) {
Local<Value> encoded;
Local<Value> error;
if (!data) return false;
const ncrypto::Buffer<const char> out = data;
if (!StringBytes::Encode(
env->isolate(), out.data, out.len, BASE64URL, &error)
.ToLocal(&encoded) ||
target->Set(env->context(), key, encoded).IsNothing()) {
if (!error.IsEmpty()) env->isolate()->ThrowException(error);
return false;
}
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<void>();
}
@ -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<void> GetEcKeyDetail(Environment* env,
Local<Object> 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);

View File

@ -25,7 +25,6 @@ using v8::FunctionCallbackInfo;
using v8::FunctionTemplate;
using v8::Int32;
using v8::Isolate;
using v8::Just;
using v8::JustVoid;
using v8::Local;
using v8::Maybe;
@ -60,8 +59,8 @@ void GetKeyFormatAndTypeFromJs(
args[*offset].As<Int32>()->Value());
if (args[*offset + 1]->IsInt32()) {
config->type_ = Just<PKEncodingType>(static_cast<PKEncodingType>(
args[*offset + 1].As<Int32>()->Value()));
config->type_ =
static_cast<PKEncodingType>(args[*offset + 1].As<Int32>()->Value());
} else {
CHECK(
(context == kKeyContextInput &&
@ -69,7 +68,7 @@ void GetKeyFormatAndTypeFromJs(
(context == kKeyContextGenerate &&
config->format_ == kKeyFormatJWK));
CHECK(args[*offset + 1]->IsNullOrUndefined());
config->type_ = Nothing<PKEncodingType>();
config->type_ = std::nullopt;
}
}
@ -140,22 +139,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);
auto res = EVPKeyPointer::TryParsePublicKey(
static_cast<EVPKeyPointer::PKFormatType>(config.format_),
static_cast<EVPKeyPointer::PKEncodingType>(config.type_.value()),
ncrypto::Buffer<const unsigned char>{
.data = reinterpret_cast<const unsigned char*>(key),
.len = key_len,
});
if (!res) return static_cast<ParseKeyResult>(res.error.value());
const unsigned char* p = reinterpret_cast<const unsigned char*>(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));
}
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 +224,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<const unsigned char*>(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 +244,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<const unsigned char*>(key);
pkey->reset(d2i_PrivateKey(EVP_PKEY_EC, nullptr, &p, key_len));
}
@ -318,10 +313,10 @@ MaybeLocal<Value> 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 +357,7 @@ MaybeLocal<Value> 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 +387,9 @@ MaybeLocal<Value> 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 +400,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 +475,7 @@ Maybe<void> ExportJWKAsymmetricKey(Environment* env,
const KeyObjectData& key,
Local<Object> 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 +530,7 @@ Maybe<void> GetSecretKeyDetail(Environment* env,
Maybe<void> GetAsymmetricKeyDetail(Environment* env,
const KeyObjectData& key,
Local<Object> 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 +718,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<const unsigned char*>(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<const unsigned char*>(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 +806,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 +1037,7 @@ void KeyObjectHandle::InitECRaw(const FunctionCallbackInfo<Value>& 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 +1061,10 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& 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<const unsigned char>&);
new_key_fn fn = type == kKeyTypePrivate ? EVPKeyPointer::NewRawPrivate
: EVPKeyPointer::NewRawPublic;
int id = GetOKPCurveFromName(*name);
@ -1083,9 +1073,14 @@ void KeyObjectHandle::InitEDRaw(const FunctionCallbackInfo<Value>& 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<const unsigned char>{
.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 +1166,27 @@ void KeyObjectHandle::GetKeyDetail(const FunctionCallbackInfo<Value>& args) {
}
Local<Value> 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 +1202,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 +1403,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;
}

View File

@ -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<int>(EVPKeyPointer::PKEncodingType::PKCS1),
// PrivateKeyInfo or EncryptedPrivateKeyInfo according to PKCS#8.
kKeyEncodingPKCS8,
kKeyEncodingPKCS8 = static_cast<int>(EVPKeyPointer::PKEncodingType::PKCS8),
// SubjectPublicKeyInfo according to X.509.
kKeyEncodingSPKI,
kKeyEncodingSPKI = static_cast<int>(EVPKeyPointer::PKEncodingType::SPKI),
// ECPrivateKey according to SEC1.
kKeyEncodingSEC1
kKeyEncodingSEC1 = static_cast<int>(EVPKeyPointer::PKEncodingType::SEC1),
};
enum PKFormatType {
kKeyFormatDER,
kKeyFormatPEM,
kKeyFormatJWK
kKeyFormatDER = static_cast<int>(EVPKeyPointer::PKFormatType::DER),
kKeyFormatPEM = static_cast<int>(EVPKeyPointer::PKFormatType::PEM),
kKeyFormatJWK = static_cast<int>(EVPKeyPointer::PKFormatType::JWK),
};
enum KeyType {
@ -48,16 +50,18 @@ enum KeyEncodingContext {
};
enum class ParseKeyResult {
kParseKeyNotRecognized =
static_cast<int>(EVPKeyPointer::PKParseError::NOT_RECOGNIZED),
kParseKeyNeedPassphrase =
static_cast<int>(EVPKeyPointer::PKParseError::NEED_PASSPHRASE),
kParseKeyFailed = static_cast<int>(EVPKeyPointer::PKParseError::FAILED),
kParseKeyOk,
kParseKeyNotRecognized,
kParseKeyNeedPassphrase,
kParseKeyFailed
};
struct AsymmetricKeyEncodingConfig {
bool output_key_object_ = false;
PKFormatType format_ = kKeyFormatDER;
v8::Maybe<PKEncodingType> type_ = v8::Nothing<PKEncodingType>();
std::optional<PKEncodingType> type_ = std::nullopt;
};
using PublicKeyEncodingConfig = AsymmetricKeyEncodingConfig;

View File

@ -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<void> ExportJWKRsaKey(Environment* env,
Local<Object> 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<void> 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

View File

@ -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<int>& 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<BackingStore> 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<size_t>(signed_sig_len);
size_t sig_len = pkey.size();
std::unique_ptr<BackingStore> 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<BackingStore> 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) {