Botan 3.4.0
Crypto and TLS for C&
tls_policy.cpp
Go to the documentation of this file.
1/*
2* Policies for TLS
3* (C) 2004-2010,2012,2015,2016 Jack Lloyd
4* 2016 Christian Mainka
5* 2017 Harry Reimann, Rohde & Schwarz Cybersecurity
6* 2022 René Meusel, Hannes Rantzsch - neXenio GmbH
7*
8* Botan is released under the Simplified BSD License (see license.txt)
9*/
10
11#include <botan/tls_policy.h>
12
13#include <botan/pk_keys.h>
14#include <botan/tls_algos.h>
15#include <botan/tls_ciphersuite.h>
16#include <botan/tls_exceptn.h>
17#include <botan/internal/stl_util.h>
18#include <optional>
19#include <sstream>
20
21namespace Botan::TLS {
22
23std::vector<Signature_Scheme> Policy::allowed_signature_schemes() const {
24 std::vector<Signature_Scheme> schemes;
25
27 const bool sig_allowed = allowed_signature_method(scheme.algorithm_name());
28 const bool hash_allowed = allowed_signature_hash(scheme.hash_function_name());
29
30 if(sig_allowed && hash_allowed) {
31 schemes.push_back(scheme);
32 }
33 }
34
35 return schemes;
36}
37
38std::vector<Signature_Scheme> Policy::acceptable_signature_schemes() const {
39 return this->allowed_signature_schemes();
40}
41
42std::optional<std::vector<Signature_Scheme>> Policy::acceptable_certificate_signature_schemes() const {
43 // the restrictions of ::acceptable_signature_schemes() shall apply
44 return std::nullopt;
45}
46
47std::vector<std::string> Policy::allowed_ciphers() const {
48 return {
49 //"AES-256/OCB(12)",
50 "ChaCha20Poly1305",
51 "AES-256/GCM",
52 "AES-128/GCM",
53 //"AES-256/CCM",
54 //"AES-128/CCM",
55 //"AES-256/CCM(8)",
56 //"AES-128/CCM(8)",
57 //"Camellia-256/GCM",
58 //"Camellia-128/GCM",
59 //"ARIA-256/GCM",
60 //"ARIA-128/GCM",
61 //"AES-256",
62 //"AES-128",
63 //"3DES",
64 };
65}
66
67std::vector<std::string> Policy::allowed_signature_hashes() const {
68 return {
69 "SHA-512",
70 "SHA-384",
71 "SHA-256",
72 };
73}
74
75std::vector<std::string> Policy::allowed_macs() const {
76 /*
77 SHA-256 is preferred because the Lucky13 countermeasure works
78 somewhat better for SHA-256 vs SHA-384:
79 https://github.com/randombit/botan/pull/675
80 */
81 return {
82 "AEAD",
83 "SHA-256",
84 "SHA-384",
85 "SHA-1",
86 };
87}
88
89std::vector<std::string> Policy::allowed_key_exchange_methods() const {
90 return {
91 //"ECDHE_PSK",
92 //"PSK",
93 "ECDH",
94 "DH",
95 //"RSA",
96 };
97}
98
99std::vector<std::string> Policy::allowed_signature_methods() const {
100 return {
101 "ECDSA", "RSA",
102 //"IMPLICIT",
103 };
104}
105
106bool Policy::allowed_signature_method(std::string_view sig_method) const {
107 return value_exists(allowed_signature_methods(), sig_method);
108}
109
110bool Policy::allowed_signature_hash(std::string_view sig_hash) const {
111 return value_exists(allowed_signature_hashes(), sig_hash);
112}
113
115 return false;
116}
117
118Group_Params Policy::choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
119 const std::vector<Group_Params>& offered_by_peer) const {
120 if(supported_by_peer.empty()) {
121 return Group_Params::NONE;
122 }
123
124 const std::vector<Group_Params> our_groups = key_exchange_groups();
125
126 // Prefer groups that were offered by the peer for the sake of saving
127 // an additional round trip. For TLS 1.2, this won't be used.
128 for(auto g : offered_by_peer) {
129 if(value_exists(our_groups, g)) {
130 return g;
131 }
132 }
133
134 // If no pre-offered groups fit our supported set, we prioritize our
135 // own preference.
136 for(auto g : our_groups) {
137 if(value_exists(supported_by_peer, g)) {
138 return g;
139 }
140 }
141
142 return Group_Params::NONE;
143}
144
146 /*
147 * Return the first listed or just default to 2048
148 */
149 for(auto g : key_exchange_groups()) {
150 if(g.is_dh_named_group()) {
151 return g;
152 }
153 }
154
155 return Group_Params::FFDHE_2048;
156}
157
158std::vector<Group_Params> Policy::key_exchange_groups() const {
159 // Default list is ordered by performance
160 return {
161#if defined(BOTAN_HAS_CURVE_25519)
162 Group_Params::X25519,
163#endif
164#if defined(BOTAN_HAS_X448)
165 Group_Params::X448,
166#endif
167
168 Group_Params::SECP256R1, Group_Params::BRAINPOOL256R1, Group_Params::SECP384R1, Group_Params::BRAINPOOL384R1,
169 Group_Params::SECP521R1, Group_Params::BRAINPOOL512R1,
170
171 Group_Params::FFDHE_2048, Group_Params::FFDHE_3072, Group_Params::FFDHE_4096, Group_Params::FFDHE_6144,
172 Group_Params::FFDHE_8192,
173 };
174}
175
176std::vector<Group_Params> Policy::key_exchange_groups_to_offer() const {
177 // by default, we offer a key share for the most-preferred group, only
178 std::vector<Group_Params> groups_to_offer;
179 const auto supported_groups = key_exchange_groups();
180 if(!supported_groups.empty()) {
181 groups_to_offer.push_back(supported_groups.front());
182 }
183 return groups_to_offer;
184}
185
187 return 2048;
188}
189
191 // Here we are at the mercy of whatever the CA signed, but most certs should be 256 bit by now
192 return 256;
193}
194
196 // x25519 is smallest curve currently supported for TLS key exchange
197 return 255;
198}
199
201 return 110;
202}
203
205 return true;
206}
207
209 /* Default assumption is all end-entity certificates should
210 be at least 2048 bits these days.
211
212 If you are connecting to arbitrary servers on the Internet
213 (ie as a web browser or SMTP client) you'll probably have to reduce this
214 to 1024 bits, or perhaps even lower.
215 */
216 return 2048;
217}
218
219void Policy::check_peer_key_acceptable(const Public_Key& public_key) const {
220 const std::string algo_name = public_key.algo_name();
221
222 const size_t keylength = public_key.key_length();
223 size_t expected_keylength = 0;
224
225 if(algo_name == "RSA") {
226 expected_keylength = minimum_rsa_bits();
227 } else if(algo_name == "DH") {
228 expected_keylength = minimum_dh_group_size();
229 } else if(algo_name == "ECDH" || algo_name == "Curve25519" || algo_name == "X448") {
230 expected_keylength = minimum_ecdh_group_size();
231 } else if(algo_name == "ECDSA") {
232 expected_keylength = minimum_ecdsa_group_size();
233 }
234 // else some other algo, so leave expected_keylength as zero and the check is a no-op
235
236 if(keylength < expected_keylength) {
237 throw TLS_Exception(Alert::InsufficientSecurity,
238 "Peer sent " + std::to_string(keylength) + " bit " + algo_name +
239 " key"
240 ", policy requires at least " +
241 std::to_string(expected_keylength));
242 }
243}
244
246 return 1;
247}
248
249std::chrono::seconds Policy::session_ticket_lifetime() const {
250 return std::chrono::days(1);
251}
252
254 return false;
255}
256
258 return 1;
259}
260
262#if defined(BOTAN_HAS_TLS_13)
263 if(version == Protocol_Version::TLS_V13 && allow_tls13()) {
264 return true;
265 }
266#endif
267
268#if defined(BOTAN_HAS_TLS_12)
269 if(version == Protocol_Version::TLS_V12 && allow_tls12()) {
270 return true;
271 }
272
273 if(version == Protocol_Version::DTLS_V12 && allow_dtls12()) {
274 return true;
275 }
276#endif
277
278 return false;
279}
280
282 if(datagram) {
283 if(acceptable_protocol_version(Protocol_Version::DTLS_V12)) {
284 return Protocol_Version::DTLS_V12;
285 }
286 throw Invalid_State("Policy forbids all available DTLS version");
287 } else {
288#if defined(BOTAN_HAS_TLS_13)
289 if(acceptable_protocol_version(Protocol_Version::TLS_V13)) {
290 return Protocol_Version::TLS_V13;
291 }
292#endif
293 if(acceptable_protocol_version(Protocol_Version::TLS_V12)) {
294 return Protocol_Version::TLS_V12;
295 }
296 throw Invalid_State("Policy forbids all available TLS version");
297 }
298}
299
300bool Policy::acceptable_ciphersuite(const Ciphersuite& ciphersuite) const {
301 return value_exists(allowed_ciphers(), ciphersuite.cipher_algo()) &&
302 value_exists(allowed_macs(), ciphersuite.mac_algo());
303}
304
306 return false;
307}
308
310 return false;
311}
312
314 return false;
315}
316
318#if defined(BOTAN_HAS_TLS_12)
319 return true;
320#else
321 return false;
322#endif
323}
324
326#if defined(BOTAN_HAS_TLS_13)
327 return true;
328#else
329 return false;
330#endif
331}
332
334#if defined(BOTAN_HAS_TLS_12)
335 return true;
336#else
337 return false;
338#endif
339}
340
342 return true;
343}
344
346 return false;
347}
348
350 return true;
351}
352
354 return true;
355}
356
357std::optional<uint16_t> Policy::record_size_limit() const {
358 return std::nullopt;
359}
360
362 return true;
363}
364
366 return true;
367}
368
370 return true;
371}
372
374 return true;
375}
376
378 return true;
379}
380
382 return false;
383}
384
388
390 return false;
391}
392
393std::vector<Certificate_Type> Policy::accepted_client_certificate_types() const {
394 return {Certificate_Type::X509};
395}
396
397std::vector<Certificate_Type> Policy::accepted_server_certificate_types() const {
398 return {Certificate_Type::X509};
399}
400
402 return false;
403}
404
406 return 0;
407}
408
409// 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1
411 return 1 * 1000;
412}
413
415 return 60 * 1000;
416}
417
419 // default MTU is IPv6 min MTU minus UDP/IP headers
420 return 1280 - 40 - 8;
421}
422
423std::vector<uint16_t> Policy::srtp_profiles() const {
424 return std::vector<uint16_t>();
425}
426
427namespace {
428
429class Ciphersuite_Preference_Ordering final {
430 public:
431 Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
432 const std::vector<std::string>& macs,
433 const std::vector<std::string>& kex,
434 const std::vector<std::string>& sigs) :
435 m_ciphers(ciphers), m_macs(macs), m_kex(kex), m_sigs(sigs) {}
436
437 bool operator()(const Ciphersuite& a, const Ciphersuite& b) const {
438 if(a.kex_method() != b.kex_method()) {
439 for(const auto& i : m_kex) {
440 if(a.kex_algo() == i) {
441 return true;
442 }
443 if(b.kex_algo() == i) {
444 return false;
445 }
446 }
447 }
448
449 if(a.cipher_algo() != b.cipher_algo()) {
450 for(const auto& m_cipher : m_ciphers) {
451 if(a.cipher_algo() == m_cipher) {
452 return true;
453 }
454 if(b.cipher_algo() == m_cipher) {
455 return false;
456 }
457 }
458 }
459
460 if(a.cipher_keylen() != b.cipher_keylen()) {
461 if(a.cipher_keylen() < b.cipher_keylen()) {
462 return false;
463 }
464 if(a.cipher_keylen() > b.cipher_keylen()) {
465 return true;
466 }
467 }
468
469 if(a.auth_method() != b.auth_method()) {
470 for(const auto& m_sig : m_sigs) {
471 if(a.sig_algo() == m_sig) {
472 return true;
473 }
474 if(b.sig_algo() == m_sig) {
475 return false;
476 }
477 }
478 }
479
480 if(a.mac_algo() != b.mac_algo()) {
481 for(const auto& m_mac : m_macs) {
482 if(a.mac_algo() == m_mac) {
483 return true;
484 }
485 if(b.mac_algo() == m_mac) {
486 return false;
487 }
488 }
489 }
490
491 return false; // equal (?!?)
492 }
493
494 private:
495 std::vector<std::string> m_ciphers, m_macs, m_kex, m_sigs;
496};
497
498} // namespace
499
500std::vector<uint16_t> Policy::ciphersuite_list(Protocol_Version version) const {
501 const std::vector<std::string> ciphers = allowed_ciphers();
502 const std::vector<std::string> macs = allowed_macs();
503 const std::vector<std::string> kex = allowed_key_exchange_methods();
504 const std::vector<std::string> sigs = allowed_signature_methods();
505
506 std::vector<Ciphersuite> ciphersuites;
507
508 for(auto&& suite : Ciphersuite::all_known_ciphersuites()) {
509 // Can we use it?
510 if(!suite.valid()) {
511 continue;
512 }
513
514 // Can we use it in this version?
515 if(!suite.usable_in_version(version)) {
516 continue;
517 }
518
519 // Is it acceptable to the policy?
520 if(!this->acceptable_ciphersuite(suite)) {
521 continue;
522 }
523
524 if(!value_exists(ciphers, suite.cipher_algo())) {
525 continue; // unsupported cipher
526 }
527
528 // these checks are irrelevant for TLS 1.3
529 // TODO: consider making a method for this logic
530 if(version.is_pre_tls_13()) {
531 if(!value_exists(kex, suite.kex_algo())) {
532 continue; // unsupported key exchange
533 }
534
535 if(!value_exists(macs, suite.mac_algo())) {
536 continue; // unsupported MAC algo
537 }
538
539 if(!value_exists(sigs, suite.sig_algo())) {
540 // allow if it's an empty sig algo and we want to use PSK
541 if(suite.auth_method() != Auth_Method::IMPLICIT || !suite.psk_ciphersuite()) {
542 continue;
543 }
544 }
545 }
546
547 // OK, consider it
548 ciphersuites.push_back(suite);
549 }
550
551 if(ciphersuites.empty()) {
552 throw Invalid_State("Policy does not allow any available cipher suite");
553 }
554
555 Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
556 std::sort(ciphersuites.begin(), ciphersuites.end(), order);
557
558 std::vector<uint16_t> ciphersuite_codes;
559 ciphersuite_codes.reserve(ciphersuites.size());
560 for(auto i : ciphersuites) {
561 ciphersuite_codes.push_back(i.ciphersuite_code());
562 }
563 return ciphersuite_codes;
564}
565
566namespace {
567
568void print_vec(std::ostream& o, const char* key, const std::vector<std::string>& v) {
569 o << key << " = ";
570 for(size_t i = 0; i != v.size(); ++i) {
571 o << v[i];
572 if(i != v.size() - 1) {
573 o << ' ';
574 }
575 }
576 o << '\n';
577}
578
579void print_vec(std::ostream& o, const char* key, const std::vector<Group_Params>& params) {
580 // first filter out any groups we don't have a name for:
581 std::vector<std::string> names;
582 for(auto p : params) {
583 if(auto name = p.to_string()) {
584 names.push_back(name.value());
585 }
586 }
587
588 o << key << " = ";
589
590 for(size_t i = 0; i != names.size(); ++i) {
591 o << names[i];
592 if(i != names.size() - 1) {
593 o << " ";
594 }
595 }
596 o << "\n";
597}
598
599void print_vec(std::ostream& o, const char* key, const std::vector<Certificate_Type>& types) {
600 o << key << " = ";
601 for(size_t i = 0; i != types.size(); ++i) {
602 o << certificate_type_to_string(types[i]);
603 if(i != types.size() - 1) {
604 o << ' ';
605 }
606 }
607 o << '\n';
608}
609
610void print_bool(std::ostream& o, const char* key, bool b) {
611 o << key << " = " << (b ? "true" : "false") << '\n';
612}
613
614} // namespace
615
616void Policy::print(std::ostream& o) const {
617 print_bool(o, "allow_tls12", allow_tls12());
618 print_bool(o, "allow_tls13", allow_tls13());
619 print_bool(o, "allow_dtls12", allow_dtls12());
620 print_vec(o, "ciphers", allowed_ciphers());
621 print_vec(o, "macs", allowed_macs());
622 print_vec(o, "signature_hashes", allowed_signature_hashes());
623 print_vec(o, "signature_methods", allowed_signature_methods());
624 print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
625 print_vec(o, "key_exchange_groups", key_exchange_groups());
626 const auto groups_to_offer = key_exchange_groups_to_offer();
627 if(groups_to_offer.empty()) {
628 print_vec(o, "key_exchange_groups_to_offer", {std::string("none")});
629 } else {
630 print_vec(o, "key_exchange_groups_to_offer", groups_to_offer);
631 }
632 print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
633 print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
634 print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation());
635 print_bool(o, "hide_unknown_users", hide_unknown_users());
636 print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences());
637 print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac());
638 print_bool(o, "support_cert_status_message", support_cert_status_message());
639 print_bool(o, "tls_13_middlebox_compatibility_mode", tls_13_middlebox_compatibility_mode());
640 print_vec(o, "accepted_client_certificate_types", accepted_client_certificate_types());
641 print_vec(o, "accepted_server_certificate_types", accepted_server_certificate_types());
642 print_bool(o, "hash_hello_random", hash_hello_random());
643 if(record_size_limit().has_value()) {
644 o << "record_size_limit = " << record_size_limit().value() << '\n';
645 }
646 o << "maximum_session_tickets_per_client_hello = " << maximum_session_tickets_per_client_hello() << '\n';
647 o << "session_ticket_lifetime = " << session_ticket_lifetime().count() << '\n';
648 o << "reuse_session_tickets = " << reuse_session_tickets() << '\n';
649 o << "new_session_tickets_upon_handshake_success = " << new_session_tickets_upon_handshake_success() << '\n';
650 o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
651 o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n';
652 o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n';
653 o << "minimum_signature_strength = " << minimum_signature_strength() << '\n';
654}
655
656std::string Policy::to_string() const {
657 std::ostringstream oss;
658 this->print(oss);
659 return oss.str();
660}
661
662std::vector<std::string> Strict_Policy::allowed_ciphers() const {
663 return {"ChaCha20Poly1305", "AES-256/GCM", "AES-128/GCM"};
664}
665
666std::vector<std::string> Strict_Policy::allowed_signature_hashes() const {
667 return {"SHA-512", "SHA-384"};
668}
669
670std::vector<std::string> Strict_Policy::allowed_macs() const {
671 return {"AEAD"};
672}
673
674std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const {
675 return {"ECDH"};
676}
677
678} // namespace Botan::TLS
virtual std::string algo_name() const =0
virtual size_t key_length() const =0
static const std::vector< Ciphersuite > & all_known_ciphersuites()
std::string mac_algo() const
std::string cipher_algo() const
virtual bool include_time_in_hello_random() const
virtual void check_peer_key_acceptable(const Public_Key &public_key) const
virtual bool abort_connection_on_undesired_renegotiation() const
virtual size_t dtls_maximum_timeout() const
virtual size_t minimum_ecdh_group_size() const
virtual size_t dtls_default_mtu() const
virtual bool allow_tls12() const
virtual std::vector< Signature_Scheme > allowed_signature_schemes() const
std::string to_string() const
virtual bool reuse_session_tickets() const
virtual std::vector< uint16_t > ciphersuite_list(Protocol_Version version) const
virtual std::vector< Certificate_Type > accepted_server_certificate_types() const
virtual std::vector< Certificate_Type > accepted_client_certificate_types() const
bool allowed_signature_method(std::string_view sig_method) const
virtual bool require_client_certificate_authentication() const
virtual std::vector< Group_Params > key_exchange_groups() const
virtual size_t new_session_tickets_upon_handshake_success() const
virtual std::vector< Group_Params > key_exchange_groups_to_offer() const
bool allowed_signature_hash(std::string_view hash) const
virtual size_t minimum_rsa_bits() const
virtual bool tls_13_middlebox_compatibility_mode() const
virtual bool only_resume_with_exact_version() const
virtual bool allow_client_initiated_renegotiation() const
virtual bool allow_dtls_epoch0_restart() const
virtual bool request_client_certificate_authentication() const
virtual bool require_cert_revocation_info() const
virtual bool negotiate_encrypt_then_mac() const
virtual bool server_uses_own_ciphersuite_preferences() const
virtual Protocol_Version latest_supported_version(bool datagram) const
virtual bool acceptable_protocol_version(Protocol_Version version) const
virtual std::vector< uint16_t > srtp_profiles() const
virtual bool support_cert_status_message() const
virtual bool acceptable_ciphersuite(const Ciphersuite &suite) const
virtual std::vector< std::string > allowed_macs() const
virtual bool hide_unknown_users() const
virtual std::optional< std::vector< Signature_Scheme > > acceptable_certificate_signature_schemes() const
virtual bool hash_hello_random() const
virtual bool allow_tls13() const
virtual std::vector< std::string > allowed_key_exchange_methods() const
virtual size_t dtls_initial_timeout() const
virtual size_t maximum_session_tickets_per_client_hello() const
virtual std::vector< Signature_Scheme > acceptable_signature_schemes() const
virtual bool use_ecc_point_compression() const
virtual bool allow_dtls12() const
virtual size_t minimum_dh_group_size() const
virtual bool allow_insecure_renegotiation() const
virtual std::optional< uint16_t > record_size_limit() const
virtual std::vector< std::string > allowed_ciphers() const
virtual std::chrono::seconds session_ticket_lifetime() const
virtual size_t minimum_signature_strength() const
virtual Group_Params default_dh_group() const
virtual size_t maximum_certificate_chain_size() const
virtual std::vector< std::string > allowed_signature_methods() const
virtual size_t minimum_ecdsa_group_size() const
virtual Group_Params choose_key_exchange_group(const std::vector< Group_Params > &supported_by_peer, const std::vector< Group_Params > &offered_by_peer) const
virtual bool allow_resumption_for_renegotiation() const
virtual std::vector< std::string > allowed_signature_hashes() const
virtual bool allow_server_initiated_renegotiation() const
virtual void print(std::ostream &o) const
static const std::vector< Signature_Scheme > & all_available_schemes()
std::vector< std::string > allowed_macs() const override
std::vector< std::string > allowed_ciphers() const override
std::vector< std::string > allowed_key_exchange_methods() const override
std::vector< std::string > allowed_signature_hashes() const override
std::string name
int(* final)(unsigned char *, CTX *)
std::string certificate_type_to_string(Certificate_Type type)
bool value_exists(const std::vector< T > &vec, const OT &val)
Definition stl_util.h:118