diff options
Diffstat (limited to 'src/crypto/ec/p256-x86_64.c')
-rw-r--r-- | src/crypto/ec/p256-x86_64.c | 485 |
1 files changed, 190 insertions, 295 deletions
diff --git a/src/crypto/ec/p256-x86_64.c b/src/crypto/ec/p256-x86_64.c index 09816ad..2f7023d 100644 --- a/src/crypto/ec/p256-x86_64.c +++ b/src/crypto/ec/p256-x86_64.c @@ -22,6 +22,7 @@ #include <openssl/ec.h> +#include <assert.h> #include <stdint.h> #include <string.h> @@ -37,18 +38,13 @@ #if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_X86_64) && \ !defined(OPENSSL_SMALL) -#if BN_BITS2 != 64 -#define TOBN(hi, lo) lo, hi -#else -#define TOBN(hi, lo) ((BN_ULONG)hi << 32 | lo) -#endif #if defined(__GNUC__) -#define ALIGN32 __attribute((aligned(32))) +#define ALIGN(x) __attribute((aligned(x))) #elif defined(_MSC_VER) -#define ALIGN32 __declspec(align(32)) +#define ALIGN(x) __declspec(align(x)) #else -#define ALIGN32 +#define ALIGN(x) #endif #define ALIGNPTR(p, N) ((uint8_t *)p + N - (size_t)p % N) @@ -69,21 +65,6 @@ typedef P256_POINT_AFFINE PRECOMP256_ROW[64]; /* Functions implemented in assembly */ -/* Modular mul by 2: res = 2*a mod P */ -void ecp_nistz256_mul_by_2(BN_ULONG res[P256_LIMBS], - const BN_ULONG a[P256_LIMBS]); -/* Modular div by 2: res = a/2 mod P */ -void ecp_nistz256_div_by_2(BN_ULONG res[P256_LIMBS], - const BN_ULONG a[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 */ -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 */ -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 */ void ecp_nistz256_neg(BN_ULONG res[P256_LIMBS], const BN_ULONG a[P256_LIMBS]); /* Montgomery mul: res = a*b*2^-256 mod P */ @@ -96,9 +77,6 @@ void ecp_nistz256_sqr_mont(BN_ULONG res[P256_LIMBS], /* Convert a number from Montgomery domain, by multiplying with 1 */ void ecp_nistz256_from_mont(BN_ULONG res[P256_LIMBS], const BN_ULONG in[P256_LIMBS]); -/* Convert a number to Montgomery domain, by multiplying with 2^512 mod P*/ -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_select_w5(P256_POINT *val, const P256_POINT *in_t, int index); void ecp_nistz256_select_w7(P256_POINT_AFFINE *val, @@ -153,48 +131,6 @@ static void copy_conditional(BN_ULONG dst[P256_LIMBS], } } -static BN_ULONG is_zero(BN_ULONG in) { - in |= (0 - in); - in = ~in; - in &= BN_MASK2; - in >>= BN_BITS2 - 1; - return in; -} - -static BN_ULONG is_equal(const BN_ULONG a[P256_LIMBS], - const BN_ULONG b[P256_LIMBS]) { - BN_ULONG res; - - res = a[0] ^ b[0]; - res |= a[1] ^ b[1]; - res |= a[2] ^ b[2]; - res |= a[3] ^ b[3]; - if (P256_LIMBS == 8) { - res |= a[4] ^ b[4]; - res |= a[5] ^ b[5]; - res |= a[6] ^ b[6]; - res |= a[7] ^ b[7]; - } - - return is_zero(res); -} - -static BN_ULONG is_one(const BN_ULONG a[P256_LIMBS]) { - BN_ULONG res; - - res = a[0] ^ ONE[0]; - res |= a[1] ^ ONE[1]; - res |= a[2] ^ ONE[2]; - res |= a[3] ^ ONE[3]; - if (P256_LIMBS == 8) { - res |= a[4] ^ ONE[4]; - res |= a[5] ^ ONE[5]; - res |= a[6] ^ ONE[6]; - } - - return is_zero(res); -} - 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); @@ -296,113 +232,117 @@ static int ecp_nistz256_bignum_to_field_elem(BN_ULONG out[P256_LIMBS], return 1; } -/* 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) { +/* r = p * p_scalar */ +static int ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, + const EC_POINT *p, const BIGNUM *p_scalar, + BN_CTX *ctx) { + assert(p != NULL); + assert(p_scalar != NULL); + static const unsigned kWindowSize = 5; static const unsigned kMask = (1 << (5 /* kWindowSize */ + 1)) - 1; - void *table_storage = OPENSSL_malloc(num * 16 * sizeof(P256_POINT) + 64); - uint8_t(*p_str)[33] = OPENSSL_malloc(num * 33 * sizeof(uint8_t)); - const BIGNUM **scalars = OPENSSL_malloc(num * sizeof(BIGNUM *)); - - if (table_storage == NULL || - p_str == NULL || - scalars == NULL) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - goto err; - } + /* A |P256_POINT| is (3 * 32) = 96 bytes, and the 64-byte alignment should + * add no more than 63 bytes of overhead. Thus, |table| should require + * ~1599 ((96 * 16) + 63) bytes of stack space. */ + ALIGN(64) P256_POINT table[16]; + uint8_t p_str[33]; - P256_POINT(*table)[16] = (void *)ALIGNPTR(table_storage, 64); - int i; - for (i = 0; i < num; i++) { - P256_POINT *row = table[i]; + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; - if (BN_num_bits(scalar[i]) > 256 || BN_is_negative(scalar[i])) { - BIGNUM *mod = BN_CTX_get(ctx); - if (mod == NULL) { + if (BN_num_bits(p_scalar) > 256 || BN_is_negative(p_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); goto err; } - - if (!BN_nnmod(mod, scalar[i], &group->order, ctx)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - goto err; - } - scalars[i] = mod; - } else { - scalars[i] = scalar[i]; + ctx = new_ctx; } - - int j; - for (j = 0; j < scalars[i]->top * BN_BYTES; j += BN_BYTES) { - BN_ULONG d = scalars[i]->d[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; - 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; - } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *mod = BN_CTX_get(ctx); + if (mod == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } + if (!BN_nnmod(mod, p_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; } + p_scalar = mod; + } - for (; j < 33; j++) { - p_str[i][j] = 0; + int j; + for (j = 0; j < p_scalar->top * BN_BYTES; j += BN_BYTES) { + BN_ULONG d = p_scalar->d[j / BN_BYTES]; + + p_str[j + 0] = d & 0xff; + p_str[j + 1] = (d >> 8) & 0xff; + p_str[j + 2] = (d >> 16) & 0xff; + p_str[j + 3] = (d >>= 24) & 0xff; + if (BN_BYTES == 8) { + d >>= 8; + p_str[j + 4] = d & 0xff; + p_str[j + 5] = (d >> 8) & 0xff; + p_str[j + 6] = (d >> 16) & 0xff; + p_str[j + 7] = (d >> 24) & 0xff; } + } - /* table[0] is implicitly (0,0,0) (the point at infinity), therefore it is - * not stored. All other values are actually stored with an offset of -1 in - * table. */ + for (; j < 33; j++) { + p_str[j] = 0; + } - if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X, &point[i]->X) || - !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y, &point[i]->Y) || - !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z, &point[i]->Z)) { - OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); - goto err; - } + /* table[0] is implicitly (0,0,0) (the point at infinity), therefore it is + * not stored. All other values are actually stored with an offset of -1 in + * table. */ + P256_POINT *row = table; - ecp_nistz256_point_double(&row[2 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[3 - 1], &row[2 - 1], &row[1 - 1]); - ecp_nistz256_point_double(&row[4 - 1], &row[2 - 1]); - ecp_nistz256_point_double(&row[6 - 1], &row[3 - 1]); - ecp_nistz256_point_double(&row[8 - 1], &row[4 - 1]); - ecp_nistz256_point_double(&row[12 - 1], &row[6 - 1]); - ecp_nistz256_point_add(&row[5 - 1], &row[4 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[7 - 1], &row[6 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[9 - 1], &row[8 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]); - ecp_nistz256_point_double(&row[14 - 1], &row[7 - 1]); - ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]); - ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]); - ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]); + if (!ecp_nistz256_bignum_to_field_elem(row[1 - 1].X, &p->X) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Y, &p->Y) || + !ecp_nistz256_bignum_to_field_elem(row[1 - 1].Z, &p->Z)) { + OPENSSL_PUT_ERROR(EC, EC_R_COORDINATES_OUT_OF_RANGE); + goto err; } + ecp_nistz256_point_double(&row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[3 - 1], &row[2 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[4 - 1], &row[2 - 1]); + ecp_nistz256_point_double(&row[6 - 1], &row[3 - 1]); + ecp_nistz256_point_double(&row[8 - 1], &row[4 - 1]); + ecp_nistz256_point_double(&row[12 - 1], &row[6 - 1]); + ecp_nistz256_point_add(&row[5 - 1], &row[4 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[7 - 1], &row[6 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[9 - 1], &row[8 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[13 - 1], &row[12 - 1], &row[1 - 1]); + ecp_nistz256_point_double(&row[14 - 1], &row[7 - 1]); + ecp_nistz256_point_double(&row[10 - 1], &row[5 - 1]); + ecp_nistz256_point_add(&row[15 - 1], &row[14 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[11 - 1], &row[10 - 1], &row[1 - 1]); + ecp_nistz256_point_add(&row[16 - 1], &row[15 - 1], &row[1 - 1]); + BN_ULONG tmp[P256_LIMBS]; - ALIGN32 P256_POINT h; + ALIGN(32) P256_POINT h; unsigned index = 255; - unsigned wvalue = p_str[0][(index - 1) / 8]; + unsigned wvalue = p_str[(index - 1) / 8]; wvalue = (wvalue >> ((index - 1) % 8)) & kMask; - ecp_nistz256_select_w5(r, table[0], booth_recode_w5(wvalue) >> 1); + ecp_nistz256_select_w5(r, table, booth_recode_w5(wvalue) >> 1); while (index >= 5) { - for (i = (index == 255 ? 1 : 0); i < num; i++) { + if (index != 255) { unsigned off = (index - 1) / 8; - wvalue = p_str[i][off] | p_str[i][off + 1] << 8; + wvalue = p_str[off] | p_str[off + 1] << 8; wvalue = (wvalue >> ((index - 1) % 8)) & kMask; wvalue = booth_recode_w5(wvalue); - ecp_nistz256_select_w5(&h, table[i], wvalue >> 1); + ecp_nistz256_select_w5(&h, table, wvalue >> 1); ecp_nistz256_neg(tmp, h.Y); copy_conditional(h.Y, tmp, (wvalue & 1)); @@ -420,217 +360,166 @@ static void ecp_nistz256_windowed_mul(const EC_GROUP *group, P256_POINT *r, } /* Final window */ - for (i = 0; i < num; i++) { - wvalue = p_str[i][0]; - wvalue = (wvalue << 1) & kMask; + wvalue = p_str[0]; + wvalue = (wvalue << 1) & kMask; - wvalue = booth_recode_w5(wvalue); + wvalue = booth_recode_w5(wvalue); - ecp_nistz256_select_w5(&h, table[i], wvalue >> 1); + ecp_nistz256_select_w5(&h, table, wvalue >> 1); - ecp_nistz256_neg(tmp, h.Y); - copy_conditional(h.Y, tmp, wvalue & 1); + ecp_nistz256_neg(tmp, h.Y); + copy_conditional(h.Y, tmp, wvalue & 1); - ecp_nistz256_point_add(r, r, &h); - } + ecp_nistz256_point_add(r, r, &h); -err: - OPENSSL_free(table_storage); - OPENSSL_free(p_str); - OPENSSL_free((BIGNUM**) scalars); -} - -/* Coordinates of G, for which we have precomputed tables */ -const static BN_ULONG def_xG[P256_LIMBS] = { - TOBN(0x79e730d4, 0x18a9143c), TOBN(0x75ba95fc, 0x5fedb601), - TOBN(0x79fb732b, 0x77622510), TOBN(0x18905f76, 0xa53755c6), -}; - -const static BN_ULONG def_yG[P256_LIMBS] = { - TOBN(0xddf25357, 0xce95560a), TOBN(0x8b4ab8e4, 0xba19e45c), - TOBN(0xd2e88688, 0xdd21f325), TOBN(0x8571ff18, 0x25885d85) -}; + ret = 1; -/* 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) && - (generator->Z.top == (P256_LIMBS - P256_LIMBS / 8)) && - is_equal(generator->X.d, def_xG) && is_equal(generator->Y.d, def_yG) && - is_one(generator->Z.d); +err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); + return ret; } -/* r = scalar*G + sum(scalars[i]*points[i]) */ 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_GROUP *group, EC_POINT *r, const BIGNUM *g_scalar, + const EC_POINT *p_, const BIGNUM *p_scalar, BN_CTX *ctx) { + assert((p_ != NULL) == (p_scalar != NULL)); + static const unsigned kWindowSize = 7; static const unsigned kMask = (1 << (7 /* kWindowSize */ + 1)) - 1; - int ret = 0, no_precomp_for_generator = 0, p_is_infinity = 0; - ALIGN32 union { + ALIGN(32) union { P256_POINT p; P256_POINT_AFFINE a; } t, p; - if (scalar == NULL && num == 0) { - return EC_POINT_set_to_infinity(group, r); - } + int ret = 0; + BN_CTX *new_ctx = NULL; + int ctx_started = 0; /* 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); + if (bn_wexpand(&r->X, P256_LIMBS) == NULL || + bn_wexpand(&r->Y, P256_LIMBS) == NULL || + bn_wexpand(&r->Z, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + goto err; + } r->X.top = P256_LIMBS; r->Y.top = P256_LIMBS; r->Z.top = P256_LIMBS; - const EC_POINT *generator = NULL; - if (scalar) { - generator = EC_GROUP_get0_generator(group); - if (generator == NULL) { - OPENSSL_PUT_ERROR(EC, EC_R_UNDEFINED_GENERATOR); - goto err; - } - - if (ecp_nistz256_is_affine_G(generator)) { - if (BN_num_bits(scalar) > 256 || BN_is_negative(scalar)) { - BIGNUM *tmp_scalar = BN_CTX_get(ctx); - if (tmp_scalar == NULL) { + if (g_scalar != NULL) { + if (BN_num_bits(g_scalar) > 256 || BN_is_negative(g_scalar)) { + if (ctx == NULL) { + new_ctx = BN_CTX_new(); + if (new_ctx == NULL) { goto err; } - - if (!BN_nnmod(tmp_scalar, scalar, &group->order, ctx)) { - OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); - goto err; - } - scalar = tmp_scalar; + ctx = new_ctx; } - - uint8_t p_str[33] = {0}; - int i; - for (i = 0; i < scalar->top * BN_BYTES; i += BN_BYTES) { - BN_ULONG d = scalar->d[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; - 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; - } + BN_CTX_start(ctx); + ctx_started = 1; + BIGNUM *tmp_scalar = BN_CTX_get(ctx); + if (tmp_scalar == NULL) { + goto err; } - for (; i < (int) sizeof(p_str); i++) { - p_str[i] = 0; + if (!BN_nnmod(tmp_scalar, g_scalar, &group->order, ctx)) { + OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); + goto err; } + g_scalar = tmp_scalar; + } - /* First window */ - unsigned wvalue = (p_str[0] << 1) & kMask; - unsigned index = kWindowSize; - - wvalue = booth_recode_w7(wvalue); + uint8_t p_str[33] = {0}; + int i; + for (i = 0; i < g_scalar->top * BN_BYTES; i += BN_BYTES) { + BN_ULONG d = g_scalar->d[i / BN_BYTES]; - const PRECOMP256_ROW *const precomputed_table = - (const PRECOMP256_ROW *)ecp_nistz256_precomputed; - ecp_nistz256_select_w7(&p.a, precomputed_table[0], wvalue >> 1); + 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; + 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; + } + } - ecp_nistz256_neg(p.p.Z, p.p.Y); - copy_conditional(p.p.Y, p.p.Z, wvalue & 1); + for (; i < (int) sizeof(p_str); i++) { + p_str[i] = 0; + } - memcpy(p.p.Z, ONE, sizeof(ONE)); + /* First window */ + unsigned wvalue = (p_str[0] << 1) & kMask; + unsigned index = kWindowSize; - for (i = 1; i < 37; i++) { - unsigned off = (index - 1) / 8; - wvalue = p_str[off] | p_str[off + 1] << 8; - wvalue = (wvalue >> ((index - 1) % 8)) & kMask; - index += kWindowSize; + wvalue = booth_recode_w7(wvalue); - wvalue = booth_recode_w7(wvalue); + const PRECOMP256_ROW *const precomputed_table = + (const PRECOMP256_ROW *)ecp_nistz256_precomputed; + ecp_nistz256_select_w7(&p.a, precomputed_table[0], wvalue >> 1); - ecp_nistz256_select_w7(&t.a, precomputed_table[i], wvalue >> 1); + ecp_nistz256_neg(p.p.Z, p.p.Y); + copy_conditional(p.p.Y, p.p.Z, wvalue & 1); - ecp_nistz256_neg(t.p.Z, t.a.Y); - copy_conditional(t.a.Y, t.p.Z, wvalue & 1); + memcpy(p.p.Z, ONE, sizeof(ONE)); - ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); - } - } else { - p_is_infinity = 1; - no_precomp_for_generator = 1; - } - } else { - p_is_infinity = 1; - } + for (i = 1; i < 37; i++) { + unsigned off = (index - 1) / 8; + wvalue = p_str[off] | p_str[off + 1] << 8; + wvalue = (wvalue >> ((index - 1) % 8)) & kMask; + index += kWindowSize; - 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; + wvalue = booth_recode_w7(wvalue); - /* Bound |num| so that all the possible overflows in the following can be - * excluded. */ - if (0xffffff < num) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - return 0; - } + ecp_nistz256_select_w7(&t.a, precomputed_table[i], wvalue >> 1); - new_scalars = OPENSSL_malloc((num + 1) * sizeof(BIGNUM *)); - if (new_scalars == NULL) { - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - return 0; - } + ecp_nistz256_neg(t.p.Z, t.a.Y); + copy_conditional(t.a.Y, t.p.Z, wvalue & 1); - new_points = OPENSSL_malloc((num + 1) * sizeof(EC_POINT *)); - if (new_points == NULL) { - OPENSSL_free((BIGNUM**) new_scalars); - OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); - return 0; + ecp_nistz256_point_add_affine(&p.p, &p.p, &t.a); } - - memcpy((BIGNUM**) new_scalars, scalars, num * sizeof(BIGNUM *)); - new_scalars[num] = scalar; - memcpy((EC_POINT**) new_points, points, num * sizeof(EC_POINT *)); - new_points[num] = generator; - - scalars = new_scalars; - points = new_points; - num++; } - if (num) { + const int p_is_infinity = g_scalar == NULL; + if (p_scalar != NULL) { P256_POINT *out = &t.p; if (p_is_infinity) { out = &p.p; } - ecp_nistz256_windowed_mul(group, out, scalars, points, num, ctx); + if (!ecp_nistz256_windowed_mul(group, out, p_, p_scalar, ctx)) { + goto err; + } if (!p_is_infinity) { ecp_nistz256_point_add(&p.p, &p.p, out); } } - if (no_precomp_for_generator) { - OPENSSL_free((BIGNUM **) scalars); - OPENSSL_free((EC_POINT **) points); - } - 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)); + + /* 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 = BN_is_one(&r->Z); ret = 1; err: + if (ctx_started) { + BN_CTX_end(ctx); + } + BN_CTX_free(new_ctx); return ret; } @@ -659,7 +548,10 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point, ecp_nistz256_mul_mont(x_aff, z_inv2, point_x); if (x != NULL) { - bn_wexpand(x, P256_LIMBS); + if (bn_wexpand(x, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } x->top = P256_LIMBS; ecp_nistz256_from_mont(x->d, x_aff); bn_correct_top(x); @@ -668,7 +560,10 @@ static int ecp_nistz256_get_affine(const EC_GROUP *group, const EC_POINT *point, 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); + if (bn_wexpand(y, P256_LIMBS) == NULL) { + OPENSSL_PUT_ERROR(EC, ERR_R_MALLOC_FAILURE); + return 0; + } y->top = P256_LIMBS; ecp_nistz256_from_mont(y->d, y_aff); bn_correct_top(y); @@ -686,7 +581,7 @@ const EC_METHOD *EC_GFp_nistz256_method(void) { ec_GFp_mont_group_set_curve, ecp_nistz256_get_affine, ecp_nistz256_points_mul, - 0, /* precompute_mult */ + 0 /* check_pub_key_order */, ec_GFp_mont_field_mul, ec_GFp_mont_field_sqr, ec_GFp_mont_field_encode, |