diff options
author | Kazuki Yamaguchi <k@rhe.jp> | 2021-04-22 19:48:47 +0900 |
---|---|---|
committer | Kazuki Yamaguchi <k@rhe.jp> | 2021-12-20 19:07:59 +0900 |
commit | f2d92076b4dc614c09aab99aa5a085d27396053b (patch) | |
tree | cf3c72ac299bb0d0981fd34f31990d7535961462 | |
parent | 1c4d75f21ba70623f1d31d56bea2bd2e346a1e91 (diff) | |
download | ruby-openssl-f2d92076b4dc614c09aab99aa5a085d27396053b.tar.gz |
pkey: use EVP_PKEY_get_params() to implement key component getters
If EVP_PKEY_get_params() family is available, use it to get the key
component values. Otherwise, check the return value of #to_data, which
should be overriden by the subclasses.
-rw-r--r-- | ext/openssl/ossl_pkey.c | 72 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey.h | 36 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_dh.c | 5 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_dsa.c | 5 | ||||
-rw-r--r-- | ext/openssl/ossl_pkey_rsa.c | 8 | ||||
-rw-r--r-- | lib/openssl/pkey.rb | 28 |
6 files changed, 100 insertions, 54 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index 160a1c85..be4d37f2 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -718,6 +718,77 @@ ossl_pkey_to_data(VALUE self) #endif } +/* + * :nodoc: + * + * call-seq: + * pkey.get_bn_param(key, default) -> bn + * + * Retrieves a BIGNUM value associated with a name of +key+. + * + * See also #to_data, which returns all available parameters. + * + * See also the man page EVP_PKEY_get_bn_param(3). + */ +static VALUE +ossl_pkey_get_bn_param(VALUE self, VALUE key) +{ +#ifdef HAVE_EVP_PKEY_TODATA + EVP_PKEY *pkey; + OSSL_PARAM params[2]; + const OSSL_PARAM *gettable, *found; + unsigned char buf[2048]; + BIGNUM *bn; + VALUE ret, tmp = Qnil; + + GetPKey(self, pkey); + ret = ossl_bn_new(NULL); + bn = GetBNPtr(ret); + if (SYMBOL_P(key)) + key = rb_sym2str(key); + + gettable = EVP_PKEY_gettable_params(pkey); + if (!gettable) + ossl_raise(ePKeyError, "EVP_PKEY_gettable_params"); + found = OSSL_PARAM_locate_const(gettable, StringValueCStr(key)); + if (!found) + ossl_raise(ePKeyError, "OSSL_PARAM_locate_const"); + if (found->data_type != OSSL_PARAM_INTEGER && + found->data_type != OSSL_PARAM_UNSIGNED_INTEGER) + ossl_raise(ePKeyError, "OSSL_PARAM_locate_const: unsupported param type"); + + memset(buf, 0, sizeof(buf)); + params[0] = OSSL_PARAM_construct_BN(StringValueCStr(key), buf, sizeof(buf)); + params[1] = OSSL_PARAM_construct_end(); + if (!EVP_PKEY_get_params(pkey, params)) { + size_t size = params[0].return_size; + if (!OSSL_PARAM_modified(params) || size == 0) + return Qnil; + + /* It might have failed because the buffer was too small */ + params[0].data = ALLOCV_N(unsigned char, tmp, size); + params[0].data_size = size; + + if (!EVP_PKEY_get_params(pkey, params) || !OSSL_PARAM_modified(params)) + ossl_raise(ePKeyError, "EVP_PKEY_get_params"); + } + if (!OSSL_PARAM_get_BN(params, &bn)) + ossl_raise(ePKeyError, "OSSL_PARAM_get_BN"); + + return ret; +#else + VALUE ret, hash; + + /* Let's assume the subclass implements #to_data */ + hash = rb_funcall(self, rb_intern("to_data"), 0); + Check_Type(hash, T_HASH); + ret = rb_hash_lookup2(hash, key, Qundef); + if (NIL_P(ret) || rb_obj_is_kind_of(ret, cBN)) + return ret; + rb_raise(ePKeyError, "key not found"); +#endif +} + VALUE ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) { @@ -1631,6 +1702,7 @@ Init_ossl_pkey(void) rb_define_method(cPKey, "inspect", ossl_pkey_inspect, 0); rb_define_method(cPKey, "to_text", ossl_pkey_to_text, 0); rb_define_method(cPKey, "to_data", ossl_pkey_to_data, 0); + rb_define_method(cPKey, "get_bn_param", ossl_pkey_get_bn_param, 1); rb_define_method(cPKey, "private_to_der", ossl_pkey_private_to_der, -1); rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1); rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0); diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 38fb9fad..6e9d0442 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -85,37 +85,6 @@ extern VALUE eEC_POINT; VALUE ossl_ec_new(EVP_PKEY *); void Init_ossl_ec(void); -#define OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, _name, _get) \ -/* \ - * call-seq: \ - * _keytype##.##_name -> aBN \ - */ \ -static VALUE ossl_##_keytype##_get_##_name(VALUE self) \ -{ \ - _type *obj; \ - const BIGNUM *bn; \ - \ - Get##_type(self, obj); \ - _get; \ - if (bn == NULL) \ - return Qnil; \ - return ossl_bn_new(bn); \ -} - -#define OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ - OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ - _type##_get0_##_group(obj, &bn, NULL, NULL)) \ - OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ - _type##_get0_##_group(obj, NULL, &bn, NULL)) \ - OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a3, \ - _type##_get0_##_group(obj, NULL, NULL, &bn)) - -#define OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ - OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a1, \ - _type##_get0_##_group(obj, &bn, NULL)) \ - OSSL_PKEY_BN_DEF_GETTER0(_keytype, _type, a2, \ - _type##_get0_##_group(obj, NULL, &bn)) - #if !OSSL_OPENSSL_PREREQ(3, 0, 0) #define OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) \ /* \ @@ -191,14 +160,9 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ #endif #define OSSL_PKEY_BN_DEF3(_keytype, _type, _group, a1, a2, a3) \ - OSSL_PKEY_BN_DEF_GETTER3(_keytype, _type, _group, a1, a2, a3) \ OSSL_PKEY_BN_DEF_SETTER3(_keytype, _type, _group, a1, a2, a3) #define OSSL_PKEY_BN_DEF2(_keytype, _type, _group, a1, a2) \ - OSSL_PKEY_BN_DEF_GETTER2(_keytype, _type, _group, a1, a2) \ OSSL_PKEY_BN_DEF_SETTER2(_keytype, _type, _group, a1, a2) -#define DEF_OSSL_PKEY_BN(class, keytype, name) \ - rb_define_method((class), #name, ossl_##keytype##_get_##name, 0) - #endif /* OSSL_PKEY_H */ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index 97b1730c..105bc930 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -416,11 +416,6 @@ Init_ossl_dh(void) rb_define_method(cDH, "to_der", ossl_dh_to_der, 0); rb_define_method(cDH, "params_ok?", ossl_dh_check_params, 0); - DEF_OSSL_PKEY_BN(cDH, dh, p); - DEF_OSSL_PKEY_BN(cDH, dh, q); - DEF_OSSL_PKEY_BN(cDH, dh, g); - DEF_OSSL_PKEY_BN(cDH, dh, pub_key); - DEF_OSSL_PKEY_BN(cDH, dh, priv_key); rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3); rb_define_method(cDH, "set_key", ossl_dh_set_key, 2); diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index aded059a..a43f2dfd 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -335,11 +335,6 @@ Init_ossl_dsa(void) rb_define_alias(cDSA, "to_s", "export"); rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0); - DEF_OSSL_PKEY_BN(cDSA, dsa, p); - DEF_OSSL_PKEY_BN(cDSA, dsa, q); - DEF_OSSL_PKEY_BN(cDSA, dsa, g); - DEF_OSSL_PKEY_BN(cDSA, dsa, pub_key); - DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key); rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3); rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index c731ce00..9edc7c52 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -542,14 +542,6 @@ Init_ossl_rsa(void) rb_define_method(cRSA, "sign_pss", ossl_rsa_sign_pss, -1); rb_define_method(cRSA, "verify_pss", ossl_rsa_verify_pss, -1); - DEF_OSSL_PKEY_BN(cRSA, rsa, n); - DEF_OSSL_PKEY_BN(cRSA, rsa, e); - DEF_OSSL_PKEY_BN(cRSA, rsa, d); - DEF_OSSL_PKEY_BN(cRSA, rsa, p); - DEF_OSSL_PKEY_BN(cRSA, rsa, q); - DEF_OSSL_PKEY_BN(cRSA, rsa, dmp1); - DEF_OSSL_PKEY_BN(cRSA, rsa, dmq1); - DEF_OSSL_PKEY_BN(cRSA, rsa, iqmp); rb_define_method(cRSA, "set_key", ossl_rsa_set_key, 3); rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2); rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3); diff --git a/lib/openssl/pkey.rb b/lib/openssl/pkey.rb index 447f7788..8390caa2 100644 --- a/lib/openssl/pkey.rb +++ b/lib/openssl/pkey.rb @@ -21,6 +21,14 @@ module OpenSSL::PKey } end + def p; get_bn_param(:p) end + def q; get_bn_param(:q) end + def g; get_bn_param(:g) end + def pub_key; get_bn_param(:pub) end + def priv_key; get_bn_param(:priv) end + def get_pqg; [p, q, g] end + def get_key; [pub_key, priv_key] end + # :call-seq: # dh.public_key -> dhnew # @@ -160,6 +168,14 @@ module OpenSSL::PKey } end + def p; get_bn_param(:p) end + def q; get_bn_param(:q) end + def g; get_bn_param(:g) end + def pub_key; get_bn_param(:pub) end + def priv_key; get_bn_param(:priv) end + def get_pqg; [p, q, g] end + def get_key; [pub_key, priv_key] end + # :call-seq: # dsa.public_key -> dsanew # @@ -341,6 +357,18 @@ module OpenSSL::PKey } end + def n; get_bn_param(:n) end + def e; get_bn_param(:e) end + def d; get_bn_param(:d) end + def p; get_bn_param(:"rsa-factor1") end + def q; get_bn_param(:"rsa-factor2") end + def dmp1; get_bn_param(:"rsa-exponent1") end + def dmq1; get_bn_param(:"rsa-exponent2") end + def iqmp; get_bn_param(:"rsa-coefficient1") end + def get_key; [n, e, d] end + def get_factors; [p, q] end + def get_crt_params; [dmp1, dmq1, iqmp] end + # :call-seq: # rsa.public_key -> rsanew # |