aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-27 20:16:13 +0000
committerlloyd <[email protected]>2012-01-27 20:16:13 +0000
commit6a8175eb54d37732c81ab292957c3f3fa2a7cc78 (patch)
tree9e1af2d80079ba744d7cb64363df648c50e4c5cf
parentce8566f949b714366f104d8a1c09e0602f380f06 (diff)
Server side PSK
-rw-r--r--src/tls/c_kex.cpp179
-rw-r--r--src/tls/s_kex.cpp24
-rw-r--r--src/tls/tls_messages.h11
-rw-r--r--src/tls/tls_server.cpp11
4 files changed, 124 insertions, 101 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp
index 7040a6068..665048b97 100644
--- a/src/tls/c_kex.cpp
+++ b/src/tls/c_kex.cpp
@@ -18,6 +18,9 @@
#include <botan/loadstor.h>
#include <memory>
+#include <iostream>
+#include <botan/hex.h>
+
namespace Botan {
namespace TLS {
@@ -218,63 +221,14 @@ 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 Handshake_State* state)
- {
- 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(kex_algo == "RSA" || kex_algo == "DH")
- key_material = reader.get_range<byte>(2, 0, 65535);
- else if(kex_algo == "ECDH")
- key_material = reader.get_range<byte>(1, 1, 255);
- else if(kex_algo == "PSK")
- key_material = reader.get_range<byte>(2, 0, 65535);
- else
- throw Internal_Error("Client_Key_Exchange received unknown kex type " + kex_algo);
- }
- }
-
-/*
-* Return the pre_master_secret (server side implementation)
-*/
-SecureVector<byte>
-Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
- const Handshake_State* state,
- Credentials_Manager& creds,
- const Policy& policy)
+ const Handshake_State* state,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng)
{
const std::string kex_algo = state->suite.kex_algo();
- if(kex_algo == "PSK")
- {
- const std::string psk_identity(
- reinterpret_cast<const char*>(&key_material[0]),
- key_material.size());
-
- SymmetricKey psk = creds.psk("tls-server",
- state->client_hello->sni_hostname(),
- psk_identity);
-
- if(psk.length() == 0)
- {
- if(policy.hide_unknown_users())
- throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
- "No PKS for identifier " + psk_identity);
- else
- psk = SymmetricKey(rng, 16);
- }
-
- MemoryVector<byte> zeros(psk.length());
-
- append_tls_length_value(pre_master, zeros, 2);
- append_tls_length_value(pre_master, psk.bits_of(), 2);
- }
- else if(kex_algo == "RSA")
+ if(kex_algo == "RSA")
{
BOTAN_ASSERT(state->server_certs && !state->server_certs->cert_chain().empty(),
"No server certificate to use for RSA");
@@ -293,7 +247,15 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
try
{
- pre_master = decryptor.decrypt(key_material);
+ if(state->version == Protocol_Version::SSL_V3)
+ {
+ pre_master = decryptor.decrypt(contents);
+ }
+ else
+ {
+ TLS_Data_Reader reader(contents);
+ pre_master = decryptor.decrypt(reader.get_range<byte>(2, 0, 65535));
+ }
if(pre_master.size() != 48 ||
client_version.major_version() != pre_master[0] ||
@@ -304,46 +266,101 @@ Client_Key_Exchange::pre_master_secret(RandomNumberGenerator& rng,
}
catch(...)
{
+ // Randomize the hide timing channel
pre_master = rng.random_vec(48);
pre_master[0] = client_version.major_version();
pre_master[1] = client_version.minor_version();
}
}
- else if(kex_algo == "DH" || kex_algo == "ECDH")
+ else
{
- const Private_Key& private_key = state->server_kex->server_kex_key();
-
- const PK_Key_Agreement_Key* ka_key =
- dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
+ TLS_Data_Reader reader(contents);
- if(!ka_key)
- throw Internal_Error("Expected key agreement key type but got " +
- private_key.algo_name());
+ SymmetricKey psk;
- try
+ if(kex_algo == "PSK" || kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE")
{
- PK_Key_Agreement ka(*ka_key, "Raw");
+ const std::string psk_identity = reader.get_string(2, 0, 65535);
+
+ psk = creds.psk("tls-server",
+ state->client_hello->sni_hostname(),
+ psk_identity);
+
+ if(psk.length() == 0)
+ {
+ if(policy.hide_unknown_users())
+ throw TLS_Exception(Alert::UNKNOWN_PSK_IDENTITY,
+ "No PSK for identifier " + psk_identity);
+ else
+ psk = SymmetricKey(rng, 16);
+ }
- 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(...)
+
+ if(kex_algo == "PSK")
{
- /*
- * Something failed in the DH computation. To avoid possible
- * timing attacks, randomize the pre-master output and carry
- * on, allowing the protocol to fail later in the finished
- * checks.
- */
- pre_master = rng.random_vec(ka_key->public_value().size());
+ MemoryVector<byte> zeros(psk.length());
+ append_tls_length_value(pre_master, zeros, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
}
- }
- else
- throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
+ else if(kex_algo == "DH" || kex_algo == "PSK_DHE" ||
+ kex_algo == "ECDH" || kex_algo == "PSK_ECDHE")
+ {
+ const Private_Key& private_key = state->server_kex->server_kex_key();
+
+ const PK_Key_Agreement_Key* ka_key =
+ dynamic_cast<const PK_Key_Agreement_Key*>(&private_key);
- return pre_master;
+ 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");
+
+ MemoryVector<byte> client_pubkey;
+
+ std::cout << hex_encode(contents) << "\n";
+
+ if(ka_key->algo_name() == "DH")
+ client_pubkey = reader.get_range<byte>(2, 0, 65535);
+ else
+ client_pubkey = reader.get_range<byte>(1, 0, 255);
+
+ std::cout << hex_encode(client_pubkey) << "\n";
+ std::cout << reader.remaining_bytes() << "\n";
+
+ SecureVector<byte> shared_secret = ka.derive_key(0, client_pubkey).bits_of();
+
+ if(ka_key->algo_name() == "DH")
+ shared_secret = strip_leading_zeros(shared_secret);
+
+ if(kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE")
+ {
+ append_tls_length_value(pre_master, shared_secret, 2);
+ append_tls_length_value(pre_master, psk.bits_of(), 2);
+ }
+ else
+ pre_master = shared_secret;
+ }
+ catch(std::exception &e)
+ {
+ /*
+ * Something failed in the DH computation. To avoid possible
+ * timing attacks, randomize the pre-master output and carry
+ * on, allowing the protocol to fail later in the finished
+ * checks.
+ */
+ std::cout << "Shared secret failed << " << e.what() << "\n";
+ pre_master = rng.random_vec(ka_key->public_value().size());
+ }
+ }
+ else
+ throw Internal_Error("Client_Key_Exchange: Unknown kex type " + kex_algo);
+
+ std::cout << hex_encode(pre_master) << "\n";
+ }
}
}
diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp
index 5a2c4d55f..951107045 100644
--- a/src/tls/s_kex.cpp
+++ b/src/tls/s_kex.cpp
@@ -9,6 +9,7 @@
#include <botan/internal/tls_reader.h>
#include <botan/internal/tls_extensions.h>
#include <botan/internal/assert.h>
+#include <botan/credentials_manager.h>
#include <botan/loadstor.h>
#include <botan/pubkey.h>
#include <botan/dh.h>
@@ -27,14 +28,19 @@ namespace TLS {
Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer,
Handshake_State* state,
const Policy& policy,
+ Credentials_Manager& creds,
RandomNumberGenerator& rng,
- const Private_Key* signing_key)
+ const Private_Key* signing_key) :
+ m_kex_key(0)
{
const std::string kex_algo = state->suite.kex_algo();
if(kex_algo == "PSK" || kex_algo == "PSK_DHE" || kex_algo == "PSK_ECDHE")
{
- std::string identity_hint = "botan";
+ std::string identity_hint =
+ creds.psk_identity_hint("tls-server",
+ state->client_hello->sni_hostname());
+
append_tls_length_value(m_params, identity_hint, 2);
}
@@ -183,14 +189,18 @@ MemoryVector<byte> Server_Key_Exchange::serialize() const
{
MemoryVector<byte> buf = params();
- // This should be an explicit version check
- if(m_hash_algo != "" && m_sig_algo != "")
+ if(m_signature.size())
{
- buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
- buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
+ // This should be an explicit version check
+ if(m_hash_algo != "" && m_sig_algo != "")
+ {
+ buf.push_back(Signature_Algorithms::hash_algo_code(m_hash_algo));
+ buf.push_back(Signature_Algorithms::sig_algo_code(m_sig_algo));
+ }
+
+ append_tls_length_value(buf, m_signature, 2);
}
- append_tls_length_value(buf, m_signature, 2);
return buf;
}
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index 97d72a0cb..7162ece1a 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -213,11 +213,6 @@ class Client_Key_Exchange : public Handshake_Message
const SecureVector<byte>& pre_master_secret() const
{ return pre_master; }
- SecureVector<byte> pre_master_secret(RandomNumberGenerator& rng,
- const Handshake_State* state,
- Credentials_Manager& creds,
- const Policy& policy);
-
Client_Key_Exchange(Record_Writer& output,
Handshake_State* state,
Credentials_Manager& creds,
@@ -225,7 +220,10 @@ class Client_Key_Exchange : public Handshake_Message
RandomNumberGenerator& rng);
Client_Key_Exchange(const MemoryRegion<byte>& buf,
- const Handshake_State* state);
+ const Handshake_State* state,
+ Credentials_Manager& creds,
+ const Policy& policy,
+ RandomNumberGenerator& rng);
private:
MemoryVector<byte> serialize() const { return key_material; }
@@ -379,6 +377,7 @@ class Server_Key_Exchange : public Handshake_Message
Server_Key_Exchange(Record_Writer& writer,
Handshake_State* state,
const Policy& policy,
+ Credentials_Manager& creds,
RandomNumberGenerator& rng,
const Private_Key* signing_key = 0);
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index 645001367..30983f48f 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -308,10 +308,10 @@ void Server::process_handshake_msg(Handshake_Type type,
{
state->server_rsa_kex_key = private_key;
}
- else if(kex_algo != "PSK") // FIXME: means we never send identity hint
+ else
{
state->server_kex =
- new Server_Key_Exchange(writer, state, policy, rng, private_key);
+ new Server_Key_Exchange(writer, state, policy, creds, rng, private_key);
}
std::vector<X509_Certificate> client_auth_CAs =
@@ -358,12 +358,9 @@ void Server::process_handshake_msg(Handshake_Type type,
else
state->set_expected_next(HANDSHAKE_CCS);
- state->client_kex = new Client_Key_Exchange(contents, state);
+ state->client_kex = new Client_Key_Exchange(contents, state, creds, policy, rng);
- SecureVector<byte> pre_master =
- state->client_kex->pre_master_secret(rng, state, creds, policy);
-
- state->keys = Session_Keys(state, pre_master, false);
+ state->keys = Session_Keys(state, state->client_kex->pre_master_secret(), false);
}
else if(type == CERTIFICATE_VERIFY)
{