ECC: unify generic ec2 and ecp scalar multiplication, deprecate ec2_mult.c
authorBilly Brumley <bbrumley@gmail.com>
Tue, 24 Apr 2018 13:01:53 +0000 (16:01 +0300)
committerAndy Polyakov <appro@openssl.org>
Wed, 9 May 2018 11:30:38 +0000 (13:30 +0200)
Reviewed-by: Richard Levitte <levitte@openssl.org>
Reviewed-by: Andy Polyakov <appro@openssl.org>
Reviewed-by: Rich Salz <rsalz@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/6070)

CHANGES
crypto/ec/build.info
crypto/ec/ec2_mult.c [deleted file]
crypto/ec/ec2_smpl.c
crypto/ec/ec_lcl.h

diff --git a/CHANGES b/CHANGES
index 08586c0..742b673 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,6 +9,10 @@
 
  Changes between 1.1.0h and 1.1.1 [xx XXX xxxx]
 
+  *) Deprecate ec2_mult.c and unify scalar multiplication code paths for
+     binary and prime elliptic curves.
+     [Billy Bob Brumley]
+
   *) Remove ECDSA nonce padding: EC_POINT_mul is now responsible for
      constant time fixed point multiplication.
      [Billy Bob Brumley]
index 1e7814f..db506c5 100644 (file)
@@ -2,7 +2,7 @@ LIBS=../../libcrypto
 SOURCE[../../libcrypto]=\
         ec_lib.c ecp_smpl.c ecp_mont.c ecp_nist.c ec_cvt.c ec_mult.c \
         ec_err.c ec_curve.c ec_check.c ec_print.c ec_asn1.c ec_key.c \
-        ec2_smpl.c ec2_mult.c ec_ameth.c ec_pmeth.c eck_prn.c \
+        ec2_smpl.c ec_ameth.c ec_pmeth.c eck_prn.c \
         ecp_nistp224.c ecp_nistp256.c ecp_nistp521.c ecp_nistputil.c \
         ecp_oct.c ec2_oct.c ec_oct.c ec_kmeth.c ecdh_ossl.c ecdh_kdf.c \
         ecdsa_ossl.c ecdsa_sign.c ecdsa_vrf.c curve25519.c ecx_meth.c \
diff --git a/crypto/ec/ec2_mult.c b/crypto/ec/ec2_mult.c
deleted file mode 100644 (file)
index 891e810..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Copyright 2002-2016 The OpenSSL Project Authors. All Rights Reserved.
- * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved
- *
- * Licensed under the OpenSSL license (the "License").  You may not use
- * this file except in compliance with the License.  You can obtain a copy
- * in the file LICENSE in the source distribution or at
- * https://www.openssl.org/source/license.html
- */
-
-#include <openssl/err.h>
-
-#include "internal/bn_int.h"
-#include "ec_lcl.h"
-
-#ifndef OPENSSL_NO_EC2M
-
-/*-
- * Compute the x-coordinate x/z for the point 2*(x/z) in Montgomery projective
- * coordinates.
- * Uses algorithm Mdouble in appendix of
- *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
- *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- * modified to not require precomputation of c=b^{2^{m-1}}.
- */
-static int gf2m_Mdouble(const EC_GROUP *group, BIGNUM *x, BIGNUM *z,
-                        BN_CTX *ctx)
-{
-    BIGNUM *t1;
-    int ret = 0;
-
-    /* Since Mdouble is static we can guarantee that ctx != NULL. */
-    BN_CTX_start(ctx);
-    t1 = BN_CTX_get(ctx);
-    if (t1 == NULL)
-        goto err;
-
-    if (!group->meth->field_sqr(group, x, x, ctx))
-        goto err;
-    if (!group->meth->field_sqr(group, t1, z, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, z, x, t1, ctx))
-        goto err;
-    if (!group->meth->field_sqr(group, x, x, ctx))
-        goto err;
-    if (!group->meth->field_sqr(group, t1, t1, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, t1, group->b, t1, ctx))
-        goto err;
-    if (!BN_GF2m_add(x, x, t1))
-        goto err;
-
-    ret = 1;
-
- err:
-    BN_CTX_end(ctx);
-    return ret;
-}
-
-/*-
- * Compute the x-coordinate x1/z1 for the point (x1/z1)+(x2/x2) in Montgomery
- * projective coordinates.
- * Uses algorithm Madd in appendix of
- *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
- *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- */
-static int gf2m_Madd(const EC_GROUP *group, const BIGNUM *x, BIGNUM *x1,
-                     BIGNUM *z1, const BIGNUM *x2, const BIGNUM *z2,
-                     BN_CTX *ctx)
-{
-    BIGNUM *t1, *t2;
-    int ret = 0;
-
-    /* Since Madd is static we can guarantee that ctx != NULL. */
-    BN_CTX_start(ctx);
-    t1 = BN_CTX_get(ctx);
-    t2 = BN_CTX_get(ctx);
-    if (t2 == NULL)
-        goto err;
-
-    if (!BN_copy(t1, x))
-        goto err;
-    if (!group->meth->field_mul(group, x1, x1, z2, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, z1, z1, x2, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, t2, x1, z1, ctx))
-        goto err;
-    if (!BN_GF2m_add(z1, z1, x1))
-        goto err;
-    if (!group->meth->field_sqr(group, z1, z1, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, x1, z1, t1, ctx))
-        goto err;
-    if (!BN_GF2m_add(x1, x1, t2))
-        goto err;
-
-    ret = 1;
-
- err:
-    BN_CTX_end(ctx);
-    return ret;
-}
-
-/*-
- * Compute the x, y affine coordinates from the point (x1, z1) (x2, z2)
- * using Montgomery point multiplication algorithm Mxy() in appendix of
- *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
- *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- * Returns:
- *     0 on error
- *     1 if return value should be the point at infinity
- *     2 otherwise
- */
-static int gf2m_Mxy(const EC_GROUP *group, const BIGNUM *x, const BIGNUM *y,
-                    BIGNUM *x1, BIGNUM *z1, BIGNUM *x2, BIGNUM *z2,
-                    BN_CTX *ctx)
-{
-    BIGNUM *t3, *t4, *t5;
-    int ret = 0;
-
-    if (BN_is_zero(z1)) {
-        BN_zero(x2);
-        BN_zero(z2);
-        return 1;
-    }
-
-    if (BN_is_zero(z2)) {
-        if (!BN_copy(x2, x))
-            return 0;
-        if (!BN_GF2m_add(z2, x, y))
-            return 0;
-        return 2;
-    }
-
-    /* Since Mxy is static we can guarantee that ctx != NULL. */
-    BN_CTX_start(ctx);
-    t3 = BN_CTX_get(ctx);
-    t4 = BN_CTX_get(ctx);
-    t5 = BN_CTX_get(ctx);
-    if (t5 == NULL)
-        goto err;
-
-    if (!BN_one(t5))
-        goto err;
-
-    if (!group->meth->field_mul(group, t3, z1, z2, ctx))
-        goto err;
-
-    if (!group->meth->field_mul(group, z1, z1, x, ctx))
-        goto err;
-    if (!BN_GF2m_add(z1, z1, x1))
-        goto err;
-    if (!group->meth->field_mul(group, z2, z2, x, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, x1, z2, x1, ctx))
-        goto err;
-    if (!BN_GF2m_add(z2, z2, x2))
-        goto err;
-
-    if (!group->meth->field_mul(group, z2, z2, z1, ctx))
-        goto err;
-    if (!group->meth->field_sqr(group, t4, x, ctx))
-        goto err;
-    if (!BN_GF2m_add(t4, t4, y))
-        goto err;
-    if (!group->meth->field_mul(group, t4, t4, t3, ctx))
-        goto err;
-    if (!BN_GF2m_add(t4, t4, z2))
-        goto err;
-
-    if (!group->meth->field_mul(group, t3, t3, x, ctx))
-        goto err;
-    if (!group->meth->field_div(group, t3, t5, t3, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, t4, t3, t4, ctx))
-        goto err;
-    if (!group->meth->field_mul(group, x2, x1, t3, ctx))
-        goto err;
-    if (!BN_GF2m_add(z2, x2, x))
-        goto err;
-
-    if (!group->meth->field_mul(group, z2, z2, t4, ctx))
-        goto err;
-    if (!BN_GF2m_add(z2, z2, y))
-        goto err;
-
-    ret = 2;
-
- err:
-    BN_CTX_end(ctx);
-    return ret;
-}
-
-/*-
- * Computes scalar*point and stores the result in r.
- * point can not equal r.
- * Uses a modified algorithm 2P of
- *     Lopez, J. and Dahab, R.  "Fast multiplication on elliptic curves over
- *     GF(2^m) without precomputation" (CHES '99, LNCS 1717).
- *
- * To protect against side-channel attack the function uses constant time swap,
- * avoiding conditional branches.
- */
-static int ec_GF2m_montgomery_point_multiply(const EC_GROUP *group,
-                                             EC_POINT *r,
-                                             const BIGNUM *scalar,
-                                             const EC_POINT *point,
-                                             BN_CTX *ctx)
-{
-    BIGNUM *x1, *x2, *z1, *z2;
-    int ret = 0, i, group_top;
-    BN_ULONG mask, word;
-
-    if (r == point) {
-        ECerr(EC_F_EC_GF2M_MONTGOMERY_POINT_MULTIPLY, EC_R_INVALID_ARGUMENT);
-        return 0;
-    }
-
-    /* if result should be point at infinity */
-    if ((scalar == NULL) || BN_is_zero(scalar) || (point == NULL) ||
-        EC_POINT_is_at_infinity(group, point)) {
-        return EC_POINT_set_to_infinity(group, r);
-    }
-
-    /* only support affine coordinates */
-    if (!point->Z_is_one)
-        return 0;
-
-    /*
-     * Since point_multiply is static we can guarantee that ctx != NULL.
-     */
-    BN_CTX_start(ctx);
-    x1 = BN_CTX_get(ctx);
-    z1 = BN_CTX_get(ctx);
-    if (z1 == NULL)
-        goto err;
-
-    x2 = r->X;
-    z2 = r->Y;
-
-    group_top = bn_get_top(group->field);
-    if (bn_wexpand(x1, group_top) == NULL
-        || bn_wexpand(z1, group_top) == NULL
-        || bn_wexpand(x2, group_top) == NULL
-        || bn_wexpand(z2, group_top) == NULL)
-        goto err;
-
-    if (!BN_GF2m_mod_arr(x1, point->X, group->poly))
-        goto err;               /* x1 = x */
-    if (!BN_one(z1))
-        goto err;               /* z1 = 1 */
-    if (!group->meth->field_sqr(group, z2, x1, ctx))
-        goto err;               /* z2 = x1^2 = x^2 */
-    if (!group->meth->field_sqr(group, x2, z2, ctx))
-        goto err;
-    if (!BN_GF2m_add(x2, x2, group->b))
-        goto err;               /* x2 = x^4 + b */
-
-    /* find top most bit and go one past it */
-    i = bn_get_top(scalar) - 1;
-    mask = BN_TBIT;
-    word = bn_get_words(scalar)[i];
-    while (!(word & mask))
-        mask >>= 1;
-    mask >>= 1;
-    /* if top most bit was at word break, go to next word */
-    if (!mask) {
-        i--;
-        mask = BN_TBIT;
-    }
-
-    for (; i >= 0; i--) {
-        word = bn_get_words(scalar)[i];
-        while (mask) {
-            BN_consttime_swap(word & mask, x1, x2, group_top);
-            BN_consttime_swap(word & mask, z1, z2, group_top);
-            if (!gf2m_Madd(group, point->X, x2, z2, x1, z1, ctx))
-                goto err;
-            if (!gf2m_Mdouble(group, x1, z1, ctx))
-                goto err;
-            BN_consttime_swap(word & mask, x1, x2, group_top);
-            BN_consttime_swap(word & mask, z1, z2, group_top);
-            mask >>= 1;
-        }
-        mask = BN_TBIT;
-    }
-
-    /* convert out of "projective" coordinates */
-    i = gf2m_Mxy(group, point->X, point->Y, x1, z1, x2, z2, ctx);
-    if (i == 0)
-        goto err;
-    else if (i == 1) {
-        if (!EC_POINT_set_to_infinity(group, r))
-            goto err;
-    } else {
-        if (!BN_one(r->Z))
-            goto err;
-        r->Z_is_one = 1;
-    }
-
-    /* GF(2^m) field elements should always have BIGNUM::neg = 0 */
-    BN_set_negative(r->X, 0);
-    BN_set_negative(r->Y, 0);
-
-    ret = 1;
-
- err:
-    BN_CTX_end(ctx);
-    return ret;
-}
-
-/*-
- * Computes the sum
- *     scalar*group->generator + scalars[0]*points[0] + ... + scalars[num-1]*points[num-1]
- * gracefully ignoring NULL scalar values.
- */
-int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
-                       const BIGNUM *scalar, size_t num,
-                       const EC_POINT *points[], const BIGNUM *scalars[],
-                       BN_CTX *ctx)
-{
-    BN_CTX *new_ctx = NULL;
-    int ret = 0;
-    size_t i;
-    EC_POINT *p = NULL;
-    EC_POINT *acc = NULL;
-
-    if (ctx == NULL) {
-        ctx = new_ctx = BN_CTX_new();
-        if (ctx == NULL)
-            return 0;
-    }
-
-    /*
-     * This implementation is more efficient than the wNAF implementation for
-     * 2 or fewer points.  Use the ec_wNAF_mul implementation for 3 or more
-     * points, or if we can perform a fast multiplication based on
-     * precomputation.
-     */
-    if ((scalar && (num > 1)) || (num > 2)
-        || (num == 0 && EC_GROUP_have_precompute_mult(group))) {
-        ret = ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
-        goto err;
-    }
-
-    if ((p = EC_POINT_new(group)) == NULL)
-        goto err;
-    if ((acc = EC_POINT_new(group)) == NULL)
-        goto err;
-
-    if (!EC_POINT_set_to_infinity(group, acc))
-        goto err;
-
-    if (scalar) {
-        if (!ec_GF2m_montgomery_point_multiply
-            (group, p, scalar, group->generator, ctx))
-            goto err;
-        if (BN_is_negative(scalar))
-            if (!group->meth->invert(group, p, ctx))
-                goto err;
-        if (!group->meth->add(group, acc, acc, p, ctx))
-            goto err;
-    }
-
-    for (i = 0; i < num; i++) {
-        if (!ec_GF2m_montgomery_point_multiply
-            (group, p, scalars[i], points[i], ctx))
-            goto err;
-        if (BN_is_negative(scalars[i]))
-            if (!group->meth->invert(group, p, ctx))
-                goto err;
-        if (!group->meth->add(group, acc, acc, p, ctx))
-            goto err;
-    }
-
-    if (!EC_POINT_copy(r, acc))
-        goto err;
-
-    ret = 1;
-
- err:
-    EC_POINT_free(p);
-    EC_POINT_free(acc);
-    BN_CTX_free(new_ctx);
-    return ret;
-}
-
-/*
- * Precomputation for point multiplication: fall back to wNAF methods because
- * ec_GF2m_simple_mul() uses ec_wNAF_mul() if appropriate
- */
-
-int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx)
-{
-    return ec_wNAF_precompute_mult(group, ctx);
-}
-
-int ec_GF2m_have_precompute_mult(const EC_GROUP *group)
-{
-    return ec_wNAF_have_precompute_mult(group);
-}
-
-#endif
index 6bd5f9d..b73805a 100644 (file)
@@ -47,14 +47,9 @@ const EC_METHOD *EC_GF2m_simple_method(void)
         ec_GF2m_simple_cmp,
         ec_GF2m_simple_make_affine,
         ec_GF2m_simple_points_make_affine,
-
-        /*
-         * the following three method functions are defined in ec2_mult.c
-         */
-        ec_GF2m_simple_mul,
-        ec_GF2m_precompute_mult,
-        ec_GF2m_have_precompute_mult,
-
+        0 /* mul */,
+        0 /* precompute_mul */,
+        0 /* have_precompute_mul */,
         ec_GF2m_simple_field_mul,
         ec_GF2m_simple_field_sqr,
         ec_GF2m_simple_field_div,
index 5b306db..36c65c5 100644 (file)
@@ -443,14 +443,6 @@ int ec_GF2m_simple_field_sqr(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
 int ec_GF2m_simple_field_div(const EC_GROUP *, BIGNUM *r, const BIGNUM *a,
                              const BIGNUM *b, BN_CTX *);
 
-/* method functions in ec2_mult.c */
-int ec_GF2m_simple_mul(const EC_GROUP *group, EC_POINT *r,
-                       const BIGNUM *scalar, size_t num,
-                       const EC_POINT *points[], const BIGNUM *scalars[],
-                       BN_CTX *);
-int ec_GF2m_precompute_mult(EC_GROUP *group, BN_CTX *ctx);
-int ec_GF2m_have_precompute_mult(const EC_GROUP *group);
-
 #ifndef OPENSSL_NO_EC_NISTP_64_GCC_128
 /* method functions in ecp_nistp224.c */
 int ec_GFp_nistp224_group_init(EC_GROUP *group);