• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

randombit / botan / 5133942576

31 May 2023 02:12PM UTC coverage: 92.023% (+0.01%) from 92.012%
5133942576

Pull #3549

github

web-flow
Merge 3ab81f7da into 1cbeffafb
Pull Request #3549: SPHINCS+

76876 of 83540 relevant lines covered (92.02%)

12184513.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

95.05
/src/lib/pubkey/pk_algs.cpp
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_GOST_34_10_2001)
50
   #include <botan/gost_3410.h>
51
#endif
52

53
#if defined(BOTAN_HAS_ELGAMAL)
54
   #include <botan/elgamal.h>
55
#endif
56

57
#if defined(BOTAN_HAS_ECDH)
58
   #include <botan/ecdh.h>
59
#endif
60

61
#if defined(BOTAN_HAS_CURVE_25519)
62
   #include <botan/curve25519.h>
63
#endif
64

65
#if defined(BOTAN_HAS_MCELIECE)
66
   #include <botan/mceliece.h>
67
#endif
68

69
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
70
   #include <botan/kyber.h>
71
#endif
72

73
#if defined(BOTAN_HAS_XMSS_RFC8391)
74
   #include <botan/xmss.h>
75
#endif
76

77
#if defined(BOTAN_HAS_SM2)
78
   #include <botan/sm2.h>
79
#endif
80

81
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
82
   #include <botan/dilithium.h>
83
#endif
84

85
#if defined(BOTAN_HAS_SPHINCS_PLUS)
86
   #include <botan/sphincsplus.h>
87
#endif
88

89
namespace Botan {
90

91
std::unique_ptr<Public_Key> load_public_key(const AlgorithmIdentifier& alg_id,
15,337✔
92
                                            [[maybe_unused]] std::span<const uint8_t> key_bits) {
93
   const std::string oid_str = alg_id.oid().to_formatted_string();
15,337✔
94
   const std::vector<std::string> alg_info = split_on(oid_str, '/');
15,337✔
95
   std::string_view alg_name = alg_info[0];
15,337✔
96

97
#if defined(BOTAN_HAS_RSA)
98
   if(alg_name == "RSA") {
15,586✔
99
      return std::make_unique<RSA_PublicKey>(alg_id, key_bits);
22,229✔
100
   }
101
#endif
102

103
#if defined(BOTAN_HAS_CURVE_25519)
104
   if(alg_name == "Curve25519") {
3,797✔
105
      return std::make_unique<Curve25519_PublicKey>(alg_id, key_bits);
44✔
106
   }
107
#endif
108

109
#if defined(BOTAN_HAS_MCELIECE)
110
   if(alg_name == "McEliece") {
3,775✔
111
      return std::make_unique<McEliece_PublicKey>(key_bits);
2✔
112
   }
113
#endif
114

115
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
116
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
6,062✔
117
      return std::make_unique<Kyber_PublicKey>(alg_id, key_bits);
24✔
118
   }
119
#endif
120

121
#if defined(BOTAN_HAS_ECDSA)
122
   if(alg_name == "ECDSA") {
3,762✔
123
      return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
4,347✔
124
   }
125
#endif
126

127
#if defined(BOTAN_HAS_ECDH)
128
   if(alg_name == "ECDH") {
1,511✔
129
      return std::make_unique<ECDH_PublicKey>(alg_id, key_bits);
33✔
130
   }
131
#endif
132

133
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
134
   if(alg_name == "DH") {
1,456✔
135
      return std::make_unique<DH_PublicKey>(alg_id, key_bits);
16✔
136
   }
137
#endif
138

139
#if defined(BOTAN_HAS_DSA)
140
   if(alg_name == "DSA") {
1,457✔
141
      return std::make_unique<DSA_PublicKey>(alg_id, key_bits);
355✔
142
   }
143
#endif
144

145
#if defined(BOTAN_HAS_ELGAMAL)
146
   if(alg_name == "ElGamal") {
2,042✔
147
      return std::make_unique<ElGamal_PublicKey>(alg_id, key_bits);
8✔
148
   }
149
#endif
150

151
#if defined(BOTAN_HAS_ECGDSA)
152
   if(alg_name == "ECGDSA") {
1,204✔
153
      return std::make_unique<ECGDSA_PublicKey>(alg_id, key_bits);
144✔
154
   }
155
#endif
156

157
#if defined(BOTAN_HAS_ECKCDSA)
158
   if(alg_name == "ECKCDSA") {
1,895✔
159
      return std::make_unique<ECKCDSA_PublicKey>(alg_id, key_bits);
142✔
160
   }
161
#endif
162

163
#if defined(BOTAN_HAS_ED25519)
164
   if(alg_name == "Ed25519") {
1,062✔
165
      return std::make_unique<Ed25519_PublicKey>(alg_id, key_bits);
1,524✔
166
   }
167
#endif
168

169
#if defined(BOTAN_HAS_GOST_34_10_2001)
170
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
377✔
171
      return std::make_unique<GOST_3410_PublicKey>(alg_id, key_bits);
130✔
172
   }
173
#endif
174

175
#if defined(BOTAN_HAS_SM2)
176
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
250✔
177
      return std::make_unique<SM2_PublicKey>(alg_id, key_bits);
26✔
178
   }
179
#endif
180

181
#if defined(BOTAN_HAS_XMSS_RFC8391)
182
   if(alg_name == "XMSS") {
221✔
183
      return std::make_unique<XMSS_PublicKey>(key_bits);
76✔
184
   }
185
#endif
186

187
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
188
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
186✔
189
      return std::make_unique<Dilithium_PublicKey>(alg_id, key_bits);
166✔
190
   }
191
#endif
192

193
#if defined(BOTAN_HAS_SPHINCS_PLUS)
194
   if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
101✔
195
      return std::make_unique<SphincsPlus_PublicKey>(alg_id, key_bits);
48✔
196
   }
197
#endif
198

199
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
152✔
200
}
15,515✔
201

202
std::unique_ptr<Private_Key> load_private_key(const AlgorithmIdentifier& alg_id,
3,428✔
203
                                              [[maybe_unused]] std::span<const uint8_t> key_bits) {
204
   const std::string oid_str = alg_id.oid().to_formatted_string();
3,428✔
205
   const std::vector<std::string> alg_info = split_on(oid_str, '/');
3,428✔
206
   std::string_view alg_name = alg_info[0];
3,428✔
207

208
#if defined(BOTAN_HAS_RSA)
209
   if(alg_name == "RSA") {
3,661✔
210
      return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
2,102✔
211
   }
212
#endif
213

214
#if defined(BOTAN_HAS_CURVE_25519)
215
   if(alg_name == "Curve25519") {
1,328✔
216
      return std::make_unique<Curve25519_PrivateKey>(alg_id, key_bits);
54✔
217
   }
218
#endif
219

220
#if defined(BOTAN_HAS_ECDSA)
221
   if(alg_name == "ECDSA") {
1,298✔
222
      return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
908✔
223
   }
224
#endif
225

226
#if defined(BOTAN_HAS_ECDH)
227
   if(alg_name == "ECDH") {
678✔
228
      return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
158✔
229
   }
230
#endif
231

232
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
233
   if(alg_name == "DH") {
566✔
234
      return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
24✔
235
   }
236
#endif
237

238
#if defined(BOTAN_HAS_DSA)
239
   if(alg_name == "DSA") {
569✔
240
      return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
278✔
241
   }
242
#endif
243

244
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
245
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-")) {
336✔
246
      return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
36✔
247
   }
248
#endif
249

250
#if defined(BOTAN_HAS_MCELIECE)
251
   if(alg_name == "McEliece") {
300✔
252
      return std::make_unique<McEliece_PrivateKey>(key_bits);
4✔
253
   }
254
#endif
255

256
#if defined(BOTAN_HAS_ECGDSA)
257
   if(alg_name == "ECGDSA") {
296✔
258
      return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
36✔
259
   }
260
#endif
261

262
#if defined(BOTAN_HAS_ECKCDSA)
263
   if(alg_name == "ECKCDSA") {
302✔
264
      return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
36✔
265
   }
266
#endif
267

268
#if defined(BOTAN_HAS_ED25519)
269
   if(alg_name == "Ed25519") {
274✔
270
      return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
17✔
271
   }
272
#endif
273

274
#if defined(BOTAN_HAS_GOST_34_10_2001)
275
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
266✔
276
      return std::make_unique<GOST_3410_PrivateKey>(alg_id, key_bits);
24✔
277
   }
278
#endif
279

280
#if defined(BOTAN_HAS_SM2)
281
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
287✔
282
      return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
40✔
283
   }
284
#endif
285

286
#if defined(BOTAN_HAS_ELGAMAL)
287
   if(alg_name == "ElGamal") {
218✔
288
      return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
28✔
289
   }
290
#endif
291

292
#if defined(BOTAN_HAS_XMSS_RFC8391)
293
   if(alg_name == "XMSS") {
204✔
294
      return std::make_unique<XMSS_PrivateKey>(key_bits);
16✔
295
   }
296
#endif
297

298
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
299
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-")) {
200✔
300
      return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
55✔
301
   }
302
#endif
303

304
#if defined(BOTAN_HAS_SPHINCS_PLUS)
305
   if(alg_name == "SPHINCS+" || alg_name.starts_with("SphincsPlus-")) {
133✔
306
      return std::make_unique<SphincsPlus_PrivateKey>(alg_id, key_bits);
72✔
307
   }
308
#endif
309

310
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
122✔
311
}
3,585✔
312

313
std::unique_ptr<Private_Key> create_ec_private_key(std::string_view alg_name,
126✔
314
                                                   const EC_Group& ec_group,
315
                                                   RandomNumberGenerator& rng) {
316
   // Potentially unused if all EC algorthms are disabled
317
   BOTAN_UNUSED(alg_name, ec_group, rng);
126✔
318

319
#if defined(BOTAN_HAS_ECDSA)
320
   if(alg_name == "ECDSA") {
126✔
321
      return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
84✔
322
   }
323
#endif
324

325
#if defined(BOTAN_HAS_ECDH)
326
   if(alg_name == "ECDH") {
84✔
327
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
56✔
328
   }
329
#endif
330

331
#if defined(BOTAN_HAS_ECKCDSA)
332
   if(alg_name == "ECKCDSA") {
64✔
333
      return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
34✔
334
   }
335
#endif
336

337
#if defined(BOTAN_HAS_GOST_34_10_2001)
338
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512") {
50✔
339
      return std::make_unique<GOST_3410_PrivateKey>(rng, ec_group);
22✔
340
   }
341
#endif
342

343
#if defined(BOTAN_HAS_SM2)
344
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc") {
40✔
345
      return std::make_unique<SM2_PrivateKey>(rng, ec_group);
22✔
346
   }
347
#endif
348

349
#if defined(BOTAN_HAS_ECGDSA)
350
   if(alg_name == "ECGDSA") {
17✔
351
      return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
34✔
352
   }
353
#endif
354

355
   return nullptr;
×
356
}
357

358
std::unique_ptr<Private_Key> create_private_key(std::string_view alg_name,
264✔
359
                                                RandomNumberGenerator& rng,
360
                                                std::string_view params,
361
                                                std::string_view provider) {
362
   /*
363
   * Default paramaters are chosen for work factor > 2**128 where possible
364
   */
365

366
#if defined(BOTAN_HAS_CURVE_25519)
367
   if(alg_name == "Curve25519") {
275✔
368
      return std::make_unique<Curve25519_PrivateKey>(rng);
6✔
369
   }
370
#endif
371

372
#if defined(BOTAN_HAS_RSA)
373
   if(alg_name == "RSA") {
277✔
374
      const size_t modulus_bits = params.empty() ? 3072 : to_u32bit(params);
43✔
375
      return std::make_unique<RSA_PrivateKey>(rng, modulus_bits);
43✔
376
   }
377
#endif
378

379
#if defined(BOTAN_HAS_MCELIECE)
380
   if(alg_name == "McEliece") {
230✔
381
      const auto [n, t] = [&]() -> std::pair<size_t, size_t> {
2✔
382
         if(params.empty()) {
2✔
383
            return {2960, 57};
×
384
         }
385

386
         const auto mce_params = split_on(params, ',');
2✔
387

388
         if(mce_params.size() != 2) {
2✔
389
            throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
×
390
         }
391

392
         const size_t mce_n = to_u32bit(mce_params[0]);
2✔
393
         const size_t mce_t = to_u32bit(mce_params[1]);
2✔
394
         return {mce_n, mce_t};
2✔
395
      }();
4✔
396

397
      return std::make_unique<McEliece_PrivateKey>(rng, n, t);
2✔
398
   }
399
#endif
400

401
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
402
   if(alg_name == "Kyber") {
258✔
403
      const auto mode = [&]() -> KyberMode {
16✔
404
         if(params.empty()) {
8✔
405
            return KyberMode::Kyber1024;
1✔
406
         }
407
         return KyberMode(params);
7✔
408
      }();
8✔
409

410
      return std::make_unique<Kyber_PrivateKey>(rng, mode);
8✔
411
   }
412
#endif
413

414
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
415
   if(alg_name == "Dilithium" || alg_name == "Dilithium-") {
237✔
416
      const auto mode = [&]() -> DilithiumMode {
18✔
417
         if(params.empty()) {
18✔
418
            return DilithiumMode::Dilithium6x5;
419
         }
420
         return DilithiumMode(params);
10✔
421
      }();
18✔
422

423
      return std::make_unique<Dilithium_PrivateKey>(rng, mode);
18✔
424
   }
425
#endif
426

427
#if defined(BOTAN_HAS_SPHINCS_PLUS)
428
   if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-") {
202✔
429
      auto sphincs_params = Sphincs_Parameters::create(params);
12✔
430

431
      return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
12✔
432
   }
433
#endif
434

435
#if defined(BOTAN_HAS_XMSS_RFC8391)
436
   if(alg_name == "XMSS") {
206✔
437
      const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t {
8✔
438
         if(params.empty()) {
4✔
439
            return XMSS_Parameters::XMSS_SHA2_10_512;
440
         }
441
         return XMSS_Parameters(params).oid();
3✔
442
      }();
4✔
443

444
      return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
4✔
445
   }
446
#endif
447

448
#if defined(BOTAN_HAS_ED25519)
449
   if(alg_name == "Ed25519") {
206✔
450
      return std::make_unique<Ed25519_PrivateKey>(rng);
20✔
451
   }
452
#endif
453

454
   // ECC crypto
455
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
456

457
   if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" ||
299✔
458
      alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" ||
91✔
459
      alg_name == "GOST-34.10-2012-512") {
38✔
460
      const std::string group_id = [&]() -> std::string {
252✔
461
         if(!params.empty()) {
126✔
462
            return std::string(params);
117✔
463
         }
464
         if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig") {
9✔
465
            return "sm2p256v1";
×
466
         }
467
         if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256") {
9✔
468
            return "gost_256A";
×
469
         }
470
         if(alg_name == "GOST-34.10-2012-512") {
9✔
471
            return "gost_512A";
×
472
         }
473
         if(alg_name == "ECGDSA") {
9✔
474
            return "brainpool256r1";
×
475
         }
476
         return "secp256r1";
9✔
477
      }();
126✔
478

479
      const EC_Group ec_group(group_id);
126✔
480
      return create_ec_private_key(alg_name, ec_group, rng);
126✔
481
   }
126✔
482
#endif
483

484
   // DL crypto
485
#if defined(BOTAN_HAS_DL_GROUP)
486
   if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") {
76✔
487
      const std::string group_id = [&]() -> std::string {
76✔
488
         if(!params.empty()) {
38✔
489
            return std::string(params);
28✔
490
         }
491
         if(alg_name == "DSA") {
10✔
492
            return "dsa/botan/2048";
8✔
493
         }
494
         return "modp/ietf/2048";
2✔
495
      }();
38✔
496

497
      DL_Group modp_group(group_id);
38✔
498

499
   #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
500
      if(alg_name == "DH") {
38✔
501
         return std::make_unique<DH_PrivateKey>(rng, modp_group);
36✔
502
      }
503
   #endif
504

505
   #if defined(BOTAN_HAS_DSA)
506
      if(alg_name == "DSA") {
20✔
507
         return std::make_unique<DSA_PrivateKey>(rng, modp_group);
26✔
508
      }
509
   #endif
510

511
   #if defined(BOTAN_HAS_ELGAMAL)
512
      if(alg_name == "ElGamal") {
7✔
513
         return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
14✔
514
      }
515
   #endif
516
   }
38✔
517
#endif
518

519
   BOTAN_UNUSED(alg_name, rng, params, provider);
×
520

521
   return std::unique_ptr<Private_Key>();
264✔
522
}
523

524
std::vector<std::string> probe_provider_private_key(std::string_view alg_name,
55✔
525
                                                    const std::vector<std::string>& possible) {
526
   std::vector<std::string> providers;
55✔
527

528
   for(auto&& prov : possible) {
275✔
529
      if(prov == "base") {
220✔
530
         providers.push_back(prov);
55✔
531
      }
532
   }
533

534
   BOTAN_UNUSED(alg_name);
55✔
535

536
   return providers;
55✔
537
}
×
538
}  // namespace Botan
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc