Botan 3.13.0
Crypto and TLS for C&
tls_signature_scheme.cpp
Go to the documentation of this file.
1/*
2* (C) 2022,2023 Jack Lloyd
3* (C) 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
4*
5* Botan is released under the Simplified BSD License (see license.txt)
6*/
7
8#include <botan/assert.h>
9#include <botan/tls_signature_scheme.h>
10
11#include <botan/hex.h>
12#include <botan/pk_keys.h>
13#include <botan/pss_params.h>
14#include <botan/tls_version.h>
15#include <botan/internal/fmt.h>
16#include <botan/internal/loadstor.h>
17
18namespace Botan::TLS {
19
20const std::vector<Signature_Scheme>& Signature_Scheme::all_available_schemes() {
21 /*
22 * This is ordered in some approximate order of preference
23 */
24 static const std::vector<Signature_Scheme> all_schemes = {
25
26 // EdDSA 25519 is currently not supported as a signature scheme for certificates
27 // certificate authentication.
28 // See: https://github.com/randombit/botan/pull/2958#discussion_r851294715
29 //
30 // #if defined(BOTAN_HAS_ED25519)
31 // EDDSA_25519,
32 // #endif
33
37
41
45
49 };
50
51 return all_schemes;
52}
53
55 if(str == "RSA_PKCS1_SHA1") {
56 return RSA_PKCS1_SHA1;
57 }
58 if(str == "RSA_PKCS1_SHA256") {
59 return RSA_PKCS1_SHA256;
60 }
61 if(str == "RSA_PKCS1_SHA384") {
62 return RSA_PKCS1_SHA384;
63 }
64 if(str == "RSA_PKCS1_SHA512") {
65 return RSA_PKCS1_SHA512;
66 }
67
68 if(str == "ECDSA_SHA1") {
69 return ECDSA_SHA1;
70 }
71 if(str == "ECDSA_SHA256" || str == "ECDSA_SECP256R1_TLS13_SHA256") {
73 }
74 if(str == "ECDSA_SHA384" || str == "ECDSA_SECP384R1_TLS13_SHA384") {
76 }
77 if(str == "ECDSA_SHA512" || str == "ECDSA_SECP521R1_TLS13_SHA512") {
79 }
80
81 if(str == "RSA_PSS_SHA256") {
82 return RSA_PSS_SHA256;
83 }
84 if(str == "RSA_PSS_SHA384") {
85 return RSA_PSS_SHA384;
86 }
87 if(str == "RSA_PSS_SHA512") {
88 return RSA_PSS_SHA512;
89 }
90
91 if(str == "ECDSA_BRAINPOOL256R1_TLS13_SHA256") {
93 }
94 if(str == "ECDSA_BRAINPOOL384R1_TLS13_SHA384") {
96 }
97 if(str == "ECDSA_BRAINPOOL512R1_TLS13_SHA512") {
99 }
100
101 // Parse signature schemes passed as hexadecimal code points (e.g. "0x081A")
102 if(str.size() == 6 && str.starts_with("0x")) {
103 try {
104 std::array<uint8_t, 2> wire_code{};
105 Botan::hex_decode(wire_code, str.substr(2), false /* no white space */);
107 } catch(const Invalid_Argument&) {
108 // pass, will throw below
109 }
110 }
111
112 throw Invalid_Argument(fmt("Unknown TLS signature scheme '{}'", str));
113}
114
116
118
120
121bool Signature_Scheme::is_available() const noexcept {
122 switch(m_code) {
123 case RSA_PSS_SHA384:
124 case RSA_PSS_SHA256:
125 case RSA_PSS_SHA512:
126 case RSA_PKCS1_SHA384:
127 case RSA_PKCS1_SHA512:
128 case RSA_PKCS1_SHA256:
135 return true;
136 default:
137 return false;
138 }
139}
140
141bool Signature_Scheme::is_set() const noexcept {
142 return m_code != NONE;
143}
144
145std::string Signature_Scheme::to_string() const {
146 switch(m_code) {
147 case RSA_PKCS1_SHA1:
148 return "RSA_PKCS1_SHA1";
149 case RSA_PKCS1_SHA256:
150 return "RSA_PKCS1_SHA256";
151 case RSA_PKCS1_SHA384:
152 return "RSA_PKCS1_SHA384";
153 case RSA_PKCS1_SHA512:
154 return "RSA_PKCS1_SHA512";
155
156 case ECDSA_SHA1:
157 return "ECDSA_SHA1";
159 return "ECDSA_SHA256";
161 return "ECDSA_SHA384";
163 return "ECDSA_SHA512";
164
166 return "ECDSA_BRAINPOOL256R1_TLS13_SHA256";
168 return "ECDSA_BRAINPOOL384R1_TLS13_SHA384";
170 return "ECDSA_BRAINPOOL512R1_TLS13_SHA512";
171
172 case RSA_PSS_SHA256:
173 return "RSA_PSS_SHA256";
174 case RSA_PSS_SHA384:
175 return "RSA_PSS_SHA384";
176 case RSA_PSS_SHA512:
177 return "RSA_PSS_SHA512";
178
179 case EDDSA_25519:
180 return "EDDSA_25519";
181 case EDDSA_448:
182 return "EDDSA_448";
183
184 default:
185 return "Unknown signature scheme: " + std::to_string(m_code);
186 }
187}
188
190 switch(m_code) {
191 case RSA_PKCS1_SHA1:
192 case ECDSA_SHA1:
193 return "SHA-1";
194
196 case RSA_PKCS1_SHA256:
197 case RSA_PSS_SHA256:
199 return "SHA-256";
200
202 case RSA_PKCS1_SHA384:
203 case RSA_PSS_SHA384:
205 return "SHA-384";
206
208 case RSA_PKCS1_SHA512:
209 case RSA_PSS_SHA512:
211 return "SHA-512";
212
213 case EDDSA_25519:
214 case EDDSA_448:
215 return "Pure";
216
217 default:
218 return "Unknown hash function";
219 }
220}
221
223 switch(m_code) {
224 case RSA_PKCS1_SHA1:
225 return "PKCS1v15(SHA-1)";
226 case RSA_PKCS1_SHA256:
227 return "PKCS1v15(SHA-256)";
228 case RSA_PKCS1_SHA384:
229 return "PKCS1v15(SHA-384)";
230 case RSA_PKCS1_SHA512:
231 return "PKCS1v15(SHA-512)";
232
233 case ECDSA_SHA1:
234 return "SHA-1";
237 return "SHA-256";
240 return "SHA-384";
243 return "SHA-512";
244
245 case RSA_PSS_SHA256:
246 return "PSS(SHA-256,MGF1,32)";
247 case RSA_PSS_SHA384:
248 return "PSS(SHA-384,MGF1,48)";
249 case RSA_PSS_SHA512:
250 return "PSS(SHA-512,MGF1,64)";
251
252 case EDDSA_25519:
253 case EDDSA_448:
254 return "Pure";
255
256 default:
257 return "Unknown padding";
258 }
259}
260
262 switch(m_code) {
263 case RSA_PKCS1_SHA1:
264 case RSA_PKCS1_SHA256:
265 case RSA_PKCS1_SHA384:
266 case RSA_PKCS1_SHA512:
267 case RSA_PSS_SHA256:
268 case RSA_PSS_SHA384:
269 case RSA_PSS_SHA512:
270 return "RSA";
271
272 case ECDSA_SHA1:
279 return "ECDSA";
280
281 case EDDSA_25519:
282 return "Ed25519";
283
284 case EDDSA_448:
285 return "Ed448";
286
287 default:
288 return "Unknown algorithm";
289 }
290}
291
293 const auto der_encode_oid = [](const std::string_view oid_name) {
294 try {
295 if(auto oid = OID::from_name(oid_name)) {
296 return oid->BER_encode();
297 }
298 } catch(...) {}
300 };
301
302 switch(m_code) {
303 // case ECDSA_SHA1: not defined
305 return {"ECDSA", der_encode_oid("secp256r1")};
307 return {"ECDSA", der_encode_oid("secp384r1")};
309 return {"ECDSA", der_encode_oid("secp521r1")};
310
312 return {"ECDSA", der_encode_oid("brainpool256r1")};
314 return {"ECDSA", der_encode_oid("brainpool384r1")};
316 return {"ECDSA", der_encode_oid("brainpool512r1")};
317
318 case EDDSA_25519:
319 return {"Ed25519", AlgorithmIdentifier::USE_EMPTY_PARAM};
320 case EDDSA_448:
321 return {"Ed448", AlgorithmIdentifier::USE_EMPTY_PARAM};
322
323 case RSA_PKCS1_SHA1:
324 case RSA_PKCS1_SHA256:
325 case RSA_PKCS1_SHA384:
326 case RSA_PKCS1_SHA512:
327 case RSA_PSS_SHA256:
328 case RSA_PSS_SHA384:
329 case RSA_PSS_SHA512:
331
332 default:
333 return AlgorithmIdentifier();
334 }
335}
336
338 switch(m_code) {
339 case RSA_PKCS1_SHA1:
341 case RSA_PKCS1_SHA256:
343 case RSA_PKCS1_SHA384:
345 case RSA_PKCS1_SHA512:
347
348 case ECDSA_SHA1:
359
360 case RSA_PSS_SHA256:
361 return AlgorithmIdentifier(OID::from_string("RSA/PSS"), PSS_Params("SHA-256", 32).serialize());
362 case RSA_PSS_SHA384:
363 return AlgorithmIdentifier(OID::from_string("RSA/PSS"), PSS_Params("SHA-384", 48).serialize());
364 case RSA_PSS_SHA512:
365 return AlgorithmIdentifier(OID::from_string("RSA/PSS"), PSS_Params("SHA-512", 64).serialize());
366
367 default:
368 // Note that Ed25519 and Ed448 end up here
369 return AlgorithmIdentifier();
370 }
371}
372
373std::optional<Signature_Format> Signature_Scheme::format() const noexcept {
374 switch(m_code) {
375 case RSA_PKCS1_SHA1:
376 case RSA_PKCS1_SHA256:
377 case RSA_PKCS1_SHA384:
378 case RSA_PKCS1_SHA512:
379 case RSA_PSS_SHA256:
380 case RSA_PSS_SHA384:
381 case RSA_PSS_SHA512:
382 case EDDSA_25519:
383 case EDDSA_448:
385
386 case ECDSA_SHA1:
394
395 default:
396 return std::nullopt;
397 }
398}
399
400bool Signature_Scheme::is_compatible_with(const Protocol_Version& protocol_version) const noexcept {
401 // RFC 8446 4.4.3:
402 // The SHA-1 algorithm MUST NOT be used in any signatures of
403 // CertificateVerify messages.
404 //
405 // Note that Botan enforces that for TLS 1.2 as well.
406 if(m_code == RSA_PKCS1_SHA1 || m_code == ECDSA_SHA1) {
407 return false;
408 }
409
410 // RFC 8446 4.4.3:
411 // RSA signatures MUST use an RSASSA-PSS algorithm, regardless of whether
412 // RSASSA-PKCS1-v1_5 algorithms appear in "signature_algorithms".
413 //
414 // Note that this is enforced for TLS 1.3 and above only.
415 if(!protocol_version.is_pre_tls_13() && (m_code == RSA_PKCS1_SHA1 || m_code == RSA_PKCS1_SHA256 ||
416 m_code == RSA_PKCS1_SHA384 || m_code == RSA_PKCS1_SHA512)) {
417 return false;
418 }
419
420 return true;
421}
422
423bool Signature_Scheme::is_suitable_for(const Private_Key& private_key) const {
424 if(algorithm_name() != private_key.algo_name()) {
425 return false;
426 }
427
428 // The ECDSA private key length must match the utilized hash output length.
429 const auto keylen = private_key.key_length();
430 if(keylen <= 250) {
431 return false;
432 }
433
434 if(algorithm_name() == "ECDSA") {
435 if(hash_function_name() == "SHA-256" && !(keylen >= 250 && keylen <= 350)) {
436 return false;
437 }
438
439 if(hash_function_name() == "SHA-384" && !(keylen >= 350 && keylen <= 450)) {
440 return false;
441 }
442
443 if(hash_function_name() == "SHA-512" && !(keylen >= 450 && keylen <= 550)) {
444 return false;
445 }
446 }
447
448 return true;
449}
450
451std::vector<AlgorithmIdentifier> to_algorithm_identifiers(const std::vector<Signature_Scheme>& schemes) {
452 std::vector<AlgorithmIdentifier> result;
453 result.reserve(schemes.size());
454 for(const auto& scheme : schemes) {
455 result.push_back(scheme.algorithm_identifier());
456 }
457 return result;
458}
459
460} // namespace Botan::TLS
#define BOTAN_ASSERT_UNREACHABLE()
Definition assert.h:166
virtual std::string algo_name() const =0
static std::optional< OID > from_name(std::string_view name)
Definition asn1_oid.cpp:66
static OID from_string(std::string_view str)
Definition asn1_oid.cpp:80
virtual size_t key_length() const =0
bool is_compatible_with(const Protocol_Version &protocol_version) const noexcept
bool is_suitable_for(const Private_Key &private_key) const
AlgorithmIdentifier key_algorithm_identifier() const
Signature_Scheme::Code wire_code() const noexcept
std::optional< Signature_Format > format() const noexcept
static Signature_Scheme from_string(std::string_view str)
AlgorithmIdentifier algorithm_identifier() const
static const std::vector< Signature_Scheme > & all_available_schemes()
std::vector< AlgorithmIdentifier > to_algorithm_identifiers(const std::vector< Signature_Scheme > &schemes)
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
size_t hex_decode(uint8_t output[], const char input[], size_t input_length, size_t &input_consumed, bool ignore_ws)
Definition hex.cpp:75
constexpr auto load_be(ParamTs &&... params)
Definition loadstor.h:504