diff --git a/ChangeLog b/ChangeLog index 8fa78d46..5e76e255 100644 --- a/ChangeLog +++ b/ChangeLog @@ -22,6 +22,7 @@ and `crypto_core_ed25519_scalar_sub()`. `crypto_scalarmult_ed25519_base_noclamp()`, and `crypto_scalarmult_ed25519_noclamp()`. These new APIs are especially useful for blinding. + - `sodium_sub()` has been implemented. - Support for WatchOS has been added. - getrandom(2) is now used on FreeBSD 12+. diff --git a/src/libsodium/crypto_core/ed25519/core_ed25519.c b/src/libsodium/crypto_core/ed25519/core_ed25519.c index c412891a..e9027e5d 100644 --- a/src/libsodium/crypto_core/ed25519/core_ed25519.c +++ b/src/libsodium/crypto_core/ed25519/core_ed25519.c @@ -88,63 +88,44 @@ crypto_core_ed25519_scalar_invert(unsigned char *recip, const unsigned char *s) return - sodium_is_zero(s, crypto_core_ed25519_SCALARBYTES); } +/* 2^252+27742317777372353535851937790883648493 */ +static const unsigned char L[] = { + 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, + 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 +}; + void crypto_core_ed25519_scalar_negate(unsigned char *neg, const unsigned char *s) { - /* 2^252+27742317777372353535851937790883648493 */ - static const unsigned char L[32] = { - 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, - 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 - }; - uint_fast16_t c = 0U; - unsigned char r = 0U; - size_t i; + unsigned char t_[crypto_core_ed25519_NONREDUCEDSCALARBYTES] = { 0U }; + unsigned char s_[crypto_core_ed25519_NONREDUCEDSCALARBYTES] = { 0U }; - for (i = 0; i < crypto_core_ed25519_SCALARBYTES; i++) { - r |= s[i]; - c = (uint_fast16_t) L[i] - (uint_fast16_t) s[i] - c; - neg[i] = (unsigned char) c; - c = (c >> 8) & 1U; - } - r = ~(r - 1U) >> 8; - for (i = 0; i < crypto_core_ed25519_SCALARBYTES; i++) { - neg[i] &= r; - } + COMPILER_ASSERT(crypto_core_ed25519_NONREDUCEDSCALARBYTES >= + 2 * crypto_core_ed25519_SCALARBYTES); + memcpy(t_ + crypto_core_ed25519_SCALARBYTES, L, + crypto_core_ed25519_SCALARBYTES); + memcpy(s_, s, crypto_core_ed25519_SCALARBYTES); + sodium_sub(t_, s_, sizeof t_); + sc25519_reduce(t_); + memcpy(neg, t_, crypto_core_ed25519_SCALARBYTES); } void -crypto_core_ed25519_scalar_complement(unsigned char *comp, const unsigned char *s) +crypto_core_ed25519_scalar_complement(unsigned char *comp, + const unsigned char *s) { - /* 2^252+27742317777372353535851937790883648493 + 1 */ - static const unsigned char L1[32] = { - 0xee, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, - 0xa2, 0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 - }; - uint_fast16_t c = 0U; - unsigned char q = 0U; - unsigned char r = 0U; - size_t i; + unsigned char t_[crypto_core_ed25519_NONREDUCEDSCALARBYTES] = { 1U }; + unsigned char s_[crypto_core_ed25519_NONREDUCEDSCALARBYTES] = { 0U }; - q |= s[0] ^ 1U; - r |= s[0]; - c = (uint_fast16_t) L1[0] - (uint_fast16_t) s[0] - c; - comp[0] = (unsigned char) c; - c = (c >> 8) & 1U; - for (i = 1U; i < crypto_core_ed25519_SCALARBYTES; i++) { - q |= s[i]; - r |= s[i]; - c = (uint_fast16_t) L1[i] - (uint_fast16_t) s[i] - c; - comp[i] = (unsigned char) c; - c = (c >> 8) & 1U; - } - q = ~(q - 1U) >> 8; - r = ~(r - 1U) >> 8; - for (i = 0; i < crypto_core_ed25519_SCALARBYTES; i++) { - comp[i] &= q & r; - } - comp[0] |= (~r) & 1U; + COMPILER_ASSERT(crypto_core_ed25519_NONREDUCEDSCALARBYTES >= + 2 * crypto_core_ed25519_SCALARBYTES); + memcpy(t_ + crypto_core_ed25519_SCALARBYTES, L, + crypto_core_ed25519_SCALARBYTES); + memcpy(s_, s, crypto_core_ed25519_SCALARBYTES); + sodium_sub(t_, s_, sizeof t_); + sc25519_reduce(t_); + memcpy(comp, t_, crypto_core_ed25519_SCALARBYTES); } void diff --git a/src/libsodium/include/sodium/utils.h b/src/libsodium/include/sodium/utils.h index 92ac2e69..84feeea6 100644 --- a/src/libsodium/include/sodium/utils.h +++ b/src/libsodium/include/sodium/utils.h @@ -55,6 +55,10 @@ SODIUM_EXPORT void sodium_add(unsigned char *a, const unsigned char *b, const size_t len) __attribute__ ((nonnull)); +SODIUM_EXPORT +void sodium_sub(unsigned char *a, const unsigned char *b, const size_t len) + __attribute__ ((nonnull)); + SODIUM_EXPORT char *sodium_bin2hex(char * const hex, const size_t hex_maxlen, const unsigned char * const bin, const size_t bin_len) diff --git a/src/libsodium/sodium/utils.c b/src/libsodium/sodium/utils.c index 007f284a..d018824a 100644 --- a/src/libsodium/sodium/utils.c +++ b/src/libsodium/sodium/utils.c @@ -335,6 +335,49 @@ sodium_add(unsigned char *a, const unsigned char *b, const size_t len) } } +void +sodium_sub(unsigned char *a, const unsigned char *b, const size_t len) +{ + uint_fast16_t c = 0U; + size_t i; + +#ifdef HAVE_AMD64_ASM + uint64_t t64_1, t64_2, t64_3, t64_4; + uint64_t t64_5, t64_6, t64_7, t64_8; + uint32_t t32; + + if (len == 64U) { + __asm__ __volatile__( + "movq (%[in]), %[t64_1] \n" + "movq 8(%[in]), %[t64_2] \n" + "movq 16(%[in]), %[t64_3] \n" + "movq 24(%[in]), %[t64_4] \n" + "movq 32(%[in]), %[t64_5] \n" + "movq 40(%[in]), %[t64_6] \n" + "movq 48(%[in]), %[t64_7] \n" + "movq 56(%[in]), %[t64_8] \n" + "subq %[t64_1], (%[out]) \n" + "sbbq %[t64_2], 8(%[out]) \n" + "sbbq %[t64_3], 16(%[out]) \n" + "sbbq %[t64_4], 24(%[out]) \n" + "sbbq %[t64_5], 32(%[out]) \n" + "sbbq %[t64_6], 40(%[out]) \n" + "sbbq %[t64_7], 48(%[out]) \n" + "sbbq %[t64_8], 56(%[out]) \n" + : [t64_1] "=&r"(t64_1), [t64_2] "=&r"(t64_2), [t64_3] "=&r"(t64_3), [t64_4] "=&r"(t64_4), + [t64_5] "=&r"(t64_5), [t64_6] "=&r"(t64_6), [t64_7] "=&r"(t64_7), [t64_8] "=&r"(t64_8) + : [in] "S"(b), [out] "D"(a) + : "memory", "flags", "cc"); + return; + } +#endif + for (i = 0; i < len; i++) { + c = (uint_fast16_t) a[i] - (uint_fast16_t) b[i] - c; + a[i] = (unsigned char) c; + c = (c >> 8) & 1U; + } +} + int _sodium_alloc_init(void) {