diff options
Diffstat (limited to 'src/tls/tls_session.cpp')
-rw-r--r-- | src/tls/tls_session.cpp | 88 |
1 files changed, 48 insertions, 40 deletions
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp index ddf0661c6..3d890210f 100644 --- a/src/tls/tls_session.cpp +++ b/src/tls/tls_session.cpp @@ -12,6 +12,7 @@ #include <botan/pem.h> #include <botan/time.h> #include <botan/lookup.h> +#include <botan/loadstor.h> #include <memory> namespace Botan { @@ -27,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), @@ -44,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) { BER_Decoder decoder(ber, ber_len); @@ -60,10 +70,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) @@ -90,13 +101,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; @@ -106,10 +110,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)) @@ -128,25 +133,23 @@ 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, - const MemoryRegion<byte>& key_name, RandomNumberGenerator& rng) { - if(key_name.size() != 16) - throw Encoding_Error("Bad length " + to_string(key_name.size()) + - " for key_name in TLS_Session::encrypt"); - - if(master_key.length() == 0) - throw Decoding_Error("Session encryption key not set"); - std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-256)")); SymmetricKey aes_key = kdf->derive_key(32, master_key.bits_of(), - "session-ticket.cipher-key"); + "tls.session.cipher-key"); SymmetricKey hmac_key = kdf->derive_key(32, master_key.bits_of(), - "session-ticket.hmac-key"); + "tls.session.hmac-key"); InitializationVector aes_iv(rng, 16); @@ -157,8 +160,8 @@ Session::encrypt(const SymmetricKey& master_key, pipe.process_msg(this->DER_encode()); MemoryVector<byte> ctext = pipe.read_all(0); - MemoryVector<byte> out; - out += key_name; + MemoryVector<byte> out(8); + store_be(ENCRYPTED_SESSION_MAGIC, &out[0]); out += aes_iv.bits_of(); out += ctext; @@ -169,25 +172,24 @@ Session::encrypt(const SymmetricKey& master_key, } Session Session::decrypt(const MemoryRegion<byte>& buf, - const SymmetricKey& master_key, - const MemoryRegion<byte>& key_name) + const SymmetricKey& master_key) { try { - if(buf.size() < (16 + 16 + 32 + 1)) - throw Decoding_Error("Encrypted TLS_Session too short to be real"); - - if(master_key.length() == 0) - throw Decoding_Error("Session master_key not set"); - - if(key_name.size() != 16) - throw Decoding_Error("Bad length " + to_string(key_name.size()) + - " for key_name"); + /* + 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(), - "session-ticket.hmac-key"); + "tls.session.mac-key"); std::auto_ptr<MessageAuthenticationCode> mac(get_mac("HMAC(SHA-256)")); mac->set_key(hmac_key); @@ -196,22 +198,28 @@ Session Session::decrypt(const MemoryRegion<byte>& buf, 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"); + 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(), - "session-ticket.cipher-key"); + "tls.session.cipher-key"); - InitializationVector aes_iv(&buf[16], 16); + InitializationVector aes_iv(&buf[8], 16); Pipe pipe(get_cipher("AES-256/CBC", aes_key, aes_iv, DECRYPTION)); - pipe.process_msg(&buf[16], buf.size() - (16 + 32)); - MemoryVector<byte> ber = pipe.read_all(); + pipe.process_msg(&buf[8+16], buf.size() - (32 + 8 + 16)); + SecureVector<byte> ber = pipe.read_all(); return Session(&ber[0], ber.size()); } - catch(...) + catch(std::exception& e) { - throw Decoding_Error("Failed to decrypt encrypted session"); + throw Decoding_Error("Failed to decrypt encrypted session -" + + std::string(e.what())); } } |