diff options
author | lloyd <[email protected]> | 2012-06-18 18:42:43 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-06-18 18:42:43 +0000 |
commit | a5f0bd2f1a1e80aa4c2f4f1f87c2413f6ac12726 (patch) | |
tree | daa35a2644dc3c7ceef085bc67a37aa99c570162 | |
parent | e24b7da5545a3d8766c85759a2974a93795436e3 (diff) |
Make TLS::Channel::send non-virtual as neither Client nor Server
needed to derive from it. Add a new overload of send taking a
std::string for convenience (eg client.send("GET / HTTP/1.0\n\r")).
Let Channel::renegotiatate's force_full_renegotiation argument default
to false.
Fix a bug where if we negotiated TLS v1.2 and our Policy was
configured to only use MD5 we would send an empty allowed signatures
which is maybe bogus or maybe just ambigious (RFC is unclear, though
we reject in this case). To fix this, support putting MD5 in the
signature algorithms extension, and then in choose_sig_format order
first by our hash preference, and only allow hashes that are allowed
by policy. Thus is a client claims to support both SHA-2 and MD5 we'll
choose SHA-2 even if the client put MD5 first (some versions of GnuTLS
ordered the list backwards due to a bug, so this is actually a useful
behavior).
-rw-r--r-- | src/tls/cert_ver.cpp | 3 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 5 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 12 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 23 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 5 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 23 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 5 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 1 |
9 files changed, 58 insertions, 21 deletions
diff --git a/src/tls/cert_ver.cpp b/src/tls/cert_ver.cpp index e6d90b060..ae00536df 100644 --- a/src/tls/cert_ver.cpp +++ b/src/tls/cert_ver.cpp @@ -21,13 +21,14 @@ namespace TLS { */ Certificate_Verify::Certificate_Verify(Record_Writer& writer, Handshake_State* state, + const Policy& policy, RandomNumberGenerator& rng, const Private_Key* priv_key) { BOTAN_ASSERT_NONNULL(priv_key); std::pair<std::string, Signature_Format> format = - state->choose_sig_format(priv_key, hash_algo, sig_algo, true); + state->choose_sig_format(priv_key, hash_algo, sig_algo, true, policy); PK_Signer signer(*priv_key, format.first, format.second); diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index 7fc7daf2d..694462082 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -126,7 +126,7 @@ Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, BOTAN_ASSERT(signing_key, "No signing key set"); std::pair<std::string, Signature_Format> format = - state->choose_sig_format(signing_key, m_hash_algo, m_sig_algo, false); + state->choose_sig_format(signing_key, m_hash_algo, m_sig_algo, false, policy); PK_Signer signer(*signing_key, format.first, format.second); diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index 3f3677105..fe1376d6e 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -234,6 +234,11 @@ void Channel::send(const byte buf[], size_t buf_size) m_writer.send(APPLICATION_DATA, buf, buf_size); } +void Channel::send(const std::string& string) + { + this->send(reinterpret_cast<const byte*>(string.c_str()), string.size()); + } + void Channel::send_alert(const Alert& alert) { if(alert.is_valid() && !m_connection_closed) diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h index 1f4075b01..4551a377e 100644 --- a/src/tls/tls_channel.h +++ b/src/tls/tls_channel.h @@ -1,6 +1,6 @@ /* * TLS Channel -* (C) 2011 Jack Lloyd +* (C) 2011,2012 Jack Lloyd * * Released under the terms of the Botan license */ @@ -15,6 +15,7 @@ #include <botan/tls_session_manager.h> #include <botan/x509cert.h> #include <vector> +#include <string> namespace Botan { @@ -36,7 +37,12 @@ class BOTAN_DLL Channel /** * Inject plaintext intended for counterparty */ - virtual void send(const byte buf[], size_t buf_size); + void send(const byte buf[], size_t buf_size); + + /** + * Inject plaintext intended for counterparty + */ + void send(const std::string& string); /** * Send a close notification alert @@ -58,7 +64,7 @@ class BOTAN_DLL Channel * @param force_full_renegotiation if true, require a full renegotiation, * otherwise allow session resumption */ - virtual void renegotiate(bool force_full_renegotiation) = 0; + virtual void renegotiate(bool force_full_renegotiation = false) = 0; /** * Attempt to send a heartbeat message (if negotiated with counterparty) diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index 3dd6484db..0231b9c53 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -1,6 +1,6 @@ /* * TLS Client -* (C) 2004-2011 Jack Lloyd +* (C) 2004-2011,2012 Jack Lloyd * * Released under the terms of the Botan license */ @@ -328,9 +328,9 @@ void Client::process_handshake_msg(Handshake_Type type, m_state->set_expected_next(SERVER_HELLO_DONE); m_state->server_kex = new Server_Key_Exchange(contents, - m_state->suite.kex_algo(), - m_state->suite.sig_algo(), - m_state->version()); + m_state->suite.kex_algo(), + m_state->suite.sig_algo(), + m_state->version()); if(m_state->suite.sig_algo() != "") { @@ -361,8 +361,8 @@ void Client::process_handshake_msg(Handshake_Type type, m_hostname); m_state->client_certs = new Certificate(m_writer, - m_state->hash, - client_certs); + m_state->hash, + client_certs); } m_state->client_kex = @@ -374,8 +374,8 @@ void Client::process_handshake_msg(Handshake_Type type, m_rng); m_state->keys = Session_Keys(m_state, - m_state->client_kex->pre_master_secret(), - false); + m_state->client_kex->pre_master_secret(), + false); if(m_state->received_handshake_msg(CERTIFICATE_REQUEST) && !m_state->client_certs->empty()) @@ -386,9 +386,10 @@ void Client::process_handshake_msg(Handshake_Type type, m_hostname); m_state->client_verify = new Certificate_Verify(m_writer, - m_state, - m_rng, - private_key); + m_state, + m_policy, + m_rng, + private_key); } m_writer.send(CHANGE_CIPHER_SPEC, 1); diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp index df25c40a5..d66b055c8 100644 --- a/src/tls/tls_extensions.cpp +++ b/src/tls/tls_extensions.cpp @@ -400,6 +400,8 @@ std::string Signature_Algorithms::hash_algo_name(byte code) { switch(code) { + case 1: + return "MD5"; // code 1 is MD5 - ignore it case 2: @@ -419,6 +421,9 @@ std::string Signature_Algorithms::hash_algo_name(byte code) byte Signature_Algorithms::hash_algo_code(const std::string& name) { + if(name == "MD5") + return 1; + if(name == "SHA-1") return 2; diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp index 481e16e0d..48e587d03 100644 --- a/src/tls/tls_handshake_state.cpp +++ b/src/tls/tls_handshake_state.cpp @@ -197,6 +197,7 @@ namespace { std::string choose_hash(const std::string& sig_algo, Protocol_Version negotiated_version, + const Policy& policy, bool for_client_auth, Client_Hello* client_hello, Certificate_Req* cert_req) @@ -222,10 +223,22 @@ std::string choose_hash(const std::string& sig_algo, cert_req->supported_algos() : client_hello->supported_algos(); - for(auto algo : supported_algos) + if(!supported_algos.empty()) { - if(algo.second == sig_algo) - return algo.first; + const auto hashes = policy.allowed_hashes(); + + /* + * Choose our most preferred hash that the counterparty supports + * in pairing with the signature algorithm we want to use. + */ + for(auto hash : hashes) + { + for(auto algo : supported_algos) + { + if(algo.first == hash && algo.second == sig_algo) + return hash; + } + } } // TLS v1.2 default hash if the counterparty sent nothing @@ -238,13 +251,15 @@ std::pair<std::string, Signature_Format> Handshake_State::choose_sig_format(const Private_Key* key, std::string& hash_algo_out, std::string& sig_algo_out, - bool for_client_auth) + bool for_client_auth, + const Policy& policy) { const std::string sig_algo = key->algo_name(); const std::string hash_algo = choose_hash(sig_algo, this->version(), + policy, for_client_auth, client_hello, cert_req); diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h index ef8b4ee8f..3ac023b1d 100644 --- a/src/tls/tls_handshake_state.h +++ b/src/tls/tls_handshake_state.h @@ -23,6 +23,8 @@ class KDF; namespace TLS { +class Policy; + /** * SSL/TLS Handshake State */ @@ -49,7 +51,8 @@ class Handshake_State choose_sig_format(const Private_Key* key, std::string& hash_algo, std::string& sig_algo, - bool for_client_auth); + bool for_client_auth, + const Policy& policy); std::string srp_identifier() const; diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 0760b1815..0bca2f44c 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -338,6 +338,7 @@ class Certificate_Verify : public Handshake_Message Certificate_Verify(Record_Writer& writer, Handshake_State* state, + const Policy& policy, RandomNumberGenerator& rng, const Private_Key* key); |