aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-20 22:21:12 +0000
committerlloyd <[email protected]>2012-01-20 22:21:12 +0000
commit87fd27adfe84478c52186107fc383890544eeeba (patch)
treef6b360af3115ae7203e15bc834d4397b0dcf28b9
parent5ccc1b53e9f20ba3d074e68844285d15b5a00912 (diff)
When generating a signature in TLS 1.2, respect the request of the
counterparty by using the highest preference hash they have available for the signature type we are generating. This does mean we will do stupid things, if the counterparty is stupid (for instance some versions of GnuTLS will prefer SHA-1 over the SHA-2s - likely someone misread the spec and ordered the list backwards). But because we filter out MD5 we'll never use that; even in the worst case, if someone requests only MD5, we'll skip over it and use SHA-1 as the fallback algorithm. Theoretically this is against the spec because we "MUST" send something compatible, but seriously, fuck em. Right in the eye.
-rw-r--r--src/tls/c_hello.cpp3
-rw-r--r--src/tls/cert_req.cpp19
-rw-r--r--src/tls/s_kex.cpp2
-rw-r--r--src/tls/tls_handshake_state.cpp64
-rw-r--r--src/tls/tls_messages.h6
-rw-r--r--src/tls/tls_policy.cpp3
-rw-r--r--src/tls/tls_policy.h2
-rw-r--r--src/tls/tls_suites.cpp31
8 files changed, 73 insertions, 57 deletions
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp
index d821482fd..2d94de462 100644
--- a/src/tls/c_hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -301,6 +301,7 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
*/
m_supported_algos.push_back(std::make_pair("SHA-1", "RSA"));
m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
}
else
{
@@ -308,8 +309,8 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA"));
m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
}
-
}
if(value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
diff --git a/src/tls/cert_req.cpp b/src/tls/cert_req.cpp
index 4e86a3270..7fbe2a809 100644
--- a/src/tls/cert_req.cpp
+++ b/src/tls/cert_req.cpp
@@ -60,9 +60,24 @@ Certificate_Req::Certificate_Req(const MemoryRegion<byte>& buf,
if(version >= TLS_V12)
{
- std::vector<u16bit> sig_hash_algs = reader.get_range_vector<u16bit>(2, 2, 65534);
+ std::vector<byte> sig_hash_algs = reader.get_range_vector<byte>(2, 2, 65534);
- // FIXME, do something with this
+ if(sig_hash_algs.size() % 2 != 0)
+ throw Decoding_Error("Bad length for signature IDs in certificate request");
+
+ for(size_t i = 0; i != sig_hash_algs.size(); i += 2)
+ {
+ std::string hash = Signature_Algorithms::hash_algo_name(sig_hash_algs[i]);
+ std::string sig = Signature_Algorithms::sig_algo_name(sig_hash_algs[i+1]);
+ m_supported_algos.push_back(std::make_pair(hash, sig));
+ }
+ }
+ else
+ {
+ // The hardcoded settings from previous protocol versions
+ m_supported_algos.push_back(std::make_pair("TLS.Digest.0", "RSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
+ m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
}
u16bit purported_size = reader.get_u16bit();
diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp
index 9ec35e19b..71e40f01c 100644
--- a/src/tls/s_kex.cpp
+++ b/src/tls/s_kex.cpp
@@ -55,7 +55,7 @@ MemoryVector<byte> Server_Key_Exchange::serialize() const
{
MemoryVector<byte> buf = serialize_params();
- // NEEDS VERSION CHECK
+ // This should be an explicit version check
if(m_hash_algo != "" && m_sig_algo != "")
{
buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp
index dfa320cda..c424c9726 100644
--- a/src/tls/tls_handshake_state.cpp
+++ b/src/tls/tls_handshake_state.cpp
@@ -7,6 +7,7 @@
#include <botan/internal/tls_handshake_state.h>
#include <botan/internal/tls_messages.h>
+#include <botan/internal/assert.h>
namespace Botan {
@@ -137,55 +138,42 @@ TLS_Handshake_State::choose_sig_format(const Private_Key* key,
{
const std::string sig_algo = key->algo_name();
- /*
- FIXME: This should respect the algo preferences in the client hello
- (or certificate request, depending on value of for_client_auth).
- */
+ const std::vector<std::pair<std::string, std::string> > supported_algos =
+ (for_client_auth) ? cert_req->supported_algos() : client_hello->supported_algos();
- if(sig_algo == "RSA")
- {
- std::string hash_algo;
+ std::string hash_algo;
- if(for_client_auth && this->version == SSL_V3)
- {
- hash_algo = "Raw";
- }
- else if(this->version < TLS_V12)
+ for(size_t i = 0; i != supported_algos.size(); ++i)
+ {
+ if(supported_algos[i].second == sig_algo)
{
- hash_algo = "TLS.Digest.0";
+ hash_algo = supported_algos[i].first;
+ break;
}
- else
- {
- hash_algo = "SHA-256"; // should be policy
+ }
- sig_algo_out = sig_algo;
- hash_algo_out = hash_algo;
- }
+ if(for_client_auth && this->version == SSL_V3)
+ hash_algo = "Raw";
+ if(hash_algo == "" && this->version == TLS_V12)
+ hash_algo = "SHA-1"; // TLS 1.2 but no compatible hashes set (?)
+
+ BOTAN_ASSERT(hash_algo != "", "Couldn't figure out hash to use");
+
+ if(this->version >= TLS_V12)
+ {
+ hash_algo_out = hash_algo;
+ sig_algo_out = sig_algo;
+ }
+
+ if(sig_algo == "RSA")
+ {
const std::string padding = "EMSA3(" + hash_algo + ")";
return std::make_pair(padding, IEEE_1363);
}
else if(sig_algo == "DSA")
{
- std::string hash_algo;
-
- if(for_client_auth && this->version == SSL_V3)
- {
- hash_algo = "Raw";
- }
- else if(this->version < TLS_V12)
- {
- hash_algo = "SHA-1";
- }
- else
- {
- hash_algo = "SHA-1"; // should be policy
-
- sig_algo_out = sig_algo;
- hash_algo_out = hash_algo;
- }
-
const std::string padding = "EMSA1(" + hash_algo + ")";
return std::make_pair(padding, DER_SEQUENCE);
@@ -206,6 +194,8 @@ TLS_Handshake_State::understand_sig_format(const Public_Key* key,
FIXME: This should check what was sent against the client hello
preferences, or the certificate request, to ensure it was allowed
by those restrictions.
+
+ Or not?
*/
if(this->version < TLS_V12)
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index c86d71045..ffc325a89 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -58,6 +58,9 @@ class Client_Hello : public Handshake_Message
return v;
}
+ std::vector<std::pair<std::string, std::string> > supported_algos() const
+ { return m_supported_algos; }
+
std::vector<u16bit> ciphersuites() const { return m_suites; }
std::vector<byte> compression_methods() const { return m_comp_methods; }
@@ -257,6 +260,9 @@ class Certificate_Req : public Handshake_Message
std::vector<byte> acceptable_types() const { return cert_types; }
std::vector<X509_DN> acceptable_CAs() const { return names; }
+ std::vector<std::pair<std::string, std::string> > supported_algos() const
+ { return m_supported_algos; }
+
Certificate_Req(Record_Writer& writer,
TLS_Handshake_Hash& hash,
const TLS_Policy& policy,
diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp
index 90fa88c82..c02f35a9a 100644
--- a/src/tls/tls_policy.cpp
+++ b/src/tls/tls_policy.cpp
@@ -197,6 +197,9 @@ u16bit TLS_Policy::choose_suite(const std::vector<u16bit>& client_suites,
if(suite.kex_algo() == "ECDH")
continue; // not currently supported
+ if(suite.kex_algo() == "ECDH")
+ continue; // not yet supported
+
if(suite.sig_algo() == "RSA" && have_rsa)
return suite_id;
else if(suite.sig_algo() == "DSA" && have_dsa)
diff --git a/src/tls/tls_policy.h b/src/tls/tls_policy.h
index c14709e7e..5bf60742b 100644
--- a/src/tls/tls_policy.h
+++ b/src/tls/tls_policy.h
@@ -75,7 +75,7 @@ class BOTAN_DLL TLS_Policy
/*
* @return the version we would prefer to negotiate
*/
- virtual Version_Code pref_version() const { return TLS_V11; }
+ virtual Version_Code pref_version() const { return TLS_V12; }
virtual ~TLS_Policy() {}
};
diff --git a/src/tls/tls_suites.cpp b/src/tls/tls_suites.cpp
index 9c63cd593..d49cfe097 100644
--- a/src/tls/tls_suites.cpp
+++ b/src/tls/tls_suites.cpp
@@ -43,7 +43,7 @@ TLS_Ciphersuite TLS_Ciphersuite::lookup_ciphersuite(u16bit suite)
case TLS_RSA_WITH_AES_256_CBC_SHA256:
return TLS_Ciphersuite("RSA", "", "SHA-256", "AES-256", 32);
- // DHE/DSS ciphersuites
+ // DH/DSS ciphersuites
case TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA:
return TLS_Ciphersuite("DSA", "DH", "SHA-1", "TripleDES", 24);
@@ -66,7 +66,7 @@ TLS_Ciphersuite TLS_Ciphersuite::lookup_ciphersuite(u16bit suite)
case TLS_DHE_DSS_WITH_AES_256_CBC_SHA256:
return TLS_Ciphersuite("DSA", "DH", "SHA-256", "AES-256", 32);
- // DHE/RSA ciphersuites
+ // DH/RSA ciphersuites
case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA:
return TLS_Ciphersuite("RSA", "DH", "SHA-1", "TripleDES", 24);
@@ -86,6 +86,19 @@ TLS_Ciphersuite TLS_Ciphersuite::lookup_ciphersuite(u16bit suite)
case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256:
return TLS_Ciphersuite("RSA", "DH", "SHA-256", "AES-256", 32);
+ // ECDH/RSA ciphersuites
+ case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
+ return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "ARC4", 16);
+
+ case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
+ return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "TripleDES", 24);
+
+ case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
+ return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "AES-128", 16);
+
+ case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
+ return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "AES-256", 32);
+
// SRP ciphersuites
case TLS_SRP_SHA_RSA_WITH_3DES_EDE_SHA:
@@ -106,7 +119,7 @@ TLS_Ciphersuite TLS_Ciphersuite::lookup_ciphersuite(u16bit suite)
case TLS_SRP_SHA_DSS_WITH_AES_256_SHA:
return TLS_Ciphersuite("DSA", "SRP", "SHA-1", "AES-256", 32);
- // ECC ciphersuites
+ // ECDH/ECDSA ciphersuites
case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA:
return TLS_Ciphersuite("ECDSA", "ECDH", "SHA-1", "ARC4", 16);
@@ -126,18 +139,6 @@ TLS_Ciphersuite TLS_Ciphersuite::lookup_ciphersuite(u16bit suite)
case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384:
return TLS_Ciphersuite("ECDSA", "ECDH", "SHA-384", "AES-256", 32);
- case TLS_ECDHE_RSA_WITH_RC4_128_SHA:
- return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "ARC4", 16);
-
- case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA:
- return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "TripleDES", 24);
-
- case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA:
- return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "AES-128", 16);
-
- case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA:
- return TLS_Ciphersuite("RSA", "ECDH", "SHA-1", "AES-256", 32);
-
case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256:
return TLS_Ciphersuite("ECDSA", "ECDH", "SHA-256", "AES-128", 16);