summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-06-19 09:29:59 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-06-19 09:29:59 +0000
commitbe1baf4a9a62aade5a411eab3ebb704f3afd2cc8 (patch)
tree8d216d4f7bcfcbe7b29871745c642914c65ae124 /ext/openssl
parentb67ead14521fb74bcf8ec28f8c78245dfb536b70 (diff)
openssl: implement initialize_copy method for PKey classes
* ext/openssl/ossl_pkey_dh.c, ext/openssl/ossl_pkey_dsa.c, ext/openssl/ossl_pkey_ec.c, ext/openssl/ossl_pkey_rsa.c: Implement initialize_copy method for OpenSSL::PKey::*. [ruby-core:75504] [Bug #12381] * test/openssl/test_pkey_dh.rb, test/openssl/test_pkey_dsa.rb, test/openssl/test_pkey_ec.rb, test/openssl/test_pkey_rsa.rb: Test they actually copy the OpenSSL objects, and modifications to cloned object don't affect the original object. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55454 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/openssl')
-rw-r--r--ext/openssl/ossl_pkey_dh.c34
-rw-r--r--ext/openssl/ossl_pkey_dsa.c21
-rw-r--r--ext/openssl/ossl_pkey_ec.c83
-rw-r--r--ext/openssl/ossl_pkey_rsa.c21
4 files changed, 147 insertions, 12 deletions
diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c
index 654d479..139af15 100644
--- a/ext/openssl/ossl_pkey_dh.c
+++ b/ext/openssl/ossl_pkey_dh.c
@@ -238,6 +238,39 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_dh_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey;
+ DH *dh, *dh_other;
+ const BIGNUM *pub, *priv;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
+ ossl_raise(eDHError, "DH already initialized");
+ GetDH(other, dh_other);
+
+ dh = DHparams_dup(dh_other);
+ if (!dh)
+ ossl_raise(eDHError, "DHparams_dup");
+ EVP_PKEY_assign_DH(pkey, dh);
+
+ DH_get0_key(dh_other, &pub, &priv);
+ if (pub) {
+ BIGNUM *pub2 = BN_dup(pub);
+ BIGNUM *priv2 = BN_dup(priv);
+
+ if (!pub2 || priv && !priv2) {
+ BN_clear_free(pub2);
+ BN_clear_free(priv2);
+ ossl_raise(eDHError, "BN_dup");
+ }
+ DH_set0_key(dh, pub2, priv2);
+ }
+
+ return self;
+}
+
/*
* call-seq:
* dh.public? -> true | false
@@ -568,6 +601,7 @@ Init_ossl_dh(void)
cDH = rb_define_class_under(mPKey, "DH", cPKey);
rb_define_singleton_method(cDH, "generate", ossl_dh_s_generate, -1);
rb_define_method(cDH, "initialize", ossl_dh_initialize, -1);
+ rb_define_copy_func(cDH, ossl_dh_initialize_copy);
rb_define_method(cDH, "public?", ossl_dh_is_public, 0);
rb_define_method(cDH, "private?", ossl_dh_is_private, 0);
rb_define_method(cDH, "to_text", ossl_dh_to_text, 0);
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 333beae..1ddc0d4 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -269,6 +269,26 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_dsa_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey;
+ DSA *dsa, *dsa_new;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
+ ossl_raise(eDSAError, "DSA already initialized");
+ GetDSA(other, dsa);
+
+ dsa_new = ASN1_dup((i2d_of_void *)i2d_DSAPrivateKey, (d2i_of_void *)d2i_DSAPrivateKey, (char *)dsa);
+ if (!dsa_new)
+ ossl_raise(eDSAError, "ASN1_dup");
+
+ EVP_PKEY_assign_DSA(pkey, dsa_new);
+
+ return self;
+}
+
/*
* call-seq:
* dsa.public? -> true | false
@@ -610,6 +630,7 @@ Init_ossl_dsa(void)
rb_define_singleton_method(cDSA, "generate", ossl_dsa_s_generate, 1);
rb_define_method(cDSA, "initialize", ossl_dsa_initialize, -1);
+ rb_define_copy_func(cDSA, ossl_dsa_initialize_copy);
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 30ded33..43eebd2 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -285,6 +285,29 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_ec_key_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey;
+ EC_KEY *ec, *ec_new;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
+ ossl_raise(eECError, "EC already initialized");
+ SafeRequire_EC_KEY(other, ec);
+
+ ec_new = EC_KEY_dup(ec);
+ if (!ec_new)
+ ossl_raise(eECError, "EC_KEY_dup");
+ if (!EVP_PKEY_assign_EC_KEY(pkey, ec_new)) {
+ EC_KEY_free(ec_new);
+ ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
+ }
+ rb_iv_set(self, "@group", Qnil); /* EC_KEY_dup() also copies the EC_GROUP */
+
+ return self;
+}
+
/*
* call-seq:
* key.group => group
@@ -903,6 +926,26 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_ec_group_initialize_copy(VALUE self, VALUE other)
+{
+ ossl_ec_group *ec_group;
+ EC_GROUP *orig;
+
+ TypedData_Get_Struct(self, ossl_ec_group, &ossl_ec_group_type, ec_group);
+ if (ec_group->group)
+ ossl_raise(eEC_GROUP, "EC::Group already initialized");
+ SafeRequire_EC_GROUP(other, orig);
+
+ ec_group->group = EC_GROUP_dup(orig);
+ if (!ec_group->group)
+ ossl_raise(eEC_GROUP, "EC_GROUP_dup");
+
+ rb_iv_set(self, "@key", Qnil);
+
+ return self;
+}
+
/* call-seq:
* group1.eql?(group2) => true | false
* group1 == group2 => true | false
@@ -1381,6 +1424,31 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_ec_point_initialize_copy(VALUE self, VALUE other)
+{
+ ossl_ec_point *ec_point;
+ EC_POINT *orig;
+ EC_GROUP *group;
+ VALUE group_v;
+
+ TypedData_Get_Struct(self, ossl_ec_point, &ossl_ec_point_type, ec_point);
+ if (ec_point->point)
+ ossl_raise(eEC_POINT, "EC::Point already initialized");
+ SafeRequire_EC_POINT(other, orig);
+
+ group_v = rb_obj_dup(rb_iv_get(other, "@group"));
+ SafeRequire_EC_GROUP(group_v, group);
+
+ ec_point->point = EC_POINT_dup(orig, group);
+ if (!ec_point->point)
+ ossl_raise(eEC_POINT, "EC_POINT_dup");
+ rb_iv_set(self, "@key", Qnil);
+ rb_iv_set(self, "@group", group_v);
+
+ return self;
+}
+
/*
* call-seq:
* point1.eql?(point2) => true | false
@@ -1624,14 +1692,6 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
return result;
}
-static void no_copy(VALUE klass)
-{
- rb_undef_method(klass, "copy");
- rb_undef_method(klass, "clone");
- rb_undef_method(klass, "dup");
- rb_undef_method(klass, "initialize_copy");
-}
-
void Init_ossl_ec(void)
{
#ifdef DONT_NEED_RDOC_WORKAROUND
@@ -1664,6 +1724,7 @@ 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);
+ rb_define_copy_func(cEC, ossl_ec_key_initialize_copy);
/* copy/dup/cmp */
rb_define_method(cEC, "group", ossl_ec_key_get_group, 0);
@@ -1700,6 +1761,7 @@ void Init_ossl_ec(void)
rb_define_alloc_func(cEC_GROUP, ossl_ec_group_alloc);
rb_define_method(cEC_GROUP, "initialize", ossl_ec_group_initialize, -1);
+ rb_define_copy_func(cEC_GROUP, ossl_ec_group_initialize_copy);
rb_define_method(cEC_GROUP, "eql?", ossl_ec_group_eql, 1);
rb_define_alias(cEC_GROUP, "==", "eql?");
/* copy/dup/cmp */
@@ -1735,6 +1797,7 @@ void Init_ossl_ec(void)
rb_define_alloc_func(cEC_POINT, ossl_ec_point_alloc);
rb_define_method(cEC_POINT, "initialize", ossl_ec_point_initialize, -1);
+ rb_define_copy_func(cEC_POINT, ossl_ec_point_initialize_copy);
rb_attr(cEC_POINT, rb_intern("group"), 1, 0, 0);
rb_define_method(cEC_POINT, "eql?", ossl_ec_point_eql, 1);
rb_define_alias(cEC_POINT, "==", "eql?");
@@ -1748,10 +1811,6 @@ void Init_ossl_ec(void)
rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, 0);
rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1);
-
- no_copy(cEC);
- no_copy(cEC_GROUP);
- no_copy(cEC_POINT);
}
#else /* defined NO_EC */
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 60fa146..2326a70 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -271,6 +271,26 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self)
return self;
}
+static VALUE
+ossl_rsa_initialize_copy(VALUE self, VALUE other)
+{
+ EVP_PKEY *pkey;
+ RSA *rsa, *rsa_new;
+
+ GetPKey(self, pkey);
+ if (EVP_PKEY_base_id(pkey) != EVP_PKEY_NONE)
+ ossl_raise(eRSAError, "RSA already initialized");
+ GetRSA(other, rsa);
+
+ rsa_new = ASN1_dup((i2d_of_void *)i2d_RSAPrivateKey, (d2i_of_void *)d2i_RSAPrivateKey, (char *)rsa);
+ if (!rsa_new)
+ ossl_raise(eRSAError, "ASN1_dup");
+
+ EVP_PKEY_assign_RSA(pkey, rsa_new);
+
+ return self;
+}
+
/*
* call-seq:
* rsa.public? => true
@@ -675,6 +695,7 @@ Init_ossl_rsa(void)
rb_define_singleton_method(cRSA, "generate", ossl_rsa_s_generate, -1);
rb_define_method(cRSA, "initialize", ossl_rsa_initialize, -1);
+ rb_define_copy_func(cRSA, ossl_rsa_initialize_copy);
rb_define_method(cRSA, "public?", ossl_rsa_is_public, 0);
rb_define_method(cRSA, "private?", ossl_rsa_is_private, 0);