From 740355d5ddb4e003e386951b9e74d8a4d49f609e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 Mar 2016 15:03:46 +0100 Subject: [PATCH 1/7] Unify legacy and Ed25519 base point by negating conversion factors --- src/ec25519.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/ec25519.c b/src/ec25519.c index 1b0ac73..0354f35 100644 --- a/src/ec25519.c +++ b/src/ec25519.c @@ -95,19 +95,19 @@ const ecc_25519_work_t ecc_25519_work_default_base = { const ecc_25519_work_t ecc_25519_work_base_ed25519 = { - {0x19, 0x94, 0x01, 0x80, 0xc6, 0x05, 0x73, 0xdd, - 0x1e, 0x69, 0xdc, 0x14, 0xd9, 0x48, 0x71, 0x95, - 0xcb, 0x8b, 0x74, 0x99, 0x29, 0x5c, 0xd9, 0x22, - 0xe6, 0xa1, 0x60, 0xde, 0xaf, 0xbc, 0x83, 0x2b}, + {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22, + 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a, + 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd, + 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54}, {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}, {1}, - {0xa6, 0xa9, 0x67, 0x66, 0x38, 0x9e, 0xf5, 0x7d, - 0xe5, 0x20, 0x7d, 0xdd, 0xe0, 0xd3, 0x8d, 0x77, - 0x3c, 0xd6, 0xf6, 0xad, 0x87, 0x16, 0xe1, 0x1b, - 0xb8, 0xb4, 0xb3, 0x7e, 0x59, 0xfd, 0x02, 0x56}, + {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82, + 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88, + 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4, + 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29} }; @@ -117,18 +117,18 @@ static const uint32_t one[32] = {1}; /** Factor to multiply the X coordinate with to convert from the legacy to the Ed25519 curve */ static const uint32_t legacy_to_ed25519[32] = { - 0x06, 0x7e, 0x45, 0xff, 0xaa, 0x04, 0x6e, 0xcc, - 0x82, 0x1a, 0x7d, 0x4b, 0xd1, 0xd3, 0xa1, 0xc5, - 0x7e, 0x4f, 0xfc, 0x03, 0xdc, 0x08, 0x7b, 0xd2, - 0xbb, 0x06, 0xa0, 0x60, 0xf4, 0xed, 0x26, 0x0f, + 0xe7, 0x81, 0xba, 0x00, 0x55, 0xfb, 0x91, 0x33, + 0x7d, 0xe5, 0x82, 0xb4, 0x2e, 0x2c, 0x5e, 0x3a, + 0x81, 0xb0, 0x03, 0xfc, 0x23, 0xf7, 0x84, 0x2d, + 0x44, 0xf9, 0x5f, 0x9f, 0x0b, 0x12, 0xd9, 0x70, }; /** Factor to multiply the X coordinate with to convert from the Ed25519 to the legacy curve */ static const uint32_t ed25519_to_legacy[32] = { - 0x04, 0x97, 0xbd, 0x24, 0x50, 0xfb, 0x4b, 0xbf, - 0x5e, 0x2a, 0xbc, 0x0d, 0x06, 0xc7, 0xce, 0xd7, - 0xfe, 0xe8, 0xfa, 0x98, 0x64, 0x7e, 0x9e, 0x07, - 0x56, 0xa4, 0xc1, 0x95, 0xdf, 0x98, 0xb4, 0x5b, + 0xe9, 0x68, 0x42, 0xdb, 0xaf, 0x04, 0xb4, 0x40, + 0xa1, 0xd5, 0x43, 0xf2, 0xf9, 0x38, 0x31, 0x28, + 0x01, 0x17, 0x05, 0x67, 0x9b, 0x81, 0x61, 0xf8, + 0xa9, 0x5b, 0x3e, 0x6a, 0x20, 0x67, 0x4b, 0x24, }; From 5ade164170ee0349ddd82ed5bdac1212d2484176 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 Mar 2016 15:12:46 +0100 Subject: [PATCH 2/7] Deprecate ecc_25519_work_base_ed25519 and ecc_25519_work_base_legacy The deprecation of ecc_25519_work_default_base and ecc_25519_scalarmult_base{,_bits} is reverted, as the Ed25519 and legacy base points are represented in the same way now. --- include/libuecc/ecc.h | 38 ++++++++++++++------------------------ src/ec25519.c | 4 ++-- 2 files changed, 16 insertions(+), 26 deletions(-) diff --git a/include/libuecc/ecc.h b/include/libuecc/ecc.h index 56c7538..0490bd5 100644 --- a/include/libuecc/ecc.h +++ b/include/libuecc/ecc.h @@ -68,33 +68,27 @@ extern const ecc_25519_work_t ecc_25519_work_identity; /** - * The generator point used by Ed25519 + * The Ed25519 default generator point * - * \ref ecc_25519_work_base_ed25519 is the inverse of \ref ecc_25519_work_base_legacy + * \deprecated Use the equivalent \ref ecc_25519_work_default_base instead. * - * The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$. **/ -extern const ecc_25519_work_t ecc_25519_work_base_ed25519; +DEPRECATED extern const ecc_25519_work_t ecc_25519_work_base_ed25519; /** - * The ec25519 legacy generator point ("default base" till libuecc v5) + * The Ed25519 default generator point * - * In new software that doesn't need compablity with older libuecc releases, you should consider - * using \ref ecc_25519_work_base_ed25519 instead. - * - * \ref ecc_25519_work_base_legacy is the inverse of \ref ecc_25519_work_base_ed25519 + * \deprecated Use the equivalent \ref ecc_25519_work_default_base instead. + */ +DEPRECATED extern const ecc_25519_work_t ecc_25519_work_base_legacy; + + +/** + * The Ed25519 default generator point * * The order of the base point is \f$ 2^{252} + 27742317777372353535851937790883648493 \f$. */ -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; +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 */ @@ -256,19 +250,15 @@ 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$. * * 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. */ -DEPRECATED 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); /** * 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$. - * - * \deprecated Use \ref ecc_25519_scalarmult and explicitly specify the base point. */ -DEPRECATED 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); /**@}*/ diff --git a/src/ec25519.c b/src/ec25519.c index 0354f35..82ff709 100644 --- a/src/ec25519.c +++ b/src/ec25519.c @@ -851,9 +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) { - ecc_25519_scalarmult_bits(out, n, &ecc_25519_work_base_legacy, bits); + ecc_25519_scalarmult_bits(out, n, &ecc_25519_work_default_base, bits); } void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n) { - ecc_25519_scalarmult(out, n, &ecc_25519_work_base_legacy); + ecc_25519_scalarmult(out, n, &ecc_25519_work_default_base); } From 26cbc55f783b5ab6541f24c8f69f595595125aca Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 18 Mar 2016 23:37:56 +0100 Subject: [PATCH 3/7] Switch internal point representation to the Ed25519 curve The Ed25519 curve allows slightly more efficient addition. --- src/ec25519.c | 247 +++++++++++++++++++++++++++----------------------- 1 file changed, 135 insertions(+), 112 deletions(-) diff --git a/src/ec25519.c b/src/ec25519.c index 82ff709..ad43f30 100644 --- a/src/ec25519.c +++ b/src/ec25519.c @@ -41,7 +41,7 @@ * which is the curve used by the Ed25519 algorithm. The functions for this curve * have the suffix \em ed25519. * - * Internally, libuecc always uses the former representation for its \em work structure. + * Internally, libuecc always uses the latter representation for its \em work structure. * * The curves are equivalent to the Montgomery Curve used in D. J. Bernstein's * Curve25519 Diffie-Hellman algorithm. @@ -62,58 +62,73 @@ const ecc_25519_work_t ecc_25519_work_identity = {{0}, {1}, {1}, {0}}; const ecc_25519_work_t ecc_25519_work_base_legacy = { - {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22, - 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a, - 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd, - 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54}, + {0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, {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}, {1}, - {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82, - 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88, - 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4, - 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29} + {0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, + 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, + 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, + 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, }; const ecc_25519_work_t ecc_25519_work_default_base = { - {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22, - 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a, - 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd, - 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54}, + {0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, {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}, {1}, - {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82, - 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88, - 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4, - 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29} + {0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, + 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, + 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, + 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, }; const ecc_25519_work_t ecc_25519_work_base_ed25519 = { - {0xd4, 0x6b, 0xfe, 0x7f, 0x39, 0xfa, 0x8c, 0x22, - 0xe1, 0x96, 0x23, 0xeb, 0x26, 0xb7, 0x8e, 0x6a, - 0x34, 0x74, 0x8b, 0x66, 0xd6, 0xa3, 0x26, 0xdd, - 0x19, 0x5e, 0x9f, 0x21, 0x50, 0x43, 0x7c, 0x54}, + {0x1a, 0xd5, 0x25, 0x8f, 0x60, 0x2d, 0x56, 0xc9, + 0xb2, 0xa7, 0x25, 0x95, 0x60, 0xc7, 0x2c, 0x69, + 0x5c, 0xdc, 0xd6, 0xfd, 0x31, 0xe2, 0xa4, 0xc0, + 0xfe, 0x53, 0x6e, 0xcd, 0xd3, 0x36, 0x69, 0x21}, {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}, {1}, - {0x47, 0x56, 0x98, 0x99, 0xc7, 0x61, 0x0a, 0x82, - 0x1a, 0xdf, 0x82, 0x22, 0x1f, 0x2c, 0x72, 0x88, - 0xc3, 0x29, 0x09, 0x52, 0x78, 0xe9, 0x1e, 0xe4, - 0x47, 0x4b, 0x4c, 0x81, 0xa6, 0x02, 0xfd, 0x29} + {0xa3, 0xdd, 0xb7, 0xa5, 0xb3, 0x8a, 0xde, 0x6d, + 0xf5, 0x52, 0x51, 0x77, 0x80, 0x9f, 0xf0, 0x20, + 0x7d, 0xe3, 0xab, 0x64, 0x8e, 0x4e, 0xea, 0x66, + 0x65, 0x76, 0x8b, 0xd7, 0x0f, 0x5f, 0x87, 0x67}, }; static const uint32_t zero[32] = {0}; 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 */ static const uint32_t legacy_to_ed25519[32] = { @@ -233,7 +248,7 @@ static void freeze(uint32_t a[32]) { * * The input must be \em squeezed. */ -static int parity(uint32_t a[32]) { +static int parity(const uint32_t a[32]) { uint32_t b[32]; add(b, a, minusp); @@ -395,13 +410,6 @@ 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. */ 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] = { 0xb0, 0xa0, 0x0e, 0x4a, 0x27, 0x1b, 0xee, 0xc4, 0x78, 0xe4, 0x2f, 0xad, 0x06, 0x18, 0x43, 0x2f, @@ -557,20 +565,22 @@ 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 * - * Also fills out the T coordinate. + * Also fills in the T coordinate. */ static int check_load_xy(ecc_25519_work_t *val) { - uint32_t X2[32], Y2[32], aX2[32], dX2[32], dX2Y2[32], aX2_Y2[32], _1_dX2Y2[32], r[32]; + uint32_t X2[32], Y2[32], dX2[32], dX2Y2[32], Y2_X2[32], Y2_X2_1[32], r[32]; /* Check validity */ square(X2, val->X); square(Y2, val->Y); - mult_int(aX2, UINT32_C(486664), X2); - mult_int(dX2, UINT32_C(486660), X2); + + mult(dX2, d, X2); mult(dX2Y2, dX2, Y2); - add(aX2_Y2, aX2, Y2); - add(_1_dX2Y2, one, dX2Y2); - sub(r, aX2_Y2, _1_dX2Y2); + + sub(Y2_X2, Y2, X2); + sub(Y2_X2_1, Y2_X2, one); + + sub(r, Y2_X2_1, dX2Y2); squeeze(r); if (!check_zero(r)) @@ -583,21 +593,6 @@ 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 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++) { out->X[i] = x->p[i]; @@ -608,34 +603,27 @@ int ecc_25519_load_xy_legacy(ecc_25519_work_t *out, const ecc_int256_t *x, const 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) { 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) { - 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]; int i; @@ -656,16 +644,37 @@ void ecc_25519_store_xy_legacy(ecc_int256_t *x, ecc_int256_t *y, const ecc_25519 } } +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) { ecc_25519_store_xy_legacy(x, y, 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; - 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], X_ed25519[32]; + 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 X2[32] /* X^2 */, X[32], Xt[32]; for (i = 0; i < 32; i++) { out->Y[i] = in->p[i]; @@ -675,21 +684,19 @@ int ecc_25519_load_packed_ed25519(ecc_25519_work_t *out, const ecc_int256_t *in) out->Y[31] &= 0x7f; square(Y2, out->Y); - mult_int(dY2, UINT32_C(486660), Y2); - sub(_1_Y2, one, Y2); - sub(a_dY2, a, dY2); - recip(_1_a_dY2, a_dY2); - mult(X2, _1_Y2, _1_a_dY2); + mult(dY2, d, Y2); + sub(Y2_1, Y2, one); + add(dY2_1, dY2, one); + recip(_1_dY2_1, dY2_1); + mult(X2, Y2_1, _1_dY2_1); if (!square_root(X, X2)) return 0; - mult(X_ed25519, X, legacy_to_ed25519); - /* No squeeze is necessary after subtractions from zero if the subtrahend is squeezed */ sub(Xt, zero, X); - select(out->X, X, Xt, (in->p[31] >> 7) ^ parity(X_ed25519)); + select(out->X, X, Xt, (in->p[31] >> 7) ^ parity(X)); mult(out->T, out->X, out->Y); @@ -699,16 +706,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 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 _1_1_dX2[32] /* 1/(1-aX^2) */, Y2[32] /* Y^2 */, Y[32], Yt[32]; + uint32_t _1_1_dX2[32] /* 1/(1-aX^2) */, Y2[32] /* Y^2 */, Y[32], Yt[32], X_legacy[32]; for (i = 0; i < 32; i++) { - out->X[i] = in->p[i]; + X_legacy[i] = in->p[i]; out->Z[i] = (i == 0); } - out->X[31] &= 0x7f; + X_legacy[31] &= 0x7f; - square(X2, out->X); + square(X2, X_legacy); mult_int(aX2, UINT32_C(486664), X2); mult_int(dX2, UINT32_C(486660), X2); sub(_1_aX2, one, aX2); @@ -724,6 +731,7 @@ 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)); + mult(out->X, X_legacy, legacy_to_ed25519); mult(out->T, out->X, out->Y); return 1; @@ -776,20 +784,26 @@ 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) { - 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]; + uint32_t A[32], B[32], C[32], D[32], E[32], F[32], G[32], H[32], t0[32], t1[32]; square(A, in->X); + square(B, in->Y); + square(t0, in->Z); mult_int(C, 2, t0); - mult_int(D, UINT32_C(486664), A); - add(t1, in->X, in->Y); - square(t2, t1); - sub(t3, t2, A); - sub(E, t3, B); + + sub(D, zero, A); + + add(t0, in->X, in->Y); + square(t1, t0); + sub(t0, t1, A); + sub(E, t0, B); + add(G, D, B); sub(F, G, C); sub(H, D, B); + mult(out->X, E, F); mult(out->Y, G, H); mult(out->T, E, H); @@ -797,22 +811,31 @@ 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) { - 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 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]; - mult(A, in1->X, in2->X); - mult(B, in1->Y, in2->Y); - mult_int(t0, UINT32_C(486660), in2->T); + 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(D, in1->Z, in2->Z); - add(t1, in1->X, in1->Y); - add(t2, in2->X, in2->Y); - mult(t3, t1, t2); - sub(t4, t3, A); - sub(E, t4, B); - sub(F, D, C); - add(G, D, C); - mult_int(t5, UINT32_C(486664), A); - sub(H, B, t5); + + mult_int(t0, 2*j, in2->Z); + mult(D, in1->Z, t0); + + sub(E, B, A); + add(F, D, C); + sub(G, D, C); + add(H, B, A); + mult(out->X, E, F); mult(out->Y, G, H); mult(out->T, E, H); From bb87f7b0e81b89104221b7558e9676b6f176d74f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 19 Mar 2016 00:47:14 +0100 Subject: [PATCH 4/7] Optimize ecc_25519_scalarmult_base We can elide one multiplication assuming that Z == 1 for the default base. --- src/ec25519.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/src/ec25519.c b/src/ec25519.c index ad43f30..0ed3741 100644 --- a/src/ec25519.c +++ b/src/ec25519.c @@ -842,6 +842,38 @@ void ecc_25519_add(ecc_25519_work_t *out, const ecc_25519_work_t *in1, const ecc 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->Y, G, H); + mult(out->T, E, H); + mult(out->Z, F, G); +} + void ecc_25519_sub(ecc_25519_work_t *out, const ecc_25519_work_t *in1, const ecc_25519_work_t *in2) { ecc_25519_work_t in2_neg; @@ -874,9 +906,25 @@ 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) { - ecc_25519_scalarmult_bits(out, n, &ecc_25519_work_default_base, bits); + ecc_25519_work_t Q2, Q2p; + 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) { - ecc_25519_scalarmult(out, n, &ecc_25519_work_default_base); + ecc_25519_scalarmult_base_bits(out, n, 256); } From b5b4697c1c11163955ae68beb40398a8e1021d3a Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 19 Mar 2016 13:59:30 +0100 Subject: [PATCH 5/7] Improve ecc_25519_scalarmult_base documentation --- include/libuecc/ecc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/libuecc/ecc.h b/include/libuecc/ecc.h index 0490bd5..1fb6106 100644 --- a/include/libuecc/ecc.h +++ b/include/libuecc/ecc.h @@ -249,6 +249,8 @@ 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$. * + * 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. */ void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n, unsigned bits); @@ -257,6 +259,8 @@ void ecc_25519_scalarmult_base_bits(ecc_25519_work_t *out, const ecc_int256_t *n * 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$. + * + * ecc_25519_scalarmult_base(out, n) is faster than ecc_25519_scalarmult(out, n, &ecc_25519_work_default_base). */ void ecc_25519_scalarmult_base(ecc_25519_work_t *out, const ecc_int256_t *n); From 3eb02ade40e64969ade1423ed095c57b53817c4f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 19 Mar 2016 14:02:43 +0100 Subject: [PATCH 6/7] Update CHANGELOG --- CHANGELOG | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/CHANGELOG b/CHANGELOG index 45bd1a1..1508442 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,22 @@ +libuecc v7 (unreleased) + +* 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) * Fixes a bug which might have caused a point's y coordinate to be negated From 7c9a6f6af088d0764e792cf849e553d7f55ff99e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sun, 27 Mar 2016 01:37:26 +0100 Subject: [PATCH 7/7] libuecc v7 --- CHANGELOG | 2 +- CMakeLists.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 1508442..2d46afe 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -libuecc v7 (unreleased) +libuecc v7 (2016/03/27) * Change conversion between Ed25519 and legacy representation. This should not affect any operations unless Ed25519 and legacy load/store diff --git a/CMakeLists.txt b/CMakeLists.txt index 2101389..779ac41 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 2.6) project(LIBUECC C) -set(PROJECT_VERSION 6) +set(PROJECT_VERSION 7) set(CMAKE_MODULE_PATH ${LIBUECC_SOURCE_DIR})