diff options
-rw-r--r-- | src/tls/c_kex.cpp | 179 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 24 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 11 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 11 |
4 files changed, 124 insertions, 101 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index 7040a6068..665048b97 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -18,6 +18,9 @@ #include <botan/loadstor.h> #include <memory> +#include <iostream> +#include <botan/hex.h> + namespace Botan { namespace TLS { @@ -218,63 +221,14 @@ Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, * Read a Client Key Exchange message */ Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents, - const Handshake_State* state) - { - const std::string kex_algo = state->suite.kex_algo(); - - if(kex_algo == "RSA" && state->version == Protocol_Version::SSL_V3) - key_material = contents; - else - { - TLS_Data_Reader reader(contents); - - if(kex_algo == "RSA" || kex_algo == "DH") - key_material = reader.get_range<byte>(2, 0, 65535); - else if(kex_algo == "ECDH") - key_material = reader.get_range<byte>(1, 1, 255); - else if(kex_algo == "PSK") - key_material = reader.get_range<byte>(2, 0, 65535); - else - throw Internal_Error("Client_Key_Exchange received unknown kex type " + kex_algo); - } - } - -/* -* Return the pre_master_secret (server side implementation) -*/ -SecureVector<byte> -Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, - const Handshake_State* state, - Credentials_Manager& creds, - const Policy& policy) + const Handshake_State* state, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng) { const std::string kex_algo = state->suite.kex_algo(); - if(kex_algo == "PSK") - { - const std::string psk_identity( - reinterpret_cast<const char*>(&key_material[0]), - key_material.size()); - - SymmetricKey psk = creds.psk("tls-server", - state->client_hello->sni_hostname(), - psk_identity); - - if(psk.length() == 0) - { - if(policy.hide_unknown_users()) - throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, - "No PKS for identifier " + psk_identity); - else - psk = SymmetricKey(rng, 16); - } - - MemoryVector<byte> zeros(psk.length()); - - append_tls_length_value(pre_master, zeros, 2); - append_tls_length_value(pre_master, psk.bits_of(), 2); - } - else if(kex_algo == "RSA") + if(kex_algo == "RSA") { BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(), "No server certificate to use for RSA"); @@ -293,7 +247,15 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, try { - pre_master = decryptor.decrypt(key_material); + if(state->version == Protocol_Version::SSL_V3) + { + pre_master = decryptor.decrypt(contents); + } + else + { + TLS_Data_Reader reader(contents); + pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535)); + } if(pre_master.size() != 48 || client_version.major_version() != pre_master[0] || @@ -304,46 +266,101 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, } catch(...) { + // Randomize the hide timing channel pre_master = rng.random_vec(48); pre_master[0] = client_version.major_version(); pre_master[1] = client_version.minor_version(); } } - else if(kex_algo == "DH" || kex_algo == "ECDH") + else { - const Private_Key& private_key = state->server_kex->server_kex_key(); - - const PK_Key_Agreement_Key* ka_key = - dynamic_cast<const PK_Key_Agreement_Key*>(&private_key); + TLS_Data_Reader reader(contents); - if(!ka_key) - throw Internal_Error("Expected key agreement key type but got " + - private_key.algo_name()); + SymmetricKey psk; - try + if(kex_algo == "PSK" || kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE") { - PK_Key_Agreement ka(*ka_key, "Raw"); + const std::string psk_identity = reader.get_string(2, 0, 65535); + + psk = creds.psk("tls-server", + state->client_hello->sni_hostname(), + psk_identity); + + if(psk.length() == 0) + { + if(policy.hide_unknown_users()) + throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, + "No PSK for identifier " + psk_identity); + else + psk = SymmetricKey(rng, 16); + } - if(ka_key->algo_name() == "DH") - pre_master = strip_leading_zeros(ka.derive_key(0, key_material).bits_of()); - else - pre_master = ka.derive_key(0, key_material).bits_of(); } - catch(...) + + if(kex_algo == "PSK") { - /* - * Something failed in the DH computation. To avoid possible - * timing attacks, randomize the pre-master output and carry - * on, allowing the protocol to fail later in the finished - * checks. - */ - pre_master = rng.random_vec(ka_key->public_value().size()); + MemoryVector<byte> zeros(psk.length()); + append_tls_length_value(pre_master, zeros, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); } - } - else - throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo); + else if(kex_algo == "DH" || kex_algo == "PSK_DHE" || + kex_algo == "ECDH" || kex_algo == "PSK_ECDHE") + { + const Private_Key& private_key = state->server_kex->server_kex_key(); + + const PK_Key_Agreement_Key* ka_key = + dynamic_cast<const PK_Key_Agreement_Key*>(&private_key); - return pre_master; + if(!ka_key) + throw Internal_Error("Expected key agreement key type but got " + + private_key.algo_name()); + + try + { + PK_Key_Agreement ka(*ka_key, "Raw"); + + MemoryVector<byte> client_pubkey; + + std::cout << hex_encode(contents) << "\n"; + + if(ka_key->algo_name() == "DH") + client_pubkey = reader.get_range<byte>(2, 0, 65535); + else + client_pubkey = reader.get_range<byte>(1, 0, 255); + + std::cout << hex_encode(client_pubkey) << "\n"; + std::cout << reader.remaining_bytes() << "\n"; + + SecureVector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of(); + + if(ka_key->algo_name() == "DH") + shared_secret = strip_leading_zeros(shared_secret); + + if(kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE") + { + append_tls_length_value(pre_master, shared_secret, 2); + append_tls_length_value(pre_master, psk.bits_of(), 2); + } + else + pre_master = shared_secret; + } + catch(std::exception &e) + { + /* + * Something failed in the DH computation. To avoid possible + * timing attacks, randomize the pre-master output and carry + * on, allowing the protocol to fail later in the finished + * checks. + */ + std::cout << "Shared secret failed << " << e.what() << "\n"; + pre_master = rng.random_vec(ka_key->public_value().size()); + } + } + else + throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo); + + std::cout << hex_encode(pre_master) << "\n"; + } } } diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index 5a2c4d55f..951107045 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -9,6 +9,7 @@ #include <botan/internal/tls_reader.h> #include <botan/internal/tls_extensions.h> #include <botan/internal/assert.h> +#include <botan/credentials_manager.h> #include <botan/loadstor.h> #include <botan/pubkey.h> #include <botan/dh.h> @@ -27,14 +28,19 @@ namespace TLS { Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, Handshake_State* state, const Policy& policy, + Credentials_Manager& creds, RandomNumberGenerator& rng, - const Private_Key* signing_key) + const Private_Key* signing_key) : + m_kex_key(0) { const std::string kex_algo = state->suite.kex_algo(); if(kex_algo == "PSK" || kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE") { - std::string identity_hint = "botan"; + std::string identity_hint = + creds.psk_identity_hint("tls-server", + state->client_hello->sni_hostname()); + append_tls_length_value(m_params, identity_hint, 2); } @@ -183,14 +189,18 @@ MemoryVector<byte> Server_Key_Exchange::serialize() const { MemoryVector<byte> buf = params(); - // This should be an explicit version check - if(m_hash_algo != "" && m_sig_algo != "") + if(m_signature.size()) { - buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo)); - buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo)); + // 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)); + buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo)); + } + + append_tls_length_value(buf, m_signature, 2); } - append_tls_length_value(buf, m_signature, 2); return buf; } diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 97d72a0cb..7162ece1a 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -213,11 +213,6 @@ class Client_Key_Exchange : public Handshake_Message const SecureVector<byte>& pre_master_secret() const { return pre_master; } - SecureVector<byte> pre_master_secret(RandomNumberGenerator& rng, - const Handshake_State* state, - Credentials_Manager& creds, - const Policy& policy); - Client_Key_Exchange(Record_Writer& output, Handshake_State* state, Credentials_Manager& creds, @@ -225,7 +220,10 @@ class Client_Key_Exchange : public Handshake_Message RandomNumberGenerator& rng); Client_Key_Exchange(const MemoryRegion<byte>& buf, - const Handshake_State* state); + const Handshake_State* state, + Credentials_Manager& creds, + const Policy& policy, + RandomNumberGenerator& rng); private: MemoryVector<byte> serialize() const { return key_material; } @@ -379,6 +377,7 @@ class Server_Key_Exchange : public Handshake_Message Server_Key_Exchange(Record_Writer& writer, Handshake_State* state, const Policy& policy, + Credentials_Manager& creds, RandomNumberGenerator& rng, const Private_Key* signing_key = 0); diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 645001367..30983f48f 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -308,10 +308,10 @@ void Server::process_handshake_msg(Handshake_Type type, { state->server_rsa_kex_key = private_key; } - else if(kex_algo != "PSK") // FIXME: means we never send identity hint + else { state->server_kex = - new Server_Key_Exchange(writer, state, policy, rng, private_key); + new Server_Key_Exchange(writer, state, policy, creds, rng, private_key); } std::vector<X509_Certificate> client_auth_CAs = @@ -358,12 +358,9 @@ void Server::process_handshake_msg(Handshake_Type type, else state->set_expected_next(HANDSHAKE_CCS); - state->client_kex = new Client_Key_Exchange(contents, state); + state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng); - SecureVector<byte> pre_master = - state->client_kex->pre_master_secret(rng, state, creds, policy); - - state->keys = Session_Keys(state, pre_master, false); + state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false); } else if(type == CERTIFICATE_VERIFY) { |