aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2021-04-22 19:48:47 +0900
committerKazuki Yamaguchi <k@rhe.jp>2021-12-20 19:07:59 +0900
commitf2d92076b4dc614c09aab99aa5a085d27396053b (patch)
treecf3c72ac299bb0d0981fd34f31990d7535961462
parent1c4d75f21ba70623f1d31d56bea2bd2e346a1e91 (diff)
downloadruby-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.c72
-rw-r--r--ext/openssl/ossl_pkey.h36
-rw-r--r--ext/openssl/ossl_pkey_dh.c5
-rw-r--r--ext/openssl/ossl_pkey_dsa.c5
-rw-r--r--ext/openssl/ossl_pkey_rsa.c8
-rw-r--r--lib/openssl/pkey.rb28
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
#