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

randombit / botan / 5111374265

29 May 2023 11:19AM UTC coverage: 92.227% (+0.5%) from 91.723%
5111374265

push

github

randombit
Next release will be 3.1.0. Update release notes

75588 of 81959 relevant lines covered (92.23%)

11886470.91 hits per line

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

94.86
/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
namespace Botan {
86

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

93
#if defined(BOTAN_HAS_RSA)
94
   if(alg_name == "RSA")
15,570✔
95
      return std::make_unique<RSA_PublicKey>(alg_id, key_bits);
22,237✔
96
#endif
97

98
#if defined(BOTAN_HAS_CURVE_25519)
99
   if(alg_name == "Curve25519")
3,777✔
100
      return std::make_unique<Curve25519_PublicKey>(alg_id, key_bits);
44✔
101
#endif
102

103
#if defined(BOTAN_HAS_MCELIECE)
104
   if(alg_name == "McEliece")
3,755✔
105
      return std::make_unique<McEliece_PublicKey>(key_bits);
2✔
106
#endif
107

108
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
109
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-"))
6,046✔
110
      return std::make_unique<Kyber_PublicKey>(alg_id, key_bits);
24✔
111
#endif
112

113
#if defined(BOTAN_HAS_ECDSA)
114
   if(alg_name == "ECDSA")
3,742✔
115
      return std::make_unique<ECDSA_PublicKey>(alg_id, key_bits);
4,355✔
116
#endif
117

118
#if defined(BOTAN_HAS_ECDH)
119
   if(alg_name == "ECDH")
1,487✔
120
      return std::make_unique<ECDH_PublicKey>(alg_id, key_bits);
33✔
121
#endif
122

123
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
124
   if(alg_name == "DH")
1,432✔
125
      return std::make_unique<DH_PublicKey>(alg_id, key_bits);
16✔
126
#endif
127

128
#if defined(BOTAN_HAS_DSA)
129
   if(alg_name == "DSA")
1,433✔
130
      return std::make_unique<DSA_PublicKey>(alg_id, key_bits);
355✔
131
#endif
132

133
#if defined(BOTAN_HAS_ELGAMAL)
134
   if(alg_name == "ElGamal")
2,018✔
135
      return std::make_unique<ElGamal_PublicKey>(alg_id, key_bits);
8✔
136
#endif
137

138
#if defined(BOTAN_HAS_ECGDSA)
139
   if(alg_name == "ECGDSA")
1,180✔
140
      return std::make_unique<ECGDSA_PublicKey>(alg_id, key_bits);
144✔
141
#endif
142

143
#if defined(BOTAN_HAS_ECKCDSA)
144
   if(alg_name == "ECKCDSA")
1,871✔
145
      return std::make_unique<ECKCDSA_PublicKey>(alg_id, key_bits);
142✔
146
#endif
147

148
#if defined(BOTAN_HAS_ED25519)
149
   if(alg_name == "Ed25519")
1,038✔
150
      return std::make_unique<Ed25519_PublicKey>(alg_id, key_bits);
1,524✔
151
#endif
152

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

158
#if defined(BOTAN_HAS_SM2)
159
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
226✔
160
      return std::make_unique<SM2_PublicKey>(alg_id, key_bits);
26✔
161
#endif
162

163
#if defined(BOTAN_HAS_XMSS_RFC8391)
164
   if(alg_name == "XMSS")
197✔
165
      return std::make_unique<XMSS_PublicKey>(key_bits);
76✔
166
#endif
167

168
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
169
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-"))
162✔
170
      return std::make_unique<Dilithium_PublicKey>(alg_id, key_bits);
166✔
171
#endif
172

173
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
152✔
174
}
15,321✔
175

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

182
#if defined(BOTAN_HAS_RSA)
183
   if(alg_name == "RSA")
3,589✔
184
      return std::make_unique<RSA_PrivateKey>(alg_id, key_bits);
2,102✔
185
#endif
186

187
#if defined(BOTAN_HAS_CURVE_25519)
188
   if(alg_name == "Curve25519")
1,256✔
189
      return std::make_unique<Curve25519_PrivateKey>(alg_id, key_bits);
54✔
190
#endif
191

192
#if defined(BOTAN_HAS_ECDSA)
193
   if(alg_name == "ECDSA")
1,226✔
194
      return std::make_unique<ECDSA_PrivateKey>(alg_id, key_bits);
908✔
195
#endif
196

197
#if defined(BOTAN_HAS_ECDH)
198
   if(alg_name == "ECDH")
606✔
199
      return std::make_unique<ECDH_PrivateKey>(alg_id, key_bits);
158✔
200
#endif
201

202
#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
203
   if(alg_name == "DH")
494✔
204
      return std::make_unique<DH_PrivateKey>(alg_id, key_bits);
24✔
205
#endif
206

207
#if defined(BOTAN_HAS_DSA)
208
   if(alg_name == "DSA")
497✔
209
      return std::make_unique<DSA_PrivateKey>(alg_id, key_bits);
278✔
210
#endif
211

212
#if defined(BOTAN_HAS_KYBER) || defined(BOTAN_HAS_KYBER_90S)
213
   if(alg_name == "Kyber" || alg_name.starts_with("Kyber-"))
264✔
214
      return std::make_unique<Kyber_PrivateKey>(alg_id, key_bits);
36✔
215
#endif
216

217
#if defined(BOTAN_HAS_MCELIECE)
218
   if(alg_name == "McEliece")
228✔
219
      return std::make_unique<McEliece_PrivateKey>(key_bits);
4✔
220
#endif
221

222
#if defined(BOTAN_HAS_ECGDSA)
223
   if(alg_name == "ECGDSA")
224✔
224
      return std::make_unique<ECGDSA_PrivateKey>(alg_id, key_bits);
36✔
225
#endif
226

227
#if defined(BOTAN_HAS_ECKCDSA)
228
   if(alg_name == "ECKCDSA")
230✔
229
      return std::make_unique<ECKCDSA_PrivateKey>(alg_id, key_bits);
36✔
230
#endif
231

232
#if defined(BOTAN_HAS_ED25519)
233
   if(alg_name == "Ed25519")
202✔
234
      return std::make_unique<Ed25519_PrivateKey>(alg_id, key_bits);
17✔
235
#endif
236

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

242
#if defined(BOTAN_HAS_SM2)
243
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
215✔
244
      return std::make_unique<SM2_PrivateKey>(alg_id, key_bits);
40✔
245
#endif
246

247
#if defined(BOTAN_HAS_ELGAMAL)
248
   if(alg_name == "ElGamal")
146✔
249
      return std::make_unique<ElGamal_PrivateKey>(alg_id, key_bits);
28✔
250
#endif
251

252
#if defined(BOTAN_HAS_XMSS_RFC8391)
253
   if(alg_name == "XMSS")
132✔
254
      return std::make_unique<XMSS_PrivateKey>(key_bits);
16✔
255
#endif
256

257
#if defined(BOTAN_HAS_DILITHIUM) || defined(BOTAN_HAS_DILITHIUM_AES)
258
   if(alg_name == "Dilithium" || alg_name.starts_with("Dilithium-"))
128✔
259
      return std::make_unique<Dilithium_PrivateKey>(alg_id, key_bits);
55✔
260
#endif
261

262
   throw Decoding_Error(fmt("Unknown or unavailable public key algorithm '{}'", alg_name));
122✔
263
}
3,441✔
264

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

271
#if defined(BOTAN_HAS_ECDSA)
272
   if(alg_name == "ECDSA")
126✔
273
      return std::make_unique<ECDSA_PrivateKey>(rng, ec_group);
84✔
274
#endif
275

276
#if defined(BOTAN_HAS_ECDH)
277
   if(alg_name == "ECDH")
84✔
278
      return std::make_unique<ECDH_PrivateKey>(rng, ec_group);
56✔
279
#endif
280

281
#if defined(BOTAN_HAS_ECKCDSA)
282
   if(alg_name == "ECKCDSA")
64✔
283
      return std::make_unique<ECKCDSA_PrivateKey>(rng, ec_group);
34✔
284
#endif
285

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

291
#if defined(BOTAN_HAS_SM2)
292
   if(alg_name == "SM2" || alg_name == "SM2_Sig" || alg_name == "SM2_Enc")
40✔
293
      return std::make_unique<SM2_PrivateKey>(rng, ec_group);
22✔
294
#endif
295

296
#if defined(BOTAN_HAS_ECGDSA)
297
   if(alg_name == "ECGDSA")
17✔
298
      return std::make_unique<ECGDSA_PrivateKey>(rng, ec_group);
34✔
299
#endif
300

301
   return nullptr;
×
302
}
303

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

312
#if defined(BOTAN_HAS_CURVE_25519)
313
   if(alg_name == "Curve25519")
263✔
314
      return std::make_unique<Curve25519_PrivateKey>(rng);
6✔
315
#endif
316

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

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

330
         const auto mce_params = split_on(params, ',');
2✔
331

332
         if(mce_params.size() != 2) {
2✔
333
            throw Invalid_Argument(fmt("create_private_key: invalid McEliece parameters '{}'", params));
×
334
         }
335

336
         const size_t mce_n = to_u32bit(mce_params[0]);
2✔
337
         const size_t mce_t = to_u32bit(mce_params[1]);
2✔
338
         return {mce_n, mce_t};
2✔
339
      }();
4✔
340

341
      return std::make_unique<McEliece_PrivateKey>(rng, n, t);
2✔
342
   }
343
#endif
344

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

353
      return std::make_unique<Kyber_PrivateKey>(rng, mode);
8✔
354
   }
355
#endif
356

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

365
      return std::make_unique<Dilithium_PrivateKey>(rng, mode);
18✔
366
   }
367
#endif
368

369
#if defined(BOTAN_HAS_XMSS_RFC8391)
370
   if(alg_name == "XMSS") {
206✔
371
      const auto xmss_oid = [&]() -> XMSS_Parameters::xmss_algorithm_t {
8✔
372
         if(params.empty())
4✔
373
            return XMSS_Parameters::XMSS_SHA2_10_512;
374
         return XMSS_Parameters(params).oid();
3✔
375
      }();
4✔
376

377
      return std::make_unique<XMSS_PrivateKey>(xmss_oid, rng);
4✔
378
   }
379
#endif
380

381
#if defined(BOTAN_HAS_ED25519)
382
   if(alg_name == "Ed25519") {
206✔
383
      return std::make_unique<Ed25519_PrivateKey>(rng);
20✔
384
   }
385
#endif
386

387
   // ECC crypto
388
#if defined(BOTAN_HAS_ECC_PUBLIC_KEY_CRYPTO)
389

390
   if(alg_name == "ECDSA" || alg_name == "ECDH" || alg_name == "ECKCDSA" || alg_name == "ECGDSA" || alg_name == "SM2" ||
299✔
391
      alg_name == "SM2_Sig" || alg_name == "SM2_Enc" || alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256" ||
91✔
392
      alg_name == "GOST-34.10-2012-512") {
38✔
393
      const std::string group_id = [&]() -> std::string {
252✔
394
         if(!params.empty())
126✔
395
            return std::string(params);
117✔
396
         if(alg_name == "SM2" || alg_name == "SM2_Enc" || alg_name == "SM2_Sig")
9✔
397
            return "sm2p256v1";
×
398
         if(alg_name == "GOST-34.10" || alg_name == "GOST-34.10-2012-256")
9✔
399
            return "gost_256A";
×
400
         if(alg_name == "GOST-34.10-2012-512")
9✔
401
            return "gost_512A";
×
402
         if(alg_name == "ECGDSA")
9✔
403
            return "brainpool256r1";
×
404
         return "secp256r1";
9✔
405
      }();
126✔
406

407
      const EC_Group ec_group(group_id);
126✔
408
      return create_ec_private_key(alg_name, ec_group, rng);
126✔
409
   }
126✔
410
#endif
411

412
   // DL crypto
413
#if defined(BOTAN_HAS_DL_GROUP)
414
   if(alg_name == "DH" || alg_name == "DSA" || alg_name == "ElGamal") {
76✔
415
      const std::string group_id = [&]() -> std::string {
76✔
416
         if(!params.empty())
38✔
417
            return std::string(params);
28✔
418
         if(alg_name == "DSA")
10✔
419
            return "dsa/botan/2048";
8✔
420
         return "modp/ietf/2048";
2✔
421
      }();
38✔
422

423
      DL_Group modp_group(group_id);
38✔
424

425
   #if defined(BOTAN_HAS_DIFFIE_HELLMAN)
426
      if(alg_name == "DH")
38✔
427
         return std::make_unique<DH_PrivateKey>(rng, modp_group);
36✔
428
   #endif
429

430
   #if defined(BOTAN_HAS_DSA)
431
      if(alg_name == "DSA")
20✔
432
         return std::make_unique<DSA_PrivateKey>(rng, modp_group);
26✔
433
   #endif
434

435
   #if defined(BOTAN_HAS_ELGAMAL)
436
      if(alg_name == "ElGamal")
7✔
437
         return std::make_unique<ElGamal_PrivateKey>(rng, modp_group);
14✔
438
   #endif
439
   }
38✔
440
#endif
441

442
   BOTAN_UNUSED(alg_name, rng, params, provider);
×
443

444
   return std::unique_ptr<Private_Key>();
252✔
445
}
446

447
std::vector<std::string> probe_provider_private_key(std::string_view alg_name,
43✔
448
                                                    const std::vector<std::string>& possible) {
449
   std::vector<std::string> providers;
43✔
450

451
   for(auto&& prov : possible) {
215✔
452
      if(prov == "base")
172✔
453
         providers.push_back(prov);
43✔
454
   }
455

456
   BOTAN_UNUSED(alg_name);
43✔
457

458
   return providers;
43✔
459
}
×
460
}  // 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

© 2026 Coveralls, Inc