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

randombit / botan / 5080663405

25 May 2023 02:18PM UTC coverage: 91.675% (-0.01%) from 91.688%
5080663405

Pull #3549

github

Pull Request #3549: SPHINCS+

78519 of 85649 relevant lines covered (91.68%)

12135443.66 hits per line

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

94.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/parsing.h>
11
#include <botan/internal/fmt.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>
92
load_public_key(const AlgorithmIdentifier& alg_id,
15,309✔
93
                [[maybe_unused]] std::span<const uint8_t> key_bits)
94
   {
95
   const std::string oid_str = alg_id.oid().to_formatted_string();
15,309✔
96
   const std::vector<std::string> alg_info = split_on(oid_str, '/');
15,309✔
97
   std::string_view alg_name = alg_info[0];
15,309✔
98

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

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

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

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

119
#if defined(BOTAN_HAS_ECDSA)
120
   if(alg_name == "ECDSA")
3,734✔
121
      return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
4,339✔
122
#endif
123

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

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

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

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

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

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

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

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

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

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

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

179
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
152✔
180
   }
15,463✔
181

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

190
#if defined(BOTAN_HAS_RSA)
191
   if(alg_name == "RSA")
3,589✔
192
      return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
2,102✔
193
#endif
194

195
#if defined(BOTAN_HAS_CURVE_25519)
196
   if(alg_name == "Curve25519")
1,256✔
197
      return std::make_unique<Curve25519_PrivateKey>(alg_id, key_bits);
54✔
198
#endif
199

200
#if defined(BOTAN_HAS_ECDSA)
201
   if(alg_name == "ECDSA")
1,226✔
202
      return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
908✔
203
#endif
204

205
#if defined(BOTAN_HAS_ECDH)
206
   if(alg_name == "ECDH")
606✔
207
      return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
158✔
208
#endif
209

210
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
211
   if(alg_name == "DH")
494✔
212
      return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
24✔
213
#endif
214

215
#if defined(BOTAN_HAS_DSA)
216
   if(alg_name == "DSA")
497✔
217
      return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
278✔
218
#endif
219

220
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
221
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-"))
264✔
222
      return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
36✔
223
#endif
224

225
#if defined(BOTAN_HAS_MCELIECE)
226
   if(alg_name == "McEliece")
228✔
227
      return std::make_unique<McEliece_PrivateKey>(key_bits);
4✔
228
#endif
229

230
#if defined(BOTAN_HAS_ECGDSA)
231
   if(alg_name == "ECGDSA")
224✔
232
      return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
36✔
233
#endif
234

235
#if defined(BOTAN_HAS_ECKCDSA)
236
   if(alg_name == "ECKCDSA")
230✔
237
      return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
36✔
238
#endif
239

240
#if defined(BOTAN_HAS_ED25519)
241
   if(alg_name == "Ed25519")
202✔
242
      return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
17✔
243
#endif
244

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

250
#if defined(BOTAN_HAS_SM2)
251
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
215✔
252
      return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
40✔
253
#endif
254

255
#if defined(BOTAN_HAS_ELGAMAL)
256
   if(alg_name == "ElGamal")
146✔
257
      return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
28✔
258
#endif
259

260
#if defined(BOTAN_HAS_XMSS_RFC8391)
261
   if(alg_name == "XMSS")
132✔
262
      return std::make_unique<XMSS_PrivateKey>(key_bits);
16✔
263
#endif
264

265
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
266
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-"))
128✔
267
      return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
55✔
268
#endif
269

270
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
122✔
271
   }
3,441✔
272

273
BOTAN_PUBLIC_API(3,0) std::unique_ptr<Private_Key>
274
create_ec_private_key(std::string_view alg_name,
126✔
275
                      const EC_Group& ec_group,
276
                      RandomNumberGenerator& rng)
277
   {
278
   // Potentially unused if all EC algorthms are disabled
279
   BOTAN_UNUSED(alg_name, ec_group, rng);
126✔
280

281
#if defined(BOTAN_HAS_ECDSA)
282
   if(alg_name == "ECDSA")
126✔
283
      return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
84✔
284
#endif
285

286
#if defined(BOTAN_HAS_ECDH)
287
   if(alg_name == "ECDH")
84✔
288
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
56✔
289
#endif
290

291
#if defined(BOTAN_HAS_ECKCDSA)
292
   if(alg_name == "ECKCDSA")
64✔
293
      return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
34✔
294
#endif
295

296
#if defined(BOTAN_HAS_GOST_34_10_2001)
297
   if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" || alg_name == "GOST-34.10-2012-512")
50✔
298
      return std::make_unique<GOST_3410_PrivateKey>(rng, ec_group);
22✔
299
#endif
300

301
#if defined(BOTAN_HAS_SM2)
302
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
40✔
303
      return std::make_unique<SM2_PrivateKey>(rng, ec_group);
22✔
304
#endif
305

306
#if defined(BOTAN_HAS_ECGDSA)
307
   if(alg_name == "ECGDSA")
17✔
308
      return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
34✔
309
#endif
310

311
   return nullptr;
×
312
   }
313

314

315
std::unique_ptr<Private_Key>
316
create_private_key(std::string_view alg_name,
252✔
317
                   RandomNumberGenerator& rng,
318
                   std::string_view params,
319
                   std::string_view provider)
320
   {
321
   /*
322
   * Default paramaters are chosen for work factor > 2**128 where possible
323
   */
324

325
#if defined(BOTAN_HAS_CURVE_25519)
326
   if(alg_name == "Curve25519")
263✔
327
      return std::make_unique<Curve25519_PrivateKey>(rng);
6✔
328
#endif
329

330
#if defined(BOTAN_HAS_RSA)
331
   if(alg_name == "RSA")
265✔
332
      {
333
      const size_t modulus_bits = params.empty() ? 3072 : to_u32bit(params);
43✔
334
      return std::make_unique<RSA_PrivateKey>(rng, modulus_bits);
43✔
335
      }
336
#endif
337

338
#if defined(BOTAN_HAS_MCELIECE)
339
   if(alg_name == "McEliece")
206✔
340
      {
341
      const auto [n, t] = [&]() -> std::pair<size_t, size_t>
2✔
342
         {
343
         if(params.empty())
2✔
344
            return {2960, 57};
×
345

346
         const auto mce_params = split_on(params, ',');
2✔
347

348
         if(mce_params.size() != 2)
2✔
349
            {
350
            throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
×
351
            }
352

353
         const size_t mce_n = to_u32bit(mce_params[0]);
2✔
354
         const size_t mce_t = to_u32bit(mce_params[1]);
2✔
355
         return {mce_n, mce_t};
2✔
356
         }();
4✔
357

358
      return std::make_unique<McEliece_PrivateKey>(rng, n, t);
2✔
359
      }
360
#endif
361

362
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
363
   if(alg_name == "Kyber")
246✔
364
      {
365
      const auto mode = [&]() -> KyberMode
16✔
366
         {
367
         if(params.empty())
8✔
368
            return KyberMode::Kyber1024;
1✔
369
         return KyberMode(params);
7✔
370
         }();
8✔
371

372
      return std::make_unique<Kyber_PrivateKey>(rng, mode);
8✔
373
      }
374
#endif
375

376
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
377
   if(alg_name == "Dilithium" || alg_name == "Dilithium-")
225✔
378
      {
379
      const auto mode = [&]() -> DilithiumMode
18✔
380
         {
381
         if(params.empty())
18✔
382
            return DilithiumMode::Dilithium6x5;
383
         return DilithiumMode(params);
10✔
384
         }();
18✔
385

386
      return std::make_unique<Dilithium_PrivateKey>(rng, mode);
18✔
387
      }
388
#endif
389

390
#if defined(BOTAN_HAS_SPHINCS_PLUS)
391
   if(alg_name == "SPHINCS+" || alg_name == "SphincsPlus-")
178✔
392
      {
393
      auto sphincs_params = Sphincs_Parameters::create(params);
×
394

395
      return std::make_unique<SphincsPlus_PrivateKey>(rng, sphincs_params);
×
396
      }
397
#endif
398

399
#if defined(BOTAN_HAS_XMSS_RFC8391)
400
   if(alg_name == "XMSS")
206✔
401
      {
402
      const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t
8✔
403
         {
404
         if(params.empty())
4✔
405
            return XMSS_Parameters::XMSS_SHA2_10_512;
406
         return XMSS_Parameters(params).oid();
3✔
407
         }();
4✔
408

409
      return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
4✔
410
      }
411
#endif
412

413
#if defined(BOTAN_HAS_ED25519)
414
   if(alg_name == "Ed25519")
206✔
415
      {
416
      return std::make_unique<Ed25519_PrivateKey>(rng);
20✔
417
      }
418
#endif
419

420
   // ECC crypto
421
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
422

423
   if(alg_name == "ECDSA" ||
206✔
424
      alg_name == "ECDH" ||
150✔
425
      alg_name == "ECKCDSA" ||
126✔
426
      alg_name == "ECGDSA" ||
94✔
427
      alg_name == "SM2" ||
76✔
428
      alg_name == "SM2_Sig" ||
72✔
429
      alg_name == "SM2_Enc" ||
58✔
430
      alg_name == "GOST-34.10" ||
60✔
431
      alg_name == "GOST-34.10-2012-256" ||
38✔
432
      alg_name == "GOST-34.10-2012-512")
38✔
433
      {
434
      const std::string group_id = [&]() -> std::string
252✔
435
         {
436
         if(!params.empty())
126✔
437
            return std::string(params);
117✔
438
         if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig")
9✔
439
            return "sm2p256v1";
×
440
         if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256")
9✔
441
            return "gost_256A";
×
442
         if(alg_name == "GOST-34.10-2012-512")
9✔
443
            return "gost_512A";
×
444
         if(alg_name == "ECGDSA")
9✔
445
            return "brainpool256r1";
×
446
         return "secp256r1";
9✔
447
         }();
126✔
448

449
      const EC_Group ec_group(group_id);
126✔
450
      return create_ec_private_key(alg_name, ec_group, rng);
126✔
451
      }
126✔
452
#endif
453

454
   // DL crypto
455
#if defined(BOTAN_HAS_DL_GROUP)
456
   if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal")
76✔
457
      {
458
      const std::string group_id = [&]() -> std::string
76✔
459
         {
460
         if(!params.empty())
38✔
461
            return std::string(params);
28✔
462
         if(alg_name == "DSA")
10✔
463
            return "dsa/botan/2048";
8✔
464
         return "modp/ietf/2048";
2✔
465
         }();
38✔
466

467
      DL_Group modp_group(group_id);
38✔
468

469
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
470
      if(alg_name == "DH")
38✔
471
         return std::make_unique<DH_PrivateKey>(rng, modp_group);
36✔
472
#endif
473

474
#if defined(BOTAN_HAS_DSA)
475
      if(alg_name == "DSA")
20✔
476
         return std::make_unique<DSA_PrivateKey>(rng, modp_group);
26✔
477
#endif
478

479
#if defined(BOTAN_HAS_ELGAMAL)
480
      if(alg_name == "ElGamal")
7✔
481
         return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
14✔
482
#endif
483
      }
38✔
484
#endif
485

486
   BOTAN_UNUSED(alg_name, rng, params, provider);
×
487

488
   return std::unique_ptr<Private_Key>();
252✔
489
   }
490

491
std::vector<std::string>
492
probe_provider_private_key(std::string_view alg_name,
43✔
493
                           const std::vector<std::string>& possible)
494
   {
495
   std::vector<std::string> providers;
43✔
496

497
   for(auto&& prov : possible)
215✔
498
      {
499
      if(prov == "base")
172✔
500
         providers.push_back(prov);
43✔
501
      }
502

503
   BOTAN_UNUSED(alg_name);
43✔
504

505
   return providers;
43✔
506
   }
×
507
}
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

© 2026 Coveralls, Inc