[前][次][番号順一覧][スレッド一覧]

ruby-changes:42974

From: rhe <ko1@a...>
Date: Wed, 18 May 2016 11:55:52 +0900 (JST)
Subject: [ruby-changes:42974] rhe:r55048 (trunk): ext/openssl: refactor OpenSSL::PKey::EC::Point#mul

rhe	2016-05-18 11:55:46 +0900 (Wed, 18 May 2016)

  New Revision: 55048

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=55048

  Log:
    ext/openssl: refactor OpenSSL::PKey::EC::Point#mul
    
    * ext/openssl/ossl_pkey_ec.c (ossl_ec_point_mul): Validate the
      arguments before passing to EC_POINT(s)_mul(). Add description of this
      method.  [ruby-core:65152] [Bug #10268]
    
    * test/openssl/test_pkey_ec.rb (test_ec_point_mul): Test that
      OpenSSL::PKey::EC::Point#mul works.

  Modified files:
    trunk/ChangeLog
    trunk/ext/openssl/ossl_pkey_ec.c
    trunk/test/openssl/test_pkey_ec.rb
Index: test/openssl/test_pkey_ec.rb
===================================================================
--- test/openssl/test_pkey_ec.rb	(revision 55047)
+++ test/openssl/test_pkey_ec.rb	(revision 55048)
@@ -190,19 +190,38 @@ class OpenSSL::TestEC < Test::Unit::Test https://github.com/ruby/ruby/blob/trunk/test/openssl/test_pkey_ec.rb#L190
   end
 
   def test_ec_point_mul
-    ec = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
-    p1 = ec.public_key
-    bn1 = OpenSSL::BN.new('10')
-    bn2 = OpenSSL::BN.new('20')
+    # y^2 = x^3 + 2x + 2 over F_17
+    # generator is (5, 1)
+    group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
+    gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16))
+    group.set_generator(gen, 0, 0)
 
-    p2 = p1.mul(bn1)
-    assert(p1.group == p2.group)
-    p2 = p1.mul(bn1, bn2)
-    assert(p1.group == p2.group)
-    p2 = p1.mul([bn1, bn2], [p1])
-    assert(p1.group == p2.group)
-    p2 = p1.mul([bn1, bn2], [p1], bn2)
-    assert(p1.group == p2.group)
+    # 3 * (6, 3) = (16, 13)
+    point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16))
+    result_a1 = point_a.mul(3.to_bn)
+    assert_equal("04100D", result_a1.to_bn.to_s(16))
+    # 3 * (6, 3) + 3 * (5, 1) = (7, 6)
+    result_a2 = point_a.mul(3.to_bn, 3.to_bn)
+    assert_equal("040706", result_a2.to_bn.to_s(16))
+    # 3 * point_a = 3 * (6, 3) = (16, 13)
+    result_b1 = point_a.mul([3.to_bn], [])
+    assert_equal("04100D", result_b1.to_bn.to_s(16))
+    # 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11)
+    result_b1 = point_a.mul([3.to_bn, 2.to_bn], [point_a])
+    assert_equal("04070B", result_b1.to_bn.to_s(16))
+    # 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10)
+    result_b1 = point_a.mul([3.to_bn], [], 5)
+    assert_equal("040D0A", result_b1.to_bn.to_s(16))
+
+    p256_key = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
+    p256_g = p256_key.group
+    assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key))
+
+    # invalid argument
+    assert_raise(TypeError) { point_a.mul(nil) }
+    assert_raise(ArgumentError) { point_a.mul([1.to_bn], [point_a]) }
+    assert_raise(TypeError) { point_a.mul([1.to_bn], nil) }
+    assert_raise(TypeError) { point_a.mul([nil], []) }
   end
 
 # test Group: asn1_flag, point_conversion
Index: ChangeLog
===================================================================
--- ChangeLog	(revision 55047)
+++ ChangeLog	(revision 55048)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Wed May 18 11:53:49 2016  Kazuki Yamaguchi  <k@r...>
+
+	* ext/openssl/ossl_pkey_ec.c (ossl_ec_point_mul): Validate the
+	  arguments before passing to EC_POINT(s)_mul(). Add description of this
+	  method.  [ruby-core:65152] [Bug #10268]
+
+	* test/openssl/test_pkey_ec.rb (test_ec_point_mul): Test that
+	  OpenSSL::PKey::EC::Point#mul works.
+
 Wed May 18 11:19:59 2016  Kazuki Yamaguchi  <k@r...>
 
 	* ext/openssl/ossl_bn.c (try_convert_to_bnptr): Extracted from
Index: ext/openssl/ossl_pkey_ec.c
===================================================================
--- ext/openssl/ossl_pkey_ec.c	(revision 55047)
+++ ext/openssl/ossl_pkey_ec.c	(revision 55048)
@@ -1500,74 +1500,84 @@ static VALUE ossl_ec_point_to_bn(VALUE s https://github.com/ruby/ruby/blob/trunk/ext/openssl/ossl_pkey_ec.c#L1500
 
 /*
  *  call-seq:
- *     point.mul(bn)  => point
- *     point.mul(bn, bn) => point
- *     point.mul([bn], [point]) => point
- *     point.mul([bn], [point], bn) => point
+ *     point.mul(bn1 [, bn2]) => point
+ *     point.mul(bns, points [, bn2]) => point
+ *
+ * Performs elliptic curve point multiplication.
+ *
+ * The first form calculates <tt>bn1 * point + bn2 * G</tt>, where +G+ is the
+ * generator of the group of +point+. +bn2+ may be ommitted, and in that case,
+ * the result is just <tt>bn1 * point</tt>.
+ *
+ * The second form calculates <tt>bns[0] * point + bns[1] * points[0] + ...
+ * + bns[-1] * points[-1] + bn2 * G</tt>. +bn2+ may be ommitted. +bns+ must be
+ * an array of OpenSSL::BN. +points+ must be an array of
+ * OpenSSL::PKey::EC::Point. Please note that <tt>points[0]</tt> is not
+ * multiplied by <tt>bns[0]</tt>, but <tt>bns[1]</tt>.
  */
 static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self)
 {
-    EC_POINT *point1, *point2;
+    EC_POINT *point_self, *point_result;
     const EC_GROUP *group;
     VALUE group_v = rb_iv_get(self, "@group");
-    VALUE bn_v1, bn_v2, r, points_v;
-    BIGNUM *bn1 = NULL, *bn2 = NULL;
+    VALUE arg1, arg2, arg3, result;
+    const BIGNUM *bn_g = NULL;
 
-    Require_EC_POINT(self, point1);
+    Require_EC_POINT(self, point_self);
     SafeRequire_EC_GROUP(group_v, group);
 
-    r = rb_obj_alloc(cEC_POINT);
-    ossl_ec_point_initialize(1, &group_v, r);
-    Require_EC_POINT(r, point2);
-
-    argc = rb_scan_args(argc, argv, "12", &bn_v1, &points_v, &bn_v2);
-
-    if (rb_obj_is_kind_of(bn_v1, cBN)) {
-        bn1 = GetBNPtr(bn_v1);
-        if (argc >= 2) {
-            bn2 = GetBNPtr(points_v);
-        }
-        if (EC_POINT_mul(group, point2, bn2, point1, bn1, ossl_bn_ctx) != 1)
-            ossl_raise(eEC_POINT, "Multiplication failed");
+    result = rb_obj_alloc(cEC_POINT);
+    ossl_ec_point_initialize(1, &group_v, result);
+    Require_EC_POINT(result, point_result);
+
+    rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3);
+    if (rb_obj_is_kind_of(arg1, cBN)) {
+	BIGNUM *bn = GetBNPtr(arg1);
+	if (argc >= 2)
+	    bn_g = GetBNPtr(arg2);
+
+	if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1)
+	    ossl_raise(eEC_POINT, NULL);
     } else {
-        size_t i, points_len, bignums_len;
-        const EC_POINT **points;
-        const BIGNUM **bignums;
-
-        Check_Type(bn_v1, T_ARRAY);
-        bignums_len = RARRAY_LEN(bn_v1);
-        bignums = (const BIGNUM **)OPENSSL_malloc(bignums_len * (int)sizeof(BIGNUM *));
-
-        for (i = 0; i < bignums_len; ++i) {
-            bignums[i] = GetBNPtr(rb_ary_entry(bn_v1, i));
-        }
-
-        if (!rb_obj_is_kind_of(points_v, rb_cArray)) {
-            OPENSSL_free((void *)bignums);
-            rb_raise(rb_eTypeError, "Argument2 must be an array");
-        }
-
-        rb_ary_unshift(points_v, self);
-        points_len = RARRAY_LEN(points_v);
-        points = (const EC_POINT **)OPENSSL_malloc(points_len * (int)sizeof(EC_POINT *));
-
-        for (i = 0; i < points_len; ++i) {
-            Get_EC_POINT(rb_ary_entry(points_v, i), points[i]);
-        }
-
-        if (argc >= 3) {
-            bn2 = GetBNPtr(bn_v2);
-        }
-        if (EC_POINTs_mul(group, point2, bn2, points_len, points, bignums, ossl_bn_ctx) != 1) {
-            OPENSSL_free((void *)bignums);
-            OPENSSL_free((void *)points);
-            ossl_raise(eEC_POINT, "Multiplication failed");
-        }
-        OPENSSL_free((void *)bignums);
-        OPENSSL_free((void *)points);
+	/*
+	 * bignums | arg1[0] | arg1[1] | arg1[2] | ...
+	 * points  | self    | arg2[0] | arg2[1] | ...
+	 */
+	int i, num;
+	VALUE tmp_p, tmp_b;
+	const EC_POINT **points;
+	const BIGNUM **bignums;
+
+	if (!rb_obj_is_kind_of(arg1, rb_cArray) ||
+	    !rb_obj_is_kind_of(arg2, rb_cArray))
+	    ossl_raise(rb_eTypeError, "points must be array");
+	if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */
+	    ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation");
+
+	num = RARRAY_LEN(arg1);
+	bignums = ALLOCV_N(const BIGNUM *, tmp_b, num);
+	for (i = 0; i < num; i++)
+	    bignums[i] = GetBNPtr(RARRAY_AREF(arg1, i));
+
+	points = ALLOCV_N(const EC_POINT *, tmp_p, num);
+	points[0] = point_self; /* self */
+	for (i = 0; i < num - 1; i++)
+	    SafeRequire_EC_POINT(RARRAY_AREF(arg2, i), points[i + 1]);
+
+	if (argc >= 3)
+	    bn_g = GetBNPtr(arg3);
+
+	if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) {
+	    ALLOCV_END(tmp_b);
+	    ALLOCV_END(tmp_p);
+	    ossl_raise(eEC_POINT, NULL);
+	}
+
+	ALLOCV_END(tmp_b);
+	ALLOCV_END(tmp_p);
     }
 
-    return r;
+    return result;
 }
 
 static void no_copy(VALUE klass)

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]