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
|
||||
|
||||
#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:
|
||||
* 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)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
const EVP_PKEY_ASN1_METHOD *ameth;
|
||||
int pkey_id;
|
||||
size_t keylen;
|
||||
|
||||
StringValue(type);
|
||||
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);
|
||||
|
||||
#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);
|
||||
if (!pkey)
|
||||
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key");
|
||||
#endif
|
||||
|
||||
return ossl_pkey_new(pkey);
|
||||
}
|
||||
|
@ -677,22 +701,23 @@ static VALUE
|
|||
ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key)
|
||||
{
|
||||
EVP_PKEY *pkey;
|
||||
const EVP_PKEY_ASN1_METHOD *ameth;
|
||||
int pkey_id;
|
||||
size_t keylen;
|
||||
|
||||
StringValue(type);
|
||||
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);
|
||||
|
||||
#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);
|
||||
if (!pkey)
|
||||
ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key");
|
||||
#endif
|
||||
|
||||
return ossl_pkey_new(pkey);
|
||||
}
|
||||
|
|
|
@ -161,6 +161,25 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase
|
|||
bob.raw_public_key.unpack1("H*")
|
||||
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
|
||||
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") }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue