1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

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
This commit is contained in:
rhe 2016-05-24 16:30:15 +00:00
parent 8cbd74a362
commit 85500b6634
3 changed files with 117 additions and 51 deletions

View file

@ -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.

View file

@ -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;
BIO *in;
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);
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);
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);
ossl_clear_error(); /* ignore errors in the previous d2i_EC_PUBKEY_bio() */
if (nid == NID_undef)
ossl_raise(eECError, "unknown curve name (%"PRIsVALUE")", arg);
if ((ec = EC_KEY_new_by_curve_name(nid)) == NULL)
ossl_raise(eECError, "unable to create curve (%"PRIsVALUE")\n", arg);
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 */

View file

@ -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)