8 #include <botan/dl_group.h>
9 #include <botan/numthry.h>
10 #include <botan/reducer.h>
11 #include <botan/monty.h>
12 #include <botan/der_enc.h>
13 #include <botan/ber_dec.h>
14 #include <botan/pem.h>
15 #include <botan/workfactor.h>
16 #include <botan/internal/monty_exp.h>
20 class DL_Group_Data
final
23 DL_Group_Data(
const BigInt& p,
const BigInt& q,
const BigInt& g) :
36 ~DL_Group_Data() =
default;
38 DL_Group_Data(
const DL_Group_Data& other) =
delete;
39 DL_Group_Data& operator=(
const DL_Group_Data& other) =
delete;
41 const BigInt& p()
const {
return m_p; }
42 const BigInt& q()
const {
return m_q; }
43 const BigInt& g()
const {
return m_g; }
45 BigInt mod_p(
const BigInt& x)
const {
return m_mod_p.reduce(x); }
47 BigInt multiply_mod_p(
const BigInt& x,
const BigInt& y)
const
52 BigInt mod_q(
const BigInt& x)
const {
return m_mod_q.reduce(x); }
54 BigInt multiply_mod_q(
const BigInt& x,
const BigInt& y)
const
56 return m_mod_q.multiply(x, y);
59 BigInt square_mod_q(
const BigInt& x)
const
61 return m_mod_q.square(x);
64 std::shared_ptr<const Montgomery_Params> monty_params_p()
const
67 size_t p_bits()
const {
return m_p_bits; }
68 size_t q_bits()
const {
return m_q_bits; }
69 size_t p_bytes()
const {
return (m_p_bits + 7) / 8; }
70 size_t q_bytes()
const {
return (m_q_bits + 7) / 8; }
72 size_t estimated_strength()
const {
return m_estimated_strength; }
74 size_t exponent_bits()
const {
return m_exponent_bits; }
76 BigInt power_g_p(
const BigInt& k,
size_t max_k_bits)
const
81 bool q_is_set()
const {
return m_q_bits > 0; }
83 void assert_q_is_set(
const std::string&
function)
const
85 if(q_is_set() ==
false)
86 throw Invalid_State(
"DL_Group::" +
function +
" q is not set for this group");
94 Modular_Reducer m_mod_q;
96 std::shared_ptr<const Montgomery_Exponentation_State>
m_monty;
99 size_t m_estimated_strength;
100 size_t m_exponent_bits;
104 std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(
const uint8_t data[],
size_t data_len,
DL_Group::Format format)
108 BER_Decoder decoder(data, data_len);
109 BER_Decoder ber = decoder.start_cons(
SEQUENCE);
123 .discard_remaining();
130 .discard_remaining();
133 throw Invalid_Argument(
"Unknown DL_Group encoding " +
std::to_string(format));
135 return std::make_shared<DL_Group_Data>(p, q, g);
139 std::shared_ptr<DL_Group_Data>
140 DL_Group::load_DL_group_info(
const char* p_str,
144 const BigInt p(p_str);
145 const BigInt q(q_str);
146 const BigInt g(g_str);
148 return std::make_shared<DL_Group_Data>(p, q, g);
152 std::shared_ptr<DL_Group_Data>
153 DL_Group::load_DL_group_info(
const char* p_str,
156 const BigInt p(p_str);
157 const BigInt q = (p - 1) / 2;
158 const BigInt g(g_str);
160 return std::make_shared<DL_Group_Data>(p, q, g);
167 if(label ==
"DH PARAMETERS")
169 else if(label ==
"DSA PARAMETERS")
171 else if(label ==
"X942 DH PARAMETERS" || label ==
"X9.42 DH PARAMETERS")
174 throw Decoding_Error(
"DL_Group: Invalid PEM label " + label);
187 if(m_data ==
nullptr)
193 Format format = pem_label_to_dl_format(label);
195 m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
200 if(m_data ==
nullptr)
211 const BigInt e = (p - 1) / q;
213 if(e == 0 || (p - 1) % q > 0)
224 throw Internal_Error(
"DL_Group: Couldn't create a suitable generator");
240 if(qbits != 0 && qbits != pbits - 1)
241 throw Invalid_Argument(
"Cannot create strong-prime DL_Group with specified q bits");
244 const BigInt q = (p - 1) / 2;
262 m_data = std::make_shared<DL_Group_Data>(p, q, g);
273 while(p.
bits() != pbits || !
is_prime(p, rng, 128,
true))
276 p = X - mod_2q.
reduce(X) + 1;
279 const BigInt g = make_dsa_generator(p, q);
280 m_data = std::make_shared<DL_Group_Data>(p, q, g);
285 qbits = ((pbits <= 1024) ? 160 : 256);
289 const BigInt g = make_dsa_generator(p, q);
290 m_data = std::make_shared<DL_Group_Data>(p, q, g);
302 const std::vector<uint8_t>& seed,
303 size_t pbits,
size_t qbits)
308 throw Invalid_Argument(
"DL_Group: The seed given does not generate a DSA group");
310 BigInt g = make_dsa_generator(p, q);
312 m_data = std::make_shared<DL_Group_Data>(p, q, g);
320 m_data = std::make_shared<DL_Group_Data>(p, 0, g);
328 m_data = std::make_shared<DL_Group_Data>(p, q, g);
331 const DL_Group_Data& DL_Group::data()
const
360 if(y <= 1 || y >= p || x <= 1 || x >= p)
379 if(g < 2 || p < 3 || q < 0)
382 const size_t prob = (strong) ? 128 : 10;
433 return data().monty_params_p();
438 return data().p_bits();
443 return data().p_bytes();
448 data().assert_q_is_set(
"q_bits");
449 return data().q_bits();
454 data().assert_q_is_set(
"q_bytes");
455 return data().q_bytes();
460 return data().estimated_strength();
465 return data().exponent_bits();
476 return data().mod_p(x);
481 return data().multiply_mod_p(x, y);
486 data().assert_q_is_set(
"inverse_mod_q");
493 data().assert_q_is_set(
"mod_q");
494 return data().mod_q(x);
499 data().assert_q_is_set(
"multiply_mod_q");
500 return data().multiply_mod_q(x, y);
505 data().assert_q_is_set(
"multiply_mod_q");
511 data().assert_q_is_set(
"square_mod_q");
512 return data().square_mod_q(x);
522 return data().power_g_p(x, x.
bits());
527 return data().power_g_p(x, max_x_bits);
536 throw Encoding_Error(
"Cannot encode DL_Group in ANSI formats when q param is missing");
538 std::vector<uint8_t> output;
575 const std::vector<uint8_t> encoding =
DER_encode(format);
589 m_data = BER_decode_DL_group(ber, ber_len, format);
594 m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
604 Format format = pem_label_to_dl_format(label);
606 m_data = BER_decode_DL_group(ber.data(), ber.size(), format);
const size_t PRIME_TABLE_SIZE
static std::shared_ptr< DL_Group_Data > DL_group_info(const std::string &name)
BigInt inverse_mod_p(const BigInt &x) const
std::string PEM_encode(Format format) const
BigInt square_mod_q(const BigInt &x) const
BigInt power_mod(const BigInt &base, const BigInt &exp, const BigInt &mod)
void randomize(RandomNumberGenerator &rng, size_t bitsize, bool set_high_bit=true)
bool verify_element_pair(const BigInt &y, const BigInt &x) const
std::vector< BigInt > m_g
std::shared_ptr< const Montgomery_Params > monty_params_p() const
int(* final)(unsigned char *, CTX *)
BigInt monty_multi_exp(std::shared_ptr< const Montgomery_Params > params_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)
const BigInt & get_q() const
const BigInt & get_p() const
std::string to_string(const BER_Object &obj)
void PEM_decode(const std::string &pem)
std::vector< uint8_t > DER_encode(Format format) const
DER_Encoder & encode(bool b)
BigInt inverse_mod_q(const BigInt &x) const
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 estimated_strength() const
const BigInt & get_g() const
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
std::shared_ptr< const Montgomery_Params > m_monty_params
BigInt random_safe_prime(RandomNumberGenerator &rng, size_t bits)
BigInt inverse_mod(const BigInt &n, const BigInt &mod)
BigInt multiply_mod_p(const BigInt &x, const BigInt &y) const
bool verify_group(RandomNumberGenerator &rng, bool strong=true) const
secure_vector< uint8_t > decode(DataSource &source, std::string &label)
std::shared_ptr< const Montgomery_Exponentation_State > monty_precompute(std::shared_ptr< const Montgomery_Params > params, const BigInt &g, size_t window_bits, bool const_time)
BigInt mod_p(const BigInt &x) const
size_t exponent_bits() const
std::shared_ptr< const Montgomery_Exponentation_State > m_monty
BigInt multi_exponentiate(const BigInt &x, const BigInt &y, const BigInt &z) const
BigInt reduce(const BigInt &x) const
BigInt random_prime(RandomNumberGenerator &rng, size_t bits, const BigInt &coprime, size_t equiv, size_t modulo, size_t prob)
BigInt multiply_mod_q(const BigInt &x, const BigInt &y) const
std::vector< T > unlock(const secure_vector< T > &in)
BigInt power_g_p(const BigInt &x) const
BigInt mod_q(const BigInt &x) const
bool verify_public_element(const BigInt &y) const
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
size_t dl_exponent_size(size_t bits)
size_t dl_work_factor(size_t bits)
void BER_decode(const std::vector< uint8_t > &ber, Format format)
BigInt monty_execute(const Montgomery_Exponentation_State &precomputed_state, const BigInt &k, size_t max_k_bits)
int32_t jacobi(const BigInt &a, const BigInt &n)
static std::string PEM_for_named_group(const std::string &name)