aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/manual/credentials_manager.rst34
-rw-r--r--doc/manual/tls.rst30
-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
12 files changed, 173 insertions, 138 deletions
diff --git a/doc/manual/credentials_manager.rst b/doc/manual/credentials_manager.rst
index 04e9e3f2e..006d47343 100644
--- a/doc/manual/credentials_manager.rst
+++ b/doc/manual/credentials_manager.rst
@@ -29,31 +29,6 @@ implementation.
The default implementation returns an empty list.
- .. cpp::function:: void verify_certificate_chain( \
- const std::string& type, \
- const std::string& hostname, \
- const std::vector<X509_Certificate>& cert_chain)
-
- Verifies the certificate chain in *cert_chain*, assuming the
- leaf certificate is the first element.
-
- If *hostname* is set, additionally ``verify_certificate_chain``
- will check that the leaf certificate has a DNS entry matching
- *hostname*.
-
- In the default implementation the *type* argument is passed,
- along with *hostname*, to ``trusted_certificate_authorities`` to
- find out what root(s) should be trusted for verifying this
- certificate.
-
- This function indicates a validation failure by throwing an
- exception.
-
- This function has a default implementation that probably
- sufficies for most uses, however can be overrided for
- implementing extra validation routines such as public key
- pinning.
-
.. cpp:function:: std::vector<X509_Certificate> cert_chain( \
const std::vector<std::string>& cert_key_types, \
const std::string& type, \
@@ -78,6 +53,15 @@ implementation.
the leaf cert of a chain returned previously by ``cert_chain``
or ``cert_chain_single_type``.
+In versions before 1.11.34, there was an additional function on `Credentials_Manager`
+
+ .. cpp::function:: void verify_certificate_chain( \
+ const std::string& type, \
+ const std::string& hostname, \
+ const std::vector<X509_Certificate>& cert_chain)
+
+This function has been replaced by `TLS::Callbacks::tls_verify_cert_chain`.
+
SRP Authentication
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/manual/tls.rst b/doc/manual/tls.rst
index 8508b0a70..2c8b7cf70 100644
--- a/doc/manual/tls.rst
+++ b/doc/manual/tls.rst
@@ -66,12 +66,12 @@ information about the connection.
For DTLS, it is possible to receive records with the `rec_no` field out of
order, or with gaps, cooresponding to reordered or lost datagrams.
- .. cpp:function:: void tls_alert(Alert alert)
+ .. cpp:function:: void tls_alert(Alert alert)
Mandatory. Called when an alert is received from the peer. Note that alerts
received before the handshake is complete are not authenticated and
could have been inserted by a MITM attacker.
-
+
.. cpp:function:: bool tls_session_established(const TLS::Session& session)
Mandatory. Called whenever a negotiation completes. This can happen more
@@ -85,6 +85,32 @@ information about the connection.
exception which will send a close message to the counterparty and
reset the connection state.
+ .. cpp::function:: 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 - default implementation should work for many users.
+ It can be overrided for implementing extra validation routines
+ such as public key pinning.
+
+ Verifies the certificate chain in *cert_chain*, assuming the
+ leaf certificate is the first element.
+
+ If usage is `Usage_Type::TLS_SERVER_AUTH`, then *hostname* should
+ match the information in the server certificate. If usage is
+ `TLS_CLIENT_AUTH`, then *hostname* specifies the host the client
+ is authenticating against (from SNI); the callback can use this for
+ any special site specific auth logic.
+
+ The `trusted_roots` parameter was returned by a call from the
+ associated `Credentials_Manager`.
+
+ .. cpp::function:: std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
+
+ Called by default `tls_verify_cert_cert` to set timeout for OCSP requests.
+ Return 0 to disable OCSP. Current default is 0.
+
.. cpp:function:: std::string tls_server_choose_app_protocol(const std::vector<std::string>& client_protos)
Optional. Called by the server when a client includes a list of protocols in the ALPN extension.
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