diff --git a/crypto/fipsmodule/ec/ec_nistp.c b/crypto/fipsmodule/ec/ec_nistp.c index be377c4c21..13120c6ee8 100644 --- a/crypto/fipsmodule/ec/ec_nistp.c +++ b/crypto/fipsmodule/ec/ec_nistp.c @@ -303,3 +303,43 @@ void scalar_rwnaf(int16_t *out, size_t window_size, } out[num_windows - 1] = window; } + +// Generate table of multiples of the input point P = (x_in, y_in, z_in): +// table <-- [2i + 1]P for i in [0, SCALAR_MUL_TABLE_NUM_POINTS - 1]. +void generate_table(const ec_nistp_meth *ctx, + ec_nistp_felem_limb *table, + ec_nistp_felem_limb *x_in, + ec_nistp_felem_limb *y_in, + ec_nistp_felem_limb *z_in) +{ + const size_t felem_num_limbs = ctx->felem_num_limbs; + const size_t felem_num_bytes = felem_num_limbs * sizeof(ec_nistp_felem_limb); + + // Helper variables to access individual coordinates of a point. + const size_t x_idx = 0; + const size_t y_idx = felem_num_limbs; + const size_t z_idx = felem_num_limbs * 2; + + // table[0] <-- P. + OPENSSL_memcpy(&table[x_idx], x_in, felem_num_bytes); + OPENSSL_memcpy(&table[y_idx], y_in, felem_num_bytes); + OPENSSL_memcpy(&table[z_idx], z_in, felem_num_bytes); + + // Compute 2P. + ec_nistp_felem x_in_dbl, y_in_dbl, z_in_dbl; + ctx->point_dbl(x_in_dbl, y_in_dbl, z_in_dbl, + &table[x_idx], &table[y_idx], &table[z_idx]); + + // Compute the rest of the table. + for (size_t i = 1; i < SCALAR_MUL_TABLE_NUM_POINTS; i++) { + // Just getting pointers to i-th and (i-1)-th point in the table. + ec_nistp_felem_limb *point_i = &table[i * 3 * felem_num_limbs]; + ec_nistp_felem_limb *point_im1 = &table[(i - 1) * 3 * felem_num_limbs]; + + // table[i] <-- table[i - 1] + 2P + ctx->point_add(&point_i[x_idx], &point_i[y_idx], &point_i[z_idx], + &point_im1[x_idx], &point_im1[y_idx], &point_im1[z_idx], + 0, x_in_dbl, y_in_dbl, z_in_dbl); + } +} + diff --git a/crypto/fipsmodule/ec/ec_nistp.h b/crypto/fipsmodule/ec/ec_nistp.h index da4476265a..1d86e9804e 100644 --- a/crypto/fipsmodule/ec/ec_nistp.h +++ b/crypto/fipsmodule/ec/ec_nistp.h @@ -96,7 +96,20 @@ void ec_nistp_point_add(const ec_nistp_meth *ctx, const ec_nistp_felem_limb *y2, const ec_nistp_felem_limb *z2); +// These two functions and two macros are temporarily defined here. +// They will be moved to ec_nistp.c as static function +// once all the scalar multiplications are implemented. void scalar_rwnaf(int16_t *out, size_t window_size, const EC_SCALAR *scalar, size_t scalar_bit_size); +void generate_table(const ec_nistp_meth *ctx, + ec_nistp_felem_limb *table, + ec_nistp_felem_limb *x_in, + ec_nistp_felem_limb *y_in, + ec_nistp_felem_limb *z_in); + +// The window size for scalar multiplication is hard coded for now. +#define SCALAR_MUL_WINDOW_SIZE (5) +#define SCALAR_MUL_TABLE_NUM_POINTS (1 << (SCALAR_MUL_WINDOW_SIZE - 1)) + #endif // EC_NISTP_H diff --git a/crypto/fipsmodule/ec/p384.c b/crypto/fipsmodule/ec/p384.c index 5dfb06b4e9..bcd3c5ba4e 100644 --- a/crypto/fipsmodule/ec/p384.c +++ b/crypto/fipsmodule/ec/p384.c @@ -490,6 +490,9 @@ OPENSSL_STATIC_ASSERT(P384_MUL_WSIZE == 5, #define P384_MUL_TABLE_SIZE (P384_MUL_TWO_TO_WSIZE >> 1) #define P384_MUL_PUB_TABLE_SIZE (1 << (P384_MUL_PUB_WSIZE - 1)) +OPENSSL_STATIC_ASSERT(P384_MUL_TABLE_SIZE <= SCALAR_MUL_TABLE_NUM_POINTS, + p384_table_size_larger_than_ec_nistp_supports) + // p384_select_point selects the |idx|-th projective point from the given // precomputed table and copies it to |out| in constant time. static void p384_select_point(p384_felem out[3], @@ -558,22 +561,12 @@ static void ec_GFp_nistp384_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, p384_felem p_pre_comp[P384_MUL_TABLE_SIZE][3]; // Set the first point in the table to P. - p384_from_generic(p_pre_comp[0][0], &p->X); - p384_from_generic(p_pre_comp[0][1], &p->Y); - p384_from_generic(p_pre_comp[0][2], &p->Z); - - // Compute tmp = [2]P. - p384_point_double(tmp[0], tmp[1], tmp[2], - p_pre_comp[0][0], p_pre_comp[0][1], p_pre_comp[0][2]); + p384_from_generic(tmp[0], &p->X); + p384_from_generic(tmp[1], &p->Y); + p384_from_generic(tmp[2], &p->Z); - // Generate the remaining 15 multiples of P. - for (size_t i = 1; i < P384_MUL_TABLE_SIZE; i++) { - p384_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], - tmp[0], tmp[1], tmp[2], 0 /* both Jacobian */, - p_pre_comp[i - 1][0], - p_pre_comp[i - 1][1], - p_pre_comp[i - 1][2]); - } + assert(sizeof(p_pre_comp) == (P384_MUL_TABLE_SIZE * 3 * sizeof(p384_felem))); + generate_table(p384_methods(), (ec_nistp_felem_limb*)p_pre_comp, tmp[0], tmp[1], tmp[2]); // Recode the scalar. int16_t rnaf[P384_MUL_NWINDOWS] = {0}; diff --git a/crypto/fipsmodule/ec/p521.c b/crypto/fipsmodule/ec/p521.c index 299eae050c..3833e04954 100644 --- a/crypto/fipsmodule/ec/p521.c +++ b/crypto/fipsmodule/ec/p521.c @@ -427,6 +427,9 @@ OPENSSL_STATIC_ASSERT(P521_MUL_WSIZE == 5, #define P521_MUL_TABLE_SIZE (P521_MUL_TWO_TO_WSIZE >> 1) #define P521_MUL_PUB_TABLE_SIZE (1 << (P521_MUL_PUB_WSIZE - 1)) +OPENSSL_STATIC_ASSERT(P521_MUL_TABLE_SIZE <= SCALAR_MUL_TABLE_NUM_POINTS, + p521_table_size_larger_than_ec_nistp_supports) + // p521_select_point selects the |idx|-th projective point from the given // precomputed table and copies it to |out| in constant time. static void p521_select_point(p521_felem out[3], @@ -495,22 +498,12 @@ static void ec_GFp_nistp521_point_mul(const EC_GROUP *group, EC_JACOBIAN *r, p521_felem p_pre_comp[P521_MUL_TABLE_SIZE][3]; // Set the first point in the table to P. - p521_from_generic(p_pre_comp[0][0], &p->X); - p521_from_generic(p_pre_comp[0][1], &p->Y); - p521_from_generic(p_pre_comp[0][2], &p->Z); - - // Compute tmp = [2]P. - p521_point_double(tmp[0], tmp[1], tmp[2], - p_pre_comp[0][0], p_pre_comp[0][1], p_pre_comp[0][2]); + p521_from_generic(tmp[0], &p->X); + p521_from_generic(tmp[1], &p->Y); + p521_from_generic(tmp[2], &p->Z); - // Generate the remaining 15 multiples of P. - for (size_t i = 1; i < P521_MUL_TABLE_SIZE; i++) { - p521_point_add(p_pre_comp[i][0], p_pre_comp[i][1], p_pre_comp[i][2], - tmp[0], tmp[1], tmp[2], 0 /* both Jacobian */, - p_pre_comp[i - 1][0], - p_pre_comp[i - 1][1], - p_pre_comp[i - 1][2]); - } + assert(sizeof(p_pre_comp) == (P521_MUL_TABLE_SIZE * 3 * sizeof(p521_felem))); + generate_table(p521_methods(), (ec_nistp_felem_limb*)p_pre_comp, tmp[0], tmp[1], tmp[2]); // Recode the scalar. int16_t rnaf[P521_MUL_NWINDOWS] = {0};