diff options
author | lloyd <[email protected]> | 2012-01-27 16:34:17 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-27 16:34:17 +0000 |
commit | 133bda471c547842044bd66a44bfe64668e966da (patch) | |
tree | 0420a87f6ac61740bd0b44888df9e97d8e3b5495 | |
parent | b96fde715dddbb3fe1eb6a9077bb92182dfa1635 (diff) |
Server side PSK kex
-rw-r--r-- | src/tls/c_kex.cpp | 35 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 5 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 5 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 5 |
4 files changed, 37 insertions, 13 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index 9f492c5a5..f5afcc100 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -185,21 +185,38 @@ 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 Ciphersuite& suite, - Protocol_Version using_version) + const Handshake_State* state, + Credentials_Manager& creds) { - if(suite.kex_algo() == "RSA" && using_version == Protocol_Version::SSL_V3) + 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(suite.kex_algo() == "RSA" || suite.kex_algo() == "DH") + if(kex_algo == "RSA" || kex_algo == "DH") key_material = reader.get_range<byte>(2, 0, 65535); - else if(suite.kex_algo() == "ECDH") + else if(kex_algo == "ECDH") key_material = reader.get_range<byte>(1, 1, 255); + else if(kex_algo == "PSK") + { + const std::string psk_identity = reader.get_string(2, 0, 65535); + + SymmetricKey psk = creds.psk("tls-server", + state->client_hello->sni_hostname(), + psk_identity); + + MemoryVector<byte> zeros(psk.length()); + + append_tls_length_value(key_material, zeros, 2); + append_tls_length_value(key_material, psk.bits_of(), 2); + + pre_master = key_material; + } else - throw Internal_Error("Unknown client key exch type " + suite.kex_algo()); + throw Internal_Error("Client_Key_Exchange received unknown kex type " + kex_algo); } } @@ -212,7 +229,11 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng, { const std::string kex_algo = state->suite.kex_algo(); - if(kex_algo == "RSA") + if(kex_algo == "PSK") + { + return key_material; + } + else if(kex_algo == "RSA") { BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(), "No server certificate to use for RSA"); diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 41ab6ece4..b29aac600 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -223,8 +223,9 @@ class Client_Key_Exchange : public Handshake_Message RandomNumberGenerator& rng); Client_Key_Exchange(const MemoryRegion<byte>& buf, - const Ciphersuite& suite, - Protocol_Version using_version); + const Handshake_State* state, + Credentials_Manager& creds); + private: MemoryVector<byte> serialize() const { return key_material; } diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp index a547e8fd5..6718b2e1e 100644 --- a/src/tls/tls_policy.cpp +++ b/src/tls/tls_policy.cpp @@ -245,8 +245,11 @@ u16bit Policy::choose_suite(const std::vector<u16bit>& client_suites, continue; } - if(!value_exists(available_cert_types, suite.sig_algo())) + if(suite.sig_algo() != "" && + !value_exists(available_cert_types, suite.sig_algo())) + { continue; + } if(value_exists(client_suites, suite_id)) return suite_id; diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index 9002c3e05..9c4410938 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -308,7 +308,7 @@ void Server::process_handshake_msg(Handshake_Type type, { state->server_rsa_kex_key = private_key; } - else + else if(kex_algo != "PSK") // FIXME: means we never send identity hint { state->server_kex = new Server_Key_Exchange(writer, state, policy, rng, private_key); @@ -358,8 +358,7 @@ void Server::process_handshake_msg(Handshake_Type type, else state->set_expected_next(HANDSHAKE_CCS); - state->client_kex = new Client_Key_Exchange(contents, state->suite, - state->version); + state->client_kex = new Client_Key_Exchange(contents, state, creds); SecureVector<byte> pre_master = state->client_kex->pre_master_secret(rng, state); |