Botan 3.13.0
Crypto and TLS for C&
tls_algos.cpp
Go to the documentation of this file.
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/exceptn.h>
10#include <botan/internal/fmt.h>
11
12#include <algorithm>
13#include <array>
14
15namespace Botan::TLS {
16
17std::string kdf_algo_to_string(KDF_Algo algo) {
18 switch(algo) {
19 case KDF_Algo::SHA_1:
20 return "SHA-1";
22 return "SHA-256";
24 return "SHA-384";
25 }
26
27 throw Invalid_State("kdf_algo_to_string unknown enum value");
28}
29
30std::string kex_method_to_string(Kex_Algo method) {
31 switch(method) {
33 return "RSA";
34 case Kex_Algo::DH:
35 return "DH";
36 case Kex_Algo::ECDH:
37 return "ECDH";
38 case Kex_Algo::PSK:
39 return "PSK";
41 return "ECDHE_PSK";
43 return "DHE_PSK";
44 case Kex_Algo::KEM:
45 return "KEM";
47 return "KEM_PSK";
49 return "HYBRID";
51 return "HYBRID_PSK";
53 return "UNDEFINED";
54 }
55
56 throw Invalid_State("kex_method_to_string unknown enum value");
57}
58
59Kex_Algo kex_method_from_string(std::string_view str) {
60 if(str == "RSA") {
62 }
63
64 if(str == "DH") {
65 return Kex_Algo::DH;
66 }
67
68 if(str == "ECDH") {
69 return Kex_Algo::ECDH;
70 }
71
72 if(str == "PSK") {
73 return Kex_Algo::PSK;
74 }
75
76 if(str == "ECDHE_PSK") {
78 }
79
80 if(str == "DHE_PSK") {
81 return Kex_Algo::DHE_PSK;
82 }
83
84 if(str == "KEM") {
85 return Kex_Algo::KEM;
86 }
87
88 if(str == "KEM_PSK") {
89 return Kex_Algo::KEM_PSK;
90 }
91
92 if(str == "HYBRID") {
93 return Kex_Algo::HYBRID;
94 }
95
96 if(str == "HYBRID_PSK") {
98 }
99
100 if(str == "UNDEFINED") {
101 return Kex_Algo::UNDEFINED;
102 }
103
104 throw Invalid_Argument(fmt("Unknown kex method '{}'", str));
105}
106
108 switch(method) {
109 case Auth_Method::RSA:
110 return "RSA";
112 return "ECDSA";
114 return "IMPLICIT";
116 return "UNDEFINED";
117 }
118
119 throw Invalid_State("auth_method_to_string unknown enum value");
120}
121
123 if(str == "RSA") {
124 return Auth_Method::RSA;
125 }
126 if(str == "ECDSA") {
127 return Auth_Method::ECDSA;
128 }
129 if(str == "IMPLICIT") {
131 }
132 if(str == "UNDEFINED") {
134 }
135
136 throw Invalid_Argument(fmt("Unknown TLS signature method '{}'", str));
137}
138
139namespace {
140
141consteval auto available_group_params() {
142 auto codes = std::array {
143#if defined(BOTAN_HAS_PCURVES_SECP256R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
145#endif
146
147#if defined(BOTAN_HAS_PCURVES_SECP384R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
149#endif
150
151#if defined(BOTAN_HAS_PCURVES_SECP521R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
153#endif
154
155#if defined(BOTAN_HAS_PCURVES_BRAINPOOL256R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
157#endif
158
159#if defined(BOTAN_HAS_PCURVES_BRAINPOOL384R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
161#endif
162
163#if defined(BOTAN_HAS_PCURVES_BRAINPOOL512R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
165#endif
166
167#if defined(BOTAN_HAS_X25519)
169#endif
170
171#if defined(BOTAN_HAS_X448)
173#endif
174
175#if defined(BOTAN_HAS_DIFFIE_HELLMAN)
178#endif
179
180#if defined(BOTAN_HAS_ML_KEM)
182
183 #if defined(BOTAN_HAS_PCURVES_SECP256R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
185 #endif
186
187 #if defined(BOTAN_HAS_PCURVES_SECP384R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
189 #endif
190
191 #if defined(BOTAN_HAS_X25519)
193 #endif
194#endif
195
196#if defined(BOTAN_HAS_FRODOKEM)
200
201 #if defined(BOTAN_HAS_PCURVES_SECP256R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
204 #endif
205
206 #if defined(BOTAN_HAS_PCURVES_SECP384R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
209 #endif
210
211 #if defined(BOTAN_HAS_PCURVES_SECP521R1) || defined(BOTAN_HAS_PCURVES_GENERIC)
214 #endif
215
216 #if defined(BOTAN_HAS_X25519)
219 #endif
220
221 #if defined(BOTAN_HAS_X448)
223 #endif
224#endif
225 };
226
227 std::sort(codes.begin(), codes.end());
228
229 return codes;
230}
231
232} // namespace
233
235 // For group codes we recognize, check the build-time availability table.
236 // Unknown codes may be user-supplied custom groups handled via callbacks.
237 if(to_string().has_value()) {
238 static constexpr auto codes = available_group_params();
239 return std::binary_search(codes.begin(), codes.end(), this->code());
240 }
241 return true;
242}
243
274
275std::optional<Group_Params> Group_Params::from_string(std::string_view group_name) {
276 if(group_name == "secp256r1") {
277 return Group_Params::SECP256R1;
278 }
279 if(group_name == "secp384r1") {
280 return Group_Params::SECP384R1;
281 }
282 if(group_name == "secp521r1") {
283 return Group_Params::SECP521R1;
284 }
285 if(group_name == "brainpool256r1") {
286 return Group_Params::BRAINPOOL256R1;
287 }
288 if(group_name == "brainpool384r1") {
289 return Group_Params::BRAINPOOL384R1;
290 }
291 if(group_name == "brainpool512r1") {
292 return Group_Params::BRAINPOOL512R1;
293 }
294 if(group_name == "x25519") {
295 return Group_Params::X25519;
296 }
297 if(group_name == "x448") {
298 return Group_Params::X448;
299 }
300 if(group_name == "brainpool256r1tls13") {
301 return Group_Params::BRAINPOOL256R1TLS13;
302 }
303 if(group_name == "brainpool384r1tls13") {
304 return Group_Params::BRAINPOOL384R1TLS13;
305 }
306 if(group_name == "brainpool512r1tls13") {
307 return Group_Params::BRAINPOOL512R1TLS13;
308 }
309
310 if(group_name == "ffdhe/ietf/2048") {
311 return Group_Params::FFDHE_2048;
312 }
313 if(group_name == "ffdhe/ietf/3072") {
314 return Group_Params::FFDHE_3072;
315 }
316 if(group_name == "ffdhe/ietf/4096") {
317 return Group_Params::FFDHE_4096;
318 }
319 if(group_name == "ffdhe/ietf/6144") {
320 return Group_Params::FFDHE_6144;
321 }
322 if(group_name == "ffdhe/ietf/8192") {
323 return Group_Params::FFDHE_8192;
324 }
325
326 if(group_name == "ML-KEM-512") {
327 return Group_Params::ML_KEM_512;
328 }
329 if(group_name == "ML-KEM-768") {
330 return Group_Params::ML_KEM_768;
331 }
332 if(group_name == "ML-KEM-1024") {
333 return Group_Params::ML_KEM_1024;
334 }
335
336 if(group_name == "eFrodoKEM-640-SHAKE") {
337 return Group_Params::eFRODOKEM_640_SHAKE_OQS;
338 }
339 if(group_name == "eFrodoKEM-976-SHAKE") {
340 return Group_Params::eFRODOKEM_976_SHAKE_OQS;
341 }
342 if(group_name == "eFrodoKEM-1344-SHAKE") {
343 return Group_Params::eFRODOKEM_1344_SHAKE_OQS;
344 }
345 if(group_name == "eFrodoKEM-640-AES") {
346 return Group_Params::eFRODOKEM_640_AES_OQS;
347 }
348 if(group_name == "eFrodoKEM-976-AES") {
349 return Group_Params::eFRODOKEM_976_AES_OQS;
350 }
351 if(group_name == "eFrodoKEM-1344-AES") {
352 return Group_Params::eFRODOKEM_1344_AES_OQS;
353 }
354
355 if(group_name == "x25519/ML-KEM-768") {
356 return Group_Params::HYBRID_X25519_ML_KEM_768;
357 }
358 if(group_name == "secp256r1/ML-KEM-768") {
359 return Group_Params::HYBRID_SECP256R1_ML_KEM_768;
360 }
361 if(group_name == "secp384r1/ML-KEM-1024") {
362 return Group_Params::HYBRID_SECP384R1_ML_KEM_1024;
363 }
364
365 if(group_name == "x25519/eFrodoKEM-640-SHAKE") {
366 return Group_Params::HYBRID_X25519_eFRODOKEM_640_SHAKE_OQS;
367 }
368 if(group_name == "x25519/eFrodoKEM-640-AES") {
369 return Group_Params::HYBRID_X25519_eFRODOKEM_640_AES_OQS;
370 }
371 if(group_name == "x448/eFrodoKEM-976-SHAKE") {
372 return Group_Params::HYBRID_X448_eFRODOKEM_976_SHAKE_OQS;
373 }
374 if(group_name == "x448/eFrodoKEM-976-AES") {
375 return Group_Params::HYBRID_X448_eFRODOKEM_976_AES_OQS;
376 }
377
378 if(group_name == "secp256r1/eFrodoKEM-640-SHAKE") {
379 return Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_SHAKE_OQS;
380 }
381 if(group_name == "secp256r1/eFrodoKEM-640-AES") {
382 return Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_AES_OQS;
383 }
384
385 if(group_name == "secp384r1/eFrodoKEM-976-SHAKE") {
386 return Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_SHAKE_OQS;
387 }
388 if(group_name == "secp384r1/eFrodoKEM-976-AES") {
389 return Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_AES_OQS;
390 }
391
392 if(group_name == "secp521r1/eFrodoKEM-1344-SHAKE") {
393 return Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_SHAKE_OQS;
394 }
395 if(group_name == "secp521r1/eFrodoKEM-1344-AES") {
396 return Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_AES_OQS;
397 }
398
399 return std::nullopt;
400}
401
402std::optional<std::string> Group_Params::to_string() const {
403 switch(m_code) {
404 case Group_Params::SECP256R1:
405 return "secp256r1";
406 case Group_Params::SECP384R1:
407 return "secp384r1";
408 case Group_Params::SECP521R1:
409 return "secp521r1";
410 case Group_Params::BRAINPOOL256R1:
411 return "brainpool256r1";
412 case Group_Params::BRAINPOOL384R1:
413 return "brainpool384r1";
414 case Group_Params::BRAINPOOL512R1:
415 return "brainpool512r1";
416 case Group_Params::X25519:
417 return "x25519";
418 case Group_Params::X448:
419 return "x448";
420 case Group_Params::BRAINPOOL256R1TLS13:
421 return "brainpool256r1tls13";
422 case Group_Params::BRAINPOOL384R1TLS13:
423 return "brainpool384r1tls13";
424 case Group_Params::BRAINPOOL512R1TLS13:
425 return "brainpool512r1tls13";
426
427 case Group_Params::FFDHE_2048:
428 return "ffdhe/ietf/2048";
429 case Group_Params::FFDHE_3072:
430 return "ffdhe/ietf/3072";
431 case Group_Params::FFDHE_4096:
432 return "ffdhe/ietf/4096";
433 case Group_Params::FFDHE_6144:
434 return "ffdhe/ietf/6144";
435 case Group_Params::FFDHE_8192:
436 return "ffdhe/ietf/8192";
437
438 case Group_Params::ML_KEM_512:
439 return "ML-KEM-512";
440 case Group_Params::ML_KEM_768:
441 return "ML-KEM-768";
442 case Group_Params::ML_KEM_1024:
443 return "ML-KEM-1024";
444
445 case Group_Params::eFRODOKEM_640_SHAKE_OQS:
446 return "eFrodoKEM-640-SHAKE";
447 case Group_Params::eFRODOKEM_976_SHAKE_OQS:
448 return "eFrodoKEM-976-SHAKE";
449 case Group_Params::eFRODOKEM_1344_SHAKE_OQS:
450 return "eFrodoKEM-1344-SHAKE";
451 case Group_Params::eFRODOKEM_640_AES_OQS:
452 return "eFrodoKEM-640-AES";
453 case Group_Params::eFRODOKEM_976_AES_OQS:
454 return "eFrodoKEM-976-AES";
455 case Group_Params::eFRODOKEM_1344_AES_OQS:
456 return "eFrodoKEM-1344-AES";
457
458 case Group_Params::HYBRID_X25519_eFRODOKEM_640_SHAKE_OQS:
459 return "x25519/eFrodoKEM-640-SHAKE";
460 case Group_Params::HYBRID_X25519_eFRODOKEM_640_AES_OQS:
461 return "x25519/eFrodoKEM-640-AES";
462 case Group_Params::HYBRID_X448_eFRODOKEM_976_SHAKE_OQS:
463 return "x448/eFrodoKEM-976-SHAKE";
464 case Group_Params::HYBRID_X448_eFRODOKEM_976_AES_OQS:
465 return "x448/eFrodoKEM-976-AES";
466 case Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_SHAKE_OQS:
467 return "secp256r1/eFrodoKEM-640-SHAKE";
468 case Group_Params::HYBRID_SECP256R1_eFRODOKEM_640_AES_OQS:
469 return "secp256r1/eFrodoKEM-640-AES";
470 case Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_SHAKE_OQS:
471 return "secp384r1/eFrodoKEM-976-SHAKE";
472 case Group_Params::HYBRID_SECP384R1_eFRODOKEM_976_AES_OQS:
473 return "secp384r1/eFrodoKEM-976-AES";
474 case Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_SHAKE_OQS:
475 return "secp521r1/eFrodoKEM-1344-SHAKE";
476 case Group_Params::HYBRID_SECP521R1_eFRODOKEM_1344_AES_OQS:
477 return "secp521r1/eFrodoKEM-1344-AES";
478
479 case Group_Params::HYBRID_X25519_ML_KEM_768:
480 return "x25519/ML-KEM-768";
481 case Group_Params::HYBRID_SECP256R1_ML_KEM_768:
482 return "secp256r1/ML-KEM-768";
483 case Group_Params::HYBRID_SECP384R1_ML_KEM_1024:
484 return "secp384r1/ML-KEM-1024";
485
486 default:
487 return std::nullopt;
488 }
489}
490
491std::optional<std::string> Group_Params::to_algorithm_spec() const {
492 switch(m_code) {
493 // Brainpool curves have two sets of code points. See RFCs 7027 and 8734.
494 case Group_Params::BRAINPOOL256R1:
495 case Group_Params::BRAINPOOL256R1TLS13:
496 return "brainpool256r1";
497 case Group_Params::BRAINPOOL384R1:
498 case Group_Params::BRAINPOOL384R1TLS13:
499 return "brainpool384r1";
500 case Group_Params::BRAINPOOL512R1:
501 case Group_Params::BRAINPOOL512R1TLS13:
502 return "brainpool512r1";
503
504 default:
505 return to_string();
506 }
507}
508
510 switch(type) {
512 return "X509";
514 return "RawPublicKey";
515 }
516
517 return "Unknown";
518}
519
520Certificate_Type certificate_type_from_string(const std::string& type_str) {
521 if(type_str == "X509") {
523 } else if(type_str == "RawPublicKey") {
525 } else {
526 throw Decoding_Error("Unknown certificate type: " + type_str);
527 }
528}
529
530} // namespace Botan::TLS
std::optional< std::string > to_algorithm_spec() const
std::optional< Group_Params_Code > pqc_hybrid_ecc() const
std::optional< std::string > to_string() const
static std::optional< Group_Params > from_string(std::string_view group_name)
Kex_Algo kex_method_from_string(std::string_view str)
Definition tls_algos.cpp:59
std::string certificate_type_to_string(Certificate_Type type)
Auth_Method auth_method_from_string(std::string_view str)
std::string kdf_algo_to_string(KDF_Algo algo)
Definition tls_algos.cpp:17
std::string kex_method_to_string(Kex_Algo method)
Definition tls_algos.cpp:30
std::string auth_method_to_string(Auth_Method method)
Certificate_Type certificate_type_from_string(const std::string &type_str)
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53