From df6589e418adb2a4018e40d53dab2fd5556ed41e Mon Sep 17 00:00:00 2001 From: Kazuki Yamaguchi Date: Thu, 22 Apr 2021 16:33:59 +0900 Subject: [PATCH] [ruby/openssl] pkey: use EVP_PKEY_dup() if available We can use it to implement OpenSSL::PKey::PKey#initialize_copy. This should work on all key types, not just DH/DSA/EC/RSA types. https://github.com/ruby/openssl/commit/66cd8cbaaf --- ext/openssl/extconf.rb | 1 + ext/openssl/ossl_pkey.c | 25 +++++++++++++++++++++++++ ext/openssl/ossl_pkey_dh.c | 4 ++++ ext/openssl/ossl_pkey_dsa.c | 4 ++++ ext/openssl/ossl_pkey_ec.c | 5 ++++- ext/openssl/ossl_pkey_rsa.c | 4 ++++ 6 files changed, 42 insertions(+), 1 deletion(-) diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 1d38b56990..fedcb930f5 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -179,6 +179,7 @@ have_func("BN_check_prime") have_func("EVP_MD_CTX_get0_md") have_func("EVP_MD_CTX_get_pkey_ctx") have_func("EVP_PKEY_eq") +have_func("EVP_PKEY_dup") Logging::message "=== Checking done. ===\n" diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 9e4f0be5f9..7030be3c8e 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -531,6 +531,26 @@ ossl_pkey_initialize(VALUE self) return self; } +#ifdef HAVE_EVP_PKEY_DUP +static VALUE +ossl_pkey_initialize_copy(VALUE self, VALUE other) +{ + EVP_PKEY *pkey, *pkey_other; + + TypedData_Get_Struct(self, EVP_PKEY, &ossl_evp_pkey_type, pkey); + TypedData_Get_Struct(other, EVP_PKEY, &ossl_evp_pkey_type, pkey_other); + if (pkey) + rb_raise(rb_eTypeError, "pkey already initialized"); + if (pkey_other) { + pkey = EVP_PKEY_dup(pkey_other); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_dup"); + RTYPEDDATA_DATA(self) = pkey; + } + return self; +} +#endif + /* * call-seq: * pkey.oid -> string @@ -1508,6 +1528,11 @@ Init_ossl_pkey(void) rb_define_alloc_func(cPKey, ossl_pkey_alloc); rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); +#ifdef HAVE_EVP_PKEY_DUP + rb_define_method(cPKey, "initialize_copy", ossl_pkey_initialize_copy, 1); +#else + rb_undef_method(cPKey, "initialize_copy"); +#endif rb_define_method(cPKey, "oid", ossl_pkey_oid, 0); rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0); rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0); diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 04c11b2157..d6f32c62f7 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -126,6 +126,7 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_dh_initialize_copy(VALUE self, VALUE other) { @@ -164,6 +165,7 @@ ossl_dh_initialize_copy(VALUE self, VALUE other) RTYPEDDATA_DATA(self) = pkey; return self; } +#endif /* * call-seq: @@ -407,7 +409,9 @@ Init_ossl_dh(void) */ cDH = rb_define_class_under(mPKey, "DH", cPKey); rb_define_method(cDH, "initialize", ossl_dh_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cDH, "initialize_copy", ossl_dh_initialize_copy, 1); +#endif rb_define_method(cDH, "public?", ossl_dh_is_public, 0); rb_define_method(cDH, "private?", ossl_dh_is_private, 0); rb_define_method(cDH, "export", ossl_dh_export, 0); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 1572454846..25404aa7f5 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -139,6 +139,7 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_dsa_initialize_copy(VALUE self, VALUE other) { @@ -166,6 +167,7 @@ ossl_dsa_initialize_copy(VALUE self, VALUE other) return self; } +#endif /* * call-seq: @@ -327,7 +329,9 @@ Init_ossl_dsa(void) cDSA = rb_define_class_under(mPKey, "DSA", cPKey); rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cDSA, "initialize_copy", ossl_dsa_initialize_copy, 1); +#endif rb_define_method(cDSA, "public?", ossl_dsa_is_public, 0); rb_define_method(cDSA, "private?", ossl_dsa_is_private, 0); diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 71e63969e7..3b4930f353 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -190,6 +190,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_ec_key_initialize_copy(VALUE self, VALUE other) { @@ -214,6 +215,7 @@ ossl_ec_key_initialize_copy(VALUE self, VALUE other) return self; } +#endif /* * call-seq: @@ -1523,8 +1525,9 @@ void Init_ossl_ec(void) rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1); rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cEC, "initialize_copy", ossl_ec_key_initialize_copy, 1); -/* copy/dup/cmp */ +#endif rb_define_method(cEC, "group", ossl_ec_key_get_group, 0); rb_define_method(cEC, "group=", ossl_ec_key_set_group, 1); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index b8dbc0e1c4..4d66010f49 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -135,6 +135,7 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) return self; } +#ifndef HAVE_EVP_PKEY_DUP static VALUE ossl_rsa_initialize_copy(VALUE self, VALUE other) { @@ -161,6 +162,7 @@ ossl_rsa_initialize_copy(VALUE self, VALUE other) return self; } +#endif /* * call-seq: @@ -535,7 +537,9 @@ Init_ossl_rsa(void) cRSA = rb_define_class_under(mPKey, "RSA", cPKey); rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1); +#ifndef HAVE_EVP_PKEY_DUP rb_define_method(cRSA, "initialize_copy", ossl_rsa_initialize_copy, 1); +#endif rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0); rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);