aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-04-06 16:43:24 +0000
committerlloyd <[email protected]>2012-04-06 16:43:24 +0000
commite91b91578a483a23bd491149d3dd21079c4a27d1 (patch)
treeedec04f11a61140f1199ab1bb2436e3297bb89ca
parent45396449cd84326626c09e48af74ccb008a0aefc (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.
-rw-r--r--doc/examples/asio_tls_server.cpp5
-rw-r--r--doc/examples/credentials.h96
-rw-r--r--doc/examples/tls_server.cpp44
-rw-r--r--doc/tls.txt16
-rw-r--r--src/credentials/credentials_manager.cpp38
-rw-r--r--src/credentials/credentials_manager.h36
-rw-r--r--src/tls/c_kex.cpp4
-rw-r--r--src/tls/s_kex.cpp43
-rw-r--r--src/tls/tls_handshake_state.cpp8
-rw-r--r--src/tls/tls_handshake_state.h2
-rw-r--r--src/tls/tls_messages.h7
-rw-r--r--src/tls/tls_policy.cpp22
-rw-r--r--src/tls/tls_server.cpp25
13 files changed, 267 insertions, 79 deletions
diff --git a/doc/examples/asio_tls_server.cpp b/doc/examples/asio_tls_server.cpp
index 5c606a3f2..e721d0455 100644
--- a/doc/examples/asio_tls_server.cpp
+++ b/doc/examples/asio_tls_server.cpp
@@ -215,6 +215,11 @@ class Session_Manager_Locked : public Botan::TLS::Session_Manager
m_session_manager.save(session);
}
+ Botan::u32bit session_lifetime() const
+ {
+ return m_session_manager.session_lifetime();
+ }
+
private:
boost::mutex m_mutex;
Botan::TLS::Session_Manager_In_Memory m_session_manager;
diff --git a/doc/examples/credentials.h b/doc/examples/credentials.h
index 0999b251d..047e42339 100644
--- a/doc/examples/credentials.h
+++ b/doc/examples/credentials.h
@@ -6,6 +6,8 @@
#include <botan/x509self.h>
#include <botan/rsa.h>
#include <botan/dsa.h>
+#include <botan/srp6.h>
+#include <botan/srp6_files.h>
#include <botan/ecdsa.h>
#include <iostream>
#include <fstream>
@@ -25,6 +27,94 @@ class Credentials_Manager_Simple : public Botan::Credentials_Manager
public:
Credentials_Manager_Simple(Botan::RandomNumberGenerator& rng) : rng(rng) {}
+ std::string srp_identifier(const std::string& type,
+ const std::string& hostname)
+ {
+ if(type == "tls-client" && hostname == "localhost")
+ return "user";
+ return "";
+ }
+
+ bool attempt_srp(const std::string& type,
+ const std::string& hostname)
+ {
+ return true;
+ if(hostname == "localhost")
+ return true;
+ return false;
+ }
+
+ std::vector<Botan::X509_Certificate>
+ trusted_certificate_authorities(const std::string&,
+ const std::string&)
+ {
+ std::vector<Botan::X509_Certificate> certs;
+
+ Botan::X509_Certificate verisign("/usr/share/ca-certificates/mozilla/VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.crt");
+ certs.push_back(verisign);
+ return certs;
+ }
+
+ void verify_certificate_chain(
+ const std::string& type,
+ const std::string& purported_hostname,
+ const std::vector<Botan::X509_Certificate>& cert_chain)
+ {
+ try
+ {
+ Botan::Credentials_Manager::verify_certificate_chain(type,
+ purported_hostname,
+ cert_chain);
+ }
+ catch(std::exception& e)
+ {
+ std::cout << "Certificate verification failed - " << e.what() << "\n";
+ }
+ }
+
+ std::string srp_password(const std::string& type,
+ const std::string& hostname,
+ const std::string& identifier)
+ {
+ if(type == "tls-client" && hostname == "localhost" && identifier == "user")
+ return "password";
+
+ return "";
+ }
+
+ bool srp_verifier(const std::string& type,
+ const std::string& context,
+ const std::string& identifier,
+ std::string& group_id,
+ Botan::BigInt& verifier,
+ Botan::MemoryRegion<Botan::byte>& salt,
+ bool generate_fake_on_unknown)
+ {
+
+ std::string pass = srp_password("tls-client", context, identifier);
+ if(pass == "")
+ {
+ if(!generate_fake_on_unknown)
+ return false;
+
+ pass.resize(16);
+ Botan::global_state().global_rng().randomize((Botan::byte*)&pass[0], pass.size());
+ }
+
+ group_id = "modp/srp/2048";
+
+ salt.resize(16);
+ Botan::global_state().global_rng().randomize(&salt[0], salt.size());
+
+ verifier = Botan::generate_srp6_verifier(identifier,
+ pass,
+ salt,
+ group_id,
+ "SHA-1");
+
+ return true;
+ }
+
std::string psk_identity_hint(const std::string&,
const std::string&)
{
@@ -34,6 +124,7 @@ class Credentials_Manager_Simple : public Botan::Credentials_Manager
std::string psk_identity(const std::string&, const std::string&,
const std::string& identity_hint)
{
+ //return "lloyd";
return "Client_identity";
}
@@ -49,6 +140,8 @@ class Credentials_Manager_Simple : public Botan::Credentials_Manager
if(identity == "Client_identity")
return Botan::SymmetricKey("b5a72e1387552e6dc10766dc0eda12961f5b21e17f98ef4c41e6572e53bd7527");
+ if(identity == "lloyd")
+ return Botan::SymmetricKey("85b3c1b7dc62b507636ac767999c9630");
throw Botan::Internal_Error("No PSK set for " + identity);
}
@@ -129,6 +222,9 @@ class Credentials_Manager_Simple : public Botan::Credentials_Manager
{
const std::string hostname = (context == "" ? "localhost" : context);
+ if(hostname == "nosuchname")
+ return std::vector<Botan::X509_Certificate>();
+
std::string key_name = "";
if(value_exists(cert_key_types, "RSA"))
diff --git a/doc/examples/tls_server.cpp b/doc/examples/tls_server.cpp
index a5f2c5d78..057584677 100644
--- a/doc/examples/tls_server.cpp
+++ b/doc/examples/tls_server.cpp
@@ -19,17 +19,6 @@ using namespace std::tr1::placeholders;
#include <iostream>
#include <memory>
-bool handshake_complete(const TLS::Session& session)
- {
- printf("Handshake complete, protocol=%04X ciphersuite=%s compression=%d\n",
- session.version(), session.ciphersuite().to_string().c_str(),
- session.compression_method());
-
- printf("Session id = %s\n", hex_encode(session.session_id()).c_str());
- printf("Master secret = %s\n", hex_encode(session.master_secret()).c_str());
- return true;
- }
-
class Blocking_TLS_Server
{
public:
@@ -44,23 +33,40 @@ class Blocking_TLS_Server
server(
output_fn,
std::tr1::bind(&Blocking_TLS_Server::reader_fn, std::tr1::ref(*this), _1, _2, _3),
- handshake_complete,
+ std::tr1::bind(&Blocking_TLS_Server::handshake_complete, std::tr1::ref(*this), _1),
sessions,
creds,
policy,
- rng),
+ rng,
+ protocols),
exit(false)
{
read_loop();
}
+ bool handshake_complete(const TLS::Session& session)
+ {
+ std::cout << "Handshake complete: "
+ << session.version().to_string() << " "
+ << session.ciphersuite().to_string() << " "
+ << "SessionID: " << hex_encode(session.session_id()) << "\n";
+
+ if(session.srp_identifier() != "")
+ std::cout << "SRP identifier: " << session.srp_identifier() << "\n";
+
+ if(server.next_protocol() != "")
+ std::cout << "Next protocol: " << server.next_protocol() << "\n";
+
+ return true;
+ }
+
size_t read(byte buf[], size_t buf_len)
{
size_t got = read_queue.read(buf, buf_len);
while(!exit && !got)
{
- read_loop(5); // header size
+ read_loop(TLS::TLS_HEADER_SIZE);
got = read_queue.read(buf, buf_len);
}
@@ -148,8 +154,14 @@ int main(int argc, char* argv[])
Credentials_Manager_Simple creds(rng);
std::vector<std::string> protocols;
- protocols.push_back("spdy/2");
- protocols.push_back("http/1.0");
+
+ /*
+ * These are the protocols we advertise to the client, but the
+ * client will send back whatever it actually plans on talking,
+ * which may or may not take into account what we advertise.
+ */
+ protocols.push_back("echo/1.0");
+ protocols.push_back("echo/1.1");
while(true)
{
diff --git a/doc/tls.txt b/doc/tls.txt
index dd4fb1270..267fb6e62 100644
--- a/doc/tls.txt
+++ b/doc/tls.txt
@@ -7,14 +7,14 @@ SSL and TLS
.. versionadded:: 1.10.2
Botan supports both client and server implementations of the SSL/TLS
-protocols, including SSL v3, TLS v1.0, and TLS v1.1 (the insecure and
-obsolete SSL v2 protocol is not supported, beyond processing SSL v2
-client hellos which some implementations send for backwards
-compatability).
-
-The implementation uses ``std::tr1::function``, so it may not have
-been compiled into the version you are using; you can test for the
-feature macro ``BOTAN_HAS_TLS`` to check.
+protocols, including SSL v3, TLS v1.0, TLS v1.1, and TLS v1.2 (the
+insecure and obsolete SSL v2 protocol is not supported, beyond
+processing SSL v2 client hellos which some clients still send for
+backwards compatability with ancient servers).
+
+The implementation uses ``std::tr1::function`` for callbacks, so it
+may not have been compiled into the version you are using; you can
+test for the feature macro ``BOTAN_HAS_TLS`` to check.
General TLS Interface
----------------------------------------
diff --git a/src/credentials/credentials_manager.cpp b/src/credentials/credentials_manager.cpp
index ef5d44819..ed737a08f 100644
--- a/src/credentials/credentials_manager.cpp
+++ b/src/credentials/credentials_manager.cpp
@@ -30,6 +30,12 @@ SymmetricKey Credentials_Manager::psk(const std::string&,
throw Internal_Error("No PSK set for identity " + identity);
}
+bool Credentials_Manager::attempt_srp(const std::string&,
+ const std::string&)
+ {
+ return false;
+ }
+
std::string Credentials_Manager::srp_identifier(const std::string&,
const std::string&)
{
@@ -46,8 +52,7 @@ std::string Credentials_Manager::srp_password(const std::string&,
bool Credentials_Manager::srp_verifier(const std::string&,
const std::string&,
const std::string&,
- BigInt&,
- BigInt&,
+ std::string&,
BigInt&,
MemoryRegion<byte>&,
bool)
@@ -99,6 +104,7 @@ void Credentials_Manager::verify_certificate_chain(
if(!cert_chain[0].matches_dns_name(purported_hostname))
throw std::runtime_error("Certificate did not match hostname");
+#if 1
std::vector<X509_Certificate> CAs = trusted_certificate_authorities(type, purported_hostname);
X509_Store store;
@@ -110,11 +116,33 @@ void Credentials_Manager::verify_certificate_chain(
X509_Code result = store.validate_cert(cert_chain[0], X509_Store::TLS_SERVER);
- if(CAs.empty() && result == CERT_ISSUER_NOT_FOUND)
- return;
+ if(CAs.empty())
+ {
+ if(result == CERT_ISSUER_NOT_FOUND)
+ return;
+ if(result == CANNOT_ESTABLISH_TRUST)
+ return;
+ }
if(result != VERIFIED)
- throw std::runtime_error("Certificate did not validate");
+ throw std::runtime_error("Certificate did not validate, code " + to_string(result));
+#else
+
+ // New X.509 API
+ const Certificate_Store& CAs =
+ trusted_certificate_authorities(type, purported_hostname);
+
+ Path_Validation_Result result =
+ x509_path_validate(cert_chain,
+ Path_Validation_Restrictions(),
+ store);
+
+ if(!result.successful_validation())
+ throw std::runtime_error("Certificate validation failure: " + result.as_string());
+
+ if(!CAs.certificate_known(result.trust_root())
+ throw std::runtime_error("Certificate chain roots in unknown/untrusted CA");
+#endif
}
}
diff --git a/src/credentials/credentials_manager.h b/src/credentials/credentials_manager.h
index e1b4268e3..67da07eec 100644
--- a/src/credentials/credentials_manager.h
+++ b/src/credentials/credentials_manager.h
@@ -49,6 +49,12 @@ class BOTAN_DLL Credentials_Manager
const std::string& identity);
/**
+ * Return true if we should attempt SRP authentication
+ */
+ virtual bool attempt_srp(const std::string& type,
+ const std::string& context);
+
+ /**
* @return identifier for client-side SRP auth, if available
for this type/context. Should return empty string
if password auth not desired/available.
@@ -73,20 +79,21 @@ class BOTAN_DLL Credentials_Manager
virtual bool srp_verifier(const std::string& type,
const std::string& context,
const std::string& identifier,
- BigInt& group_prime,
- BigInt& group_generator,
+ std::string& group_name,
BigInt& verifier,
MemoryRegion<byte>& salt,
bool generate_fake_on_unknown);
/**
- * Return a cert chain we can use, ordered from leaf to root.
- * Assumed that we can get the private key of the leaf with
- * private_key_for
+ * Return a cert chain we can use, ordered from leaf to root,
+ * or else an empty vector.
*
- * @param cert_key_type is a set string representing the allowed
- * key type ("RSA", "DSA", "ECDSA", etc) or empty if no
- * preference.
+ * It is assumed that the caller can get the private key of the
+ * leaf with private_key_for
+ *
+ * @param cert_key_types specifies the key types desired ("RSA",
+ * "DSA", "ECDSA", etc), or empty if there
+ * is no preference by the caller.
*/
virtual std::vector<X509_Certificate> cert_chain(
const std::vector<std::string>& cert_key_types,
@@ -94,13 +101,14 @@ class BOTAN_DLL Credentials_Manager
const std::string& context);
/**
- * Return a cert chain we can use, ordered from leaf to root.
- * Assumed that we can get the private key of the leaf with
- * private_key_for
+ * Return a cert chain we can use, ordered from leaf to root,
+ * or else an empty vector.
+ *
+ * It is assumed that the caller can get the private key of the
+ * leaf with private_key_for
*
- * @param cert_key_type is a set string representing the allowed
- * key type ("RSA", "DSA", "ECDSA", etc) or empty if no
- * preference.
+ * @param cert_key_type specifies the type of key requested
+ * ("RSA", "DSA", "ECDSA", etc)
*/
std::vector<X509_Certificate> cert_chain_single_type(
const std::string& cert_key_type,
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))