aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-06-18 18:42:43 +0000
committerlloyd <[email protected]>2012-06-18 18:42:43 +0000
commita5f0bd2f1a1e80aa4c2f4f1f87c2413f6ac12726 (patch)
treedaa35a2644dc3c7ceef085bc67a37aa99c570162
parente24b7da5545a3d8766c85759a2974a93795436e3 (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.cpp3
-rw-r--r--src/tls/s_kex.cpp2
-rw-r--r--src/tls/tls_channel.cpp5
-rw-r--r--src/tls/tls_channel.h12
-rw-r--r--src/tls/tls_client.cpp23
-rw-r--r--src/tls/tls_extensions.cpp5
-rw-r--r--src/tls/tls_handshake_state.cpp23
-rw-r--r--src/tls/tls_handshake_state.h5
-rw-r--r--src/tls/tls_messages.h1
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);