diff options
author | lloyd <[email protected]> | 2012-03-22 18:41:39 +0000 |
---|---|---|
committer | lloyd <[email protected]> | 2012-03-22 18:41:39 +0000 |
commit | c670e02f82087945f2c96b7cf69177ba374b27fc (patch) | |
tree | b3cec42ca7917db3183b9d997fbacc5c793d1721 /src/tls/tls_session.cpp | |
parent | 4b3a653d7522365fcff3cda0afa40aac269e5767 (diff) | |
parent | 4004e38a00f6bf5743af68d47e44f7adf3872d2b (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.cpp | 118 |
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())); + } + } + } } + |