diff --git a/src/cli/perf_math.cpp b/src/cli/perf_math.cpp index 9e0bb007bb9..9e64d9604c5 100644 --- a/src/cli/perf_math.cpp +++ b/src/cli/perf_math.cpp @@ -14,7 +14,6 @@ #if defined(BOTAN_HAS_NUMBERTHEORY) #include #include - #include #include #endif @@ -148,62 +147,6 @@ BOTAN_REGISTER_PERF_TEST("mp_div10", PerfTest_MpDiv10); #if defined(BOTAN_HAS_NUMBERTHEORY) -class PerfTest_NistpRedc final : public PerfTest { - public: - void go(const PerfConfig& config) override { - std::chrono::milliseconds runtime_per_group = config.runtime(); - - Botan::secure_vector ws; - - auto p192_timer = config.make_timer("P-192 redc"); - Botan::BigInt r192(config.rng(), 192 * 2 - 1); - while(p192_timer->under(runtime_per_group)) { - Botan::BigInt r = r192; - p192_timer->run([&]() { Botan::redc_p192(r, ws); }); - r192 += 1; - } - config.record_result(*p192_timer); - - auto p224_timer = config.make_timer("P-224 redc"); - Botan::BigInt r224(config.rng(), 224 * 2 - 1); - while(p224_timer->under(runtime_per_group)) { - Botan::BigInt r = r224; - p224_timer->run([&]() { Botan::redc_p224(r, ws); }); - r224 += 1; - } - config.record_result(*p224_timer); - - auto p256_timer = config.make_timer("P-256 redc"); - Botan::BigInt r256(config.rng(), 256 * 2 - 1); - while(p256_timer->under(runtime_per_group)) { - Botan::BigInt r = r256; - p256_timer->run([&]() { Botan::redc_p256(r, ws); }); - r256 += 1; - } - config.record_result(*p256_timer); - - auto p384_timer = config.make_timer("P-384 redc"); - Botan::BigInt r384(config.rng(), 384 * 2 - 1); - while(p384_timer->under(runtime_per_group)) { - Botan::BigInt r = r384; - p384_timer->run([&]() { Botan::redc_p384(r384, ws); }); - r384 += 1; - } - config.record_result(*p384_timer); - - auto p521_timer = config.make_timer("P-521 redc"); - Botan::BigInt r521(config.rng(), 521 * 2 - 1); - while(p521_timer->under(runtime_per_group)) { - Botan::BigInt r = r521; - p521_timer->run([&]() { Botan::redc_p521(r521, ws); }); - r521 += 1; - } - config.record_result(*p521_timer); - } -}; - -BOTAN_REGISTER_PERF_TEST("nistp_redc", PerfTest_NistpRedc); - class PerfTest_BnRedc final : public PerfTest { public: void go(const PerfConfig& config) override { diff --git a/src/lib/math/numbertheory/curve_nistp.h b/src/lib/math/numbertheory/curve_nistp.h deleted file mode 100644 index 101f636ebf0..00000000000 --- a/src/lib/math/numbertheory/curve_nistp.h +++ /dev/null @@ -1,86 +0,0 @@ -/* -* Arithmetic operations specialized for NIST ECC primes -* (C) 2014,2015 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_NIST_PRIMES_H_ -#define BOTAN_NIST_PRIMES_H_ - -#include - -namespace Botan { - -/* -* NIST Prime reduction functions. -* -* Reduces the value in place -* -* ws is a workspace function which is used as a temporary, -* and will be resized as needed. -*/ - -/** -* Return the P-521 prime -*/ -BOTAN_TEST_API const BigInt& prime_p521(); - -/** -* Reduce an input modulo P-521 -* -* Input value x must be between 0 and p**2 -*/ -BOTAN_TEST_API void redc_p521(BigInt& x, secure_vector& ws); - -/** -* Return the P-384 prime -*/ -BOTAN_TEST_API const BigInt& prime_p384(); - -/** -* Reduce an input modulo P-384 -* -* Input value x must be between 0 and p**2 -*/ -BOTAN_TEST_API void redc_p384(BigInt& x, secure_vector& ws); - -/** -* Return the P-256 prime -*/ -BOTAN_TEST_API const BigInt& prime_p256(); - -/** -* Reduce an input modulo P-256 -* -* Input value x must be between 0 and p**2 -*/ -BOTAN_TEST_API void redc_p256(BigInt& x, secure_vector& ws); - -/** -* Return the P-224 prime -*/ -BOTAN_TEST_API const BigInt& prime_p224(); - -/** -* Reduce an input modulo P-224 -* -* Input value x must be between 0 and p**2 -*/ -BOTAN_TEST_API void redc_p224(BigInt& x, secure_vector& ws); - -/** -* Return the P-192 prime -*/ -BOTAN_TEST_API const BigInt& prime_p192(); - -/** -* Reduce an input modulo P-192 -* -* Input value x must be between 0 and p**2 -*/ -BOTAN_TEST_API void redc_p192(BigInt& x, secure_vector& ws); - -} // namespace Botan - -#endif diff --git a/src/lib/math/numbertheory/info.txt b/src/lib/math/numbertheory/info.txt index a3507e9531a..f6b8b5afe6b 100644 --- a/src/lib/math/numbertheory/info.txt +++ b/src/lib/math/numbertheory/info.txt @@ -13,7 +13,6 @@ reducer.h -curve_nistp.h monty.h monty_exp.h primality.h diff --git a/src/lib/math/numbertheory/nistp_redc.cpp b/src/lib/math/numbertheory/nistp_redc.cpp deleted file mode 100644 index ac579a77fdb..00000000000 --- a/src/lib/math/numbertheory/nistp_redc.cpp +++ /dev/null @@ -1,540 +0,0 @@ -/* -* NIST prime reductions -* (C) 2014,2015,2018 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include - -#include -#include - -namespace Botan { - -const BigInt& prime_p521() { - static const BigInt p521( - "0x1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - - return p521; -} - -void redc_p521(BigInt& x, secure_vector& ws) { - BOTAN_DEBUG_ASSERT(x.is_positive()); - - const size_t p_full_words = 521 / BOTAN_MP_WORD_BITS; - const size_t p_top_bits = 521 % BOTAN_MP_WORD_BITS; - const size_t p_words = p_full_words + 1; - - static const constinit auto p521_words = hex_to_words( - "1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"); - - if(ws.size() < p_words + 1) { - ws.resize(p_words + 1); - } - - clear_mem(ws.data(), ws.size()); - bigint_shr2(ws.data(), x._data(), std::min(x.size(), 2 * p_words), 521); - - x.mask_bits(521); - x.grow_to(p_words); - - // Word-level carry will be zero - word carry = bigint_add3_nc(x.mutable_data(), x._data(), p_words, ws.data(), p_words); - BOTAN_ASSERT_EQUAL(carry, 0, "Final carry in P-521 reduction"); - - const word top_word = x.word_at(p_full_words); - - /* - * Check if we need to reduce modulo P - * There are two possible cases: - * - The result overflowed past 521 bits, in which case bit 522 will be set - * - The result is exactly 2**521 - 1 - */ - const auto bit_522_set = CT::Mask::expand(top_word >> p_top_bits); - - const word max = WordInfo::max; - word and_512 = max; - for(size_t i = 0; i != p_full_words; ++i) { - and_512 &= x.word_at(i); - } - const auto all_512_low_bits_set = CT::Mask::is_equal(and_512, max); - const auto has_p521_top_word = CT::Mask::is_equal(top_word, 0x1FF); - const auto is_p521 = all_512_low_bits_set & has_p521_top_word; - - const auto needs_reduction = is_p521 | bit_522_set; - - bigint_cnd_sub(needs_reduction.value(), x.mutable_data(), p521_words.data(), p_words); -} - -namespace { - -/** -* Treating this MPI as a sequence of 32-bit words in big-endian -* order, return word i. The array is assumed to be large enough. -*/ -constexpr uint32_t get_uint32(const word xw[], size_t i) { -#if(BOTAN_MP_WORD_BITS == 32) - return xw[i]; -#else - return static_cast(xw[i / 2] >> ((i % 2) * 32)); -#endif -} - -inline void set_words(word x[], size_t i, uint32_t R0, uint32_t R1) { -#if(BOTAN_MP_WORD_BITS == 32) - x[i] = R0; - x[i + 1] = R1; -#else - x[i / 2] = (static_cast(R1) << 32) | R0; -#endif -} - -} // namespace - -const BigInt& prime_p192() { - static const BigInt p192("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"); - return p192; -} - -void redc_p192(BigInt& x, secure_vector& ws) { - BOTAN_DEBUG_ASSERT(x.is_positive()); - - BOTAN_UNUSED(ws); - - static const size_t p192_limbs = 192 / BOTAN_MP_WORD_BITS; - - x.grow_to(2 * p192_limbs); - word* xw = x.mutable_data(); - - const uint64_t X00 = get_uint32(xw, 0); - const uint64_t X01 = get_uint32(xw, 1); - const uint64_t X02 = get_uint32(xw, 2); - const uint64_t X03 = get_uint32(xw, 3); - const uint64_t X04 = get_uint32(xw, 4); - const uint64_t X05 = get_uint32(xw, 5); - const uint64_t X06 = get_uint32(xw, 6); - const uint64_t X07 = get_uint32(xw, 7); - const uint64_t X08 = get_uint32(xw, 8); - const uint64_t X09 = get_uint32(xw, 9); - const uint64_t X10 = get_uint32(xw, 10); - const uint64_t X11 = get_uint32(xw, 11); - - const uint64_t S0 = X00 + X06 + X10; - const uint64_t S1 = X01 + X07 + X11; - const uint64_t S2 = X02 + X06 + X08 + X10; - const uint64_t S3 = X03 + X07 + X09 + X11; - const uint64_t S4 = X04 + X08 + X10; - const uint64_t S5 = X05 + X09 + X11; - - uint64_t S = 0; - uint32_t R0 = 0, R1 = 0; - - S += S0; - R0 = static_cast(S); - S >>= 32; - - S += S1; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 0, R0, R1); - - S += S2; - R0 = static_cast(S); - S >>= 32; - - S += S3; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 2, R0, R1); - - S += S4; - R0 = static_cast(S); - S >>= 32; - - S += S5; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 4, R0, R1); - - // No underflow possible - - /* - This is a table of (i*P-192) % 2**192 for i in 1...3 - */ - static const constinit std::array p192_mults[3] = { - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF"), - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFFFFFFFFFE"), - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFFFFFFFFFD"), - }; - - CT::unpoison(S); - BOTAN_ASSERT(S <= 2, "Expected overflow"); - - BOTAN_ASSERT_NOMSG(x.size() >= p192_limbs + 1); - x.mask_bits(192); - word borrow = bigint_sub2(x.mutable_data(), p192_limbs + 1, p192_mults[S].data(), p192_limbs); - BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1); - bigint_cnd_add(borrow, x.mutable_data(), p192_limbs + 1, p192_mults[0].data(), p192_limbs); -} - -const BigInt& prime_p224() { - static const BigInt p224("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"); - return p224; -} - -void redc_p224(BigInt& x, secure_vector& ws) { - BOTAN_DEBUG_ASSERT(x.is_positive()); - - static const size_t p224_limbs = (BOTAN_MP_WORD_BITS == 32) ? 7 : 4; - - BOTAN_UNUSED(ws); - - x.grow_to(2 * p224_limbs); - word* xw = x.mutable_data(); - - const int64_t X00 = get_uint32(xw, 0); - const int64_t X01 = get_uint32(xw, 1); - const int64_t X02 = get_uint32(xw, 2); - const int64_t X03 = get_uint32(xw, 3); - const int64_t X04 = get_uint32(xw, 4); - const int64_t X05 = get_uint32(xw, 5); - const int64_t X06 = get_uint32(xw, 6); - const int64_t X07 = get_uint32(xw, 7); - const int64_t X08 = get_uint32(xw, 8); - const int64_t X09 = get_uint32(xw, 9); - const int64_t X10 = get_uint32(xw, 10); - const int64_t X11 = get_uint32(xw, 11); - const int64_t X12 = get_uint32(xw, 12); - const int64_t X13 = get_uint32(xw, 13); - - // One full copy of P224 is added, so the result is always positive - - const int64_t S0 = 0x00000001 + X00 - X07 - X11; - const int64_t S1 = 0x00000000 + X01 - X08 - X12; - const int64_t S2 = 0x00000000 + X02 - X09 - X13; - const int64_t S3 = 0xFFFFFFFF + X03 + X07 + X11 - X10; - const int64_t S4 = 0xFFFFFFFF + X04 + X08 + X12 - X11; - const int64_t S5 = 0xFFFFFFFF + X05 + X09 + X13 - X12; - const int64_t S6 = 0xFFFFFFFF + X06 + X10 - X13; - - int64_t S = 0; - uint32_t R0 = 0, R1 = 0; - - S += S0; - R0 = static_cast(S); - S >>= 32; - - S += S1; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 0, R0, R1); - - S += S2; - R0 = static_cast(S); - S >>= 32; - - S += S3; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 2, R0, R1); - - S += S4; - R0 = static_cast(S); - S >>= 32; - - S += S5; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 4, R0, R1); - - S += S6; - R0 = static_cast(S); - S >>= 32; - - set_words(xw, 6, R0, 0); - - static const constinit std::array p224_mults[3] = { - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001"), - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFE000000000000000000000002"), - hex_to_words("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFD000000000000000000000003"), - }; - - CT::unpoison(S); - BOTAN_ASSERT(S >= 0 && S <= 2, "Expected overflow"); - - BOTAN_ASSERT_NOMSG(x.size() >= p224_limbs + 1); - x.mask_bits(224); - word borrow = bigint_sub2(x.mutable_data(), p224_limbs + 1, p224_mults[S].data(), p224_limbs); - BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1); - bigint_cnd_add(borrow, x.mutable_data(), p224_limbs + 1, p224_mults[0].data(), p224_limbs); -} - -const BigInt& prime_p256() { - static const BigInt p256("0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"); - return p256; -} - -void redc_p256(BigInt& x, secure_vector& ws) { - BOTAN_DEBUG_ASSERT(x.is_positive()); - - static const size_t p256_limbs = (BOTAN_MP_WORD_BITS == 32) ? 8 : 4; - - BOTAN_UNUSED(ws); - - x.grow_to(2 * p256_limbs); - word* xw = x.mutable_data(); - - const int64_t X00 = get_uint32(xw, 0); - const int64_t X01 = get_uint32(xw, 1); - const int64_t X02 = get_uint32(xw, 2); - const int64_t X03 = get_uint32(xw, 3); - const int64_t X04 = get_uint32(xw, 4); - const int64_t X05 = get_uint32(xw, 5); - const int64_t X06 = get_uint32(xw, 6); - const int64_t X07 = get_uint32(xw, 7); - const int64_t X08 = get_uint32(xw, 8); - const int64_t X09 = get_uint32(xw, 9); - const int64_t X10 = get_uint32(xw, 10); - const int64_t X11 = get_uint32(xw, 11); - const int64_t X12 = get_uint32(xw, 12); - const int64_t X13 = get_uint32(xw, 13); - const int64_t X14 = get_uint32(xw, 14); - const int64_t X15 = get_uint32(xw, 15); - - // Adds 6 * P-256 to prevent underflow - const int64_t S0 = 0xFFFFFFFA + X00 + X08 + X09 - (X11 + X12 + X13) - X14; - const int64_t S1 = 0xFFFFFFFF + X01 + X09 + X10 - X12 - (X13 + X14 + X15); - const int64_t S2 = 0xFFFFFFFF + X02 + X10 + X11 - (X13 + X14 + X15); - const int64_t S3 = 0x00000005 + X03 + (X11 + X12) * 2 + X13 - X15 - X08 - X09; - const int64_t S4 = 0x00000000 + X04 + (X12 + X13) * 2 + X14 - X09 - X10; - const int64_t S5 = 0x00000000 + X05 + (X13 + X14) * 2 + X15 - X10 - X11; - const int64_t S6 = 0x00000006 + X06 + X13 + X14 * 3 + X15 * 2 - X08 - X09; - const int64_t S7 = 0xFFFFFFFA + X07 + X15 * 3 + X08 - X10 - (X11 + X12 + X13); - - int64_t S = 0; - - uint32_t R0 = 0, R1 = 0; - - S += S0; - R0 = static_cast(S); - S >>= 32; - - S += S1; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 0, R0, R1); - - S += S2; - R0 = static_cast(S); - S >>= 32; - - S += S3; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 2, R0, R1); - - S += S4; - R0 = static_cast(S); - S >>= 32; - - S += S5; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 4, R0, R1); - - S += S6; - R0 = static_cast(S); - S >>= 32; - - S += S7; - R1 = static_cast(S); - S >>= 32; - set_words(xw, 6, R0, R1); - - S += 5; // the top digits of 6*P-256 - - /* - This is a table of (i*P-256) % 2**256 for i in 1...10 - */ - static const constinit std::array p256_mults[11] = { - hex_to_words("FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF"), - hex_to_words("FFFFFFFE00000002000000000000000000000001FFFFFFFFFFFFFFFFFFFFFFFE"), - hex_to_words("FFFFFFFD00000003000000000000000000000002FFFFFFFFFFFFFFFFFFFFFFFD"), - hex_to_words("FFFFFFFC00000004000000000000000000000003FFFFFFFFFFFFFFFFFFFFFFFC"), - hex_to_words("FFFFFFFB00000005000000000000000000000004FFFFFFFFFFFFFFFFFFFFFFFB"), - hex_to_words("FFFFFFFA00000006000000000000000000000005FFFFFFFFFFFFFFFFFFFFFFFA"), - hex_to_words("FFFFFFF900000007000000000000000000000006FFFFFFFFFFFFFFFFFFFFFFF9"), - hex_to_words("FFFFFFF800000008000000000000000000000007FFFFFFFFFFFFFFFFFFFFFFF8"), - hex_to_words("FFFFFFF700000009000000000000000000000008FFFFFFFFFFFFFFFFFFFFFFF7"), - hex_to_words("FFFFFFF60000000A000000000000000000000009FFFFFFFFFFFFFFFFFFFFFFF6"), - hex_to_words("FFFFFFF50000000B00000000000000000000000AFFFFFFFFFFFFFFFFFFFFFFF5"), - }; - - CT::unpoison(S); - BOTAN_ASSERT(S >= 0 && S <= 10, "Expected overflow"); - - BOTAN_ASSERT_NOMSG(x.size() >= p256_limbs + 1); - x.mask_bits(256); - word borrow = bigint_sub2(x.mutable_data(), p256_limbs + 1, p256_mults[S].data(), p256_limbs); - BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1); - bigint_cnd_add(borrow, x.mutable_data(), p256_limbs + 1, p256_mults[0].data(), p256_limbs); -} - -const BigInt& prime_p384() { - static const BigInt p384( - "0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"); - return p384; -} - -void redc_p384(BigInt& x, secure_vector& ws) { - BOTAN_DEBUG_ASSERT(x.is_positive()); - - BOTAN_UNUSED(ws); - - static const size_t p384_limbs = (BOTAN_MP_WORD_BITS == 32) ? 12 : 6; - - x.grow_to(2 * p384_limbs); - word* xw = x.mutable_data(); - - const int64_t X00 = get_uint32(xw, 0); - const int64_t X01 = get_uint32(xw, 1); - const int64_t X02 = get_uint32(xw, 2); - const int64_t X03 = get_uint32(xw, 3); - const int64_t X04 = get_uint32(xw, 4); - const int64_t X05 = get_uint32(xw, 5); - const int64_t X06 = get_uint32(xw, 6); - const int64_t X07 = get_uint32(xw, 7); - const int64_t X08 = get_uint32(xw, 8); - const int64_t X09 = get_uint32(xw, 9); - const int64_t X10 = get_uint32(xw, 10); - const int64_t X11 = get_uint32(xw, 11); - const int64_t X12 = get_uint32(xw, 12); - const int64_t X13 = get_uint32(xw, 13); - const int64_t X14 = get_uint32(xw, 14); - const int64_t X15 = get_uint32(xw, 15); - const int64_t X16 = get_uint32(xw, 16); - const int64_t X17 = get_uint32(xw, 17); - const int64_t X18 = get_uint32(xw, 18); - const int64_t X19 = get_uint32(xw, 19); - const int64_t X20 = get_uint32(xw, 20); - const int64_t X21 = get_uint32(xw, 21); - const int64_t X22 = get_uint32(xw, 22); - const int64_t X23 = get_uint32(xw, 23); - - // One copy of P-384 is added to prevent underflow - const int64_t S0 = 0xFFFFFFFF + X00 + X12 + X20 + X21 - X23; - const int64_t S1 = 0x00000000 + X01 + X13 + X22 + X23 - X12 - X20; - const int64_t S2 = 0x00000000 + X02 + X14 + X23 - X13 - X21; - const int64_t S3 = 0xFFFFFFFF + X03 + X12 + X15 + X20 + X21 - X14 - X22 - X23; - const int64_t S4 = 0xFFFFFFFE + X04 + X12 + X13 + X16 + X20 + X21 * 2 + X22 - X15 - X23 * 2; - const int64_t S5 = 0xFFFFFFFF + X05 + X13 + X14 + X17 + X21 + X22 * 2 + X23 - X16; - const int64_t S6 = 0xFFFFFFFF + X06 + X14 + X15 + X18 + X22 + X23 * 2 - X17; - const int64_t S7 = 0xFFFFFFFF + X07 + X15 + X16 + X19 + X23 - X18; - const int64_t S8 = 0xFFFFFFFF + X08 + X16 + X17 + X20 - X19; - const int64_t S9 = 0xFFFFFFFF + X09 + X17 + X18 + X21 - X20; - const int64_t SA = 0xFFFFFFFF + X10 + X18 + X19 + X22 - X21; - const int64_t SB = 0xFFFFFFFF + X11 + X19 + X20 + X23 - X22; - - int64_t S = 0; - - uint32_t R0 = 0, R1 = 0; - - S += S0; - R0 = static_cast(S); - S >>= 32; - - S += S1; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 0, R0, R1); - - S += S2; - R0 = static_cast(S); - S >>= 32; - - S += S3; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 2, R0, R1); - - S += S4; - R0 = static_cast(S); - S >>= 32; - - S += S5; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 4, R0, R1); - - S += S6; - R0 = static_cast(S); - S >>= 32; - - S += S7; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 6, R0, R1); - - S += S8; - R0 = static_cast(S); - S >>= 32; - - S += S9; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 8, R0, R1); - - S += SA; - R0 = static_cast(S); - S >>= 32; - - S += SB; - R1 = static_cast(S); - S >>= 32; - - set_words(xw, 10, R0, R1); - - /* - This is a table of (i*P-384) % 2**384 for i in 1...4 - */ - static const constinit std::array p384_mults[5] = { - hex_to_words( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF"), - hex_to_words( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFDFFFFFFFE0000000000000001FFFFFFFE"), - hex_to_words( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFCFFFFFFFD0000000000000002FFFFFFFD"), - hex_to_words( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFBFFFFFFFC0000000000000003FFFFFFFC"), - hex_to_words( - "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAFFFFFFFB0000000000000004FFFFFFFB"), - }; - - CT::unpoison(S); - BOTAN_ASSERT(S >= 0 && S <= 4, "Expected overflow"); - - BOTAN_ASSERT_NOMSG(x.size() >= p384_limbs + 1); - x.mask_bits(384); - word borrow = bigint_sub2(x.mutable_data(), p384_limbs + 1, p384_mults[S].data(), p384_limbs); - BOTAN_DEBUG_ASSERT(borrow == 0 || borrow == 1); - bigint_cnd_add(borrow, x.mutable_data(), p384_limbs + 1, p384_mults[0].data(), p384_limbs); -} - -} // namespace Botan diff --git a/src/lib/pubkey/ec_group/curve_gfp.cpp b/src/lib/pubkey/ec_group/curve_gfp.cpp index d179f95a645..9db949d141e 100644 --- a/src/lib/pubkey/ec_group/curve_gfp.cpp +++ b/src/lib/pubkey/ec_group/curve_gfp.cpp @@ -10,7 +10,6 @@ #include #include -#include #include #include @@ -157,438 +156,9 @@ void CurveGFp_Montgomery::curve_sqr_words(BigInt& z, const word x[], size_t x_si bigint_monty_redc(z.mutable_data(), m_p._data(), m_p_words, m_p_dash, ws.data(), ws.size()); } -class CurveGFp_NIST : public CurveGFp_Repr { - public: - CurveGFp_NIST(size_t p_bits, const BigInt& a, const BigInt& b) : - m_1(1), - m_a(a), - m_b(b), - m_p_bits(p_bits), - m_p_words((p_bits + BOTAN_MP_WORD_BITS - 1) / BOTAN_MP_WORD_BITS) { - // All Solinas prime curves are assumed a == -3 - } - - bool a_is_zero() const override { return false; } - - bool a_is_minus_3() const override { return true; } - - const BigInt& get_a() const override { return m_a; } - - const BigInt& get_b() const override { return m_b; } - - const BigInt& get_1_rep() const override { return m_1; } - - size_t get_p_bits() const override { return m_p_bits; } - - size_t get_ws_size() const override { return 2 * m_p_words; } - - const BigInt& get_a_rep() const override { return m_a; } - - const BigInt& get_b_rep() const override { return m_b; } - - bool is_one(const BigInt& x) const override { return x == 1; } - - void to_curve_rep(BigInt& x, secure_vector& ws) const override { redc_mod_p(x, ws); } - - void from_curve_rep(BigInt& x, secure_vector& ws) const override { redc_mod_p(x, ws); } - - virtual void redc_mod_p(BigInt& z, secure_vector& ws) const = 0; - - BigInt invert_element(const BigInt& x, secure_vector& ws) const override; - - void curve_mul_words( - BigInt& z, const word x_words[], size_t x_size, const BigInt& y, secure_vector& ws) const override; - - void curve_mul_tmp(BigInt& x, const BigInt& y, BigInt& tmp, secure_vector& ws) const { - curve_mul(tmp, x, y, ws); - x.swap(tmp); - } - - void curve_sqr_tmp(BigInt& x, BigInt& tmp, secure_vector& ws) const { - curve_sqr(tmp, x, ws); - x.swap(tmp); - } - - void curve_sqr_words(BigInt& z, const word x_words[], size_t x_size, secure_vector& ws) const override; - - private: - // Curve parameters - BigInt m_1; - BigInt m_a, m_b; - size_t m_p_bits; // cache of m_p.bits() - size_t m_p_words; // cache of m_p.sig_words() -}; - -BigInt CurveGFp_NIST::invert_element(const BigInt& x, secure_vector& ws) const { - BOTAN_UNUSED(ws); - return inverse_mod(x, get_p()); -} - -void CurveGFp_NIST::curve_mul_words( - BigInt& z, const word x_w[], size_t x_size, const BigInt& y, secure_vector& ws) const { - BOTAN_DEBUG_ASSERT(y.sig_words() <= m_p_words); - - if(ws.size() < get_ws_size()) { - ws.resize(get_ws_size()); - } - - const size_t output_size = 2 * m_p_words; - if(z.size() < output_size) { - z.grow_to(output_size); - } - - bigint_mul(z.mutable_data(), - z.size(), - x_w, - x_size, - std::min(m_p_words, x_size), - y._data(), - y.size(), - std::min(m_p_words, y.size()), - ws.data(), - ws.size()); - - this->redc_mod_p(z, ws); -} - -void CurveGFp_NIST::curve_sqr_words(BigInt& z, const word x[], size_t x_size, secure_vector& ws) const { - if(ws.size() < get_ws_size()) { - ws.resize(get_ws_size()); - } - - const size_t output_size = 2 * m_p_words; - if(z.size() < output_size) { - z.grow_to(output_size); - } - - bigint_sqr(z.mutable_data(), output_size, x, x_size, std::min(m_p_words, x_size), ws.data(), ws.size()); - - this->redc_mod_p(z, ws); -} - -/** -* The NIST P-192 curve -*/ -class CurveGFp_P192 final : public CurveGFp_NIST { - public: - CurveGFp_P192(const BigInt& a, const BigInt& b) : CurveGFp_NIST(192, a, b) {} - - const BigInt& get_p() const override { return prime_p192(); } - - private: - void redc_mod_p(BigInt& x, secure_vector& ws) const override { redc_p192(x, ws); } -}; - -/** -* The NIST P-224 curve -*/ -class CurveGFp_P224 final : public CurveGFp_NIST { - public: - CurveGFp_P224(const BigInt& a, const BigInt& b) : CurveGFp_NIST(224, a, b) {} - - const BigInt& get_p() const override { return prime_p224(); } - - private: - void redc_mod_p(BigInt& x, secure_vector& ws) const override { redc_p224(x, ws); } -}; - -/** -* The NIST P-256 curve -*/ -class CurveGFp_P256 final : public CurveGFp_NIST { - public: - CurveGFp_P256(const BigInt& a, const BigInt& b) : CurveGFp_NIST(256, a, b) {} - - const BigInt& get_p() const override { return prime_p256(); } - - private: - void redc_mod_p(BigInt& x, secure_vector& ws) const override { redc_p256(x, ws); } - - BigInt invert_element(const BigInt& x, secure_vector& ws) const override; -}; - -BigInt CurveGFp_P256::invert_element(const BigInt& x, secure_vector& ws) const { - BigInt r, p2, p4, p8, p16, p32, tmp; - - curve_sqr(r, x, ws); - - curve_mul(p2, r, x, ws); - curve_sqr(r, p2, ws); - curve_sqr_tmp(r, tmp, ws); - - curve_mul(p4, r, p2, ws); - - curve_sqr(r, p4, ws); - for(size_t i = 0; i != 3; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul(p8, r, p4, ws); - - curve_sqr(r, p8, ws); - for(size_t i = 0; i != 7; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul(p16, r, p8, ws); - - curve_sqr(r, p16, ws); - for(size_t i = 0; i != 15; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul(p32, r, p16, ws); - - curve_sqr(r, p32, ws); - for(size_t i = 0; i != 31; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x, tmp, ws); - - for(size_t i = 0; i != 32 * 4; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p32, tmp, ws); - - for(size_t i = 0; i != 32; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p32, tmp, ws); - - for(size_t i = 0; i != 16; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p16, tmp, ws); - for(size_t i = 0; i != 8; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p8, tmp, ws); - - for(size_t i = 0; i != 4; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p4, tmp, ws); - - for(size_t i = 0; i != 2; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, p2, tmp, ws); - - for(size_t i = 0; i != 2; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x, tmp, ws); - - return r; -} - -/** -* The NIST P-384 curve -*/ -class CurveGFp_P384 final : public CurveGFp_NIST { - public: - CurveGFp_P384(const BigInt& a, const BigInt& b) : CurveGFp_NIST(384, a, b) {} - - const BigInt& get_p() const override { return prime_p384(); } - - private: - void redc_mod_p(BigInt& x, secure_vector& ws) const override { redc_p384(x, ws); } - - BigInt invert_element(const BigInt& x, secure_vector& ws) const override; -}; - -BigInt CurveGFp_P384::invert_element(const BigInt& x, secure_vector& ws) const { - // From https://briansmith.org/ecc-inversion-addition-chains-01 - - BigInt r, x2, x3, x15, x30, tmp, rl; - - r = x; - curve_sqr_tmp(r, tmp, ws); - curve_mul_tmp(r, x, tmp, ws); - x2 = r; - - curve_sqr_tmp(r, tmp, ws); - curve_mul_tmp(r, x, tmp, ws); - - x3 = r; - - for(size_t i = 0; i != 3; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x3, tmp, ws); - - rl = r; - for(size_t i = 0; i != 6; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - for(size_t i = 0; i != 3; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x3, tmp, ws); - - x15 = r; - for(size_t i = 0; i != 15; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x15, tmp, ws); - - x30 = r; - for(size_t i = 0; i != 30; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x30, tmp, ws); - - rl = r; - for(size_t i = 0; i != 60; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 120; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - for(size_t i = 0; i != 15; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x15, tmp, ws); - - for(size_t i = 0; i != 31; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x30, tmp, ws); - - for(size_t i = 0; i != 2; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x2, tmp, ws); - - for(size_t i = 0; i != 94; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x30, tmp, ws); - - for(size_t i = 0; i != 2; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - - curve_mul_tmp(r, x, tmp, ws); - - return r; -} - -/** -* The NIST P-521 curve -*/ -class CurveGFp_P521 final : public CurveGFp_NIST { - public: - CurveGFp_P521(const BigInt& a, const BigInt& b) : CurveGFp_NIST(521, a, b) {} - - const BigInt& get_p() const override { return prime_p521(); } - - private: - void redc_mod_p(BigInt& x, secure_vector& ws) const override { redc_p521(x, ws); } - - BigInt invert_element(const BigInt& x, secure_vector& ws) const override; -}; - -BigInt CurveGFp_P521::invert_element(const BigInt& x, secure_vector& ws) const { - // Addition chain from https://eprint.iacr.org/2014/852.pdf section - - BigInt r; - BigInt rl; - BigInt a7; - BigInt tmp; - - curve_sqr(r, x, ws); - curve_mul_tmp(r, x, tmp, ws); - - curve_sqr_tmp(r, tmp, ws); - curve_mul_tmp(r, x, tmp, ws); - - rl = r; - - for(size_t i = 0; i != 3; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - curve_sqr_tmp(r, tmp, ws); - curve_mul_tmp(r, x, tmp, ws); - a7 = r; // need this value later - - curve_sqr_tmp(r, tmp, ws); - curve_mul_tmp(r, x, tmp, ws); - - rl = r; - for(size_t i = 0; i != 8; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 16; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 32; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 64; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 128; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - rl = r; - for(size_t i = 0; i != 256; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, rl, tmp, ws); - - for(size_t i = 0; i != 7; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, a7, tmp, ws); - - for(size_t i = 0; i != 2; ++i) { - curve_sqr_tmp(r, tmp, ws); - } - curve_mul_tmp(r, x, tmp, ws); - - return r; -} - } // namespace std::shared_ptr CurveGFp::choose_repr(const BigInt& p, const BigInt& a, const BigInt& b) { - if(p == prime_p192() && p == a + 3) { - return std::make_shared(a, b); - } - if(p == prime_p224() && p == a + 3) { - return std::make_shared(a, b); - } - if(p == prime_p256() && p == a + 3) { - return std::make_shared(a, b); - } - if(p == prime_p384() && p == a + 3) { - return std::make_shared(a, b); - } - if(p == prime_p521() && p == a + 3) { - return std::make_shared(a, b); - } - return std::make_shared(p, a, b); } diff --git a/src/scripts/test_cli.py b/src/scripts/test_cli.py index e3f5bac09f3..1d254f60d9e 100755 --- a/src/scripts/test_cli.py +++ b/src/scripts/test_cli.py @@ -1704,8 +1704,7 @@ def cli_speed_math_tests(_tmp_dir): msec = 1 # these all have a common output format math_ops = ['mp_mul', 'mp_div', 'mp_div10', 'modexp', 'random_prime', 'inverse_mod', - 'rfc3394', 'fpe_fe1', 'ecdsa_recovery', 'ecc', - 'bn_redc', 'nistp_redc', 'primality_test'] + 'rfc3394', 'fpe_fe1', 'ecdsa_recovery', 'ecc', 'bn_redc', 'primality_test'] format_re = re.compile(r'^.* [0-9]+ /sec; [0-9]+\.[0-9]+ ms/op .*\([0-9]+ (op|ops) in [0-9]+(\.[0-9]+)? ms\)') for op in math_ops: diff --git a/src/tests/test_ec_group.cpp b/src/tests/test_ec_group.cpp index 05b2099ded2..20c276a7e64 100644 --- a/src/tests/test_ec_group.cpp +++ b/src/tests/test_ec_group.cpp @@ -18,7 +18,6 @@ #include #include #include - #include #endif namespace Botan_Tests { @@ -110,8 +109,8 @@ std::vector ECC_Randomized_Tests::run() { try { const size_t trials = (Test::run_long_tests() ? 10 : 3); for(size_t i = 0; i < trials; ++i) { - const Botan::BigInt a = group.random_scalar(rng()); - const Botan::BigInt b = group.random_scalar(rng()); + const Botan::BigInt a = test_integer(rng(), group.get_order_bits(), group.get_order()); + const Botan::BigInt b = test_integer(rng(), group.get_order_bits(), group.get_order()); const Botan::BigInt c = group.mod_order(a + b); const Botan::EC_Point P = pt * a; @@ -160,78 +159,6 @@ std::vector ECC_Randomized_Tests::run() { BOTAN_REGISTER_TEST("pubkey", "ecc_randomized", ECC_Randomized_Tests); -class NIST_Curve_Reduction_Tests final : public Test { - public: - typedef std::function&)> reducer_fn; - - std::vector run() override { - std::vector results; - - // Using lambdas here to avoid strange UbSan warning (#1370) - - results.push_back(random_redc_test( - "P-384", Botan::prime_p384(), [](Botan::BigInt& p, Botan::secure_vector& ws) -> void { - Botan::redc_p384(p, ws); - })); - results.push_back(random_redc_test( - "P-256", Botan::prime_p256(), [](Botan::BigInt& p, Botan::secure_vector& ws) -> void { - Botan::redc_p256(p, ws); - })); - results.push_back(random_redc_test( - "P-224", Botan::prime_p224(), [](Botan::BigInt& p, Botan::secure_vector& ws) -> void { - Botan::redc_p224(p, ws); - })); - results.push_back(random_redc_test( - "P-192", Botan::prime_p192(), [](Botan::BigInt& p, Botan::secure_vector& ws) -> void { - Botan::redc_p192(p, ws); - })); - results.push_back(random_redc_test( - "P-521", Botan::prime_p521(), [](Botan::BigInt& p, Botan::secure_vector& ws) -> void { - Botan::redc_p521(p, ws); - })); - - return results; - } - - static Test::Result random_redc_test(const std::string& prime_name, - const Botan::BigInt& p, - const reducer_fn& redc_fn) { - const Botan::BigInt p2 = p * p; - const size_t p_bits = p.bits(); - - Botan::Modular_Reducer p_redc(p); - Botan::secure_vector ws; - - auto rng = Test::new_rng("random_redc " + prime_name); - - Test::Result result("NIST " + prime_name + " reduction"); - result.start_timer(); - - const size_t trials = (Test::run_long_tests() ? 128 : 16); - - for(size_t i = 0; i <= trials; ++i) { - const Botan::BigInt x = test_integer(*rng, 2 * p_bits, p2); - - // TODO: time and report all three approaches - const Botan::BigInt v1 = x % p; - const Botan::BigInt v2 = p_redc.reduce(x); - - Botan::BigInt v3 = x; - redc_fn(v3, ws); - - if(!result.test_eq("reference redc", v1, v2) || !result.test_eq("specialized redc", v2, v3)) { - result.test_note("failing input" + Botan::hex_encode(Botan::BigInt::encode(x))); - } - } - - result.end_timer(); - - return result; - } -}; - -BOTAN_REGISTER_TEST("pubkey", "nist_redc", NIST_Curve_Reduction_Tests); - class EC_Group_Tests : public Test { public: std::vector run() override {