aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls/tls_client.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/tls/tls_client.cpp')
-rw-r--r--src/lib/tls/tls_client.cpp86
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();