aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls/tls_session.cpp
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-03-22 18:41:39 +0000
committerlloyd <[email protected]>2012-03-22 18:41:39 +0000
commitc670e02f82087945f2c96b7cf69177ba374b27fc (patch)
treeb3cec42ca7917db3183b9d997fbacc5c793d1721 /src/tls/tls_session.cpp
parent4b3a653d7522365fcff3cda0afa40aac269e5767 (diff)
parent4004e38a00f6bf5743af68d47e44f7adf3872d2b (diff)
propagate from branch 'net.randombit.botan.tls-state-machine' (head 6bcbae3d22e4d873a8e941d0325ad666482ac4da)
to branch 'net.randombit.botan.tls-session-ticket' (head 9048722b5d18b39cf21f8542942dab94a9bd4e6b)
Diffstat (limited to 'src/tls/tls_session.cpp')
-rw-r--r--src/tls/tls_session.cpp118
1 files changed, 108 insertions, 10 deletions
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp
index 7a32c33d8..a41112bf4 100644
--- a/src/tls/tls_session.cpp
+++ b/src/tls/tls_session.cpp
@@ -1,6 +1,6 @@
/*
* TLS Session State
-* (C) 2011 Jack Lloyd
+* (C) 2011-2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/
@@ -11,6 +11,9 @@
#include <botan/asn1_str.h>
#include <botan/pem.h>
#include <botan/time.h>
+#include <botan/lookup.h>
+#include <botan/loadstor.h>
+#include <memory>
namespace Botan {
@@ -25,10 +28,12 @@ Session::Session(const MemoryRegion<byte>& session_identifier,
bool secure_renegotiation_supported,
size_t fragment_size,
const std::vector<X509_Certificate>& certs,
+ const MemoryRegion<byte>& ticket,
const std::string& sni_hostname,
const std::string& srp_identifier) :
m_start_time(system_time()),
m_identifier(session_identifier),
+ m_session_ticket(ticket),
m_master_secret(master_secret),
m_version(version),
m_ciphersuite(ciphersuite),
@@ -42,6 +47,13 @@ Session::Session(const MemoryRegion<byte>& session_identifier,
{
}
+Session::Session(const std::string& pem)
+ {
+ SecureVector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION");
+
+ *this = Session(&der[0], der.size());
+ }
+
Session::Session(const byte ber[], size_t ber_len)
{
byte side_code = 0;
@@ -56,10 +68,11 @@ Session::Session(const byte ber[], size_t ber_len)
.start_cons(SEQUENCE)
.decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
"Unknown version in session structure")
- .decode(m_identifier, OCTET_STRING)
.decode_integer_type(m_start_time)
.decode_integer_type(major_version)
.decode_integer_type(minor_version)
+ .decode(m_identifier, OCTET_STRING)
+ .decode(m_session_ticket, OCTET_STRING)
.decode_integer_type(m_ciphersuite)
.decode_integer_type(m_compression_method)
.decode_integer_type(side_code)
@@ -86,13 +99,6 @@ Session::Session(const byte ber[], size_t ber_len)
}
}
-Session::Session(const std::string& pem)
- {
- SecureVector<byte> der = PEM_Code::decode_check_label(pem, "SSL SESSION");
-
- *this = Session(&der[0], der.size());
- }
-
SecureVector<byte> Session::DER_encode() const
{
MemoryVector<byte> peer_cert_bits;
@@ -102,10 +108,11 @@ SecureVector<byte> Session::DER_encode() const
return DER_Encoder()
.start_cons(SEQUENCE)
.encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
- .encode(m_identifier, OCTET_STRING)
.encode(static_cast<size_t>(m_start_time))
.encode(static_cast<size_t>(m_version.major_version()))
.encode(static_cast<size_t>(m_version.minor_version()))
+ .encode(m_identifier, OCTET_STRING)
+ .encode(m_session_ticket, OCTET_STRING)
.encode(static_cast<size_t>(m_ciphersuite))
.encode(static_cast<size_t>(m_compression_method))
.encode(static_cast<size_t>(m_connection_side))
@@ -124,6 +131,97 @@ std::string Session::PEM_encode() const
return PEM_Code::encode(this->DER_encode(), "SSL SESSION");
}
+namespace {
+
+const u64bit ENCRYPTED_SESSION_MAGIC = 0xACE4480800000000;
+
+}
+
+MemoryVector<byte>
+Session::encrypt(const SymmetricKey& master_key,
+ RandomNumberGenerator& rng)
+ {
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-256)"));
+
+ SymmetricKey aes_key = kdf->derive_key(32, master_key.bits_of(),
+ "tls.session.cipher-key");
+
+ SymmetricKey hmac_key = kdf->derive_key(32, master_key.bits_of(),
+ "tls.session.mac-key");
+
+ InitializationVector aes_iv(rng, 16);
+
+ std::auto_ptr<MessageAuthenticationCode> mac(get_mac("HMAC(SHA-256)"));
+ mac->set_key(hmac_key);
+
+ Pipe pipe(get_cipher("AES-256/CBC", aes_key, aes_iv, ENCRYPTION));
+ pipe.process_msg(this->DER_encode());
+ MemoryVector<byte> ctext = pipe.read_all(0);
+
+ MemoryVector<byte> out(8);
+ store_be(ENCRYPTED_SESSION_MAGIC, &out[0]);
+ out += aes_iv.bits_of();
+ out += ctext;
+
+ mac->update(out);
+
+ out += mac->final();
+ return out;
+ }
+
+Session Session::decrypt(const MemoryRegion<byte>& buf,
+ const SymmetricKey& master_key)
+ {
+ try
+ {
+ /*
+ 8 bytes header
+ 16 bytes IV
+ 32 bytes MAC
+ 16 bytes per AES block * 4 blocks (absolute min amount due to
+ 48 bytes master secret)
+ */
+ if(buf.size() < (8 + 16 + 32 + 4*16))
+ throw Decoding_Error("Encrypted TLS session too short to be valid");
+
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-256)"));
+
+ SymmetricKey hmac_key = kdf->derive_key(32, master_key.bits_of(),
+ "tls.session.mac-key");
+
+ std::auto_ptr<MessageAuthenticationCode> mac(get_mac("HMAC(SHA-256)"));
+ mac->set_key(hmac_key);
+
+ mac->update(&buf[0], buf.size() - 32);
+ MemoryVector<byte> computed_mac = mac->final();
+
+ if(!same_mem(&buf[buf.size() - 32], &computed_mac[0], computed_mac.size()))
+ throw Decoding_Error("MAC verification failed for encrypted session");
+
+ const u64bit header = load_be<u64bit>(buf, 0);
+
+ if(header != ENCRYPTED_SESSION_MAGIC)
+ throw Decoding_Error("Unknown header value in encrypted session");
+
+ SymmetricKey aes_key = kdf->derive_key(32, master_key.bits_of(),
+ "tls.session.cipher-key");
+
+ InitializationVector aes_iv(&buf[8], 16);
+
+ Pipe pipe(get_cipher("AES-256/CBC", aes_key, aes_iv, DECRYPTION));
+ pipe.process_msg(&buf[8+16], buf.size() - (32 + 8 + 16));
+ SecureVector<byte> ber = pipe.read_all();
+
+ return Session(&ber[0], ber.size());
+ }
+ catch(std::exception& e)
+ {
+ throw Decoding_Error("Failed to decrypt encrypted session -" +
+ std::string(e.what()));
+ }
+ }
+
}
}
+