aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-01-23 13:28:40 +0000
committerlloyd <[email protected]>2012-01-23 13:28:40 +0000
commit99b96f74af6e13f99f53ecda061697da72c5d4fb (patch)
treee3af6f058270da388acc2ffd3e74bbc86ba1c68c /src/tls
parente0065f2af522b9573aaf364391139ac12e77eecb (diff)
Have the client key exchange examine the server key exchange message
directly (if it was sent), so that the client implementation doesn't have to know what key exchange mechanisms we actually support. Return a value in ECC curves extension serialization method.
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/c_kex.cpp68
-rw-r--r--src/tls/tls_client.cpp30
-rw-r--r--src/tls/tls_extensions.cpp2
-rw-r--r--src/tls/tls_handshake_state.cpp2
-rw-r--r--src/tls/tls_handshake_state.h1
-rw-r--r--src/tls/tls_messages.h8
6 files changed, 59 insertions, 52 deletions
diff --git a/src/tls/c_kex.cpp b/src/tls/c_kex.cpp
index 8abea8fcd..b2dd0b861 100644
--- a/src/tls/c_kex.cpp
+++ b/src/tls/c_kex.cpp
@@ -40,42 +40,66 @@ SecureVector<byte> strip_leading_zeros(const MemoryRegion<byte>& input)
* Create a new Client Key Exchange message
*/
Client_Key_Exchange::Client_Key_Exchange(Record_Writer& writer,
- TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- const Public_Key* pub_key,
- Version_Code using_version,
- Version_Code pref_version)
+ TLS_Handshake_State* state,
+ const std::vector<X509_Certificate>& peer_certs,
+ RandomNumberGenerator& rng)
{
include_length = true;
- if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key))
+ if(state->server_kex)
{
- DH_PrivateKey priv_key(rng, dh_pub->get_domain());
+ std::auto_ptr<Public_Key> pub_key(state->server_kex->key());
- PK_Key_Agreement ka(priv_key, "Raw");
+ if(pub_key->algo_name() != state->suite.kex_algo())
+ throw TLS_Exception(HANDSHAKE_FAILURE,
+ "Server sent a " + pub_key->algo_name() +
+ " key but we expected " + state->suite.kex_algo());
- pre_master = strip_leading_zeros(
- ka.derive_key(0, dh_pub->public_value()).bits_of());
+ if(const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(pub_key.get()))
+ {
+ DH_PrivateKey priv_key(rng, dh_pub->get_domain());
+
+ PK_Key_Agreement ka(priv_key, "Raw");
- key_material = priv_key.public_value();
+ pre_master = strip_leading_zeros(
+ ka.derive_key(0, dh_pub->public_value()).bits_of());
+
+ key_material = priv_key.public_value();
+ }
+ else
+ throw Internal_Error("Server key exchange not a known key type");
}
- else if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key))
+ else
{
- pre_master = rng.random_vec(48);
- pre_master[0] = (pref_version >> 8) & 0xFF;
- pre_master[1] = (pref_version ) & 0xFF;
+ // No server key exchange msg better mean a RSA key in the cert
+
+ std::auto_ptr<Public_Key> pub_key(peer_certs[0].subject_public_key());
- PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");
+ if(peer_certs.empty())
+ throw Internal_Error("No certificate and no server key exchange");
- key_material = encryptor.encrypt(pre_master, rng);
+ if(const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(pub_key.get()))
+ {
+ const Version_Code pref_version = state->client_hello->version();
- if(using_version == SSL_V3)
- include_length = false;
+ pre_master = rng.random_vec(48);
+ pre_master[0] = (pref_version >> 8) & 0xFF;
+ pre_master[1] = (pref_version ) & 0xFF;
+
+ PK_Encryptor_EME encryptor(*rsa_pub, "PKCS1v15");
+
+ key_material = encryptor.encrypt(pre_master, rng);
+
+ if(state->version == SSL_V3)
+ include_length = false;
+ }
+ else
+ throw TLS_Exception(HANDSHAKE_FAILURE,
+ "Expected a RSA key in server cert but got " +
+ pub_key->algo_name());
}
- else
- throw Invalid_Argument("Client_Key_Exchange: Key not RSA or DH");
- send(writer, hash);
+ send(writer, state->hash);
}
/*
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 1d79327e8..48f0aec16 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -9,9 +9,7 @@
#include <botan/internal/tls_handshake_state.h>
#include <botan/internal/tls_messages.h>
#include <botan/internal/stl_util.h>
-#include <botan/rsa.h>
-#include <botan/dsa.h>
-#include <botan/dh.h>
+#include <memory>
namespace Botan {
@@ -255,9 +253,9 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
throw TLS_Exception(BAD_CERTIFICATE,
"TLS_Client: Server certificate is not valid");
- state->kex_pub = peer_certs[0].subject_public_key();
+ std::auto_ptr<Public_Key> peer_key(peer_certs[0].subject_public_key());
- if(state->kex_pub->algo_name() != state->suite.sig_algo())
+ if(peer_key->algo_name() != state->suite.sig_algo())
throw TLS_Exception(ILLEGAL_PARAMETER,
"Certificate key type did not match ciphersuite");
}
@@ -276,22 +274,9 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
if(!state->server_kex->verify(peer_certs[0], state))
{
throw TLS_Exception(DECRYPT_ERROR,
- "Bad signature on server key exchange");
+ "Bad signature on server key exchange");
}
}
-
- if(state->kex_pub)
- delete state->kex_pub;
-
- state->kex_pub = state->server_kex->key();
-
- // this should be in client_key_exchange
- if(dynamic_cast<DH_PublicKey*>(state->kex_pub) &&
- state->suite.kex_algo() != "DH")
- {
- throw TLS_Exception(HANDSHAKE_FAILURE,
- "Server sent DH key but negotiated something else");
- }
}
else if(type == CERTIFICATE_REQUEST)
{
@@ -319,9 +304,10 @@ void TLS_Client::process_handshake_msg(Handshake_Type type,
}
state->client_kex =
- new Client_Key_Exchange(writer, state->hash, rng,
- state->kex_pub, state->version,
- state->client_hello->version());
+ new Client_Key_Exchange(writer,
+ state,
+ peer_certs,
+ rng);
state->keys = Session_Keys(state,
state->client_kex->pre_master_secret(),
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index d9351fdb1..570c7161c 100644
--- a/src/tls/tls_extensions.cpp
+++ b/src/tls/tls_extensions.cpp
@@ -364,6 +364,8 @@ MemoryVector<byte> Supported_Elliptic_Curves::serialize() const
buf[0] = get_byte<u16bit>(0, buf.size()-2);
buf[1] = get_byte<u16bit>(1, buf.size()-2);
+
+ return buf;
}
Supported_Elliptic_Curves::Supported_Elliptic_Curves()
diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp
index c424c9726..6ad9b630c 100644
--- a/src/tls/tls_handshake_state.cpp
+++ b/src/tls/tls_handshake_state.cpp
@@ -89,7 +89,6 @@ TLS_Handshake_State::TLS_Handshake_State()
client_finished = 0;
server_finished = 0;
- kex_pub = 0;
kex_priv = 0;
version = SSL_V3;
@@ -264,7 +263,6 @@ TLS_Handshake_State::~TLS_Handshake_State()
delete client_finished;
delete server_finished;
- delete kex_pub;
delete kex_priv;
}
diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h
index b2ed0dd20..18b289fe1 100644
--- a/src/tls/tls_handshake_state.h
+++ b/src/tls/tls_handshake_state.h
@@ -76,7 +76,6 @@ class TLS_Handshake_State
class Finished* client_finished;
class Finished* server_finished;
- Public_Key* kex_pub;
Private_Key* kex_priv;
TLS_Ciphersuite suite;
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index ffc325a89..e58a3bfbf 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -210,11 +210,9 @@ class Client_Key_Exchange : public Handshake_Message
Version_Code version);
Client_Key_Exchange(Record_Writer& output,
- TLS_Handshake_Hash& hash,
- RandomNumberGenerator& rng,
- const Public_Key* my_key,
- Version_Code using_version,
- Version_Code pref_version);
+ TLS_Handshake_State* state,
+ const std::vector<X509_Certificate>& peer_certs,
+ RandomNumberGenerator& rng);
Client_Key_Exchange(const MemoryRegion<byte>& buf,
const TLS_Ciphersuite& suite,