summaryrefslogtreecommitdiffstats
path: root/src/crypto/ec/p256-x86_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/ec/p256-x86_64.c')
-rw-r--r--src/crypto/ec/p256-x86_64.c485
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,