aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristian Mainka <[email protected]>2016-05-03 16:41:18 +0200
committerChristian Mainka <[email protected]>2016-05-03 16:41:18 +0200
commit6d327f879c608908ca2c6b9b99f7fd74d498b4ef (patch)
tree37887b96bf353db53aef93525a49706c7967de2d /src
parente6f56a82b639776282b9f4fd6a66e426ea0910d2 (diff)
TLS Policy support
* --policy works for TLS Server and TLS Client * Example policy BSI_TR-02102-2.txt * Fine granular configuration for TLS 1.0, 1.1, 1.2 and DTLS 1.0 and 1.2 * Minimum ecdh and rsa group size
Diffstat (limited to 'src')
-rw-r--r--src/cli/tls_server.cpp23
-rw-r--r--src/lib/tls/msg_certificate.cpp42
-rw-r--r--src/lib/tls/tls_client.cpp2
-rw-r--r--src/lib/tls/tls_messages.h2
-rw-r--r--src/lib/tls/tls_policy.cpp50
-rw-r--r--src/lib/tls/tls_policy.h79
-rw-r--r--src/lib/tls/tls_server.cpp2
7 files changed, 173 insertions, 27 deletions
diff --git a/src/cli/tls_server.cpp b/src/cli/tls_server.cpp
index 2496f5508..7fc38cf31 100644
--- a/src/cli/tls_server.cpp
+++ b/src/cli/tls_server.cpp
@@ -33,7 +33,7 @@ namespace Botan_CLI {
class TLS_Server final : public Command
{
public:
- TLS_Server() : Command("tls_server cert key --port=443 --type=tcp") {}
+ TLS_Server() : Command("tls_server cert key --port=443 --type=tcp --policy=") {}
void go() override
{
@@ -47,7 +47,24 @@ class TLS_Server final : public Command
const bool is_tcp = (transport == "tcp");
- Botan::TLS::Policy policy; // TODO read policy from file
+ std::unique_ptr<Botan::TLS::Policy> policy;
+ const std::string policy_file = get_arg("policy");
+ std::filebuf fb;
+ if(policy_file.size() > 0)
+ {
+ std::ifstream policy_stream(policy_file);
+ if(!policy_stream.good())
+ {
+ error_output() << "Failed reading policy file\n";
+ return;
+ }
+ policy.reset(new Botan::TLS::Text_Policy(policy_stream));
+ }
+
+ if(!policy)
+ {
+ policy.reset(new Botan::TLS::Policy);
+ }
Botan::TLS::Session_Manager_In_Memory session_manager(rng()); // TODO sqlite3
@@ -112,7 +129,7 @@ class TLS_Server final : public Command
std::bind(&TLS_Server::handshake_complete, this, _1),
session_manager,
creds,
- policy,
+ *policy,
rng(),
protocol_chooser,
!is_tcp);
diff --git a/src/lib/tls/msg_certificate.cpp b/src/lib/tls/msg_certificate.cpp
index 5be9379bd..fd998cd5e 100644
--- a/src/lib/tls/msg_certificate.cpp
+++ b/src/lib/tls/msg_certificate.cpp
@@ -31,7 +31,7 @@ Certificate::Certificate(Handshake_IO& io,
/**
* Deserialize a Certificate message
*/
-Certificate::Certificate(const std::vector<byte>& buf)
+Certificate::Certificate(const std::vector<byte>& buf, const Policy &policy)
{
if(buf.size() < 3)
throw Decoding_Error("Certificate: Message malformed");
@@ -54,7 +54,45 @@ Certificate::Certificate(const std::vector<byte>& buf)
throw Decoding_Error("Certificate: Message malformed");
DataSource_Memory cert_buf(&certs[3], cert_size);
- m_certs.push_back(X509_Certificate(cert_buf));
+ X509_Certificate cert(cert_buf);
+
+ std::unique_ptr<Public_Key> cert_pub_key(cert.subject_public_key());
+
+ const std::string algo_name = cert_pub_key->algo_name();
+ const size_t keylength = cert_pub_key->max_input_bits();
+ if(algo_name == "RSA")
+ {
+ const size_t expected_keylength = policy.minimum_rsa_bits();
+ if(keylength < expected_keylength)
+ throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
+ "The peer sent RSA certificate of " +
+ std::to_string(keylength) +
+ " bits, policy requires at least " +
+ std::to_string(expected_keylength));
+ }
+ else if(algo_name == "DH")
+ {
+ const size_t expected_keylength = policy.minimum_dh_group_size();
+ if(keylength < expected_keylength)
+ throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
+ "The peer sent DH certificate of " +
+ std::to_string(keylength) +
+ " bits, policy requires at least " +
+ std::to_string(expected_keylength));
+ }
+ else if(algo_name == "ECDH")
+ {
+ const size_t expected_keylength = policy.minimum_ecdh_group_size();
+ if(keylength < expected_keylength)
+ throw TLS_Exception(Alert::INSUFFICIENT_SECURITY,
+ "The peer sent ECDH certificate of " +
+ std::to_string(keylength) +
+ " bits, policy requires at least " +
+ std::to_string(expected_keylength));
+
+ }
+
+ m_certs.push_back(cert);
certs += cert_size + 3;
}
diff --git a/src/lib/tls/tls_client.cpp b/src/lib/tls/tls_client.cpp
index 301c77c6b..0423b6536 100644
--- a/src/lib/tls/tls_client.cpp
+++ b/src/lib/tls/tls_client.cpp
@@ -352,7 +352,7 @@ void Client::process_handshake_msg(const Handshake_State* active_state,
state.set_expected_next(SERVER_HELLO_DONE);
}
- state.server_certs(new Certificate(contents));
+ state.server_certs(new Certificate(contents, policy()));
const std::vector<X509_Certificate>& server_certs =
state.server_certs()->cert_chain();
diff --git a/src/lib/tls/tls_messages.h b/src/lib/tls/tls_messages.h
index 3bee89e13..cbeb9ad05 100644
--- a/src/lib/tls/tls_messages.h
+++ b/src/lib/tls/tls_messages.h
@@ -341,7 +341,7 @@ class Certificate final : public Handshake_Message
Handshake_Hash& hash,
const std::vector<X509_Certificate>& certs);
- explicit Certificate(const std::vector<byte>& buf);
+ explicit Certificate(const std::vector<byte>& buf, const Policy &policy);
private:
std::vector<byte> serialize() const override;
diff --git a/src/lib/tls/tls_policy.cpp b/src/lib/tls/tls_policy.cpp
index 10b193215..b98f1106c 100644
--- a/src/lib/tls/tls_policy.cpp
+++ b/src/lib/tls/tls_policy.cpp
@@ -127,6 +127,17 @@ size_t Policy::minimum_dh_group_size() const
return 1024;
}
+size_t Policy::minimum_ecdh_group_size() const
+ {
+ return 159;
+ }
+
+
+size_t Policy::minimum_rsa_bits() const
+ {
+ return 1000; // Not 1024, since some certificates use, e.g., only 1023 bits
+ }
+
/*
* Return allowed compression algorithms
*/
@@ -147,10 +158,17 @@ bool Policy::send_fallback_scsv(Protocol_Version version) const
bool Policy::acceptable_protocol_version(Protocol_Version version) const
{
- if(version.is_datagram_protocol())
- return (version >= Protocol_Version::DTLS_V12);
- else
- return (version >= Protocol_Version::TLS_V10);
+ // Uses boolean optimization:
+ // First check the current version (left part), then if it is allowed
+ // (right part)
+ // checks are ordered according to their probability
+ return (
+ ( ( version == Protocol_Version::TLS_V10) && allow_tls10() ) ||
+ ( ( version == Protocol_Version::TLS_V12) && allow_tls12() ) ||
+ ( ( version == Protocol_Version::TLS_V11) && allow_tls11() ) ||
+ ( ( version == Protocol_Version::DTLS_V12) && allow_dtls12() ) ||
+ ( ( version == Protocol_Version::DTLS_V10) && allow_dtls10() )
+ );
}
Protocol_Version Policy::latest_supported_version(bool datagram) const
@@ -168,6 +186,11 @@ bool Policy::acceptable_ciphersuite(const Ciphersuite&) const
bool Policy::allow_server_initiated_renegotiation() const { return false; }
bool Policy::allow_insecure_renegotiation() const { return false; }
+bool Policy::allow_tls10() const { return true; }
+bool Policy::allow_tls11() const { return true; }
+bool Policy::allow_tls12() const { return true; }
+bool Policy::allow_dtls10() const { return false; }
+bool Policy::allow_dtls12() const { return true; }
bool Policy::include_time_in_hello_random() const { return true; }
bool Policy::hide_unknown_users() const { return false; }
bool Policy::server_uses_own_ciphersuite_preferences() const { return true; }
@@ -339,6 +362,11 @@ void print_bool(std::ostream& o,
void Policy::print(std::ostream& o) const
{
+ print_bool(o, "allow_tls10", allow_tls10());
+ print_bool(o, "allow_tls11", allow_tls11());
+ print_bool(o, "allow_tls12", allow_tls12());
+ print_bool(o, "allow_dtls10", allow_dtls10());
+ print_bool(o, "allow_dtls12", allow_dtls12());
print_vec(o, "ciphers", allowed_ciphers());
print_vec(o, "macs", allowed_macs());
print_vec(o, "signature_hashes", allowed_signature_hashes());
@@ -354,6 +382,8 @@ void Policy::print(std::ostream& o) const
o << "session_ticket_lifetime = " << session_ticket_lifetime() << '\n';
o << "dh_group = " << dh_group() << '\n';
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';
}
std::vector<std::string> Strict_Policy::allowed_ciphers() const
@@ -376,13 +406,11 @@ std::vector<std::string> Strict_Policy::allowed_key_exchange_methods() const
return { "ECDH" };
}
-bool Strict_Policy::acceptable_protocol_version(Protocol_Version version) const
- {
- if(version.is_datagram_protocol())
- return (version >= Protocol_Version::DTLS_V12);
- else
- return (version >= Protocol_Version::TLS_V12);
- }
+bool Strict_Policy::allow_tls10() const { return false; }
+bool Strict_Policy::allow_tls11() const { return false; }
+bool Strict_Policy::allow_tls12() const { return true; }
+bool Strict_Policy::allow_dtls10() const { return false; }
+bool Strict_Policy::allow_dtls12() const { return true; }
}
diff --git a/src/lib/tls/tls_policy.h b/src/lib/tls/tls_policy.h
index f8262cdee..4ae84b833 100644
--- a/src/lib/tls/tls_policy.h
+++ b/src/lib/tls/tls_policy.h
@@ -101,6 +101,31 @@ class BOTAN_DLL Policy
* Allow servers to initiate a new handshake
*/
virtual bool allow_server_initiated_renegotiation() const;
+
+ /**
+ * Allow TLS v1.0
+ */
+ virtual bool allow_tls10() const;
+
+ /**
+ * Allow TLS v1.1
+ */
+ virtual bool allow_tls11() const;
+
+ /**
+ * Allow TLS v1.2
+ */
+ virtual bool allow_tls12() const;
+
+ /**
+ * Allow DTLS v1.0
+ */
+ virtual bool allow_dtls10() const;
+
+ /**
+ * Allow DTLS v1.2
+ */
+ virtual bool allow_dtls12() const;
virtual std::string dh_group() const;
@@ -108,7 +133,17 @@ class BOTAN_DLL Policy
* Return the minimum DH group size we're willing to use
*/
virtual size_t minimum_dh_group_size() const;
-
+
+ /**
+ * Return the minimum ECDH group size we're willing to use
+ */
+ virtual size_t minimum_ecdh_group_size() const;
+
+ /**
+ * Return the minimum RSA bit size we're willing to use
+ */
+ virtual size_t minimum_rsa_bits() const;
+
/**
* If this function returns false, unknown SRP/PSK identifiers
* will be rejected with an unknown_psk_identifier alert as soon
@@ -207,9 +242,12 @@ class BOTAN_DLL NSA_Suite_B_128 : public Policy
std::vector<std::string> allowed_ecc_curves() const override
{ return std::vector<std::string>({"secp256r1"}); }
-
- bool acceptable_protocol_version(Protocol_Version version) const override
- { return version == Protocol_Version::TLS_V12; }
+
+ bool allow_tls10() const override { return false; }
+ bool allow_tls11() const override { return false; }
+ bool allow_tls12() const override { return true; }
+ bool allow_dtls10() const override { return false; }
+ bool allow_dtls12() const override { return false; }
};
/**
@@ -220,9 +258,12 @@ class BOTAN_DLL Datagram_Policy : public Policy
public:
std::vector<std::string> allowed_macs() const override
{ return std::vector<std::string>({"AEAD"}); }
-
- bool acceptable_protocol_version(Protocol_Version version) const override
- { return version == Protocol_Version::DTLS_V12; }
+
+ bool allow_tls10() const override { return false; }
+ bool allow_tls11() const override { return false; }
+ bool allow_tls12() const override { return false; }
+ bool allow_dtls10() const override { return false; }
+ bool allow_dtls12() const override { return true; }
};
/*
@@ -243,7 +284,11 @@ class BOTAN_DLL Strict_Policy : public Policy
std::vector<std::string> allowed_key_exchange_methods() const override;
- bool acceptable_protocol_version(Protocol_Version version) const override;
+ bool allow_tls10() const override;
+ bool allow_tls11() const override;
+ bool allow_tls12() const override;
+ bool allow_dtls10() const override;
+ bool allow_dtls12() const override;
};
class BOTAN_DLL Text_Policy : public Policy
@@ -267,6 +312,21 @@ class BOTAN_DLL Text_Policy : public Policy
std::vector<std::string> allowed_ecc_curves() const override
{ return get_list("ecc_curves", Policy::allowed_ecc_curves()); }
+
+ bool allow_tls10() const override
+ { return get_bool("allow_tls10", Policy::allow_tls10()); }
+
+ bool allow_tls11() const override
+ { return get_bool("allow_tls11", Policy::allow_tls11()); }
+
+ bool allow_tls12() const override
+ { return get_bool("allow_tls12", Policy::allow_tls12()); }
+
+ bool allow_dtls10() const override
+ { return get_bool("allow_dtls10", Policy::allow_dtls10()); }
+
+ bool allow_dtls12() const override
+ { return get_bool("allow_dtls12", Policy::allow_dtls12()); }
bool allow_insecure_renegotiation() const override
{ return get_bool("allow_insecure_renegotiation", Policy::allow_insecure_renegotiation()); }
@@ -286,6 +346,9 @@ class BOTAN_DLL Text_Policy : public Policy
size_t minimum_dh_group_size() const override
{ return get_len("minimum_dh_group_size", Policy::minimum_dh_group_size()); }
+ size_t minimum_rsa_bits() const override
+ { return get_len("minimum_rsa_bits", Policy::minimum_rsa_bits()); }
+
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 41b14ae08..39b5afd65 100644
--- a/src/lib/tls/tls_server.cpp
+++ b/src/lib/tls/tls_server.cpp
@@ -591,7 +591,7 @@ void Server::process_handshake_msg(const Handshake_State* active_state,
}
else if(type == CERTIFICATE)
{
- state.client_certs(new Certificate(contents));
+ state.client_certs(new Certificate(contents, policy()));
state.set_expected_next(CLIENT_KEX);
}