diff options
author | Harry Reimann <[email protected]> | 2017-11-29 08:35:27 +0100 |
---|---|---|
committer | Harry Reimann <[email protected]> | 2017-12-04 10:54:14 +0100 |
commit | 805bb27dff20e491e76142db2b5fe1bd586d4788 (patch) | |
tree | 64cc4c6ea4633a86509a8b18635c802ec3c3a8e8 | |
parent | b236a8aa0803bac4fba3c1de840379fb01f54ca1 (diff) |
Make support for certificate status messages optional via policy
Don't postpone the verification of a server certificate if certificate
status messages are not expected in client handshake. When using an
external crypto device it may be necessary to verify the certificate
before using the public key for verification of the signature in the
server key exchange message.
-rw-r--r-- | src/lib/tls/msg_client_hello.cpp | 3 | ||||
-rw-r--r-- | src/lib/tls/msg_server_hello.cpp | 9 | ||||
-rw-r--r-- | src/lib/tls/tls_client.cpp | 24 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.cpp | 2 | ||||
-rw-r--r-- | src/lib/tls/tls_policy.h | 7 | ||||
-rw-r--r-- | src/lib/tls/tls_text_policy.cpp | 5 | ||||
-rw-r--r-- | src/tests/unit_tls.cpp | 3 |
7 files changed, 43 insertions, 10 deletions
diff --git a/src/lib/tls/msg_client_hello.cpp b/src/lib/tls/msg_client_hello.cpp index 3b13cf21d..bcd8397e8 100644 --- a/src/lib/tls/msg_client_hello.cpp +++ b/src/lib/tls/msg_client_hello.cpp @@ -105,7 +105,8 @@ Client_Hello::Client_Hello(Handshake_IO& io, m_extensions.add(new Renegotiation_Extension(reneg_info)); m_extensions.add(new Server_Name_Indicator(client_settings.hostname())); - m_extensions.add(new Certificate_Status_Request({}, {})); + if(policy.support_cert_status_message()) + m_extensions.add(new Certificate_Status_Request({}, {})); if(reneg_info.empty() && !next_protocols.empty()) m_extensions.add(new Application_Layer_Protocol_Notification(next_protocols)); diff --git a/src/lib/tls/msg_server_hello.cpp b/src/lib/tls/msg_server_hello.cpp index 67c3d530f..81f9e1f62 100644 --- a/src/lib/tls/msg_server_hello.cpp +++ b/src/lib/tls/msg_server_hello.cpp @@ -37,7 +37,7 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Extended_Master_Secret); // Sending the extension back does not commit us to sending a stapled response - if(client_hello.supports_cert_status_message()) + if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) m_extensions.add(new Certificate_Status_Request); Ciphersuite c = Ciphersuite::by_id(m_ciphersuite); @@ -105,7 +105,7 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Extended_Master_Secret); // Sending the extension back does not commit us to sending a stapled response - if(client_hello.supports_cert_status_message()) + if(client_hello.supports_cert_status_message() && policy.support_cert_status_message()) m_extensions.add(new Certificate_Status_Request); if(client_hello.supports_encrypt_then_mac() && policy.negotiate_encrypt_then_mac()) @@ -115,11 +115,6 @@ Server_Hello::Server_Hello(Handshake_IO& io, m_extensions.add(new Encrypt_then_MAC); } - if(client_hello.supports_cert_status_message()) - { - m_extensions.add(new Certificate_Status_Request); - } - if(resumed_session.ciphersuite().ecc_ciphersuite()) { m_extensions.add(new Supported_Point_Formats(policy.use_ecc_point_compression())); diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 0e620a279..a1b71841d 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -386,7 +386,8 @@ void Client::process_handshake_msg(const Handshake_State* active_state, "Client: No certificates sent by server"); /* - Certificate verification happens after we receive the server hello done, + If the server supports certificate status messages, + certificate verification happens after we receive the server hello done, in case an OCSP response was also available */ @@ -412,6 +413,24 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { state.set_expected_next(CERTIFICATE_STATUS); // optional } + else + { + try + { + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-client", m_info.hostname()); + + callbacks().tls_verify_cert_chain(server_certs, + {}, + trusted_CAs, + Usage_Type::TLS_SERVER_AUTH, + m_info.hostname(), + policy()); + } + catch(std::exception& e) + { + throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); + } + } } else if(type == CERTIFICATE_STATUS) { @@ -459,7 +478,8 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { state.server_hello_done(new Server_Hello_Done(contents)); - if(state.server_certs() != nullptr) + if(state.server_certs() != nullptr && + state.server_hello()->supports_certificate_status_message()) { try { diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp index 5d82eee0c..1c6be6620 100644 --- a/src/lib/tls/tls_policy.cpp +++ b/src/lib/tls/tls_policy.cpp @@ -341,6 +341,7 @@ 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; } bool Policy::negotiate_encrypt_then_mac() const { return true; } +bool Policy::support_cert_status_message() const { return true; } // 1 second initial timeout, 60 second max - see RFC 6347 sec 4.2.4.1 size_t Policy::dtls_initial_timeout() const { return 1*1000; } @@ -552,6 +553,7 @@ void Policy::print(std::ostream& o) const print_bool(o, "hide_unknown_users", hide_unknown_users()); print_bool(o, "server_uses_own_ciphersuite_preferences", server_uses_own_ciphersuite_preferences()); print_bool(o, "negotiate_encrypt_then_mac", negotiate_encrypt_then_mac()); + print_bool(o, "support_cert_status_message", support_cert_status_message()); o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n'; o << "dh_group = " << dh_group() << '\n'; o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n'; diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h index db2cbb3bb..fe7e50f8d 100644 --- a/src/lib/tls/tls_policy.h +++ b/src/lib/tls/tls_policy.h @@ -288,6 +288,11 @@ class BOTAN_PUBLIC_API(2,0) Policy virtual bool negotiate_encrypt_then_mac() const; /** + * Indicates whether certificate status messages should be supported + */ + virtual bool support_cert_status_message() const; + + /** * Return allowed ciphersuites, in order of preference */ virtual std::vector<uint16_t> ciphersuite_list(Protocol_Version version, @@ -502,6 +507,8 @@ class BOTAN_PUBLIC_API(2,0) Text_Policy : public Policy bool negotiate_encrypt_then_mac() const override; + bool support_cert_status_message() const override; + std::string dh_group() const override; size_t minimum_ecdh_group_size() const override; diff --git a/src/lib/tls/tls_text_policy.cpp b/src/lib/tls/tls_text_policy.cpp index 345e6005f..1f93b1e0f 100644 --- a/src/lib/tls/tls_text_policy.cpp +++ b/src/lib/tls/tls_text_policy.cpp @@ -103,6 +103,11 @@ bool Text_Policy::negotiate_encrypt_then_mac() const return get_bool("negotiate_encrypt_then_mac", Policy::negotiate_encrypt_then_mac()); } +bool Text_Policy::support_cert_status_message() const + { + return get_bool("support_cert_status_message", Policy::support_cert_status_message()); + } + std::string Text_Policy::dh_group() const { return get_str("dh_group", Policy::dh_group()); diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp index b22028a0e..026eeb62d 100644 --- a/src/tests/unit_tls.cpp +++ b/src/tests/unit_tls.cpp @@ -1308,6 +1308,9 @@ class TLS_Unit_Tests final : public Test test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD", { { "signature_methods", "RSA" } }); + test_modern_versions(results, *client_ses, *server_ses, *creds, "ECDH", "AES-128/GCM", "AEAD", + { { "support_cert_status_message", "false" } }); + #if defined(BOTAN_HAS_DSA) test_modern_versions(results, *client_ses, *server_ses, *creds, "DH", "AES-128/GCM", "AEAD", { { "signature_methods", "DSA" } }); |