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

randombit / botan / 13721134418

07 Mar 2025 12:54PM UTC coverage: 91.669%. Remained the same
13721134418

push

github

web-flow
Merge pull request #4752 from randombit/jack/fix-tls13-nist-pqc

TLS 1.3 PQ hybrid NIST curve extensions and fixes

95874 of 104587 relevant lines covered (91.67%)

11238638.88 hits per line

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

57.83
/src/lib/tls/tls_algos.cpp
1
/*
2
* (C) 2017 Jack Lloyd
3
*
4
* Botan is released under the Simplified BSD License (see license.txt)
5
*/
6

7
#include <botan/tls_algos.h>
8

9
#include <botan/ec_group.h>
10
#include <botan/exceptn.h>
11
#include <botan/internal/fmt.h>
12

13
namespace Botan::TLS {
14

15
std::string kdf_algo_to_string(KDF_Algo algo) {
210,305✔
16
   switch(algo) {
210,305✔
17
      case KDF_Algo::SHA_1:
38,947✔
18
         return "SHA-1";
38,947✔
19
      case KDF_Algo::SHA_256:
126,839✔
20
         return "SHA-256";
126,839✔
21
      case KDF_Algo::SHA_384:
44,519✔
22
         return "SHA-384";
44,519✔
23
   }
24

25
   throw Invalid_State("kdf_algo_to_string unknown enum value");
×
26
}
27

28
std::string kex_method_to_string(Kex_Algo method) {
7,790✔
29
   switch(method) {
7,790✔
30
      case Kex_Algo::STATIC_RSA:
737✔
31
         return "RSA";
737✔
32
      case Kex_Algo::DH:
1,106✔
33
         return "DH";
1,106✔
34
      case Kex_Algo::ECDH:
4,189✔
35
         return "ECDH";
4,189✔
36
      case Kex_Algo::PSK:
860✔
37
         return "PSK";
860✔
38
      case Kex_Algo::ECDHE_PSK:
864✔
39
         return "ECDHE_PSK";
864✔
40
      case Kex_Algo::DHE_PSK:
×
41
         return "DHE_PSK";
×
42
      case Kex_Algo::KEM:
2✔
43
         return "KEM";
2✔
44
      case Kex_Algo::KEM_PSK:
×
45
         return "KEM_PSK";
×
46
      case Kex_Algo::HYBRID:
30✔
47
         return "HYBRID";
30✔
48
      case Kex_Algo::HYBRID_PSK:
2✔
49
         return "HYBRID_PSK";
2✔
50
      case Kex_Algo::UNDEFINED:
×
51
         return "UNDEFINED";
×
52
   }
53

54
   throw Invalid_State("kex_method_to_string unknown enum value");
×
55
}
56

57
Kex_Algo kex_method_from_string(std::string_view str) {
5✔
58
   if(str == "RSA") {
5✔
59
      return Kex_Algo::STATIC_RSA;
1✔
60
   }
61

62
   if(str == "DH") {
4✔
63
      return Kex_Algo::DH;
1✔
64
   }
65

66
   if(str == "ECDH") {
3✔
67
      return Kex_Algo::ECDH;
1✔
68
   }
69

70
   if(str == "PSK") {
2✔
71
      return Kex_Algo::PSK;
1✔
72
   }
73

74
   if(str == "ECDHE_PSK") {
1✔
75
      return Kex_Algo::ECDHE_PSK;
1✔
76
   }
77

78
   if(str == "DHE_PSK") {
×
79
      return Kex_Algo::DHE_PSK;
×
80
   }
81

82
   if(str == "KEM") {
×
83
      return Kex_Algo::KEM;
×
84
   }
85

86
   if(str == "KEM_PSK") {
×
87
      return Kex_Algo::KEM_PSK;
×
88
   }
89

90
   if(str == "HYBRID") {
×
91
      return Kex_Algo::HYBRID;
×
92
   }
93

94
   if(str == "HYBRID_PSK") {
×
95
      return Kex_Algo::HYBRID_PSK;
×
96
   }
97

98
   if(str == "UNDEFINED") {
×
99
      return Kex_Algo::UNDEFINED;
×
100
   }
101

102
   throw Invalid_Argument(fmt("Unknown kex method '{}'", str));
×
103
}
104

105
std::string auth_method_to_string(Auth_Method method) {
9,632✔
106
   switch(method) {
9,632✔
107
      case Auth_Method::RSA:
6,635✔
108
         return "RSA";
6,635✔
109
      case Auth_Method::ECDSA:
2,846✔
110
         return "ECDSA";
2,846✔
111
      case Auth_Method::IMPLICIT:
151✔
112
         return "IMPLICIT";
151✔
113
      case Auth_Method::UNDEFINED:
×
114
         return "UNDEFINED";
×
115
   }
116

117
   throw Invalid_State("auth_method_to_string unknown enum value");
×
118
}
119

120
Auth_Method auth_method_from_string(std::string_view str) {
3✔
121
   if(str == "RSA") {
3✔
122
      return Auth_Method::RSA;
1✔
123
   }
124
   if(str == "ECDSA") {
2✔
125
      return Auth_Method::ECDSA;
1✔
126
   }
127
   if(str == "IMPLICIT") {
1✔
128
      return Auth_Method::IMPLICIT;
1✔
129
   }
130
   if(str == "UNDEFINED") {
×
131
      return Auth_Method::UNDEFINED;
×
132
   }
133

134
   throw Invalid_Argument(fmt("Unknown TLS signature method '{}'", str));
×
135
}
136

137
bool Group_Params::is_available() const {
621✔
138
#if !defined(BOTAN_HAS_X25519)
139
   if(is_x25519()) {
140
      return false;
141
   }
142
   if(is_pqc_hybrid() && pqc_hybrid_ecc() == Group_Params_Code::X25519) {
143
      return false;
144
   }
145
#endif
146

147
#if !defined(BOTAN_HAS_X448)
148
   if(is_x448()) {
149
      return false;
150
   }
151
   if(is_pqc_hybrid() && pqc_hybrid_ecc() == Group_Params_Code::X448) {
152
      return false;
153
   }
154
#endif
155

156
#if !defined(BOTAN_HAS_DIFFIE_HELLMAN)
157
   if(is_in_ffdhe_range()) {
158
      return false;
159
   }
160
#endif
161

162
#if !defined(BOTAN_HAS_ML_KEM)
163
   if(is_pure_ml_kem() || is_pqc_hybrid_ml_kem()) {
164
      return false;
165
   }
166
#endif
167

168
#if !defined(BOTAN_HAS_FRODOKEM)
169
   if(is_pure_frodokem() || is_pqc_hybrid_frodokem()) {
170
      return false;
171
   }
172
#endif
173

174
   return true;
621✔
175
}
176

177
std::optional<Group_Params_Code> Group_Params::pqc_hybrid_ecc() const {
×
178
   switch(m_code) {
×
179
      case Group_Params_Code::HYBRID_X25519_ML_KEM_768:
×
180

181
      case Group_Params_Code::HYBRID_X25519_eFRODOKEM_640_SHAKE_OQS:
×
182
      case Group_Params_Code::HYBRID_X25519_eFRODOKEM_640_AES_OQS:
×
183
         return Group_Params_Code::X25519;
×
184

185
      case Group_Params_Code::HYBRID_X448_eFRODOKEM_976_SHAKE_OQS:
×
186
      case Group_Params_Code::HYBRID_X448_eFRODOKEM_976_AES_OQS:
×
187
         return Group_Params_Code::X448;
×
188

189
      case Group_Params_Code::HYBRID_SECP256R1_ML_KEM_768:
×
190
      case Group_Params_Code::HYBRID_SECP256R1_eFRODOKEM_640_SHAKE_OQS:
×
191
      case Group_Params_Code::HYBRID_SECP256R1_eFRODOKEM_640_AES_OQS:
×
192
         return Group_Params_Code::SECP256R1;
×
193

194
      case Group_Params_Code::HYBRID_SECP384R1_ML_KEM_1024:
×
195
      case Group_Params_Code::HYBRID_SECP384R1_eFRODOKEM_976_SHAKE_OQS:
×
196
      case Group_Params_Code::HYBRID_SECP384R1_eFRODOKEM_976_AES_OQS:
×
197
         return Group_Params_Code::SECP384R1;
×
198

199
      case Group_Params_Code::HYBRID_SECP521R1_eFRODOKEM_1344_SHAKE_OQS:
×
200
      case Group_Params_Code::HYBRID_SECP521R1_eFRODOKEM_1344_AES_OQS:
×
201
         return Group_Params_Code::SECP521R1;
×
202

203
      default:
×
204
         return {};
×
205
   }
206
}
207

208
std::optional<Group_Params> Group_Params::from_string(std::string_view group_name) {
621✔
209
   if(group_name == "secp256r1") {
621✔
210
      return Group_Params::SECP256R1;
90✔
211
   }
212
   if(group_name == "secp384r1") {
531✔
213
      return Group_Params::SECP384R1;
49✔
214
   }
215
   if(group_name == "secp521r1") {
482✔
216
      return Group_Params::SECP521R1;
44✔
217
   }
218
   if(group_name == "brainpool256r1") {
438✔
219
      return Group_Params::BRAINPOOL256R1;
28✔
220
   }
221
   if(group_name == "brainpool384r1") {
410✔
222
      return Group_Params::BRAINPOOL384R1;
12✔
223
   }
224
   if(group_name == "brainpool512r1") {
398✔
225
      return Group_Params::BRAINPOOL512R1;
12✔
226
   }
227
   if(group_name == "x25519") {
386✔
228
      return Group_Params::X25519;
103✔
229
   }
230
   if(group_name == "x448") {
283✔
231
      return Group_Params::X448;
41✔
232
   }
233

234
   if(group_name == "ffdhe/ietf/2048") {
242✔
235
      return Group_Params::FFDHE_2048;
69✔
236
   }
237
   if(group_name == "ffdhe/ietf/3072") {
173✔
238
      return Group_Params::FFDHE_3072;
28✔
239
   }
240
   if(group_name == "ffdhe/ietf/4096") {
145✔
241
      return Group_Params::FFDHE_4096;
22✔
242
   }
243
   if(group_name == "ffdhe/ietf/6144") {
123✔
244
      return Group_Params::FFDHE_6144;
16✔
245
   }
246
   if(group_name == "ffdhe/ietf/8192") {
107✔
247
      return Group_Params::FFDHE_8192;
16✔
248
   }
249

250
   if(group_name == "ML-KEM-512") {
91✔
251
      return Group_Params::ML_KEM_512;
×
252
   }
253
   if(group_name == "ML-KEM-768") {
91✔
254
      return Group_Params::ML_KEM_768;
30✔
255
   }
256
   if(group_name == "ML-KEM-1024") {
61✔
257
      return Group_Params::ML_KEM_1024;
×
258
   }
259

260
   if(group_name == "eFrodoKEM-640-SHAKE") {
61✔
261
      return Group_Params::eFRODOKEM_640_SHAKE_OQS;
×
262
   }
263
   if(group_name == "eFrodoKEM-976-SHAKE") {
61✔
264
      return Group_Params::eFRODOKEM_976_SHAKE_OQS;
×
265
   }
266
   if(group_name == "eFrodoKEM-1344-SHAKE") {
61✔
267
      return Group_Params::eFRODOKEM_1344_SHAKE_OQS;
×
268
   }
269
   if(group_name == "eFrodoKEM-640-AES") {
61✔
270
      return Group_Params::eFRODOKEM_640_AES_OQS;
×
271
   }
272
   if(group_name == "eFrodoKEM-976-AES") {
61✔
273
      return Group_Params::eFRODOKEM_976_AES_OQS;
×
274
   }
275
   if(group_name == "eFrodoKEM-1344-AES") {
61✔
276
      return Group_Params::eFRODOKEM_1344_AES_OQS;
×
277
   }
278

279
   if(group_name == "x25519/ML-KEM-768") {
61✔
280
      return Group_Params::HYBRID_X25519_ML_KEM_768;
39✔
281
   }
282
   if(group_name == "secp256r1/ML-KEM-768") {
22✔
283
      return Group_Params::HYBRID_SECP256R1_ML_KEM_768;
9✔
284
   }
285
   if(group_name == "secp384r1/ML-KEM-1024") {
13✔
286
      return Group_Params::HYBRID_SECP384R1_ML_KEM_1024;
9✔
287
   }
288

289
   if(group_name == "x25519/eFrodoKEM-640-SHAKE") {
4✔
290
      return Group_Params::HYBRID_X25519_eFRODOKEM_640_SHAKE_OQS;
×
291
   }
292
   if(group_name == "x25519/eFrodoKEM-640-AES") {
4✔
293
      return Group_Params::HYBRID_X25519_eFRODOKEM_640_AES_OQS;
×
294
   }
295
   if(group_name == "x448/eFrodoKEM-976-SHAKE") {
4✔
296
      return Group_Params::HYBRID_X448_eFRODOKEM_976_SHAKE_OQS;
×
297
   }
298
   if(group_name == "x448/eFrodoKEM-976-AES") {
4✔
299
      return Group_Params::HYBRID_X448_eFRODOKEM_976_AES_OQS;
×
300
   }
301

302
   if(group_name == "secp256r1/eFrodoKEM-640-SHAKE") {
4✔
303
      return Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_SHAKE_OQS;
×
304
   }
305
   if(group_name == "secp256r1/eFrodoKEM-640-AES") {
4✔
306
      return Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_AES_OQS;
×
307
   }
308

309
   if(group_name == "secp384r1/eFrodoKEM-976-SHAKE") {
4✔
310
      return Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_SHAKE_OQS;
×
311
   }
312
   if(group_name == "secp384r1/eFrodoKEM-976-AES") {
4✔
313
      return Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_AES_OQS;
×
314
   }
315

316
   if(group_name == "secp521r1/eFrodoKEM-1344-SHAKE") {
4✔
317
      return Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_SHAKE_OQS;
×
318
   }
319
   if(group_name == "secp521r1/eFrodoKEM-1344-AES") {
4✔
320
      return Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_AES_OQS;
×
321
   }
322

323
   return std::nullopt;
4✔
324
}
325

326
std::optional<std::string> Group_Params::to_string() const {
1,002✔
327
   switch(m_code) {
1,002✔
328
      case Group_Params::SECP256R1:
113✔
329
         return "secp256r1";
113✔
330
      case Group_Params::SECP384R1:
121✔
331
         return "secp384r1";
121✔
332
      case Group_Params::SECP521R1:
60✔
333
         return "secp521r1";
60✔
334
      case Group_Params::BRAINPOOL256R1:
26✔
335
         return "brainpool256r1";
26✔
336
      case Group_Params::BRAINPOOL384R1:
10✔
337
         return "brainpool384r1";
10✔
338
      case Group_Params::BRAINPOOL512R1:
12✔
339
         return "brainpool512r1";
12✔
340
      case Group_Params::X25519:
558✔
341
         return "x25519";
558✔
342
      case Group_Params::X448:
8✔
343
         return "x448";
8✔
344

345
      case Group_Params::FFDHE_2048:
22✔
346
         return "ffdhe/ietf/2048";
22✔
347
      case Group_Params::FFDHE_3072:
10✔
348
         return "ffdhe/ietf/3072";
10✔
349
      case Group_Params::FFDHE_4096:
4✔
350
         return "ffdhe/ietf/4096";
4✔
351
      case Group_Params::FFDHE_6144:
2✔
352
         return "ffdhe/ietf/6144";
2✔
353
      case Group_Params::FFDHE_8192:
2✔
354
         return "ffdhe/ietf/8192";
2✔
355

356
      case Group_Params::ML_KEM_512:
×
357
         return "ML-KEM-512";
×
358
      case Group_Params::ML_KEM_768:
4✔
359
         return "ML-KEM-768";
4✔
360
      case Group_Params::ML_KEM_1024:
×
361
         return "ML-KEM-1024";
×
362

363
      case Group_Params::eFRODOKEM_640_SHAKE_OQS:
×
364
         return "eFrodoKEM-640-SHAKE";
×
365
      case Group_Params::eFRODOKEM_976_SHAKE_OQS:
×
366
         return "eFrodoKEM-976-SHAKE";
×
367
      case Group_Params::eFRODOKEM_1344_SHAKE_OQS:
×
368
         return "eFrodoKEM-1344-SHAKE";
×
369
      case Group_Params::eFRODOKEM_640_AES_OQS:
×
370
         return "eFrodoKEM-640-AES";
×
371
      case Group_Params::eFRODOKEM_976_AES_OQS:
×
372
         return "eFrodoKEM-976-AES";
×
373
      case Group_Params::eFRODOKEM_1344_AES_OQS:
×
374
         return "eFrodoKEM-1344-AES";
×
375

376
      case Group_Params::HYBRID_X25519_eFRODOKEM_640_SHAKE_OQS:
×
377
         return "x25519/eFrodoKEM-640-SHAKE";
×
378
      case Group_Params::HYBRID_X25519_eFRODOKEM_640_AES_OQS:
×
379
         return "x25519/eFrodoKEM-640-AES";
×
380
      case Group_Params::HYBRID_X448_eFRODOKEM_976_SHAKE_OQS:
×
381
         return "x448/eFrodoKEM-976-SHAKE";
×
382
      case Group_Params::HYBRID_X448_eFRODOKEM_976_AES_OQS:
×
383
         return "x448/eFrodoKEM-976-AES";
×
384
      case Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_SHAKE_OQS:
×
385
         return "secp256r1/eFrodoKEM-640-SHAKE";
×
386
      case Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_AES_OQS:
×
387
         return "secp256r1/eFrodoKEM-640-AES";
×
388
      case Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_SHAKE_OQS:
×
389
         return "secp384r1/eFrodoKEM-976-SHAKE";
×
390
      case Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_AES_OQS:
×
391
         return "secp384r1/eFrodoKEM-976-AES";
×
392
      case Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_SHAKE_OQS:
×
393
         return "secp521r1/eFrodoKEM-1344-SHAKE";
×
394
      case Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_AES_OQS:
×
395
         return "secp521r1/eFrodoKEM-1344-AES";
×
396

397
      case Group_Params::HYBRID_X25519_ML_KEM_768:
38✔
398
         return "x25519/ML-KEM-768";
38✔
399
      case Group_Params::HYBRID_SECP256R1_ML_KEM_768:
6✔
400
         return "secp256r1/ML-KEM-768";
6✔
401
      case Group_Params::HYBRID_SECP384R1_ML_KEM_1024:
6✔
402
         return "secp384r1/ML-KEM-1024";
6✔
403

404
      default:
×
405
         return std::nullopt;
×
406
   }
407
}
408

409
}  // namespace Botan::TLS
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