aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/tls
diff options
context:
space:
mode:
authorJack Lloyd <[email protected]>2016-11-25 17:15:28 -0500
committerJack Lloyd <[email protected]>2016-11-25 17:15:28 -0500
commitce1c593c8f6258a5fa0df50f620e4bdde4e7d034 (patch)
treef27f17e6f24657d138dd1946314801d9415e4a6e /src/lib/tls
parent4a849b7ebb329630ef03d5b3961d57c5f76cfa0b (diff)
parentcdb20d3599f38807f4495c9c705b5864928b2824 (diff)
Merge GH #653 OCSP and X.509 path validation refactor
Splits up path validation into several sub-functions for easier testing and creating customized validation code. Much improved OCSP handling and OCSP tests.
Diffstat (limited to 'src/lib/tls')
-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.h59
-rw-r--r--src/lib/tls/tls_channel.cpp12
-rw-r--r--src/lib/tls/tls_client.cpp8
-rw-r--r--src/lib/tls/tls_policy.cpp8
-rw-r--r--src/lib/tls/tls_policy.h18
-rw-r--r--src/lib/tls/tls_server.cpp9
9 files changed, 149 insertions, 86 deletions
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..e95b1c0f7
--- /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/tls_policy.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,
+ const TLS::Policy& policy)
+ {
+ if(cert_chain.empty())
+ throw Invalid_Argument("Certificate chain was empty");
+
+ Path_Validation_Restrictions restrictions(true, policy.minimum_signature_strength());
+
+ 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(),
+ tls_verify_cert_chain_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..c5fe32f29 100644
--- a/src/lib/tls/tls_callbacks.h
+++ b/src/lib/tls/tls_callbacks.h
@@ -11,11 +11,22 @@
#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;
+class Policy;
/**
* Encapsulates the callbacks that a TLS channel will make which are due to
@@ -53,7 +64,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 +92,52 @@ 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 trusted_roots the list of trusted certificates
+
+ * @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.
+ * @param policy the TLS policy associated with the session being authenticated
+ * using the certificate chain
+ */
+ 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,
+ const TLS::Policy& policy);
+
+ /**
+ * Called by default `tls_verify_cert_chain` to get the timeout to use for OCSP
+ * requests. Return 0 to disable online OCSP checks.
+ */
+ virtual std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const
+ {
+ return std::chrono::milliseconds(0);
+ }
+
+ /**
* 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..185084734 100644
--- a/src/lib/tls/tls_client.cpp
+++ b/src/lib/tls/tls_client.cpp
@@ -391,7 +391,13 @@ 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(),
+ policy());
}
catch(std::exception& e)
{
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index 49a8ad1fc..4bd071d0b 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -156,6 +156,11 @@ size_t Policy::minimum_ecdh_group_size() const
return 255;
}
+size_t Policy::minimum_signature_strength() const
+ {
+ return 110;
+ }
+
size_t Policy::minimum_rsa_bits() const
{
/* Default assumption is all end-entity certificates should
@@ -466,6 +471,7 @@ void Policy::print(std::ostream& o) const
o << "minimum_dh_group_size = " << minimum_dh_group_size() << '\n';
o << "minimum_ecdh_group_size = " << minimum_ecdh_group_size() << '\n';
o << "minimum_rsa_bits = " << minimum_rsa_bits() << '\n';
+ o << "minimum_signature_strength = " << minimum_signature_strength() << '\n';
}
std::vector<std::string> Strict_Policy::allowed_ciphers() const
@@ -485,7 +491,7 @@ std::vector<std::string> Strict_Policy::allowed_macs() const
std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const
{
- return { "ECDH" };
+ return { "CECPQ1", "ECDH" };
}
bool Strict_Policy::allow_tls10() const { return false; }
diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h
index efef7e1f7..519139fff 100644
--- a/src/lib/tls/tls_policy.h
+++ b/src/lib/tls/tls_policy.h
@@ -57,6 +57,15 @@ class BOTAN_DLL Policy
*/
virtual std::vector<std::string> allowed_signature_methods() const;
+ /**
+ * The minimum signature strength we will accept
+ * Returning 80 allows RSA 1024 and SHA-1. Values larger than 80 disable SHA-1 support.
+ * Returning 110 allows RSA 2048.
+ * Return 128 to force ECC (P-256) or large (~3000 bit) RSA keys.
+ * Default is 110
+ */
+ virtual size_t minimum_signature_strength() const;
+
bool allowed_signature_method(const std::string& sig_method) const;
/**
@@ -301,7 +310,9 @@ class BOTAN_DLL NSA_Suite_B_128 : public Policy
std::vector<std::string> allowed_ecc_curves() const override
{ return std::vector<std::string>({"secp256r1"}); }
-
+
+ size_t minimum_signature_strength() const override { return 128; }
+
bool allow_tls10() const override { return false; }
bool allow_tls11() const override { return false; }
bool allow_tls12() const override { return true; }
@@ -419,7 +430,10 @@ class BOTAN_DLL Text_Policy : public Policy
size_t minimum_rsa_bits() const override
{ return get_len("minimum_rsa_bits", Policy::minimum_rsa_bits()); }
-
+
+ size_t minimum_signature_strength() const override
+ { return get_len("minimum_signature_strength", Policy::minimum_signature_strength()); }
+
bool hide_unknown_users() const override
{ return get_bool("hide_unknown_users", Policy::hide_unknown_users()); }
diff --git a/src/lib/tls/tls_server.cpp b/src/lib/tls/tls_server.cpp
index 5e3b222f1..4e07b5f7c 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -523,7 +523,14 @@ 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,
+ policy());
}
catch ( std::exception& e )
{