Botan 3.4.0
Crypto and TLS for C&
pk_algs.cpp
Go to the documentation of this file.
1/*
2* PK Key
3* (C) 1999-2010,2016 Jack Lloyd
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/pk_algs.h>
9
10#include <botan/internal/fmt.h>
11#include <botan/internal/parsing.h>
12
13#if defined(BOTAN_HAS_RSA)
14 #include <botan/rsa.h>
15#endif
16
17#if defined(BOTAN_HAS_DSA)
18 #include <botan/dsa.h>
19#endif
20
21#if defined(BOTAN_HAS_DL_GROUP)
22 #include <botan/dl_group.h>
23#endif
24
25#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
26 #include <botan/dh.h>
27#endif
28
29#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
30 #include <botan/ecc_key.h>
31#endif
32
33#if defined(BOTAN_HAS_ECDSA)
34 #include <botan/ecdsa.h>
35#endif
36
37#if defined(BOTAN_HAS_ECGDSA)
38 #include <botan/ecgdsa.h>
39#endif
40
41#if defined(BOTAN_HAS_ECKCDSA)
42 #include <botan/eckcdsa.h>
43#endif
44
45#if defined(BOTAN_HAS_ED25519)
46 #include <botan/ed25519.h>
47#endif
48
49#if defined(BOTAN_HAS_ED448)
50 #include <botan/ed448.h>
51#endif
52
53#if defined(BOTAN_HAS_GOST_34_10_2001)
54 #include <botan/gost_3410.h>
55#endif
56
57#if defined(BOTAN_HAS_ELGAMAL)
58 #include <botan/elgamal.h>
59#endif
60
61#if defined(BOTAN_HAS_ECDH)
62 #include <botan/ecdh.h>
63#endif
64
65#if defined(BOTAN_HAS_CURVE_25519)
66 #include <botan/curve25519.h>
67#endif
68
69#if defined(BOTAN_HAS_X448)
70 #include <botan/x448.h>
71#endif
72
73#if defined(BOTAN_HAS_MCELIECE)
74 #include <botan/mceliece.h>
75#endif
76
77#if defined(BOTAN_HAS_FRODOKEM)
78 #include <botan/frodokem.h>
79#endif
80
81#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
82 #include <botan/kyber.h>
83#endif
84
85#if defined(BOTAN_HAS_XMSS_RFC8391)
86 #include <botan/xmss.h>
87#endif
88
89#if defined(BOTAN_HAS_SM2)
90 #include <botan/sm2.h>
91#endif
92
93#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
94 #include <botan/dilithium.h>
95#endif
96
97#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
98 #include <botan/sphincsplus.h>
99#endif
100
101namespace Botan {
102
103std::unique_ptr<Public_Key> load_public_key(const AlgorithmIdentifier& alg_id,
104 [[maybe_unused]] std::span<const uint8_t> key_bits) {
105 const std::string oid_str = alg_id.oid().to_formatted_string();
106 const std::vector<std::string> alg_info = split_on(oid_str, '/');
107 std::string_view alg_name = alg_info[0];
108
109#if defined(BOTAN_HAS_RSA)
110 if(alg_name == "RSA") {
111 return std::make_unique<RSA_PublicKey>(alg_id, key_bits);
112 }
113#endif
114
115#if defined(BOTAN_HAS_CURVE_25519)
116 if(alg_name == "Curve25519") {
117 return std::make_unique<Curve25519_PublicKey>(alg_id, key_bits);
118 }
119#endif
120
121#if defined(BOTAN_HAS_X448)
122 if(alg_name == "X448") {
123 return std::make_unique<X448_PublicKey>(alg_id, key_bits);
124 }
125#endif
126
127#if defined(BOTAN_HAS_MCELIECE)
128 if(alg_name == "McEliece") {
129 return std::make_unique<McEliece_PublicKey>(key_bits);
130 }
131#endif
132
133#if defined(BOTAN_HAS_FRODOKEM)
134 if(alg_name == "FrodoKEM" || alg_name.starts_with("FrodoKEM-") || alg_name.starts_with("eFrodoKEM-")) {
135 return std::make_unique<FrodoKEM_PublicKey>(alg_id, key_bits);
136 }
137#endif
138
139#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
140 if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
141 return std::make_unique<Kyber_PublicKey>(alg_id, key_bits);
142 }
143#endif
144
145#if defined(BOTAN_HAS_ECDSA)
146 if(alg_name == "ECDSA") {
147 return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
148 }
149#endif
150
151#if defined(BOTAN_HAS_ECDH)
152 if(alg_name == "ECDH") {
153 return std::make_unique<ECDH_PublicKey>(alg_id, key_bits);
154 }
155#endif
156
157#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
158 if(alg_name == "DH") {
159 return std::make_unique<DH_PublicKey>(alg_id, key_bits);
160 }
161#endif
162
163#if defined(BOTAN_HAS_DSA)
164 if(alg_name == "DSA") {
165 return std::make_unique<DSA_PublicKey>(alg_id, key_bits);
166 }
167#endif
168
169#if defined(BOTAN_HAS_ELGAMAL)
170 if(alg_name == "ElGamal") {
171 return std::make_unique<ElGamal_PublicKey>(alg_id, key_bits);
172 }
173#endif
174
175#if defined(BOTAN_HAS_ECGDSA)
176 if(alg_name == "ECGDSA") {
177 return std::make_unique<ECGDSA_PublicKey>(alg_id, key_bits);
178 }
179#endif
180
181#if defined(BOTAN_HAS_ECKCDSA)
182 if(alg_name == "ECKCDSA") {
183 return std::make_unique<ECKCDSA_PublicKey>(alg_id, key_bits);
184 }
185#endif
186
187#if defined(BOTAN_HAS_ED25519)
188 if(alg_name == "Ed25519") {
189 return std::make_unique<Ed25519_PublicKey>(alg_id, key_bits);
190 }
191#endif
192
193#if defined(BOTAN_HAS_ED448)
194 if(alg_name == "Ed448") {
195 return std::make_unique<Ed448_PublicKey>(alg_id, key_bits);
196 }
197#endif
198
199#if defined(BOTAN_HAS_GOST_34_10_2001)
200 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
201 return std::make_unique<GOST_3410_PublicKey>(alg_id, key_bits);
202 }
203#endif
204
205#if defined(BOTAN_HAS_SM2)
206 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
207 return std::make_unique<SM2_PublicKey>(alg_id, key_bits);
208 }
209#endif
210
211#if defined(BOTAN_HAS_XMSS_RFC8391)
212 if(alg_name == "XMSS") {
213 return std::make_unique<XMSS_PublicKey>(key_bits);
214 }
215#endif
216
217#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
218 if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
219 return std::make_unique<Dilithium_PublicKey>(alg_id, key_bits);
220 }
221#endif
222
223#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
224 if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
225 return std::make_unique<SphincsPlus_PublicKey>(alg_id, key_bits);
226 }
227#endif
228
229 throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
230}
231
232std::unique_ptr<Private_Key> load_private_key(const AlgorithmIdentifier& alg_id,
233 [[maybe_unused]] std::span<const uint8_t> key_bits) {
234 const std::string oid_str = alg_id.oid().to_formatted_string();
235 const std::vector<std::string> alg_info = split_on(oid_str, '/');
236 std::string_view alg_name = alg_info[0];
237
238#if defined(BOTAN_HAS_RSA)
239 if(alg_name == "RSA") {
240 return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
241 }
242#endif
243
244#if defined(BOTAN_HAS_CURVE_25519)
245 if(alg_name == "Curve25519") {
246 return std::make_unique<Curve25519_PrivateKey>(alg_id, key_bits);
247 }
248#endif
249
250#if defined(BOTAN_HAS_X448)
251 if(alg_name == "X448") {
252 return std::make_unique<X448_PrivateKey>(alg_id, key_bits);
253 }
254#endif
255
256#if defined(BOTAN_HAS_ECDSA)
257 if(alg_name == "ECDSA") {
258 return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
259 }
260#endif
261
262#if defined(BOTAN_HAS_ECDH)
263 if(alg_name == "ECDH") {
264 return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
265 }
266#endif
267
268#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
269 if(alg_name == "DH") {
270 return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
271 }
272#endif
273
274#if defined(BOTAN_HAS_DSA)
275 if(alg_name == "DSA") {
276 return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
277 }
278#endif
279
280#if defined(BOTAN_HAS_FRODOKEM)
281 if(alg_name == "FrodoKEM" || alg_name.starts_with("FrodoKEM-") || alg_name.starts_with("eFrodoKEM-")) {
282 return std::make_unique<FrodoKEM_PrivateKey>(alg_id, key_bits);
283 }
284#endif
285
286#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
287 if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
288 return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
289 }
290#endif
291
292#if defined(BOTAN_HAS_MCELIECE)
293 if(alg_name == "McEliece") {
294 return std::make_unique<McEliece_PrivateKey>(key_bits);
295 }
296#endif
297
298#if defined(BOTAN_HAS_ECGDSA)
299 if(alg_name == "ECGDSA") {
300 return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
301 }
302#endif
303
304#if defined(BOTAN_HAS_ECKCDSA)
305 if(alg_name == "ECKCDSA") {
306 return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
307 }
308#endif
309
310#if defined(BOTAN_HAS_ED25519)
311 if(alg_name == "Ed25519") {
312 return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
313 }
314#endif
315
316#if defined(BOTAN_HAS_ED448)
317 if(alg_name == "Ed448") {
318 return std::make_unique<Ed448_PrivateKey>(alg_id, key_bits);
319 }
320#endif
321
322#if defined(BOTAN_HAS_GOST_34_10_2001)
323 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
324 return std::make_unique<GOST_3410_PrivateKey>(alg_id, key_bits);
325 }
326#endif
327
328#if defined(BOTAN_HAS_SM2)
329 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
330 return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
331 }
332#endif
333
334#if defined(BOTAN_HAS_ELGAMAL)
335 if(alg_name == "ElGamal") {
336 return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
337 }
338#endif
339
340#if defined(BOTAN_HAS_XMSS_RFC8391)
341 if(alg_name == "XMSS") {
342 return std::make_unique<XMSS_PrivateKey>(key_bits);
343 }
344#endif
345
346#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
347 if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
348 return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
349 }
350#endif
351
352#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
353 if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
354 return std::make_unique<SphincsPlus_PrivateKey>(alg_id, key_bits);
355 }
356#endif
357
358 throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
359}
360
361std::unique_ptr<Private_Key> create_ec_private_key(std::string_view alg_name,
362 const EC_Group& ec_group,
364 // Potentially unused if all EC algorithms are disabled
365 BOTAN_UNUSED(alg_name, ec_group, rng);
366
367#if defined(BOTAN_HAS_ECDSA)
368 if(alg_name == "ECDSA") {
369 return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
370 }
371#endif
372
373#if defined(BOTAN_HAS_ECDH)
374 if(alg_name == "ECDH") {
375 return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
376 }
377#endif
378
379#if defined(BOTAN_HAS_ECKCDSA)
380 if(alg_name == "ECKCDSA") {
381 return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
382 }
383#endif
384
385#if defined(BOTAN_HAS_GOST_34_10_2001)
386 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
387 return std::make_unique<GOST_3410_PrivateKey>(rng, ec_group);
388 }
389#endif
390
391#if defined(BOTAN_HAS_SM2)
392 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
393 return std::make_unique<SM2_PrivateKey>(rng, ec_group);
394 }
395#endif
396
397#if defined(BOTAN_HAS_ECGDSA)
398 if(alg_name == "ECGDSA") {
399 return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
400 }
401#endif
402
403 return nullptr;
404}
405
406std::unique_ptr<Private_Key> create_private_key(std::string_view alg_name,
408 std::string_view params,
409 std::string_view provider) {
410 /*
411 * Default paramaters are chosen for work factor > 2**128 where possible
412 */
413
414#if defined(BOTAN_HAS_CURVE_25519)
415 if(alg_name == "Curve25519") {
416 return std::make_unique<Curve25519_PrivateKey>(rng);
417 }
418#endif
419
420#if defined(BOTAN_HAS_X448)
421 if(alg_name == "X448") {
422 return std::make_unique<X448_PrivateKey>(rng);
423 }
424#endif
425
426#if defined(BOTAN_HAS_RSA)
427 if(alg_name == "RSA") {
428 const size_t modulus_bits = params.empty() ? 3072 : to_u32bit(params);
429 return std::make_unique<RSA_PrivateKey>(rng, modulus_bits);
430 }
431#endif
432
433#if defined(BOTAN_HAS_MCELIECE)
434 if(alg_name == "McEliece") {
435 const auto [n, t] = [&]() -> std::pair<size_t, size_t> {
436 if(params.empty()) {
437 return {2960, 57};
438 }
439
440 const auto mce_params = split_on(params, ',');
441
442 if(mce_params.size() != 2) {
443 throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
444 }
445
446 const size_t mce_n = to_u32bit(mce_params[0]);
447 const size_t mce_t = to_u32bit(mce_params[1]);
448 return {mce_n, mce_t};
449 }();
450
451 return std::make_unique<McEliece_PrivateKey>(rng, n, t);
452 }
453#endif
454
455#if defined(BOTAN_HAS_FRODOKEM)
456 if(alg_name == "FrodoKEM") {
457 const auto mode = params.empty() ? FrodoKEMMode::FrodoKEM976_SHAKE : FrodoKEMMode(params);
458 return std::make_unique<FrodoKEM_PrivateKey>(rng, mode);
459 }
460#endif
461
462#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
463 if(alg_name == "Kyber") {
464 const auto mode = [&]() -> KyberMode {
465 if(params.empty()) {
467 }
468 return KyberMode(params);
469 }();
470
471 return std::make_unique<Kyber_PrivateKey>(rng, mode);
472 }
473#endif
474
475#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
476 if(alg_name == "Dilithium" || alg_name == "Dilithium-") {
477 const auto mode = [&]() -> DilithiumMode {
478 if(params.empty()) {
480 }
481 return DilithiumMode(params);
482 }();
483
484 return std::make_unique<Dilithium_PrivateKey>(rng, mode);
485 }
486#endif
487
488#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
489 if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-") {
490 auto sphincs_params = Sphincs_Parameters::create(params);
491
492 return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
493 }
494#endif
495
496#if defined(BOTAN_HAS_XMSS_RFC8391)
497 if(alg_name == "XMSS") {
498 const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t {
499 if(params.empty()) {
501 }
502 return XMSS_Parameters(params).oid();
503 }();
504
505 return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
506 }
507#endif
508
509#if defined(BOTAN_HAS_ED25519)
510 if(alg_name == "Ed25519") {
511 return std::make_unique<Ed25519_PrivateKey>(rng);
512 }
513#endif
514
515#if defined(BOTAN_HAS_ED448)
516 if(alg_name == "Ed448") {
517 return std::make_unique<Ed448_PrivateKey>(rng);
518 }
519#endif
520
521 // ECC crypto
522#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
523
524 if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" ||
525 alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" ||
526 alg_name == "GOST-34.10-2012-512") {
527 const std::string group_id = [&]() -> std::string {
528 if(!params.empty()) {
529 return std::string(params);
530 }
531 if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig") {
532 return "sm2p256v1";
533 }
534 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256") {
535 return "gost_256A";
536 }
537 if(alg_name == "GOST-34.10-2012-512") {
538 return "gost_512A";
539 }
540 if(alg_name == "ECGDSA") {
541 return "brainpool256r1";
542 }
543 return "secp256r1";
544 }();
545
546 const EC_Group ec_group(group_id);
547 return create_ec_private_key(alg_name, ec_group, rng);
548 }
549#endif
550
551 // DL crypto
552#if defined(BOTAN_HAS_DL_GROUP)
553 if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") {
554 const std::string group_id = [&]() -> std::string {
555 if(!params.empty()) {
556 return std::string(params);
557 }
558 if(alg_name == "DSA") {
559 return "dsa/botan/2048";
560 }
561 return "modp/ietf/2048";
562 }();
563
564 DL_Group modp_group(group_id);
565
566 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
567 if(alg_name == "DH") {
568 return std::make_unique<DH_PrivateKey>(rng, modp_group);
569 }
570 #endif
571
572 #if defined(BOTAN_HAS_DSA)
573 if(alg_name == "DSA") {
574 return std::make_unique<DSA_PrivateKey>(rng, modp_group);
575 }
576 #endif
577
578 #if defined(BOTAN_HAS_ELGAMAL)
579 if(alg_name == "ElGamal") {
580 return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
581 }
582 #endif
583 }
584#endif
585
586 BOTAN_UNUSED(alg_name, rng, params, provider);
587
588 return std::unique_ptr<Private_Key>();
589}
590
591std::vector<std::string> probe_provider_private_key(std::string_view alg_name,
592 const std::vector<std::string>& possible) {
593 std::vector<std::string> providers;
594
595 for(auto&& prov : possible) {
596 if(prov == "base") {
597 providers.push_back(prov);
598 }
599 }
600
601 BOTAN_UNUSED(alg_name);
602
603 return providers;
604}
605} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
const OID & oid() const
Definition asn1_obj.h:455
std::string to_formatted_string() const
Definition asn1_oid.cpp:114
static Sphincs_Parameters create(Sphincs_Parameter_Set set, Sphincs_Hash_Type hash)
xmss_algorithm_t oid() const
uint32_t to_u32bit(std::string_view str_view)
Definition parsing.cpp:32
std::unique_ptr< Private_Key > create_private_key(std::string_view alg_name, RandomNumberGenerator &rng, std::string_view params, std::string_view provider)
Definition pk_algs.cpp:406
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< std::string > split_on(std::string_view str, char delim)
Definition parsing.cpp:111
std::vector< std::string > probe_provider_private_key(std::string_view alg_name, const std::vector< std::string > &possible)
Definition pk_algs.cpp:591
std::unique_ptr< Private_Key > load_private_key(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition pk_algs.cpp:232
std::unique_ptr< Public_Key > load_public_key(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition pk_algs.cpp:103
std::unique_ptr< Private_Key > create_ec_private_key(std::string_view alg_name, const EC_Group &ec_group, RandomNumberGenerator &rng)
Definition pk_algs.cpp:361