diff options
Diffstat (limited to 'src/lib/tls/tls_client.cpp')
-rw-r--r-- | src/lib/tls/tls_client.cpp | 86 |
1 files changed, 60 insertions, 26 deletions
diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp index 185084734..37dd37812 100644 --- a/src/lib/tls/tls_client.cpp +++ b/src/lib/tls/tls_client.cpp @@ -13,6 +13,8 @@ #include <iterator> #include <sstream> +#include <botan/hex.h> + namespace Botan { namespace TLS { @@ -26,7 +28,7 @@ class Client_Handshake_State : public Handshake_State Client_Handshake_State(Handshake_IO* io, Callbacks& cb) : Handshake_State(io, cb) {} - const Public_Key& get_server_public_Key() const + const Public_Key& get_server_public_key() const { BOTAN_ASSERT(server_public_key, "Server sent us a certificate"); return *server_public_key.get(); @@ -370,16 +372,6 @@ void Client::process_handshake_msg(const Handshake_State* active_state, } else if(type == CERTIFICATE) { - if(state.ciphersuite().kex_algo() != "RSA") - { - state.set_expected_next(SERVER_KEX); - } - else - { - state.set_expected_next(CERTIFICATE_REQUEST); // optional - state.set_expected_next(SERVER_HELLO_DONE); - } - state.server_certs(new Certificate(contents, policy())); const std::vector<X509_Certificate>& server_certs = @@ -389,20 +381,10 @@ void Client::process_handshake_msg(const Handshake_State* active_state, throw TLS_Exception(Alert::HANDSHAKE_FAILURE, "Client: No certificates sent by server"); - 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()); - } + /* + Certificate verification happens after we receive the server hello done, + in case an OCSP response was also available + */ std::unique_ptr<Public_Key> peer_key(server_certs[0].subject_public_key()); @@ -411,6 +393,35 @@ void Client::process_handshake_msg(const Handshake_State* active_state, "Certificate key type did not match ciphersuite"); state.server_public_key.reset(peer_key.release()); + + if(state.ciphersuite().kex_algo() != "RSA") + { + state.set_expected_next(SERVER_KEX); + } + else + { + state.set_expected_next(CERTIFICATE_REQUEST); // optional + state.set_expected_next(SERVER_HELLO_DONE); + } + + if(state.server_hello()->supports_certificate_status_message()) + { + state.set_expected_next(CERTIFICATE_STATUS); // optional + } + } + else if(type == CERTIFICATE_STATUS) + { + state.server_cert_status(new Certificate_Status(contents)); + + if(state.ciphersuite().kex_algo() != "RSA") + { + state.set_expected_next(SERVER_KEX); + } + else + { + state.set_expected_next(CERTIFICATE_REQUEST); // optional + state.set_expected_next(SERVER_HELLO_DONE); + } } else if(type == SERVER_KEX) { @@ -426,7 +437,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state, if(state.ciphersuite().sig_algo() != "") { - const Public_Key& server_key = state.get_server_public_Key(); + const Public_Key& server_key = state.get_server_public_key(); if(!state.server_kex()->verify(server_key, state, policy())) { @@ -444,6 +455,29 @@ void Client::process_handshake_msg(const Handshake_State* active_state, { state.server_hello_done(new Server_Hello_Done(contents)); + if(state.server_certs() != nullptr) + { + try + { + auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-client", m_info.hostname()); + + std::vector<std::shared_ptr<const OCSP::Response>> ocsp; + if(state.server_cert_status() != nullptr) + ocsp.push_back(state.server_cert_status()->response()); + + callbacks().tls_verify_cert_chain(state.server_certs()->cert_chain(), + ocsp, + trusted_CAs, + Usage_Type::TLS_SERVER_AUTH, + m_info.hostname(), + policy()); + } + catch(std::exception& e) + { + throw TLS_Exception(Alert::BAD_CERTIFICATE, e.what()); + } + } + if(state.received_handshake_msg(CERTIFICATE_REQUEST)) { const auto& types = state.cert_req()->acceptable_cert_types(); |