diff options
author | lloyd <[email protected]> | 2012-01-20 22:21:12 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-20 22:21:12 +0000 |
commit | 87fd27adfe84478c52186107fc383890544eeeba (patch) | |
tree | f6b360af3115ae7203e15bc834d4397b0dcf28b9 | |
parent | 5ccc1b53e9f20ba3d074e68844285d15b5a00912 (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.cpp | 3 | ||||
-rw-r--r-- | src/tls/cert_req.cpp | 19 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 64 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 6 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 3 | ||||
-rw-r--r-- | src/tls/tls_policy.h | 2 | ||||
-rw-r--r-- | src/tls/tls_suites.cpp | 31 |
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); |