/src/botan/src/lib/pubkey/dl_group/dl_group.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Discrete Logarithm Parameters |
3 | | * (C) 1999-2008,2015,2018 Jack Lloyd |
4 | | * |
5 | | * Botan is released under the Simplified BSD License (see license.txt) |
6 | | */ |
7 | | |
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> |
16 | | #include <botan/pem.h> |
17 | | #include <botan/internal/workfactor.h> |
18 | | #include <botan/internal/monty_exp.h> |
19 | | |
20 | | namespace Botan { |
21 | | |
22 | | class DL_Group_Data final |
23 | | { |
24 | | public: |
25 | | DL_Group_Data(const BigInt& p, const BigInt& q, const BigInt& g, DL_Group_Source source) : |
26 | | m_p(p), m_q(q), m_g(g), |
27 | | m_mod_p(p), |
28 | | m_mod_q(q), |
29 | | m_monty_params(std::make_shared<Montgomery_Params>(m_p, m_mod_p)), |
30 | | m_monty(monty_precompute(m_monty_params, m_g, /*window bits=*/4)), |
31 | | m_p_bits(p.bits()), |
32 | | m_q_bits(q.bits()), |
33 | | m_estimated_strength(dl_work_factor(m_p_bits)), |
34 | | m_exponent_bits(dl_exponent_size(m_p_bits)), |
35 | | m_source(source) |
36 | 369 | { |
37 | 369 | } |
38 | | |
39 | 340 | ~DL_Group_Data() = default; |
40 | | |
41 | | DL_Group_Data(const DL_Group_Data& other) = delete; |
42 | | DL_Group_Data& operator=(const DL_Group_Data& other) = delete; |
43 | | |
44 | 0 | const BigInt& p() const { return m_p; } |
45 | 354 | const BigInt& q() const { return m_q; } |
46 | 109 | const BigInt& g() const { return m_g; } |
47 | | |
48 | 0 | BigInt mod_p(const BigInt& x) const { return m_mod_p.reduce(x); } |
49 | | |
50 | | BigInt multiply_mod_p(const BigInt& x, const BigInt& y) const |
51 | 0 | { |
52 | 0 | return m_mod_p.multiply(x, y); |
53 | 0 | } |
54 | | |
55 | 0 | BigInt mod_q(const BigInt& x) const { return m_mod_q.reduce(x); } |
56 | | |
57 | | BigInt multiply_mod_q(const BigInt& x, const BigInt& y) const |
58 | 218 | { |
59 | 218 | return m_mod_q.multiply(x, y); |
60 | 218 | } |
61 | | |
62 | | BigInt square_mod_q(const BigInt& x) const |
63 | 0 | { |
64 | 0 | return m_mod_q.square(x); |
65 | 0 | } |
66 | | |
67 | | std::shared_ptr<const Montgomery_Params> monty_params_p() const |
68 | 109 | { return m_monty_params; } |
69 | | |
70 | 22 | size_t p_bits() const { return m_p_bits; } |
71 | 318 | size_t q_bits() const { return m_q_bits; } |
72 | 0 | size_t p_bytes() const { return (m_p_bits + 7) / 8; } |
73 | 0 | size_t q_bytes() const { return (m_q_bits + 7) / 8; } |
74 | | |
75 | 0 | size_t estimated_strength() const { return m_estimated_strength; } |
76 | | |
77 | 0 | size_t exponent_bits() const { return m_exponent_bits; } |
78 | | |
79 | | BigInt power_g_p(const BigInt& k, size_t max_k_bits) const |
80 | 116 | { |
81 | 116 | return monty_execute(*m_monty, k, max_k_bits); |
82 | 116 | } |
83 | | |
84 | | BigInt power_g_p_vartime(const BigInt& k) const |
85 | 0 | { |
86 | 0 | return monty_execute_vartime(*m_monty, k); |
87 | 0 | } |
88 | | |
89 | | BigInt power_b_p(const BigInt& b, const BigInt& k, size_t max_k_bits) const |
90 | 0 | { |
91 | 0 | return monty_exp(m_monty_params, b, k, max_k_bits); |
92 | 0 | } |
93 | | |
94 | | BigInt power_b_p_vartime(const BigInt& b, const BigInt& k) const |
95 | 0 | { |
96 | 0 | return monty_exp_vartime(m_monty_params, b, k); |
97 | 0 | } |
98 | | |
99 | 537 | bool q_is_set() const { return m_q_bits > 0; } |
100 | | |
101 | | void assert_q_is_set(const std::string& function) const |
102 | 537 | { |
103 | 537 | if(q_is_set() == false) |
104 | 1 | throw Invalid_State("DL_Group::" + function + " q is not set for this group"); |
105 | 537 | } |
106 | | |
107 | 0 | DL_Group_Source source() const { return m_source; } |
108 | | |
109 | | private: |
110 | | BigInt m_p; |
111 | | BigInt m_q; |
112 | | BigInt m_g; |
113 | | Modular_Reducer m_mod_p; |
114 | | Modular_Reducer m_mod_q; |
115 | | std::shared_ptr<const Montgomery_Params> m_monty_params; |
116 | | std::shared_ptr<const Montgomery_Exponentation_State> m_monty; |
117 | | size_t m_p_bits; |
118 | | size_t m_q_bits; |
119 | | size_t m_estimated_strength; |
120 | | size_t m_exponent_bits; |
121 | | DL_Group_Source m_source; |
122 | | }; |
123 | | |
124 | | //static |
125 | | std::shared_ptr<DL_Group_Data> DL_Group::BER_decode_DL_group(const uint8_t data[], size_t data_len, |
126 | | DL_Group_Format format, |
127 | | DL_Group_Source source) |
128 | 386 | { |
129 | 386 | BigInt p, q, g; |
130 | | |
131 | 386 | BER_Decoder decoder(data, data_len); |
132 | 386 | BER_Decoder ber = decoder.start_sequence(); |
133 | | |
134 | 386 | if(format == DL_Group_Format::ANSI_X9_57) |
135 | 322 | { |
136 | 322 | ber.decode(p) |
137 | 322 | .decode(q) |
138 | 322 | .decode(g) |
139 | 322 | .verify_end(); |
140 | 322 | } |
141 | 64 | else if(format == DL_Group_Format::ANSI_X9_42) |
142 | 60 | { |
143 | 60 | ber.decode(p) |
144 | 60 | .decode(g) |
145 | 60 | .decode(q) |
146 | 60 | .discard_remaining(); |
147 | 60 | } |
148 | 4 | else if(format == DL_Group_Format::PKCS_3) |
149 | 0 | { |
150 | | // q is left as zero |
151 | 0 | ber.decode(p) |
152 | 0 | .decode(g) |
153 | 0 | .discard_remaining(); |
154 | 0 | } |
155 | 4 | else |
156 | 4 | throw Invalid_Argument("Unknown DL_Group encoding"); |
157 | | |
158 | 382 | return std::make_shared<DL_Group_Data>(p, q, g, source); |
159 | 382 | } |
160 | | |
161 | | //static |
162 | | std::shared_ptr<DL_Group_Data> |
163 | | DL_Group::load_DL_group_info(const char* p_str, |
164 | | const char* q_str, |
165 | | const char* g_str) |
166 | 0 | { |
167 | 0 | const BigInt p(p_str); |
168 | 0 | const BigInt q(q_str); |
169 | 0 | const BigInt g(g_str); |
170 | |
|
171 | 0 | return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin); |
172 | 0 | } |
173 | | |
174 | | //static |
175 | | std::shared_ptr<DL_Group_Data> |
176 | | DL_Group::load_DL_group_info(const char* p_str, |
177 | | const char* g_str) |
178 | 0 | { |
179 | 0 | const BigInt p(p_str); |
180 | 0 | const BigInt q = (p - 1) / 2; |
181 | 0 | const BigInt g(g_str); |
182 | |
|
183 | 0 | return std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::Builtin); |
184 | 0 | } |
185 | | |
186 | | namespace { |
187 | | |
188 | | DL_Group_Format pem_label_to_dl_format(const std::string& label) |
189 | 0 | { |
190 | 0 | if(label == "DH PARAMETERS") |
191 | 0 | return DL_Group_Format::PKCS_3; |
192 | 0 | else if(label == "DSA PARAMETERS") |
193 | 0 | return DL_Group_Format::ANSI_X9_57; |
194 | 0 | else if(label == "X942 DH PARAMETERS" || label == "X9.42 DH PARAMETERS") |
195 | 0 | return DL_Group_Format::ANSI_X9_42; |
196 | 0 | else |
197 | 0 | throw Decoding_Error("DL_Group: Invalid PEM label " + label); |
198 | 0 | } |
199 | | |
200 | | } |
201 | | |
202 | | /* |
203 | | * DL_Group Constructor |
204 | | */ |
205 | | DL_Group::DL_Group(const std::string& str) |
206 | 0 | { |
207 | | // Either a name or a PEM block, try name first |
208 | 0 | m_data = DL_group_info(str); |
209 | |
|
210 | 0 | if(m_data == nullptr) |
211 | 0 | { |
212 | 0 | try |
213 | 0 | { |
214 | 0 | std::string label; |
215 | 0 | const std::vector<uint8_t> ber = unlock(PEM_Code::decode(str, label)); |
216 | 0 | DL_Group_Format format = pem_label_to_dl_format(label); |
217 | |
|
218 | 0 | m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource); |
219 | 0 | } |
220 | 0 | catch(...) {} |
221 | 0 | } |
222 | |
|
223 | 0 | if(m_data == nullptr) |
224 | 0 | throw Invalid_Argument("DL_Group: Unknown group " + str); |
225 | 0 | } |
226 | | |
227 | | namespace { |
228 | | |
229 | | /* |
230 | | * Create generator of the q-sized subgroup (DSA style generator) |
231 | | */ |
232 | | BigInt make_dsa_generator(const BigInt& p, const BigInt& q) |
233 | 0 | { |
234 | 0 | BigInt e, r; |
235 | 0 | vartime_divide(p - 1, q, e, r); |
236 | |
|
237 | 0 | if(e == 0 || r > 0) |
238 | 0 | throw Invalid_Argument("make_dsa_generator q does not divide p-1"); |
239 | | |
240 | 0 | for(size_t i = 0; i != PRIME_TABLE_SIZE; ++i) |
241 | 0 | { |
242 | | // TODO precompute! |
243 | 0 | BigInt g = power_mod(BigInt::from_word(PRIMES[i]), e, p); |
244 | 0 | if(g > 1) |
245 | 0 | return g; |
246 | 0 | } |
247 | |
|
248 | 0 | throw Internal_Error("DL_Group: Couldn't create a suitable generator"); |
249 | 0 | } |
250 | | |
251 | | } |
252 | | |
253 | | /* |
254 | | * DL_Group Constructor |
255 | | */ |
256 | | DL_Group::DL_Group(RandomNumberGenerator& rng, |
257 | | PrimeType type, size_t pbits, size_t qbits) |
258 | 0 | { |
259 | 0 | if(pbits < 1024) |
260 | 0 | throw Invalid_Argument("DL_Group: prime size " + std::to_string(pbits) + " is too small"); |
261 | | |
262 | 0 | if(type == Strong) |
263 | 0 | { |
264 | 0 | if(qbits != 0 && qbits != pbits - 1) |
265 | 0 | throw Invalid_Argument("Cannot create strong-prime DL_Group with specified q bits"); |
266 | | |
267 | 0 | const BigInt p = random_safe_prime(rng, pbits); |
268 | 0 | const BigInt q = (p - 1) / 2; |
269 | | |
270 | | /* |
271 | | Always choose a generator that is quadratic reside mod p, |
272 | | this forces g to be a generator of the subgroup of size q. |
273 | | */ |
274 | 0 | BigInt g = BigInt::from_word(2); |
275 | 0 | if(jacobi(g, p) != 1) |
276 | 0 | { |
277 | | // prime table does not contain 2 |
278 | 0 | for(size_t i = 0; i < PRIME_TABLE_SIZE; ++i) |
279 | 0 | { |
280 | 0 | g = BigInt::from_word(PRIMES[i]); |
281 | 0 | if(jacobi(g, p) == 1) |
282 | 0 | break; |
283 | 0 | } |
284 | 0 | } |
285 | |
|
286 | 0 | m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated); |
287 | 0 | } |
288 | 0 | else if(type == Prime_Subgroup) |
289 | 0 | { |
290 | 0 | if(qbits == 0) |
291 | 0 | qbits = dl_exponent_size(pbits); |
292 | |
|
293 | 0 | const BigInt q = random_prime(rng, qbits); |
294 | 0 | Modular_Reducer mod_2q(2*q); |
295 | 0 | BigInt X; |
296 | 0 | BigInt p; |
297 | 0 | while(p.bits() != pbits || !is_prime(p, rng, 128, true)) |
298 | 0 | { |
299 | 0 | X.randomize(rng, pbits); |
300 | 0 | p = X - mod_2q.reduce(X) + 1; |
301 | 0 | } |
302 | |
|
303 | 0 | const BigInt g = make_dsa_generator(p, q); |
304 | 0 | m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated); |
305 | 0 | } |
306 | 0 | else if(type == DSA_Kosherizer) |
307 | 0 | { |
308 | 0 | if(qbits == 0) |
309 | 0 | qbits = ((pbits <= 1024) ? 160 : 256); |
310 | |
|
311 | 0 | BigInt p, q; |
312 | 0 | generate_dsa_primes(rng, p, q, pbits, qbits); |
313 | 0 | const BigInt g = make_dsa_generator(p, q); |
314 | 0 | m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated); |
315 | 0 | } |
316 | 0 | else |
317 | 0 | { |
318 | 0 | throw Invalid_Argument("DL_Group unknown PrimeType"); |
319 | 0 | } |
320 | 0 | } |
321 | | |
322 | | /* |
323 | | * DL_Group Constructor |
324 | | */ |
325 | | DL_Group::DL_Group(RandomNumberGenerator& rng, |
326 | | const std::vector<uint8_t>& seed, |
327 | | size_t pbits, size_t qbits) |
328 | 0 | { |
329 | 0 | BigInt p, q; |
330 | |
|
331 | 0 | if(!generate_dsa_primes(rng, p, q, pbits, qbits, seed)) |
332 | 0 | throw Invalid_Argument("DL_Group: The seed given does not generate a DSA group"); |
333 | | |
334 | 0 | BigInt g = make_dsa_generator(p, q); |
335 | |
|
336 | 0 | m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::RandomlyGenerated); |
337 | 0 | } |
338 | | |
339 | | /* |
340 | | * DL_Group Constructor |
341 | | */ |
342 | | DL_Group::DL_Group(const BigInt& p, const BigInt& g) |
343 | 0 | { |
344 | 0 | m_data = std::make_shared<DL_Group_Data>(p, BigInt::zero(), g, DL_Group_Source::ExternalSource); |
345 | 0 | } |
346 | | |
347 | | /* |
348 | | * DL_Group Constructor |
349 | | */ |
350 | | DL_Group::DL_Group(const BigInt& p, const BigInt& q, const BigInt& g) |
351 | 0 | { |
352 | 0 | m_data = std::make_shared<DL_Group_Data>(p, q, g, DL_Group_Source::ExternalSource); |
353 | 0 | } |
354 | | |
355 | | const DL_Group_Data& DL_Group::data() const |
356 | 1.78k | { |
357 | 1.78k | if(m_data) |
358 | 1.78k | return *m_data; |
359 | | |
360 | 0 | throw Invalid_State("DL_Group uninitialized"); |
361 | 0 | } |
362 | | |
363 | | bool DL_Group::verify_public_element(const BigInt& y) const |
364 | 0 | { |
365 | 0 | const BigInt& p = get_p(); |
366 | 0 | const BigInt& q = get_q(); |
367 | |
|
368 | 0 | if(y <= 1 || y >= p) |
369 | 0 | return false; |
370 | | |
371 | 0 | if(q.is_zero() == false) |
372 | 0 | { |
373 | 0 | if(data().power_b_p_vartime(y, q) != 1) |
374 | 0 | return false; |
375 | 0 | } |
376 | | |
377 | 0 | return true; |
378 | 0 | } |
379 | | |
380 | | bool DL_Group::verify_element_pair(const BigInt& y, const BigInt& x) const |
381 | 0 | { |
382 | 0 | const BigInt& p = get_p(); |
383 | |
|
384 | 0 | if(y <= 1 || y >= p || x <= 1 || x >= p) |
385 | 0 | return false; |
386 | | |
387 | 0 | if(y != this->power_g_p(x)) |
388 | 0 | return false; |
389 | | |
390 | 0 | return true; |
391 | 0 | } |
392 | | |
393 | | /* |
394 | | * Verify the parameters |
395 | | */ |
396 | | bool DL_Group::verify_group(RandomNumberGenerator& rng, |
397 | | bool strong) const |
398 | 0 | { |
399 | 0 | const bool from_builtin = (source() == DL_Group_Source::Builtin); |
400 | |
|
401 | 0 | if(!strong && from_builtin) |
402 | 0 | return true; |
403 | | |
404 | 0 | const BigInt& p = get_p(); |
405 | 0 | const BigInt& q = get_q(); |
406 | 0 | const BigInt& g = get_g(); |
407 | |
|
408 | 0 | if(g < 2 || p < 3 || q < 0) |
409 | 0 | return false; |
410 | | |
411 | 0 | const size_t test_prob = 128; |
412 | 0 | const bool is_randomly_generated = (source() != DL_Group_Source::ExternalSource); |
413 | |
|
414 | 0 | if(!is_prime(p, rng, test_prob, is_randomly_generated)) |
415 | 0 | { |
416 | 0 | return false; |
417 | 0 | } |
418 | | |
419 | 0 | if(q != 0) |
420 | 0 | { |
421 | 0 | if((p - 1) % q != 0) |
422 | 0 | { |
423 | 0 | return false; |
424 | 0 | } |
425 | 0 | if(data().power_g_p_vartime(q) != 1) |
426 | 0 | { |
427 | 0 | return false; |
428 | 0 | } |
429 | 0 | if(!is_prime(q, rng, test_prob, is_randomly_generated)) |
430 | 0 | { |
431 | 0 | return false; |
432 | 0 | } |
433 | 0 | } |
434 | 0 | else |
435 | 0 | { |
436 | 0 | if(!from_builtin && !is_randomly_generated) |
437 | 0 | { |
438 | | // If we got this p,g from some unknown source, try to verify |
439 | | // that the group order is not too absurdly small. |
440 | |
|
441 | 0 | const size_t upper_bound = strong ? 1000 : 100; |
442 | |
|
443 | 0 | for(size_t i = 2; i != upper_bound; ++i) |
444 | 0 | { |
445 | 0 | if(data().power_g_p_vartime(BigInt::from_word(i)) == 1) |
446 | 0 | { |
447 | 0 | return false; |
448 | 0 | } |
449 | 0 | } |
450 | 0 | } |
451 | 0 | } |
452 | |
|
453 | 0 | return true; |
454 | 0 | } |
455 | | |
456 | | /* |
457 | | * Return the prime |
458 | | */ |
459 | | const BigInt& DL_Group::get_p() const |
460 | 0 | { |
461 | 0 | return data().p(); |
462 | 0 | } |
463 | | |
464 | | /* |
465 | | * Return the generator |
466 | | */ |
467 | | const BigInt& DL_Group::get_g() const |
468 | 109 | { |
469 | 109 | return data().g(); |
470 | 109 | } |
471 | | |
472 | | /* |
473 | | * Return the subgroup |
474 | | */ |
475 | | const BigInt& DL_Group::get_q() const |
476 | 354 | { |
477 | 354 | return data().q(); |
478 | 354 | } |
479 | | |
480 | | std::shared_ptr<const Montgomery_Params> DL_Group::monty_params_p() const |
481 | 0 | { |
482 | 0 | return data().monty_params_p(); |
483 | 0 | } |
484 | | |
485 | | size_t DL_Group::p_bits() const |
486 | 22 | { |
487 | 22 | return data().p_bits(); |
488 | 22 | } |
489 | | |
490 | | size_t DL_Group::p_bytes() const |
491 | 0 | { |
492 | 0 | return data().p_bytes(); |
493 | 0 | } |
494 | | |
495 | | size_t DL_Group::q_bits() const |
496 | 319 | { |
497 | 319 | data().assert_q_is_set("q_bits"); |
498 | 319 | return data().q_bits(); |
499 | 319 | } |
500 | | |
501 | | size_t DL_Group::q_bytes() const |
502 | 0 | { |
503 | 0 | data().assert_q_is_set("q_bytes"); |
504 | 0 | return data().q_bytes(); |
505 | 0 | } |
506 | | |
507 | | size_t DL_Group::estimated_strength() const |
508 | 0 | { |
509 | 0 | return data().estimated_strength(); |
510 | 0 | } |
511 | | |
512 | | size_t DL_Group::exponent_bits() const |
513 | 0 | { |
514 | 0 | return data().exponent_bits(); |
515 | 0 | } |
516 | | |
517 | | BigInt DL_Group::inverse_mod_p(const BigInt& x) const |
518 | 0 | { |
519 | | // precompute?? |
520 | 0 | return inverse_mod(x, get_p()); |
521 | 0 | } |
522 | | |
523 | | BigInt DL_Group::mod_p(const BigInt& x) const |
524 | 0 | { |
525 | 0 | return data().mod_p(x); |
526 | 0 | } |
527 | | |
528 | | BigInt DL_Group::multiply_mod_p(const BigInt& x, const BigInt& y) const |
529 | 0 | { |
530 | 0 | return data().multiply_mod_p(x, y); |
531 | 0 | } |
532 | | |
533 | | BigInt DL_Group::inverse_mod_q(const BigInt& x) const |
534 | 0 | { |
535 | 0 | data().assert_q_is_set("inverse_mod_q"); |
536 | | // precompute?? |
537 | 0 | return inverse_mod(x, get_q()); |
538 | 0 | } |
539 | | |
540 | | BigInt DL_Group::mod_q(const BigInt& x) const |
541 | 0 | { |
542 | 0 | data().assert_q_is_set("mod_q"); |
543 | 0 | return data().mod_q(x); |
544 | 0 | } |
545 | | |
546 | | BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y) const |
547 | 218 | { |
548 | 218 | data().assert_q_is_set("multiply_mod_q"); |
549 | 218 | return data().multiply_mod_q(x, y); |
550 | 218 | } |
551 | | |
552 | | BigInt DL_Group::multiply_mod_q(const BigInt& x, const BigInt& y, const BigInt& z) const |
553 | 0 | { |
554 | 0 | data().assert_q_is_set("multiply_mod_q"); |
555 | 0 | return data().multiply_mod_q(data().multiply_mod_q(x, y), z); |
556 | 0 | } |
557 | | |
558 | | BigInt DL_Group::square_mod_q(const BigInt& x) const |
559 | 0 | { |
560 | 0 | data().assert_q_is_set("square_mod_q"); |
561 | 0 | return data().square_mod_q(x); |
562 | 0 | } |
563 | | |
564 | | BigInt DL_Group::multi_exponentiate(const BigInt& x, const BigInt& y, const BigInt& z) const |
565 | 109 | { |
566 | 109 | return monty_multi_exp(data().monty_params_p(), get_g(), x, y, z); |
567 | 109 | } |
568 | | |
569 | | BigInt DL_Group::power_g_p(const BigInt& x) const |
570 | 0 | { |
571 | 0 | return data().power_g_p(x, x.bits()); |
572 | 0 | } |
573 | | |
574 | | BigInt DL_Group::power_g_p(const BigInt& x, size_t max_x_bits) const |
575 | 116 | { |
576 | 116 | return data().power_g_p(x, max_x_bits); |
577 | 116 | } |
578 | | |
579 | | BigInt DL_Group::power_b_p(const BigInt& b, const BigInt& x, size_t max_x_bits) const |
580 | 0 | { |
581 | 0 | return data().power_b_p(b, x, max_x_bits); |
582 | 0 | } |
583 | | |
584 | | DL_Group_Source DL_Group::source() const |
585 | 0 | { |
586 | 0 | return data().source(); |
587 | 0 | } |
588 | | |
589 | | /* |
590 | | * DER encode the parameters |
591 | | */ |
592 | | std::vector<uint8_t> DL_Group::DER_encode(DL_Group_Format format) const |
593 | 0 | { |
594 | 0 | if(get_q().is_zero() && (format != DL_Group_Format::PKCS_3)) |
595 | 0 | throw Encoding_Error("Cannot encode DL_Group in ANSI formats when q param is missing"); |
596 | | |
597 | 0 | std::vector<uint8_t> output; |
598 | 0 | DER_Encoder der(output); |
599 | |
|
600 | 0 | if(format == DL_Group_Format::ANSI_X9_57) |
601 | 0 | { |
602 | 0 | der.start_sequence() |
603 | 0 | .encode(get_p()) |
604 | 0 | .encode(get_q()) |
605 | 0 | .encode(get_g()) |
606 | 0 | .end_cons(); |
607 | 0 | } |
608 | 0 | else if(format == DL_Group_Format::ANSI_X9_42) |
609 | 0 | { |
610 | 0 | der.start_sequence() |
611 | 0 | .encode(get_p()) |
612 | 0 | .encode(get_g()) |
613 | 0 | .encode(get_q()) |
614 | 0 | .end_cons(); |
615 | 0 | } |
616 | 0 | else if(format == DL_Group_Format::PKCS_3) |
617 | 0 | { |
618 | 0 | der.start_sequence() |
619 | 0 | .encode(get_p()) |
620 | 0 | .encode(get_g()) |
621 | 0 | .end_cons(); |
622 | 0 | } |
623 | 0 | else |
624 | 0 | throw Invalid_Argument("Unknown DL_Group encoding"); |
625 | | |
626 | 0 | return output; |
627 | 0 | } |
628 | | |
629 | | /* |
630 | | * PEM encode the parameters |
631 | | */ |
632 | | std::string DL_Group::PEM_encode(DL_Group_Format format) const |
633 | 0 | { |
634 | 0 | const std::vector<uint8_t> encoding = DER_encode(format); |
635 | |
|
636 | 0 | if(format == DL_Group_Format::PKCS_3) |
637 | 0 | return PEM_Code::encode(encoding, "DH PARAMETERS"); |
638 | 0 | else if(format == DL_Group_Format::ANSI_X9_57) |
639 | 0 | return PEM_Code::encode(encoding, "DSA PARAMETERS"); |
640 | 0 | else if(format == DL_Group_Format::ANSI_X9_42) |
641 | 0 | return PEM_Code::encode(encoding, "X9.42 DH PARAMETERS"); |
642 | 0 | else |
643 | 0 | throw Invalid_Argument("Unknown DL_Group encoding"); |
644 | 0 | } |
645 | | |
646 | | DL_Group::DL_Group(const uint8_t ber[], size_t ber_len, DL_Group_Format format) |
647 | 156 | { |
648 | 156 | m_data = BER_decode_DL_group(ber, ber_len, format, DL_Group_Source::ExternalSource); |
649 | 156 | } |
650 | | |
651 | | void DL_Group::BER_decode(const std::vector<uint8_t>& ber, DL_Group_Format format) |
652 | 230 | { |
653 | 230 | m_data = BER_decode_DL_group(ber.data(), ber.size(), format, DL_Group_Source::ExternalSource); |
654 | 230 | } |
655 | | |
656 | | //static |
657 | | DL_Group DL_Group::DL_Group_from_PEM(const std::string& pem) |
658 | 0 | { |
659 | 0 | std::string label; |
660 | 0 | const std::vector<uint8_t> ber = unlock(PEM_Code::decode(pem, label)); |
661 | 0 | DL_Group_Format format = pem_label_to_dl_format(label); |
662 | 0 | return DL_Group(ber, format); |
663 | 0 | } |
664 | | |
665 | | } |