Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EC] Unify scalar multiplication for P-256/384/521 #1693

Merged
merged 18 commits into from
Jul 17, 2024
Merged
16 changes: 9 additions & 7 deletions crypto/fipsmodule/ec/ec_nistp.c
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,6 @@ static void scalar_rwnaf(int16_t *out, size_t window_size,
// determined by the maximum scalar bit size -- 521 bits in our case.
#define SCALAR_MUL_MAX_NUM_WINDOWS DIV_AND_CEIL(521, SCALAR_MUL_WINDOW_SIZE)

// We define the maximum number of digits a scalar can be recoded to with
// |scalar_rwnaf|, to avoid need for dynami

// 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].
static void generate_table(const ec_nistp_meth *ctx,
Expand Down Expand Up @@ -375,7 +372,7 @@ static void select_point_from_table(const ec_nistp_meth *ctx,
idx, SCALAR_MUL_TABLE_NUM_POINTS, entry_size);
}

// Multiplication of a point by a scalar, r = [scalar]P.
// Multiplication of an arbitrary point by a scalar, r = [scalar]P.
// The product is computed with the use of a small table generated on-the-fly
dkostic marked this conversation as resolved.
Show resolved Hide resolved
// and the scalar recoded in the regular-wNAF representation.
//
Expand All @@ -388,7 +385,7 @@ static void select_point_from_table(const ec_nistp_meth *ctx,
// The scalar is recoded (regular-wNAF encoding) into signed digits as explained
// in |scalar_rwnaf| function. Namely, for a window size |w| we have:
// scalar' = s_0 + s_1*2^w + s_2*2^(2*w) + ... + s_{m-1}*2^(m*w),
// where digits s_i are in [\pm 1, \pm 3, ..., \pm 31] and
// where digits s_i are in [\pm 1, \pm 3, ..., \pm (2^w-1)] and
// m = ceil(scalar_bit_size / w). Note that for an odd scalar we have that
// scalar = scalar', while in the case of an even scalar we have that
// scalar = scalar' - 1.
Expand All @@ -412,6 +409,10 @@ void ec_nistp_scalar_mul(const ec_nistp_meth *ctx,
const ec_nistp_felem_limb *y_in,
const ec_nistp_felem_limb *z_in,
const EC_SCALAR *scalar) {
// Make sure that the max table size is large enough.
assert(SCALAR_MUL_TABLE_MAX_NUM_FELEM_LIMBS >=
SCALAR_MUL_TABLE_NUM_POINTS * ctx->felem_num_limbs * 3);

// Table of multiples of P = (x_in, y_in, z_in).
ec_nistp_felem_limb table[SCALAR_MUL_TABLE_MAX_NUM_FELEM_LIMBS];
dkostic marked this conversation as resolved.
Show resolved Hide resolved
generate_table(ctx, table, x_in, y_in, z_in);
Expand All @@ -437,8 +438,9 @@ void ec_nistp_scalar_mul(const ec_nistp_meth *ctx,
// description above the function).
const size_t num_windows = DIV_AND_CEIL(ctx->felem_num_bits, SCALAR_MUL_WINDOW_SIZE);

// Step 1. Initialize the accmulator (res) with the most significant digit,
// s_{m-1}, of the scalar (note that this digit can't be negative).
// Step 1. Initialize the accmulator (res) with the input point multiplied by
// the most significant digit of the scalar s_{m-1} (note that this digit
// can't be negative).
int16_t idx = rwnaf[num_windows - 1];
idx >>= 1;
select_point_from_table(ctx, res, table, idx);
Expand Down
30 changes: 1 addition & 29 deletions crypto/fipsmodule/ec/p384.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,35 +508,7 @@ static void p384_select_point_affine(p384_felem out[2],
}
}

// Multiplication of a point by a scalar, r = [scalar]P.
// The product is computed with the use of a small table generated on-the-fly
// and the scalar recoded in the regular-wNAF representation.
//
// The precomputed (on-the-fly) table |p_pre_comp| holds 16 odd multiples of P:
// [2i + 1]P for i in [0, 15].
// Computing the negation of a point P = (x, y) is relatively easy:
// -P = (x, -y).
// So we may assume that instead of the above-mentioned 64, we have 128 points:
// [\pm 1]P, [\pm 3]P, [\pm 5]P, ..., [\pm 31]P.
//
// The 384-bit scalar is recoded (regular-wNAF encoding) into 77 signed digits
// each of length 5 bits, as explained in the |p384_felem_mul_scalar_rwnaf|
// function. Namely,
// scalar' = s_0 + s_1*2^5 + s_2*2^10 + ... + s_76*2^380,
// where digits s_i are in [\pm 1, \pm 3, ..., \pm 31]. Note that for an odd
// scalar we have that scalar = scalar', while in the case of an even
// scalar we have that scalar = scalar' - 1.
//
// The required product, [scalar]P, is computed by the following algorithm.
// 1. Initialize the accumulator with the point from |p_pre_comp|
// corresponding to the most significant digit s_76 of the scalar.
// 2. For digits s_i starting from s_75 down to s_0:
// 3. Double the accumulator 5 times. (note that doubling a point [a]P
// seven times results in [2^5*a]P).
// 4. Read from |p_pre_comp| the point corresponding to abs(s_i),
// negate it if s_i is negative, and add it to the accumulator.
//
// Note: this function is constant-time.
// Multiplication of an arbitrary point by a scalar, r = [scalar]P.
dkostic marked this conversation as resolved.
Show resolved Hide resolved
static void ec_GFp_nistp384_point_mul(const EC_GROUP *group, EC_JACOBIAN *r,
const EC_JACOBIAN *p,
const EC_SCALAR *scalar) {
Expand Down
30 changes: 1 addition & 29 deletions crypto/fipsmodule/ec/p521.c
Original file line number Diff line number Diff line change
Expand Up @@ -445,35 +445,7 @@ static void p521_select_point_affine(p521_felem out[2],
}
}

// Multiplication of a point by a scalar, r = [scalar]P.
// The product is computed with the use of a small table generated on-the-fly
// and the scalar recoded in the regular-wNAF representation.
//
// The precomputed (on-the-fly) table |p_pre_comp| holds 16 odd multiples of P:
// [2i + 1]P for i in [0, 15].
// Computing the negation of a point P = (x, y) is relatively easy:
// -P = (x, -y).
// So we may assume that instead of the above-mentioned 16, we have 32 points:
// [\pm 1]P, [\pm 3]P, [\pm 5]P, ..., [\pm 31]P.
//
// The 521-bit scalar is recoded (regular-wNAF encoding) into 105 signed digits
// each of length 5 bits, as explained in the |p521_felem_mul_scalar_rwnaf|
// function. Namely,
// scalar' = s_0 + s_1*2^5 + s_2*2^10 + ... + s_104*2^520,
// where digits s_i are in [\pm 1, \pm 3, ..., \pm 31]. Note that for an odd
// scalar we have that scalar = scalar', while in the case of an even
// scalar we have that scalar = scalar' - 1.
//
// The required product, [scalar]P, is computed by the following algorithm.
// 1. Initialize the accumulator with the point from |p_pre_comp|
// corresponding to the most significant digit s_104 of the scalar.
// 2. For digits s_i starting from s_104 down to s_0:
// 3. Double the accumulator 5 times. (note that doubling a point [a]P
// seven times results in [2^5*a]P).
// 4. Read from |p_pre_comp| the point corresponding to abs(s_i),
// negate it if s_i is negative, and add it to the accumulator.
//
// Note: this function is constant-time.
// Multiplication of an arbitrary point by a scalar, r = [scalar]P.
static void ec_GFp_nistp521_point_mul(const EC_GROUP *group, EC_JACOBIAN *r,
const EC_JACOBIAN *p,
const EC_SCALAR *scalar) {
Expand Down
Loading