From 50bcbb4d8f09189cc669bb482487858234da7f6e Mon Sep 17 00:00:00 2001 From: lloyd Date: Wed, 25 Jan 2012 12:49:29 +0000 Subject: Move all key exchange mechanism code (eg DH/ECDH/SRP) out of the server handshake flow and into the server and client key exchange message types. It already was hidden from the client handshake code. --- src/tls/c_kex.cpp | 61 ++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 19 deletions(-) (limited to 'src/tls/c_kex.cpp') diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index 901d9e004..ea2e91972 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -108,8 +109,7 @@ Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, append_tls_length_value(key_material, priv_key.public_value(), 1); } else - throw Internal_Error("Server key exchange type " + state->suite.kex_algo() + - " not known"); + throw Internal_Error("Unknown key exchange type " + state->suite.kex_algo()); } else { @@ -169,18 +169,33 @@ Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion& contents, } /* -* Return the pre_master_secret +* Return the pre_master_secret (server side implementation) */ SecureVector Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, - const Private_Key* priv_key, - Protocol_Version client_version) + const Handshake_State* state) { - if(const RSA_PrivateKey* rsa = dynamic_cast(priv_key)) + const std::string kex_algo = state->suite.kex_algo(); + + if(kex_algo == "") { - PK_Decryptor_EME decryptor(*rsa, "PKCS1v15"); + BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(), + "No server certificate to use for RSA"); + + const Private_Key* private_key = state->server_rsa_kex_key; + + if(!private_key) + throw Internal_Error("Expected RSA kex but no server kex key set"); + + if(!dynamic_cast(private_key)) + throw Internal_Error("Expected RSA key but got " + private_key->algo_name()); + + PK_Decryptor_EME decryptor(*private_key, "PKCS1v15"); - try { + Protocol_Version client_version = state->client_hello->version(); + + try + { pre_master = decryptor.decrypt(key_material); if(pre_master.size() != 48 || @@ -189,7 +204,7 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, { throw Decoding_Error("Client_Key_Exchange: Secret corrupted"); } - } + } catch(...) { pre_master = rng.random_vec(48); @@ -199,18 +214,26 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, return pre_master; } - - // DH or ECDH - if(const PK_Key_Agreement_Key* dh = dynamic_cast(priv_key)) + else if(kex_algo == "DH" || kex_algo == "ECDH") { - try { - PK_Key_Agreement ka(*dh, "Raw"); + const Private_Key& private_key = state->server_kex->server_kex_key(); + + const PK_Key_Agreement_Key* ka_key = + dynamic_cast(&private_key); + + 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"); - if(dh->algo_name() == "DH") + 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(...) { /* @@ -219,13 +242,13 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, * on, allowing the protocol to fail later in the finished * checks. */ - pre_master = rng.random_vec(dh->public_value().size()); + pre_master = rng.random_vec(ka_key->public_value().size()); } return pre_master; } - - throw Invalid_Argument("Client_Key_Exchange: Unknown key type " + priv_key->algo_name()); + else + throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo); } } -- cgit v1.2.3