From 845ef24b0ca32e7c92bf06919fa881c17c8569f9 Mon Sep 17 00:00:00 2001 From: dkostic <25055813+dkostic@users.noreply.github.com> Date: Tue, 25 Jun 2024 13:45:06 -0700 Subject: [PATCH] Add point add/dbl to ec_nistp_felem_meth and rename it to ec_nistp_meth (#1654) --- crypto/fipsmodule/ec/ec_nistp.c | 118 ++++++++++++++++---------------- crypto/fipsmodule/ec/ec_nistp.h | 54 ++++++++++----- crypto/fipsmodule/ec/p256.c | 24 ++++--- crypto/fipsmodule/ec/p384.c | 48 +++++++------ crypto/fipsmodule/ec/p521.c | 48 +++++++------ 5 files changed, 161 insertions(+), 131 deletions(-) diff --git a/crypto/fipsmodule/ec/ec_nistp.c b/crypto/fipsmodule/ec/ec_nistp.c index f3eaadde07..41b7e0bfac 100644 --- a/crypto/fipsmodule/ec/ec_nistp.c +++ b/crypto/fipsmodule/ec/ec_nistp.c @@ -70,7 +70,7 @@ static void cmovznz(ec_nistp_felem_limb *out, // // Outputs can equal corresponding inputs, i.e., x_out == x_in is allowed; // while x_out == y_in is not (maybe this works, but it's not tested). -void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, +void ec_nistp_point_double(const ec_nistp_meth *ctx, ec_nistp_felem_limb *x_out, ec_nistp_felem_limb *y_out, ec_nistp_felem_limb *z_out, @@ -79,26 +79,26 @@ void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, const ec_nistp_felem_limb *z_in) { ec_nistp_felem delta, gamma, beta, ftmp, ftmp2, tmptmp, alpha, fourbeta; // delta = z^2 - ctx->sqr(delta, z_in); + ctx->felem_sqr(delta, z_in); // gamma = y^2 - ctx->sqr(gamma, y_in); + ctx->felem_sqr(gamma, y_in); // beta = x*gamma - ctx->mul(beta, x_in, gamma); + ctx->felem_mul(beta, x_in, gamma); // alpha = 3*(x-delta)*(x+delta) - ctx->sub(ftmp, x_in, delta); - ctx->add(ftmp2, x_in, delta); + ctx->felem_sub(ftmp, x_in, delta); + ctx->felem_add(ftmp2, x_in, delta); - ctx->add(tmptmp, ftmp2, ftmp2); - ctx->add(ftmp2, ftmp2, tmptmp); - ctx->mul(alpha, ftmp, ftmp2); + ctx->felem_add(tmptmp, ftmp2, ftmp2); + ctx->felem_add(ftmp2, ftmp2, tmptmp); + ctx->felem_mul(alpha, ftmp, ftmp2); // x' = alpha^2 - 8*beta - ctx->sqr(x_out, alpha); - ctx->add(fourbeta, beta, beta); - ctx->add(fourbeta, fourbeta, fourbeta); - ctx->add(tmptmp, fourbeta, fourbeta); - ctx->sub(x_out, x_out, tmptmp); + ctx->felem_sqr(x_out, alpha); + ctx->felem_add(fourbeta, beta, beta); + ctx->felem_add(fourbeta, fourbeta, fourbeta); + ctx->felem_add(tmptmp, fourbeta, fourbeta); + ctx->felem_sub(x_out, x_out, tmptmp); // z' = (y + z)^2 - gamma - delta // The following calculation differs from the Coq proof cited above. @@ -109,18 +109,18 @@ void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, // sub(z_out, z_out, delta); // Our operations sequence is a bit more efficient because it saves us // a certain number of conditional moves. - ctx->add(ftmp, y_in, z_in); - ctx->sqr(z_out, ftmp); - ctx->sub(z_out, z_out, gamma); - ctx->sub(z_out, z_out, delta); + ctx->felem_add(ftmp, y_in, z_in); + ctx->felem_sqr(z_out, ftmp); + ctx->felem_sub(z_out, z_out, gamma); + ctx->felem_sub(z_out, z_out, delta); // y' = alpha*(4*beta - x') - 8*gamma^2 - ctx->sub(y_out, fourbeta, x_out); - ctx->add(gamma, gamma, gamma); - ctx->sqr(gamma, gamma); - ctx->mul(y_out, alpha, y_out); - ctx->add(gamma, gamma, gamma); - ctx->sub(y_out, y_out, gamma); + ctx->felem_sub(y_out, fourbeta, x_out); + ctx->felem_add(gamma, gamma, gamma); + ctx->felem_sqr(gamma, gamma); + ctx->felem_mul(y_out, alpha, y_out); + ctx->felem_add(gamma, gamma, gamma); + ctx->felem_sub(y_out, y_out, gamma); } // ec_nistp_point_add calculates (x1, y1, z1) + (x2, y2, z2) @@ -137,7 +137,7 @@ void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, // are equal, (while not equal to the point at infinity). This case should // never happen during single point multiplication, so there is no timing leak // for ECDH and ECDSA. -void ec_nistp_point_add(const ec_nistp_felem_meth *ctx, +void ec_nistp_point_add(const ec_nistp_meth *ctx, ec_nistp_felem_limb *x3, ec_nistp_felem_limb *y3, ec_nistp_felem_limb *z3, @@ -150,69 +150,69 @@ void ec_nistp_point_add(const ec_nistp_felem_meth *ctx, const ec_nistp_felem_limb *z2) { ec_nistp_felem x_out, y_out, z_out; - ec_nistp_felem_limb z1nz = ctx->nz(z1); - ec_nistp_felem_limb z2nz = ctx->nz(z2); + ec_nistp_felem_limb z1nz = ctx->felem_nz(z1); + ec_nistp_felem_limb z2nz = ctx->felem_nz(z2); // z1z1 = z1**2 ec_nistp_felem z1z1; - ctx->sqr(z1z1, z1); + ctx->felem_sqr(z1z1, z1); ec_nistp_felem u1, s1, two_z1z2; if (!mixed) { // z2z2 = z2**2 ec_nistp_felem z2z2; - ctx->sqr(z2z2, z2); + ctx->felem_sqr(z2z2, z2); // u1 = x1*z2z2 - ctx->mul(u1, x1, z2z2); + ctx->felem_mul(u1, x1, z2z2); // two_z1z2 = (z1 + z2)**2 - (z1z1 + z2z2) = 2z1z2 - ctx->add(two_z1z2, z1, z2); - ctx->sqr(two_z1z2, two_z1z2); - ctx->sub(two_z1z2, two_z1z2, z1z1); - ctx->sub(two_z1z2, two_z1z2, z2z2); + ctx->felem_add(two_z1z2, z1, z2); + ctx->felem_sqr(two_z1z2, two_z1z2); + ctx->felem_sub(two_z1z2, two_z1z2, z1z1); + ctx->felem_sub(two_z1z2, two_z1z2, z2z2); // s1 = y1 * z2**3 - ctx->mul(s1, z2, z2z2); - ctx->mul(s1, s1, y1); + ctx->felem_mul(s1, z2, z2z2); + ctx->felem_mul(s1, s1, y1); } else { // We'll assume z2 = 1 (special case z2 = 0 is handled later). // u1 = x1*z2z2 OPENSSL_memcpy(u1, x1, ctx->felem_num_limbs * sizeof(ec_nistp_felem_limb)); // two_z1z2 = 2z1z2 - ctx->add(two_z1z2, z1, z1); + ctx->felem_add(two_z1z2, z1, z1); // s1 = y1 * z2**3 OPENSSL_memcpy(s1, y1, ctx->felem_num_limbs * sizeof(ec_nistp_felem_limb)); } // u2 = x2*z1z1 ec_nistp_felem u2; - ctx->mul(u2, x2, z1z1); + ctx->felem_mul(u2, x2, z1z1); // h = u2 - u1 ec_nistp_felem h; - ctx->sub(h, u2, u1); + ctx->felem_sub(h, u2, u1); - ec_nistp_felem_limb xneq = ctx->nz(h); + ec_nistp_felem_limb xneq = ctx->felem_nz(h); // z_out = two_z1z2 * h - ctx->mul(z_out, h, two_z1z2); + ctx->felem_mul(z_out, h, two_z1z2); // z1z1z1 = z1 * z1z1 ec_nistp_felem z1z1z1; - ctx->mul(z1z1z1, z1, z1z1); + ctx->felem_mul(z1z1z1, z1, z1z1); // s2 = y2 * z1**3 ec_nistp_felem s2; - ctx->mul(s2, y2, z1z1z1); + ctx->felem_mul(s2, y2, z1z1z1); // r = (s2 - s1)*2 ec_nistp_felem r; - ctx->sub(r, s2, s1); - ctx->add(r, r, r); + ctx->felem_sub(r, s2, s1); + ctx->felem_add(r, r, r); - ec_nistp_felem_limb yneq = ctx->nz(r); + ec_nistp_felem_limb yneq = ctx->felem_nz(r); // This case will never occur in the constant-time |ec_GFp_mont_mul|. ec_nistp_felem_limb is_nontrivial_double = @@ -226,30 +226,30 @@ void ec_nistp_point_add(const ec_nistp_felem_meth *ctx, // I = (2h)**2 ec_nistp_felem i; - ctx->add(i, h, h); - ctx->sqr(i, i); + ctx->felem_add(i, h, h); + ctx->felem_sqr(i, i); // J = h * I ec_nistp_felem j; - ctx->mul(j, h, i); + ctx->felem_mul(j, h, i); // V = U1 * I ec_nistp_felem v; - ctx->mul(v, u1, i); + ctx->felem_mul(v, u1, i); // x_out = r**2 - J - 2V - ctx->sqr(x_out, r); - ctx->sub(x_out, x_out, j); - ctx->sub(x_out, x_out, v); - ctx->sub(x_out, x_out, v); + ctx->felem_sqr(x_out, r); + ctx->felem_sub(x_out, x_out, j); + ctx->felem_sub(x_out, x_out, v); + ctx->felem_sub(x_out, x_out, v); // y_out = r(V-x_out) - 2 * s1 * J - ctx->sub(y_out, v, x_out); - ctx->mul(y_out, y_out, r); + ctx->felem_sub(y_out, v, x_out); + ctx->felem_mul(y_out, y_out, r); ec_nistp_felem s1j; - ctx->mul(s1j, s1, j); - ctx->sub(y_out, y_out, s1j); - ctx->sub(y_out, y_out, s1j); + ctx->felem_mul(s1j, s1, j); + ctx->felem_sub(y_out, y_out, s1j); + ctx->felem_sub(y_out, y_out, s1j); cmovznz(x_out, ctx->felem_num_limbs, z1nz, x2, x_out); cmovznz(y_out, ctx->felem_num_limbs, z1nz, y2, y_out); diff --git a/crypto/fipsmodule/ec/ec_nistp.h b/crypto/fipsmodule/ec/ec_nistp.h index 152cb57090..d17dd25912 100644 --- a/crypto/fipsmodule/ec/ec_nistp.h +++ b/crypto/fipsmodule/ec/ec_nistp.h @@ -7,7 +7,7 @@ #include -// We have two implementations of the field arithmetic for NIST curves: +// We have two implementations of field arithmetic for NIST curves: // - Fiat-crypto // - s2n-bignum // Both Fiat-crypto and s2n-bignum implementations are formally verified. @@ -34,29 +34,49 @@ typedef uint64_t ec_nistp_felem_limb; typedef uint32_t ec_nistp_felem_limb; #endif -// ec_nistp_felem_meth is a struct that holds pointers to implementations of field -// arithmetic functions for specific curves. It is meant to be used +// ec_nistp_meth is a struct that holds pointers to implementations of field +// and point arithmetic functions for specific curves. It is meant to be used // in higher level functions like this: -// void point_double(nistp_felem_methods *ctx, ...) { -// ctx->add(...); -// ctx->mul(...); +// void point_double(ec_nistp_meth *ctx, ...) { +// ctx->felem_add(...); +// ctx->felem_mul(...); +// +// ctx->point_dbl(...); // } // This makes the functions reusable between different curves by simply // providing an appropriate methods object. typedef struct { size_t felem_num_limbs; - void (*add)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); - void (*sub)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); - void (*mul)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); - void (*sqr)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a); - ec_nistp_felem_limb (*nz)(const ec_nistp_felem_limb *a); -} ec_nistp_felem_meth; + void (*felem_add)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); + void (*felem_sub)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); + void (*felem_mul)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a, const ec_nistp_felem_limb *b); + void (*felem_sqr)(ec_nistp_felem_limb *c, const ec_nistp_felem_limb *a); + ec_nistp_felem_limb (*felem_nz)(const ec_nistp_felem_limb *a); -const ec_nistp_felem_meth *p256_felem_methods(void); -const ec_nistp_felem_meth *p384_felem_methods(void); -const ec_nistp_felem_meth *p521_felem_methods(void); + void (*point_dbl)(ec_nistp_felem_limb *x_out, + ec_nistp_felem_limb *y_out, + ec_nistp_felem_limb *z_out, + const ec_nistp_felem_limb *x_in, + const ec_nistp_felem_limb *y_in, + const ec_nistp_felem_limb *z_in); + void (*point_add)(ec_nistp_felem_limb *x3, + ec_nistp_felem_limb *y3, + ec_nistp_felem_limb *z3, + const ec_nistp_felem_limb *x1, + const ec_nistp_felem_limb *y1, + const ec_nistp_felem_limb *z1, + const int mixed, + const ec_nistp_felem_limb *x2, + const ec_nistp_felem_limb *y2, + const ec_nistp_felem_limb *z2); -void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, +} ec_nistp_meth; + +const ec_nistp_meth *p256_methods(void); +const ec_nistp_meth *p384_methods(void); +const ec_nistp_meth *p521_methods(void); + +void ec_nistp_point_double(const ec_nistp_meth *ctx, ec_nistp_felem_limb *x_out, ec_nistp_felem_limb *y_out, ec_nistp_felem_limb *z_out, @@ -64,7 +84,7 @@ void ec_nistp_point_double(const ec_nistp_felem_meth *ctx, const ec_nistp_felem_limb *y_in, const ec_nistp_felem_limb *z_in); -void ec_nistp_point_add(const ec_nistp_felem_meth *ctx, +void ec_nistp_point_add(const ec_nistp_meth *ctx, ec_nistp_felem_limb *x3, ec_nistp_felem_limb *y3, ec_nistp_felem_limb *z3, diff --git a/crypto/fipsmodule/ec/p256.c b/crypto/fipsmodule/ec/p256.c index 8ca5278562..b0d94e69eb 100644 --- a/crypto/fipsmodule/ec/p256.c +++ b/crypto/fipsmodule/ec/p256.c @@ -167,22 +167,13 @@ static void fiat_p256_inv_square(fiat_p256_felem out, fiat_p256_square(out, ret); // 2^256 - 2^224 + 2^192 + 2^96 - 2^2 } -DEFINE_METHOD_FUNCTION(ec_nistp_felem_meth, p256_felem_methods) { - out->felem_num_limbs = FIAT_P256_NLIMBS; - out->add = fiat_p256_add; - out->sub = fiat_p256_sub; - out->mul = fiat_p256_mul; - out->sqr = fiat_p256_square; - out->nz = fiat_p256_nz; -} - static void fiat_p256_point_double(fiat_p256_felem x_out, fiat_p256_felem y_out, fiat_p256_felem z_out, const fiat_p256_felem x_in, const fiat_p256_felem y_in, const fiat_p256_felem z_in) { - ec_nistp_point_double(p256_felem_methods(), x_out, y_out, z_out, x_in, y_in, z_in); + ec_nistp_point_double(p256_methods(), x_out, y_out, z_out, x_in, y_in, z_in); } static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3, @@ -192,7 +183,18 @@ static void fiat_p256_point_add(fiat_p256_felem x3, fiat_p256_felem y3, const fiat_p256_felem x2, const fiat_p256_felem y2, const fiat_p256_felem z2) { - ec_nistp_point_add(p256_felem_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); + ec_nistp_point_add(p256_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); +} + +DEFINE_METHOD_FUNCTION(ec_nistp_meth, p256_methods) { + out->felem_num_limbs = FIAT_P256_NLIMBS; + out->felem_add = fiat_p256_add; + out->felem_sub = fiat_p256_sub; + out->felem_mul = fiat_p256_mul; + out->felem_sqr = fiat_p256_square; + out->felem_nz = fiat_p256_nz; + out->point_dbl = fiat_p256_point_double; + out->point_add = fiat_p256_point_add; } #include "./p256_table.h" diff --git a/crypto/fipsmodule/ec/p384.c b/crypto/fipsmodule/ec/p384.c index 930b1ac26f..8f0160954e 100644 --- a/crypto/fipsmodule/ec/p384.c +++ b/crypto/fipsmodule/ec/p384.c @@ -241,33 +241,13 @@ static void p384_inv_square(p384_felem out, p384_felem_sqr(out, ret); // 2^384 - 2^128 - 2^96 + 2^32 - 2^2 = p - 3 } -#if defined(EC_NISTP_USE_S2N_BIGNUM) -DEFINE_METHOD_FUNCTION(ec_nistp_felem_meth, p384_felem_methods) { - out->felem_num_limbs = P384_NLIMBS; - out->add = bignum_add_p384; - out->sub = bignum_sub_p384; - out->mul = bignum_montmul_p384_selector; - out->sqr = bignum_montsqr_p384_selector; - out->nz = p384_felem_nz; -} -#else -DEFINE_METHOD_FUNCTION(ec_nistp_felem_meth, p384_felem_methods) { - out->felem_num_limbs = P384_NLIMBS; - out->add = fiat_p384_add; - out->sub = fiat_p384_sub; - out->mul = fiat_p384_mul; - out->sqr = fiat_p384_square; - out->nz = p384_felem_nz; -} -#endif - static void p384_point_double(p384_felem x_out, p384_felem y_out, p384_felem z_out, const p384_felem x_in, const p384_felem y_in, const p384_felem z_in) { - ec_nistp_point_double(p384_felem_methods(), x_out, y_out, z_out, x_in, y_in, z_in); + ec_nistp_point_double(p384_methods(), x_out, y_out, z_out, x_in, y_in, z_in); } // p384_point_add calculates (x1, y1, z1) + (x2, y2, z2) @@ -287,9 +267,33 @@ static void p384_point_add(p384_felem x3, p384_felem y3, p384_felem z3, const p384_felem x2, const p384_felem y2, const p384_felem z2) { - ec_nistp_point_add(p384_felem_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); + ec_nistp_point_add(p384_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); } +#if defined(EC_NISTP_USE_S2N_BIGNUM) +DEFINE_METHOD_FUNCTION(ec_nistp_meth, p384_methods) { + out->felem_num_limbs = P384_NLIMBS; + out->felem_add = bignum_add_p384; + out->felem_sub = bignum_sub_p384; + out->felem_mul = bignum_montmul_p384_selector; + out->felem_sqr = bignum_montsqr_p384_selector; + out->felem_nz = p384_felem_nz; + out->point_dbl = p384_point_double; + out->point_add = p384_point_add; +} +#else +DEFINE_METHOD_FUNCTION(ec_nistp_meth, p384_methods) { + out->felem_num_limbs = P384_NLIMBS; + out->felem_add = fiat_p384_add; + out->felem_sub = fiat_p384_sub; + out->felem_mul = fiat_p384_mul; + out->felem_sqr = fiat_p384_square; + out->felem_nz = p384_felem_nz; + out->point_dbl = p384_point_double; + out->point_add = p384_point_add; +} +#endif + // OPENSSL EC_METHOD FUNCTIONS // Takes the Jacobian coordinates (X, Y, Z) of a point and returns: diff --git a/crypto/fipsmodule/ec/p521.c b/crypto/fipsmodule/ec/p521.c index d3a015cd13..2489213143 100644 --- a/crypto/fipsmodule/ec/p521.c +++ b/crypto/fipsmodule/ec/p521.c @@ -259,33 +259,13 @@ static void p521_felem_inv(p521_felem output, const p521_felem t1) { p521_felem_mul(output, acc, t1); } -#if defined(EC_NISTP_USE_S2N_BIGNUM) -DEFINE_METHOD_FUNCTION(ec_nistp_felem_meth, p521_felem_methods) { - out->felem_num_limbs = P521_NLIMBS; - out->add = bignum_add_p521; - out->sub = bignum_sub_p521; - out->mul = bignum_mul_p521_selector; - out->sqr = bignum_sqr_p521_selector; - out->nz = p521_felem_nz; -} -#else -DEFINE_METHOD_FUNCTION(ec_nistp_felem_meth, p521_felem_methods) { - out->felem_num_limbs = P521_NLIMBS; - out->add = fiat_secp521r1_carry_add; - out->sub = fiat_secp521r1_carry_sub; - out->mul = fiat_secp521r1_carry_mul; - out->sqr = fiat_secp521r1_carry_square; - out->nz = p521_felem_nz; -} -#endif - static void p521_point_double(p521_felem x_out, p521_felem y_out, p521_felem z_out, const p521_felem x_in, const p521_felem y_in, const p521_felem z_in) { - ec_nistp_point_double(p521_felem_methods(), x_out, y_out, z_out, x_in, y_in, z_in); + ec_nistp_point_double(p521_methods(), x_out, y_out, z_out, x_in, y_in, z_in); } // p521_point_add calculates (x1, y1, z1) + (x2, y2, z2) @@ -305,9 +285,33 @@ static void p521_point_add(p521_felem x3, p521_felem y3, p521_felem z3, const p521_felem x2, const p521_felem y2, const p521_felem z2) { - ec_nistp_point_add(p521_felem_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); + ec_nistp_point_add(p521_methods(), x3, y3, z3, x1, y1, z1, mixed, x2, y2, z2); } +#if defined(EC_NISTP_USE_S2N_BIGNUM) +DEFINE_METHOD_FUNCTION(ec_nistp_meth, p521_methods) { + out->felem_num_limbs = P521_NLIMBS; + out->felem_add = bignum_add_p521; + out->felem_sub = bignum_sub_p521; + out->felem_mul = bignum_mul_p521_selector; + out->felem_sqr = bignum_sqr_p521_selector; + out->felem_nz = p521_felem_nz; + out->point_dbl = p521_point_double; + out->point_add = p521_point_add; +} +#else +DEFINE_METHOD_FUNCTION(ec_nistp_meth, p521_methods) { + out->felem_num_limbs = P521_NLIMBS; + out->felem_add = fiat_secp521r1_carry_add; + out->felem_sub = fiat_secp521r1_carry_sub; + out->felem_mul = fiat_secp521r1_carry_mul; + out->felem_sqr = fiat_secp521r1_carry_square; + out->felem_nz = p521_felem_nz; + out->point_dbl = p521_point_double; + out->point_add = p521_point_add; +} +#endif + // OPENSSL EC_METHOD FUNCTIONS // Takes the Jacobian coordinates (X, Y, Z) of a point and returns: