[openssl] OpenSSL_1_1_1-stable update

tomas at openssl.org tomas at openssl.org
Mon May 17 08:41:58 UTC 2021


The branch OpenSSL_1_1_1-stable has been updated
       via  7e12c2b3d9ccf97186e4d2cb27aafb084c893ce5 (commit)
       via  c054a6d45dab1bbe38e1c89518e40ba9a9660baa (commit)
      from  b743b16113ca0e30c383191c804de37dbfc4f12e (commit)


- Log -----------------------------------------------------------------
commit 7e12c2b3d9ccf97186e4d2cb27aafb084c893ce5
Author: Theo Buehler <tb at openbsd.org>
Date:   Sat May 1 13:09:10 2021 +0200

    Test oct2point for hybrid point encoding of (0, y)
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15112)

commit c054a6d45dab1bbe38e1c89518e40ba9a9660baa
Author: Theo Buehler <tb at openbsd.org>
Date:   Sat May 1 12:25:50 2021 +0200

    Avoid division by zero in hybrid point encoding
    
    In hybrid and compressed point encodings, the form octet contains a bit
    of information allowing to calculate y from x.  For a point on a binary
    curve, this bit is zero if x is zero, otherwise it must match the
    rightmost bit of of the field element y / x.  The existing code only
    considers the second possibility. It could thus incorrecly fail with a
    division by zero error as found by Guido Vranken's cryptofuzz.
    
    This commit adds a few explanatory comments to oct2point. The only
    actual code change is in the last hunk which adds a BN_is_zero(x)
    check to avoid the division by zero.
    
    Fixes #15021
    
    Reviewed-by: Nicola Tuveri <nic.tuv at gmail.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    Reviewed-by: Tomas Mraz <tomas at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/15112)

-----------------------------------------------------------------------

Summary of changes:
 crypto/ec/ec2_oct.c | 41 +++++++++++++++++++++++++++++++++--------
 test/ectest.c       | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 84 insertions(+), 9 deletions(-)

diff --git a/crypto/ec/ec2_oct.c b/crypto/ec/ec2_oct.c
index 48543265ee..a0ff0496b3 100644
--- a/crypto/ec/ec2_oct.c
+++ b/crypto/ec/ec2_oct.c
@@ -247,9 +247,21 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
         ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
         return 0;
     }
-    form = buf[0];
-    y_bit = form & 1;
-    form = form & ~1U;
+
+    /*
+     * The first octet is the point converison octet PC, see X9.62, page 4
+     * and section 4.4.2.  It must be:
+     *     0x00          for the point at infinity
+     *     0x02 or 0x03  for compressed form
+     *     0x04          for uncompressed form
+     *     0x06 or 0x07  for hybrid form.
+     * For compressed or hybrid forms, we store the last bit of buf[0] as
+     * y_bit and clear it from buf[0] so as to obtain a POINT_CONVERSION_*.
+     * We error if buf[0] contains any but the above values.
+     */
+    y_bit = buf[0] & 1;
+    form = buf[0] & ~1U;
+
     if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
         && (form != POINT_CONVERSION_UNCOMPRESSED)
         && (form != POINT_CONVERSION_HYBRID)) {
@@ -261,6 +273,7 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
         return 0;
     }
 
+    /* The point at infinity is represented by a single zero octet. */
     if (form == 0) {
         if (len != 1) {
             ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
@@ -312,11 +325,23 @@ int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
             goto err;
         }
         if (form == POINT_CONVERSION_HYBRID) {
-            if (!group->meth->field_div(group, yxi, y, x, ctx))
-                goto err;
-            if (y_bit != BN_is_odd(yxi)) {
-                ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
-                goto err;
+            /*
+             * Check that the form in the encoding was set correctly
+             * according to X9.62 4.4.2.a, 4(c), see also first paragraph
+             * of X9.62, 4.4.1.b.
+             */
+            if (BN_is_zero(x)) {
+                if (y_bit != 0) {
+                    ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+                    goto err;
+                }
+            } else {
+                if (!group->meth->field_div(group, yxi, y, x, ctx))
+                    goto err;
+                if (y_bit != BN_is_odd(yxi)) {
+                    ECerr(ERR_LIB_EC, EC_R_INVALID_ENCODING);
+                    goto err;
+                }
             }
         }
 
diff --git a/test/ectest.c b/test/ectest.c
index 9bdbf70afb..bb2ff699c6 100644
--- a/test/ectest.c
+++ b/test/ectest.c
@@ -1124,7 +1124,56 @@ err:
     BN_free(yplusone);
     return r;
 }
-# endif
+
+static int hybrid_point_encoding_test(void)
+{
+    BIGNUM *x = NULL, *y = NULL;
+    EC_GROUP *group = NULL;
+    EC_POINT *point = NULL;
+    unsigned char *buf = NULL;
+    size_t len;
+    int r = 0;
+
+    if (!TEST_true(BN_dec2bn(&x, "0"))
+        || !TEST_true(BN_dec2bn(&y, "1"))
+        || !TEST_ptr(group = EC_GROUP_new_by_curve_name(NID_sect571k1))
+        || !TEST_ptr(point = EC_POINT_new(group))
+        || !TEST_true(EC_POINT_set_affine_coordinates(group, point, x, y, NULL))
+        || !TEST_size_t_ne(0, (len = EC_POINT_point2oct(group,
+                                                        point,
+                                                        POINT_CONVERSION_HYBRID,
+                                                        NULL,
+                                                        0,
+                                                        NULL)))
+        || !TEST_ptr(buf = OPENSSL_malloc(len))
+        || !TEST_size_t_eq(len, EC_POINT_point2oct(group,
+                                                   point,
+                                                   POINT_CONVERSION_HYBRID,
+                                                   buf,
+                                                   len,
+                                                   NULL)))
+        goto err;
+
+    r = 1;
+
+    /* buf contains a valid hybrid point, check that we can decode it. */
+    if (!TEST_true(EC_POINT_oct2point(group, point, buf, len, NULL)))
+        r = 0;
+
+    /* Flip the y_bit and verify that the invalid encoding is rejected. */
+    buf[0] ^= 1;
+    if (!TEST_false(EC_POINT_oct2point(group, point, buf, len, NULL)))
+        r = 0;
+
+err:
+    BN_free(x);
+    BN_free(y);
+    EC_GROUP_free(group);
+    EC_POINT_free(point);
+    OPENSSL_free(buf);
+    return r;
+}
+#endif
 
 static int internal_curve_test(int n)
 {
@@ -2195,6 +2244,7 @@ int setup_tests(void)
     ADD_ALL_TESTS(cardinality_test, crv_len);
     ADD_TEST(prime_field_tests);
 # ifndef OPENSSL_NO_EC2M
+    ADD_TEST(hybrid_point_encoding_test);
     ADD_TEST(char2_field_tests);
     ADD_ALL_TESTS(char2_curve_test, OSSL_NELEM(char2_curve_tests));
 # endif


More information about the openssl-commits mailing list