Botan  2.7.0
Crypto and TLS for C++11
tls_session.cpp
Go to the documentation of this file.
1 /*
2 * TLS Session State
3 * (C) 2011-2012,2015 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/der_enc.h>
10 #include <botan/ber_dec.h>
11 #include <botan/asn1_str.h>
12 #include <botan/pem.h>
13 #include <botan/aead.h>
14 #include <botan/mac.h>
15 #include <botan/rng.h>
16 
17 namespace Botan {
18 
19 namespace TLS {
20 
21 Session::Session(const std::vector<uint8_t>& session_identifier,
22  const secure_vector<uint8_t>& master_secret,
23  Protocol_Version version,
24  uint16_t ciphersuite,
25  Connection_Side side,
26  bool extended_master_secret,
27  bool encrypt_then_mac,
28  const std::vector<X509_Certificate>& certs,
29  const std::vector<uint8_t>& ticket,
30  const Server_Information& server_info,
31  const std::string& srp_identifier,
32  uint16_t srtp_profile) :
33  m_start_time(std::chrono::system_clock::now()),
34  m_identifier(session_identifier),
35  m_session_ticket(ticket),
36  m_master_secret(master_secret),
37  m_version(version),
38  m_ciphersuite(ciphersuite),
39  m_connection_side(side),
40  m_srtp_profile(srtp_profile),
41  m_extended_master_secret(extended_master_secret),
42  m_encrypt_then_mac(encrypt_then_mac),
43  m_peer_certs(certs),
44  m_server_info(server_info),
45  m_srp_identifier(srp_identifier)
46  {
47  }
48 
49 Session::Session(const std::string& pem)
50  {
51  secure_vector<uint8_t> der = PEM_Code::decode_check_label(pem, "TLS SESSION");
52 
53  *this = Session(der.data(), der.size());
54  }
55 
56 Session::Session(const uint8_t ber[], size_t ber_len)
57  {
58  uint8_t side_code = 0;
59 
60  ASN1_String server_hostname;
61  ASN1_String server_service;
62  size_t server_port;
63 
64  ASN1_String srp_identifier_str;
65 
66  uint8_t major_version = 0, minor_version = 0;
67  std::vector<uint8_t> peer_cert_bits;
68 
69  size_t start_time = 0;
70  size_t srtp_profile = 0;
71  size_t fragment_size = 0;
72  size_t compression_method = 0;
73 
74  BER_Decoder(ber, ber_len)
76  .decode_and_check(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION),
77  "Unknown version in serialized TLS session")
79  .decode_integer_type(major_version)
80  .decode_integer_type(minor_version)
81  .decode(m_identifier, OCTET_STRING)
82  .decode(m_session_ticket, OCTET_STRING)
83  .decode_integer_type(m_ciphersuite)
84  .decode_integer_type(compression_method)
85  .decode_integer_type(side_code)
86  .decode_integer_type(fragment_size)
87  .decode(m_extended_master_secret)
88  .decode(m_encrypt_then_mac)
89  .decode(m_master_secret, OCTET_STRING)
90  .decode(peer_cert_bits, OCTET_STRING)
91  .decode(server_hostname)
92  .decode(server_service)
93  .decode(server_port)
94  .decode(srp_identifier_str)
95  .decode(srtp_profile)
96  .end_cons()
97  .verify_end();
98 
99  /*
100  * Compression is not supported and must be zero
101  */
102  if(compression_method != 0)
103  {
104  throw Decoding_Error("Serialized TLS session contains non-null compression method");
105  }
106 
107  /*
108  Fragment size is not supported anymore, but the field is still
109  set in the session object.
110  */
111  if(fragment_size != 0)
112  {
113  throw Decoding_Error("Serialized TLS session used maximum fragment length which is "
114  " no longer supported");
115  }
116 
117  m_version = Protocol_Version(major_version, minor_version);
118  m_start_time = std::chrono::system_clock::from_time_t(start_time);
119  m_connection_side = static_cast<Connection_Side>(side_code);
120  m_srtp_profile = static_cast<uint16_t>(srtp_profile);
121 
122  m_server_info = Server_Information(server_hostname.value(),
123  server_service.value(),
124  static_cast<uint16_t>(server_port));
125 
126  m_srp_identifier = srp_identifier_str.value();
127 
128  if(!peer_cert_bits.empty())
129  {
130  DataSource_Memory certs(peer_cert_bits.data(), peer_cert_bits.size());
131 
132  while(!certs.end_of_data())
133  m_peer_certs.push_back(X509_Certificate(certs));
134  }
135  }
136 
138  {
139  std::vector<uint8_t> peer_cert_bits;
140  for(size_t i = 0; i != m_peer_certs.size(); ++i)
141  peer_cert_bits += m_peer_certs[i].BER_encode();
142 
143  return DER_Encoder()
145  .encode(static_cast<size_t>(TLS_SESSION_PARAM_STRUCT_VERSION))
146  .encode(static_cast<size_t>(std::chrono::system_clock::to_time_t(m_start_time)))
147  .encode(static_cast<size_t>(m_version.major_version()))
148  .encode(static_cast<size_t>(m_version.minor_version()))
149  .encode(m_identifier, OCTET_STRING)
150  .encode(m_session_ticket, OCTET_STRING)
151  .encode(static_cast<size_t>(m_ciphersuite))
152  .encode(static_cast<size_t>(/*old compression method*/0))
153  .encode(static_cast<size_t>(m_connection_side))
154  .encode(static_cast<size_t>(/*old fragment size*/0))
155  .encode(m_extended_master_secret)
156  .encode(m_encrypt_then_mac)
157  .encode(m_master_secret, OCTET_STRING)
158  .encode(peer_cert_bits, OCTET_STRING)
159  .encode(ASN1_String(m_server_info.hostname(), UTF8_STRING))
160  .encode(ASN1_String(m_server_info.service(), UTF8_STRING))
161  .encode(static_cast<size_t>(m_server_info.port()))
162  .encode(ASN1_String(m_srp_identifier, UTF8_STRING))
163  .encode(static_cast<size_t>(m_srtp_profile))
164  .end_cons()
165  .get_contents();
166  }
167 
168 std::string Session::PEM_encode() const
169  {
170  return PEM_Code::encode(this->DER_encode(), "TLS SESSION");
171  }
172 
173 std::chrono::seconds Session::session_age() const
174  {
175  return std::chrono::duration_cast<std::chrono::seconds>(
176  std::chrono::system_clock::now() - m_start_time);
177  }
178 
179 std::vector<uint8_t>
181  {
182  std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw("AES-256/GCM", ENCRYPTION);
183  const size_t nonce_len = aead->default_nonce_length();
184 
185  const secure_vector<uint8_t> nonce = rng.random_vec(nonce_len);
186  const secure_vector<uint8_t> bits = this->DER_encode();
187 
188  // Support any length key for input
189  std::unique_ptr<MessageAuthenticationCode> hmac(MessageAuthenticationCode::create("HMAC(SHA-256)"));
190  hmac->set_key(key);
191  hmac->update(nonce);
192  aead->set_key(hmac->final());
193 
194  secure_vector<uint8_t> buf = nonce;
195  buf += bits;
196  aead->start(buf.data(), nonce_len);
197  aead->finish(buf, nonce_len);
198  return unlock(buf);
199  }
200 
201 Session Session::decrypt(const uint8_t in[], size_t in_len, const SymmetricKey& key)
202  {
203  try
204  {
205  std::unique_ptr<AEAD_Mode> aead = AEAD_Mode::create_or_throw("AES-256/GCM", DECRYPTION);
206  const size_t nonce_len = aead->default_nonce_length();
207 
208  if(in_len < nonce_len + aead->tag_size())
209  throw Decoding_Error("Encrypted session too short to be valid");
210 
211  // Support any length key for input
212  std::unique_ptr<MessageAuthenticationCode> hmac(MessageAuthenticationCode::create("HMAC(SHA-256)"));
213  hmac->set_key(key);
214  hmac->update(in, nonce_len); // nonce bytes
215  aead->set_key(hmac->final());
216 
217  aead->start(in, nonce_len);
218  secure_vector<uint8_t> buf(in + nonce_len, in + in_len);
219  aead->finish(buf, 0);
220 
221  return Session(buf.data(), buf.size());
222  }
223  catch(std::exception& e)
224  {
225  throw Decoding_Error("Failed to decrypt serialized TLS session: " +
226  std::string(e.what()));
227  }
228  }
229 
230 }
231 
232 }
static Session decrypt(const uint8_t ctext[], size_t ctext_size, const SymmetricKey &key)
static std::unique_ptr< MessageAuthenticationCode > create(const std::string &algo_spec, const std::string &provider="")
Definition: mac.cpp:46
secure_vector< uint8_t > random_vec(size_t bytes)
Definition: rng.h:132
BER_Decoder & decode_integer_type(T &out)
Definition: ber_dec.h:242
uint8_t minor_version() const
Definition: tls_version.h:82
BER_Decoder & decode_and_check(const T &expected, const std::string &error_msg)
Definition: ber_dec.h:277
std::chrono::system_clock::time_point start_time() const
Definition: tls_session.h:168
secure_vector< uint8_t > get_contents()
Definition: der_enc.cpp:152
Definition: bigint.h:796
std::string hostname() const
DER_Encoder & end_cons()
Definition: der_enc.cpp:191
BER_Decoder & decode(bool &out)
Definition: ber_dec.h:170
DER_Encoder & encode(bool b)
Definition: der_enc.cpp:285
secure_vector< uint8_t > decode_check_label(DataSource &source, const std::string &label_want)
Definition: pem.cpp:54
std::string encode(const uint8_t der[], size_t length, const std::string &label, size_t width)
Definition: pem.cpp:43
BER_Decoder & end_cons()
Definition: ber_dec.cpp:300
std::vector< uint8_t > encrypt(const SymmetricKey &key, RandomNumberGenerator &rng) const
std::string PEM_encode() const
BER_Decoder start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: ber_dec.cpp:290
Definition: alg_id.cpp:13
secure_vector< uint8_t > BER_encode(const Private_Key &key)
Definition: pkcs8.cpp:139
secure_vector< uint8_t > DER_encode() const
std::chrono::seconds session_age() const
const std::string & value() const
Definition: asn1_str.h:27
std::vector< T > unlock(const secure_vector< T > &in)
Definition: secmem.h:95
BER_Decoder & verify_end()
Definition: ber_dec.cpp:208
uint8_t major_version() const
Definition: tls_version.h:77
DER_Encoder & start_cons(ASN1_Tag type_tag, ASN1_Tag class_tag=UNIVERSAL)
Definition: der_enc.cpp:181
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
static std::unique_ptr< AEAD_Mode > create_or_throw(const std::string &algo, Cipher_Dir direction, const std::string &provider="")
Definition: aead.cpp:42