Avoid hard-coded linkage of WNAF-based multiplication.

If the application is only using the P-256 implementation in p256-64.c,
then the WNAF code would all be dead code. The change reorganizes the
code so that all modern toolchains should be able to recognize that
fact and eliminate the WNAF-based code when it is unused.

Change-Id: I9f94bd934ca7d2292de4c29bb89e17c940c7cd2a
Reviewed-on: https://boringssl-review.googlesource.com/6173
Reviewed-by: Adam Langley <alangley@gmail.com>
diff --git a/crypto/ec/ec.c b/crypto/ec/ec.c
index f2d5167..4f614f2 100644
--- a/crypto/ec/ec.c
+++ b/crypto/ec/ec.c
@@ -569,12 +569,7 @@
 }
 
 int EC_GROUP_precompute_mult(EC_GROUP *group, BN_CTX *ctx) {
-  if (group->meth->mul == 0) {
-    /* use default */
-    return ec_wNAF_precompute_mult(group, ctx);
-  }
-
-  if (group->meth->precompute_mult != 0) {
+  if (group->meth->precompute_mult != NULL) {
     return group->meth->precompute_mult(group, ctx);
   }
 
@@ -582,16 +577,10 @@
 }
 
 int EC_GROUP_have_precompute_mult(const EC_GROUP *group) {
-  if (group->meth->mul == 0) {
-    /* use default */
-    return ec_wNAF_have_precompute_mult(group);
+  if (group->pre_comp != NULL) {
+    return 1;
   }
-
-  if (group->meth->have_precompute_mult != 0) {
-    return group->meth->have_precompute_mult(group);
-  }
-
-  return 0; /* cannot tell whether precomputation has been performed */
+  return 0;
 }
 
 EC_POINT *EC_POINT_new(const EC_GROUP *group) {
@@ -797,9 +786,15 @@
 int EC_POINTs_mul(const EC_GROUP *group, EC_POINT *r, const BIGNUM *scalar,
                   size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
                   BN_CTX *ctx) {
-  if (group->meth->mul == 0) {
-    /* use default. Warning, not constant-time. */
-    return ec_wNAF_mul(group, r, scalar, num, points, scalars, ctx);
+  size_t i;
+  for (i = 0; i < num; i++) {
+    if (points[i]->meth != r->meth) {
+      break;
+    }
+  }
+  if (i != num) {
+    OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS);
+    return 0;
   }
 
   return group->meth->mul(group, r, scalar, num, points, scalars, ctx);
diff --git a/crypto/ec/ec_montgomery.c b/crypto/ec/ec_montgomery.c
index fde9844..3715e0c 100644
--- a/crypto/ec/ec_montgomery.c
+++ b/crypto/ec/ec_montgomery.c
@@ -81,9 +81,8 @@
                                 ec_GFp_mont_group_copy,
                                 ec_GFp_mont_group_set_curve,
                                 ec_GFp_simple_point_get_affine_coordinates,
-                                0 /* mul */,
-                                0 /* precompute_mult */,
-                                0 /* have_precompute_mult */,
+                                ec_wNAF_mul /* XXX: Not constant time. */,
+                                ec_wNAF_precompute_mult,
                                 ec_GFp_mont_field_mul,
                                 ec_GFp_mont_field_sqr,
                                 ec_GFp_mont_field_encode,
diff --git a/crypto/ec/internal.h b/crypto/ec/internal.h
index 836490a..6fdaf41 100644
--- a/crypto/ec/internal.h
+++ b/crypto/ec/internal.h
@@ -102,8 +102,6 @@
              size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
              BN_CTX *);
   int (*precompute_mult)(EC_GROUP *group, BN_CTX *);
-  int (*have_precompute_mult)(const EC_GROUP *group);
-
 
   /* internal functions */
 
@@ -170,7 +168,6 @@
                 size_t num, const EC_POINT *points[], const BIGNUM *scalars[],
                 BN_CTX *);
 int ec_wNAF_precompute_mult(EC_GROUP *group, BN_CTX *);
-int ec_wNAF_have_precompute_mult(const EC_GROUP *group);
 
 /* method functions in simple.c */
 int ec_GFp_simple_group_init(EC_GROUP *);
diff --git a/crypto/ec/p224-64.c b/crypto/ec/p224-64.c
index 1958a90..e530c9f 100644
--- a/crypto/ec/p224-64.c
+++ b/crypto/ec/p224-64.c
@@ -1328,7 +1328,6 @@
                                 ec_GFp_nistp224_point_get_affine_coordinates,
                                 ec_GFp_nistp224_points_mul,
                                 0 /* precompute_mult */,
-                                0 /* have_precompute_mult */,
                                 ec_GFp_simple_field_mul,
                                 ec_GFp_simple_field_sqr,
                                 0 /* field_encode */,
diff --git a/crypto/ec/p256-64.c b/crypto/ec/p256-64.c
index bc657cd..2adcd6b 100644
--- a/crypto/ec/p256-64.c
+++ b/crypto/ec/p256-64.c
@@ -1908,7 +1908,7 @@
       ec_GFp_simple_group_copy, ec_GFp_nistp256_group_set_curve,
       ec_GFp_nistp256_point_get_affine_coordinates,
       ec_GFp_nistp256_points_mul,
-      0 /* precompute_mult */, 0 /* have_precompute_mult */,
+      0 /* precompute_mult */,
       ec_GFp_simple_field_mul, ec_GFp_simple_field_sqr,
       0 /* field_encode */, 0 /* field_decode */, 0 /* field_set_to_one */
   };
diff --git a/crypto/ec/simple.c b/crypto/ec/simple.c
index 9381028..2695fda 100644
--- a/crypto/ec/simple.c
+++ b/crypto/ec/simple.c
@@ -85,7 +85,6 @@
                                 ec_GFp_simple_point_get_affine_coordinates,
                                 0 /* mul */,
                                 0 /* precompute_mult */,
-                                0 /* have_precompute_mult */,
                                 ec_GFp_simple_field_mul,
                                 ec_GFp_simple_field_sqr,
                                 0 /* field_encode */,
diff --git a/crypto/ec/wnaf.c b/crypto/ec/wnaf.c
index 7fa0e1b..4aaffd9 100644
--- a/crypto/ec/wnaf.c
+++ b/crypto/ec/wnaf.c
@@ -846,8 +846,3 @@
   EC_POINT_free(base);
   return ret;
 }
-
-
-int ec_wNAF_have_precompute_mult(const EC_GROUP *group) {
-  return group->pre_comp != NULL;
-}