Botan 3.12.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/tls_signature_scheme.h>
18#include <botan/internal/stl_util.h>
19#include <algorithm>
20#include <optional>
21#include <sstream>
22
23namespace Botan::TLS {
24
26 return false;
27}
28
29std::vector<Signature_Scheme> Policy::allowed_signature_schemes() const {
30 std::vector<Signature_Scheme> schemes;
31
33 const bool sig_allowed = allowed_signature_method(scheme.algorithm_name());
34 const bool hash_allowed = allowed_signature_hash(scheme.hash_function_name());
35
36 if(sig_allowed && hash_allowed) {
37 schemes.push_back(scheme);
38 }
39 }
40
41 return schemes;
42}
43
44std::vector<Signature_Scheme> Policy::acceptable_signature_schemes() const {
45 return this->allowed_signature_schemes();
46}
47
48std::optional<std::vector<Signature_Scheme>> Policy::acceptable_certificate_signature_schemes() const {
49 // the restrictions of ::acceptable_signature_schemes() shall apply
50 return std::nullopt;
51}
52
53std::vector<std::string> Policy::allowed_ciphers() const {
54 return {
55 //"AES-256/OCB(12)",
56 "AES-256/GCM",
57 "AES-128/GCM",
58 "ChaCha20Poly1305",
59 //"AES-256/CCM",
60 //"AES-128/CCM",
61 //"AES-256/CCM(8)",
62 //"AES-128/CCM(8)",
63 //"Camellia-256/GCM",
64 //"Camellia-128/GCM",
65 //"ARIA-256/GCM",
66 //"ARIA-128/GCM",
67 //"AES-256",
68 //"AES-128",
69 //"3DES",
70 };
71}
72
73std::vector<std::string> Policy::allowed_signature_hashes() const {
74 return {
75 "SHA-512",
76 "SHA-384",
77 "SHA-256",
78 };
79}
80
81std::vector<std::string> Policy::allowed_macs() const {
82 /*
83 SHA-256 is preferred because the Lucky13 countermeasure works
84 somewhat better for SHA-256 vs SHA-384:
85 https://github.com/randombit/botan/pull/675
86 */
87 return {
88 "AEAD",
89 "SHA-256",
90 "SHA-384",
91 "SHA-1",
92 };
93}
94
95std::vector<std::string> Policy::allowed_key_exchange_methods() const {
96 return {
97 //"ECDHE_PSK",
98 //"PSK",
99 "ECDH",
100 "DH",
101 //"RSA",
102 };
103}
104
105std::vector<std::string> Policy::allowed_signature_methods() const {
106 return {
107 "ECDSA", "RSA",
108 //"IMPLICIT",
109 };
110}
111
112bool Policy::allowed_signature_method(std::string_view sig_method) const {
113 return value_exists(allowed_signature_methods(), sig_method);
114}
115
116bool Policy::allowed_signature_hash(std::string_view sig_hash) const {
117 return value_exists(allowed_signature_hashes(), sig_hash);
118}
119
121 return false;
122}
123
124Group_Params Policy::choose_key_exchange_group(const std::vector<Group_Params>& supported_by_peer,
125 const std::vector<Group_Params>& offered_by_peer) const {
126 if(supported_by_peer.empty()) {
127 return Group_Params::NONE;
128 }
129
130 const auto our_groups = key_exchange_groups();
131
132 // First check if the peer sent a PQ share of a group we also support
133 for(auto share : offered_by_peer) {
134 if(share.is_post_quantum() && value_exists(our_groups, share)) {
135 return share;
136 }
137 }
138
139 // Then check if the peer offered a PQ algo we also support
140 for(auto share : supported_by_peer) {
141 if(share.is_post_quantum() && value_exists(our_groups, share)) {
142 return share;
143 }
144 }
145
146 // Prefer groups that were offered by the peer for the sake of saving
147 // an additional round trip. For TLS 1.2, this won't be used.
148 for(auto g : offered_by_peer) {
149 if(value_exists(our_groups, g)) {
150 return g;
151 }
152 }
153
154 // If no pre-offered groups fit our supported set, we prioritize our
155 // own preference.
156 for(auto g : our_groups) {
157 if(value_exists(supported_by_peer, g)) {
158 return g;
159 }
160 }
161
162 return Group_Params::NONE;
163}
164
166 /*
167 * Return the first listed or just default to 2048
168 */
169 for(auto g : key_exchange_groups()) {
170 if(g.is_dh_named_group()) {
171 return g;
172 }
173 }
174
175 return Group_Params::FFDHE_2048;
176}
177
178std::vector<Group_Params> Policy::key_exchange_groups() const {
179 return {
180 // clang-format off
181#if defined(BOTAN_HAS_X25519)
182 Group_Params::X25519,
183#endif
184
185 Group_Params::SECP256R1,
186
187#if defined(BOTAN_HAS_ML_KEM) && defined(BOTAN_HAS_TLS_13_PQC)
188
189#if defined(BOTAN_HAS_X25519)
191#endif
192
195#endif
196
197#if defined(BOTAN_HAS_X448)
198 Group_Params::X448,
199#endif
200
201 Group_Params::SECP384R1,
202 Group_Params::SECP521R1,
203
204 Group_Params::BRAINPOOL256R1,
205 Group_Params::BRAINPOOL384R1,
206 Group_Params::BRAINPOOL512R1,
207
208 Group_Params::FFDHE_2048,
209 Group_Params::FFDHE_3072,
210
211 // clang-format on
212 };
213}
214
215std::vector<Group_Params> Policy::key_exchange_groups_to_offer() const {
216 std::vector<Group_Params> groups_to_offer;
217
218 const auto supported_groups = key_exchange_groups();
219 BOTAN_ASSERT(!supported_groups.empty(), "Policy allows at least one key exchange group");
220
221 /*
222 * Initially prefer sending a key share only of the first pure-ECC
223 * group, since these shares are small and PQ support is still not
224 * that widespread.
225 */
226 for(auto group : key_exchange_groups()) {
227 if(group.is_pure_ecc_group()) {
228 groups_to_offer.push_back(group);
229 break;
230 }
231 }
232
233 /*
234 * If for some reason no pure ECC groups are enabled then simply
235 * send a share of whatever the policy's top preference is.
236 */
237 if(groups_to_offer.empty()) {
238 groups_to_offer.push_back(supported_groups.front());
239 }
240
241 return groups_to_offer;
242}
243
245 return 2048;
246}
247
249 return 8192;
250}
251
253 // Here we are at the mercy of whatever the CA signed, but most certs should be 256 bit by now
254 return 256;
255}
256
258 // x25519 is smallest curve currently supported for TLS key exchange
259 return 255;
260}
261
263 return 110;
264}
265
267 return true;
268}
269
271 /* Default assumption is all end-entity certificates should
272 be at least 2048 bits these days.
273
274 If you are connecting to arbitrary servers on the Internet
275 (ie as a web browser or SMTP client) you'll probably have to reduce this
276 to 1024 bits, or perhaps even lower.
277 */
278 return 2048;
279}
280
281void Policy::check_peer_key_acceptable(const Public_Key& public_key) const {
282 const std::string algo_name = public_key.algo_name();
283
284 const size_t keylength = public_key.key_length();
285 size_t expected_keylength = 0;
286
287 if(algo_name == "RSA") {
288 expected_keylength = minimum_rsa_bits();
289 } else if(algo_name == "DH") {
290 expected_keylength = minimum_dh_group_size();
291 } else if(algo_name == "ECDH" || algo_name == "X25519" || algo_name == "X448") {
292 expected_keylength = minimum_ecdh_group_size();
293 } else if(algo_name == "ECDSA") {
294 expected_keylength = minimum_ecdsa_group_size();
295 }
296 // else some other algo, so leave expected_keylength as zero and the check is a no-op
297
298 if(keylength < expected_keylength) {
299 throw TLS_Exception(Alert::InsufficientSecurity,
300 "Peer sent " + std::to_string(keylength) + " bit " + algo_name +
301 " key"
302 ", policy requires at least " +
303 std::to_string(expected_keylength));
304 }
305}
306
308 return 1;
309}
310
311std::chrono::seconds Policy::session_ticket_lifetime() const {
312 return std::chrono::days(1);
313}
314
316 return false;
317}
318
320 return 1;
321}
322
324#if defined(BOTAN_HAS_TLS_13)
325 if(version == Protocol_Version::TLS_V13 && allow_tls13()) {
326 return true;
327 }
328#endif
329
330#if defined(BOTAN_HAS_TLS_12)
331 if(version == Protocol_Version::TLS_V12 && allow_tls12()) {
332 return true;
333 }
334
335 if(version == Protocol_Version::DTLS_V12 && allow_dtls12()) {
336 return true;
337 }
338#endif
339
340 BOTAN_UNUSED(version);
341 return false;
342}
343
345 if(datagram) {
346 if(acceptable_protocol_version(Protocol_Version::DTLS_V12)) {
347 return Protocol_Version::DTLS_V12;
348 }
349 } else {
350 if(acceptable_protocol_version(Protocol_Version::TLS_V13)) {
351 return Protocol_Version::TLS_V13;
352 }
353 if(acceptable_protocol_version(Protocol_Version::TLS_V12)) {
354 return Protocol_Version::TLS_V12;
355 }
356 }
357
358 throw Invalid_State("Policy forbids all available TLS version");
359}
360
361bool Policy::acceptable_ciphersuite(const Ciphersuite& ciphersuite) const {
362 return value_exists(allowed_ciphers(), ciphersuite.cipher_algo()) &&
363 value_exists(allowed_macs(), ciphersuite.mac_algo());
364}
365
367 return false;
368}
369
371 return false;
372}
373
375 return false;
376}
377
379#if defined(BOTAN_HAS_TLS_12)
380 return true;
381#else
382 return false;
383#endif
384}
385
387#if defined(BOTAN_HAS_TLS_13)
388 return true;
389#else
390 return false;
391#endif
392}
393
395#if defined(BOTAN_HAS_TLS_12)
396 return true;
397#else
398 return false;
399#endif
400}
401
403 return true;
404}
405
407 return false;
408}
409
411 return true;
412}
413
415 return true;
416}
417
419 return true;
420}
421
422std::optional<uint16_t> Policy::record_size_limit() const {
423 return std::nullopt;
424}
425
427 return true;
428}
429
431 return true;
432}
433
435 return true;
436}
437
439 return true;
440}
441
443 return true;
444}
445
447 return false;
448}
449
453
455 return false;
456}
457
458std::vector<Certificate_Type> Policy::accepted_client_certificate_types() const {
459 return {Certificate_Type::X509};
460}
461
462std::vector<Certificate_Type> Policy::accepted_server_certificate_types() const {
463 return {Certificate_Type::X509};
464}
465
467 return false;
468}
469
471 return 65536;
472}
473
475 return 65536;
476}
477
479 return 1000;
480}
481
483 return 10;
484}
485
486// 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1
488 return 1 * 1000;
489}
490
492 return 60 * 1000;
493}
494
496 // default MTU is IPv6 min MTU minus UDP/IP headers
497 return 1280 - 40 - 8;
498}
499
500std::vector<uint16_t> Policy::srtp_profiles() const {
501 return std::vector<uint16_t>();
502}
503
504namespace {
505
506class Ciphersuite_Preference_Ordering final {
507 public:
508 Ciphersuite_Preference_Ordering(const std::vector<std::string>& ciphers,
509 const std::vector<std::string>& macs,
510 const std::vector<std::string>& kex,
511 const std::vector<std::string>& sigs) :
512 m_ciphers(ciphers), m_macs(macs), m_kex(kex), m_sigs(sigs) {}
513
514 bool operator()(const Ciphersuite& a, const Ciphersuite& b) const {
515 if(a.kex_method() != b.kex_method()) {
516 for(const auto& i : m_kex) {
517 if(a.kex_algo() == i) {
518 return true;
519 }
520 if(b.kex_algo() == i) {
521 return false;
522 }
523 }
524 }
525
526 if(a.cipher_algo() != b.cipher_algo()) {
527 for(const auto& m_cipher : m_ciphers) {
528 if(a.cipher_algo() == m_cipher) {
529 return true;
530 }
531 if(b.cipher_algo() == m_cipher) {
532 return false;
533 }
534 }
535 }
536
537 if(a.cipher_keylen() != b.cipher_keylen()) {
538 if(a.cipher_keylen() < b.cipher_keylen()) {
539 return false;
540 }
541 if(a.cipher_keylen() > b.cipher_keylen()) {
542 return true;
543 }
544 }
545
546 if(a.auth_method() != b.auth_method()) {
547 for(const auto& m_sig : m_sigs) {
548 if(a.sig_algo() == m_sig) {
549 return true;
550 }
551 if(b.sig_algo() == m_sig) {
552 return false;
553 }
554 }
555 }
556
557 if(a.mac_algo() != b.mac_algo()) {
558 for(const auto& m_mac : m_macs) {
559 if(a.mac_algo() == m_mac) {
560 return true;
561 }
562 if(b.mac_algo() == m_mac) {
563 return false;
564 }
565 }
566 }
567
568 return false; // equal (?!?)
569 }
570
571 private:
572 std::vector<std::string> m_ciphers, m_macs, m_kex, m_sigs;
573};
574
575} // namespace
576
577std::vector<uint16_t> Policy::ciphersuite_list(Protocol_Version version) const {
578 const std::vector<std::string> ciphers = allowed_ciphers();
579 const std::vector<std::string> macs = allowed_macs();
580 const std::vector<std::string> kex = allowed_key_exchange_methods();
581 const std::vector<std::string> sigs = allowed_signature_methods();
582
583 std::vector<Ciphersuite> ciphersuites;
584
585 for(auto&& suite : Ciphersuite::all_known_ciphersuites()) {
586 // Can we use it?
587 if(!suite.valid()) {
588 continue;
589 }
590
591 // Can we use it in this version?
592 if(!suite.usable_in_version(version)) {
593 continue;
594 }
595
596 // Is it acceptable to the policy?
597 if(!this->acceptable_ciphersuite(suite)) {
598 continue;
599 }
600
601 if(!value_exists(ciphers, suite.cipher_algo())) {
602 continue; // unsupported cipher
603 }
604
605 // these checks are irrelevant for TLS 1.3
606 // TODO: consider making a method for this logic
607 if(version.is_pre_tls_13()) {
608 if(!value_exists(kex, suite.kex_algo())) {
609 continue; // unsupported key exchange
610 }
611
612 if(!value_exists(macs, suite.mac_algo())) {
613 continue; // unsupported MAC algo
614 }
615
616 if(!value_exists(sigs, suite.sig_algo())) {
617 // allow if it's an empty sig algo and we want to use PSK
618 if(suite.auth_method() != Auth_Method::IMPLICIT || !suite.psk_ciphersuite()) {
619 continue;
620 }
621 }
622 }
623
624 // OK, consider it
625 ciphersuites.push_back(suite);
626 }
627
628 if(ciphersuites.empty()) {
629 throw Invalid_State("Policy does not allow any available cipher suite");
630 }
631
632 const Ciphersuite_Preference_Ordering order(ciphers, macs, kex, sigs);
633 std::sort(ciphersuites.begin(), ciphersuites.end(), order);
634
635 std::vector<uint16_t> ciphersuite_codes;
636 ciphersuite_codes.reserve(ciphersuites.size());
637 for(const auto& i : ciphersuites) {
638 ciphersuite_codes.push_back(i.ciphersuite_code());
639 }
640 return ciphersuite_codes;
641}
642
643namespace {
644
645void print_vec(std::ostream& o, const char* key, const std::vector<std::string>& v) {
646 o << key << " = ";
647 for(size_t i = 0; i != v.size(); ++i) {
648 o << v[i];
649 if(i != v.size() - 1) {
650 o << ' ';
651 }
652 }
653 o << '\n';
654}
655
656void print_vec(std::ostream& o, const char* key, const std::vector<Group_Params>& params) {
657 // first filter out any groups we don't have a name for:
658 std::vector<std::string> names;
659 for(auto p : params) {
660 if(auto name = p.to_string()) {
661 names.push_back(name.value());
662 }
663 }
664
665 o << key << " = ";
666
667 for(size_t i = 0; i != names.size(); ++i) {
668 o << names[i];
669 if(i != names.size() - 1) {
670 o << " ";
671 }
672 }
673 o << "\n";
674}
675
676void print_vec(std::ostream& o, const char* key, const std::vector<Certificate_Type>& types) {
677 o << key << " = ";
678 for(size_t i = 0; i != types.size(); ++i) {
679 o << certificate_type_to_string(types[i]);
680 if(i != types.size() - 1) {
681 o << ' ';
682 }
683 }
684 o << '\n';
685}
686
687void print_bool(std::ostream& o, const char* key, bool b) {
688 o << key << " = " << (b ? "true" : "false") << '\n';
689}
690
691} // namespace
692
693void Policy::print(std::ostream& o) const {
694 print_bool(o, "allow_tls12", allow_tls12());
695 print_bool(o, "allow_tls13", allow_tls13());
696 print_bool(o, "allow_dtls12", allow_dtls12());
697 print_bool(o, "allow_ssl_key_log_file", allow_ssl_key_log_file());
698 print_vec(o, "ciphers", allowed_ciphers());
699 print_vec(o, "macs", allowed_macs());
700 print_vec(o, "signature_hashes", allowed_signature_hashes());
701 print_vec(o, "signature_methods", allowed_signature_methods());
702 print_vec(o, "key_exchange_methods", allowed_key_exchange_methods());
703 print_vec(o, "key_exchange_groups", key_exchange_groups());
704 const auto groups_to_offer = key_exchange_groups_to_offer();
705 if(groups_to_offer.empty()) {
706 print_vec(o, "key_exchange_groups_to_offer", {std::string("none")});
707 } else {
708 print_vec(o, "key_exchange_groups_to_offer", groups_to_offer);
709 }
710 print_bool(o, "allow_insecure_renegotiation", allow_insecure_renegotiation());
711 print_bool(o, "include_time_in_hello_random", include_time_in_hello_random());
712 print_bool(o, "allow_server_initiated_renegotiation", allow_server_initiated_renegotiation());
713 print_bool(o, "hide_unknown_users", hide_unknown_users());
714 print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences());
715 print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac());
716 print_bool(o, "require_extended_master_secret", require_extended_master_secret());
717 print_bool(o, "support_cert_status_message", support_cert_status_message());
718 print_bool(o, "tls_13_middlebox_compatibility_mode", tls_13_middlebox_compatibility_mode());
719 print_vec(o, "accepted_client_certificate_types", accepted_client_certificate_types());
720 print_vec(o, "accepted_server_certificate_types", accepted_server_certificate_types());
721 print_bool(o, "hash_hello_random", hash_hello_random());
722 if(record_size_limit().has_value()) {
723 o << "record_size_limit = " << record_size_limit().value() << '\n';
724 }
725 o << "maximum_session_tickets_per_client_hello = " << maximum_session_tickets_per_client_hello() << '\n';
726 o << "session_ticket_lifetime = " << session_ticket_lifetime().count() << '\n';
727 print_bool(o, "reuse_session_tickets", reuse_session_tickets());
728 o << "new_session_tickets_upon_handshake_success = " << new_session_tickets_upon_handshake_success() << '\n';
729 o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
730 o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n';
731 o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n';
732 o << "minimum_signature_strength = " << minimum_signature_strength() << '\n';
733}
734
735std::string Policy::to_string() const {
736 std::ostringstream oss;
737 this->print(oss);
738 return oss.str();
739}
740
741std::vector<std::string> Strict_Policy::allowed_ciphers() const {
742 return {"AES-256/GCM", "AES-128/GCM", "ChaCha20Poly1305"};
743}
744
745std::vector<std::string> Strict_Policy::allowed_signature_hashes() const {
746 return {"SHA-512", "SHA-384"};
747}
748
749std::vector<std::string> Strict_Policy::allowed_macs() const {
750 return {"AEAD"};
751}
752
753std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const {
754 return {"ECDH"};
755}
756
757} // namespace Botan::TLS
#define BOTAN_UNUSED
Definition assert.h:144
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:62
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 maximum_dh_group_size() const
virtual size_t dtls_maximum_timeout() const
virtual size_t minimum_ecdh_group_size() const
virtual size_t maximum_handshake_message_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_ssl_key_log_file() 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 require_extended_master_secret() 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_connection() 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 uint64_t minimum_key_update_interval_ms() 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 certificate_type_to_string(Certificate_Type type)
bool value_exists(const std::vector< T > &vec, const V &val)
Definition stl_util.h:44