aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/cert_ver.cpp80
-rw-r--r--src/tls/finished.cpp103
-rw-r--r--src/tls/rec_read.cpp2
-rw-r--r--src/tls/rec_wri.cpp2
-rw-r--r--src/tls/s_kex.cpp77
-rw-r--r--src/tls/tls_channel.cpp3
-rw-r--r--src/tls/tls_channel.h2
-rw-r--r--src/tls/tls_client.cpp46
-rw-r--r--src/tls/tls_handshake_state.cpp42
-rw-r--r--src/tls/tls_handshake_state.h41
-rw-r--r--src/tls/tls_messages.h39
-rw-r--r--src/tls/tls_record.h6
-rw-r--r--src/tls/tls_server.cpp37
-rw-r--r--src/tls/tls_session_key.cpp37
-rw-r--r--src/tls/tls_session_key.h13
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;