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

randombit / botan / 5122901828

30 May 2023 02:42PM UTC coverage: 92.22% (+0.01%) from 92.209%
5122901828

Pull #3549

github

web-flow
Merge 26dd3cf4b into 057bcbc35
Pull Request #3549: SPHINCS+

76784 of 83262 relevant lines covered (92.22%)

12270748.88 hits per line

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

93.82
/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,313✔
92
                                            [[maybe_unused]] std::span<const uint8_t> key_bits) {
93
   const std::string oid_str = alg_id.oid().to_formatted_string();
15,313✔
94
   const std::vector<std::string> alg_info = split_on(oid_str, '/');
15,313✔
95
   std::string_view alg_name = alg_info[0];
15,313✔
96

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

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

107
#if defined(BOTAN_HAS_MCELIECE)
108
   if(alg_name == "McEliece")
3,751✔
109
      return std::make_unique<McEliece_PublicKey>(key_bits);
2✔
110
#endif
111

112
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
113
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-"))
6,038✔
114
      return std::make_unique<Kyber_PublicKey>(alg_id, key_bits);
24✔
115
#endif
116

117
#if defined(BOTAN_HAS_ECDSA)
118
   if(alg_name == "ECDSA")
3,738✔
119
      return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
4,347✔
120
#endif
121

122
#if defined(BOTAN_HAS_ECDH)
123
   if(alg_name == "ECDH")
1,487✔
124
      return std::make_unique<ECDH_PublicKey>(alg_id, key_bits);
33✔
125
#endif
126

127
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
128
   if(alg_name == "DH")
1,432✔
129
      return std::make_unique<DH_PublicKey>(alg_id, key_bits);
16✔
130
#endif
131

132
#if defined(BOTAN_HAS_DSA)
133
   if(alg_name == "DSA")
1,433✔
134
      return std::make_unique<DSA_PublicKey>(alg_id, key_bits);
355✔
135
#endif
136

137
#if defined(BOTAN_HAS_ELGAMAL)
138
   if(alg_name == "ElGamal")
2,018✔
139
      return std::make_unique<ElGamal_PublicKey>(alg_id, key_bits);
8✔
140
#endif
141

142
#if defined(BOTAN_HAS_ECGDSA)
143
   if(alg_name == "ECGDSA")
1,180✔
144
      return std::make_unique<ECGDSA_PublicKey>(alg_id, key_bits);
144✔
145
#endif
146

147
#if defined(BOTAN_HAS_ECKCDSA)
148
   if(alg_name == "ECKCDSA")
1,871✔
149
      return std::make_unique<ECKCDSA_PublicKey>(alg_id, key_bits);
142✔
150
#endif
151

152
#if defined(BOTAN_HAS_ED25519)
153
   if(alg_name == "Ed25519")
1,038✔
154
      return std::make_unique<Ed25519_PublicKey>(alg_id, key_bits);
1,524✔
155
#endif
156

157
#if defined(BOTAN_HAS_GOST_34_10_2001)
158
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
353✔
159
      return std::make_unique<GOST_3410_PublicKey>(alg_id, key_bits);
130✔
160
#endif
161

162
#if defined(BOTAN_HAS_SM2)
163
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
226✔
164
      return std::make_unique<SM2_PublicKey>(alg_id, key_bits);
26✔
165
#endif
166

167
#if defined(BOTAN_HAS_XMSS_RFC8391)
168
   if(alg_name == "XMSS")
197✔
169
      return std::make_unique<XMSS_PublicKey>(key_bits);
76✔
170
#endif
171

172
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
173
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-"))
162✔
174
      return std::make_unique<Dilithium_PublicKey>(alg_id, key_bits);
166✔
175
#endif
176

177
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
152✔
178
}
15,467✔
179

180
std::unique_ptr<Private_Key> load_private_key(const AlgorithmIdentifier& alg_id,
3,356✔
181
                                              [[maybe_unused]] std::span<const uint8_t> key_bits) {
182
   const std::string oid_str = alg_id.oid().to_formatted_string();
3,356✔
183
   const std::vector<std::string> alg_info = split_on(oid_str, '/');
3,356✔
184
   std::string_view alg_name = alg_info[0];
3,356✔
185

186
#if defined(BOTAN_HAS_RSA)
187
   if(alg_name == "RSA")
3,589✔
188
      return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
2,102✔
189
#endif
190

191
#if defined(BOTAN_HAS_CURVE_25519)
192
   if(alg_name == "Curve25519")
1,256✔
193
      return std::make_unique<Curve25519_PrivateKey>(alg_id, key_bits);
54✔
194
#endif
195

196
#if defined(BOTAN_HAS_ECDSA)
197
   if(alg_name == "ECDSA")
1,226✔
198
      return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
908✔
199
#endif
200

201
#if defined(BOTAN_HAS_ECDH)
202
   if(alg_name == "ECDH")
606✔
203
      return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
158✔
204
#endif
205

206
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
207
   if(alg_name == "DH")
494✔
208
      return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
24✔
209
#endif
210

211
#if defined(BOTAN_HAS_DSA)
212
   if(alg_name == "DSA")
497✔
213
      return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
278✔
214
#endif
215

216
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
217
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-"))
264✔
218
      return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
36✔
219
#endif
220

221
#if defined(BOTAN_HAS_MCELIECE)
222
   if(alg_name == "McEliece")
228✔
223
      return std::make_unique<McEliece_PrivateKey>(key_bits);
4✔
224
#endif
225

226
#if defined(BOTAN_HAS_ECGDSA)
227
   if(alg_name == "ECGDSA")
224✔
228
      return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
36✔
229
#endif
230

231
#if defined(BOTAN_HAS_ECKCDSA)
232
   if(alg_name == "ECKCDSA")
230✔
233
      return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
36✔
234
#endif
235

236
#if defined(BOTAN_HAS_ED25519)
237
   if(alg_name == "Ed25519")
202✔
238
      return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
17✔
239
#endif
240

241
#if defined(BOTAN_HAS_GOST_34_10_2001)
242
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
194✔
243
      return std::make_unique<GOST_3410_PrivateKey>(alg_id, key_bits);
24✔
244
#endif
245

246
#if defined(BOTAN_HAS_SM2)
247
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
215✔
248
      return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
40✔
249
#endif
250

251
#if defined(BOTAN_HAS_ELGAMAL)
252
   if(alg_name == "ElGamal")
146✔
253
      return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
28✔
254
#endif
255

256
#if defined(BOTAN_HAS_XMSS_RFC8391)
257
   if(alg_name == "XMSS")
132✔
258
      return std::make_unique<XMSS_PrivateKey>(key_bits);
16✔
259
#endif
260

261
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
262
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-"))
128✔
263
      return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
55✔
264
#endif
265

266
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
122✔
267
}
3,441✔
268

269
std::unique_ptr<Private_Key> create_ec_private_key(std::string_view alg_name,
126✔
270
                                                   const EC_Group& ec_group,
271
                                                   RandomNumberGenerator& rng) {
272
   // Potentially unused if all EC algorthms are disabled
273
   BOTAN_UNUSED(alg_name, ec_group, rng);
126✔
274

275
#if defined(BOTAN_HAS_ECDSA)
276
   if(alg_name == "ECDSA")
126✔
277
      return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
84✔
278
#endif
279

280
#if defined(BOTAN_HAS_ECDH)
281
   if(alg_name == "ECDH")
84✔
282
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
56✔
283
#endif
284

285
#if defined(BOTAN_HAS_ECKCDSA)
286
   if(alg_name == "ECKCDSA")
64✔
287
      return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
34✔
288
#endif
289

290
#if defined(BOTAN_HAS_GOST_34_10_2001)
291
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
50✔
292
      return std::make_unique<GOST_3410_PrivateKey>(rng, ec_group);
22✔
293
#endif
294

295
#if defined(BOTAN_HAS_SM2)
296
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
40✔
297
      return std::make_unique<SM2_PrivateKey>(rng, ec_group);
22✔
298
#endif
299

300
#if defined(BOTAN_HAS_ECGDSA)
301
   if(alg_name == "ECGDSA")
17✔
302
      return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
34✔
303
#endif
304

305
   return nullptr;
×
306
}
307

308
std::unique_ptr<Private_Key> create_private_key(std::string_view alg_name,
252✔
309
                                                RandomNumberGenerator& rng,
310
                                                std::string_view params,
311
                                                std::string_view provider) {
312
   /*
313
   * Default paramaters are chosen for work factor > 2**128 where possible
314
   */
315

316
#if defined(BOTAN_HAS_CURVE_25519)
317
   if(alg_name == "Curve25519")
263✔
318
      return std::make_unique<Curve25519_PrivateKey>(rng);
6✔
319
#endif
320

321
#if defined(BOTAN_HAS_RSA)
322
   if(alg_name == "RSA") {
265✔
323
      const size_t modulus_bits = params.empty() ? 3072 : to_u32bit(params);
43✔
324
      return std::make_unique<RSA_PrivateKey>(rng, modulus_bits);
43✔
325
   }
326
#endif
327

328
#if defined(BOTAN_HAS_MCELIECE)
329
   if(alg_name == "McEliece") {
206✔
330
      const auto [n, t] = [&]() -> std::pair<size_t, size_t> {
2✔
331
         if(params.empty())
2✔
332
            return {2960, 57};
×
333

334
         const auto mce_params = split_on(params, ',');
2✔
335

336
         if(mce_params.size() != 2) {
2✔
337
            throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
×
338
         }
339

340
         const size_t mce_n = to_u32bit(mce_params[0]);
2✔
341
         const size_t mce_t = to_u32bit(mce_params[1]);
2✔
342
         return {mce_n, mce_t};
2✔
343
      }();
4✔
344

345
      return std::make_unique<McEliece_PrivateKey>(rng, n, t);
2✔
346
   }
347
#endif
348

349
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
350
   if(alg_name == "Kyber") {
246✔
351
      const auto mode = [&]() -> KyberMode {
16✔
352
         if(params.empty())
8✔
353
            return KyberMode::Kyber1024;
1✔
354
         return KyberMode(params);
7✔
355
      }();
8✔
356

357
      return std::make_unique<Kyber_PrivateKey>(rng, mode);
8✔
358
   }
359
#endif
360

361
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
362
   if(alg_name == "Dilithium" || alg_name == "Dilithium-") {
225✔
363
      const auto mode = [&]() -> DilithiumMode {
18✔
364
         if(params.empty())
18✔
365
            return DilithiumMode::Dilithium6x5;
366
         return DilithiumMode(params);
10✔
367
      }();
18✔
368

369
      return std::make_unique<Dilithium_PrivateKey>(rng, mode);
18✔
370
   }
371
#endif
372

373
#if defined(BOTAN_HAS_SPHINCS_PLUS)
374
   if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-") {
178✔
375
      auto sphincs_params = Sphincs_Parameters::create(params);
×
376

377
      return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
×
378
   }
379
#endif
380

381
#if defined(BOTAN_HAS_XMSS_RFC8391)
382
   if(alg_name == "XMSS") {
206✔
383
      const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t {
8✔
384
         if(params.empty())
4✔
385
            return XMSS_Parameters::XMSS_SHA2_10_512;
386
         return XMSS_Parameters(params).oid();
3✔
387
      }();
4✔
388

389
      return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
4✔
390
   }
391
#endif
392

393
#if defined(BOTAN_HAS_ED25519)
394
   if(alg_name == "Ed25519") {
206✔
395
      return std::make_unique<Ed25519_PrivateKey>(rng);
20✔
396
   }
397
#endif
398

399
   // ECC crypto
400
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
401

402
   if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" ||
299✔
403
      alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" ||
91✔
404
      alg_name == "GOST-34.10-2012-512") {
38✔
405
      const std::string group_id = [&]() -> std::string {
252✔
406
         if(!params.empty())
126✔
407
            return std::string(params);
117✔
408
         if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig")
9✔
409
            return "sm2p256v1";
×
410
         if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256")
9✔
411
            return "gost_256A";
×
412
         if(alg_name == "GOST-34.10-2012-512")
9✔
413
            return "gost_512A";
×
414
         if(alg_name == "ECGDSA")
9✔
415
            return "brainpool256r1";
×
416
         return "secp256r1";
9✔
417
      }();
126✔
418

419
      const EC_Group ec_group(group_id);
126✔
420
      return create_ec_private_key(alg_name, ec_group, rng);
126✔
421
   }
126✔
422
#endif
423

424
   // DL crypto
425
#if defined(BOTAN_HAS_DL_GROUP)
426
   if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") {
76✔
427
      const std::string group_id = [&]() -> std::string {
76✔
428
         if(!params.empty())
38✔
429
            return std::string(params);
28✔
430
         if(alg_name == "DSA")
10✔
431
            return "dsa/botan/2048";
8✔
432
         return "modp/ietf/2048";
2✔
433
      }();
38✔
434

435
      DL_Group modp_group(group_id);
38✔
436

437
   #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
438
      if(alg_name == "DH")
38✔
439
         return std::make_unique<DH_PrivateKey>(rng, modp_group);
36✔
440
   #endif
441

442
   #if defined(BOTAN_HAS_DSA)
443
      if(alg_name == "DSA")
20✔
444
         return std::make_unique<DSA_PrivateKey>(rng, modp_group);
26✔
445
   #endif
446

447
   #if defined(BOTAN_HAS_ELGAMAL)
448
      if(alg_name == "ElGamal")
7✔
449
         return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
14✔
450
   #endif
451
   }
38✔
452
#endif
453

454
   BOTAN_UNUSED(alg_name, rng, params, provider);
×
455

456
   return std::unique_ptr<Private_Key>();
252✔
457
}
458

459
std::vector<std::string> probe_provider_private_key(std::string_view alg_name,
43✔
460
                                                    const std::vector<std::string>& possible) {
461
   std::vector<std::string> providers;
43✔
462

463
   for(auto&& prov : possible) {
215✔
464
      if(prov == "base")
172✔
465
         providers.push_back(prov);
43✔
466
   }
467

468
   BOTAN_UNUSED(alg_name);
43✔
469

470
   return providers;
43✔
471
}
×
472
}  // 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