Correctly set Z_is_one on the return value in the NISTZ256 implementation.
[openssl.git] / crypto / ec / ecp_nistz256.c
index 54a36c7c103dc71bddfab1d37484187859991891..b6eec7dc2cd8ddab7f71513e6830bfffc7852a35 100644 (file)
 
 #include <string.h>
 
-#include "internal/bn_int.h"
-#include <openssl/err.h>
-#include <openssl/ec.h>
 #include "cryptlib.h"
-
+#include "internal/bn_int.h"
 #include "ec_lcl.h"
 
 #if BN_BITS2 != 64
@@ -116,13 +113,13 @@ void ecp_nistz256_to_mont(BN_ULONG res[P256_LIMBS],
                           const BN_ULONG in[P256_LIMBS]);
 /* Functions that perform constant time access to the precomputed tables */
 void ecp_nistz256_scatter_w5(P256_POINT *val,
-                             const P256_POINT *in_t, int index);
+                             const P256_POINT *in_t, int idx);
 void ecp_nistz256_gather_w5(P256_POINT *val,
-                            const P256_POINT *in_t, int index);
+                            const P256_POINT *in_t, int idx);
 void ecp_nistz256_scatter_w7(P256_POINT_AFFINE *val,
-                             const P256_POINT_AFFINE *in_t, int index);
+                             const P256_POINT_AFFINE *in_t, int idx);
 void ecp_nistz256_gather_w7(P256_POINT_AFFINE *val,
-                            const P256_POINT_AFFINE *in_t, int index);
+                            const P256_POINT_AFFINE *in_t, int idx);
 
 /* One converted into the Montgomery domain */
 static const BN_ULONG ONE[P256_LIMBS] = {
@@ -166,7 +163,7 @@ static unsigned int _booth_recode_w7(unsigned int in)
 static void copy_conditional(BN_ULONG dst[P256_LIMBS],
                              const BN_ULONG src[P256_LIMBS], BN_ULONG move)
 {
-    BN_ULONG mask1 = -move;
+    BN_ULONG mask1 = 0-move;
     BN_ULONG mask2 = ~mask1;
 
     dst[0] = (src[0] & mask1) ^ (dst[0] & mask2);
@@ -560,10 +557,11 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
                                       P256_POINT *r,
                                       const BIGNUM **scalar,
                                       const EC_POINT **point,
-                                      int num, BN_CTX *ctx)
+                                      size_t num, BN_CTX *ctx)
 {
-    int i, j;
-    unsigned int index;
+    size_t i;
+    int j;
+    unsigned int idx;
     unsigned char (*p_str)[33] = NULL;
     const unsigned int window_size = 5;
     const unsigned int mask = (1 << (window_size + 1)) - 1;
@@ -573,8 +571,9 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
     P256_POINT (*table)[16] = NULL;
     void *table_storage = NULL;
 
-    if ((table_storage =
-         OPENSSL_malloc((num * 16 + 5) * sizeof(P256_POINT) + 64)) == NULL
+    if ((num * 16 + 6) > OPENSSL_MALLOC_MAX_NELEMS(P256_POINT)
+        || (table_storage =
+            OPENSSL_malloc((num * 16 + 5) * sizeof(P256_POINT) + 64)) == NULL
         || (p_str =
             OPENSSL_malloc(num * 33 * sizeof(unsigned char))) == NULL
         || (scalars = OPENSSL_malloc(num * sizeof(BIGNUM *))) == NULL) {
@@ -588,6 +587,7 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
     for (i = 0; i < num; i++) {
         P256_POINT *row = table[i];
 
+        /* This is an unusual input, we don't guarantee constant-timeness. */
         if ((BN_num_bits(scalar[i]) > 256) || BN_is_negative(scalar[i])) {
             BIGNUM *mod;
 
@@ -604,16 +604,16 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
         for (j = 0; j < bn_get_top(scalars[i]) * BN_BYTES; j += BN_BYTES) {
             BN_ULONG d = bn_get_words(scalars[i])[j / BN_BYTES];
 
-            p_str[i][j + 0] = d & 0xff;
-            p_str[i][j + 1] = (d >> 8) & 0xff;
-            p_str[i][j + 2] = (d >> 16) & 0xff;
-            p_str[i][j + 3] = (d >>= 24) & 0xff;
+            p_str[i][j + 0] = (unsigned char)d;
+            p_str[i][j + 1] = (unsigned char)(d >> 8);
+            p_str[i][j + 2] = (unsigned char)(d >> 16);
+            p_str[i][j + 3] = (unsigned char)(d >>= 24);
             if (BN_BYTES == 8) {
                 d >>= 8;
-                p_str[i][j + 4] = d & 0xff;
-                p_str[i][j + 5] = (d >> 8) & 0xff;
-                p_str[i][j + 6] = (d >> 16) & 0xff;
-                p_str[i][j + 7] = (d >> 24) & 0xff;
+                p_str[i][j + 4] = (unsigned char)d;
+                p_str[i][j + 5] = (unsigned char)(d >> 8);
+                p_str[i][j + 6] = (unsigned char)(d >> 16);
+                p_str[i][j + 7] = (unsigned char)(d >> 24);
             }
         }
         for (; j < 33; j++)
@@ -666,10 +666,10 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
         ecp_nistz256_scatter_w5  (row, &temp[1], 16);
     }
 
-    index = 255;
+    idx = 255;
 
-    wvalue = p_str[0][(index - 1) / 8];
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
+    wvalue = p_str[0][(idx - 1) / 8];
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
 
     /*
      * We gather to temp[0], because we know it's position relative
@@ -678,12 +678,12 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
     ecp_nistz256_gather_w5(&temp[0], table[0], _booth_recode_w5(wvalue) >> 1);
     memcpy(r, &temp[0], sizeof(temp[0]));
 
-    while (index >= 5) {
-        for (i = (index == 255 ? 1 : 0); i < num; i++) {
-            unsigned int off = (index - 1) / 8;
+    while (idx >= 5) {
+        for (i = (idx == 255 ? 1 : 0); i < num; i++) {
+            unsigned int off = (idx - 1) / 8;
 
             wvalue = p_str[i][off] | p_str[i][off + 1] << 8;
-            wvalue = (wvalue >> ((index - 1) % 8)) & mask;
+            wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
 
             wvalue = _booth_recode_w5(wvalue);
 
@@ -695,7 +695,7 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group,
             ecp_nistz256_point_add(r, r, &temp[0]);
         }
 
-        index -= window_size;
+        idx -= window_size;
 
         ecp_nistz256_point_double(r, r);
         ecp_nistz256_point_double(r, r);
@@ -871,14 +871,11 @@ static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
  err:
     if (ctx != NULL)
         BN_CTX_end(ctx);
-    if (pre_comp)
-        ecp_nistz256_pre_comp_free(pre_comp);
+    ecp_nistz256_pre_comp_free(pre_comp);
     if (precomp_storage)
         OPENSSL_free(precomp_storage);
-    if (P)
-        EC_POINT_free(P);
-    if (T)
-        EC_POINT_free(T);
+    EC_POINT_free(P);
+    EC_POINT_free(T);
     return ret;
 }
 
@@ -943,7 +940,7 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
     unsigned char sign1, digit1;
     unsigned char sign2, digit2;
     unsigned char sign3, digit3;
-    unsigned int index = 0;
+    unsigned int idx = 0;
     BN_ULONG tmp[P256_LIMBS];
     int i;
 
@@ -955,19 +952,19 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
     /* Initial four windows */
     wvalue = *((u16 *) & p_str[0]);
     wvalue = (wvalue << 1) & mask;
-    index += window_size;
+    idx += window_size;
     booth_recode_w7(&sign0, &digit0, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign1, &digit1, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign2, &digit2, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign3, &digit3, wvalue);
 
     ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[0],
@@ -987,21 +984,21 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
     ecp_nistz256_avx2_to_mont(&aX4[4 * 9], &aX4[4 * 9]);
     ecp_nistz256_avx2_set1(&aX4[4 * 9 * 2]);
 
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign0, &digit0, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign1, &digit1, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign2, &digit2, wvalue);
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-    index += window_size;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+    idx += window_size;
     booth_recode_w7(&sign3, &digit3, wvalue);
 
     ecp_nistz256_avx2_multi_gather_w7(point_arr, preComputedTable[4 * 1],
@@ -1023,21 +1020,21 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
     ecp_nistz256_avx2_point_add_affines_x4(aX4, aX4, bX4);
 
     for (i = 2; i < 9; i++) {
-        wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-        wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-        index += window_size;
+        wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+        wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+        idx += window_size;
         booth_recode_w7(&sign0, &digit0, wvalue);
-        wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-        wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-        index += window_size;
+        wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+        wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+        idx += window_size;
         booth_recode_w7(&sign1, &digit1, wvalue);
-        wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-        wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-        index += window_size;
+        wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+        wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+        idx += window_size;
         booth_recode_w7(&sign2, &digit2, wvalue);
-        wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-        wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-        index += window_size;
+        wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+        wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+        idx += window_size;
         booth_recode_w7(&sign3, &digit3, wvalue);
 
         ecp_nistz256_avx2_multi_gather_w7(point_arr,
@@ -1066,8 +1063,8 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
 
     ecp_nistz256_avx2_convert_transpose_back(res_point_arr, aX4);
     /* Last window is performed serially */
-    wvalue = *((u16 *) & p_str[(index - 1) / 8]);
-    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
+    wvalue = *((u16 *) & p_str[(idx - 1) / 8]);
+    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
     booth_recode_w7(&sign0, &digit0, wvalue);
     ecp_nistz256_gather_w7((P256_POINT_AFFINE *)r,
                            preComputedTable[36], digit0);
@@ -1129,7 +1126,7 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
     const PRECOMP256_ROW *preComputedTable = NULL;
     const EC_PRE_COMP *pre_comp = NULL;
     const EC_POINT *generator = NULL;
-    unsigned int index = 0;
+    unsigned int idx = 0;
     const unsigned int window_size = 7;
     const unsigned int mask = (1 << (window_size + 1)) - 1;
     unsigned int wvalue;
@@ -1225,16 +1222,16 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
             for (i = 0; i < bn_get_top(scalar) * BN_BYTES; i += BN_BYTES) {
                 BN_ULONG d = bn_get_words(scalar)[i / BN_BYTES];
 
-                p_str[i + 0] = d & 0xff;
-                p_str[i + 1] = (d >> 8) & 0xff;
-                p_str[i + 2] = (d >> 16) & 0xff;
-                p_str[i + 3] = (d >>= 24) & 0xff;
+                p_str[i + 0] = (unsigned char)d;
+                p_str[i + 1] = (unsigned char)(d >> 8);
+                p_str[i + 2] = (unsigned char)(d >> 16);
+                p_str[i + 3] = (unsigned char)(d >>= 24);
                 if (BN_BYTES == 8) {
                     d >>= 8;
-                    p_str[i + 4] = d & 0xff;
-                    p_str[i + 5] = (d >> 8) & 0xff;
-                    p_str[i + 6] = (d >> 16) & 0xff;
-                    p_str[i + 7] = (d >> 24) & 0xff;
+                    p_str[i + 4] = (unsigned char)d;
+                    p_str[i + 5] = (unsigned char)(d >> 8);
+                    p_str[i + 6] = (unsigned char)(d >> 16);
+                    p_str[i + 7] = (unsigned char)(d >> 24);
                 }
             }
 
@@ -1249,7 +1246,7 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
             {
                 /* First window */
                 wvalue = (p_str[0] << 1) & mask;
-                index += window_size;
+                idx += window_size;
 
                 wvalue = _booth_recode_w7(wvalue);
 
@@ -1262,10 +1259,10 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
                 memcpy(p.p.Z, ONE, sizeof(ONE));
 
                 for (i = 1; i < 37; i++) {
-                    unsigned int off = (index - 1) / 8;
+                    unsigned int off = (idx - 1) / 8;
                     wvalue = p_str[off] | p_str[off + 1] << 8;
-                    wvalue = (wvalue >> ((index - 1) % 8)) & mask;
-                    index += window_size;
+                    wvalue = (wvalue >> ((idx - 1) % 8)) & mask;
+                    idx += window_size;
 
                     wvalue = _booth_recode_w7(wvalue);
 
@@ -1335,9 +1332,11 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
     bn_set_data(r->X, p.p.X, sizeof(p.p.X));
     bn_set_data(r->Y, p.p.Y, sizeof(p.p.Y));
     bn_set_data(r->Z, p.p.Z, sizeof(p.p.Z));
+    /* Not constant-time, but we're only operating on the public output. */
     bn_correct_top(r->X);
     bn_correct_top(r->Y);
     bn_correct_top(r->Z);
+    r->Z_is_one = is_one(p.p.Z);
 
     ret = 1;