diff options
author | lloyd <[email protected]> | 2012-01-23 13:28:40 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-23 13:28:40 +0000 |
commit | 99b96f74af6e13f99f53ecda061697da72c5d4fb (patch) | |
tree | e3af6f058270da388acc2ffd3e74bbc86ba1c68c /src/tls | |
parent | e0065f2af522b9573aaf364391139ac12e77eecb (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.cpp | 68 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 30 | ||||
-rw-r--r-- | src/tls/tls_extensions.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 2 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 1 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 8 |
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, |