NISTZ256: don't swallow malloc errors
[openssl.git] / crypto / ec / ecp_nistz256.c
index bf3fcc6b5925bc68f82f31cfeed96b048d6ffd86..bd0931220681a33307ed53b9c46aaf89ccc473d0 100644 (file)
 #include "ec_lcl.h"
 
 #if BN_BITS2 != 64
-# define TOBN(hi,lo)   lo,hi
+# define TOBN(hi,lo)    lo,hi
 #else
-# define TOBN(hi,lo)   ((BN_ULONG)hi<<32|lo)
+# define TOBN(hi,lo)    ((BN_ULONG)hi<<32|lo)
 #endif
 
 #if defined(__GNUC__)
-# define ALIGN32       __attribute((aligned(32)))
+# define ALIGN32        __attribute((aligned(32)))
 #elif defined(_MSC_VER)
-# define ALIGN32       __declspec(align(32))
+# define ALIGN32        __declspec(align(32))
 #else
 # define ALIGN32
 #endif
 
-#define ALIGNPTR(p,N)  ((unsigned char *)p+N-(size_t)p%N)
-#define P256_LIMBS     (256/BN_BITS2)
+#define ALIGNPTR(p,N)   ((unsigned char *)p+N-(size_t)p%N)
+#define P256_LIMBS      (256/BN_BITS2)
 
 typedef unsigned short u16;
 
@@ -71,9 +71,11 @@ typedef P256_POINT_AFFINE PRECOMP256_ROW[64];
 typedef struct ec_pre_comp_st {
     const EC_GROUP *group;      /* Parent EC_GROUP object */
     size_t w;                   /* Window size */
-    /* Constant time access to the X and Y coordinates of the pre-computed,
+    /*
+     * Constant time access to the X and Y coordinates of the pre-computed,
      * generator multiplies, in the Montgomery domain. Pre-calculated
-     * multiplies are stored in affine form. */
+     * multiplies are stored in affine form.
+     */
     PRECOMP256_ROW *precomp;
     void *precomp_storage;
     int references;
@@ -89,15 +91,15 @@ void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS],
 /* Modular mul by 3: res = 3*a mod P */
 void ecp_nistz256_mul_by_3(BN_ULONG res[P256_LIMBS],
                            const BN_ULONG a[P256_LIMBS]);
-/* Modular add: res = a+b mod P          */
+/* Modular add: res = a+b mod P   */
 void ecp_nistz256_add(BN_ULONG res[P256_LIMBS],
                       const BN_ULONG a[P256_LIMBS],
                       const BN_ULONG b[P256_LIMBS]);
-/* Modular sub: res = a-b mod P          */
+/* Modular sub: res = a-b mod P   */
 void ecp_nistz256_sub(BN_ULONG res[P256_LIMBS],
                       const BN_ULONG a[P256_LIMBS],
                       const BN_ULONG b[P256_LIMBS]);
-/* Modular neg: res = -a mod P   */
+/* Modular neg: res = -a mod P    */
 void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]);
 /* Montgomery mul: res = a*b*2^-256 mod P */
 void ecp_nistz256_mul_mont(BN_ULONG res[P256_LIMBS],
@@ -127,7 +129,7 @@ static const BN_ULONG ONE[P256_LIMBS] = {
 static void *ecp_nistz256_pre_comp_dup(void *);
 static void ecp_nistz256_pre_comp_free(void *);
 static void ecp_nistz256_pre_comp_clear_free(void *);
-static EC_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP * group);
+static EC_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group);
 
 /* Precomputed tables for the default generator */
 #include "ecp_nistz256_table.c"
@@ -220,16 +222,28 @@ static BN_ULONG is_one(const BN_ULONG a[P256_LIMBS])
     return is_zero(res);
 }
 
+static int ecp_nistz256_set_words(BIGNUM *a, BN_ULONG words[P256_LIMBS])
+ {
+     if (bn_wexpand(a, P256_LIMBS) == NULL) {
+         ECerr(EC_F_ECP_NISTZ256_SET_WORDS, ERR_R_MALLOC_FAILURE);
+         return 0;
+     }
+     memcpy(a->d, words, sizeof(BN_ULONG) * P256_LIMBS);
+     a->top = P256_LIMBS;
+     bn_correct_top(a);
+     return 1;
+}
+
 #ifndef ECP_NISTZ256_REFERENCE_IMPLEMENTATION
-void ecp_nistz256_point_double(P256_POINT * r, const P256_POINT * a);
-void ecp_nistz256_point_add(P256_POINT * r,
-                            const P256_POINT * a, const P256_POINT * b);
-void ecp_nistz256_point_add_affine(P256_POINT * r,
-                                   const P256_POINT * a,
-                                   const P256_POINT_AFFINE * b);
+void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a);
+void ecp_nistz256_point_add(P256_POINT *r,
+                            const P256_POINT *a, const P256_POINT *b);
+void ecp_nistz256_point_add_affine(P256_POINT *r,
+                                   const P256_POINT *a,
+                                   const P256_POINT_AFFINE *b);
 #else
 /* Point double: r = 2*a */
-static void ecp_nistz256_point_double(P256_POINT * r, const P256_POINT * a)
+static void ecp_nistz256_point_double(P256_POINT *r, const P256_POINT *a)
 {
     BN_ULONG S[P256_LIMBS];
     BN_ULONG M[P256_LIMBS];
@@ -275,8 +289,8 @@ static void ecp_nistz256_point_double(P256_POINT * r, const P256_POINT * a)
 }
 
 /* Point addition: r = a+b */
-static void ecp_nistz256_point_add(P256_POINT * r,
-                                   const P256_POINT * a, const P256_POINT * b)
+static void ecp_nistz256_point_add(P256_POINT *r,
+                                   const P256_POINT *a, const P256_POINT *b)
 {
     BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS];
     BN_ULONG U1[P256_LIMBS], S1[P256_LIMBS];
@@ -303,17 +317,17 @@ static void ecp_nistz256_point_add(P256_POINT * r,
 
     /* We encode infinity as (0,0), which is not on the curve,
      * so it is OK. */
-    in1infty = in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
-               in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3];
+    in1infty = (in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
+                in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3]);
     if (P256_LIMBS == 8)
-        in1infty |= in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
-                    in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7];
+        in1infty |= (in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
+                     in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7]);
 
-    in2infty = in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
-               in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3];
+    in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
+                in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]);
     if (P256_LIMBS == 8)
-        in2infty |= in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
-                    in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7];
+        in2infty |= (in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
+                     in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7]);
 
     in1infty = is_zero(in1infty);
     in2infty = is_zero(in2infty);
@@ -332,8 +346,9 @@ static void ecp_nistz256_point_add(P256_POINT * r,
     ecp_nistz256_mul_mont(U2, in2_x, Z1sqr);    /* U2 = X2*Z1^2 */
     ecp_nistz256_sub(H, U2, U1);                /* H = U2 - U1 */
 
-    /* This should not happen during sign/ecdh,
-     * so no constant time violation */
+    /*
+     * This should not happen during sign/ecdh, so no constant time violation
+     */
     if (is_equal(U1, U2) && !in1infty && !in2infty) {
         if (is_equal(S1, S2)) {
             ecp_nistz256_point_double(r, a);
@@ -376,9 +391,9 @@ static void ecp_nistz256_point_add(P256_POINT * r,
 }
 
 /* Point addition when b is known to be affine: r = a+b */
-static void ecp_nistz256_point_add_affine(P256_POINT * r,
-                                          const P256_POINT * a,
-                                          const P256_POINT_AFFINE * b)
+static void ecp_nistz256_point_add_affine(P256_POINT *r,
+                                          const P256_POINT *a,
+                                          const P256_POINT_AFFINE *b)
 {
     BN_ULONG U2[P256_LIMBS], S2[P256_LIMBS];
     BN_ULONG Z1sqr[P256_LIMBS];
@@ -400,19 +415,21 @@ static void ecp_nistz256_point_add_affine(P256_POINT * r,
     const BN_ULONG *in2_x = b->X;
     const BN_ULONG *in2_y = b->Y;
 
-    /* In affine representation we encode infty as (0,0),
-     * which is not on the curve, so it is OK */
-    in1infty = in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
-               in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3];
+    /*
+     * In affine representation we encode infty as (0,0), which is not on the
+     * curve, so it is OK
+     */
+    in1infty = (in1_x[0] | in1_x[1] | in1_x[2] | in1_x[3] |
+                in1_y[0] | in1_y[1] | in1_y[2] | in1_y[3]);
     if (P256_LIMBS == 8)
-        in1infty |= in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
-                    in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7];
+        in1infty |= (in1_x[4] | in1_x[5] | in1_x[6] | in1_x[7] |
+                     in1_y[4] | in1_y[5] | in1_y[6] | in1_y[7]);
 
-    in2infty = in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
-               in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3];
+    in2infty = (in2_x[0] | in2_x[1] | in2_x[2] | in2_x[3] |
+                in2_y[0] | in2_y[1] | in2_y[2] | in2_y[3]);
     if (P256_LIMBS == 8)
-        in2infty |= in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
-                    in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7];
+        in2infty |= (in2_x[4] | in2_x[5] | in2_x[6] | in2_x[7] |
+                     in2_y[4] | in2_y[5] | in2_y[6] | in2_y[7]);
 
     in1infty = is_zero(in1infty);
     in2infty = is_zero(in2infty);
@@ -463,8 +480,10 @@ static void ecp_nistz256_point_add_affine(P256_POINT * r,
 static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
                                      const BN_ULONG in[P256_LIMBS])
 {
-    /* The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff ffffffff ffffffff
-       We use FLT and used poly-2 as exponent */
+    /*
+     * The poly is ffffffff 00000001 00000000 00000000 00000000 ffffffff
+     * ffffffff ffffffff We use FLT and used poly-2 as exponent
+     */
     BN_ULONG p2[P256_LIMBS];
     BN_ULONG p4[P256_LIMBS];
     BN_ULONG p8[P256_LIMBS];
@@ -534,10 +553,12 @@ static void ecp_nistz256_mod_inverse(BN_ULONG r[P256_LIMBS],
     memcpy(r, res, sizeof(res));
 }
 
-/* ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
- * returns one if it fits. Otherwise it returns zero. */
+/*
+ * ecp_nistz256_bignum_to_field_elem copies the contents of |in| to |out| and
+ * returns one if it fits. Otherwise it returns zero.
+ */
 static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS],
-                                             const BIGNUM * in)
+                                             const BIGNUM *in)
 {
     if (in->top > P256_LIMBS)
         return 0;
@@ -548,13 +569,14 @@ static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS],
 }
 
 /* r = sum(scalar[i]*point[i]) */
-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)
+static int ecp_nistz256_windowed_mul(const EC_GROUP *group,
+                                      P256_POINT *r,
+                                      const BIGNUM **scalar,
+                                      const EC_POINT **point,
+                                      int num, BN_CTX *ctx)
 {
-    int i, j;
+
+    int i, j, ret = 0;
     unsigned int index;
     unsigned char (*p_str)[33] = NULL;
     const unsigned int window_size = 5;
@@ -563,7 +585,7 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP * group,
     BN_ULONG tmp[P256_LIMBS];
     ALIGN32 P256_POINT h;
     const BIGNUM **scalars = NULL;
-    P256_POINT(*table)[16] = NULL;
+    P256_POINT (*table)[16] = NULL;
     void *table_storage = NULL;
 
     if ((table_storage =
@@ -580,6 +602,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;
 
@@ -688,13 +711,15 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP * group,
         ecp_nistz256_point_add(r, r, &h);
     }
 
-err:
+    ret = 1;
+ err:
     if (table_storage)
         OPENSSL_free(table_storage);
     if (p_str)
         OPENSSL_free(p_str);
     if (scalars)
         OPENSSL_free(scalars);
+    return ret;
 }
 
 /* Coordinates of G, for which we have precomputed tables */
@@ -708,9 +733,11 @@ const static BN_ULONG def_yG[P256_LIMBS] = {
     TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85)
 };
 
-/* ecp_nistz256_is_affine_G returns one if |generator| is the standard,
- * P-256 generator. */
-static int ecp_nistz256_is_affine_G(const EC_POINT * generator)
+/*
+ * ecp_nistz256_is_affine_G returns one if |generator| is the standard, P-256
+ * generator.
+ */
+static int ecp_nistz256_is_affine_G(const EC_POINT *generator)
 {
     return (generator->X.top == P256_LIMBS) &&
         (generator->Y.top == P256_LIMBS) &&
@@ -719,16 +746,19 @@ static int ecp_nistz256_is_affine_G(const EC_POINT * generator)
         is_equal(generator->Y.d, def_yG) && is_one(generator->Z.d);
 }
 
-static int ecp_nistz256_mult_precompute(EC_GROUP * group, BN_CTX * ctx)
+static int ecp_nistz256_mult_precompute(EC_GROUP *group, BN_CTX *ctx)
 {
-    /* We precompute a table for a Booth encoded exponent (wNAF) based
+    /*
+     * We precompute a table for a Booth encoded exponent (wNAF) based
      * computation. Each table holds 64 values for safe access, with an
-     * implicit value of infinity at index zero. We use window of size 7,
-     * and therefore require ceil(256/7) = 37 tables. */
+     * implicit value of infinity at index zero. We use window of size 7, and
+     * therefore require ceil(256/7) = 37 tables.
+     */
     BIGNUM *order;
     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;
 
@@ -747,8 +777,10 @@ static int ecp_nistz256_mult_precompute(EC_GROUP * group, BN_CTX * ctx)
     }
 
     if (ecp_nistz256_is_affine_G(generator)) {
-        /* No need to calculate tables for the standard generator
-         * because we have them statically. */
+        /*
+         * No need to calculate tables for the standard generator because we
+         * have them statically.
+         */
         return 1;
     }
 
@@ -756,7 +788,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;
     }
@@ -787,17 +819,25 @@ 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);
+    /*
+     * The zero entry is implicitly infinity, and we skip it, storing other
+     * values with -1 offset.
+     */
+    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++) {
-            /* It would be faster to use
+            /*
+             * It would be faster to use
              * ec_GFp_simple_points_make_affine and make multiple
-             * points affine at the same time. */
+             * points affine at the same time.
+             */
             ec_GFp_simple_make_affine(group, P, ctx);
             ecp_nistz256_bignum_to_field_elem(preComputedTable[j]
                                               [k].X, &P->X);
@@ -827,9 +867,11 @@ static int ecp_nistz256_mult_precompute(EC_GROUP * group, BN_CTX * ctx)
 
     ret = 1;
 
-err:
+ err:
     if (ctx != NULL)
         BN_CTX_end(ctx);
+    BN_CTX_free(new_ctx);
+
     if (pre_comp)
         ecp_nistz256_pre_comp_free(pre_comp);
     if (precomp_storage)
@@ -886,13 +928,14 @@ static void booth_recode_w7(unsigned char *sign,
     *digit = d;
 }
 
-/* ecp_nistz256_avx2_mul_g performs multiplication by G, using only the
+/*
+ * ecp_nistz256_avx2_mul_g performs multiplication by G, using only the
  * precomputed table. It does 4 affine point additions in parallel,
- * significantly speeding up point multiplication for a fixed value. */
-static void ecp_nistz256_avx2_mul_g(P256_POINT * r,
+ * significantly speeding up point multiplication for a fixed value.
+ */
+static void ecp_nistz256_avx2_mul_g(P256_POINT *r,
                                     unsigned char p_str[33],
-                                    const
-                                    P256_POINT_AFFINE(*preComputedTable)[64])
+                                    const P256_POINT_AFFINE(*preComputedTable)[64])
 {
     const unsigned int window_size = 7;
     const unsigned int mask = (1 << (window_size + 1)) - 1;
@@ -1042,9 +1085,9 @@ static void ecp_nistz256_avx2_mul_g(P256_POINT * r,
 # endif
 #endif
 
-static int ecp_nistz256_set_from_affine(EC_POINT * out, const EC_GROUP * group,
-                                        const P256_POINT_AFFINE * in,
-                                        BN_CTX * ctx)
+static int ecp_nistz256_set_from_affine(EC_POINT *out, const EC_GROUP *group,
+                                        const P256_POINT_AFFINE *in,
+                                        BN_CTX *ctx)
 {
     BIGNUM x, y;
     BN_ULONG d_x[P256_LIMBS], d_y[P256_LIMBS];
@@ -1068,12 +1111,12 @@ static int ecp_nistz256_set_from_affine(EC_POINT * out, const EC_GROUP * group,
 }
 
 /* r = scalar*G + sum(scalars[i]*points[i]) */
-static int ecp_nistz256_points_mul(const EC_GROUP * group,
-                                   EC_POINT * r,
-                                   const BIGNUM * scalar,
+static int ecp_nistz256_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)
+                                   const EC_POINT *points[],
+                                   const BIGNUM *scalars[], BN_CTX *ctx)
 {
     int i = 0, ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0;
     size_t j;
@@ -1082,6 +1125,9 @@ static int ecp_nistz256_points_mul(const EC_GROUP * group,
     const EC_PRE_COMP *pre_comp = NULL;
     const EC_POINT *generator = NULL;
     unsigned int index = 0;
+    BN_CTX *new_ctx = NULL;
+    const BIGNUM **new_scalars = NULL;
+    const EC_POINT **new_points = NULL;
     const unsigned int window_size = 7;
     const unsigned int mask = (1 << (window_size + 1)) - 1;
     unsigned int wvalue;
@@ -1095,6 +1141,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);
 
@@ -1105,13 +1152,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);
-    r->X.top = P256_LIMBS;
-    r->Y.top = P256_LIMBS;
-    r->Z.top = 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);
@@ -1127,16 +1174,19 @@ static int ecp_nistz256_points_mul(const EC_GROUP * group,
                                 ecp_nistz256_pre_comp_clear_free);
 
         if (pre_comp) {
-            /* If there is a precomputed table for the generator,
-             * check that it was generated with the same
-             * generator. */
+            /*
+             * If there is a precomputed table for the generator, check that
+             * it was generated with the same generator.
+             */
             EC_POINT *pre_comp_generator = EC_POINT_new(group);
             if (pre_comp_generator == NULL)
                 goto err;
 
             if (!ecp_nistz256_set_from_affine
-                (pre_comp_generator, group, pre_comp->precomp[0], ctx))
+                (pre_comp_generator, group, pre_comp->precomp[0], 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;
@@ -1145,10 +1195,12 @@ static int ecp_nistz256_points_mul(const EC_GROUP * group,
         }
 
         if (preComputedTable == NULL && ecp_nistz256_is_affine_G(generator)) {
-            /* If there is no precomputed data, but the generator
+            /*
+             * If there is no precomputed data, but the generator
              * is the default, a hardcoded table of precomputed
              * data is used. This is because applications, such as
-             * Apache, do not use EC_KEY_precompute_mult. */
+             * Apache, do not use EC_KEY_precompute_mult.
+             */
             preComputedTable = (const PRECOMP256_ROW *)ecp_nistz256_precomputed;
         }
 
@@ -1228,22 +1280,20 @@ static int ecp_nistz256_points_mul(const EC_GROUP * group,
         p_is_infinity = 1;
 
     if (no_precomp_for_generator) {
-        /* Without a precomputed table for the generator, it has to be
-         * handled like a normal point. */
-        const BIGNUM **new_scalars;
-        const EC_POINT **new_points;
-
+        /*
+         * Without a precomputed table for the generator, it has to be
+         * handled like a normal point.
+         */
         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 *));
@@ -1261,39 +1311,44 @@ static int ecp_nistz256_points_mul(const EC_GROUP * group,
         if (p_is_infinity)
             out = &p.p;
 
-        ecp_nistz256_windowed_mul(group, out, scalars, points, num, ctx);
+        if (!ecp_nistz256_windowed_mul(group, out, scalars, points, num, ctx))
+            goto err;
 
         if (!p_is_infinity)
             ecp_nistz256_point_add(&p.p, &p.p, out);
     }
 
-    if (no_precomp_for_generator) {
-        OPENSSL_free(points);
-        OPENSSL_free(scalars);
+    /* Not constant-time, but we're only operating on the public output. */
+    if (!ecp_nistz256_set_words(&r->X, p.p.X) ||
+        !ecp_nistz256_set_words(&r->Y, p.p.Y) ||
+        !ecp_nistz256_set_words(&r->Z, p.p.Z)) {
+        goto err;
     }
-
-    memcpy(r->X.d, p.p.X, sizeof(p.p.X));
-    memcpy(r->Y.d, p.p.Y, sizeof(p.p.Y));
-    memcpy(r->Z.d, p.p.Z, sizeof(p.p.Z));
-    bn_correct_top(&r->X);
-    bn_correct_top(&r->Y);
-    bn_correct_top(&r->Z);
+    r->Z_is_one = is_one(p.p.Z) & 1;
 
     ret = 1;
 
 err:
+    if (ctx)
+        BN_CTX_end(ctx);
+    BN_CTX_free(new_ctx);
+    if (new_points)
+        OPENSSL_free(new_points);
+    if (new_scalars)
+        OPENSSL_free(new_scalars);
     return ret;
 }
 
-static int ecp_nistz256_get_affine(const EC_GROUP * group,
-                                   const EC_POINT * point,
-                                   BIGNUM * x, BIGNUM * y, BN_CTX * ctx)
+static int ecp_nistz256_get_affine(const EC_GROUP *group,
+                                   const EC_POINT *point,
+                                   BIGNUM *x, BIGNUM *y, BN_CTX *ctx)
 {
     BN_ULONG z_inv2[P256_LIMBS];
     BN_ULONG z_inv3[P256_LIMBS];
     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);
@@ -1312,32 +1367,30 @@ 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);
-        x->top = P256_LIMBS;
-        ecp_nistz256_from_mont(x->d, x_aff);
-        bn_correct_top(x);
+        ecp_nistz256_from_mont(x_ret, x_aff);
+        if (!ecp_nistz256_set_words(x, x_ret))
+            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);
-        y->top = P256_LIMBS;
-        ecp_nistz256_from_mont(y->d, y_aff);
-        bn_correct_top(y);
+        ecp_nistz256_from_mont(y_ret, y_aff);
+        if (!ecp_nistz256_set_words(y, y_ret))
+            return 0;
     }
 
     return 1;
 }
 
-static EC_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP * group)
+static EC_PRE_COMP *ecp_nistz256_pre_comp_new(const EC_GROUP *group)
 {
     EC_PRE_COMP *ret = NULL;
 
     if (!group)
         return NULL;
 
-    ret = (EC_PRE_COMP *) OPENSSL_malloc(sizeof(EC_PRE_COMP));
+    ret = (EC_PRE_COMP *)OPENSSL_malloc(sizeof(EC_PRE_COMP));
 
     if (!ret) {
         ECerr(EC_F_ECP_NISTZ256_PRE_COMP_NEW, ERR_R_MALLOC_FAILURE);
@@ -1401,7 +1454,7 @@ static void ecp_nistz256_pre_comp_clear_free(void *pre_)
     OPENSSL_free(pre);
 }
 
-static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP * group)
+static int ecp_nistz256_window_have_precompute_mult(const EC_GROUP *group)
 {
     /* There is a hard-coded table for the default generator. */
     const EC_POINT *generator = EC_GROUP_get0_generator(group);