mirror of
https://github.com/ruby/ruby.git
synced 2025-08-15 13:39:04 +02:00
[ruby/openssl] pkey: use EVP_PKEY_new_raw_{private,public}_key_ex() if available
Algorithms implemented only in OpenSSL 3 providers may not have a
corresponding NID. The *_ex() variants have been added in OpenSSL 3.0
to handle such algorithms, by taking algorithm names as a string.
e730e457cc
This commit is contained in:
parent
0c6075bd42
commit
a1996b32a9
2 changed files with 60 additions and 16 deletions
|
@ -635,6 +635,29 @@ ossl_pkey_initialize_copy(VALUE self, VALUE other)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef OSSL_USE_PROVIDER
|
||||||
|
static int
|
||||||
|
lookup_pkey_type(VALUE type)
|
||||||
|
{
|
||||||
|
const EVP_PKEY_ASN1_METHOD *ameth;
|
||||||
|
int pkey_id;
|
||||||
|
|
||||||
|
StringValue(type);
|
||||||
|
/*
|
||||||
|
* XXX: EVP_PKEY_asn1_find_str() looks up a PEM type string. Should we use
|
||||||
|
* OBJ_txt2nid() instead (and then somehow check if the NID is an acceptable
|
||||||
|
* EVP_PKEY type)?
|
||||||
|
* It is probably fine, though, since it can handle all algorithms that
|
||||||
|
* support raw keys in 1.1.1: { X25519, X448, ED25519, ED448, HMAC }.
|
||||||
|
*/
|
||||||
|
ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
|
||||||
|
if (!ameth)
|
||||||
|
ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
|
||||||
|
EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
|
||||||
|
return pkey_id;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey
|
* OpenSSL::PKey.new_raw_private_key(algo, string) -> PKey
|
||||||
|
@ -646,22 +669,23 @@ static VALUE
|
||||||
ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
|
ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
const EVP_PKEY_ASN1_METHOD *ameth;
|
|
||||||
int pkey_id;
|
|
||||||
size_t keylen;
|
size_t keylen;
|
||||||
|
|
||||||
StringValue(type);
|
|
||||||
StringValue(key);
|
StringValue(key);
|
||||||
ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
|
|
||||||
if (!ameth)
|
|
||||||
ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
|
|
||||||
EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
|
|
||||||
|
|
||||||
keylen = RSTRING_LEN(key);
|
keylen = RSTRING_LEN(key);
|
||||||
|
|
||||||
|
#ifdef OSSL_USE_PROVIDER
|
||||||
|
pkey = EVP_PKEY_new_raw_private_key_ex(NULL, StringValueCStr(type), NULL,
|
||||||
|
(unsigned char *)RSTRING_PTR(key),
|
||||||
|
keylen);
|
||||||
|
if (!pkey)
|
||||||
|
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key_ex");
|
||||||
|
#else
|
||||||
|
int pkey_id = lookup_pkey_type(type);
|
||||||
pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
|
pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
|
||||||
if (!pkey)
|
if (!pkey)
|
||||||
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
|
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
|
||||||
|
#endif
|
||||||
|
|
||||||
return ossl_pkey_new(pkey);
|
return ossl_pkey_new(pkey);
|
||||||
}
|
}
|
||||||
|
@ -677,22 +701,23 @@ static VALUE
|
||||||
ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
|
ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
|
||||||
{
|
{
|
||||||
EVP_PKEY *pkey;
|
EVP_PKEY *pkey;
|
||||||
const EVP_PKEY_ASN1_METHOD *ameth;
|
|
||||||
int pkey_id;
|
|
||||||
size_t keylen;
|
size_t keylen;
|
||||||
|
|
||||||
StringValue(type);
|
|
||||||
StringValue(key);
|
StringValue(key);
|
||||||
ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type));
|
|
||||||
if (!ameth)
|
|
||||||
ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type);
|
|
||||||
EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth);
|
|
||||||
|
|
||||||
keylen = RSTRING_LEN(key);
|
keylen = RSTRING_LEN(key);
|
||||||
|
|
||||||
|
#ifdef OSSL_USE_PROVIDER
|
||||||
|
pkey = EVP_PKEY_new_raw_public_key_ex(NULL, StringValueCStr(type), NULL,
|
||||||
|
(unsigned char *)RSTRING_PTR(key),
|
||||||
|
keylen);
|
||||||
|
if (!pkey)
|
||||||
|
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key_ex");
|
||||||
|
#else
|
||||||
|
int pkey_id = lookup_pkey_type(type);
|
||||||
pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
|
pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen);
|
||||||
if (!pkey)
|
if (!pkey)
|
||||||
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
|
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
|
||||||
|
#endif
|
||||||
|
|
||||||
return ossl_pkey_new(pkey);
|
return ossl_pkey_new(pkey);
|
||||||
}
|
}
|
||||||
|
|
|
@ -161,6 +161,25 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
|
||||||
bob.raw_public_key.unpack1("H*")
|
bob.raw_public_key.unpack1("H*")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_ml_dsa
|
||||||
|
# AWS-LC also supports ML-DSA, but it's implemented in a different way
|
||||||
|
return unless openssl?(3, 5, 0)
|
||||||
|
|
||||||
|
pkey = OpenSSL::PKey.generate_key("ML-DSA-44")
|
||||||
|
assert_match(/type_name=ML-DSA-44/, pkey.inspect)
|
||||||
|
sig = pkey.sign(nil, "data")
|
||||||
|
assert_equal(2420, sig.bytesize)
|
||||||
|
assert_equal(true, pkey.verify(nil, sig, "data"))
|
||||||
|
|
||||||
|
pub2 = OpenSSL::PKey.read(pkey.public_to_der)
|
||||||
|
assert_equal(true, pub2.verify(nil, sig, "data"))
|
||||||
|
|
||||||
|
raw_public_key = pkey.raw_public_key
|
||||||
|
assert_equal(1312, raw_public_key.bytesize)
|
||||||
|
pub3 = OpenSSL::PKey.new_raw_public_key("ML-DSA-44", raw_public_key)
|
||||||
|
assert_equal(true, pub3.verify(nil, sig, "data"))
|
||||||
|
end
|
||||||
|
|
||||||
def test_raw_initialize_errors
|
def test_raw_initialize_errors
|
||||||
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") }
|
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("foo123", "xxx") }
|
||||||
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") }
|
assert_raise(OpenSSL::PKey::PKeyError) { OpenSSL::PKey.new_raw_private_key("ED25519", "xxx") }
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue