summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-24 16:30:15 +0000
committerrhe <rhe@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2016-05-24 16:30:15 +0000
commit85500b6634290809aafc7be3eaec9f0c77b50ca9 (patch)
tree182bb2bc4938d4e0464613ca9eb06c99ea3f9c94
parent8cbd74a362a918b6ce332d6240432318165527b0 (diff)
openssl: add EC.generate
* ext/openssl/ossl_pkey_ec.c (ec_key_new_from_group): Create a new EC_KEY on given EC group. Extracted from ossl_ec_key_initialize(). (ossl_ec_key_s_generate): Added. Create a new EC instance and generate a random private and public key. (ossl_ec_key_initialize): Use ec_key_new_from_group(). (Init_ossl_ec): Define the new method EC.generate. This change is for consistency with other PKey types. [ruby-core:45541] [Bug #6567] * test/openssl/test_pkey_ec.rb: Test that EC.generate works. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55152 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog12
-rw-r--r--ext/openssl/ossl_pkey_ec.c147
-rw-r--r--test/openssl/test_pkey_ec.rb9
3 files changed, 117 insertions, 51 deletions
diff --git a/ChangeLog b/ChangeLog
index 6d9b83dd00..e8fa625051 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+Wed May 25 01:13:55 2016 Kazuki Yamaguchi <k@rhe.jp>
+
+ * ext/openssl/ossl_pkey_ec.c (ec_key_new_from_group): Create a new
+ EC_KEY on given EC group. Extracted from ossl_ec_key_initialize().
+ (ossl_ec_key_s_generate): Added. Create a new EC instance and
+ generate a random private and public key.
+ (ossl_ec_key_initialize): Use ec_key_new_from_group().
+ (Init_ossl_ec): Define the new method EC.generate. This change is
+ for consistency with other PKey types. [ruby-core:45541] [Bug #6567]
+
+ * test/openssl/test_pkey_ec.rb: Test that EC.generate works.
+
Wed May 25 00:37:16 2016 Kazuki Yamaguchi <k@rhe.jp>
* ext/openssl/ossl_pkey_ec.c (ossl_ec_key_generate_key): Fix up RDoc.
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index 74bc7abea8..9210ae48ab 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -149,6 +149,69 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
return obj;
}
+/*
+ * Creates a new EC_KEY on the EC group obj. arg can be an EC::Group or a String
+ * representing an OID.
+ */
+static EC_KEY *
+ec_key_new_from_group(VALUE arg)
+{
+ EC_KEY *ec;
+
+ if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ EC_GROUP *group;
+
+ SafeRequire_EC_GROUP(arg, group);
+
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(eECError, NULL);
+
+ if (!EC_KEY_set_group(ec, group)) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, NULL);
+ }
+ } else {
+ int nid = OBJ_sn2nid(StringValueCStr(arg));
+
+ if (nid == NID_undef)
+ ossl_raise(eECError, "invalid curve name");
+
+ if (!(ec = EC_KEY_new_by_curve_name(nid)))
+ ossl_raise(eECError, NULL);
+
+ EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
+ EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
+ }
+
+ return ec;
+}
+
+/*
+ * call-seq:
+ * EC.generate(ec_group) -> ec
+ * EC.generate(string) -> ec
+ *
+ * Creates a new EC instance with a new random private and public key.
+ */
+static VALUE
+ossl_ec_key_s_generate(VALUE klass, VALUE arg)
+{
+ EC_KEY *ec;
+ VALUE obj;
+
+ ec = ec_key_new_from_group(arg);
+
+ obj = ec_instance(klass, ec);
+ if (obj == Qfalse) {
+ EC_KEY_free(ec);
+ ossl_raise(eECError, NULL);
+ }
+
+ if (!EC_KEY_generate_key(ec))
+ ossl_raise(eECError, "EC_KEY_generate_key");
+
+ return obj;
+}
/* call-seq:
* OpenSSL::PKey::EC.new()
@@ -165,9 +228,8 @@ VALUE ossl_ec_new(EVP_PKEY *pkey)
static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
{
EVP_PKEY *pkey;
- EC_KEY *ec = NULL;
+ EC_KEY *ec;
VALUE arg, pass;
- VALUE group = Qnil;
GetPKey(self, pkey);
if (pkey->pkey.ec)
@@ -176,58 +238,43 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
rb_scan_args(argc, argv, "02", &arg, &pass);
if (NIL_P(arg)) {
- ec = EC_KEY_new();
+ if (!(ec = EC_KEY_new()))
+ ossl_raise(eECError, NULL);
+ } else if (rb_obj_is_kind_of(arg, cEC)) {
+ EC_KEY *other_ec = NULL;
+
+ SafeRequire_EC_KEY(arg, other_ec);
+ if (!(ec = EC_KEY_dup(other_ec)))
+ ossl_raise(eECError, NULL);
+ } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
+ ec = ec_key_new_from_group(arg);
} else {
- if (rb_obj_is_kind_of(arg, cEC)) {
- EC_KEY *other_ec = NULL;
-
- SafeRequire_EC_KEY(arg, other_ec);
- ec = EC_KEY_dup(other_ec);
- } else if (rb_obj_is_kind_of(arg, cEC_GROUP)) {
- ec = EC_KEY_new();
- group = arg;
- } else {
- BIO *in;
-
- pass = ossl_pem_passwd_value(pass);
- in = ossl_obj2bio(arg);
-
- ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
- }
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = d2i_ECPrivateKey_bio(in, NULL);
- }
- if (!ec) {
- OSSL_BIO_reset(in);
- ec = d2i_EC_PUBKEY_bio(in, NULL);
- }
-
- BIO_free(in);
-
- if (ec == NULL) {
- const char *name = StringValueCStr(arg);
- int nid = OBJ_sn2nid(name);
+ BIO *in;
- ossl_clear_error(); /* ignore errors in the previous d2i_EC_PUBKEY_bio() */
- if (nid == NID_undef)
- ossl_raise(eECError, "unknown curve name (%"PRIsVALUE")", arg);
+ pass = ossl_pem_passwd_value(pass);
+ in = ossl_obj2bio(arg);
- if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
- ossl_raise(eECError, "unable to create curve (%"PRIsVALUE")\n", arg);
+ ec = PEM_read_bio_ECPrivateKey(in, NULL, ossl_pem_passwd_cb, (void *)pass);
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = PEM_read_bio_EC_PUBKEY(in, NULL, ossl_pem_passwd_cb, (void *)pass);
+ }
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = d2i_ECPrivateKey_bio(in, NULL);
+ }
+ if (!ec) {
+ OSSL_BIO_reset(in);
+ ec = d2i_EC_PUBKEY_bio(in, NULL);
+ }
+ BIO_free(in);
- EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE);
- EC_KEY_set_conv_form(ec, POINT_CONVERSION_UNCOMPRESSED);
- }
- }
+ if (!ec) {
+ ossl_clear_error();
+ ec = ec_key_new_from_group(arg);
+ }
}
- if (ec == NULL)
- ossl_raise(eECError, NULL);
-
if (!EVP_PKEY_assign_EC_KEY(pkey, ec)) {
EC_KEY_free(ec);
ossl_raise(eECError, "EVP_PKEY_assign_EC_KEY");
@@ -235,9 +282,6 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self)
rb_iv_set(self, "@group", Qnil);
- if (!NIL_P(group))
- rb_funcall(self, rb_intern("group="), 1, arg);
-
return self;
}
@@ -1620,6 +1664,7 @@ void Init_ossl_ec(void)
rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0);
+ rb_define_singleton_method(cEC, "generate", ossl_ec_key_s_generate, 1);
rb_define_method(cEC, "initialize", ossl_ec_key_initialize, -1);
/* copy/dup/cmp */
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 712507f609..4161e9b0e0 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -38,6 +38,15 @@ class OpenSSL::TestEC < OpenSSL::TestCase
end
end
+ def test_generate
+ assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") }
+ g = OpenSSL::PKey::EC::Group.new("prime256v1")
+ ec = OpenSSL::PKey::EC.generate(g)
+ assert_equal(true, ec.private?)
+ ec = OpenSSL::PKey::EC.generate("prime256v1")
+ assert_equal(true, ec.private?)
+ end
+
def test_check_key
for key in @keys
assert_equal(true, key.check_key)