Compare commits

..

No commits in common. "master" and "v6" have entirely different histories.
master ... v6

4 changed files with 146 additions and 230 deletions

View file

@ -1,22 +1,3 @@
libuecc v7 (2016/03/27)
* Change conversion between Ed25519 and legacy representation. This should
not affect any operations unless Ed25519 and legacy load/store
functions are mixed when accessing a work structure. Doing so is now
officially supported, for example to convert a legacy public key to
Ed25519 format.
* The changed representation allows to use the same
ecc_25519_work_default_base for both Ed25519 and legacy.
ecc_25519_work_default_base and ecc_25519_scalarmult_base have been
undeprecated, ecc_25519_work_base_ed25519 and
ecc_25519_work_base_legacy are deprecated now.
* All points are now internally represented with Ed25519 coordinates, which
allows about 6% faster scalar multplication than the legacy
representation.
* ecc_25519_scalarmult_base has been further optimized, making it another
6% faster than normal ecc_25519_scalarmult.
libuecc v6 (2015/10/25) libuecc v6 (2015/10/25)
* Fixes a bug which might have caused a point's y coordinate to be negated * Fixes a bug which might have caused a point's y coordinate to be negated

View file

@ -1,6 +1,6 @@
cmake_minimum_required(VERSION 2.6) cmake_minimum_required(VERSION 2.6)
project(LIBUECC C) project(LIBUECC C)
set(PROJECT_VERSION 7) set(PROJECT_VERSION 6)
set(CMAKE_MODULE_PATH ${LIBUECC_SOURCE_DIR}) set(CMAKE_MODULE_PATH ${LIBUECC_SOURCE_DIR})

View file

@ -68,27 +68,33 @@ extern const ecc_25519_work_t ecc_25519_work_identity;
/** /**
* The Ed25519 default generator point * The generator point used by Ed25519
* *
* \deprecated Use the equivalent \ref ecc_25519_work_default_base instead. * \ref ecc_25519_work_base_ed25519 is the inverse of \ref ecc_25519_work_base_legacy
* *
* The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$.
**/ **/
DEPRECATED extern const ecc_25519_work_t ecc_25519_work_base_ed25519; extern const ecc_25519_work_t ecc_25519_work_base_ed25519;
/** /**
* The Ed25519 default generator point * The ec25519 legacy generator point ("default base" till libuecc v5)
* *
* \deprecated Use the equivalent \ref ecc_25519_work_default_base instead. * In new software that doesn't need compablity with older libuecc releases, you should consider
*/ * using \ref ecc_25519_work_base_ed25519 instead.
DEPRECATED extern const ecc_25519_work_t ecc_25519_work_base_legacy; *
* \ref ecc_25519_work_base_legacy is the inverse of \ref ecc_25519_work_base_ed25519
/**
* The Ed25519 default generator point
* *
* The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$. * The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$.
*/ */
extern const ecc_25519_work_t ecc_25519_work_default_base; extern const ecc_25519_work_t ecc_25519_work_base_legacy;
/**
* The ec25519 legacy generator point (provided for API/ABI compatiblity with older releases of libuecc)
*
* \deprecated Use \ref ecc_25519_work_base_legacy instead.
*/
DEPRECATED extern const ecc_25519_work_t ecc_25519_work_default_base;
/** Loads a point of the Ed25519 curve with given coordinates into its unpacked representation */ /** Loads a point of the Ed25519 curve with given coordinates into its unpacked representation */
@ -249,20 +255,20 @@ void ecc_25519_scalarmult(ecc_25519_work_t *out, const ecc_int256_t *n, const ec
* *
* The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$. * The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$.
* *
* ecc_25519_scalarmult_base_bits(out, n, bits) is faster than ecc_25519_scalarmult_bits(out, n, &ecc_25519_work_default_base, bits).
*
* See the notes about \ref ecc_25519_scalarmult_bits before using this function. * See the notes about \ref ecc_25519_scalarmult_bits before using this function.
*
* \deprecated Use \ref ecc_25519_scalarmult_bits and explicitly specify the base point.
*/ */
void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n, unsigned bits); DEPRECATED void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n, unsigned bits);
/** /**
* Does a scalar multiplication of the default base point (generator element) of the Elliptic Curve with an integer * Does a scalar multiplication of the default base point (generator element) of the Elliptic Curve with an integer
* *
* The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$. * The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$.
* *
* ecc_25519_scalarmult_base(out, n) is faster than ecc_25519_scalarmult(out, n, &ecc_25519_work_default_base). * \deprecated Use \ref ecc_25519_scalarmult and explicitly specify the base point.
*/ */
void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n); DEPRECATED void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n);
/**@}*/ /**@}*/

View file

@ -41,7 +41,7 @@
* which is the curve used by the Ed25519 algorithm. The functions for this curve * which is the curve used by the Ed25519 algorithm. The functions for this curve
* have the suffix \em ed25519. * have the suffix \em ed25519.
* *
* Internally, libuecc always uses the latter representation for its \em work structure. * Internally, libuecc always uses the former representation for its \em work structure.
* *
* The curves are equivalent to the Montgomery Curve used in D. J. Bernstein's * The curves are equivalent to the Montgomery Curve used in D. J. Bernstein's
* Curve25519 Diffie-Hellman algorithm. * Curve25519 Diffie-Hellman algorithm.
@ -62,88 +62,73 @@
const ecc_25519_work_t ecc_25519_work_identity = {{0}, {1}, {1}, {0}}; const ecc_25519_work_t ecc_25519_work_identity = {{0}, {1}, {1}, {0}};
const ecc_25519_work_t ecc_25519_work_base_legacy = { const ecc_25519_work_t ecc_25519_work_base_legacy = {
{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22,
0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a,
0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd,
0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54},
{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},
{1}, {1},
{0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82,
0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88,
0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4,
0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29}
}; };
const ecc_25519_work_t ecc_25519_work_default_base = { const ecc_25519_work_t ecc_25519_work_default_base = {
{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22,
0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a,
0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd,
0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54},
{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},
{1}, {1},
{0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82,
0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88,
0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4,
0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29}
}; };
const ecc_25519_work_t ecc_25519_work_base_ed25519 = { const ecc_25519_work_t ecc_25519_work_base_ed25519 = {
{0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, {0x19, 0x94, 0x01, 0x80, 0xc6, 0x05, 0x73, 0xdd,
0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, 0x1e, 0x69, 0xdc, 0x14, 0xd9, 0x48, 0x71, 0x95,
0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, 0xcb, 0x8b, 0x74, 0x99, 0x29, 0x5c, 0xd9, 0x22,
0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, 0xe6, 0xa1, 0x60, 0xde, 0xaf, 0xbc, 0x83, 0x2b},
{0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, {0x58, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66}, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66},
{1}, {1},
{0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, {0xa6, 0xa9, 0x67, 0x66, 0x38, 0x9e, 0xf5, 0x7d,
0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, 0xe5, 0x20, 0x7d, 0xdd, 0xe0, 0xd3, 0x8d, 0x77,
0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, 0x3c, 0xd6, 0xf6, 0xad, 0x87, 0x16, 0xe1, 0x1b,
0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, 0xb8, 0xb4, 0xb3, 0x7e, 0x59, 0xfd, 0x02, 0x56},
}; };
static const uint32_t zero[32] = {0}; static const uint32_t zero[32] = {0};
static const uint32_t one[32] = {1}; static const uint32_t one[32] = {1};
static const uint32_t minus1[32] = {
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
};
/** Ed25519 parameter -(121665/121666) */
static const uint32_t d[32] = {
0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75,
0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c,
0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52,
};
/** Factor to multiply the X coordinate with to convert from the legacy to the Ed25519 curve */ /** Factor to multiply the X coordinate with to convert from the legacy to the Ed25519 curve */
static const uint32_t legacy_to_ed25519[32] = { static const uint32_t legacy_to_ed25519[32] = {
0xe7, 0x81, 0xba, 0x00, 0x55, 0xfb, 0x91, 0x33, 0x06, 0x7e, 0x45, 0xff, 0xaa, 0x04, 0x6e, 0xcc,
0x7d, 0xe5, 0x82, 0xb4, 0x2e, 0x2c, 0x5e, 0x3a, 0x82, 0x1a, 0x7d, 0x4b, 0xd1, 0xd3, 0xa1, 0xc5,
0x81, 0xb0, 0x03, 0xfc, 0x23, 0xf7, 0x84, 0x2d, 0x7e, 0x4f, 0xfc, 0x03, 0xdc, 0x08, 0x7b, 0xd2,
0x44, 0xf9, 0x5f, 0x9f, 0x0b, 0x12, 0xd9, 0x70, 0xbb, 0x06, 0xa0, 0x60, 0xf4, 0xed, 0x26, 0x0f,
}; };
/** Factor to multiply the X coordinate with to convert from the Ed25519 to the legacy curve */ /** Factor to multiply the X coordinate with to convert from the Ed25519 to the legacy curve */
static const uint32_t ed25519_to_legacy[32] = { static const uint32_t ed25519_to_legacy[32] = {
0xe9, 0x68, 0x42, 0xdb, 0xaf, 0x04, 0xb4, 0x40, 0x04, 0x97, 0xbd, 0x24, 0x50, 0xfb, 0x4b, 0xbf,
0xa1, 0xd5, 0x43, 0xf2, 0xf9, 0x38, 0x31, 0x28, 0x5e, 0x2a, 0xbc, 0x0d, 0x06, 0xc7, 0xce, 0xd7,
0x01, 0x17, 0x05, 0x67, 0x9b, 0x81, 0x61, 0xf8, 0xfe, 0xe8, 0xfa, 0x98, 0x64, 0x7e, 0x9e, 0x07,
0xa9, 0x5b, 0x3e, 0x6a, 0x20, 0x67, 0x4b, 0x24, 0x56, 0xa4, 0xc1, 0x95, 0xdf, 0x98, 0xb4, 0x5b,
}; };
@ -248,7 +233,7 @@ static void freeze(uint32_t a[32]) {
* *
* The input must be \em squeezed. * The input must be \em squeezed.
*/ */
static int parity(const uint32_t a[32]) { static int parity(uint32_t a[32]) {
uint32_t b[32]; uint32_t b[32];
add(b, a, minusp); add(b, a, minusp);
@ -410,6 +395,13 @@ static void select(uint32_t out[32], const uint32_t r[32], const uint32_t s[32],
* If the given integer has no square root, 0 is returned, 1 otherwise. * If the given integer has no square root, 0 is returned, 1 otherwise.
*/ */
static int square_root(uint32_t out[32], const uint32_t z[32]) { static int square_root(uint32_t out[32], const uint32_t z[32]) {
static const uint32_t minus1[32] = {
0xec, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f
};
static const uint32_t rho_s[32] = { static const uint32_t rho_s[32] = {
0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4,
0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f,
@ -565,22 +557,20 @@ static void recip(uint32_t out[32], const uint32_t z[32]) {
/** /**
* Checks if the X and Y coordinates of a work structure represent a valid point of the curve * Checks if the X and Y coordinates of a work structure represent a valid point of the curve
* *
* Also fills in the T coordinate. * Also fills out the T coordinate.
*/ */
static int check_load_xy(ecc_25519_work_t *val) { static int check_load_xy(ecc_25519_work_t *val) {
uint32_t X2[32], Y2[32], dX2[32], dX2Y2[32], Y2_X2[32], Y2_X2_1[32], r[32]; uint32_t X2[32], Y2[32], aX2[32], dX2[32], dX2Y2[32], aX2_Y2[32], _1_dX2Y2[32], r[32];
/* Check validity */ /* Check validity */
square(X2, val->X); square(X2, val->X);
square(Y2, val->Y); square(Y2, val->Y);
mult_int(aX2, UINT32_C(486664), X2);
mult(dX2, d, X2); mult_int(dX2, UINT32_C(486660), X2);
mult(dX2Y2, dX2, Y2); mult(dX2Y2, dX2, Y2);
add(aX2_Y2, aX2, Y2);
sub(Y2_X2, Y2, X2); add(_1_dX2Y2, one, dX2Y2);
sub(Y2_X2_1, Y2_X2, one); sub(r, aX2_Y2, _1_dX2Y2);
sub(r, Y2_X2_1, dX2Y2);
squeeze(r); squeeze(r);
if (!check_zero(r)) if (!check_zero(r))
@ -593,6 +583,21 @@ static int check_load_xy(ecc_25519_work_t *val) {
int ecc_25519_load_xy_ed25519(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) { int ecc_25519_load_xy_ed25519(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) {
int i; int i;
uint32_t tmp[32];
for (i = 0; i < 32; i++) {
tmp[i] = x->p[i];
out->Y[i] = y->p[i];
out->Z[i] = (i == 0);
}
mult(out->X, tmp, ed25519_to_legacy);
return check_load_xy(out);
}
int ecc_25519_load_xy_legacy(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) {
int i;
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
out->X[i] = x->p[i]; out->X[i] = x->p[i];
@ -603,27 +608,34 @@ int ecc_25519_load_xy_ed25519(ecc_25519_work_t *out, const ecc_int256_t *x, cons
return check_load_xy(out); return check_load_xy(out);
} }
int ecc_25519_load_xy_legacy(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) {
int i;
uint32_t tmp[32];
for (i = 0; i < 32; i++) {
tmp[i] = x->p[i];
out->Y[i] = y->p[i];
out->Z[i] = (i == 0);
}
mult(out->X, tmp, legacy_to_ed25519);
return check_load_xy(out);
}
int ecc_25519_load_xy(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) { int ecc_25519_load_xy(ecc_25519_work_t *out, const ecc_int256_t *x, const ecc_int256_t *y) {
return ecc_25519_load_xy_legacy(out, x, y); return ecc_25519_load_xy_legacy(out, x, y);
} }
void ecc_25519_store_xy_ed25519(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) { void ecc_25519_store_xy_ed25519(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) {
uint32_t X[32], tmp[32], Y[32], Z[32];
int i;
recip(Z, in->Z);
if (x) {
mult(tmp, Z, in->X);
mult(X, tmp, legacy_to_ed25519);
freeze(X);
for (i = 0; i < 32; i++)
x->p[i] = X[i];
}
if (y) {
mult(Y, Z, in->Y);
freeze(Y);
for (i = 0; i < 32; i++)
y->p[i] = Y[i];
}
}
void ecc_25519_store_xy_legacy(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) {
uint32_t X[32], Y[32], Z[32]; uint32_t X[32], Y[32], Z[32];
int i; int i;
@ -644,37 +656,16 @@ void ecc_25519_store_xy_ed25519(ecc_int256_t *x, ecc_int256_t *y, const ecc_2551
} }
} }
void ecc_25519_store_xy_legacy(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) {
uint32_t X[32], tmp[32], Y[32], Z[32];
int i;
recip(Z, in->Z);
if (x) {
mult(tmp, Z, in->X);
mult(X, tmp, ed25519_to_legacy);
freeze(X);
for (i = 0; i < 32; i++)
x->p[i] = X[i];
}
if (y) {
mult(Y, Z, in->Y);
freeze(Y);
for (i = 0; i < 32; i++)
y->p[i] = Y[i];
}
}
void ecc_25519_store_xy(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) { void ecc_25519_store_xy(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519_work_t *in) {
ecc_25519_store_xy_legacy(x, y, in); ecc_25519_store_xy_legacy(x, y, in);
} }
int ecc_25519_load_packed_ed25519(ecc_25519_work_t *out, const ecc_int256_t *in) { int ecc_25519_load_packed_ed25519(ecc_25519_work_t *out, const ecc_int256_t *in) {
static const uint32_t a[32] = {UINT32_C(486664)};
int i; int i;
uint32_t Y2[32] /* Y^2 */, dY2[32] /* dY^2 */, Y2_1[32] /* Y^2-1 */, dY2_1[32] /* dY^2+1 */, _1_dY2_1[32] /* 1/(dY^2+1) */; uint32_t Y2[32] /* Y^2 */, dY2[32] /* dY^2 */, _1_Y2[32] /* 1-Y^2 */, a_dY2[32] /* a-dY^2 */, _1_a_dY2[32] /* 1/(a-dY^2) */;
uint32_t X2[32] /* X^2 */, X[32], Xt[32]; uint32_t X2[32] /* X^2 */, X[32], Xt[32], X_ed25519[32];
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
out->Y[i] = in->p[i]; out->Y[i] = in->p[i];
@ -684,19 +675,21 @@ int ecc_25519_load_packed_ed25519(ecc_25519_work_t *out, const ecc_int256_t *in)
out->Y[31] &= 0x7f; out->Y[31] &= 0x7f;
square(Y2, out->Y); square(Y2, out->Y);
mult(dY2, d, Y2); mult_int(dY2, UINT32_C(486660), Y2);
sub(Y2_1, Y2, one); sub(_1_Y2, one, Y2);
add(dY2_1, dY2, one); sub(a_dY2, a, dY2);
recip(_1_dY2_1, dY2_1); recip(_1_a_dY2, a_dY2);
mult(X2, Y2_1, _1_dY2_1); mult(X2, _1_Y2, _1_a_dY2);
if (!square_root(X, X2)) if (!square_root(X, X2))
return 0; return 0;
mult(X_ed25519, X, legacy_to_ed25519);
/* No squeeze is necessary after subtractions from zero if the subtrahend is squeezed */ /* No squeeze is necessary after subtractions from zero if the subtrahend is squeezed */
sub(Xt, zero, X); sub(Xt, zero, X);
select(out->X, X, Xt, (in->p[31] >> 7) ^ parity(X)); select(out->X, X, Xt, (in->p[31] >> 7) ^ parity(X_ed25519));
mult(out->T, out->X, out->Y); mult(out->T, out->X, out->Y);
@ -706,16 +699,16 @@ int ecc_25519_load_packed_ed25519(ecc_25519_work_t *out, const ecc_int256_t *in)
int ecc_25519_load_packed_legacy(ecc_25519_work_t *out, const ecc_int256_t *in) { int ecc_25519_load_packed_legacy(ecc_25519_work_t *out, const ecc_int256_t *in) {
int i; int i;
uint32_t X2[32] /* X^2 */, aX2[32] /* aX^2 */, dX2[32] /* dX^2 */, _1_aX2[32] /* 1-aX^2 */, _1_dX2[32] /* 1-aX^2 */; uint32_t X2[32] /* X^2 */, aX2[32] /* aX^2 */, dX2[32] /* dX^2 */, _1_aX2[32] /* 1-aX^2 */, _1_dX2[32] /* 1-aX^2 */;
uint32_t _1_1_dX2[32] /* 1/(1-aX^2) */, Y2[32] /* Y^2 */, Y[32], Yt[32], X_legacy[32]; uint32_t _1_1_dX2[32] /* 1/(1-aX^2) */, Y2[32] /* Y^2 */, Y[32], Yt[32];
for (i = 0; i < 32; i++) { for (i = 0; i < 32; i++) {
X_legacy[i] = in->p[i]; out->X[i] = in->p[i];
out->Z[i] = (i == 0); out->Z[i] = (i == 0);
} }
X_legacy[31] &= 0x7f; out->X[31] &= 0x7f;
square(X2, X_legacy); square(X2, out->X);
mult_int(aX2, UINT32_C(486664), X2); mult_int(aX2, UINT32_C(486664), X2);
mult_int(dX2, UINT32_C(486660), X2); mult_int(dX2, UINT32_C(486660), X2);
sub(_1_aX2, one, aX2); sub(_1_aX2, one, aX2);
@ -731,7 +724,6 @@ int ecc_25519_load_packed_legacy(ecc_25519_work_t *out, const ecc_int256_t *in)
select(out->Y, Y, Yt, (in->p[31] >> 7) ^ parity(Y)); select(out->Y, Y, Yt, (in->p[31] >> 7) ^ parity(Y));
mult(out->X, X_legacy, legacy_to_ed25519);
mult(out->T, out->X, out->Y); mult(out->T, out->X, out->Y);
return 1; return 1;
@ -784,26 +776,20 @@ void ecc_25519_negate(ecc_25519_work_t *out, const ecc_25519_work_t *in) {
} }
void ecc_25519_double(ecc_25519_work_t *out, const ecc_25519_work_t *in) { void ecc_25519_double(ecc_25519_work_t *out, const ecc_25519_work_t *in) {
uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32]; uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32], t2[32], t3[32];
square(A, in->X); square(A, in->X);
square(B, in->Y); square(B, in->Y);
square(t0, in->Z); square(t0, in->Z);
mult_int(C, 2, t0); mult_int(C, 2, t0);
mult_int(D, UINT32_C(486664), A);
sub(D, zero, A); add(t1, in->X, in->Y);
square(t2, t1);
add(t0, in->X, in->Y); sub(t3, t2, A);
square(t1, t0); sub(E, t3, B);
sub(t0, t1, A);
sub(E, t0, B);
add(G, D, B); add(G, D, B);
sub(F, G, C); sub(F, G, C);
sub(H, D, B); sub(H, D, B);
mult(out->X, E, F); mult(out->X, E, F);
mult(out->Y, G, H); mult(out->Y, G, H);
mult(out->T, E, H); mult(out->T, E, H);
@ -811,63 +797,22 @@ void ecc_25519_double(ecc_25519_work_t *out, const ecc_25519_work_t *in) {
} }
void ecc_25519_add(ecc_25519_work_t *out, const ecc_25519_work_t *in1, const ecc_25519_work_t *in2) { void ecc_25519_add(ecc_25519_work_t *out, const ecc_25519_work_t *in1, const ecc_25519_work_t *in2) {
const uint32_t j = UINT32_C(60833); uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32], t2[32], t3[32], t4[32], t5[32];
const uint32_t k = UINT32_C(121665);
uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32];
sub(t0, in1->Y, in1->X); mult(A, in1->X, in2->X);
mult_int(t1, j, t0); mult(B, in1->Y, in2->Y);
sub(t0, in2->Y, in2->X); mult_int(t0, UINT32_C(486660), in2->T);
mult(A, t0, t1);
add(t0, in1->Y, in1->X);
mult_int(t1, j, t0);
add(t0, in2->Y, in2->X);
mult(B, t0, t1);
mult_int(t0, k, in2->T);
mult(C, in1->T, t0); mult(C, in1->T, t0);
mult(D, in1->Z, in2->Z);
mult_int(t0, 2*j, in2->Z); add(t1, in1->X, in1->Y);
mult(D, in1->Z, t0); add(t2, in2->X, in2->Y);
mult(t3, t1, t2);
sub(E, B, A); sub(t4, t3, A);
add(F, D, C); sub(E, t4, B);
sub(G, D, C); sub(F, D, C);
add(H, B, A); add(G, D, C);
mult_int(t5, UINT32_C(486664), A);
mult(out->X, E, F); sub(H, B, t5);
mult(out->Y, G, H);
mult(out->T, E, H);
mult(out->Z, F, G);
}
/** Adds two points of the Elliptic Curve, assuming that in2->Z == 1 */
static void ecc_25519_add1(ecc_25519_work_t *out, const ecc_25519_work_t *in1, const ecc_25519_work_t *in2) {
const uint32_t j = UINT32_C(60833);
const uint32_t k = UINT32_C(121665);
uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32];
sub(t0, in1->Y, in1->X);
mult_int(t1, j, t0);
sub(t0, in2->Y, in2->X);
mult(A, t0, t1);
add(t0, in1->Y, in1->X);
mult_int(t1, j, t0);
add(t0, in2->Y, in2->X);
mult(B, t0, t1);
mult_int(t0, k, in2->T);
mult(C, in1->T, t0);
mult_int(D, 2*j, in1->Z);
sub(E, B, A);
add(F, D, C);
sub(G, D, C);
add(H, B, A);
mult(out->X, E, F); mult(out->X, E, F);
mult(out->Y, G, H); mult(out->Y, G, H);
mult(out->T, E, H); mult(out->T, E, H);
@ -906,25 +851,9 @@ void ecc_25519_scalarmult(ecc_25519_work_t *out, const ecc_int256_t *n, const ec
} }
void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n, unsigned bits) { void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n, unsigned bits) {
ecc_25519_work_t Q2, Q2p; ecc_25519_scalarmult_bits(out, n, &ecc_25519_work_base_legacy, bits);
ecc_25519_work_t cur = ecc_25519_work_identity;
int b, pos;
if (bits > 256)
bits = 256;
for (pos = bits - 1; pos >= 0; --pos) {
b = n->p[pos / 8] >> (pos & 7);
b &= 1;
ecc_25519_double(&Q2, &cur);
ecc_25519_add1(&Q2p, &Q2, &ecc_25519_work_default_base);
selectw(&cur, &Q2, &Q2p, b);
}
*out = cur;
} }
void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n) { void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n) {
ecc_25519_scalarmult_base_bits(out, n, 256); ecc_25519_scalarmult(out, n, &ecc_25519_work_base_legacy);
} }