aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-21 20:13:15 -0500
committerJack Lloyd <[email protected]>2016-11-23 08:31:07 -0500
commit33e855853886193867b32da847b8b77f7bc102ee (patch)
treeed8d4d93f247832f7768b5fe1e92cde7109e4352 /src
parent987fcef3f93fe06500b81da2706b358cff85d53a (diff)
Move TLS cert verification callback from Credentials_Manager to TLS::Callbacks
It is the only function in C_M which is called on to process session-specific (and adversarially provided) inputs, rather than passively returning some credential which is typically not session specific.
Diffstat (limited to 'src')
-rw-r--r--src/cli/credentials.h18
-rw-r--r--src/cli/tls_client.cpp26
-rw-r--r--src/lib/tls/credentials_manager.cpp49
-rw-r--r--src/lib/tls/credentials_manager.h19
-rw-r--r--src/lib/tls/tls_callbacks.cpp53
-rw-r--r--src/lib/tls/tls_callbacks.h45
-rw-r--r--src/lib/tls/tls_channel.cpp12
-rw-r--r--src/lib/tls/tls_client.cpp7
-rw-r--r--src/lib/tls/tls_server.cpp8
-rw-r--r--src/tests/unit_tls.cpp10
10 files changed, 136 insertions, 111 deletions
diff --git a/src/cli/credentials.h b/src/cli/credentials.h
index 95bbd5aa4..71acdc83d 100644
--- a/src/cli/credentials.h
+++ b/src/cli/credentials.h
@@ -92,24 +92,6 @@ class Basic_Credentials_Manager : public Botan::Credentials_Manager
return v;
}
- void verify_certificate_chain(
- const std::string& type,
- const std::string& purported_hostname,
- const std::vector<Botan::X509_Certificate>& cert_chain) override
- {
- try
- {
- Credentials_Manager::verify_certificate_chain(type,
- purported_hostname,
- cert_chain);
- }
- catch(std::exception& e)
- {
- std::cout << e.what() << std::endl;
- //throw;
- }
- }
-
std::vector<Botan::X509_Certificate> cert_chain(
const std::vector<std::string>& algos,
const std::string& type,
diff --git a/src/cli/tls_client.cpp b/src/cli/tls_client.cpp
index 0d96f3348..fdbc21ec9 100644
--- a/src/cli/tls_client.cpp
+++ b/src/cli/tls_client.cpp
@@ -10,6 +10,7 @@
#if defined(BOTAN_HAS_TLS) && defined(BOTAN_TARGET_OS_HAS_SOCKETS)
#include <botan/tls_client.h>
+#include <botan/x509path.h>
#include <botan/hex.h>
#if defined(BOTAN_HAS_TLS_SQLITE3_SESSION_MANAGER)
@@ -250,6 +251,31 @@ class TLS_Client final : public Command, public Botan::TLS::Callbacks
return fd;
}
+ void tls_verify_cert_chain(
+ const std::vector<Botan::X509_Certificate>& cert_chain,
+ const std::vector<Botan::Certificate_Store*>& trusted_roots,
+ Botan::Usage_Type usage,
+ const std::string& hostname) override
+ {
+ if(cert_chain.empty())
+ throw std::invalid_argument("Certificate chain was empty");
+
+ Botan::Path_Validation_Restrictions restrictions(true, 80);
+
+ auto ocsp_timeout = std::chrono::milliseconds(300);
+
+ Botan::Path_Validation_Result result =
+ Botan::x509_path_validate(cert_chain,
+ restrictions,
+ trusted_roots,
+ hostname,
+ usage,
+ std::chrono::system_clock::now(),
+ ocsp_timeout);
+
+ std::cout << "Certificate validation status: " << result.result_string() << "\n";
+ }
+
bool tls_session_established(const Botan::TLS::Session& session) override
{
output() << "Handshake complete, " << session.version().to_string()
diff --git a/src/lib/tls/credentials_manager.cpp b/src/lib/tls/credentials_manager.cpp
index 650d922ce..a42fb5789 100644
--- a/src/lib/tls/credentials_manager.cpp
+++ b/src/lib/tls/credentials_manager.cpp
@@ -93,53 +93,4 @@ Credentials_Manager::trusted_certificate_authorities(
return std::vector<Certificate_Store*>();
}
-namespace {
-
-bool cert_in_some_store(const std::vector<Certificate_Store*>& trusted_CAs,
- const X509_Certificate& trust_root)
- {
- for(auto CAs : trusted_CAs)
- if(CAs->certificate_known(trust_root))
- return true;
- return false;
- }
-
-Usage_Type choose_leaf_usage(const std::string& ctx)
- {
- // These are reversed because ctx is denoting the current perspective
- if(ctx == "tls-client")
- return Usage_Type::TLS_SERVER_AUTH;
- else if(ctx == "tls-server")
- return Usage_Type::TLS_CLIENT_AUTH;
- else
- return Usage_Type::UNSPECIFIED;
- }
-
-}
-
-void Credentials_Manager::verify_certificate_chain(
- const std::string& type,
- const std::string& purported_hostname,
- const std::vector<X509_Certificate>& cert_chain)
- {
- if(cert_chain.empty())
- throw Invalid_Argument("Certificate chain was empty");
-
- auto trusted_CAs = trusted_certificate_authorities(type, purported_hostname);
-
- Path_Validation_Restrictions restrictions;
-
- Path_Validation_Result result = x509_path_validate(cert_chain,
- restrictions,
- trusted_CAs,
- purported_hostname,
- choose_leaf_usage(type));
-
- if(!result.successful_validation())
- throw Exception("Certificate validation failure: " + result.result_string());
-
- if(!cert_in_some_store(trusted_CAs, result.trust_root()))
- throw Exception("Certificate chain roots in unknown/untrusted CA");
- }
-
}
diff --git a/src/lib/tls/credentials_manager.h b/src/lib/tls/credentials_manager.h
index 96e840d13..0e2fe0dea 100644
--- a/src/lib/tls/credentials_manager.h
+++ b/src/lib/tls/credentials_manager.h
@@ -44,25 +44,6 @@ class BOTAN_DLL Credentials_Manager
const std::string& context);
/**
- * Check the certificate chain is valid up to a trusted root, and
- * optionally (if hostname != "") that the hostname given is
- * consistent with the leaf certificate.
- *
- * This function should throw an exception derived from
- * std::exception with an informative what() result if the
- * certificate chain cannot be verified.
-
- * @param type specifies the type of operation occurring
- * @param hostname specifies the purported hostname
- * @param cert_chain specifies a certificate chain leading to a
- * trusted root CA certificate.
- */
- virtual void verify_certificate_chain(
- const std::string& type,
- const std::string& hostname,
- const std::vector<X509_Certificate>& cert_chain);
-
- /**
* Return a cert chain we can use, ordered from leaf to root,
* or else an empty vector.
*
diff --git a/src/lib/tls/tls_callbacks.cpp b/src/lib/tls/tls_callbacks.cpp
new file mode 100644
index 000000000..1bf1af6a3
--- /dev/null
+++ b/src/lib/tls/tls_callbacks.cpp
@@ -0,0 +1,53 @@
+/*
+* TLS Callbacks
+* (C) 2016 Jack Lloyd
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/tls_callbacks.h>
+#include <botan/x509path.h>
+#include <botan/ocsp.h>
+#include <botan/certstor.h>
+
+namespace Botan {
+
+TLS::Callbacks::~Callbacks() {}
+
+void TLS::Callbacks::tls_inspect_handshake_msg(const Handshake_Message&)
+ {
+ // default is no op
+ }
+
+std::string TLS::Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>&)
+ {
+ return "";
+ }
+
+void TLS::Callbacks::tls_verify_cert_chain(
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::vector<Certificate_Store*>& trusted_roots,
+ Usage_Type usage,
+ const std::string& hostname)
+ {
+ if(cert_chain.empty())
+ throw Invalid_Argument("Certificate chain was empty");
+
+ Path_Validation_Restrictions restrictions;
+
+ auto ocsp_timeout = std::chrono::milliseconds(300);
+
+ Path_Validation_Result result =
+ x509_path_validate(cert_chain,
+ restrictions,
+ trusted_roots,
+ (usage == Usage_Type::TLS_SERVER_AUTH ? hostname : ""),
+ usage,
+ std::chrono::system_clock::now(),
+ ocsp_timeout);
+
+ if(!result.successful_validation())
+ throw Exception("Certificate validation failure: " + result.result_string());
+ }
+
+}
diff --git a/src/lib/tls/tls_callbacks.h b/src/lib/tls/tls_callbacks.h
index f81071a05..9de7710f4 100644
--- a/src/lib/tls/tls_callbacks.h
+++ b/src/lib/tls/tls_callbacks.h
@@ -11,8 +11,18 @@
#include <botan/tls_session.h>
#include <botan/tls_alert.h>
+
namespace Botan {
+class Certificate_Store;
+class X509_Certificate;
+
+namespace OCSP {
+
+class Response;
+
+}
+
namespace TLS {
class Handshake_Message;
@@ -53,7 +63,7 @@ class BOTAN_DLL Callbacks
virtual void tls_record_received(u64bit seq_no, const uint8_t data[], size_t size) = 0;
/**
- * Mandary callback: alert received
+ * Mandatory callback: alert received
* Called when an alert is received from the peer
* If fatal, the connection is closing. If not fatal, the connection may
* still be closing (depending on the error and the peer).
@@ -81,6 +91,39 @@ class BOTAN_DLL Callbacks
virtual void tls_session_activated() {}
/**
+ * Optional callback with default impl: verify cert chain
+ *
+ * Default implementation performs a standard PKIX validation
+ * and initiates network OCSP request for end-entity cert.
+ * Override to provide different behavior.
+ *
+ * Check the certificate chain is valid up to a trusted root, and
+ * optionally (if hostname != "") that the hostname given is
+ * consistent with the leaf certificate.
+ *
+ * This function should throw an exception derived from
+ * std::exception with an informative what() result if the
+ * certificate chain cannot be verified.
+ *
+ * @param cert_chain specifies a certificate chain leading to a
+ * trusted root CA certificate.
+
+ * @param usage what this cert chain is being used for
+ * Usage_Type::TLS_SERVER_AUTH for server chains,
+ * Usage_Type::TLS_CLIENT_AUTH for client chains,
+ * Usage_Type::UNSPECIFIED for other uses
+ * @param hostname when authenticating a server, this is the hostname
+ * the client requested (eg via SNI). When authenticating a client,
+ * this is the server name the client is authenticating *to*.
+ * Empty in other cases or if no hostname was used.
+ */
+ virtual void tls_verify_cert_chain(
+ const std::vector<X509_Certificate>& cert_chain,
+ const std::vector<Certificate_Store*>& trusted_roots,
+ Usage_Type usage,
+ const std::string& hostname);
+
+ /**
* Optional callback: inspect handshake message
* Throw an exception to abort the handshake.
* Default simply ignores the message.
diff --git a/src/lib/tls/tls_channel.cpp b/src/lib/tls/tls_channel.cpp
index 95b151ad2..c8fe407e2 100644
--- a/src/lib/tls/tls_channel.cpp
+++ b/src/lib/tls/tls_channel.cpp
@@ -19,18 +19,6 @@ namespace Botan {
namespace TLS {
-Callbacks::~Callbacks() {}
-
-void Callbacks::tls_inspect_handshake_msg(const Handshake_Message&)
- {
- // default is no op
- }
-
-std::string Callbacks::tls_server_choose_app_protocol(const std::vector<std::string>&)
- {
- return "";
- }
-
size_t TLS::Channel::IO_BUF_DEFAULT_SIZE = 10*1024;
Channel::Channel(Callbacks& callbacks,
diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp
index 183886c66..99b4ac731 100644
--- a/src/lib/tls/tls_client.cpp
+++ b/src/lib/tls/tls_client.cpp
@@ -391,7 +391,12 @@ void Client::process_handshake_msg(const Handshake_State* active_state,
try
{
- m_creds.verify_certificate_chain("tls-client", m_info.hostname(), server_certs);
+ 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());
}
catch(std::exception& e)
{
diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp
index 5e3b222f1..abe22df3c 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -523,7 +523,13 @@ void Server::process_certificate_verify_msg(Server_Handshake_State& pending_stat
try
{
- m_creds.verify_certificate_chain ( "tls-server", "", client_certs );
+ const std::string sni_hostname = pending_state.client_hello()->sni_hostname();
+ auto trusted_CAs = m_creds.trusted_certificate_authorities("tls-server", sni_hostname);
+
+ callbacks().tls_verify_cert_chain(client_certs,
+ trusted_CAs,
+ Usage_Type::TLS_CLIENT_AUTH,
+ sni_hostname);
}
catch ( std::exception& e )
{
diff --git a/src/tests/unit_tls.cpp b/src/tests/unit_tls.cpp
index b69f97cca..df58f7311 100644
--- a/src/tests/unit_tls.cpp
+++ b/src/tests/unit_tls.cpp
@@ -97,16 +97,6 @@ class Credentials_Manager_Test : public Botan::Credentials_Manager
return chain;
}
- void verify_certificate_chain(
- const std::string& type,
- const std::string& purported_hostname,
- const std::vector<Botan::X509_Certificate>& cert_chain) override
- {
- Credentials_Manager::verify_certificate_chain(type,
- purported_hostname,
- cert_chain);
- }
-
Botan::Private_Key* private_key_for(const Botan::X509_Certificate& crt,
const std::string&,
const std::string&) override