1 /*
2 * TLS Session State
3 * (C) 2011-2012,2015,2019 Jack Lloyd
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/tls_session.h>
9 #include <botan/loadstor.h>
10 #include <botan/der_enc.h>
11 #include <botan/ber_dec.h>
12 #include <botan/asn1_obj.h>
13 #include <botan/pem.h>
14 #include <botan/aead.h>
15 #include <botan/mac.h>
16 #include <botan/rng.h>
17 
18 namespace Botan {
19 
20 namespace TLS {
21 
Session(const std::vector<uint8_t> & session_identifier,const secure_vector<uint8_t> & master_secret,Protocol_Version version,uint16_t ciphersuite,Connection_Side side,bool extended_master_secret,bool encrypt_then_mac,const std::vector<X509_Certificate> & certs,const std::vector<uint8_t> & ticket,const Server_Information & server_info,const std::string & srp_identifier,uint16_t srtp_profile)22 Session::Session(const std::vector<uint8_t>& session_identifier,
23                  const secure_vector<uint8_t>& master_secret,
24                  Protocol_Version version,
25                  uint16_t ciphersuite,
26                  Connection_Side side,
27                  bool extended_master_secret,
28                  bool encrypt_then_mac,
29                  const std::vector<X509_Certificate>& certs,
30                  const std::vector<uint8_t>& ticket,
31                  const Server_Information& server_info,
32                  const std::string& srp_identifier,
33                  uint16_t srtp_profile) :
34    m_start_time(std::chrono::system_clock::now()),
35    m_identifier(session_identifier),
36    m_session_ticket(ticket),
37    m_master_secret(master_secret),
38    m_version(version),
39    m_ciphersuite(ciphersuite),
40    m_connection_side(side),
41    m_srtp_profile(srtp_profile),
42    m_extended_master_secret(extended_master_secret),
43    m_encrypt_then_mac(encrypt_then_mac),
44    m_peer_certs(certs),
45    m_server_info(server_info),
46    m_srp_identifier(srp_identifier)
47    {
48    }
49 
Session(const std::string & pem)50 Session::Session(const std::string& pem)
51    {
52    secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
53 
54    *this = Session(der.data(), der.size());
55    }
56 
Session(const uint8_t ber[],size_t ber_len)57 Session::Session(const uint8_t ber[], size_t ber_len)
58    {
59    uint8_t side_code = 0;
60 
61    ASN1_String server_hostname;
62    ASN1_String server_service;
63    size_t server_port;
64 
65    ASN1_String srp_identifier_str;
66 
67    uint8_t major_version = 0, minor_version = 0;
68    std::vector<uint8_t> peer_cert_bits;
69 
70    size_t start_time = 0;
71    size_t srtp_profile = 0;
72    size_t fragment_size = 0;
73    size_t compression_method = 0;
74 
75    BER_Decoder(ber, ber_len)
76       .start_cons(SEQUENCE)
77         .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
78                           "Unknown version in serialized TLS session")
79         .decode_integer_type(start_time)
80         .decode_integer_type(major_version)
81         .decode_integer_type(minor_version)
82         .decode(m_identifier, OCTET_STRING)
83         .decode(m_session_ticket, OCTET_STRING)
84         .decode_integer_type(m_ciphersuite)
85         .decode_integer_type(compression_method)
86         .decode_integer_type(side_code)
87         .decode_integer_type(fragment_size)
88         .decode(m_extended_master_secret)
89         .decode(m_encrypt_then_mac)
90         .decode(m_master_secret, OCTET_STRING)
91         .decode(peer_cert_bits, OCTET_STRING)
92         .decode(server_hostname)
93         .decode(server_service)
94         .decode(server_port)
95         .decode(srp_identifier_str)
96         .decode(srtp_profile)
97       .end_cons()
98       .verify_end();
99 
100    /*
101    * Compression is not supported and must be zero
102    */
103    if(compression_method != 0)
104       {
105       throw Decoding_Error("Serialized TLS session contains non-null compression method");
106       }
107 
108    /*
109    Fragment size is not supported anymore, but the field is still
110    set in the session object.
111    */
112    if(fragment_size != 0)
113       {
114       throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
115                            " no longer supported");
116       }
117 
118    m_version = Protocol_Version(major_version, minor_version);
119    m_start_time = std::chrono::system_clock::from_time_t(start_time);
120    m_connection_side = static_cast<Connection_Side>(side_code);
121    m_srtp_profile = static_cast<uint16_t>(srtp_profile);
122 
123    m_server_info = Server_Information(server_hostname.value(),
124                                       server_service.value(),
125                                       static_cast<uint16_t>(server_port));
126 
127    m_srp_identifier = srp_identifier_str.value();
128 
129    if(!peer_cert_bits.empty())
130       {
131       DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
132 
133       while(!certs.end_of_data())
134          m_peer_certs.push_back(X509_Certificate(certs));
135       }
136    }
137 
DER_encode() const138 secure_vector<uint8_t> Session::DER_encode() const
139    {
140    std::vector<uint8_t> peer_cert_bits;
141    for(size_t i = 0; i != m_peer_certs.size(); ++i)
142       peer_cert_bits += m_peer_certs[i].BER_encode();
143 
144    return DER_Encoder()
145       .start_cons(SEQUENCE)
146          .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
147          .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
148          .encode(static_cast<size_t>(m_version.major_version()))
149          .encode(static_cast<size_t>(m_version.minor_version()))
150          .encode(m_identifier, OCTET_STRING)
151          .encode(m_session_ticket, OCTET_STRING)
152          .encode(static_cast<size_t>(m_ciphersuite))
153          .encode(static_cast<size_t>(/*old compression method*/0))
154          .encode(static_cast<size_t>(m_connection_side))
155          .encode(static_cast<size_t>(/*old fragment size*/0))
156          .encode(m_extended_master_secret)
157          .encode(m_encrypt_then_mac)
158          .encode(m_master_secret, OCTET_STRING)
159          .encode(peer_cert_bits, OCTET_STRING)
160          .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
161          .encode(ASN1_String(m_server_info.service(), UTF8_STRING))
162          .encode(static_cast<size_t>(m_server_info.port()))
163          .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
164          .encode(static_cast<size_t>(m_srtp_profile))
165       .end_cons()
166    .get_contents();
167    }
168 
PEM_encode() const169 std::string Session::PEM_encode() const
170    {
171    return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
172    }
173 
session_age() const174 std::chrono::seconds Session::session_age() const
175    {
176    return std::chrono::duration_cast<std::chrono::seconds>(
177       std::chrono::system_clock::now() - m_start_time);
178    }
179 
180 namespace {
181 
182 // The output length of the HMAC must be a valid keylength for the AEAD
183 const char* TLS_SESSION_CRYPT_HMAC = "HMAC(SHA-512-256)";
184 // SIV would be better, but we can't assume it is available
185 const char* TLS_SESSION_CRYPT_AEAD = "AES-256/GCM";
186 const char* TLS_SESSION_CRYPT_KEY_NAME = "BOTAN TLS SESSION KEY NAME";
187 const uint64_t TLS_SESSION_CRYPT_MAGIC = 0x068B5A9D396C0000;
188 const size_t TLS_SESSION_CRYPT_MAGIC_LEN = 8;
189 const size_t TLS_SESSION_CRYPT_KEY_NAME_LEN = 4;
190 const size_t TLS_SESSION_CRYPT_AEAD_NONCE_LEN = 12;
191 const size_t TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN = 16;
192 const size_t TLS_SESSION_CRYPT_AEAD_TAG_SIZE = 16;
193 
194 const size_t TLS_SESSION_CRYPT_HDR_LEN =
195    TLS_SESSION_CRYPT_MAGIC_LEN +
196    TLS_SESSION_CRYPT_KEY_NAME_LEN +
197    TLS_SESSION_CRYPT_AEAD_NONCE_LEN +
198    TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
199 
200 const size_t TLS_SESSION_CRYPT_OVERHEAD =
201    TLS_SESSION_CRYPT_HDR_LEN + TLS_SESSION_CRYPT_AEAD_TAG_SIZE;
202 
203 }
204 
205 std::vector<uint8_t>
encrypt(const SymmetricKey & key,RandomNumberGenerator & rng) const206 Session::encrypt(const SymmetricKey& key, RandomNumberGenerator& rng) const
207    {
208    auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
209    hmac->set_key(key);
210 
211    // First derive the "key name"
212    std::vector<uint8_t> key_name(hmac->output_length());
213    hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
214    hmac->final(key_name.data());
215    key_name.resize(TLS_SESSION_CRYPT_KEY_NAME_LEN);
216 
217    std::vector<uint8_t> aead_nonce;
218    std::vector<uint8_t> key_seed;
219 
220    rng.random_vec(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
221    rng.random_vec(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
222 
223    hmac->update(key_seed);
224    const secure_vector<uint8_t> aead_key = hmac->final();
225 
226    secure_vector<uint8_t> bits = this->DER_encode();
227 
228    // create the header
229    std::vector<uint8_t> buf;
230    buf.reserve(TLS_SESSION_CRYPT_OVERHEAD + bits.size());
231    buf.resize(TLS_SESSION_CRYPT_MAGIC_LEN);
232    store_be(TLS_SESSION_CRYPT_MAGIC, &buf[0]);
233    buf += key_name;
234    buf += key_seed;
235    buf += aead_nonce;
236 
237    std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, ENCRYPTION);
238    BOTAN_ASSERT_NOMSG(aead->valid_nonce_length(TLS_SESSION_CRYPT_AEAD_NONCE_LEN));
239    BOTAN_ASSERT_NOMSG(aead->tag_size() == TLS_SESSION_CRYPT_AEAD_TAG_SIZE);
240    aead->set_key(aead_key);
241    aead->set_associated_data_vec(buf);
242    aead->start(aead_nonce);
243    aead->finish(bits, 0);
244 
245    // append the ciphertext
246    buf += bits;
247    return buf;
248    }
249 
decrypt(const uint8_t in[],size_t in_len,const SymmetricKey & key)250 Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
251    {
252    try
253       {
254       const size_t min_session_size = 48 + 4; // serious under-estimate
255       if(in_len < TLS_SESSION_CRYPT_OVERHEAD + min_session_size)
256          throw Decoding_Error("Encrypted session too short to be valid");
257 
258       const uint8_t* magic = &in[0];
259       const uint8_t* key_name = magic + TLS_SESSION_CRYPT_MAGIC_LEN;
260       const uint8_t* key_seed = key_name + TLS_SESSION_CRYPT_KEY_NAME_LEN;
261       const uint8_t* aead_nonce = key_seed + TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN;
262       const uint8_t* ctext = aead_nonce + TLS_SESSION_CRYPT_AEAD_NONCE_LEN;
263       const size_t ctext_len = in_len - TLS_SESSION_CRYPT_HDR_LEN; // includes the tag
264 
265       if(load_be<uint64_t>(magic, 0) != TLS_SESSION_CRYPT_MAGIC)
266          throw Decoding_Error("Missing expected magic numbers");
267 
268       auto hmac = MessageAuthenticationCode::create_or_throw(TLS_SESSION_CRYPT_HMAC);
269       hmac->set_key(key);
270 
271       // First derive and check the "key name"
272       std::vector<uint8_t> cmp_key_name(hmac->output_length());
273       hmac->update(TLS_SESSION_CRYPT_KEY_NAME);
274       hmac->final(cmp_key_name.data());
275 
276       if(same_mem(cmp_key_name.data(), key_name, TLS_SESSION_CRYPT_KEY_NAME_LEN) == false)
277          throw Decoding_Error("Wrong key name for encrypted session");
278 
279       hmac->update(key_seed, TLS_SESSION_CRYPT_AEAD_KEY_SEED_LEN);
280       const secure_vector<uint8_t> aead_key = hmac->final();
281 
282       auto aead = AEAD_Mode::create_or_throw(TLS_SESSION_CRYPT_AEAD, DECRYPTION);
283       aead->set_key(aead_key);
284       aead->set_associated_data(in, TLS_SESSION_CRYPT_HDR_LEN);
285       aead->start(aead_nonce, TLS_SESSION_CRYPT_AEAD_NONCE_LEN);
286       secure_vector<uint8_t> buf(ctext, ctext + ctext_len);
287       aead->finish(buf, 0);
288       return Session(buf.data(), buf.size());
289       }
290    catch(std::exception& e)
291       {
292       throw Decoding_Error("Failed to decrypt serialized TLS session: " +
293                            std::string(e.what()));
294       }
295    }
296 
297 }
298 
299 }
300