#include <assert.h>
#include <string.h>
#include <openssl/mem.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "internal.h"
#include "../internal.h"
#include "./curve25519_tables.h"
#if defined(BORINGSSL_HAS_UINT128)
#include "../../third_party/fiat/curve25519_64.h"
#elif defined(OPENSSL_64_BIT)
#include "../../third_party/fiat/curve25519_64_msvc.h"
#else
#include "../../third_party/fiat/curve25519_32.h"
#endif
static uint64_t load_3(const uint8_t *in) { … }
static uint64_t load_4(const uint8_t *in) { … }
#if defined(OPENSSL_64_BIT)
fe_limb_t;
#define FE_NUM_LIMBS …
#define assert_fe(f) …
#define assert_fe_loose(f) …
#else
typedef uint32_t fe_limb_t;
#define FE_NUM_LIMBS …
#define assert_fe …
#define assert_fe_loose …
#endif
static_assert;
static void fe_frombytes_strict(fe *h, const uint8_t s[32]) { … }
static void fe_frombytes(fe *h, const uint8_t s[32]) { … }
static void fe_tobytes(uint8_t s[32], const fe *f) { … }
static void fe_0(fe *h) { … }
static void fe_loose_0(fe_loose *h) { … }
static void fe_1(fe *h) { … }
static void fe_loose_1(fe_loose *h) { … }
static void fe_add(fe_loose *h, const fe *f, const fe *g) { … }
static void fe_sub(fe_loose *h, const fe *f, const fe *g) { … }
static void fe_carry(fe *h, const fe_loose* f) { … }
static void fe_mul_impl(fe_limb_t out[FE_NUM_LIMBS],
const fe_limb_t in1[FE_NUM_LIMBS],
const fe_limb_t in2[FE_NUM_LIMBS]) { … }
static void fe_mul_ltt(fe_loose *h, const fe *f, const fe *g) { … }
static void fe_mul_llt(fe_loose *h, const fe_loose *f, const fe *g) { … }
static void fe_mul_ttt(fe *h, const fe *f, const fe *g) { … }
static void fe_mul_tlt(fe *h, const fe_loose *f, const fe *g) { … }
static void fe_mul_ttl(fe *h, const fe *f, const fe_loose *g) { … }
static void fe_mul_tll(fe *h, const fe_loose *f, const fe_loose *g) { … }
static void fe_sq_tl(fe *h, const fe_loose *f) { … }
static void fe_sq_tt(fe *h, const fe *f) { … }
static void fe_cswap(fe *f, fe *g, fe_limb_t b) { … }
static void fe_mul121666(fe *h, const fe_loose *f) { … }
static void fe_neg(fe_loose *h, const fe *f) { … }
static void fe_cmov(fe_loose *f, const fe_loose *g, fe_limb_t b) { … }
static void fe_copy(fe *h, const fe *f) { … }
static void fe_copy_lt(fe_loose *h, const fe *f) { … }
static void fe_loose_invert(fe *out, const fe_loose *z) { … }
static void fe_invert(fe *out, const fe *z) { … }
static int fe_isnonzero(const fe_loose *f) { … }
static int fe_isnegative(const fe *f) { … }
static void fe_sq2_tt(fe *h, const fe *f) { … }
static void fe_pow22523(fe *out, const fe *z) { … }
void x25519_ge_tobytes(uint8_t s[32], const ge_p2 *h) { … }
static void ge_p3_tobytes(uint8_t s[32], const ge_p3 *h) { … }
int x25519_ge_frombytes_vartime(ge_p3 *h, const uint8_t s[32]) { … }
static void ge_p2_0(ge_p2 *h) { … }
static void ge_p3_0(ge_p3 *h) { … }
static void ge_cached_0(ge_cached *h) { … }
static void ge_precomp_0(ge_precomp *h) { … }
static void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) { … }
void x25519_ge_p3_to_cached(ge_cached *r, const ge_p3 *p) { … }
void x25519_ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) { … }
void x25519_ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) { … }
static void ge_p1p1_to_cached(ge_cached *r, const ge_p1p1 *p) { … }
static void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) { … }
static void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) { … }
static void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { … }
static void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) { … }
void x25519_ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { … }
void x25519_ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) { … }
static void cmov(ge_precomp *t, const ge_precomp *u, uint8_t b) { … }
void x25519_ge_scalarmult_small_precomp(
ge_p3 *h, const uint8_t a[32], const uint8_t precomp_table[15 * 2 * 32]) { … }
#if defined(OPENSSL_SMALL)
void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) { … }
#else
static void table_select(ge_precomp *t, const int pos, const signed char b) {
uint8_t bnegative = constant_time_msb_w(b);
uint8_t babs = b - ((bnegative & b) << 1);
uint8_t t_bytes[3][32] = {
{constant_time_is_zero_w(b) & 1}, {constant_time_is_zero_w(b) & 1}, {0}};
#if defined(__clang__)
__asm__("" : "+m" (t_bytes) : );
#endif
static_assert(sizeof(t_bytes) == sizeof(k25519Precomp[pos][0]), "");
for (int i = 0; i < 8; i++) {
constant_time_conditional_memxor(t_bytes, k25519Precomp[pos][i],
sizeof(t_bytes),
constant_time_eq_w(babs, 1 + i));
}
fe yplusx, yminusx, xy2d;
fe_frombytes_strict(&yplusx, t_bytes[0]);
fe_frombytes_strict(&yminusx, t_bytes[1]);
fe_frombytes_strict(&xy2d, t_bytes[2]);
fe_copy_lt(&t->yplusx, &yplusx);
fe_copy_lt(&t->yminusx, &yminusx);
fe_copy_lt(&t->xy2d, &xy2d);
ge_precomp minust;
fe_copy_lt(&minust.yplusx, &yminusx);
fe_copy_lt(&minust.yminusx, &yplusx);
fe_neg(&minust.xy2d, &xy2d);
cmov(t, &minust, bnegative>>7);
}
void x25519_ge_scalarmult_base(ge_p3 *h, const uint8_t a[32]) {
#if defined(BORINGSSL_FE25519_ADX)
if (CRYPTO_is_BMI1_capable() && CRYPTO_is_BMI2_capable() &&
CRYPTO_is_ADX_capable()) {
uint8_t t[4][32];
x25519_ge_scalarmult_base_adx(t, a);
fiat_25519_from_bytes(h->X.v, t[0]);
fiat_25519_from_bytes(h->Y.v, t[1]);
fiat_25519_from_bytes(h->Z.v, t[2]);
fiat_25519_from_bytes(h->T.v, t[3]);
return;
}
#endif
signed char e[64];
signed char carry;
ge_p1p1 r;
ge_p2 s;
ge_precomp t;
int i;
for (i = 0; i < 32; ++i) {
e[2 * i + 0] = (a[i] >> 0) & 15;
e[2 * i + 1] = (a[i] >> 4) & 15;
}
carry = 0;
for (i = 0; i < 63; ++i) {
e[i] += carry;
carry = e[i] + 8;
carry >>= 4;
e[i] -= carry << 4;
}
e[63] += carry;
ge_p3_0(h);
for (i = 1; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
x25519_ge_p1p1_to_p3(h, &r);
}
ge_p3_dbl(&r, h);
x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
x25519_ge_p1p1_to_p2(&s, &r);
ge_p2_dbl(&r, &s);
x25519_ge_p1p1_to_p3(h, &r);
for (i = 0; i < 64; i += 2) {
table_select(&t, i / 2, e[i]);
ge_madd(&r, h, &t);
x25519_ge_p1p1_to_p3(h, &r);
}
}
#endif
static void cmov_cached(ge_cached *t, ge_cached *u, uint8_t b) { … }
void x25519_ge_scalarmult(ge_p2 *r, const uint8_t *scalar, const ge_p3 *A) { … }
static void slide(signed char *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) { … }
static inline int64_t int64_lshift21(int64_t a) { … }
void x25519_sc_reduce(uint8_t s[64]) { … }
static void sc_muladd(uint8_t *s, const uint8_t *a, const uint8_t *b,
const uint8_t *c) { … }
void ED25519_keypair(uint8_t out_public_key[32], uint8_t out_private_key[64]) { … }
int ED25519_sign(uint8_t out_sig[64], const uint8_t *message,
size_t message_len, const uint8_t private_key[64]) { … }
int ED25519_verify(const uint8_t *message, size_t message_len,
const uint8_t signature[64], const uint8_t public_key[32]) { … }
void ED25519_keypair_from_seed(uint8_t out_public_key[32],
uint8_t out_private_key[64],
const uint8_t seed[32]) { … }
static void x25519_scalar_mult_generic(uint8_t out[32],
const uint8_t scalar[32],
const uint8_t point[32]) { … }
static void x25519_scalar_mult(uint8_t out[32], const uint8_t scalar[32],
const uint8_t point[32]) { … }
void X25519_keypair(uint8_t out_public_value[32], uint8_t out_private_key[32]) { … }
int X25519(uint8_t out_shared_key[32], const uint8_t private_key[32],
const uint8_t peer_public_value[32]) { … }
void X25519_public_from_private(uint8_t out_public_value[32],
const uint8_t private_key[32]) { … }