diff options
author | lloyd <[email protected]> | 2012-01-19 15:03:07 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-01-19 15:03:07 +0000 |
commit | 30104a60568b392886c1d717a7ca006378552e4d (patch) | |
tree | 2ad36cb3d8ced600d15a85f38ae2f7d9e7a32698 | |
parent | b899ee14925310574da400c2af0f491f8cd2a103 (diff) |
I'm not sure if I like this asthetically, but passing around the
entire handshake state in many cases makes things simpler to update,
in that each message type already knows what it needs depending on the
version, params, etc, and this way a) that knowledge doesn't need to
percolate up the the actual client and server handshake code and b)
each message type can be updated for new formats/version without
having to change its callers. Downside is it hides the dependency
information away, and makes it non-obvious what needs to be created
beforehand for each message to work correctly. However this is
(almost) entirely predicated on the handshake message flows, and these
we control with the next expected message scheme, so this should be
fairly safe to do.
This checkin only updates the ones where it was immediately relevant
but for consistency probably all of them should be updated in the same
way.
-rw-r--r-- | src/tls/cert_ver.cpp | 80 | ||||
-rw-r--r-- | src/tls/finished.cpp | 103 | ||||
-rw-r--r-- | src/tls/rec_read.cpp | 2 | ||||
-rw-r--r-- | src/tls/rec_wri.cpp | 2 | ||||
-rw-r--r-- | src/tls/s_kex.cpp | 77 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 3 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 2 | ||||
-rw-r--r-- | src/tls/tls_client.cpp | 46 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.cpp | 42 | ||||
-rw-r--r-- | src/tls/tls_handshake_state.h | 41 | ||||
-rw-r--r-- | src/tls/tls_messages.h | 39 | ||||
-rw-r--r-- | src/tls/tls_record.h | 6 | ||||
-rw-r--r-- | src/tls/tls_server.cpp | 37 | ||||
-rw-r--r-- | src/tls/tls_session_key.cpp | 37 | ||||
-rw-r--r-- | src/tls/tls_session_key.h | 13 |
15 files changed, 219 insertions, 311 deletions
diff --git a/src/tls/cert_ver.cpp b/src/tls/cert_ver.cpp index 3463a82ee..81d529e88 100644 --- a/src/tls/cert_ver.cpp +++ b/src/tls/cert_ver.cpp @@ -21,56 +21,36 @@ namespace Botan { * Create a new Certificate Verify message */ Certificate_Verify::Certificate_Verify(Record_Writer& writer, - TLS_Handshake_Hash& hash, + TLS_Handshake_State* state, RandomNumberGenerator& rng, - Version_Code version, - const SecureVector<byte>& master_secret, const Private_Key* priv_key) { BOTAN_ASSERT_NONNULL(priv_key); - std::string padding = ""; - Signature_Format format = IEEE_1363; + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(priv_key, true); - if(priv_key->algo_name() == "RSA") - { - if(version == SSL_V3) - padding = "EMSA3(Raw)"; - else - padding = "EMSA3(TLS.Digest.0)"; - } - else if(priv_key->algo_name() == "DSA") - { - if(version == SSL_V3) - padding = "Raw"; - else - padding = "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(priv_key->algo_name() + - " is invalid/unknown for TLS signatures"); + PK_Signer signer(*priv_key, format.first, format.second); - PK_Signer signer(*priv_key, padding, format); - - if(version == SSL_V3) + if(state->version == SSL_V3) { - SecureVector<byte> md5_sha = hash.final_ssl3(master_secret); + SecureVector<byte> md5_sha = state->hash.final_ssl3( + state->keys.master_secret()); if(priv_key->algo_name() == "DSA") signature = signer.sign_message(&md5_sha[16], md5_sha.size()-16, rng); else signature = signer.sign_message(md5_sha, rng); } - else if(version == TLS_V10 || version == TLS_V11) + else if(state->version == TLS_V10 || state->version == TLS_V11) { - signature = signer.sign_message(hash.get_contents(), rng); + signature = signer.sign_message(state->hash.get_contents(), rng); } else throw TLS_Exception(PROTOCOL_VERSION, "Unknown TLS version in certificate verification"); - send(writer, hash); + send(writer, state->hash); } /* @@ -101,45 +81,27 @@ void Certificate_Verify::deserialize(const MemoryRegion<byte>& buf) * Verify a Certificate Verify message */ bool Certificate_Verify::verify(const X509_Certificate& cert, - TLS_Handshake_Hash& hash, - Version_Code version, - const SecureVector<byte>& master_secret) + TLS_Handshake_State* state) { std::auto_ptr<Public_Key> key(cert.subject_public_key()); - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(key->algo_name() == "RSA") - { - if(version == SSL_V3) - padding = "EMSA3(Raw)"; - else - padding = "EMSA3(TLS.Digest.0)"; - } - else if(key->algo_name() == "DSA") - { - if(version == SSL_V3) - padding = "Raw"; - else - padding = "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(key->algo_name() + - " is invalid/unknown for TLS signatures"); + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(key.get(), true); - PK_Verifier verifier(*key, padding, format); + PK_Verifier verifier(*key, format.first, format.second); - if(version == SSL_V3) + if(state->version == SSL_V3) { - SecureVector<byte> md5_sha = hash.final_ssl3(master_secret); + SecureVector<byte> md5_sha = state->hash.final_ssl3( + state->keys.master_secret()); return verifier.verify_message(&md5_sha[16], md5_sha.size()-16, &signature[0], signature.size()); } - else if(version == TLS_V10 || version == TLS_V11) - return verifier.verify_message(hash.get_contents(), signature); + else if(state->version == TLS_V10 || state->version == TLS_V11) + { + return verifier.verify_message(state->hash.get_contents(), signature); + } else throw TLS_Exception(PROTOCOL_VERSION, "Unknown TLS version in certificate verification"); diff --git a/src/tls/finished.cpp b/src/tls/finished.cpp index 70b714bfd..836512f81 100644 --- a/src/tls/finished.cpp +++ b/src/tls/finished.cpp @@ -1,6 +1,6 @@ /* * Finished Message -* (C) 2004-2006 Jack Lloyd +* (C) 2004-2006,2012 Jack Lloyd * * Released under the terms of the Botan license */ @@ -10,58 +10,15 @@ namespace Botan { -/* -* Create a new Finished message -*/ -Finished::Finished(Record_Writer& writer, - TLS_Handshake_Hash& hash, - Version_Code version, - Connection_Side side, - const MemoryRegion<byte>& master_secret) - { - verification_data = compute_verify(master_secret, hash, side, version); - send(writer, hash); - } - -/* -* Serialize a Finished message -*/ -MemoryVector<byte> Finished::serialize() const - { - return verification_data; - } - -/* -* Deserialize a Finished message -*/ -void Finished::deserialize(const MemoryRegion<byte>& buf) - { - verification_data = buf; - } - -/* -* Verify a Finished message -*/ -bool Finished::verify(const MemoryRegion<byte>& secret, - Version_Code version, - const TLS_Handshake_Hash& hash, - Connection_Side side) - { - MemoryVector<byte> computed = compute_verify(secret, hash, side, version); - if(computed == verification_data) - return true; - return false; - } +namespace { /* * Compute the verify_data */ -MemoryVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, - TLS_Handshake_Hash hash, - Connection_Side side, - Version_Code version) +MemoryVector<byte> finished_compute_verify(TLS_Handshake_State* state, + Connection_Side side) { - if(version == SSL_V3) + if(state->version == SSL_V3) { const byte SSL_CLIENT_LABEL[] = { 0x43, 0x4C, 0x4E, 0x54 }; const byte SSL_SERVER_LABEL[] = { 0x53, 0x52, 0x56, 0x52 }; @@ -69,13 +26,13 @@ MemoryVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, MemoryVector<byte> ssl3_finished; if(side == CLIENT) - hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL)); + state->hash.update(SSL_CLIENT_LABEL, sizeof(SSL_CLIENT_LABEL)); else - hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL)); + state->hash.update(SSL_SERVER_LABEL, sizeof(SSL_SERVER_LABEL)); - return hash.final_ssl3(secret); + return state->hash.final_ssl3(state->keys.master_secret()); } - else if(version == TLS_V10 || version == TLS_V11) + else if(state->version == TLS_V10 || state->version == TLS_V11) { const byte TLS_CLIENT_LABEL[] = { 0x63, 0x6C, 0x69, 0x65, 0x6E, 0x74, 0x20, 0x66, 0x69, 0x6E, 0x69, @@ -92,12 +49,50 @@ MemoryVector<byte> Finished::compute_verify(const MemoryRegion<byte>& secret, input += std::make_pair(TLS_CLIENT_LABEL, sizeof(TLS_CLIENT_LABEL)); else input += std::make_pair(TLS_SERVER_LABEL, sizeof(TLS_SERVER_LABEL)); - input += hash.final(); + input += state->hash.final(); - return prf.derive_key(12, secret, input); + return prf.derive_key(12, state->keys.master_secret(), input); } else throw Invalid_Argument("Finished message: Unknown protocol version"); } } + +/* +* Create a new Finished message +*/ +Finished::Finished(Record_Writer& writer, + TLS_Handshake_State* state, + Connection_Side side) + { + verification_data = finished_compute_verify(state, side); + send(writer, state->hash); + } + +/* +* Serialize a Finished message +*/ +MemoryVector<byte> Finished::serialize() const + { + return verification_data; + } + +/* +* Deserialize a Finished message +*/ +void Finished::deserialize(const MemoryRegion<byte>& buf) + { + verification_data = buf; + } + +/* +* Verify a Finished message +*/ +bool Finished::verify(TLS_Handshake_State* state, + Connection_Side side) + { + return (verification_data == finished_compute_verify(state, side)); + } + +} diff --git a/src/tls/rec_read.cpp b/src/tls/rec_read.cpp index f8e6bab26..20dfaae2e 100644 --- a/src/tls/rec_read.cpp +++ b/src/tls/rec_read.cpp @@ -68,7 +68,7 @@ void Record_Reader::set_version(Version_Code version) * Set the keys for reading */ void Record_Reader::activate(const TLS_Cipher_Suite& suite, - const SessionKeys& keys, + const Session_Keys& keys, Connection_Side side) { m_cipher.reset(); diff --git a/src/tls/rec_wri.cpp b/src/tls/rec_wri.cpp index fdcb98cc9..c0a79a631 100644 --- a/src/tls/rec_wri.cpp +++ b/src/tls/rec_wri.cpp @@ -71,7 +71,7 @@ void Record_Writer::set_version(Version_Code version) * Set the keys for writing */ void Record_Writer::activate(const TLS_Cipher_Suite& suite, - const SessionKeys& keys, + const Session_Keys& keys, Connection_Side side) { m_cipher.reset(); diff --git a/src/tls/s_kex.cpp b/src/tls/s_kex.cpp index 150f13474..69531c7c4 100644 --- a/src/tls/s_kex.cpp +++ b/src/tls/s_kex.cpp @@ -9,8 +9,6 @@ #include <botan/internal/tls_reader.h> #include <botan/pubkey.h> #include <botan/dh.h> -#include <botan/rsa.h> -#include <botan/dsa.h> #include <botan/loadstor.h> #include <memory> @@ -20,15 +18,11 @@ namespace Botan { * Create a new Server Key Exchange message */ Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, - TLS_Handshake_Hash& hash, + TLS_Handshake_State* state, RandomNumberGenerator& rng, - const Public_Key* kex_key, - const Private_Key* priv_key, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random) + const Private_Key* private_key) { - const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(kex_key); - const RSA_PublicKey* rsa_pub = dynamic_cast<const RSA_PublicKey*>(kex_key); + const DH_PublicKey* dh_pub = dynamic_cast<const DH_PublicKey*>(state->kex_priv); if(dh_pub) { @@ -36,37 +30,21 @@ Server_Key_Exchange::Server_Key_Exchange(Record_Writer& writer, params.push_back(dh_pub->get_domain().get_g()); params.push_back(BigInt::decode(dh_pub->public_value())); } - else if(rsa_pub) - { - params.push_back(rsa_pub->get_n()); - params.push_back(rsa_pub->get_e()); - } else - throw Invalid_Argument("Bad key for TLS key exchange: not DH or RSA"); - - // FIXME: cut and paste - std::string padding = ""; - Signature_Format format = IEEE_1363; + throw Invalid_Argument("Unknown key type " + state->kex_priv->algo_name() + + " for TLS key exchange"); - if(priv_key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(priv_key->algo_name() == "DSA") - { - padding = "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(priv_key->algo_name() + - " is invalid/unknown for TLS signatures"); + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(private_key, false); - PK_Signer signer(*priv_key, padding, format); + PK_Signer signer(*private_key, format.first, format.second); - signer.update(c_random); - signer.update(s_random); + signer.update(state->client_hello->random()); + signer.update(state->server_hello->random()); signer.update(serialize_params()); signature = signer.signature(rng); - send(writer, hash); + send(writer, state->hash); } /** @@ -135,9 +113,7 @@ void Server_Key_Exchange::deserialize(const MemoryRegion<byte>& buf) */ Public_Key* Server_Key_Exchange::key() const { - if(params.size() == 2) - return new RSA_PublicKey(params[0], params[1]); - else if(params.size() == 3) + if(params.size() == 3) return new DH_PublicKey(DL_Group(params[0], params[1]), params[2]); else throw Internal_Error("Server_Key_Exchange::key: No key set"); @@ -147,33 +123,18 @@ Public_Key* Server_Key_Exchange::key() const * Verify a Server Key Exchange message */ bool Server_Key_Exchange::verify(const X509_Certificate& cert, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random) const + TLS_Handshake_State* state) const { - std::auto_ptr<Public_Key> key(cert.subject_public_key()); - // FIXME: cut and paste - std::string padding = ""; - Signature_Format format = IEEE_1363; - - if(key->algo_name() == "RSA") - padding = "EMSA3(TLS.Digest.0)"; - else if(key->algo_name() == "DSA") - { - padding = "EMSA1(SHA-1)"; - format = DER_SEQUENCE; - } - else - throw Invalid_Argument(key->algo_name() + - " is invalid/unknown for TLS signatures"); + std::pair<std::string, Signature_Format> format = + state->choose_sig_format(key.get(), false); - PK_Verifier verifier(*key, padding, format); + PK_Verifier verifier(*key, format.first, format.second); - MemoryVector<byte> params_got = serialize_params(); - verifier.update(c_random); - verifier.update(s_random); - verifier.update(params_got); + verifier.update(state->client_hello->random()); + verifier.update(state->server_hello->random()); + verifier.update(serialize_params()); return verifier.check_signature(signature); } diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp index e688f354d..a1e9fd8cd 100644 --- a/src/tls/tls_channel.cpp +++ b/src/tls/tls_channel.cpp @@ -8,6 +8,7 @@ #include <botan/tls_channel.h> #include <botan/internal/tls_alerts.h> #include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> #include <botan/internal/assert.h> #include <botan/loadstor.h> @@ -135,7 +136,7 @@ void TLS_Channel::read_handshake(byte rec_type, if(rec_type == HANDSHAKE) { if(!state) - state = new Handshake_State; + state = new TLS_Handshake_State; state->queue.write(&rec_buf[0], rec_buf.size()); } diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h index c86b48f09..2b4e6d161 100644 --- a/src/tls/tls_channel.h +++ b/src/tls/tls_channel.h @@ -90,7 +90,7 @@ class BOTAN_DLL TLS_Channel std::vector<X509_Certificate> peer_certs; - class Handshake_State* state; + class TLS_Handshake_State* state; class Secure_Renegotiation_State { diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp index ca4a56007..ef96c04fb 100644 --- a/src/tls/tls_client.cpp +++ b/src/tls/tls_client.cpp @@ -6,8 +6,8 @@ */ #include <botan/tls_client.h> -#include <botan/internal/tls_session_key.h> #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> @@ -35,7 +35,7 @@ TLS_Client::TLS_Client(std::tr1::function<void (const byte[], size_t)> output_fn { writer.set_version(SSL_V3); - state = new Handshake_State; + state = new TLS_Handshake_State; state->set_expected_next(SERVER_HELLO); state->client_npn_cb = next_protocol; @@ -87,7 +87,7 @@ void TLS_Client::renegotiate() if(state) return; // currently in handshake - state = new Handshake_State; + state = new TLS_Handshake_State; state->set_expected_next(SERVER_HELLO); state->client_hello = new Client_Hello(writer, state->hash, policy, rng, @@ -188,18 +188,16 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, // successful resumption /* - * In this case, we offered the original session and the server - * must resume with it + * In this case, we offered the version used in the original + * session, and the server must resume with the same version. */ if(state->server_hello->version() != state->client_hello->version()) throw TLS_Exception(HANDSHAKE_FAILURE, "Server resumed session but with wrong version"); - state->keys = SessionKeys(state->suite, state->version, - state->resume_master_secret, - state->client_hello->random(), - state->server_hello->random(), - true); + state->keys = Session_Keys(state, + state->resume_master_secret, + true); state->set_expected_next(HANDSHAKE_CCS); } @@ -295,11 +293,11 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, if(state->suite.sig_type() != TLS_ALGO_SIGNER_ANON) { - if(!state->server_kex->verify(peer_certs[0], - state->client_hello->random(), - state->server_hello->random())) + if(!state->server_kex->verify(peer_certs[0], state)) + { throw TLS_Exception(DECRYPT_ERROR, "Bad signature on server key exchange"); + } } } else if(type == CERTIFICATE_REQUEST) @@ -333,10 +331,9 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, state->kex_pub, state->version, state->client_hello->version()); - state->keys = SessionKeys(state->suite, state->version, - state->client_kex->pre_master_secret(), - state->client_hello->random(), - state->server_hello->random()); + state->keys = Session_Keys(state, + state->client_kex->pre_master_secret(), + false); if(state->received_handshake_msg(CERTIFICATE_REQUEST) && !state->client_certs->empty()) @@ -347,10 +344,8 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, state->client_hello->sni_hostname()); state->client_verify = new Certificate_Verify(writer, - state->hash, + state, rng, - state->version, - state->keys.master_secret(), private_key); } @@ -366,9 +361,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, state->next_protocol = new Next_Protocol(writer, state->hash, protocol); } - state->client_finished = new Finished(writer, state->hash, - state->version, CLIENT, - state->keys.master_secret()); + state->client_finished = new Finished(writer, state, CLIENT); } else if(type == HANDSHAKE_CCS) { @@ -382,8 +375,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, state->server_finished = new Finished(contents); - if(!state->server_finished->verify(state->keys.master_secret(), - state->version, state->hash, SERVER)) + if(!state->server_finished->verify(state, SERVER)) throw TLS_Exception(DECRYPT_ERROR, "Finished message didn't verify"); @@ -395,9 +387,7 @@ void TLS_Client::process_handshake_msg(Handshake_Type type, writer.activate(state->suite, state->keys, CLIENT); - state->client_finished = new Finished(writer, state->hash, - state->version, CLIENT, - state->keys.master_secret()); + state->client_finished = new Finished(writer, state, CLIENT); } TLS_Session session_info( diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp index d6f215067..f2f6a2baf 100644 --- a/src/tls/tls_handshake_state.cpp +++ b/src/tls/tls_handshake_state.cpp @@ -6,6 +6,7 @@ */ #include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> namespace Botan { @@ -71,7 +72,7 @@ u32bit bitmask_for_handshake_type(Handshake_Type type) /* * Initialize the SSL/TLS Handshake State */ -Handshake_State::Handshake_State() +TLS_Handshake_State::TLS_Handshake_State() { client_hello = 0; server_hello = 0; @@ -96,7 +97,7 @@ Handshake_State::Handshake_State() hand_received_mask = 0; } -void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) +void TLS_Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) { const u32bit mask = bitmask_for_handshake_type(handshake_msg); @@ -116,22 +117,53 @@ void Handshake_State::confirm_transition_to(Handshake_Type handshake_msg) hand_expecting_mask = 0; } -void Handshake_State::set_expected_next(Handshake_Type handshake_msg) +void TLS_Handshake_State::set_expected_next(Handshake_Type handshake_msg) { hand_expecting_mask |= bitmask_for_handshake_type(handshake_msg); } -bool Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const +bool TLS_Handshake_State::received_handshake_msg(Handshake_Type handshake_msg) const { const u32bit mask = bitmask_for_handshake_type(handshake_msg); return (hand_received_mask & mask); } +std::pair<std::string, Signature_Format> +TLS_Handshake_State::choose_sig_format(const Public_Key* key, bool for_client_auth) + { + const std::string algo_name = key->algo_name(); + + if(algo_name == "RSA") + { + std::string padding = ""; + + if(for_client_auth && this->version == SSL_V3) + padding = "EMSA3(Raw)"; + else + padding = "EMSA3(TLS.Digest.0)"; + + return std::make_pair(padding, IEEE_1363); + } + else if(algo_name == "DSA") + { + std::string padding = ""; + + if(for_client_auth && this->version == SSL_V3) + padding = "Raw"; + else + padding = "EMSA1(SHA-1)"; + + return std::make_pair(padding, DER_SEQUENCE); + } + + throw Invalid_Argument(algo_name + " is invalid/unknown for TLS signatures"); + } + /* * Destroy the SSL/TLS Handshake State */ -Handshake_State::~Handshake_State() +TLS_Handshake_State::~TLS_Handshake_State() { delete client_hello; delete server_hello; diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h index 7ca2dae94..e58a83f3e 100644 --- a/src/tls/tls_handshake_state.h +++ b/src/tls/tls_handshake_state.h @@ -8,9 +8,13 @@ #ifndef BOTAN_TLS_HANDSHAKE_STATE_H__ #define BOTAN_TLS_HANDSHAKE_STATE_H__ -#include <botan/internal/tls_messages.h> +#include <botan/internal/tls_handshake_hash.h> #include <botan/internal/tls_session_key.h> #include <botan/secqueue.h> +#include <botan/pk_keys.h> +#include <botan/pubkey.h> + +#include <utility> #if defined(BOTAN_USE_STD_TR1) @@ -31,40 +35,43 @@ namespace Botan { /** * SSL/TLS Handshake State */ -class Handshake_State +class TLS_Handshake_State { public: - Handshake_State(); - ~Handshake_State(); + TLS_Handshake_State(); + ~TLS_Handshake_State(); bool received_handshake_msg(Handshake_Type handshake_msg) const; void confirm_transition_to(Handshake_Type handshake_msg); void set_expected_next(Handshake_Type handshake_msg); + std::pair<std::string, Signature_Format> + choose_sig_format(const Public_Key* key, bool for_client_auth); + Version_Code version; - Client_Hello* client_hello; - Server_Hello* server_hello; - Certificate* server_certs; - Server_Key_Exchange* server_kex; - Certificate_Req* cert_req; - Server_Hello_Done* server_hello_done; + class Client_Hello* client_hello; + class Server_Hello* server_hello; + class Certificate* server_certs; + class Server_Key_Exchange* server_kex; + class Certificate_Req* cert_req; + class Server_Hello_Done* server_hello_done; - Certificate* client_certs; - Client_Key_Exchange* client_kex; - Certificate_Verify* client_verify; + class Certificate* client_certs; + class Client_Key_Exchange* client_kex; + class Certificate_Verify* client_verify; - Next_Protocol* next_protocol; + class Next_Protocol* next_protocol; - Finished* client_finished; - Finished* server_finished; + class Finished* client_finished; + class Finished* server_finished; Public_Key* kex_pub; Private_Key* kex_priv; TLS_Cipher_Suite suite; - SessionKeys keys; + Session_Keys keys; TLS_Handshake_Hash hash; SecureQueue queue; diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h index ee05031c0..0b43545dc 100644 --- a/src/tls/tls_messages.h +++ b/src/tls/tls_messages.h @@ -8,7 +8,7 @@ #ifndef BOTAN_TLS_MESSAGES_H__ #define BOTAN_TLS_MESSAGES_H__ -#include <botan/internal/tls_handshake_hash.h> +#include <botan/internal/tls_handshake_state.h> #include <botan/tls_session.h> #include <botan/tls_policy.h> #include <botan/tls_magic.h> @@ -290,20 +290,14 @@ class Certificate_Verify : public Handshake_Message /** * Check the signature on a certificate verify message * @param cert the purported certificate - * @param hash the running handshake message hash - * @param version the version number we negotiated - * @param master_secret the session key (only used if version is SSL_V3) + * @param state the handshake state */ bool verify(const X509_Certificate& cert, - TLS_Handshake_Hash& hash, - Version_Code version, - const SecureVector<byte>& master_secret); + TLS_Handshake_State* state); Certificate_Verify(Record_Writer& writer, - TLS_Handshake_Hash& hash, + TLS_Handshake_State* state, RandomNumberGenerator& rng, - Version_Code version, - const SecureVector<byte>& master_secret, const Private_Key* key); Certificate_Verify(const MemoryRegion<byte>& buf) { deserialize(buf); } @@ -325,27 +319,18 @@ class Finished : public Handshake_Message MemoryVector<byte> verify_data() const { return verification_data; } - bool verify(const MemoryRegion<byte>& buf, - Version_Code version, - const TLS_Handshake_Hash& hash, + bool verify(TLS_Handshake_State* state, Connection_Side side); Finished(Record_Writer& writer, - TLS_Handshake_Hash& hash, - Version_Code version, - Connection_Side side, - const MemoryRegion<byte>& master_secret); + TLS_Handshake_State* state, + Connection_Side side); Finished(const MemoryRegion<byte>& buf) { deserialize(buf); } private: MemoryVector<byte> serialize() const; void deserialize(const MemoryRegion<byte>&); - MemoryVector<byte> compute_verify(const MemoryRegion<byte>& master_secret, - TLS_Handshake_Hash hash, - Connection_Side side, - Version_Code version); - Connection_Side side; MemoryVector<byte> verification_data; }; @@ -375,16 +360,12 @@ class Server_Key_Exchange : public Handshake_Message Public_Key* key() const; bool verify(const X509_Certificate& cert, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random) const; + TLS_Handshake_State* state) const; Server_Key_Exchange(Record_Writer& writer, - TLS_Handshake_Hash& hash, + TLS_Handshake_State* state, RandomNumberGenerator& rng, - const Public_Key* kex_key, - const Private_Key* priv_key, - const MemoryRegion<byte>& c_random, - const MemoryRegion<byte>& s_random); + const Private_Key* priv_key); Server_Key_Exchange(const MemoryRegion<byte>& buf) { deserialize(buf); } private: diff --git a/src/tls/tls_record.h b/src/tls/tls_record.h index c7d2d0018..a9bcb8f26 100644 --- a/src/tls/tls_record.h +++ b/src/tls/tls_record.h @@ -30,7 +30,7 @@ namespace Botan { -class SessionKeys; +class Session_Keys; /** * TLS Record Writer @@ -44,7 +44,7 @@ class BOTAN_DLL Record_Writer void alert(Alert_Level level, Alert_Type type); void activate(const TLS_Cipher_Suite& suite, - const SessionKeys& keys, + const Session_Keys& keys, Connection_Side side); void set_version(Version_Code version); @@ -98,7 +98,7 @@ class BOTAN_DLL Record_Reader MemoryVector<byte>& msg); void activate(const TLS_Cipher_Suite& suite, - const SessionKeys& keys, + const Session_Keys& keys, Connection_Side side); void set_version(Version_Code version); diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp index ccba16629..e3e2fe208 100644 --- a/src/tls/tls_server.cpp +++ b/src/tls/tls_server.cpp @@ -6,8 +6,8 @@ */ #include <botan/tls_server.h> -#include <botan/internal/tls_session_key.h> #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/dh.h> @@ -104,7 +104,7 @@ void TLS_Server::renegotiate() if(state) return; // currently in handshake - state = new Handshake_State; + state = new TLS_Handshake_State; state->set_expected_next(CLIENT_HELLO); Hello_Request hello_req(writer); } @@ -129,7 +129,7 @@ void TLS_Server::read_handshake(byte rec_type, { if(rec_type == HANDSHAKE && !state) { - state = new Handshake_State; + state = new TLS_Handshake_State; state->set_expected_next(CLIENT_HELLO); } @@ -207,19 +207,13 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->suite = TLS_Cipher_Suite(state->server_hello->ciphersuite()); - state->keys = SessionKeys(state->suite, state->version, - session_info.master_secret(), - state->client_hello->random(), - state->server_hello->random(), - true); + state->keys = Session_Keys(state, session_info.master_secret(), true); writer.send(CHANGE_CIPHER_SPEC, 1); writer.activate(state->suite, state->keys, SERVER); - state->server_finished = new Finished(writer, state->hash, - state->version, SERVER, - state->keys.master_secret()); + state->server_finished = new Finished(writer, state, SERVER); if(!handshake_fn(session_info)) session_manager.remove_entry(session_info.session_id()); @@ -275,10 +269,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, throw Internal_Error("TLS_Server: Unknown ciphersuite kex type"); state->server_kex = - new Server_Key_Exchange(writer, state->hash, rng, - state->kex_priv, private_key, - state->client_hello->random(), - state->server_hello->random()); + new Server_Key_Exchange(writer, state, rng, private_key); } else state->kex_priv = PKCS8::copy_key(*private_key, rng); @@ -330,9 +321,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->client_kex->pre_master_secret(rng, state->kex_priv, state->client_hello->version()); - state->keys = SessionKeys(state->suite, state->version, pre_master, - state->client_hello->random(), - state->server_hello->random()); + state->keys = Session_Keys(state, pre_master, false); } else if(type == CERTIFICATE_VERIFY) { @@ -342,10 +331,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->client_certs->cert_chain(); const bool sig_valid = - state->client_verify->verify(client_certs[0], - state->hash, - state->server_hello->version(), - state->keys.master_secret()); + state->client_verify->verify(client_certs[0], state); state->hash.update(type, contents); @@ -384,8 +370,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, state->client_finished = new Finished(contents); - if(!state->client_finished->verify(state->keys.master_secret(), - state->version, state->hash, CLIENT)) + if(!state->client_finished->verify(state, CLIENT)) throw TLS_Exception(DECRYPT_ERROR, "Finished message didn't verify"); @@ -398,9 +383,7 @@ void TLS_Server::process_handshake_msg(Handshake_Type type, writer.activate(state->suite, state->keys, SERVER); - state->server_finished = new Finished(writer, state->hash, - state->version, SERVER, - state->keys.master_secret()); + state->server_finished = new Finished(writer, state, SERVER); if(state->client_certs && state->client_verify) peer_certs = state->client_certs->cert_chain(); diff --git a/src/tls/tls_session_key.cpp b/src/tls/tls_session_key.cpp index f0ddc4493..66a02542b 100644 --- a/src/tls/tls_session_key.cpp +++ b/src/tls/tls_session_key.cpp @@ -6,6 +6,8 @@ */ #include <botan/internal/tls_session_key.h> +#include <botan/internal/tls_handshake_state.h> +#include <botan/internal/tls_messages.h> #include <botan/lookup.h> #include <memory> @@ -20,29 +22,26 @@ std::string lookup_prf_name(Version_Code version) else if(version == TLS_V10 || version == TLS_V11) return "TLS-PRF"; else - throw Invalid_Argument("SessionKeys: Unknown version code"); + throw Invalid_Argument("Session_Keys: Unknown version code"); } } /** -* SessionKeys Constructor +* Session_Keys Constructor */ -SessionKeys::SessionKeys(const TLS_Cipher_Suite& suite, - Version_Code version, - const MemoryRegion<byte>& pre_master_secret, - const MemoryRegion<byte>& client_random, - const MemoryRegion<byte>& server_random, - bool resuming) +Session_Keys::Session_Keys(TLS_Handshake_State* state, + const MemoryRegion<byte>& pre_master_secret, + bool resuming) { - const std::string prf_name = lookup_prf_name(version); + const std::string prf_name = lookup_prf_name(state->version); - const size_t mac_keylen = output_length_of(suite.mac_algo()); - const size_t cipher_keylen = suite.cipher_keylen(); + const size_t mac_keylen = output_length_of(state->suite.mac_algo()); + const size_t cipher_keylen = state->suite.cipher_keylen(); size_t cipher_ivlen = 0; - if(have_block_cipher(suite.cipher_algo())) - cipher_ivlen = block_size_of(suite.cipher_algo()); + if(have_block_cipher(state->suite.cipher_algo())) + cipher_ivlen = block_size_of(state->suite.cipher_algo()); const size_t prf_gen = 2 * (mac_keylen + cipher_keylen + cipher_ivlen); @@ -62,20 +61,20 @@ SessionKeys::SessionKeys(const TLS_Cipher_Suite& suite, { SecureVector<byte> salt; - if(version != SSL_V3) + if(state->version != SSL_V3) salt += std::make_pair(MASTER_SECRET_MAGIC, sizeof(MASTER_SECRET_MAGIC)); - salt += client_random; - salt += server_random; + salt += state->client_hello->random(); + salt += state->server_hello->random(); master_sec = prf->derive_key(48, pre_master_secret, salt); } SecureVector<byte> salt; - if(version != SSL_V3) + if(state->version != SSL_V3) salt += std::make_pair(KEY_GEN_MAGIC, sizeof(KEY_GEN_MAGIC)); - salt += server_random; - salt += client_random; + salt += state->server_hello->random(); + salt += state->client_hello->random(); SymmetricKey keyblock = prf->derive_key(prf_gen, master_sec, salt); diff --git a/src/tls/tls_session_key.h b/src/tls/tls_session_key.h index a698dfcfc..8ba3d2b72 100644 --- a/src/tls/tls_session_key.h +++ b/src/tls/tls_session_key.h @@ -17,7 +17,7 @@ namespace Botan { /** * TLS Session Keys */ -class SessionKeys +class Session_Keys { public: SymmetricKey client_cipher_key() const { return c_cipher; } @@ -31,14 +31,11 @@ class SessionKeys const SecureVector<byte>& master_secret() const { return master_sec; } - SessionKeys() {} + Session_Keys() {} - SessionKeys(const TLS_Cipher_Suite& suite, - Version_Code version, - const MemoryRegion<byte>& pre_master, - const MemoryRegion<byte>& client_random, - const MemoryRegion<byte>& server_random, - bool resuming = false); + Session_Keys(class TLS_Handshake_State* state, + const MemoryRegion<byte>& pre_master, + bool resuming); private: SecureVector<byte> master_sec; |