Botan 3.5.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_X25519)
66 #include <botan/x25519.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_HSS_LMS)
86 #include <botan/hss_lms.h>
87#endif
88
89#if defined(BOTAN_HAS_XMSS_RFC8391)
90 #include <botan/xmss.h>
91#endif
92
93#if defined(BOTAN_HAS_SM2)
94 #include <botan/sm2.h>
95#endif
96
97#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
98 #include <botan/dilithium.h>
99#endif
100
101#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
102 #include <botan/sphincsplus.h>
103#endif
104
105namespace Botan {
106
107std::unique_ptr<Public_Key> load_public_key(const AlgorithmIdentifier& alg_id,
108 [[maybe_unused]] std::span<const uint8_t> key_bits) {
109 const std::string oid_str = alg_id.oid().to_formatted_string();
110 const std::vector<std::string> alg_info = split_on(oid_str, '/');
111 std::string_view alg_name = alg_info[0];
112
113#if defined(BOTAN_HAS_RSA)
114 if(alg_name == "RSA") {
115 return std::make_unique<RSA_PublicKey>(alg_id, key_bits);
116 }
117#endif
118
119#if defined(BOTAN_HAS_X25519)
120 if(alg_name == "X25519" || alg_name == "Curve25519") {
121 return std::make_unique<X25519_PublicKey>(alg_id, key_bits);
122 }
123#endif
124
125#if defined(BOTAN_HAS_X448)
126 if(alg_name == "X448") {
127 return std::make_unique<X448_PublicKey>(alg_id, key_bits);
128 }
129#endif
130
131#if defined(BOTAN_HAS_MCELIECE)
132 if(alg_name == "McEliece") {
133 return std::make_unique<McEliece_PublicKey>(key_bits);
134 }
135#endif
136
137#if defined(BOTAN_HAS_FRODOKEM)
138 if(alg_name == "FrodoKEM" || alg_name.starts_with("FrodoKEM-") || alg_name.starts_with("eFrodoKEM-")) {
139 return std::make_unique<FrodoKEM_PublicKey>(alg_id, key_bits);
140 }
141#endif
142
143#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
144 if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
145 return std::make_unique<Kyber_PublicKey>(alg_id, key_bits);
146 }
147#endif
148
149#if defined(BOTAN_HAS_ECDSA)
150 if(alg_name == "ECDSA") {
151 return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
152 }
153#endif
154
155#if defined(BOTAN_HAS_ECDH)
156 if(alg_name == "ECDH") {
157 return std::make_unique<ECDH_PublicKey>(alg_id, key_bits);
158 }
159#endif
160
161#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
162 if(alg_name == "DH") {
163 return std::make_unique<DH_PublicKey>(alg_id, key_bits);
164 }
165#endif
166
167#if defined(BOTAN_HAS_DSA)
168 if(alg_name == "DSA") {
169 return std::make_unique<DSA_PublicKey>(alg_id, key_bits);
170 }
171#endif
172
173#if defined(BOTAN_HAS_ELGAMAL)
174 if(alg_name == "ElGamal") {
175 return std::make_unique<ElGamal_PublicKey>(alg_id, key_bits);
176 }
177#endif
178
179#if defined(BOTAN_HAS_ECGDSA)
180 if(alg_name == "ECGDSA") {
181 return std::make_unique<ECGDSA_PublicKey>(alg_id, key_bits);
182 }
183#endif
184
185#if defined(BOTAN_HAS_ECKCDSA)
186 if(alg_name == "ECKCDSA") {
187 return std::make_unique<ECKCDSA_PublicKey>(alg_id, key_bits);
188 }
189#endif
190
191#if defined(BOTAN_HAS_ED25519)
192 if(alg_name == "Ed25519") {
193 return std::make_unique<Ed25519_PublicKey>(alg_id, key_bits);
194 }
195#endif
196
197#if defined(BOTAN_HAS_ED448)
198 if(alg_name == "Ed448") {
199 return std::make_unique<Ed448_PublicKey>(alg_id, key_bits);
200 }
201#endif
202
203#if defined(BOTAN_HAS_GOST_34_10_2001)
204 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
205 return std::make_unique<GOST_3410_PublicKey>(alg_id, key_bits);
206 }
207#endif
208
209#if defined(BOTAN_HAS_SM2)
210 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
211 return std::make_unique<SM2_PublicKey>(alg_id, key_bits);
212 }
213#endif
214
215#if defined(BOTAN_HAS_XMSS_RFC8391)
216 if(alg_name == "XMSS") {
217 return std::make_unique<XMSS_PublicKey>(key_bits);
218 }
219#endif
220
221#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
222 if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
223 return std::make_unique<Dilithium_PublicKey>(alg_id, key_bits);
224 }
225#endif
226
227#if defined(BOTAN_HAS_HSS_LMS)
228 if(alg_name == "HSS-LMS") {
229 return std::make_unique<HSS_LMS_PublicKey>(key_bits);
230 }
231#endif
232
233#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
234 if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
235 return std::make_unique<SphincsPlus_PublicKey>(alg_id, key_bits);
236 }
237#endif
238
239 throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
240}
241
242std::unique_ptr<Private_Key> load_private_key(const AlgorithmIdentifier& alg_id,
243 [[maybe_unused]] std::span<const uint8_t> key_bits) {
244 const std::string oid_str = alg_id.oid().to_formatted_string();
245 const std::vector<std::string> alg_info = split_on(oid_str, '/');
246 std::string_view alg_name = alg_info[0];
247
248#if defined(BOTAN_HAS_RSA)
249 if(alg_name == "RSA") {
250 return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
251 }
252#endif
253
254#if defined(BOTAN_HAS_X25519)
255 if(alg_name == "X25519" || alg_name == "Curve25519") {
256 return std::make_unique<X25519_PrivateKey>(alg_id, key_bits);
257 }
258#endif
259
260#if defined(BOTAN_HAS_X448)
261 if(alg_name == "X448") {
262 return std::make_unique<X448_PrivateKey>(alg_id, key_bits);
263 }
264#endif
265
266#if defined(BOTAN_HAS_ECDSA)
267 if(alg_name == "ECDSA") {
268 return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
269 }
270#endif
271
272#if defined(BOTAN_HAS_ECDH)
273 if(alg_name == "ECDH") {
274 return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
275 }
276#endif
277
278#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
279 if(alg_name == "DH") {
280 return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
281 }
282#endif
283
284#if defined(BOTAN_HAS_DSA)
285 if(alg_name == "DSA") {
286 return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
287 }
288#endif
289
290#if defined(BOTAN_HAS_FRODOKEM)
291 if(alg_name == "FrodoKEM" || alg_name.starts_with("FrodoKEM-") || alg_name.starts_with("eFrodoKEM-")) {
292 return std::make_unique<FrodoKEM_PrivateKey>(alg_id, key_bits);
293 }
294#endif
295
296#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
297 if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
298 return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
299 }
300#endif
301
302#if defined(BOTAN_HAS_MCELIECE)
303 if(alg_name == "McEliece") {
304 return std::make_unique<McEliece_PrivateKey>(key_bits);
305 }
306#endif
307
308#if defined(BOTAN_HAS_ECGDSA)
309 if(alg_name == "ECGDSA") {
310 return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
311 }
312#endif
313
314#if defined(BOTAN_HAS_ECKCDSA)
315 if(alg_name == "ECKCDSA") {
316 return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
317 }
318#endif
319
320#if defined(BOTAN_HAS_ED25519)
321 if(alg_name == "Ed25519") {
322 return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
323 }
324#endif
325
326#if defined(BOTAN_HAS_ED448)
327 if(alg_name == "Ed448") {
328 return std::make_unique<Ed448_PrivateKey>(alg_id, key_bits);
329 }
330#endif
331
332#if defined(BOTAN_HAS_GOST_34_10_2001)
333 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
334 return std::make_unique<GOST_3410_PrivateKey>(alg_id, key_bits);
335 }
336#endif
337
338#if defined(BOTAN_HAS_SM2)
339 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
340 return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
341 }
342#endif
343
344#if defined(BOTAN_HAS_ELGAMAL)
345 if(alg_name == "ElGamal") {
346 return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
347 }
348#endif
349
350#if defined(BOTAN_HAS_XMSS_RFC8391)
351 if(alg_name == "XMSS") {
352 return std::make_unique<XMSS_PrivateKey>(key_bits);
353 }
354#endif
355
356#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
357 if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
358 return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
359 }
360#endif
361
362#if defined(BOTAN_HAS_HSS_LMS)
363 if(alg_name == "HSS-LMS-Private-Key") {
364 return std::make_unique<HSS_LMS_PrivateKey>(key_bits);
365 }
366#endif
367
368#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
369 if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
370 return std::make_unique<SphincsPlus_PrivateKey>(alg_id, key_bits);
371 }
372#endif
373
374 throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
375}
376
377std::unique_ptr<Private_Key> create_ec_private_key(std::string_view alg_name,
378 const EC_Group& ec_group,
380 // Potentially unused if all EC algorithms are disabled
381 BOTAN_UNUSED(alg_name, ec_group, rng);
382
383#if defined(BOTAN_HAS_ECDSA)
384 if(alg_name == "ECDSA") {
385 return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
386 }
387#endif
388
389#if defined(BOTAN_HAS_ECDH)
390 if(alg_name == "ECDH") {
391 return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
392 }
393#endif
394
395#if defined(BOTAN_HAS_ECKCDSA)
396 if(alg_name == "ECKCDSA") {
397 return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
398 }
399#endif
400
401#if defined(BOTAN_HAS_GOST_34_10_2001)
402 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
403 return std::make_unique<GOST_3410_PrivateKey>(rng, ec_group);
404 }
405#endif
406
407#if defined(BOTAN_HAS_SM2)
408 if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
409 return std::make_unique<SM2_PrivateKey>(rng, ec_group);
410 }
411#endif
412
413#if defined(BOTAN_HAS_ECGDSA)
414 if(alg_name == "ECGDSA") {
415 return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
416 }
417#endif
418
419 return nullptr;
420}
421
422std::unique_ptr<Private_Key> create_private_key(std::string_view alg_name,
424 std::string_view params,
425 std::string_view provider) {
426 /*
427 * Default paramaters are chosen for work factor > 2**128 where possible
428 */
429
430#if defined(BOTAN_HAS_X25519)
431 if(alg_name == "X25519" || alg_name == "Curve25519") {
432 return std::make_unique<X25519_PrivateKey>(rng);
433 }
434#endif
435
436#if defined(BOTAN_HAS_X448)
437 if(alg_name == "X448") {
438 return std::make_unique<X448_PrivateKey>(rng);
439 }
440#endif
441
442#if defined(BOTAN_HAS_RSA)
443 if(alg_name == "RSA") {
444 const size_t modulus_bits = params.empty() ? 3072 : to_u32bit(params);
445 return std::make_unique<RSA_PrivateKey>(rng, modulus_bits);
446 }
447#endif
448
449#if defined(BOTAN_HAS_MCELIECE)
450 if(alg_name == "McEliece") {
451 const auto [n, t] = [&]() -> std::pair<size_t, size_t> {
452 if(params.empty()) {
453 return {2960, 57};
454 }
455
456 const auto mce_params = split_on(params, ',');
457
458 if(mce_params.size() != 2) {
459 throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
460 }
461
462 const size_t mce_n = to_u32bit(mce_params[0]);
463 const size_t mce_t = to_u32bit(mce_params[1]);
464 return {mce_n, mce_t};
465 }();
466
467 return std::make_unique<McEliece_PrivateKey>(rng, n, t);
468 }
469#endif
470
471#if defined(BOTAN_HAS_FRODOKEM)
472 if(alg_name == "FrodoKEM") {
473 const auto mode = params.empty() ? FrodoKEMMode::FrodoKEM976_SHAKE : FrodoKEMMode(params);
474 return std::make_unique<FrodoKEM_PrivateKey>(rng, mode);
475 }
476#endif
477
478#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
479 if(alg_name == "Kyber") {
480 const auto mode = [&]() -> KyberMode {
481 if(params.empty()) {
483 }
484 return KyberMode(params);
485 }();
486
487 return std::make_unique<Kyber_PrivateKey>(rng, mode);
488 }
489#endif
490
491#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
492 if(alg_name == "Dilithium" || alg_name == "Dilithium-") {
493 const auto mode = [&]() -> DilithiumMode {
494 if(params.empty()) {
496 }
497 return DilithiumMode(params);
498 }();
499
500 return std::make_unique<Dilithium_PrivateKey>(rng, mode);
501 }
502#endif
503
504#if defined(BOTAN_HAS_HSS_LMS)
505 if(alg_name == "HSS-LMS") {
506 return std::make_unique<HSS_LMS_PrivateKey>(rng, params);
507 }
508#endif
509
510#if defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHA2) || defined(BOTAN_HAS_SPHINCS_PLUS_WITH_SHAKE)
511 if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-") {
512 auto sphincs_params = Sphincs_Parameters::create(params);
513
514 return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
515 }
516#endif
517
518#if defined(BOTAN_HAS_XMSS_RFC8391)
519 if(alg_name == "XMSS") {
520 const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t {
521 if(params.empty()) {
523 }
524 return XMSS_Parameters(params).oid();
525 }();
526
527 return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
528 }
529#endif
530
531#if defined(BOTAN_HAS_ED25519)
532 if(alg_name == "Ed25519") {
533 return std::make_unique<Ed25519_PrivateKey>(rng);
534 }
535#endif
536
537#if defined(BOTAN_HAS_ED448)
538 if(alg_name == "Ed448") {
539 return std::make_unique<Ed448_PrivateKey>(rng);
540 }
541#endif
542
543 // ECC crypto
544#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
545
546 if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" ||
547 alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" ||
548 alg_name == "GOST-34.10-2012-512") {
549 const std::string group_id = [&]() -> std::string {
550 if(!params.empty()) {
551 return std::string(params);
552 }
553 if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig") {
554 return "sm2p256v1";
555 }
556 if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256") {
557 return "gost_256A";
558 }
559 if(alg_name == "GOST-34.10-2012-512") {
560 return "gost_512A";
561 }
562 if(alg_name == "ECGDSA") {
563 return "brainpool256r1";
564 }
565 return "secp256r1";
566 }();
567
568 auto ec_group = EC_Group::from_name(group_id);
569 return create_ec_private_key(alg_name, ec_group, rng);
570 }
571#endif
572
573 // DL crypto
574#if defined(BOTAN_HAS_DL_GROUP)
575 if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") {
576 const std::string group_id = [&]() -> std::string {
577 if(!params.empty()) {
578 return std::string(params);
579 }
580 if(alg_name == "DSA") {
581 return "dsa/botan/2048";
582 }
583 return "modp/ietf/2048";
584 }();
585
586 DL_Group modp_group(group_id);
587
588 #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
589 if(alg_name == "DH") {
590 return std::make_unique<DH_PrivateKey>(rng, modp_group);
591 }
592 #endif
593
594 #if defined(BOTAN_HAS_DSA)
595 if(alg_name == "DSA") {
596 return std::make_unique<DSA_PrivateKey>(rng, modp_group);
597 }
598 #endif
599
600 #if defined(BOTAN_HAS_ELGAMAL)
601 if(alg_name == "ElGamal") {
602 return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
603 }
604 #endif
605 }
606#endif
607
608 BOTAN_UNUSED(alg_name, rng, params, provider);
609
610 return std::unique_ptr<Private_Key>();
611}
612
613std::vector<std::string> probe_provider_private_key(std::string_view alg_name,
614 const std::vector<std::string>& possible) {
615 std::vector<std::string> providers;
616
617 for(auto&& prov : possible) {
618 if(prov == "base") {
619 providers.push_back(prov);
620 }
621 }
622
623 BOTAN_UNUSED(alg_name);
624
625 return providers;
626}
627} // namespace Botan
#define BOTAN_UNUSED
Definition assert.h:118
const OID & oid() const
Definition asn1_obj.h:464
static EC_Group from_name(std::string_view name)
Definition ec_group.cpp:420
std::string to_formatted_string() const
Definition asn1_oid.cpp:139
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:422
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:613
std::unique_ptr< Private_Key > load_private_key(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition pk_algs.cpp:242
std::unique_ptr< Public_Key > load_public_key(const AlgorithmIdentifier &alg_id, std::span< const uint8_t > key_bits)
Definition pk_algs.cpp:107
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:377