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