diff options
author | lloyd <[email protected]> | 2012-04-06 16:43:24 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-04-06 16:43:24 +0000 |
commit | e91b91578a483a23bd491149d3dd21079c4a27d1 (patch) | |
tree | edec04f11a61140f1199ab1bb2436e3297bb89ca /src/tls | |
parent | 45396449cd84326626c09e48af74ccb008a0aefc (diff) |
Finish up server side SRP support, a little ugly but it works.
Add SRP hooks in the examples
Fix next protocol support in the tls_server example.
Diffstat (limited to 'src/tls')
-rw-r--r-- | src/tls/c_kex.cpp | 4 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 43 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 8 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 2 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 7 | ||||
-rw-r--r-- | src/tls/tls_policy.cpp | 22 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 25 |
7 files changed, 75 insertions, 36 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp index 16c02e2b8..13925a482 100644 --- a/src/tls/c_kex.cpp +++ b/src/tls/c_kex.cpp @@ -332,7 +332,9 @@ Client_Key_Exchange::Client_Key_Exchange(const MemoryRegion<byte>& contents, } else if(kex_algo == "SRP_SHA") { - throw Internal_Error("SRP_SHA server side not done"); + SRP6_Server_Session& srp = state->server_kex->server_srp_params(); + + pre_master = srp.step2(BigInt::decode(reader.get_range<byte>(2, 0, 65535))).bits_of(); } else if(kex_algo == "DH" || kex_algo == "DHE_PSK" || kex_algo == "ECDH" || kex_algo == "ECDHE_PSK") diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index 24bc6ecaa..68a5c16db 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -33,7 +33,7 @@ Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, Credentials_Manager& creds, RandomNumberGenerator& rng, const Private_Key* signing_key) : - m_kex_key(0) + m_kex_key(0), m_srp_params(0) { const std::string hostname = state->client_hello->sni_hostname(); const std::string kex_algo = state->suite.kex_algo(); @@ -93,34 +93,30 @@ Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, { const std::string srp_identifier = state->client_hello->srp_identifier(); - BigInt N, g, v; + std::string group_id; + BigInt v; MemoryVector<byte> salt; const bool found = creds.srp_verifier("tls-server", hostname, srp_identifier, - N, g, v, salt, + group_id, v, salt, policy.hide_unknown_users()); if(!found) throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, "Unknown SRP user " + srp_identifier); -#if 0 - BigInt B = srp6_server_step1(v, srp6_group_identifier(N, g), - "SHA-1", rng); -#else - BigInt B = 0; -#endif + m_srp_params = new SRP6_Server_Session; - append_tls_length_value(m_params, BigInt::encode(N), 2); - append_tls_length_value(m_params, BigInt::encode(g), 2); + BigInt B = m_srp_params->step1(v, group_id, + "SHA-1", rng); + + DL_Group group(group_id); + + append_tls_length_value(m_params, BigInt::encode(group.get_p()), 2); + append_tls_length_value(m_params, BigInt::encode(group.get_g()), 2); append_tls_length_value(m_params, salt, 1); append_tls_length_value(m_params, BigInt::encode(B), 2); - - /* - * To finish, client key exchange needs to know - * group_id, v, b, B - */ } else if(kex_algo != "PSK") throw Internal_Error("Server_Key_Exchange: Unknown kex type " + kex_algo); @@ -150,7 +146,7 @@ Server_Key_Exchange::Server_Key_Exchange(const MemoryRegion<byte>& buf, const std::string& kex_algo, const std::string& sig_algo, Protocol_Version version) : - m_kex_key(0) + m_kex_key(0), m_srp_params(0) { if(buf.size() < 6) throw Decoding_Error("Server_Key_Exchange: Packet corrupted"); @@ -230,6 +226,11 @@ Server_Key_Exchange::Server_Key_Exchange(const MemoryRegion<byte>& buf, } } +Server_Key_Exchange::~Server_Key_Exchange() + { + delete m_kex_key; + delete m_srp_params; + } /** * Serialize a Server Key Exchange message @@ -278,6 +279,14 @@ const Private_Key& Server_Key_Exchange::server_kex_key() const BOTAN_ASSERT(m_kex_key, "Key is non-NULL"); return *m_kex_key; } + +// Only valid for SRP negotiation +SRP6_Server_Session& Server_Key_Exchange::server_srp_params() + { + BOTAN_ASSERT(m_srp_params, "SRP params are non-NULL"); + return *m_srp_params; + } + } } diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp index 48d9abbeb..8e9003108 100644 --- a/src/tls/tls_handshake_state.cpp +++ b/src/tls/tls_handshake_state.cpp @@ -143,6 +143,14 @@ bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const return (hand_received_mask & mask); } +std::string Handshake_State::srp_identifier() const + { + if(suite.valid() && suite.kex_algo() == "SRP_SHA") + return client_hello->srp_identifier(); + + return ""; + } + const MemoryRegion<byte>& Handshake_State::session_ticket() const { if(new_session_ticket && !new_session_ticket->ticket().empty()) diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h index 2a78d1d1e..c347c4574 100644 --- a/src/tls/tls_handshake_state.h +++ b/src/tls/tls_handshake_state.h @@ -64,6 +64,8 @@ class Handshake_State std::string& sig_algo, bool for_client_auth); + std::string srp_identifier() const; + KDF* protocol_specific_prf(); Protocol_Version version() const { return m_version; } diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index ff6ebda4d..c8a9382d6 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -21,6 +21,7 @@ namespace Botan { class Credentials_Manager; +class SRP6_Server_Session; namespace TLS { @@ -396,6 +397,9 @@ class Server_Key_Exchange : public Handshake_Message // Only valid for certain kex types const Private_Key& server_kex_key() const; + // Only valid for SRP negotiation + SRP6_Server_Session& server_srp_params(); + Server_Key_Exchange(Record_Writer& writer, Handshake_State* state, const Policy& policy, @@ -408,11 +412,12 @@ class Server_Key_Exchange : public Handshake_Message const std::string& sig_alg, Protocol_Version version); - ~Server_Key_Exchange() { delete m_kex_key; } + ~Server_Key_Exchange(); private: MemoryVector<byte> serialize() const; Private_Key* m_kex_key; + SRP6_Server_Session* m_srp_params; MemoryVector<byte> m_params; diff --git a/src/tls/tls_policy.cpp b/src/tls/tls_policy.cpp index de3c6f674..c42a6904c 100644 --- a/src/tls/tls_policy.cpp +++ b/src/tls/tls_policy.cpp @@ -47,7 +47,7 @@ std::vector<std::string> Policy::allowed_key_exchange_methods() const { std::vector<std::string> allowed; - //allowed.push_back("SRP_SHA"); + allowed.push_back("SRP_SHA"); //allowed.push_back("ECDHE_PSK"); //allowed.push_back("DHE_PSK"); //allowed.push_back("PSK"); @@ -204,19 +204,10 @@ class Ciphersuite_Preference_Ordering std::vector<u16bit> ciphersuite_list(const Policy& policy, bool have_srp) { - std::vector<std::string> ciphers = policy.allowed_ciphers(); - std::vector<std::string> hashes = policy.allowed_hashes(); - std::vector<std::string> kex = policy.allowed_key_exchange_methods(); - std::vector<std::string> sigs = policy.allowed_signature_methods(); - - if(!have_srp) - { - std::vector<std::string>::iterator i = - std::find(kex.begin(), kex.end(), "SRP_SHA"); - - if(i != kex.end()) - kex.erase(i); - } + const std::vector<std::string> ciphers = policy.allowed_ciphers(); + const std::vector<std::string> hashes = policy.allowed_hashes(); + const std::vector<std::string> kex = policy.allowed_key_exchange_methods(); + const std::vector<std::string> sigs = policy.allowed_signature_methods(); Ciphersuite_Preference_Ordering order(ciphers, hashes, kex, sigs); @@ -230,6 +221,9 @@ std::vector<u16bit> ciphersuite_list(const Policy& policy, if(!suite.valid()) continue; // not a ciphersuite we know, skip + if(!have_srp && suite.kex_algo() == "SRP_SHA") + continue; + if(!value_exists(kex, suite.kex_algo())) continue; // unsupported key exchange diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index f5b4efc30..10872a825 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -91,11 +91,18 @@ bool check_for_resume(Session& session_info, */ u16bit choose_ciphersuite( const Policy& policy, + Credentials_Manager& creds, const std::map<std::string, std::vector<X509_Certificate> >& cert_chains, const Client_Hello* client_hello) { + const bool have_srp = creds.attempt_srp("tls-server", + client_hello->sni_hostname()); + const std::vector<u16bit> client_suites = client_hello->ciphersuites(); - const std::vector<u16bit> server_suites = ciphersuite_list(policy, false); + const std::vector<u16bit> server_suites = ciphersuite_list(policy, have_srp); + + if(server_suites.empty()) + throw Internal_Error("Policy forbids us from negotiating any ciphersuite"); const bool have_shared_ecc_curve = (policy.choose_curve(client_hello->supported_ecc_curves()) != ""); @@ -116,6 +123,18 @@ u16bit choose_ciphersuite( if(cert_chains.count(suite.sig_algo()) == 0) continue; + /* + The client may offer SRP cipher suites in the hello message but + omit the SRP extension. If the server would like to select an + SRP cipher suite in this case, the server SHOULD return a fatal + "unknown_psk_identity" alert immediately after processing the + client hello message. + - RFC 5054 section 2.5.1.2 + */ + if(suite.kex_algo() == "SRP_SHA" && client_hello->srp_identifier() == "") + throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY, + "Client wanted SRP but did not send username"); + return suite_id; } @@ -368,7 +387,7 @@ void Server::process_handshake_msg(Handshake_Type type, state->hash, rng.random_vec(32), // new session ID state->version(), - choose_ciphersuite(policy, cert_chains, state->client_hello), + choose_ciphersuite(policy, creds, cert_chains, state->client_hello), choose_compression(policy, state->client_hello->compression_methods()), state->client_hello->fragment_size(), secure_renegotiation.supported(), @@ -546,7 +565,7 @@ void Server::process_handshake_msg(Handshake_Type type, peer_certs, MemoryVector<byte>(), m_hostname, - "" + state->srp_identifier() ); if(handshake_fn(session_info)) |