diff options
author | Jack Lloyd <[email protected]> | 2020-11-08 04:40:40 -0500 |
---|---|---|
committer | Jack Lloyd <[email protected]> | 2020-11-08 04:59:59 -0500 |
commit | d21e444cf70401a9f930f91427cb6cd615085351 (patch) | |
tree | c343292e8ae9b1bee65c02514348d891a374ad6b | |
parent | 9ebdba973c9c86c53e42cc2636e6f373d5e5bc98 (diff) |
Cleanup in number theory
Remove or hide deprecated functions
Consolidate some source files
-rw-r--r-- | src/lib/math/numbertheory/dsa_gen.cpp | 1 | ||||
-rw-r--r-- | src/lib/math/numbertheory/info.txt | 3 | ||||
-rw-r--r-- | src/lib/math/numbertheory/jacobi.cpp | 52 | ||||
-rw-r--r-- | src/lib/math/numbertheory/make_prm.cpp | 2 | ||||
-rw-r--r-- | src/lib/math/numbertheory/mod_inv.cpp | 119 | ||||
-rw-r--r-- | src/lib/math/numbertheory/monty.cpp | 29 | ||||
-rw-r--r-- | src/lib/math/numbertheory/monty.h | 8 | ||||
-rw-r--r-- | src/lib/math/numbertheory/mp_numth.cpp | 84 | ||||
-rw-r--r-- | src/lib/math/numbertheory/numthry.cpp | 155 | ||||
-rw-r--r-- | src/lib/math/numbertheory/numthry.h | 107 | ||||
-rw-r--r-- | src/lib/math/numbertheory/pow_mod.cpp | 328 | ||||
-rw-r--r-- | src/lib/math/numbertheory/pow_mod.h | 120 | ||||
-rw-r--r-- | src/lib/math/numbertheory/primality.h | 33 | ||||
-rw-r--r-- | src/lib/math/numbertheory/ressol.cpp | 87 | ||||
-rw-r--r-- | src/lib/pubkey/dl_group/dl_group.cpp | 1 | ||||
-rw-r--r-- | src/lib/pubkey/ec_group/curve_gfp.cpp | 1 | ||||
-rw-r--r-- | src/tests/test_bigint.cpp | 40 |
17 files changed, 231 insertions, 939 deletions
diff --git a/src/lib/math/numbertheory/dsa_gen.cpp b/src/lib/math/numbertheory/dsa_gen.cpp index a5efbc266..8a86d0cfd 100644 --- a/src/lib/math/numbertheory/dsa_gen.cpp +++ b/src/lib/math/numbertheory/dsa_gen.cpp @@ -5,6 +5,7 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/primality.h> #include <botan/numthry.h> #include <botan/hash.h> #include <botan/reducer.h> diff --git a/src/lib/math/numbertheory/info.txt b/src/lib/math/numbertheory/info.txt index a5b914a30..3d91db8d7 100644 --- a/src/lib/math/numbertheory/info.txt +++ b/src/lib/math/numbertheory/info.txt @@ -1,5 +1,5 @@ <defines> -NUMBERTHEORY -> 20131128 +NUMBERTHEORY -> 20201108 </defines> <header:public> @@ -11,7 +11,6 @@ reducer.h curve_nistp.h monty.h monty_exp.h -pow_mod.h primality.h </header:internal> diff --git a/src/lib/math/numbertheory/jacobi.cpp b/src/lib/math/numbertheory/jacobi.cpp deleted file mode 100644 index 284fc2b20..000000000 --- a/src/lib/math/numbertheory/jacobi.cpp +++ /dev/null @@ -1,52 +0,0 @@ -/* -* Jacobi Function -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/numthry.h> - -namespace Botan { - -/* -* Calculate the Jacobi symbol -*/ -int32_t jacobi(const BigInt& a, const BigInt& n) - { - if(n.is_even() || n < 2) - throw Invalid_Argument("jacobi: second argument must be odd and > 1"); - - BigInt x = a % n; - BigInt y = n; - int32_t J = 1; - - while(y > 1) - { - x %= y; - if(x > y / 2) - { - x = y - x; - if(y % 4 == 3) - J = -J; - } - if(x.is_zero()) - return 0; - - size_t shifts = low_zero_bits(x); - x >>= shifts; - if(shifts % 2) - { - word y_mod_8 = y % 8; - if(y_mod_8 == 3 || y_mod_8 == 5) - J = -J; - } - - if(x % 4 == 3 && y % 4 == 3) - J = -J; - std::swap(x, y); - } - return J; - } - -} diff --git a/src/lib/math/numbertheory/make_prm.cpp b/src/lib/math/numbertheory/make_prm.cpp index bac15c707..30f6ae91d 100644 --- a/src/lib/math/numbertheory/make_prm.cpp +++ b/src/lib/math/numbertheory/make_prm.cpp @@ -5,12 +5,12 @@ * Botan is released under the Simplified BSD License (see license.txt) */ +#include <botan/internal/primality.h> #include <botan/numthry.h> #include <botan/rng.h> #include <botan/internal/bit_ops.h> #include <botan/internal/loadstor.h> #include <botan/reducer.h> -#include <botan/internal/primality.h> #include <algorithm> namespace Botan { diff --git a/src/lib/math/numbertheory/mod_inv.cpp b/src/lib/math/numbertheory/mod_inv.cpp index b7c6f2b1e..f6f6c6c17 100644 --- a/src/lib/math/numbertheory/mod_inv.cpp +++ b/src/lib/math/numbertheory/mod_inv.cpp @@ -12,81 +12,6 @@ namespace Botan { -/* -Sets result to a^-1 * 2^k mod a -with n <= k <= 2n -Returns k - -"The Montgomery Modular Inverse - Revisited" Çetin Koç, E. Savas -https://citeseerx.ist.psu.edu/viewdoc/citations?doi=10.1.1.75.8377 - -A const time implementation of this algorithm is described in -"Constant Time Modular Inversion" Joppe W. Bos -http://www.joppebos.com/files/CTInversion.pdf -*/ -size_t almost_montgomery_inverse(BigInt& result, - const BigInt& a, - const BigInt& p) - { - size_t k = 0; - - BigInt u = p, v = a, r = 0, s = 1; - - while(v > 0) - { - if(u.is_even()) - { - u >>= 1; - s <<= 1; - } - else if(v.is_even()) - { - v >>= 1; - r <<= 1; - } - else if(u > v) - { - u -= v; - u >>= 1; - r += s; - s <<= 1; - } - else - { - v -= u; - v >>= 1; - s += r; - r <<= 1; - } - - ++k; - } - - if(r >= p) - { - r -= p; - } - - result = p - r; - - return k; - } - -BigInt normalized_montgomery_inverse(const BigInt& a, const BigInt& p) - { - BigInt r; - size_t k = almost_montgomery_inverse(r, a, p); - - for(size_t i = 0; i != k; ++i) - { - if(r.is_odd()) - r += p; - r >>= 1; - } - - return r; - } - namespace { BigInt inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod) @@ -259,8 +184,8 @@ BigInt inverse_mod(const BigInt& n, const BigInt& mod) if(mod.is_odd()) { /* - Fastpath for common case. This leaks information if n > mod - but we don't guarantee const time behavior in that case. + Fastpath for common case. This leaks if n is greater than mod or + not, but we don't guarantee const time behavior in that case. */ if(n < mod) return inverse_mod_odd_modulus(n, mod); @@ -313,44 +238,4 @@ BigInt inverse_mod(const BigInt& n, const BigInt& mod) return h; } -// Deprecated forwarding functions: -BigInt inverse_euclid(const BigInt& x, const BigInt& modulus) - { - return inverse_mod(x, modulus); - } - -BigInt ct_inverse_mod_odd_modulus(const BigInt& n, const BigInt& mod) - { - return inverse_mod_odd_modulus(n, mod); - } - -word monty_inverse(word a) - { - if(a % 2 == 0) - throw Invalid_Argument("monty_inverse only valid for odd integers"); - - /* - * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç - * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. - */ - - word b = 1; - word r = 0; - - for(size_t i = 0; i != BOTAN_MP_WORD_BITS; ++i) - { - const word bi = b % 2; - r >>= 1; - r += bi << (BOTAN_MP_WORD_BITS - 1); - - b -= a * bi; - b >>= 1; - } - - // Now invert in addition space - r = (MP_WORD_MAX - r) + 1; - - return r; - } - } diff --git a/src/lib/math/numbertheory/monty.cpp b/src/lib/math/numbertheory/monty.cpp index 40cee2986..709f1ebe5 100644 --- a/src/lib/math/numbertheory/monty.cpp +++ b/src/lib/math/numbertheory/monty.cpp @@ -10,6 +10,35 @@ namespace Botan { +word monty_inverse(word a) + { + if(a % 2 == 0) + throw Invalid_Argument("monty_inverse only valid for odd integers"); + + /* + * From "A New Algorithm for Inversion mod p^k" by Çetin Kaya Koç + * https://eprint.iacr.org/2017/411.pdf sections 5 and 7. + */ + + word b = 1; + word r = 0; + + for(size_t i = 0; i != BOTAN_MP_WORD_BITS; ++i) + { + const word bi = b % 2; + r >>= 1; + r += bi << (BOTAN_MP_WORD_BITS - 1); + + b -= a * bi; + b >>= 1; + } + + // Now invert in addition space + r = (MP_WORD_MAX - r) + 1; + + return r; + } + Montgomery_Params::Montgomery_Params(const BigInt& p, const Modular_Reducer& mod_p) { diff --git a/src/lib/math/numbertheory/monty.h b/src/lib/math/numbertheory/monty.h index 8e0cd342f..b4c90397e 100644 --- a/src/lib/math/numbertheory/monty.h +++ b/src/lib/math/numbertheory/monty.h @@ -8,7 +8,6 @@ #define BOTAN_MONTY_INT_H_ #include <botan/bigint.h> -BOTAN_FUTURE_INTERNAL_HEADER(monty.h) namespace Botan { @@ -16,6 +15,13 @@ class Modular_Reducer; class Montgomery_Params; +/* +* Compute -input^-1 mod 2^MP_WORD_BITS. Throws an exception if input +* is even. If input is odd, then input and 2^n are relatively prime +* and an inverse exists. +*/ +word monty_inverse(word input); + /** * The Montgomery representation of an integer */ diff --git a/src/lib/math/numbertheory/mp_numth.cpp b/src/lib/math/numbertheory/mp_numth.cpp deleted file mode 100644 index eef641996..000000000 --- a/src/lib/math/numbertheory/mp_numth.cpp +++ /dev/null @@ -1,84 +0,0 @@ -/* -* Fused and Important MP Algorithms -* (C) 1999-2007 Jack Lloyd -* 2016 Matthias Gierlings -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/numthry.h> -#include <botan/internal/mp_core.h> -#include <botan/internal/rounding.h> -#include <algorithm> - -namespace Botan { - -/* -* Square a BigInt -*/ -BigInt square(const BigInt& x) - { - BigInt z = x; - secure_vector<word> ws; - z.square(ws); - return z; - } - -/* -* Multiply-Add Operation -*/ -BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c) - { - if(c.is_negative()) - throw Invalid_Argument("mul_add: Third argument must be > 0"); - - BigInt::Sign sign = BigInt::Positive; - if(a.sign() != b.sign()) - sign = BigInt::Negative; - - const size_t a_sw = a.sig_words(); - const size_t b_sw = b.sig_words(); - const size_t c_sw = c.sig_words(); - - BigInt r(sign, std::max(a_sw + b_sw, c_sw) + 1); - secure_vector<word> workspace(r.size()); - - bigint_mul(r.mutable_data(), r.size(), - a.data(), a.size(), a_sw, - b.data(), b.size(), b_sw, - workspace.data(), workspace.size()); - - const size_t r_size = std::max(r.sig_words(), c_sw); - bigint_add2(r.mutable_data(), r_size, c.data(), c_sw); - return r; - } - -/* -* Subtract-Multiply Operation -*/ -BigInt sub_mul(const BigInt& a, const BigInt& b, const BigInt& c) - { - if(a.is_negative() || b.is_negative()) - throw Invalid_Argument("sub_mul: First two arguments must be >= 0"); - - BigInt r = a; - r -= b; - r *= c; - return r; - } - -/* -* Multiply-Subtract Operation -*/ -BigInt mul_sub(const BigInt& a, const BigInt& b, const BigInt& c) - { - if(c.is_negative() || c.is_zero()) - throw Invalid_Argument("mul_sub: Third argument must be > 0"); - - BigInt r = a; - r *= b; - r -= c; - return r; - } - -} diff --git a/src/lib/math/numbertheory/numthry.cpp b/src/lib/math/numbertheory/numthry.cpp index f8e1ae8d9..18e372c58 100644 --- a/src/lib/math/numbertheory/numthry.cpp +++ b/src/lib/math/numbertheory/numthry.cpp @@ -1,6 +1,7 @@ /* * Number Theory Functions * (C) 1999-2011,2016,2018,2019 Jack Lloyd +* (C) 2007,2008 Falko Strenzke, FlexSecure GmbH * * Botan is released under the Simplified BSD License (see license.txt) */ @@ -34,6 +35,160 @@ void sub_abs(BigInt& z, const BigInt& x, const BigInt& y) } /* +* Tonelli-Shanks algorithm +*/ +BigInt ressol(const BigInt& a, const BigInt& p) + { + if(p <= 1 || p.is_even()) + throw Invalid_Argument("ressol: invalid prime"); + + if(a == 0) + return 0; + else if(a < 0) + throw Invalid_Argument("ressol: value to solve for must be positive"); + else if(a >= p) + throw Invalid_Argument("ressol: value to solve for must be less than p"); + + if(p == 2) + return a; + + if(jacobi(a, p) != 1) // not a quadratic residue + return -BigInt(1); + + if(p % 4 == 3) // The easy case + { + return power_mod(a, ((p+1) >> 2), p); + } + + size_t s = low_zero_bits(p - 1); + BigInt q = p >> s; + + q -= 1; + q >>= 1; + + Modular_Reducer mod_p(p); + + BigInt r = power_mod(a, q, p); + BigInt n = mod_p.multiply(a, mod_p.square(r)); + r = mod_p.multiply(r, a); + + if(n == 1) + return r; + + // find random non quadratic residue z + BigInt z = 2; + while(jacobi(z, p) == 1) // while z quadratic residue + ++z; + + BigInt c = power_mod(z, (q << 1) + 1, p); + + while(n > 1) + { + q = n; + + size_t i = 0; + while(q != 1) + { + q = mod_p.square(q); + ++i; + + if(i >= s) + { + return -BigInt(1); + } + } + + c = power_mod(c, BigInt::power_of_2(s-i-1), p); + r = mod_p.multiply(r, c); + c = mod_p.square(c); + n = mod_p.multiply(n, c); + s = i; + } + + return r; + } + +/* +* Calculate the Jacobi symbol +*/ +int32_t jacobi(const BigInt& a, const BigInt& n) + { + if(n.is_even() || n < 2) + throw Invalid_Argument("jacobi: second argument must be odd and > 1"); + + BigInt x = a % n; + BigInt y = n; + int32_t J = 1; + + while(y > 1) + { + x %= y; + if(x > y / 2) + { + x = y - x; + if(y % 4 == 3) + J = -J; + } + if(x.is_zero()) + return 0; + + size_t shifts = low_zero_bits(x); + x >>= shifts; + if(shifts % 2) + { + word y_mod_8 = y % 8; + if(y_mod_8 == 3 || y_mod_8 == 5) + J = -J; + } + + if(x % 4 == 3 && y % 4 == 3) + J = -J; + std::swap(x, y); + } + return J; + } + +/* +* Multiply-Add Operation +*/ +BigInt mul_add(const BigInt& a, const BigInt& b, const BigInt& c) + { + if(c.is_negative()) + throw Invalid_Argument("mul_add: Third argument must be > 0"); + + BigInt::Sign sign = BigInt::Positive; + if(a.sign() != b.sign()) + sign = BigInt::Negative; + + const size_t a_sw = a.sig_words(); + const size_t b_sw = b.sig_words(); + const size_t c_sw = c.sig_words(); + + BigInt r(sign, std::max(a_sw + b_sw, c_sw) + 1); + secure_vector<word> workspace(r.size()); + + bigint_mul(r.mutable_data(), r.size(), + a.data(), a.size(), a_sw, + b.data(), b.size(), b_sw, + workspace.data(), workspace.size()); + + const size_t r_size = std::max(r.sig_words(), c_sw); + bigint_add2(r.mutable_data(), r_size, c.data(), c_sw); + return r; + } + +/* +* Square a BigInt +*/ +BigInt square(const BigInt& x) + { + BigInt z = x; + secure_vector<word> ws; + z.square(ws); + return z; + } + +/* * Return the number of 0 bits at the end of n */ size_t low_zero_bits(const BigInt& n) diff --git a/src/lib/math/numbertheory/numthry.h b/src/lib/math/numbertheory/numthry.h index be9cd985e..4bf572f5b 100644 --- a/src/lib/math/numbertheory/numthry.h +++ b/src/lib/math/numbertheory/numthry.h @@ -27,30 +27,6 @@ BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a*b)+c") const BigInt& c); /** -* Fused subtract-multiply -* @param a an integer -* @param b an integer -* @param c an integer -* @return (a-b)*c -*/ -BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a-b)*c") - sub_mul(const BigInt& a, - const BigInt& b, - const BigInt& c); - -/** -* Fused multiply-subtract -* @param a an integer -* @param b an integer -* @param c an integer -* @return (a*b)-c -*/ -BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Just use (a*b)-c") - mul_sub(const BigInt& a, - const BigInt& b, - const BigInt& c); - -/** * Return the absolute value * @param n an integer * @return absolute value of n @@ -95,36 +71,6 @@ BigInt BOTAN_PUBLIC_API(2,0) inverse_mod(const BigInt& x, const BigInt& modulus); /** -* Deprecated modular inversion function. Use inverse_mod instead. -* @param x a positive integer -* @param modulus a positive integer -* @return y st (x*y) % modulus == 1 or 0 if no such value -*/ -BigInt BOTAN_DEPRECATED_API("Use inverse_mod") inverse_euclid(const BigInt& x, const BigInt& modulus); - -/** -* Deprecated modular inversion function. Use inverse_mod instead. -*/ -BigInt BOTAN_DEPRECATED_API("Use inverse_mod") ct_inverse_mod_odd_modulus(const BigInt& x, const BigInt& modulus); - -/** -* Return a^-1 * 2^k mod b -* Returns k, between n and 2n -* Not const time -*/ -size_t BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod") - almost_montgomery_inverse(BigInt& result, - const BigInt& a, - const BigInt& b); - -/** -* Call almost_montgomery_inverse and correct the result to a^-1 mod b -*/ -BigInt BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod") - normalized_montgomery_inverse(const BigInt& a, const BigInt& b); - - -/** * Compute the Jacobi symbol. If n is prime, this is equivalent * to the Legendre symbol. * @see http://mathworld.wolfram.com/JacobiSymbol.html @@ -156,14 +102,6 @@ BigInt BOTAN_PUBLIC_API(2,0) power_mod(const BigInt& b, */ BigInt BOTAN_PUBLIC_API(2,0) ressol(const BigInt& x, const BigInt& p); -/* -* Compute -input^-1 mod 2^MP_WORD_BITS. Throws an exception if input -* is even. If input is odd, then input and 2^n are relatively prime -* and an inverse exists. -*/ -word BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use inverse_mod") - monty_inverse(word input); - /** * @param x an integer * @return count of the low zero bits in x, or, equivalently, the @@ -194,18 +132,6 @@ bool BOTAN_PUBLIC_API(2,0) is_prime(const BigInt& n, */ BigInt BOTAN_PUBLIC_API(2,8) is_perfect_square(const BigInt& x); -inline bool BOTAN_DEPRECATED("Use is_prime") - quick_check_prime(const BigInt& n, RandomNumberGenerator& rng) - { return is_prime(n, rng, 32); } - -inline bool BOTAN_DEPRECATED("Use is_prime") - check_prime(const BigInt& n, RandomNumberGenerator& rng) - { return is_prime(n, rng, 56); } - -inline bool BOTAN_DEPRECATED("Use is_prime") - verify_prime(const BigInt& n, RandomNumberGenerator& rng) - { return is_prime(n, rng, 80); } - /** * Randomly generate a prime suitable for discrete logarithm parameters * @param rng a random number generator @@ -249,39 +175,6 @@ BigInt BOTAN_PUBLIC_API(2,0) random_safe_prime(RandomNumberGenerator& rng, size_t bits); /** -* Generate DSA parameters using the FIPS 186 kosherizer -* @param rng a random number generator -* @param p_out where the prime p will be stored -* @param q_out where the prime q will be stored -* @param pbits how long p will be in bits -* @param qbits how long q will be in bits -* @return random seed used to generate this parameter set -*/ -std::vector<uint8_t> BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use DL_Group") -generate_dsa_primes(RandomNumberGenerator& rng, - BigInt& p_out, BigInt& q_out, - size_t pbits, size_t qbits); - -/** -* Generate DSA parameters using the FIPS 186 kosherizer -* @param rng a random number generator -* @param p_out where the prime p will be stored -* @param q_out where the prime q will be stored -* @param pbits how long p will be in bits -* @param qbits how long q will be in bits -* @param seed the seed used to generate the parameters -* @param offset optional offset from seed to start searching at -* @return true if seed generated a valid DSA parameter set, otherwise - false. p_out and q_out are only valid if true was returned. -*/ -bool BOTAN_PUBLIC_API(2,0) BOTAN_DEPRECATED("Use DL_Group") -generate_dsa_primes(RandomNumberGenerator& rng, - BigInt& p_out, BigInt& q_out, - size_t pbits, size_t qbits, - const std::vector<uint8_t>& seed, - size_t offset = 0); - -/** * The size of the PRIMES[] array */ const size_t PRIME_TABLE_SIZE = 6541; diff --git a/src/lib/math/numbertheory/pow_mod.cpp b/src/lib/math/numbertheory/pow_mod.cpp deleted file mode 100644 index 5e94fe586..000000000 --- a/src/lib/math/numbertheory/pow_mod.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/* -* Modular Exponentiation Proxy -* (C) 1999-2007,2012,2018,2019 Jack Lloyd -* 2016 Matthias Gierlings -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/internal/pow_mod.h> -#include <botan/numthry.h> -#include <botan/reducer.h> -#include <botan/internal/monty.h> -#include <botan/internal/monty_exp.h> -#include <botan/internal/rounding.h> -#include <vector> - -namespace Botan { - -class Modular_Exponentiator - { - public: - virtual void set_base(const BigInt&) = 0; - virtual void set_exponent(const BigInt&) = 0; - virtual BigInt execute() const = 0; - virtual Modular_Exponentiator* copy() const = 0; - - Modular_Exponentiator() = default; - Modular_Exponentiator(const Modular_Exponentiator&) = default; - Modular_Exponentiator & operator=(const Modular_Exponentiator&) = default; - virtual ~Modular_Exponentiator() = default; - }; - -namespace { - -/** -* Fixed Window Exponentiator -*/ -class Fixed_Window_Exponentiator final : public Modular_Exponentiator - { - public: - void set_exponent(const BigInt& e) override { m_exp = e; } - void set_base(const BigInt&) override; - BigInt execute() const override; - - Modular_Exponentiator* copy() const override - { return new Fixed_Window_Exponentiator(*this); } - - Fixed_Window_Exponentiator(const BigInt&, Power_Mod::Usage_Hints); - private: - Modular_Reducer m_reducer; - BigInt m_exp; - size_t m_window_bits; - std::vector<BigInt> m_g; - Power_Mod::Usage_Hints m_hints; - }; - -void Fixed_Window_Exponentiator::set_base(const BigInt& base) - { - m_window_bits = Power_Mod::window_bits(m_exp.bits(), base.bits(), m_hints); - - m_g.resize(static_cast<size_t>(1) << m_window_bits); - m_g[0] = 1; - m_g[1] = m_reducer.reduce(base); - - for(size_t i = 2; i != m_g.size(); ++i) - m_g[i] = m_reducer.multiply(m_g[i-1], m_g[1]); - } - -BigInt Fixed_Window_Exponentiator::execute() const - { - const size_t exp_nibbles = (m_exp.bits() + m_window_bits - 1) / m_window_bits; - - BigInt x = 1; - - for(size_t i = exp_nibbles; i > 0; --i) - { - for(size_t j = 0; j != m_window_bits; ++j) - x = m_reducer.square(x); - - const uint32_t nibble = m_exp.get_substring(m_window_bits*(i-1), m_window_bits); - - // not const time: - x = m_reducer.multiply(x, m_g[nibble]); - } - return x; - } - -/* -* Fixed_Window_Exponentiator Constructor -*/ -Fixed_Window_Exponentiator::Fixed_Window_Exponentiator(const BigInt& n, - Power_Mod::Usage_Hints hints) - : m_reducer{Modular_Reducer(n)}, m_exp{}, m_window_bits{}, m_g{}, m_hints{hints} - {} - -class Montgomery_Exponentiator final : public Modular_Exponentiator - { - public: - void set_exponent(const BigInt& e) override { m_e = e; } - void set_base(const BigInt&) override; - BigInt execute() const override; - - Modular_Exponentiator* copy() const override - { return new Montgomery_Exponentiator(*this); } - - Montgomery_Exponentiator(const BigInt&, Power_Mod::Usage_Hints); - private: - BigInt m_p; - Modular_Reducer m_mod_p; - std::shared_ptr<const Montgomery_Params> m_monty_params; - std::shared_ptr<const Montgomery_Exponentation_State> m_monty; - - BigInt m_e; - Power_Mod::Usage_Hints m_hints; - }; - -void Montgomery_Exponentiator::set_base(const BigInt& base) - { - size_t window_bits = Power_Mod::window_bits(m_e.bits(), base.bits(), m_hints); - m_monty = monty_precompute(m_monty_params, m_mod_p.reduce(base), window_bits); - } - -BigInt Montgomery_Exponentiator::execute() const - { - /* - This leaks size of e via loop iterations, not possible to fix without - breaking this API. Round up to avoid leaking fine details. - */ - return monty_execute(*m_monty, m_e, round_up(m_e.bits(), 8)); - } - -Montgomery_Exponentiator::Montgomery_Exponentiator(const BigInt& mod, - Power_Mod::Usage_Hints hints) : - m_p(mod), - m_mod_p(mod), - m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)), - m_hints(hints) - { - } - -} - -/* -* Power_Mod Constructor -*/ -Power_Mod::Power_Mod(const BigInt& n, Usage_Hints hints, bool disable_monty) - { - set_modulus(n, hints, disable_monty); - } - -Power_Mod::~Power_Mod() { /* for ~unique_ptr */ } - -/* -* Power_Mod Copy Constructor -*/ -Power_Mod::Power_Mod(const Power_Mod& other) - { - if(other.m_core.get()) - m_core.reset(other.m_core->copy()); - } - -/* -* Power_Mod Assignment Operator -*/ -Power_Mod& Power_Mod::operator=(const Power_Mod& other) - { - if(this != &other) - { - if(other.m_core) - m_core.reset(other.m_core->copy()); - else - m_core.reset(); - } - return (*this); - } - -/* -* Set the modulus -*/ -void Power_Mod::set_modulus(const BigInt& n, Usage_Hints hints, bool disable_monty) const - { - // Allow set_modulus(0) to mean "drop old state" - - m_core.reset(); - - if(n != 0) - { - if(n.is_odd() && disable_monty == false) - m_core.reset(new Montgomery_Exponentiator(n, hints)); - else - m_core.reset(new Fixed_Window_Exponentiator(n, hints)); - } - } - -/* -* Set the base -*/ -void Power_Mod::set_base(const BigInt& b) const - { - if(b.is_negative()) - throw Invalid_Argument("Power_Mod::set_base: arg must be non-negative"); - - if(!m_core) - throw Internal_Error("Power_Mod::set_base: m_core was NULL"); - m_core->set_base(b); - } - -/* -* Set the exponent -*/ -void Power_Mod::set_exponent(const BigInt& e) const - { - if(e.is_negative()) - throw Invalid_Argument("Power_Mod::set_exponent: arg must be > 0"); - - if(!m_core) - throw Internal_Error("Power_Mod::set_exponent: m_core was NULL"); - m_core->set_exponent(e); - } - -/* -* Compute the result -*/ -BigInt Power_Mod::execute() const - { - if(!m_core) - throw Internal_Error("Power_Mod::execute: m_core was NULL"); - return m_core->execute(); - } - -/* -* Try to choose a good window size -*/ -size_t Power_Mod::window_bits(size_t exp_bits, size_t, - Power_Mod::Usage_Hints hints) - { - static const size_t wsize[][2] = { - { 1434, 7 }, - { 539, 6 }, - { 197, 4 }, - { 70, 3 }, - { 17, 2 }, - { 0, 0 } - }; - - size_t window_bits = 1; - - if(exp_bits) - { - for(size_t j = 0; wsize[j][0]; ++j) - { - if(exp_bits >= wsize[j][0]) - { - window_bits += wsize[j][1]; - break; - } - } - } - - if(hints & Power_Mod::BASE_IS_FIXED) - window_bits += 2; - if(hints & Power_Mod::EXP_IS_LARGE) - ++window_bits; - - return window_bits; - } - -namespace { - -/* -* Choose potentially useful hints -*/ -Power_Mod::Usage_Hints choose_base_hints(const BigInt& b, const BigInt& n) - { - if(b == 2) - return Power_Mod::Usage_Hints(Power_Mod::BASE_IS_2 | - Power_Mod::BASE_IS_SMALL); - - const size_t b_bits = b.bits(); - const size_t n_bits = n.bits(); - - if(b_bits < n_bits / 32) - return Power_Mod::BASE_IS_SMALL; - if(b_bits > n_bits / 4) - return Power_Mod::BASE_IS_LARGE; - - return Power_Mod::NO_HINTS; - } - -/* -* Choose potentially useful hints -*/ -Power_Mod::Usage_Hints choose_exp_hints(const BigInt& e, const BigInt& n) - { - const size_t e_bits = e.bits(); - const size_t n_bits = n.bits(); - - if(e_bits < n_bits / 32) - return Power_Mod::BASE_IS_SMALL; - if(e_bits > n_bits / 4) - return Power_Mod::BASE_IS_LARGE; - return Power_Mod::NO_HINTS; - } - -} - -/* -* Fixed_Exponent_Power_Mod Constructor -*/ -Fixed_Exponent_Power_Mod::Fixed_Exponent_Power_Mod(const BigInt& e, - const BigInt& n, - Usage_Hints hints) : - Power_Mod(n, Usage_Hints(hints | EXP_IS_FIXED | choose_exp_hints(e, n))) - { - set_exponent(e); - } - -/* -* Fixed_Base_Power_Mod Constructor -*/ -Fixed_Base_Power_Mod::Fixed_Base_Power_Mod(const BigInt& b, const BigInt& n, - Usage_Hints hints) : - Power_Mod(n, Usage_Hints(hints | BASE_IS_FIXED | choose_base_hints(b, n))) - { - set_base(b); - } - -} diff --git a/src/lib/math/numbertheory/pow_mod.h b/src/lib/math/numbertheory/pow_mod.h deleted file mode 100644 index 5581752ea..000000000 --- a/src/lib/math/numbertheory/pow_mod.h +++ /dev/null @@ -1,120 +0,0 @@ -/* -* Modular Exponentiator -* (C) 1999-2007 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#ifndef BOTAN_POWER_MOD_H_ -#define BOTAN_POWER_MOD_H_ - -#include <botan/bigint.h> - -namespace Botan { - -class Modular_Exponentiator; - -/** -* Modular Exponentiator Proxy -*/ -class BOTAN_TEST_API Power_Mod - { - public: - - enum Usage_Hints { - NO_HINTS = 0x0000, - - BASE_IS_FIXED = 0x0001, - BASE_IS_SMALL = 0x0002, - BASE_IS_LARGE = 0x0004, - BASE_IS_2 = 0x0008, - - EXP_IS_FIXED = 0x0100, - EXP_IS_SMALL = 0x0200, - EXP_IS_LARGE = 0x0400 - }; - - /* - * Try to choose a good window size - */ - static size_t window_bits(size_t exp_bits, size_t base_bits, - Power_Mod::Usage_Hints hints); - - /** - * @param modulus the modulus - * @param hints Passed to set_modulus if modulus > 0 - * @param disable_montgomery_arith Disables use of Montgomery - * representation. Likely only useful for testing. - */ - void set_modulus(const BigInt& modulus, - Usage_Hints hints = NO_HINTS, - bool disable_montgomery_arith = false) const; - - /** - * Set the base - */ - void set_base(const BigInt& base) const; - - /** - * Set the exponent - */ - void set_exponent(const BigInt& exponent) const; - - /** - * All three of the above functions must have already been called. - * @return result of g^x%p - */ - BigInt execute() const; - - Power_Mod& operator=(const Power_Mod&); - - /** - * @param modulus Optionally call set_modulus - * @param hints Passed to set_modulus if modulus > 0 - * @param disable_montgomery_arith Disables use of Montgomery - * representation. Likely only useful for testing. - */ - Power_Mod(const BigInt& modulus = 0, - Usage_Hints hints = NO_HINTS, - bool disable_montgomery_arith = false); - Power_Mod(const Power_Mod&); - virtual ~Power_Mod(); - private: - mutable std::unique_ptr<Modular_Exponentiator> m_core; - }; - -/** -* Fixed Exponent Modular Exponentiator Proxy -*/ -class Fixed_Exponent_Power_Mod final : public Power_Mod - { - public: - BigInt operator()(const BigInt& b) const - { set_base(b); return execute(); } - - Fixed_Exponent_Power_Mod() = default; - - Fixed_Exponent_Power_Mod(const BigInt& exponent, - const BigInt& modulus, - Usage_Hints hints = NO_HINTS); - }; - -/** -* Fixed Base Modular Exponentiator Proxy -*/ -class Fixed_Base_Power_Mod final : public Power_Mod - { - public: - BigInt operator()(const BigInt& e) const - { set_exponent(e); return execute(); } - - Fixed_Base_Power_Mod() = default; - - Fixed_Base_Power_Mod(const BigInt& base, - const BigInt& modulus, - Usage_Hints hints = NO_HINTS); - }; - -} - -#endif diff --git a/src/lib/math/numbertheory/primality.h b/src/lib/math/numbertheory/primality.h index db7a76a74..8a602bbad 100644 --- a/src/lib/math/numbertheory/primality.h +++ b/src/lib/math/numbertheory/primality.h @@ -9,6 +9,7 @@ #include <botan/types.h> #include <memory> +#include <vector> namespace Botan { @@ -95,6 +96,38 @@ bool BOTAN_TEST_API is_miller_rabin_probable_prime(const BigInt& n, RandomNumberGenerator& rng, size_t t); +/** +* Generate DSA parameters using the FIPS 186 kosherizer +* @param rng a random number generator +* @param p_out where the prime p will be stored +* @param q_out where the prime q will be stored +* @param pbits how long p will be in bits +* @param qbits how long q will be in bits +* @return random seed used to generate this parameter set +*/ +std::vector<uint8_t> +generate_dsa_primes(RandomNumberGenerator& rng, + BigInt& p_out, BigInt& q_out, + size_t pbits, size_t qbits); + +/** +* Generate DSA parameters using the FIPS 186 kosherizer +* @param rng a random number generator +* @param p_out where the prime p will be stored +* @param q_out where the prime q will be stored +* @param pbits how long p will be in bits +* @param qbits how long q will be in bits +* @param seed the seed used to generate the parameters +* @param offset optional offset from seed to start searching at +* @return true if seed generated a valid DSA parameter set, otherwise + false. p_out and q_out are only valid if true was returned. +*/ +bool BOTAN_TEST_API generate_dsa_primes(RandomNumberGenerator& rng, + BigInt& p_out, BigInt& q_out, + size_t pbits, size_t qbits, + const std::vector<uint8_t>& seed, + size_t offset = 0); + } #endif diff --git a/src/lib/math/numbertheory/ressol.cpp b/src/lib/math/numbertheory/ressol.cpp deleted file mode 100644 index de89e0384..000000000 --- a/src/lib/math/numbertheory/ressol.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/* -* (C) 2007,2008 Falko Strenzke, FlexSecure GmbH -* (C) 2008 Jack Lloyd -* -* Botan is released under the Simplified BSD License (see license.txt) -*/ - -#include <botan/numthry.h> -#include <botan/reducer.h> - -namespace Botan { - -/* -* Tonelli-Shanks algorithm -*/ -BigInt ressol(const BigInt& a, const BigInt& p) - { - if(p <= 1 || p.is_even()) - throw Invalid_Argument("ressol: invalid prime"); - - if(a == 0) - return 0; - else if(a < 0) - throw Invalid_Argument("ressol: value to solve for must be positive"); - else if(a >= p) - throw Invalid_Argument("ressol: value to solve for must be less than p"); - - if(p == 2) - return a; - - if(jacobi(a, p) != 1) // not a quadratic residue - return -BigInt(1); - - if(p % 4 == 3) // The easy case - { - return power_mod(a, ((p+1) >> 2), p); - } - - size_t s = low_zero_bits(p - 1); - BigInt q = p >> s; - - q -= 1; - q >>= 1; - - Modular_Reducer mod_p(p); - - BigInt r = power_mod(a, q, p); - BigInt n = mod_p.multiply(a, mod_p.square(r)); - r = mod_p.multiply(r, a); - - if(n == 1) - return r; - - // find random non quadratic residue z - BigInt z = 2; - while(jacobi(z, p) == 1) // while z quadratic residue - ++z; - - BigInt c = power_mod(z, (q << 1) + 1, p); - - while(n > 1) - { - q = n; - - size_t i = 0; - while(q != 1) - { - q = mod_p.square(q); - ++i; - - if(i >= s) - { - return -BigInt(1); - } - } - - c = power_mod(c, BigInt::power_of_2(s-i-1), p); - r = mod_p.multiply(r, c); - c = mod_p.square(c); - n = mod_p.multiply(n, c); - s = i; - } - - return r; - } - -} diff --git a/src/lib/pubkey/dl_group/dl_group.cpp b/src/lib/pubkey/dl_group/dl_group.cpp index f147c33fb..0de5a5de4 100644 --- a/src/lib/pubkey/dl_group/dl_group.cpp +++ b/src/lib/pubkey/dl_group/dl_group.cpp @@ -8,6 +8,7 @@ #include <botan/dl_group.h> #include <botan/numthry.h> #include <botan/reducer.h> +#include <botan/internal/primality.h> #include <botan/internal/monty.h> #include <botan/internal/divide.h> #include <botan/der_enc.h> diff --git a/src/lib/pubkey/ec_group/curve_gfp.cpp b/src/lib/pubkey/ec_group/curve_gfp.cpp index da049aebb..c4ac23e98 100644 --- a/src/lib/pubkey/ec_group/curve_gfp.cpp +++ b/src/lib/pubkey/ec_group/curve_gfp.cpp @@ -12,6 +12,7 @@ #include <botan/reducer.h> #include <botan/internal/mp_core.h> #include <botan/internal/mp_asmi.h> +#include <botan/internal/monty.h> namespace Botan { diff --git a/src/tests/test_bigint.cpp b/src/tests/test_bigint.cpp index cbca5667e..1552fad08 100644 --- a/src/tests/test_bigint.cpp +++ b/src/tests/test_bigint.cpp @@ -12,7 +12,6 @@ #include <botan/internal/divide.h> #include <botan/internal/primality.h> #include <botan/reducer.h> - #include <botan/internal/pow_mod.h> #include <botan/internal/parsing.h> #include "test_rng.h" #endif @@ -535,38 +534,6 @@ class BigInt_Powmod_Test final : public Text_Based_Test const BigInt expected = vars.get_req_bn("Output"); result.test_eq("power_mod", Botan::power_mod(base, exponent, modulus), expected); - - /* - * Only the basic power_mod interface supports negative base - */ - if(base.is_negative()) - return result; - - Botan::Power_Mod pow_mod1(modulus); - - pow_mod1.set_base(base); - pow_mod1.set_exponent(exponent); - result.test_eq("pow_mod1", pow_mod1.execute(), expected); - - Botan::Power_Mod pow_mod2(modulus); - - // Reverses ordering which affects window size - pow_mod2.set_exponent(exponent); - pow_mod2.set_base(base); - result.test_eq("pow_mod2", pow_mod2.execute(), expected); - result.test_eq("pow_mod2 #2", pow_mod2.execute(), expected); - - if(modulus.is_odd()) - { - // TODO: test different hints - // also TODO: remove bogus hinting arguments :) - Botan::Power_Mod pow_mod3(modulus, Botan::Power_Mod::NO_HINTS, /*disable_montgomery=*/true); - - pow_mod3.set_exponent(exponent); - pow_mod3.set_base(base); - result.test_eq("pow_mod_fixed_window", pow_mod3.execute(), expected); - } - return result; } }; @@ -673,13 +640,6 @@ class BigInt_InvMod_Test final : public Text_Based_Test } */ - if(mod.is_odd() && a_inv != 0) - { - result.test_eq("normalized_montgomery_inverse", - normalized_montgomery_inverse(a, mod), - expected); - } - return result; } }; |