8#include <botan/dl_group.h>
9#include <botan/numthry.h>
10#include <botan/reducer.h>
11#include <botan/internal/primality.h>
12#include <botan/internal/monty.h>
13#include <botan/internal/divide.h>
14#include <botan/der_enc.h>
15#include <botan/ber_dec.h>
17#include <botan/internal/workfactor.h>
18#include <botan/internal/monty_exp.h>
19#include <botan/internal/fmt.h>
24class DL_Group_Data
final
27 DL_Group_Data(
const BigInt& p,
const BigInt& q,
const BigInt& g,
DL_Group_Source source) :
28 m_p(p), m_q(q), m_g(g),
31 m_monty_params(
std::make_shared<Montgomery_Params>(m_p, m_mod_p)),
41 ~DL_Group_Data() =
default;
43 DL_Group_Data(
const DL_Group_Data& other) =
delete;
44 DL_Group_Data(DL_Group_Data&& other) =
delete;
45 DL_Group_Data& operator=(
const DL_Group_Data& other) =
delete;
46 DL_Group_Data& operator=(DL_Group_Data&& other) =
delete;
48 const BigInt& p()
const {
return m_p; }
49 const BigInt& q()
const {
return m_q; }
50 const BigInt& g()
const {
return m_g; }
52 BigInt mod_p(
const BigInt& x)
const {
return m_mod_p.reduce(x); }
54 BigInt multiply_mod_p(
const BigInt& x,
const BigInt&
y)
const
56 return m_mod_p.multiply(x,
y);
59 BigInt mod_q(
const BigInt& x)
const {
return m_mod_q.reduce(x); }
61 BigInt multiply_mod_q(
const BigInt& x,
const BigInt&
y)
const
63 return m_mod_q.multiply(x,
y);
66 BigInt square_mod_q(
const BigInt& x)
const
68 return m_mod_q.square(x);
71 std::shared_ptr<const Montgomery_Params> monty_params_p()
const
72 {
return m_monty_params; }
74 size_t p_bits()
const {
return m_p_bits; }
75 size_t q_bits()
const {
return m_q_bits; }
76 size_t p_bytes()
const {
return (m_p_bits + 7) / 8; }
77 size_t q_bytes()
const {
return (m_q_bits + 7) / 8; }
79 size_t estimated_strength()
const {
return m_estimated_strength; }
81 size_t exponent_bits()
const {
return m_exponent_bits; }
83 BigInt power_g_p(
const BigInt& k,
size_t max_k_bits)
const
88 BigInt power_g_p_vartime(
const BigInt& k)
const
93 BigInt power_b_p(
const BigInt& b,
const BigInt& k,
size_t max_k_bits)
const
95 return monty_exp(m_monty_params, b, k, max_k_bits);
98 BigInt power_b_p_vartime(
const BigInt& b,
const BigInt& k)
const
103 bool q_is_set()
const {
return m_q_bits > 0; }
105 void assert_q_is_set(std::string_view function)
const
107 if(q_is_set() ==
false)
108 throw Invalid_State(
fmt(
"DL_Group::{}: q is not set for this group", function));
117 Modular_Reducer m_mod_p;
118 Modular_Reducer m_mod_q;
119 std::shared_ptr<const Montgomery_Params> m_monty_params;
120 std::shared_ptr<const Montgomery_Exponentation_State> m_monty;
123 size_t m_estimated_strength;
124 size_t m_exponent_bits;
129std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(
const uint8_t data[],
size_t data_len,
135 BER_Decoder decoder(data, data_len);
136 BER_Decoder ber = decoder.start_sequence();
150 .discard_remaining();
157 .discard_remaining();
160 throw Invalid_Argument(
"Unknown DL_Group encoding");
162 return std::make_shared<DL_Group_Data>(p, q, g,
source);
166std::shared_ptr<DL_Group_Data>
167DL_Group::load_DL_group_info(
const char* p_str,
171 const BigInt p(p_str);
172 const BigInt q(q_str);
173 const BigInt g(g_str);
179std::shared_ptr<DL_Group_Data>
180DL_Group::load_DL_group_info(
const char* p_str,
183 const BigInt p(p_str);
184 const BigInt q = (p - 1) / 2;
185 const BigInt g(g_str);
194 if(label ==
"DH PARAMETERS")
196 else if(label ==
"DSA PARAMETERS")
198 else if(label ==
"X942 DH PARAMETERS" || label ==
"X9.42 DH PARAMETERS")
201 throw Decoding_Error(
fmt(
"DL_Group: Unknown PEM label '{}'", label));
214 if(m_data ==
nullptr)
227 if(m_data ==
nullptr)
252 throw Internal_Error(
"DL_Group: Couldn't create a suitable generator");
261 PrimeType type,
size_t pbits,
size_t qbits)
267 throw Invalid_Argument(
fmt(
"DL_Group: requested q size {} is too big for p {}", qbits, pbits));
271 if(qbits != 0 && qbits != pbits - 1)
272 throw Invalid_Argument(
"Cannot create strong-prime DL_Group with specified q bits");
275 const BigInt q = (p - 1) / 2;
304 while(p.
bits() != pbits || !
is_prime(p, rng, 128,
true))
306 X.randomize(rng, pbits);
310 const BigInt g = make_dsa_generator(p, q);
316 qbits = ((pbits <= 1024) ? 160 : 256);
320 const BigInt g = make_dsa_generator(p, q);
333 const std::vector<uint8_t>& seed,
334 size_t pbits,
size_t qbits)
339 throw Invalid_Argument(
"DL_Group: The seed given does not generate a DSA group");
341 BigInt g = make_dsa_generator(p, q);
362const DL_Group_Data& DL_Group::data()
const
380 if(data().power_b_p_vartime(
y, q) != 1)
405 if(y <= 1 || y >= p || x <= 1 || x >= p)
422 if(!strong && from_builtin)
429 if(g < 2 || p < 3 || q < 0)
432 const size_t test_prob = 128;
435 if(!
is_prime(p, rng, test_prob, is_randomly_generated))
446 if(data().power_g_p_vartime(q) != 1)
450 if(!
is_prime(q, rng, test_prob, is_randomly_generated))
457 if(!from_builtin && !is_randomly_generated)
462 const size_t upper_bound = strong ? 1000 : 100;
464 for(
size_t i = 2; i != upper_bound; ++i)
503 return data().monty_params_p();
508 return data().q_is_set();
513 return data().p_bits();
518 return data().p_bytes();
523 data().assert_q_is_set(
"q_bits");
524 return data().q_bits();
529 data().assert_q_is_set(
"q_bytes");
530 return data().q_bytes();
535 return data().estimated_strength();
540 return data().exponent_bits();
551 return data().mod_p(x);
556 return data().multiply_mod_p(x,
y);
561 data().assert_q_is_set(
"inverse_mod_q");
568 data().assert_q_is_set(
"mod_q");
569 return data().mod_q(x);
574 data().assert_q_is_set(
"multiply_mod_q");
575 return data().multiply_mod_q(x,
y);
580 data().assert_q_is_set(
"multiply_mod_q");
586 data().assert_q_is_set(
"square_mod_q");
587 return data().square_mod_q(x);
597 return data().power_g_p(x, x.
bits());
602 return data().power_g_p(x, max_x_bits);
612 return data().power_b_p(b, x, max_x_bits);
617 return data().source();
626 throw Encoding_Error(
"Cannot encode DL_Group in ANSI formats when q param is missing");
628 std::vector<uint8_t> output;
665 const std::vector<uint8_t> encoding =
DER_encode(format);
static BigInt from_word(word n)
DER_Encoder & start_sequence()
DER_Encoder & encode(bool b)
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
BigInt mod_p(const BigInt &x) const
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
std::shared_ptr< const Montgomery_Params > monty_params_p() const
std::string PEM_encode(DL_Group_Format format) const
const BigInt & get_p() const
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
void BER_decode(const std::vector< uint8_t > &ber, DL_Group_Format format)
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
static DL_Group DL_Group_from_PEM(std::string_view pem)
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
BigInt reduce(const BigInt &x) const
int(* final)(unsigned char *, CTX *)
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)
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
void vartime_divide(const BigInt &x, const BigInt &y_arg, BigInt &q_out, BigInt &r_out)
BigInt monty_exp(std::shared_ptr< const Montgomery_Params > params_p, const BigInt &g, const BigInt &k, size_t max_k_bits)
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)
const size_t PRIME_TABLE_SIZE
size_t dl_work_factor(size_t bits)
BigInt monty_multi_exp(const std::shared_ptr< const Montgomery_Params > ¶ms_p, const BigInt &x_bn, const BigInt &z1, const BigInt &y_bn, const BigInt &z2)
bool is_prime(const BigInt &n, RandomNumberGenerator &rng, size_t prob, bool is_random)
std::vector< T > unlock(const secure_vector< T > &in)
BigInt monty_exp_vartime(std::shared_ptr< const Montgomery_Params > params_p, const BigInt &g, const BigInt &k)
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)
size_t dl_exponent_size(size_t bits)
BigInt monty_execute_vartime(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k)
int32_t jacobi(const BigInt &a, const BigInt &n)
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
BigInt monty_execute(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k, size_t max_k_bits)
std::shared_ptr< const Montgomery_Exponentation_State > monty_precompute(const std::shared_ptr< const Montgomery_Params > ¶ms, const BigInt &g, size_t window_bits, bool const_time)