ruby-changes:49119
From: rhe <ko1@a...>
Date: Thu, 14 Dec 2017 20:19:21 +0900 (JST)
Subject: [ruby-changes:49119] rhe:r61235 (trunk): openssl: import v2.1.0
rhe 2017-12-14 20:19:16 +0900 (Thu, 14 Dec 2017) New Revision: 61235 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=61235 Log: openssl: import v2.1.0 Import Ruby/OpenSSL 2.1.0. Commits since v2.1.0.beta2 can be found at: https://github.com/ruby/openssl/compare/v2.1.0.beta2...v2.1.0 ---------------------------------------------------------------- Kazuki Yamaguchi (8): test/test_ssl: prevent changing default internal encoding ssl: remove a misleading comment pkey/ec: rearrange PKey::EC::Point#initialize ssl: remove unreachable code asn1: fix docs pkey/ec: add support for octet string encoding of EC point Ruby/OpenSSL 2.0.7 Ruby/OpenSSL 2.1.0 eregon (1): Fix test-all tests to avoid creating report_on_exception warnings Modified files: trunk/ext/openssl/History.md trunk/ext/openssl/lib/openssl/pkey.rb trunk/ext/openssl/openssl.gemspec trunk/ext/openssl/ossl_asn1.c trunk/ext/openssl/ossl_pkey_ec.c trunk/ext/openssl/ossl_ssl.c trunk/test/openssl/test_pkey_ec.rb Index: ext/openssl/ossl_ssl.c =================================================================== --- ext/openssl/ossl_ssl.c (revision 61234) +++ ext/openssl/ossl_ssl.c (revision 61235) @@ -377,7 +377,6 @@ ossl_call_session_get_cb(VALUE ary) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L377 return rb_funcallv(cb, id_call, 1, &ary); } -/* this method is currently only called for servers (in OpenSSL <= 0.9.8e) */ static SSL_SESSION * #if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy) @@ -1035,10 +1034,6 @@ ossl_sslctx_set_ciphers(VALUE self, VALU https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_ssl.c#L1034 } GetSSLCTX(self, ctx); - if(!ctx){ - ossl_raise(eSSLError, "SSL_CTX is not initialized."); - return Qnil; - } if (!SSL_CTX_set_cipher_list(ctx, StringValueCStr(str))) { ossl_raise(eSSLError, "SSL_CTX_set_cipher_list"); } Index: ext/openssl/ossl_pkey_ec.c =================================================================== --- ext/openssl/ossl_pkey_ec.c (revision 61234) +++ ext/openssl/ossl_pkey_ec.c (revision 61235) @@ -1319,76 +1319,61 @@ ec_point_new(const EC_POINT *point, cons https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L1319 return obj; } +static VALUE ossl_ec_point_initialize_copy(VALUE, VALUE); /* * call-seq: * OpenSSL::PKey::EC::Point.new(point) - * OpenSSL::PKey::EC::Point.new(group) - * OpenSSL::PKey::EC::Point.new(group, bn) + * OpenSSL::PKey::EC::Point.new(group [, encoded_point]) * - * See the OpenSSL documentation for EC_POINT_* + * Creates a new instance of OpenSSL::PKey::EC::Point. If the only argument is + * an instance of EC::Point, a copy is returned. Otherwise, creates a point + * that belongs to _group_. + * + * _encoded_point_ is the octet string representation of the point. This + * must be either a String or an OpenSSL::BN. */ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self) { EC_POINT *point; - VALUE arg1, arg2; - VALUE group_v = Qnil; - const EC_GROUP *group = NULL; + VALUE group_v, arg2; + const EC_GROUP *group; TypedData_Get_Struct(self, EC_POINT, &ossl_ec_point_type, point); if (point) - ossl_raise(eEC_POINT, "EC_POINT already initialized"); + rb_raise(eEC_POINT, "EC_POINT already initialized"); - switch (rb_scan_args(argc, argv, "11", &arg1, &arg2)) { - case 1: - if (rb_obj_is_kind_of(arg1, cEC_POINT)) { - const EC_POINT *arg_point; - - group_v = rb_attr_get(arg1, id_i_group); - GetECGroup(group_v, group); - GetECPoint(arg1, arg_point); - - point = EC_POINT_dup(arg_point, group); - } else if (rb_obj_is_kind_of(arg1, cEC_GROUP)) { - group_v = arg1; - GetECGroup(group_v, group); - - point = EC_POINT_new(group); - } else { - ossl_raise(eEC_POINT, "wrong argument type: must be OpenSSL::PKey::EC::Point or OpenSSL::Pkey::EC::Group"); - } - - break; - case 2: - if (!rb_obj_is_kind_of(arg1, cEC_GROUP)) - ossl_raise(rb_eArgError, "1st argument must be OpenSSL::PKey::EC::Group"); - group_v = arg1; - GetECGroup(group_v, group); - - if (rb_obj_is_kind_of(arg2, cBN)) { - const BIGNUM *bn = GetBNPtr(arg2); - - point = EC_POINT_bn2point(group, bn, NULL, ossl_bn_ctx); - } else { - BIO *in = ossl_obj2bio(&arg1); - -/* BUG: finish me */ - - BIO_free(in); - - if (point == NULL) { - ossl_raise(eEC_POINT, "unknown type for 2nd arg"); - } - } - break; - default: - ossl_raise(rb_eArgError, "wrong number of arguments"); + rb_scan_args(argc, argv, "11", &group_v, &arg2); + if (rb_obj_is_kind_of(group_v, cEC_POINT)) { + if (argc != 1) + rb_raise(rb_eArgError, "invalid second argument"); + return ossl_ec_point_initialize_copy(self, group_v); } - if (point == NULL) - ossl_raise(eEC_POINT, NULL); - - if (NIL_P(group_v)) - ossl_raise(rb_eRuntimeError, "missing group (internal error)"); + GetECGroup(group_v, group); + if (argc == 1) { + point = EC_POINT_new(group); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_new"); + } + else { + if (rb_obj_is_kind_of(arg2, cBN)) { + point = EC_POINT_bn2point(group, GetBNPtr(arg2), NULL, ossl_bn_ctx); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_bn2point"); + } + else { + StringValue(arg2); + point = EC_POINT_new(group); + if (!point) + ossl_raise(eEC_POINT, "EC_POINT_new"); + if (!EC_POINT_oct2point(group, point, + (unsigned char *)RSTRING_PTR(arg2), + RSTRING_LEN(arg2), ossl_bn_ctx)) { + EC_POINT_free(point); + ossl_raise(eEC_POINT, "EC_POINT_oct2point"); + } + } + } RTYPEDDATA_DATA(self) = point; rb_ivar_set(self, id_i_group, group_v); @@ -1543,38 +1528,38 @@ static VALUE ossl_ec_point_set_to_infini https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L1528 /* * call-seq: - * point.to_bn(conversion_form = nil) => OpenSSL::BN + * point.to_octet_string(conversion_form) -> String + * + * Returns the octet string representation of the elliptic curve point. * - * Convert the EC point into an octet string and store in an OpenSSL::BN. If - * _conversion_form_ is given, the point data is converted using the specified - * form. If not given, the default form set in the EC::Group object is used. + * _conversion_form_ specifies how the point is converted. Possible values are: * - * See also EC::Point#point_conversion_form=. + * - +:compressed+ + * - +:uncompressed+ + * - +:hybrid+ */ static VALUE -ossl_ec_point_to_bn(int argc, VALUE *argv, VALUE self) +ossl_ec_point_to_octet_string(VALUE self, VALUE conversion_form) { EC_POINT *point; - VALUE form_obj, bn_obj; const EC_GROUP *group; point_conversion_form_t form; - BIGNUM *bn; + VALUE str; + size_t len; GetECPoint(self, point); GetECPointGroup(self, group); - rb_scan_args(argc, argv, "01", &form_obj); - if (NIL_P(form_obj)) - form = EC_GROUP_get_point_conversion_form(group); - else - form = parse_point_conversion_form_symbol(form_obj); - - bn_obj = rb_obj_alloc(cBN); - bn = GetBNPtr(bn_obj); - - if (EC_POINT_point2bn(group, point, form, bn, ossl_bn_ctx) == NULL) - ossl_raise(eEC_POINT, "EC_POINT_point2bn"); + form = parse_point_conversion_form_symbol(conversion_form); - return bn_obj; + len = EC_POINT_point2oct(group, point, form, NULL, 0, ossl_bn_ctx); + if (!len) + ossl_raise(eEC_POINT, "EC_POINT_point2oct"); + str = rb_str_new(NULL, (long)len); + if (!EC_POINT_point2oct(group, point, form, + (unsigned char *)RSTRING_PTR(str), len, + ossl_bn_ctx)) + ossl_raise(eEC_POINT, "EC_POINT_point2oct"); + return str; } /* @@ -1799,7 +1784,7 @@ void Init_ossl_ec(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L1784 rb_define_method(cEC_POINT, "set_to_infinity!", ossl_ec_point_set_to_infinity, 0); /* all the other methods */ - rb_define_method(cEC_POINT, "to_bn", ossl_ec_point_to_bn, -1); + rb_define_method(cEC_POINT, "to_octet_string", ossl_ec_point_to_octet_string, 1); rb_define_method(cEC_POINT, "mul", ossl_ec_point_mul, -1); id_i_group = rb_intern("@group"); Index: ext/openssl/openssl.gemspec =================================================================== --- ext/openssl/openssl.gemspec (revision 61234) +++ ext/openssl/openssl.gemspec (revision 61235) @@ -1,16 +1,16 @@ https://github.com/ruby/ruby/blob/trunk/ext/openssl/openssl.gemspec#L1 # -*- encoding: utf-8 -*- -# stub: openssl 2.1.0.beta2 ruby lib +# stub: openssl 2.1.0 ruby lib # stub: ext/openssl/extconf.rb Gem::Specification.new do |s| s.name = "openssl".freeze - s.version = "2.1.0.beta2" + s.version = "2.1.0" - s.required_rubygems_version = Gem::Requirement.new("> 1.3.1".freeze) if s.respond_to? :required_rubygems_version= + s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version= s.metadata = { "msys2_mingw_dependencies" => "openssl" } if s.respond_to? :metadata= s.require_paths = ["lib".freeze] s.authors = ["Martin Bosslet".freeze, "SHIBATA Hiroshi".freeze, "Zachary Scott".freeze, "Kazuki Yamaguchi".freeze] - s.date = "2017-11-25" + s.date = "2017-12-14" s.description = "It wraps the OpenSSL library.".freeze s.email = ["ruby-core@r...".freeze] s.extensions = ["ext/openssl/extconf.rb".freeze] @@ -20,7 +20,7 @@ Gem::Specification.new do |s| https://github.com/ruby/ruby/blob/trunk/ext/openssl/openssl.gemspec#L20 s.licenses = ["Ruby".freeze] s.rdoc_options = ["--main".freeze, "README.md".freeze] s.required_ruby_version = Gem::Requirement.new(">= 2.3.0".freeze) - s.rubygems_version = "2.7.2".freeze + s.rubygems_version = "2.7.3".freeze s.summary = "OpenSSL provides SSL, TLS and general purpose cryptography.".freeze if s.respond_to? :specification_version then Index: ext/openssl/lib/openssl/pkey.rb =================================================================== --- ext/openssl/lib/openssl/pkey.rb (revision 61234) +++ ext/openssl/lib/openssl/pkey.rb (revision 61235) @@ -1,3 +1,25 @@ https://github.com/ruby/ruby/blob/trunk/ext/openssl/lib/openssl/pkey.rb#L1 # frozen_string_literal: false -module OpenSSL +#-- +# Ruby/OpenSSL Project +# Copyright (C) 2017 Ruby/OpenSSL Project Authors +#++ + +module OpenSSL::PKey + if defined?(EC) + class EC::Point + # :call-seq: + # point.to_bn([conversion_form]) -> OpenSSL::BN + # + # Returns the octet string representation of the EC point as an instance of + # OpenSSL::BN. + # + # If _conversion_form_ is not given, the _point_conversion_form_ attribute + # set to the group is used. + # + # See #to_octet_string for more information. + def to_bn(conversion_form = group.point_conversion_form) + OpenSSL::BN.new(to_octet_string(conversion_form), 2) + end + end + end end Index: ext/openssl/ossl_asn1.c =================================================================== --- ext/openssl/ossl_asn1.c (revision 61234) +++ ext/openssl/ossl_asn1.c (revision 61235) @@ -1665,12 +1665,12 @@ Init_ossl_asn1(void) https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_asn1.c#L1665 * == Primitive sub-classes and their mapping to Ruby classes * * OpenSSL::ASN1::EndOfContent <=> _value_ is always +nil+ * * OpenSSL::ASN1::Boolean <=> _value_ is +true+ or +false+ - * * OpenSSL::ASN1::Integer <=> _value_ is an Integer + * * OpenSSL::ASN1::Integer <=> _value_ is an OpenSSL::BN * * OpenSSL::ASN1::BitString <=> _value_ is a String * * OpenSSL::ASN1::OctetString <=> _value_ is a String * * OpenSSL::ASN1::Null <=> _value_ is always +nil+ * * OpenSSL::ASN1::Object <=> _value_ is a String - * * OpenSSL::ASN1::Enumerated <=> _value_ is an Integer + * * OpenSSL::ASN1::Enumerated <=> _value_ is an OpenSSL::BN * * OpenSSL::ASN1::UTF8String <=> _value_ is a String * * OpenSSL::ASN1::NumericString <=> _value_ is a String * * OpenSSL::ASN1::PrintableString <=> _value_ is a String Index: ext/openssl/History.md =================================================================== --- ext/openssl/History.md (revision 61234) +++ ext/openssl/History.md (revision 61235) @@ -1,5 +1,5 @@ https://github.com/ruby/ruby/blob/trunk/ext/openssl/History.md#L1 -Version 2.1.0.beta2 -=================== +Version 2.1.0 +============= Notable changes --------------- @@ -50,6 +50,24 @@ Notable changes https://github.com/ruby/ruby/blob/trunk/ext/openssl/History.md#L50 [[GitHub #169]](https://github.com/ruby/openssl/pull/169) * OpenSSL::SSL::SSLContext#add_certificate is added. [[GitHub #167]](https://github.com/ruby/openssl/pull/167) +* OpenSSL::PKey::EC::Point#to_octet_string is added. + OpenSSL::PKey::EC::Point.new can now take String as the second argument. + [[GitHub #177]](https://github.com/ruby/openssl/pull/177) + + +Version 2.0.7 +============= + +Bug fixes +--------- + +* OpenSSL::Cipher#auth_data= could segfault if called against a non-AEAD cipher. + [[Bug #14024]](https://bugs.ruby-lang.org/issues/14024) +* OpenSSL::X509::Certificate#public_key= (and similar methods) could segfault + when an instance of OpenSSL::PKey::PKey with no public key components is + passed. + [[Bug #14087]](https://bugs.ruby-lang.org/issues/14087) + [[GitHub #168]](https://github.com/ruby/openssl/pull/168) Version 2.0.6 Index: test/openssl/test_pkey_ec.rb =================================================================== --- test/openssl/test_pkey_ec.rb (revision 61234) +++ test/openssl/test_pkey_ec.rb (revision 61235) @@ -120,14 +120,9 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L120 asn1 = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(1), OpenSSL::ASN1::OctetString(p256.private_key.to_s(2)), - OpenSSL::ASN1::ASN1Data.new( - [OpenSSL::ASN1::ObjectId("prime256v1")], - 0, :CONTEXT_SPECIFIC - ), - OpenSSL::ASN1::ASN1Data.new( - [OpenSSL::ASN1::BitString(p256.public_key.to_bn.to_s(2))], - 1, :CONTEXT_SPECIFIC - ) + OpenSSL::ASN1::ObjectId("prime256v1", 0, :EXPLICIT), + OpenSSL::ASN1::BitString(p256.public_key.to_octet_string(:uncompressed), + 1, :EXPLICIT) ]) key = OpenSSL::PKey::EC.new(asn1.to_der) assert_predicate key, :private? @@ -181,7 +176,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L176 OpenSSL::ASN1::ObjectId("prime256v1") ]), OpenSSL::ASN1::BitString( - p256.public_key.to_bn.to_s(2) + p256.public_key.to_octet_string(:uncompressed) ) ]) key = OpenSSL::PKey::EC.new(asn1.to_der) @@ -224,7 +219,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L219 assert_equal :uncompressed, group4.point_conversion_form assert_equal group1, group4 assert_equal group1.curve_name, group4.curve_name - assert_equal group1.generator.to_bn, group4.generator.to_bn + assert_equal group1.generator.to_octet_string(:uncompressed), + group4.generator.to_octet_string(:uncompressed) assert_equal group1.order, group4.order assert_equal group1.cofactor, group4.cofactor assert_equal group1.seed, group4.seed @@ -239,34 +235,57 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L235 point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn) assert_equal point, point2 assert_equal point.to_bn, point2.to_bn + assert_equal point.to_octet_string(:uncompressed), + point2.to_octet_string(:uncompressed) + + point3 = OpenSSL::PKey::EC::Point.new(group, + point.to_octet_string(:uncompressed)) + assert_equal point, point3 + assert_equal point.to_bn, point3.to_bn + assert_equal point.to_octet_string(:uncompressed), + point3.to_octet_string(:uncompressed) + point2.invert! - assert_not_equal point.to_bn, point2.to_bn + point3.invert! + assert_not_equal point.to_octet_string(:uncompressed), + point2.to_octet_string(:uncompressed) + assert_equal point2.to_octet_string(:uncompressed), + point3.to_octet_string(:uncompressed) begin group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) group.point_conversion_form = :uncompressed - generator = OpenSSL::PKey::EC::Point.new(group, 0x040501.to_bn) + generator = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 })) group.set_generator(generator, 19, 1) - point = OpenSSL::PKey::EC::Point.new(group, 0x040603.to_bn) + point = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 })) rescue OpenSSL::PKey::EC::Group::Error pend "Patched OpenSSL rejected curve" if /unsupported field/ =~ $!.message raise end + assert_equal 0x040603.to_bn, point.to_bn assert_equal 0x040603.to_bn, point.to_bn(:uncompressed) assert_equal 0x0306.to_bn, point.to_bn(:compressed) assert_equal 0x070603.to_bn, point.to_bn(:hybrid) - assert_equal 0x040603.to_bn, point.to_bn + group2 = group.dup; group2.point_conversion_form = :compressed + point2 = OpenSSL::PKey::EC::Point.new(group2, B(%w{ 04 06 03 })) + assert_equal 0x0306.to_bn, point2.to_bn + + assert_equal B(%w{ 04 06 03 }), point.to_octet_string(:uncompressed) + assert_equal B(%w{ 03 06 }), point.to_octet_string(:compressed) + assert_equal B(%w{ 07 06 03 }), point.to_octet_string(:hybrid) + assert_equal true, point.on_curve? point.invert! # 8.5 - assert_equal 0x04060E.to_bn, point.to_bn + assert_equal B(%w{ 04 06 0E }), point.to_octet_string(:uncompressed) assert_equal true, point.on_curve? assert_equal false, point.infinity? point.set_to_infinity! assert_equal true, point.infinity? assert_equal 0.to_bn, point.to_bn + assert_equal B(%w{ 00 }), point.to_octet_string(:uncompressed) assert_equal true, point.on_curve? end @@ -276,25 +295,25 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L295 # generator is (5, 1) group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2) group.point_conversion_form = :uncompressed - gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16)) + gen = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 05 01 })) group.set_generator(gen, 19, 1) # 3 * (6, 3) = (16, 13) - point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16)) + point_a = OpenSSL::PKey::EC::Point.new(group, B(%w{ 04 06 03 })) result_a1 = point_a.mul(3) - assert_equal("04100D", result_a1.to_bn.to_s(16)) + assert_equal B(%w{ 04 10 0D }), result_a1.to_octet_string(:uncompressed) # 3 * (6, 3) + 3 * (5, 1) = (7, 6) result_a2 = point_a.mul(3, 3) - assert_equal("040706", result_a2.to_bn.to_s(16)) + assert_equal B(%w{ 04 07 06 }), result_a2.to_octet_string(:uncompressed) # 3 * point_a = 3 * (6, 3) = (16, 13) result_b1 = point_a.mul([3], []) - assert_equal("04100D", result_b1.to_bn.to_s(16)) + assert_equal B(%w{ 04 10 0D }), result_b1.to_octet_string(:uncompressed) # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11) result_b1 = point_a.mul([3, 2], [point_a]) - assert_equal("04070B", result_b1.to_bn.to_s(16)) + assert_equal B(%w{ 04 07 0B }), result_b1.to_octet_string(:uncompressed) # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10) result_b1 = point_a.mul([3], [], 5) - assert_equal("040D0A", result_b1.to_bn.to_s(16)) + assert_equal B(%w{ 04 0D 0A }), result_b1.to_octet_string(:uncompressed) rescue OpenSSL::PKey::EC::Group::Error # CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits raise if $!.message !~ /unsupported field/ @@ -316,6 +335,10 @@ class OpenSSL::TestEC < OpenSSL::PKeyTes https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L335 private + def B(ary) + [Array(ary).join].pack("H*") + end + def assert_same_ec(expected, key) check_component(expected, key, [:group, :public_key, :private_key]) end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/