8#include <botan/dl_group.h>
10#include <botan/ber_dec.h>
11#include <botan/der_enc.h>
12#include <botan/numthry.h>
14#include <botan/internal/barrett.h>
15#include <botan/internal/divide.h>
16#include <botan/internal/fmt.h>
17#include <botan/internal/mod_inv.h>
18#include <botan/internal/monty.h>
19#include <botan/internal/monty_exp.h>
20#include <botan/internal/primality.h>
21#include <botan/internal/workfactor.h>
28void check_dl_group_params(
const BigInt& p,
const BigInt& g) {
29 if(p.signum() <= 0 || p.is_even() || p.bits() < 3 || p.bits() > 16384) {
32 if(g.signum() <= 0 || g < 2 || g >= p) {
38 check_dl_group_params(p, g);
39 if(q.signum() <= 0 || q.is_even() || q.bits() >= p.bits()) {
46class DL_Group_Data final {
48 static std::shared_ptr<DL_Group_Data> create(
const BigInt& p,
52 check_dl_group_params(p, q, g);
53 return std::make_shared<DL_Group_Data>(p, q, g, source);
56 static std::shared_ptr<DL_Group_Data> create(
const BigInt& p,
const BigInt& g,
DL_Group_Source source) {
57 check_dl_group_params(p, g);
58 return std::make_shared<DL_Group_Data>(p, g, source);
63 DL_Group_Data(
const BigInt& p,
const BigInt& q,
const BigInt& g,
DL_Group_Source source) :
67 m_mod_p(Barrett_Reduction::for_public_modulus(p)),
68 m_mod_q(Barrett_Reduction::for_public_modulus(q)),
69 m_monty_params(m_p, m_mod_p),
79 DL_Group_Data(
const BigInt& p,
const BigInt& g,
DL_Group_Source source) :
82 m_mod_p(Barrett_Reduction::for_public_modulus(p)),
83 m_monty_params(m_p, m_mod_p),
91 ~DL_Group_Data() =
default;
93 DL_Group_Data(
const DL_Group_Data& other) =
delete;
94 DL_Group_Data(DL_Group_Data&& other) =
delete;
95 DL_Group_Data& operator=(
const DL_Group_Data& other) =
delete;
96 DL_Group_Data& operator=(DL_Group_Data&& other) =
delete;
98 const BigInt& p()
const {
return m_p; }
100 const BigInt& q()
const {
return m_q; }
102 const BigInt& g()
const {
return m_g; }
104 const Barrett_Reduction& reducer_mod_p()
const {
return m_mod_p; }
106 const Barrett_Reduction& reducer_mod_q()
const {
111 const Montgomery_Params& monty_params_p()
const {
return m_monty_params; }
113 size_t p_bits()
const {
return m_p_bits; }
115 size_t q_bits()
const {
return m_q_bits; }
117 size_t p_bytes()
const {
return (m_p_bits + 7) / 8; }
119 size_t q_bytes()
const {
return (m_q_bits + 7) / 8; }
121 size_t estimated_strength()
const {
return m_estimated_strength; }
123 size_t exponent_bits()
const {
return m_exponent_bits; }
125 BigInt power_g_p(
const BigInt& k,
size_t max_k_bits)
const {
131 BigInt power_b_p(
const BigInt& b,
const BigInt& k,
size_t max_k_bits)
const {
135 BigInt power_b_p_vartime(
const BigInt& b,
const BigInt& k)
const {
139 bool q_is_set()
const {
return m_q_bits > 0; }
141 void assert_q_is_set(std::string_view function)
const {
143 throw Invalid_State(
fmt(
"DL_Group::{}: q is not set for this group", function));
153 Barrett_Reduction m_mod_p;
154 std::optional<Barrett_Reduction> m_mod_q;
155 Montgomery_Params m_monty_params;
156 std::shared_ptr<const Montgomery_Exponentiation_State> m_monty;
159 size_t m_estimated_strength;
160 size_t m_exponent_bits;
165std::shared_ptr<DL_Group_Data> DL_Group::DER_decode_DL_group(
const std::span<const uint8_t> data,
169 BER_Decoder inner = decoder.start_sequence();
178 inner.decode(p).decode(q).decode(g).verify_end();
179 return DL_Group_Data::create(p, q, g,
source);
187 inner.decode(p).decode(g).decode(q).discard_remaining();
188 return DL_Group_Data::create(p, q, g,
source);
195 inner.decode(p).decode(g).discard_remaining();
196 return DL_Group_Data::create(p, g,
source);
198 throw Invalid_Argument(
"Unknown DL_Group encoding");
203std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(
const char* p_str,
const char* q_str,
const char* g_str) {
204 const BigInt p(p_str);
205 const BigInt q(q_str);
206 const BigInt g(g_str);
216std::shared_ptr<DL_Group_Data> DL_Group::load_DL_group_info(
const char* p_str,
const char* g_str) {
217 const BigInt p(p_str);
218 const BigInt q = (p - 1) / 2;
219 const BigInt g(g_str);
227 if(label ==
"DH PARAMETERS") {
229 }
else if(label ==
"DSA PARAMETERS") {
231 }
else if(label ==
"X942 DH PARAMETERS" || label ==
"X9.42 DH PARAMETERS") {
247 if(m_data ==
nullptr) {
257 if(m_data ==
nullptr) {
290 if(e == 0 || r > 0) {
296 const Montgomery_Params params(p, mod_p);
305 throw Internal_Error(
"DL_Group: Couldn't create a suitable generator");
319 throw Invalid_Argument(
fmt(
"DL_Group: requested q size {} is too big for p {}", qbits, pbits));
323 if(qbits != 0 && qbits != pbits - 1) {
324 throw Invalid_Argument(
"Cannot create strong-prime DL_Group with specified q bits");
328 const BigInt q = (p - 1) / 2;
352 while(p.
bits() != pbits || !
is_prime(p, rng, 128,
true)) {
355 p = X - (X % q2) + 1;
358 const BigInt g = make_dsa_generator(p, q);
362 qbits = ((pbits <= 1024) ? 160 : 256);
368 const BigInt g = make_dsa_generator(p, q);
383 throw Invalid_Argument(
"DL_Group: The seed given does not generate a DSA group");
386 const BigInt g = make_dsa_generator(p, q);
409const DL_Group_Data& DL_Group::data()
const {
414 throw Invalid_State(
"DL_Group uninitialized");
421 if(y <= 1 || y >= p) {
426 if(data().power_b_p_vartime(y, q) != 1) {
438 if(x <= 1 || x >= p) {
452 if(y <= 1 || y >= p || x <= 1 || x >= p) {
469 if(!strong && from_builtin) {
477 if(g < 2 || p < 3 || q < 0) {
481 const size_t test_prob = 128;
484 if(!
is_prime(p, rng, test_prob, is_randomly_generated)) {
489 if((p - 1) % q != 0) {
492 if(data().power_g_p_vartime(q) != 1) {
495 if(!
is_prime(q, rng, test_prob, is_randomly_generated)) {
499 if(!from_builtin && !is_randomly_generated) {
503 const size_t upper_bound = strong ? 1000 : 100;
505 for(
size_t i = 2; i != upper_bound; ++i) {
538 return data().monty_params_p();
542 return data().q_is_set();
546 return data().p_bits();
550 return data().p_bytes();
554 data().assert_q_is_set(
"q_bits");
555 return data().q_bits();
559 data().assert_q_is_set(
"q_bytes");
560 return data().q_bytes();
564 return data().estimated_strength();
568 return data().exponent_bits();
577 return data().reducer_mod_p().reduce(x);
581 return data().reducer_mod_p().multiply(x, y);
585 return data().reducer_mod_p();
589 data().assert_q_is_set(
"inverse_mod_q");
595 data().assert_q_is_set(
"mod_q");
596 return data().reducer_mod_q().reduce(x);
600 data().assert_q_is_set(
"multiply_mod_q");
601 return data().reducer_mod_q().multiply(x, y);
605 data().assert_q_is_set(
"multiply_mod_q");
610 data().assert_q_is_set(
"square_mod_q");
611 return data().reducer_mod_q().
square(x);
619 return data().power_g_p(x, max_x_bits);
627 return data().power_b_p(b, x, max_x_bits);
631 return data().source();
639 throw Encoding_Error(
"Cannot encode DL_Group in ANSI formats when q param is missing");
642 std::vector<uint8_t> output;
662 const std::vector<uint8_t> encoding =
DER_encode(format);
#define BOTAN_STATE_CHECK(expr)
static Barrett_Reduction for_public_modulus(const BigInt &m)
void randomize(RandomNumberGenerator &rng, size_t bitsize, bool set_high_bit=true)
static BigInt from_word(word n)
BigInt & square(secure_vector< word > &ws)
DER_Encoder & start_sequence()
DER_Encoder & encode(bool b)
const Barrett_Reduction & _reducer_mod_p() const
bool verify_private_element(const BigInt &x) const
std::vector< uint8_t > DER_encode(DL_Group_Format format) const
BigInt power_g_p(const BigInt &x) const
static DL_Group from_PEM(std::string_view pem)
BigInt mod_p(const BigInt &x) const
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
std::string PEM_encode(DL_Group_Format format) const
const BigInt & get_p() const
static DL_Group from_name(std::string_view name)
BigInt multi_exponentiate(const BigInt &x, const BigInt &y, const BigInt &z) const
bool verify_public_element(const BigInt &y) const
BigInt square_mod_q(const BigInt &x) const
BigInt inverse_mod_q(const BigInt &x) const
bool verify_element_pair(const BigInt &y, const BigInt &x) const
size_t estimated_strength() const
DL_Group_Source source() const
BigInt multiply_mod_q(const BigInt &x, const BigInt &y) const
BigInt inverse_mod_p(const BigInt &x) const
const Montgomery_Params & _monty_params_p() const
BigInt power_b_p(const BigInt &b, const BigInt &x, size_t max_x_bits) const
size_t exponent_bits() const
BigInt mod_q(const BigInt &x) const
bool verify_group(RandomNumberGenerator &rng, bool strong=true) const
const BigInt & get_g() const
static std::shared_ptr< DL_Group_Data > DL_group_info(std::string_view name)
const BigInt & get_q() const
std::string encode(const uint8_t der[], size_t length, std::string_view label, size_t width)
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
void vartime_divide(const BigInt &x, const BigInt &y_arg, BigInt &q_out, BigInt &r_out)
int32_t jacobi(BigInt a, BigInt n)
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
std::string fmt(std::string_view format, const T &... args)
Montgomery_Int monty_exp_vartime(const Montgomery_Params ¶ms_p, const BigInt &g, const BigInt &k)
size_t dl_exponent_size(size_t p_bits)
std::shared_ptr< const Montgomery_Exponentiation_State > monty_precompute(const Montgomery_Int &g, size_t window_bits, bool const_time)
const size_t PRIME_TABLE_SIZE
size_t dl_work_factor(size_t bits)
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
BigInt inverse_mod_public_prime(const BigInt &x, const BigInt &p)
Montgomery_Int monty_multi_exp(const Montgomery_Params ¶ms_p, const BigInt &x_bn, const BigInt &z1, const BigInt &y_bn, const BigInt &z2)
Montgomery_Int monty_execute_vartime(const Montgomery_Exponentiation_State &precomputed_state, const BigInt &k)
std::vector< T > unlock(const secure_vector< T > &in)
bool generate_dsa_primes(RandomNumberGenerator &rng, BigInt &p, BigInt &q, size_t pbits, size_t qbits, const std::vector< uint8_t > &seed_c, size_t offset)
Montgomery_Int monty_execute(const Montgomery_Exponentiation_State &precomputed_state, const BigInt &k, size_t max_k_bits)
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
Montgomery_Int monty_exp(const Montgomery_Params ¶ms_p, const BigInt &g, const BigInt &k, size_t max_k_bits)