diff options
author | Christian Mainka <[email protected]> | 2016-05-03 16:41:18 +0200 |
---|---|---|
committer | Christian Mainka <[email protected]> | 2016-05-03 16:41:18 +0200 |
commit | 6d327f879c608908ca2c6b9b99f7fd74d498b4ef (patch) | |
tree | 37887b96bf353db53aef93525a49706c7967de2d /src | |
parent | e6f56a82b639776282b9f4fd6a66e426ea0910d2 (diff) |
TLS Policy support
* --policy works for TLS Server and TLS Client
* Example policy BSI_TR-02102-2.txt
* Fine granular configuration for TLS 1.0, 1.1, 1.2 and DTLS 1.0 and 1.2
* Minimum ecdh and rsa group size
Diffstat (limited to 'src')
-rw-r--r-- | src/cli/tls_server.cpp | 23 | ||||
-rw-r--r-- | src/lib/tls/msg_certificate.cpp | 42 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_messages.h | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 50 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.h | 79 | ||||
-rw-r--r-- | src/lib/tls/tls_server.cpp | 2 |
7 files changed, 173 insertions, 27 deletions
diff --git a/src/cli/tls_server.cpp b/src/cli/tls_server.cpp index 2496f5508..7fc38cf31 100644 --- a/src/cli/tls_server.cpp +++ b/src/cli/tls_server.cpp @@ -33,7 +33,7 @@ namespace Botan_CLI { class TLS_Server final : public Command { public: - TLS_Server() : Command("tls_server cert key --port=443 --type=tcp") {} + TLS_Server() : Command("tls_server cert key --port=443 --type=tcp --policy=") {} void go() override { @@ -47,7 +47,24 @@ class TLS_Server final : public Command const bool is_tcp = (transport == "tcp"); - Botan::TLS::Policy policy; // TODO read policy from file + std::unique_ptr<Botan::TLS::Policy> policy; + const std::string policy_file = get_arg("policy"); + std::filebuf fb; + if(policy_file.size() > 0) + { + std::ifstream policy_stream(policy_file); + if(!policy_stream.good()) + { + error_output() << "Failed reading policy file\n"; + return; + } + policy.reset(new Botan::TLS::Text_Policy(policy_stream)); + } + + if(!policy) + { + policy.reset(new Botan::TLS::Policy); + } Botan::TLS::Session_Manager_In_Memory session_manager(rng()); // TODO sqlite3 @@ -112,7 +129,7 @@ class TLS_Server final : public Command std::bind(&TLS_Server::handshake_complete, this, _1), session_manager, creds, - policy, + *policy, rng(), protocol_chooser, !is_tcp); diff --git a/src/lib/tls/msg_certificate.cpp b/src/lib/tls/msg_certificate.cpp index 5be9379bd..fd998cd5e 100644 --- a/src/lib/tls/msg_certificate.cpp +++ b/src/lib/tls/msg_certificate.cpp @@ -31,7 +31,7 @@ Certificate::Certificate(Handshake_IO& io, /** * Deserialize a Certificate message */ -Certificate::Certificate(const std::vector<byte>& buf) +Certificate::Certificate(const std::vector<byte>& buf, const Policy &policy) { if(buf.size() < 3) throw Decoding_Error("Certificate: Message malformed"); @@ -54,7 +54,45 @@ Certificate::Certificate(const std::vector<byte>& buf) throw Decoding_Error("Certificate: Message malformed"); DataSource_Memory cert_buf(&certs[3], cert_size); - m_certs.push_back(X509_Certificate(cert_buf)); + X509_Certificate cert(cert_buf); + + std::unique_ptr<Public_Key> cert_pub_key(cert.subject_public_key()); + + const std::string algo_name = cert_pub_key->algo_name(); + const size_t keylength = cert_pub_key->max_input_bits(); + if(algo_name == "RSA") + { + const size_t expected_keylength = policy.minimum_rsa_bits(); + if(keylength < expected_keylength) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "The peer sent RSA certificate of " + + std::to_string(keylength) + + " bits, policy requires at least " + + std::to_string(expected_keylength)); + } + else if(algo_name == "DH") + { + const size_t expected_keylength = policy.minimum_dh_group_size(); + if(keylength < expected_keylength) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "The peer sent DH certificate of " + + std::to_string(keylength) + + " bits, policy requires at least " + + std::to_string(expected_keylength)); + } + else if(algo_name == "ECDH") + { + const size_t expected_keylength = policy.minimum_ecdh_group_size(); + if(keylength < expected_keylength) + throw TLS_Exception(Alert::INSUFFICIENT_SECURITY, + "The peer sent ECDH certificate of " + + std::to_string(keylength) + + " bits, policy requires at least " + + std::to_string(expected_keylength)); + + } + + m_certs.push_back(cert); certs += cert_size + 3; } diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 301c77c6b..0423b6536 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -352,7 +352,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state, state.set_expected_next(SERVER_HELLO_DONE); } - state.server_certs(new Certificate(contents)); + state.server_certs(new Certificate(contents, policy())); const std::vector<X509_Certificate>& server_certs = state.server_certs()->cert_chain(); diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h index 3bee89e13..cbeb9ad05 100644 --- a/src/lib/tls/tls_messages.h +++ b/src/lib/tls/tls_messages.h @@ -341,7 +341,7 @@ class Certificate final : public Handshake_Message Handshake_Hash& hash, const std::vector<X509_Certificate>& certs); - explicit Certificate(const std::vector<byte>& buf); + explicit Certificate(const std::vector<byte>& buf, const Policy &policy); private: std::vector<byte> serialize() const override; diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 10b193215..b98f1106c 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -127,6 +127,17 @@ size_t Policy::minimum_dh_group_size() const return 1024; } +size_t Policy::minimum_ecdh_group_size() const + { + return 159; + } + + +size_t Policy::minimum_rsa_bits() const + { + return 1000; // Not 1024, since some certificates use, e.g., only 1023 bits + } + /* * Return allowed compression algorithms */ @@ -147,10 +158,17 @@ bool Policy::send_fallback_scsv(Protocol_Version version) const bool Policy::acceptable_protocol_version(Protocol_Version version) const { - if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - else - return (version >= Protocol_Version::TLS_V10); + // Uses boolean optimization: + // First check the current version (left part), then if it is allowed + // (right part) + // checks are ordered according to their probability + return ( + ( ( version == Protocol_Version::TLS_V10) && allow_tls10() ) || + ( ( version == Protocol_Version::TLS_V12) && allow_tls12() ) || + ( ( version == Protocol_Version::TLS_V11) && allow_tls11() ) || + ( ( version == Protocol_Version::DTLS_V12) && allow_dtls12() ) || + ( ( version == Protocol_Version::DTLS_V10) && allow_dtls10() ) + ); } Protocol_Version Policy::latest_supported_version(bool datagram) const @@ -168,6 +186,11 @@ bool Policy::acceptable_ciphersuite(const Ciphersuite&) const bool Policy::allow_server_initiated_renegotiation() const { return false; } bool Policy::allow_insecure_renegotiation() const { return false; } +bool Policy::allow_tls10() const { return true; } +bool Policy::allow_tls11() const { return true; } +bool Policy::allow_tls12() const { return true; } +bool Policy::allow_dtls10() const { return false; } +bool Policy::allow_dtls12() const { return true; } bool Policy::include_time_in_hello_random() const { return true; } bool Policy::hide_unknown_users() const { return false; } bool Policy::server_uses_own_ciphersuite_preferences() const { return true; } @@ -339,6 +362,11 @@ void print_bool(std::ostream& o, void Policy::print(std::ostream& o) const { + print_bool(o, "allow_tls10", allow_tls10()); + print_bool(o, "allow_tls11", allow_tls11()); + print_bool(o, "allow_tls12", allow_tls12()); + print_bool(o, "allow_dtls10", allow_dtls10()); + print_bool(o, "allow_dtls12", allow_dtls12()); print_vec(o, "ciphers", allowed_ciphers()); print_vec(o, "macs", allowed_macs()); print_vec(o, "signature_hashes", allowed_signature_hashes()); @@ -354,6 +382,8 @@ void Policy::print(std::ostream& o) const o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n'; o << "dh_group = " << dh_group() << '\n'; o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n'; + o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n'; + o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n'; } std::vector<std::string> Strict_Policy::allowed_ciphers() const @@ -376,13 +406,11 @@ std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const return { "ECDH" }; } -bool Strict_Policy::acceptable_protocol_version(Protocol_Version version) const - { - if(version.is_datagram_protocol()) - return (version >= Protocol_Version::DTLS_V12); - else - return (version >= Protocol_Version::TLS_V12); - } +bool Strict_Policy::allow_tls10() const { return false; } +bool Strict_Policy::allow_tls11() const { return false; } +bool Strict_Policy::allow_tls12() const { return true; } +bool Strict_Policy::allow_dtls10() const { return false; } +bool Strict_Policy::allow_dtls12() const { return true; } } diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index f8262cdee..4ae84b833 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -101,6 +101,31 @@ class BOTAN_DLL Policy * Allow servers to initiate a new handshake */ virtual bool allow_server_initiated_renegotiation() const; + + /** + * Allow TLS v1.0 + */ + virtual bool allow_tls10() const; + + /** + * Allow TLS v1.1 + */ + virtual bool allow_tls11() const; + + /** + * Allow TLS v1.2 + */ + virtual bool allow_tls12() const; + + /** + * Allow DTLS v1.0 + */ + virtual bool allow_dtls10() const; + + /** + * Allow DTLS v1.2 + */ + virtual bool allow_dtls12() const; virtual std::string dh_group() const; @@ -108,7 +133,17 @@ class BOTAN_DLL Policy * Return the minimum DH group size we're willing to use */ virtual size_t minimum_dh_group_size() const; - + + /** + * Return the minimum ECDH group size we're willing to use + */ + virtual size_t minimum_ecdh_group_size() const; + + /** + * Return the minimum RSA bit size we're willing to use + */ + virtual size_t minimum_rsa_bits() const; + /** * If this function returns false, unknown SRP/PSK identifiers * will be rejected with an unknown_psk_identifier alert as soon @@ -207,9 +242,12 @@ class BOTAN_DLL NSA_Suite_B_128 : public Policy std::vector<std::string> allowed_ecc_curves() const override { return std::vector<std::string>({"secp256r1"}); } - - bool acceptable_protocol_version(Protocol_Version version) const override - { return version == Protocol_Version::TLS_V12; } + + bool allow_tls10() const override { return false; } + bool allow_tls11() const override { return false; } + bool allow_tls12() const override { return true; } + bool allow_dtls10() const override { return false; } + bool allow_dtls12() const override { return false; } }; /** @@ -220,9 +258,12 @@ class BOTAN_DLL Datagram_Policy : public Policy public: std::vector<std::string> allowed_macs() const override { return std::vector<std::string>({"AEAD"}); } - - bool acceptable_protocol_version(Protocol_Version version) const override - { return version == Protocol_Version::DTLS_V12; } + + bool allow_tls10() const override { return false; } + bool allow_tls11() const override { return false; } + bool allow_tls12() const override { return false; } + bool allow_dtls10() const override { return false; } + bool allow_dtls12() const override { return true; } }; /* @@ -243,7 +284,11 @@ class BOTAN_DLL Strict_Policy : public Policy std::vector<std::string> allowed_key_exchange_methods() const override; - bool acceptable_protocol_version(Protocol_Version version) const override; + bool allow_tls10() const override; + bool allow_tls11() const override; + bool allow_tls12() const override; + bool allow_dtls10() const override; + bool allow_dtls12() const override; }; class BOTAN_DLL Text_Policy : public Policy @@ -267,6 +312,21 @@ class BOTAN_DLL Text_Policy : public Policy std::vector<std::string> allowed_ecc_curves() const override { return get_list("ecc_curves", Policy::allowed_ecc_curves()); } + + bool allow_tls10() const override + { return get_bool("allow_tls10", Policy::allow_tls10()); } + + bool allow_tls11() const override + { return get_bool("allow_tls11", Policy::allow_tls11()); } + + bool allow_tls12() const override + { return get_bool("allow_tls12", Policy::allow_tls12()); } + + bool allow_dtls10() const override + { return get_bool("allow_dtls10", Policy::allow_dtls10()); } + + bool allow_dtls12() const override + { return get_bool("allow_dtls12", Policy::allow_dtls12()); } bool allow_insecure_renegotiation() const override { return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation()); } @@ -286,6 +346,9 @@ class BOTAN_DLL Text_Policy : public Policy size_t minimum_dh_group_size() const override { return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size()); } + size_t minimum_rsa_bits() const override + { return get_len("minimum_rsa_bits", Policy::minimum_rsa_bits()); } + bool hide_unknown_users() const override { return get_bool("hide_unknown_users", Policy::hide_unknown_users()); } diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp index 41b14ae08..39b5afd65 100644 --- a/src/lib/tls/tls_server.cpp +++ b/src/lib/tls/tls_server.cpp @@ -591,7 +591,7 @@ void Server::process_handshake_msg(const Handshake_State* active_state, } else if(type == CERTIFICATE) { - state.client_certs(new Certificate(contents)); + state.client_certs(new Certificate(contents, policy())); state.set_expected_next(CLIENT_KEX); } |