Skip to content

Commit

Permalink
Fix-up curve25519 code to prepare for s2n-bignum (#1306)
Browse files Browse the repository at this point in the history
  • Loading branch information
torben-hansen authored Nov 15, 2023
1 parent 1345b5d commit 616c407
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 53 deletions.
66 changes: 33 additions & 33 deletions crypto/curve25519/curve25519.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
#endif


OPENSSL_INLINE int x25519_s2n_bignum_capable(void) {
OPENSSL_INLINE int curve25519_s2n_bignum_capable(void) {
#if defined(CURVE25519_S2N_BIGNUM_CAPABLE)
return 1;
#else
Expand Down Expand Up @@ -111,20 +111,20 @@ void curve25519_x25519base_byte_alt(uint8_t res[32], const uint8_t scalar[32]) {

// Run-time detection for each implementation

OPENSSL_INLINE int x25519_s2n_bignum_alt_capable(void);
OPENSSL_INLINE int x25519_s2n_bignum_no_alt_capable(void);
OPENSSL_INLINE int curve25519_s2n_bignum_alt_capable(void);
OPENSSL_INLINE int curve25519_s2n_bignum_no_alt_capable(void);

// For aarch64, |x25519_s2n_bignum_alt_capable| returns 1 if we categorize the
// CPU as a CPU having a wide multiplier (i.e. "higher" throughput). CPUs with
// this feature are e.g.: AWS Graviton 3 and Apple M1. Return 0 otherwise, so we
// don't match CPUs without wide multipliers.
// For aarch64, |curve25519_s2n_bignum_alt_capable| returns 1 if we categorize
// the CPU as a CPU having a wide multiplier (i.e. "higher" throughput). CPUs
// with this feature are e.g.: AWS Graviton 3 and Apple M1. Return 0 otherwise,
// so we don't match CPUs without wide multipliers.
//
// For x86_64, |x25519_s2n_bignum_alt_capable| always returns 1. If x25519
// For x86_64, |curve25519_s2n_bignum_alt_capable| always returns 1. If x25519
// s2n-bignum capable, the x86_64 s2n-bignum-alt version should be supported on
// pretty much any x86_64 CPU.
//
// For all other architectures, return 0.
OPENSSL_INLINE int x25519_s2n_bignum_alt_capable(void) {
OPENSSL_INLINE int curve25519_s2n_bignum_alt_capable(void) {
#if defined(OPENSSL_X86_64)
return 1;
#elif defined(OPENSSL_AARCH64)
Expand All @@ -138,15 +138,15 @@ OPENSSL_INLINE int x25519_s2n_bignum_alt_capable(void) {
#endif
}

// For aarch64, |x25519_s2n_bignum_no_alt_capable| always returns 1. If x25519
// s2n-bignum capable, the Armv8 s2n-bignum-alt version should be supported on
// pretty much any Armv8 CPU.
// For aarch64, |curve25519_s2n_bignum_no_alt_capable| always returns 1. If
// x25519 s2n-bignum capable, the Armv8 s2n-bignum-alt version should be
// supported on pretty much any Armv8 CPU.
//
// For x86_64, |x25519_s2n_bignum_alt_capable| returns 1 if we detect support
// for bmi+adx instruction sets. Return 0 otherwise.
// For x86_64, |curve25519_s2n_bignum_alt_capable| returns 1 if we detect
// support for bmi+adx instruction sets. Return 0 otherwise.
//
// For all other architectures, return 0.
OPENSSL_INLINE int x25519_s2n_bignum_no_alt_capable(void) {
OPENSSL_INLINE int curve25519_s2n_bignum_no_alt_capable(void) {
#if defined(OPENSSL_X86_64)
if (CRYPTO_is_BMI2_capable() == 1 && CRYPTO_is_ADX_capable() == 1) {
return 1;
Expand Down Expand Up @@ -179,9 +179,9 @@ OPENSSL_INLINE int x25519_s2n_bignum_no_alt_capable(void) {
// prefer s2n-bignum-no-alt over s2n-bignum-alt if the former is supported.
// For aarch64: if a wide multiplier is supported, we prefer s2n-bignum-alt over
// s2n-bignum-no-alt if the former is supported.
// x25519_s2n_bignum_alt_capable() specifically looks to match CPUs that have
// wide multipliers. this ensures that s2n-bignum-alt will only be used on
// such CPUs.
// |curve25519_s2n_bignum_alt_capable| specifically looks to match CPUs that
// have wide multipliers. this ensures that s2n-bignum-alt will only be used
// on such CPUs.

static void x25519_s2n_bignum(uint8_t out_shared_key[32],
const uint8_t private_key[32], const uint8_t peer_public_value[32]) {
Expand All @@ -194,10 +194,10 @@ static void x25519_s2n_bignum(uint8_t out_shared_key[32],

#if defined(OPENSSL_X86_64)

if (x25519_s2n_bignum_no_alt_capable() == 1) {
if (curve25519_s2n_bignum_no_alt_capable() == 1) {
curve25519_x25519_byte(out_shared_key, private_key_internal_demask,
peer_public_value);
} else if (x25519_s2n_bignum_alt_capable() == 1) {
} else if (curve25519_s2n_bignum_alt_capable() == 1) {
curve25519_x25519_byte_alt(out_shared_key, private_key_internal_demask,
peer_public_value);
} else {
Expand All @@ -206,10 +206,10 @@ static void x25519_s2n_bignum(uint8_t out_shared_key[32],

#elif defined(OPENSSL_AARCH64)

if (x25519_s2n_bignum_alt_capable() == 1) {
if (curve25519_s2n_bignum_alt_capable() == 1) {
curve25519_x25519_byte_alt(out_shared_key, private_key_internal_demask,
peer_public_value);
} else if (x25519_s2n_bignum_no_alt_capable() == 1) {
} else if (curve25519_s2n_bignum_no_alt_capable() == 1) {
curve25519_x25519_byte(out_shared_key, private_key_internal_demask,
peer_public_value);
} else {
Expand All @@ -235,19 +235,19 @@ static void x25519_s2n_bignum_public_from_private(

#if defined(OPENSSL_X86_64)

if (x25519_s2n_bignum_no_alt_capable() == 1) {
if (curve25519_s2n_bignum_no_alt_capable() == 1) {
curve25519_x25519base_byte(out_public_value, private_key_internal_demask);
} else if (x25519_s2n_bignum_alt_capable() == 1) {
} else if (curve25519_s2n_bignum_alt_capable() == 1) {
curve25519_x25519base_byte_alt(out_public_value, private_key_internal_demask);
} else {
abort();
}

#elif defined(OPENSSL_AARCH64)

if (x25519_s2n_bignum_alt_capable() == 1) {
if (curve25519_s2n_bignum_alt_capable() == 1) {
curve25519_x25519base_byte_alt(out_public_value, private_key_internal_demask);
} else if (x25519_s2n_bignum_no_alt_capable() == 1) {
} else if (curve25519_s2n_bignum_no_alt_capable() == 1) {
curve25519_x25519base_byte(out_public_value, private_key_internal_demask);
} else {
abort();
Expand Down Expand Up @@ -278,7 +278,7 @@ static void ed25519_sign_s2n_bignum(
abort();
}

static int ed25519_verify_s2n_bignum(uint8_t R_have_encoded[32],
static int ed25519_verify_s2n_bignum(uint8_t R_computed_encoded[32],
const uint8_t public_key[32], uint8_t R_expected[32],
uint8_t S[32], const uint8_t *message, size_t message_len) {
abort();
Expand Down Expand Up @@ -427,25 +427,25 @@ int ED25519_verify(const uint8_t *message, size_t message_len,
// Step: rfc8032 5.1.7.[1,2,3]
// Verification works by computing [S]B - [k]A' and comparing against R_expected.
int res = 0;
uint8_t R_have_encoded[32];
uint8_t R_computed_encoded[32];
if (ed25519_s2n_bignum_capable() == 1) {
res = ed25519_verify_s2n_bignum(R_have_encoded, public_key, R_expected, S,
res = ed25519_verify_s2n_bignum(R_computed_encoded, public_key, R_expected, S,
message, message_len);
} else {
res = ed25519_verify_nohw(R_have_encoded, public_key, R_expected, S,
res = ed25519_verify_nohw(R_computed_encoded, public_key, R_expected, S,
message, message_len);
}

// Comparison [S]B - [k]A' =? R_expected. Short-circuits if decoding failed.
return (res == 1) &&
CRYPTO_memcmp(R_have_encoded, R_expected, sizeof(R_have_encoded)) == 0;
CRYPTO_memcmp(R_computed_encoded, R_expected, sizeof(R_computed_encoded)) == 0;
}


void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]) {

if (x25519_s2n_bignum_capable() == 1) {
if (curve25519_s2n_bignum_capable() == 1) {
x25519_s2n_bignum_public_from_private(out_public_value, private_key);
} else {
x25519_public_from_private_nohw(out_public_value, private_key);
Expand Down Expand Up @@ -480,7 +480,7 @@ int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],

static const uint8_t kZeros[32] = {0};

if (x25519_s2n_bignum_capable() == 1) {
if (curve25519_s2n_bignum_capable() == 1) {
x25519_s2n_bignum(out_shared_key, private_key, peer_public_value);
} else {
x25519_scalar_mult_generic_nohw(out_shared_key, private_key, peer_public_value);
Expand Down
18 changes: 9 additions & 9 deletions crypto/curve25519/curve25519_nohw.c
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,7 @@ static void fe_sub(fe_loose *h, const fe *f, const fe *g) {
assert_fe_loose(h->v);
}

void fe_carry(fe *h, const fe_loose* f) {
static void fe_carry(fe *h, const fe_loose* f) {
assert_fe_loose(f->v);
fiat_25519_carry(h->v, f->v);
assert_fe(h->v);
Expand Down Expand Up @@ -273,7 +273,7 @@ static void fe_mul121666(fe *h, const fe_loose *f) {
}

// h = -f
void fe_neg(fe_loose *h, const fe *f) {
static void fe_neg(fe_loose *h, const fe *f) {
assert_fe(f->v);
fiat_25519_opp(h->v, f->v);
assert_fe_loose(h->v);
Expand Down Expand Up @@ -481,7 +481,7 @@ void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) {
s[31] ^= fe_isnegative(&x) << 7;
}

void ge_p3_tobytes(uint8_t s[32], const ge_p3 *h) {
static void ge_p3_tobytes(uint8_t s[32], const ge_p3 *h) {
fe recip;
fe x;
fe y;
Expand Down Expand Up @@ -956,7 +956,7 @@ static void slide(signed char *r, const uint8_t *a) {
// where a = a[0]+256*a[1]+...+256^31 a[31].
// and b = b[0]+256*b[1]+...+256^31 b[31].
// B is the Ed25519 base point (x,4/5) with x positive.
void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
static void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
const ge_p3 *A, const uint8_t *b) {
signed char aslide[256];
signed char bslide[256];
Expand Down Expand Up @@ -1382,7 +1382,7 @@ void x25519_sc_reduce(uint8_t s[64]) {
// Output:
// s[0]+256*s[1]+...+256^31*s[31] = (ab+c) mod l
// where l = 2^252 + 27742317777372353535851937790883648493.
void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
const uint8_t *c) {
int64_t a0 = 2097151 & load_3(a);
int64_t a1 = 2097151 & (load_4(a + 2) >> 5);
Expand Down Expand Up @@ -2000,7 +2000,7 @@ void ed25519_sign_nohw(
sc_muladd(out_sig + 32, k, s, r);
}

int ed25519_verify_nohw(uint8_t R_have_encoded[32],
int ed25519_verify_nohw(uint8_t R_computed_encoded[32],
const uint8_t public_key[ED25519_PUBLIC_KEY_LEN], uint8_t R_expected[32],
uint8_t S[32], const uint8_t *message, size_t message_len) {

Expand Down Expand Up @@ -2033,9 +2033,9 @@ int ed25519_verify_nohw(uint8_t R_have_encoded[32],
fe_carry(&A.T, &t);

// Compute R_have <- [S]B - [k]A'.
ge_p2 R_have;
ge_double_scalarmult_vartime(&R_have, k, &A, S);
x25519_ge_tobytes(R_have_encoded, &R_have);
ge_p2 R_computed;
ge_double_scalarmult_vartime(&R_computed, k, &A, S);
x25519_ge_tobytes(R_computed_encoded, &R_computed);

return 1;
}
12 changes: 1 addition & 11 deletions crypto/curve25519/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,20 +135,10 @@ void ed25519_sign_nohw(
uint8_t r[SHA512_DIGEST_LENGTH], const uint8_t *s, const uint8_t *A,
const void *message, size_t message_len);

int ed25519_verify_nohw(uint8_t R_have_encoded[32],
int ed25519_verify_nohw(uint8_t R_computed_encoded[32],
const uint8_t public_key[ED25519_PUBLIC_KEY_LEN], uint8_t R_expected[32],
uint8_t S[32], const uint8_t *message, size_t message_len);

// Port to internal linkage in curve25519_nohw.c when adding implementation
// from s2n-bignum ed25519
void ge_p3_tobytes(uint8_t s[32], const ge_p3 *h);
void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
const uint8_t *c);
void fe_neg(fe_loose *h, const fe *f);
void fe_carry(fe *h, const fe_loose* f);
void ge_double_scalarmult_vartime(ge_p2 *r, const uint8_t *a,
const ge_p3 *A, const uint8_t *b);

enum spake2_state_t {
spake2_state_init = 0,
spake2_state_msg_generated,
Expand Down

0 comments on commit 616c407

Please sign in to comment.