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] Implement generic scalar multiplication #1982

Closed
wants to merge 2 commits into from

Conversation

dkostic
Copy link
Contributor

@dkostic dkostic commented Nov 11, 2024

Issues:

Resolves #ISSUE-NUMBER1
Addresses #ISSUE-NUMBER2

Description of changes:

This change implements a generic scalar multiplication function
that can work in four modes of operation which covers the three
functions we need to implement: multiplication of an arbitrary
point, of a base point, and the so-called public multiplication.

Call-outs:

Point out areas that need special attention or support during the review process. Discuss architecture or design changes.

Testing:

How is this change tested (unit tests, fuzz tests, etc.)? Are there any testing steps to be verified by the reviewer?

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license and the ISC license.

This change implements a generic scalar multiplication function
that can work in four modes of operation which covers the three
functions we need to implement: multiplication of an arbitrary
point, of a base point, and the so-called public multiplication.
@dkostic dkostic requested a review from a team as a code owner November 11, 2024 19:21
@codecov-commenter
Copy link

codecov-commenter commented Nov 11, 2024

Codecov Report

Attention: Patch coverage is 59.32203% with 24 lines in your changes missing coverage. Please review.

Project coverage is 78.85%. Comparing base (c9d48a6) to head (1bf868b).
Report is 18 commits behind head on main.

Files with missing lines Patch % Lines
crypto/fipsmodule/ec/ec_nistp.c 52.94% 24 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1982      +/-   ##
==========================================
+ Coverage   78.79%   78.85%   +0.06%     
==========================================
  Files         590      593       +3     
  Lines      101506   101977     +471     
  Branches    14401    14454      +53     
==========================================
+ Hits        79979    80414     +435     
- Misses      20891    20918      +27     
- Partials      636      645       +9     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

crypto/fipsmodule/ec/ec_nistp.c Show resolved Hide resolved
crypto/fipsmodule/ec/ec_nistp.c Outdated Show resolved Hide resolved
@@ -444,6 +453,15 @@ void ec_nistp_scalar_mul(const ec_nistp_meth *ctx,
ec_nistp_felem_limb *x_tmp = &tmp[0];
ec_nistp_felem_limb *y_tmp = &tmp[ctx->felem_num_limbs];
ec_nistp_felem_limb *z_tmp = &tmp[ctx->felem_num_limbs * 2];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

something ensures no overflow?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

few lines above:
ec_nistp_felem_limb tmp[3 * FELEM_MAX_NUM_OF_LIMBS];
where FELEM_MAX_NUM_OF_LIMBS is defined to ensure no overflow. But I can add an assert if you think it's worth it?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, a runtime debug assert on ctx->felem_num_limbs seems reasonable to exercise that during testing.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you already have these below

  assert(SCALAR_MUL_TABLE_MAX_NUM_FELEM_LIMBS >=
         SCALAR_MUL_TABLE_NUM_POINTS * ctx->felem_num_limbs * 3);

So, that should be sufficient, right?

// Table of multiples of the base point G.
const ec_nistp_felem_limb *table_g = ctx->scalar_mul_base_table;

scalar_mul_core(ctx, x_res_g, y_res_g, z_res_g, scalar_g, table_g, base);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

non constant modes?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right :)

@@ -444,6 +453,15 @@ void ec_nistp_scalar_mul(const ec_nistp_meth *ctx,
ec_nistp_felem_limb *x_tmp = &tmp[0];
ec_nistp_felem_limb *y_tmp = &tmp[ctx->felem_num_limbs];
ec_nistp_felem_limb *z_tmp = &tmp[ctx->felem_num_limbs * 2];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, a runtime debug assert on ctx->felem_num_limbs seems reasonable to exercise that during testing.

// Table of multiples of P = (x_in, y_in, z_in).
ec_nistp_felem_limb table[SCALAR_MUL_TABLE_MAX_NUM_FELEM_LIMBS];
generate_table(ctx, table, x_in, y_in, z_in);
static inline void scalar_mul_core(const ec_nistp_meth *ctx,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quite a big function to inline.

const EC_SCALAR *scalar,
const ec_nistp_felem_limb *table,
enum scalar_mul_core_mode mode) {
// Mode based invariants.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just something to ponder later. Is something else using scalar_mul_core apart from the three function further below? If not, while these modes attempts to abstract some semantics, it's almost too much abstraction. If the set of functions that invoke, and will ever invoke scalar_mul_core, one could have this as three arguments.

It also appears there is some implicit relationship between the table argument and the mode argument. Although, any mistakes mis-configuring that e.g. use mode != base for a full table, will likely cause the unit tests to have severe hiccups.

@@ -444,6 +453,15 @@ void ec_nistp_scalar_mul(const ec_nistp_meth *ctx,
ec_nistp_felem_limb *x_tmp = &tmp[0];
ec_nistp_felem_limb *y_tmp = &tmp[ctx->felem_num_limbs];
ec_nistp_felem_limb *z_tmp = &tmp[ctx->felem_num_limbs * 2];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, you already have these below

  assert(SCALAR_MUL_TABLE_MAX_NUM_FELEM_LIMBS >=
         SCALAR_MUL_TABLE_NUM_POINTS * ctx->felem_num_limbs * 3);

So, that should be sufficient, right?

@nebeid nebeid self-requested a review November 15, 2024 17:13
@dkostic dkostic closed this Nov 19, 2024
Copy link
Contributor

@nebeid nebeid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed, but just submitting my pending changes.

// operation doesn't have to be implemented in constant-time.
enum scalar_mul_core_mode { base, base_nonct, arbitrary, arbitrary_nonct };
//
// In arbitrary modes the input table is a single table with odd multiples of P:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// In arbitrary modes the input table is a single table with odd multiples of P:
// When used to multiply an arbitrary point, the input table is a single table with odd multiples of P:

//
// In arbitrary modes the input table is a single table with odd multiples of P:
// [2i + 1]P for i in [0, SCALAR_MUL_TABLE_NUM_POINTS - 1],
// In base modes the input table is a full table of m single subtables:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// In base modes the input table is a full table of m single subtables:
// When used to multiply a base point, the input table is a full table of m single subtables:

//
// The required product, [scalar]P, is computed by the following algorithm.
// 1. Initialize the accumulator with the point from |table|
// corresponding to the most significant digit s_{m-1} of the scalar.
// 2. For digits s_i starting from s_{m-2} down to s_0:
// 3. Double the accumulator w times. (note that doubling a point [a]P
// w times results in [2^w*a]P).
// 3. Double the accumulator w times if in an arbitrary mode.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// 3. Double the accumulator w times if in an arbitrary mode.
// 3. Double the accumulator w times if in an arbitrary-point multiplication mode.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants