Error checking and memory leak fixes in NISTZ256.
[oweals/openssl.git] / crypto / ec / ecp_nistz256.c
index c50b845fdc71034e4960b1f966f79b240e7f9167..fd4898d2279886ee63580e0699ecda9890733782 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
@@ -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,9 +557,10 @@ 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;
+    size_t i;
+    int j;
     unsigned int idx;
     unsigned char (*p_str)[33] = NULL;
     const unsigned int window_size = 5;
@@ -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++)
@@ -765,6 +765,7 @@ static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
     EC_POINT *P = NULL, *T = NULL;
     const EC_POINT *generator;
     EC_PRE_COMP *pre_comp;
+    BN_CTX *new_ctx = NULL;
     int i, j, k, ret = 0;
     size_t w;
 
@@ -794,7 +795,7 @@ static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
         return 0;
 
     if (ctx == NULL) {
-        ctx = BN_CTX_new();
+        ctx = new_ctx = BN_CTX_new();
         if (ctx == NULL)
             goto err;
     }
@@ -825,15 +826,19 @@ static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
 
     P = EC_POINT_new(group);
     T = EC_POINT_new(group);
+    if (P == NULL || T == NULL)
+        goto err;
 
     /*
      * The zero entry is implicitly infinity, and we skip it, storing other
      * values with -1 offset.
      */
-    EC_POINT_copy(T, generator);
+    if (!EC_POINT_copy(T, generator))
+        goto err;
 
     for (k = 0; k < 64; k++) {
-        EC_POINT_copy(P, T);
+        if (!EC_POINT_copy(P, T))
+            goto err;
         for (j = 0; j < 37; j++) {
             P256_POINT_AFFINE temp;
             /*
@@ -871,14 +876,13 @@ 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);
+    BN_CTX_free(new_ctx);
+
+    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;
 }
 
@@ -1129,6 +1133,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;
+    BN_CTX *new_ctx = NULL;
     unsigned int idx = 0;
     const unsigned int window_size = 7;
     const unsigned int mask = (1 << (window_size + 1)) - 1;
@@ -1148,6 +1153,7 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
         ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, EC_R_INCOMPATIBLE_OBJECTS);
         return 0;
     }
+
     if ((scalar == NULL) && (num == 0))
         return EC_POINT_set_to_infinity(group, r);
 
@@ -1158,13 +1164,13 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
         }
     }
 
-    /* Need 256 bits for space for all coordinates. */
-    bn_wexpand(r->X, P256_LIMBS);
-    bn_wexpand(r->Y, P256_LIMBS);
-    bn_wexpand(r->Z, P256_LIMBS);
-    bn_set_top(r->X, P256_LIMBS);
-    bn_set_top(r->Y, P256_LIMBS);
-    bn_set_top(r->Z, P256_LIMBS);
+    if (ctx == NULL) {
+        ctx = new_ctx = BN_CTX_new();
+        if (ctx == NULL)
+            goto err;
+    }
+
+    BN_CTX_start(ctx);
 
     if (scalar) {
         generator = EC_GROUP_get0_generator(group);
@@ -1190,8 +1196,10 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
 
             if (!ecp_nistz256_set_from_affine(pre_comp_generator,
                                               group, pre_comp->precomp[0],
-                                              ctx))
+                                              ctx)) {
+                EC_POINT_free(pre_comp_generator);
                 goto err;
+            }
 
             if (0 == EC_POINT_cmp(group, generator, pre_comp_generator, ctx))
                 preComputedTable = (const PRECOMP256_ROW *)pre_comp->precomp;
@@ -1225,16 +1233,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);
                 }
             }
 
@@ -1296,14 +1304,14 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
         new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *));
         if (!new_scalars) {
             ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
-            return 0;
+            goto err;
         }
 
         new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *));
         if (!new_points) {
             OPENSSL_free(new_scalars);
             ECerr(EC_F_ECP_NISTZ256_POINTS_MUL, ERR_R_MALLOC_FAILURE);
-            return 0;
+            goto err;
         }
 
         memcpy(new_scalars, scalars, num * sizeof(BIGNUM *));
@@ -1332,16 +1340,20 @@ static int ecp_nistz256_points_mul(const EC_GROUP *group,
         OPENSSL_free(scalars);
     }
 
-    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));
-    bn_correct_top(r->X);
-    bn_correct_top(r->Y);
-    bn_correct_top(r->Z);
+    /* Not constant-time, but we're only operating on the public output. */
+    if (!bn_set_words(r->X, p.p.X, P256_LIMBS) ||
+        !bn_set_words(r->Y, p.p.Y, P256_LIMBS) ||
+        !bn_set_words(r->Z, p.p.Z, P256_LIMBS)) {
+        goto err;
+    }
+    r->Z_is_one = is_one(p.p.Z);
 
     ret = 1;
 
- err:
+err:
+    if (ctx)
+        BN_CTX_end(ctx);
+    BN_CTX_free(new_ctx);
     return ret;
 }
 
@@ -1354,6 +1366,7 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group,
     BN_ULONG x_aff[P256_LIMBS];
     BN_ULONG y_aff[P256_LIMBS];
     BN_ULONG point_x[P256_LIMBS], point_y[P256_LIMBS], point_z[P256_LIMBS];
+    BN_ULONG x_ret[P256_LIMBS], y_ret[P256_LIMBS];
 
     if (EC_POINT_is_at_infinity(group, point)) {
         ECerr(EC_F_ECP_NISTZ256_GET_AFFINE, EC_R_POINT_AT_INFINITY);
@@ -1372,19 +1385,17 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group,
     ecp_nistz256_mul_mont(x_aff, z_inv2, point_x);
 
     if (x != NULL) {
-        bn_wexpand(x, P256_LIMBS);
-        bn_set_top(x, P256_LIMBS);
-        ecp_nistz256_from_mont(bn_get_words(x), x_aff);
-        bn_correct_top(x);
+        ecp_nistz256_from_mont(x_ret, x_aff);
+        if (!bn_set_words(x, x_ret, P256_LIMBS))
+            return 0;
     }
 
     if (y != NULL) {
         ecp_nistz256_mul_mont(z_inv3, z_inv3, z_inv2);
         ecp_nistz256_mul_mont(y_aff, z_inv3, point_y);
-        bn_wexpand(y, P256_LIMBS);
-        bn_set_top(y, P256_LIMBS);
-        ecp_nistz256_from_mont(bn_get_words(y), y_aff);
-        bn_correct_top(y);
+        ecp_nistz256_from_mont(y_ret, y_aff);
+        if (!bn_set_words(y, y_ret, P256_LIMBS))
+            return 0;
     }
 
     return 1;