Skip to content

Commit

Permalink
Added generic EC scalar rwnaf encoding for ec_nistp
Browse files Browse the repository at this point in the history
  • Loading branch information
dkostic committed Jun 25, 2024
1 parent 845ef24 commit ca05d18
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 75 deletions.
39 changes: 39 additions & 0 deletions crypto/fipsmodule/ec/ec_nistp.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,3 +259,42 @@ void ec_nistp_point_add(const ec_nistp_meth *ctx,
cmovznz(z3, ctx->felem_num_limbs, z2nz, z1, z_out);
}

static int16_t get_bit(const EC_SCALAR *in, size_t in_bit_size, size_t i) {
if (i >= in_bit_size) {
return 0;
}
#if defined(OPENSSL_64_BIT)
assert(sizeof(BN_ULONG) == 8);
return (in->words[i >> 6] >> (i & 63)) & 1;
#else
assert(sizeof(BN_ULONG) == 4);
return (in->words[i >> 5] >> (i & 31)) & 1;
#endif
}

#define DIV_AND_CEIL(a, b) ((a + b - 1) / b)

// Compute "regular" wNAF representation of a scalar, see
// Joye, Tunstall, "Exponent Recoding and Regular Exponentiation Algorithms",
// AfricaCrypt 2009, Alg 6.
// It forces an odd scalar and outputs digits in
// {\pm 1, \pm 3, \pm 5, \pm 7, \pm 9, ...}
// i.e. signed odd digits with _no zeroes_ -- that makes it "regular".
void scalar_rwnaf(int16_t *out, size_t window_size,
const EC_SCALAR *scalar, size_t scalar_bit_size) {
int16_t window, d;

const BN_ULONG window_mask = (1 << (window_size + 1)) - 1;
const size_t num_windows = DIV_AND_CEIL(scalar_bit_size, window_size);

window = (scalar->words[0] & window_mask) | 1;
for (size_t i = 0; i < num_windows - 1; i++) {
d = (window & window_mask) - (1 << window_size);
out[i] = d;
window = (window - d) >> window_size;
for (size_t j = 1; j <= window_size; j++) {
window += get_bit(scalar, scalar_bit_size, (i + 1) * window_size + j) << j;
}
}
out[num_windows - 1] = window;
}
3 changes: 3 additions & 0 deletions crypto/fipsmodule/ec/ec_nistp.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,5 +95,8 @@ void ec_nistp_point_add(const ec_nistp_meth *ctx,
const ec_nistp_felem_limb *x2,
const ec_nistp_felem_limb *y2,
const ec_nistp_felem_limb *z2);

void scalar_rwnaf(int16_t *out, size_t window_size,
const EC_SCALAR *scalar, size_t scalar_bit_size);
#endif // EC_NISTP_H

40 changes: 2 additions & 38 deletions crypto/fipsmodule/ec/p384.c
Original file line number Diff line number Diff line change
Expand Up @@ -470,21 +470,6 @@ static int ec_GFp_nistp384_cmp_x_coordinate(const EC_GROUP *group,
//
// For detailed analysis of different window sizes see the bottom of this file.


// p384_get_bit returns the |i|-th bit in |in|
static crypto_word_t p384_get_bit(const EC_SCALAR *in, int i) {
if (i < 0 || i >= 384) {
return 0;
}
#if defined(OPENSSL_64_BIT)
assert(sizeof(BN_ULONG) == 8);
return (in->words[i >> 6] >> (i & 63)) & 1;
#else
assert(sizeof(BN_ULONG) == 4);
return (in->words[i >> 5] >> (i & 31)) & 1;
#endif
}

// Constants for scalar encoding in the scalar multiplication functions.
#define P384_MUL_WSIZE (5) // window size w
// Assert the window size is 5 because the pre-computed table in |p384_table.h|
Expand All @@ -506,27 +491,6 @@ 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))

// Compute "regular" wNAF representation of a scalar, see
// Joye, Tunstall, "Exponent Recoding and Regular Exponentiation Algorithms",
// AfricaCrypt 2009, Alg 6.
// It forces an odd scalar and outputs digits in
// {\pm 1, \pm 3, \pm 5, \pm 7, \pm 9, ...}
// i.e. signed odd digits with _no zeroes_ -- that makes it "regular".
static void p384_felem_mul_scalar_rwnaf(int16_t *out, const EC_SCALAR *in) {
int16_t window, d;

window = (in->words[0] & P384_MUL_WSIZE_MASK) | 1;
for (size_t i = 0; i < P384_MUL_NWINDOWS - 1; i++) {
d = (window & P384_MUL_WSIZE_MASK) - P384_MUL_TWO_TO_WSIZE;
out[i] = d;
window = (window - d) >> P384_MUL_WSIZE;
for (size_t j = 1; j <= P384_MUL_WSIZE; j++) {
window += p384_get_bit(in, (i + 1) * P384_MUL_WSIZE + j) << j;
}
}
out[P384_MUL_NWINDOWS - 1] = window;
}

// 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],
Expand Down Expand Up @@ -614,7 +578,7 @@ static void ec_GFp_nistp384_point_mul(const EC_GROUP *group, EC_JACOBIAN *r,

// Recode the scalar.
int16_t rnaf[P384_MUL_NWINDOWS] = {0};
p384_felem_mul_scalar_rwnaf(rnaf, scalar);
scalar_rwnaf(rnaf, P384_MUL_WSIZE, scalar, 384);

// Initialize the accumulator |res| with the table entry corresponding to
// the most significant digit of the recoded scalar (note that this digit
Expand Down Expand Up @@ -738,7 +702,7 @@ static void ec_GFp_nistp384_point_mul_base(const EC_GROUP *group,
int16_t rnaf[P384_MUL_NWINDOWS] = {0};

// Recode the scalar.
p384_felem_mul_scalar_rwnaf(rnaf, scalar);
scalar_rwnaf(rnaf, P384_MUL_WSIZE, scalar, 384);

// Process the 4 groups of digits starting from group (3) down to group (0).
for (int i = 3; i >= 0; i--) {
Expand Down
39 changes: 2 additions & 37 deletions crypto/fipsmodule/ec/p521.c
Original file line number Diff line number Diff line change
Expand Up @@ -407,20 +407,6 @@ static void ec_GFp_nistp521_dbl(const EC_GROUP *group, EC_JACOBIAN *r,
// The precomputed table of base point multiples is generated by the code in
// |make_tables.go| script.

// p521_get_bit returns the |i|-th bit in |in|
static crypto_word_t p521_get_bit(const EC_SCALAR *in, int i) {
if (i < 0 || i >= 521) {
return 0;
}
#if defined(OPENSSL_64_BIT)
assert(sizeof(BN_ULONG) == 8);
return (in->words[i >> 6] >> (i & 63)) & 1;
#else
assert(sizeof(BN_ULONG) == 4);
return (in->words[i >> 5] >> (i & 31)) & 1;
#endif
}

// Constants for scalar encoding in the scalar multiplication functions.
#define P521_MUL_WSIZE (5) // window size w
// Assert the window size is 5 because the pre-computed table in |p521_table.h|
Expand All @@ -442,27 +428,6 @@ 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))

// Compute "regular" wNAF representation of a scalar, see
// Joye, Tunstall, "Exponent Recoding and Regular Exponentiation Algorithms",
// AfricaCrypt 2009, Alg 6.
// It forces an odd scalar and outputs digits in
// {\pm 1, \pm 3, \pm 5, \pm 7, \pm 9, ...}
// i.e. signed odd digits with _no zeroes_ -- that makes it "regular".
static void p521_felem_mul_scalar_rwnaf(int16_t *out, const EC_SCALAR *in) {
int16_t window, d;

window = (in->words[0] & P521_MUL_WSIZE_MASK) | 1;
for (size_t i = 0; i < P521_MUL_NWINDOWS - 1; i++) {
d = (window & P521_MUL_WSIZE_MASK) - P521_MUL_TWO_TO_WSIZE;
out[i] = d;
window = (window - d) >> P521_MUL_WSIZE;
for (size_t j = 1; j <= P521_MUL_WSIZE; j++) {
window += p521_get_bit(in, (i + 1) * P521_MUL_WSIZE + j) << j;
}
}
out[P521_MUL_NWINDOWS - 1] = window;
}

// 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],
Expand Down Expand Up @@ -550,7 +515,7 @@ static void ec_GFp_nistp521_point_mul(const EC_GROUP *group, EC_JACOBIAN *r,

// Recode the scalar.
int16_t rnaf[P521_MUL_NWINDOWS] = {0};
p521_felem_mul_scalar_rwnaf(rnaf, scalar);
scalar_rwnaf(rnaf, P521_MUL_WSIZE, scalar, 521);

// Initialize the accumulator |res| with the table entry corresponding to
// the most significant digit of the recoded scalar (note that this digit
Expand Down Expand Up @@ -674,7 +639,7 @@ static void ec_GFp_nistp521_point_mul_base(const EC_GROUP *group,
int16_t rnaf[P521_MUL_NWINDOWS] = {0};

// Recode the scalar.
p521_felem_mul_scalar_rwnaf(rnaf, scalar);
scalar_rwnaf(rnaf, P521_MUL_WSIZE, scalar, 521);

// Process the 4 groups of digits starting from group (3) down to group (0).
for (int i = 3; i >= 0; i--) {
Expand Down

0 comments on commit ca05d18

Please sign in to comment.