void ED25519_FN(curved25519_scalarmult_basepoint) (curved25519_key pk, const curved25519_key e) { curved25519_key ec; bignum256modm s; bignum25519 MM16 yplusz, zminusy; ge25519 MM16 p; size_t i; /* clamp */ for (i = 0; i < 32; i++) ec[i] = e[i]; ec[0] &= 248; ec[31] &= 127; ec[31] |= 64; expand_raw256_modm(s, ec); /* scalar * basepoint */ ge25519_scalarmult_base_niels(&p, ge25519_niels_base_multiples, s); /* u = (y + z) / (z - y) */ curve25519_add(yplusz, p.y, p.z); curve25519_sub(zminusy, p.z, p.y); curve25519_recip(zminusy, zminusy); curve25519_mul(yplusz, yplusz, zminusy); curve25519_contract(pk, yplusz); }
int ed25519_donna_pubkey_from_curve25519_pubkey(unsigned char *out, const unsigned char *inp, int signbit) { static const bignum25519 ALIGN(16) one = { 1 }; bignum25519 ALIGN(16) u, uminus1, uplus1, inv_uplus1, y; /* Prop228: y = (u-1)/(u+1) */ curve25519_expand(u, inp); curve25519_sub(uminus1, u, one); curve25519_add(uplus1, u, one); curve25519_recip(inv_uplus1, uplus1); curve25519_mul(y, uminus1, inv_uplus1); curve25519_contract(out, y); /* Propagate sign. */ out[31] |= (!!signbit) << 7; return 0; }
static int test_subs() { #if defined(HAVE_UINT128) && !defined(ED25519_SSE2) /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ static const bignum25519 max_bignum = { 0x7ffffffffffff,0x8000000001230,0x7ffffffffffff,0x7ffffffffffff,0x7ffffffffffff }; /* what max_bignum should fully reduce to */ static const unsigned char max_bignum_raw[32] = { 0x12,0x00,0x00,0x00,0x00,0x00,0x88,0x91,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; /* (max_bignum * max_bignum) */ static const unsigned char max_bignum_squared_raw[32] = { 0x44,0x01,0x00,0x00,0x00,0x00,0x20,0x77,0x14,0x00,0x00,0x00,0x40,0x58,0xbb,0x52, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; #else /* largest result for each limb from a mult or square: all elements except r1 reduced, r1 overflowed as far as possible */ static const bignum25519 ALIGN(16) max_bignum = { 0x3ffffff,0x2000300,0x3ffffff,0x1ffffff,0x3ffffff, 0x1ffffff,0x3ffffff,0x1ffffff,0x3ffffff,0x1ffffff }; /* what max_bignum should fully reduce to */ static const unsigned char max_bignum_raw[32] = { 0x12,0x00,0x00,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; /* (max_bignum * max_bignum) */ static const unsigned char max_bignum_squared_raw[32] = { 0x44,0x01,0x00,0x90,0xb0,0x01,0x10,0x60,0x90,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, }; #endif unsigned char result[32]; static const bignum25519 ALIGN(16) zero = {0}; bignum25519 ALIGN(16) a, b, c; size_t i; /* a = max_bignum - 0, which expands to 2p + max_bignum - 0 */ curve25519_sub(a, max_bignum, zero); curve25519_contract(result, a); if (memcmp(result, max_bignum_raw, 32) != 0) return -1; /* b = (max_bignum * max_bignum) */ curve25519_mul(b, a, a); curve25519_contract(result, b); if (memcmp(result, max_bignum_squared_raw, 32) != 0) return -1; curve25519_square(b, a); curve25519_contract(result, b); if (memcmp(result, max_bignum_squared_raw, 32) != 0) return -1; /* b = ((a - 0) - 0) */ curve25519_sub_after_basic(b, a, zero); curve25519_contract(result, b); if (memcmp(result, max_bignum_raw, 32) != 0) return -1; /* a = (max_bignum * max_bignum) */ curve25519_mul(a, b, b); curve25519_contract(result, a); if (memcmp(result, max_bignum_squared_raw, 32) != 0) return -1; curve25519_square(a, b); curve25519_contract(result, a); if (memcmp(result, max_bignum_squared_raw, 32) != 0) return -1; return 0; }