From 47908b70683d9d0789be4fd4168c7e1ec52307ea Mon Sep 17 00:00:00 2001 From: lloyd Date: Thu, 5 Apr 2012 01:30:24 +0000 Subject: Initial client-side support for SRP (finally!). Tested against OpenSSL 1.0.1, only the certificate versions tested currently as OpenSSL doesn't support anon SRP. --- src/tls/c_kex.cpp | 29 +++++++++++++++++++++++++++++ src/tls/s_kex.cpp | 14 ++++++++++++++ src/tls/tls_client.cpp | 1 + src/tls/tls_messages.h | 1 + 4 files changed, 45 insertions(+) diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index ed571852c..0a6339bd0 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, Handshake_State* state, Credentials_Manager& creds, const std::vector& peer_certs, + const std::string& hostname, RandomNumberGenerator& rng) { const std::string kex_algo = state->suite.kex_algo(); @@ -171,6 +173,33 @@ Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer, append_tls_length_value(key_material, priv_key.public_value(), 1); } + else if(kex_algo == "SRP_SHA") + { + const BigInt N = BigInt::decode(reader.get_range(2, 1, 65535)); + const BigInt g = BigInt::decode(reader.get_range(2, 1, 65535)); + MemoryVector salt = reader.get_range(1, 1, 255); + const BigInt B = BigInt::decode(reader.get_range(2, 1, 65535)); + + const std::string srp_group = srp6_group_identifier(N, g); + + const std::string srp_identifier = + creds.srp_identifier("tls-client", hostname); + + const std::string srp_password = + creds.srp_password("tls-client", hostname, srp_identifier); + + std::pair srp_vals = + srp6_client_agree(srp_identifier, + srp_password, + srp_group, + "SHA-1", + salt, + B, + rng); + + append_tls_length_value(key_material, BigInt::encode(srp_vals.first), 2); + pre_master = srp_vals.second.bits_of(); + } else { throw Internal_Error("Client_Key_Exchange: Unknown kex " + diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index 6707d2611..a5c8ff8d7 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -167,6 +167,20 @@ Server_Key_Exchange::Server_Key_Exchange(const MemoryRegion& buf, m_params.push_back(get_byte(1, curve_id)); append_tls_length_value(m_params, ecdh_key, 1); } + else if(kex_algo == "SRP_SHA") + { + // 2 bigints (N,g) then salt, then server B + + const BigInt N = BigInt::decode(reader.get_range(2, 1, 65535)); + const BigInt g = BigInt::decode(reader.get_range(2, 1, 65535)); + MemoryVector salt = reader.get_range(1, 1, 255); + const BigInt B = BigInt::decode(reader.get_range(2, 1, 65535)); + + append_tls_length_value(m_params, BigInt::encode(N), 2); + append_tls_length_value(m_params, BigInt::encode(g), 2); + append_tls_length_value(m_params, salt, 1); + append_tls_length_value(m_params, BigInt::encode(B), 2); + } else if(kex_algo != "PSK") throw Decoding_Error("Server_Key_Exchange: Unsupported kex type " + kex_algo); diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index 2ec7eec2e..850d053a2 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -342,6 +342,7 @@ void Client::process_handshake_msg(Handshake_Type type, state, creds, peer_certs, + state->client_hello->sni_hostname(), rng); state->keys = Session_Keys(state, diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index 920a1c7a7..ff6ebda4d 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -238,6 +238,7 @@ class Client_Key_Exchange : public Handshake_Message Handshake_State* state, Credentials_Manager& creds, const std::vector& peer_certs, + const std::string& hostname, RandomNumberGenerator& rng); Client_Key_Exchange(const MemoryRegion& buf, -- cgit v1.2.3