aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/build-data/cc/gcc.txt2
-rw-r--r--src/tls/c_hello.cpp31
-rw-r--r--src/tls/info.txt1
-rw-r--r--src/tls/s_hello.cpp8
-rw-r--r--src/tls/tls_client.cpp30
-rw-r--r--src/tls/tls_extensions.cpp9
-rw-r--r--src/tls/tls_extensions.h35
-rw-r--r--src/tls/tls_handshake_state.cpp9
-rw-r--r--src/tls/tls_handshake_state.h1
-rw-r--r--src/tls/tls_messages.h30
-rw-r--r--src/tls/tls_reader.h9
-rw-r--r--src/tls/tls_server.cpp1
-rw-r--r--src/tls/tls_session.cpp118
-rw-r--r--src/tls/tls_session.h26
14 files changed, 288 insertions, 22 deletions
diff --git a/src/build-data/cc/gcc.txt b/src/build-data/cc/gcc.txt
index 3de85099c..6173f6271 100644
--- a/src/build-data/cc/gcc.txt
+++ b/src/build-data/cc/gcc.txt
@@ -13,7 +13,7 @@ add_lib_option -l
lang_flags "-D_REENTRANT -Wno-long-long"
warning_flags "-W -Wall"
-maintainer_warning_flags "-Werror -Weffc++ -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast"
+maintainer_warning_flags "-Werror -Wall -Wextra -Wstrict-aliasing -Wstrict-overflow=5 -Wcast-align -Wmissing-declarations -Wpointer-arith -Wcast-qual -Wold-style-cast"
lib_opt_flags "-O3"
check_opt_flags "-O2"
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp
index 35389f37b..df76c748f 100644
--- a/src/tls/c_hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -71,7 +71,8 @@ Client_Hello::Client_Hello(Record_Writer& writer,
m_next_protocol(next_protocol),
m_fragment_size(0),
m_secure_renegotiation(true),
- m_renegotiation_info(reneg_info)
+ m_renegotiation_info(reneg_info),
+ m_supports_session_ticket(true)
{
std::vector<std::string> hashes = policy.allowed_hashes();
std::vector<std::string> sigs = policy.allowed_signature_methods();
@@ -86,7 +87,7 @@ Client_Hello::Client_Hello(Record_Writer& writer,
}
/*
-* Create a new Client Hello message
+* Create a new Client Hello message (session resumption case)
*/
Client_Hello::Client_Hello(Record_Writer& writer,
Handshake_Hash& hash,
@@ -100,7 +101,8 @@ Client_Hello::Client_Hello(Record_Writer& writer,
m_srp_identifier(session.srp_identifier()),
m_next_protocol(next_protocol),
m_fragment_size(session.fragment_size()),
- m_secure_renegotiation(session.secure_renegotiation())
+ m_secure_renegotiation(session.secure_renegotiation()),
+ m_supports_session_ticket(true)
{
m_suites.push_back(session.ciphersuite_code());
m_comp_methods.push_back(session.compression_method());
@@ -110,10 +112,14 @@ Client_Hello::Client_Hello(Record_Writer& writer,
hash.update(writer.send(*this));
}
+/*
+* Read a counterparty client hello
+*/
Client_Hello::Client_Hello(const MemoryRegion<byte>& buf, Handshake_Type type)
{
m_next_protocol = false;
m_secure_renegotiation = false;
+ m_supports_session_ticket = false;
m_fragment_size = 0;
if(type == CLIENT_HELLO)
@@ -153,6 +159,7 @@ MemoryVector<byte> Client_Hello::serialize() const
extensions.add(new Server_Name_Indicator(m_hostname));
extensions.add(new SRP_Identifier(m_srp_identifier));
extensions.add(new Supported_Elliptic_Curves(m_supported_curves));
+ extensions.add(new Session_Ticket());
if(m_version >= Protocol_Version::TLS_V12)
extensions.add(new Signature_Algorithms(m_supported_algos));
@@ -302,6 +309,24 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
}
}
+ if(Maximum_Fragment_Length* frag = extensions.get<Maximum_Fragment_Length>())
+ {
+ m_fragment_size = frag->fragment_size();
+ }
+
+ if(Session_Ticket* ticket = extensions.get<Session_Ticket>())
+ {
+ m_supports_session_ticket = true;
+ m_session_ticket = ticket->contents();
+ }
+
+ if(Renegotation_Extension* reneg = extensions.get<Renegotation_Extension>())
+ {
+ // checked by TLS_Client / TLS_Server as they know the handshake state
+ m_secure_renegotiation = true;
+ m_renegotiation_info = reneg->renegotiation_info();
+ }
+
if(value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV)))
{
/*
diff --git a/src/tls/info.txt b/src/tls/info.txt
index 822914a3d..9cc936471 100644
--- a/src/tls/info.txt
+++ b/src/tls/info.txt
@@ -45,6 +45,7 @@ rec_read.cpp
rec_wri.cpp
s_hello.cpp
s_kex.cpp
+session_ticket.cpp
tls_channel.cpp
tls_client.cpp
tls_extensions.cpp
diff --git a/src/tls/s_hello.cpp b/src/tls/s_hello.cpp
index 9bcbdb5e9..3e30382f6 100644
--- a/src/tls/s_hello.cpp
+++ b/src/tls/s_hello.cpp
@@ -89,6 +89,7 @@ Server_Hello::Server_Hello(Record_Writer& writer,
Server_Hello::Server_Hello(const MemoryRegion<byte>& buf)
{
m_secure_renegotiation = false;
+ m_supports_session_ticket = false;
m_next_protocol = false;
if(buf.size() < 38)
@@ -132,6 +133,13 @@ Server_Hello::Server_Hello(const MemoryRegion<byte>& buf)
m_next_protocols = npn->protocols();
m_next_protocol = true;
}
+
+ if(Session_Ticket* ticket = extensions.get<Session_Ticket>())
+ {
+ if(!ticket->contents().empty())
+ throw Decoding_Error("TLS server sent non-empty session ticket extension");
+ m_supports_session_ticket = true;
+ }
}
/*
diff --git a/src/tls/tls_client.cpp b/src/tls/tls_client.cpp
index 02e24a1c9..f6e016725 100644
--- a/src/tls/tls_client.cpp
+++ b/src/tls/tls_client.cpp
@@ -11,6 +11,9 @@
#include <botan/internal/stl_util.h>
#include <memory>
+#include <stdio.h>
+#include <botan/hex.h>
+
namespace Botan {
namespace TLS {
@@ -173,6 +176,13 @@ void Client::process_handshake_msg(Handshake_Type type,
"Server sent next protocol but we didn't request it");
}
+ if(state->server_hello->supports_session_ticket())
+ {
+ if(!state->client_hello->supports_session_ticket())
+ throw TLS_Exception(Alert::HANDSHAKE_FAILURE,
+ "Server sent session ticket extension but we did not");
+ }
+
state->set_version(state->server_hello->version());
writer.set_version(state->version());
@@ -199,7 +209,10 @@ void Client::process_handshake_msg(Handshake_Type type,
state->resume_master_secret,
true);
- state->set_expected_next(HANDSHAKE_CCS);
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
}
else
{
@@ -306,8 +319,6 @@ void Client::process_handshake_msg(Handshake_Type type,
}
else if(type == SERVER_HELLO_DONE)
{
- state->set_expected_next(HANDSHAKE_CCS);
-
state->server_hello_done = new Server_Hello_Done(contents);
if(state->received_handshake_msg(CERTIFICATE_REQUEST))
@@ -364,6 +375,17 @@ void Client::process_handshake_msg(Handshake_Type type,
}
state->client_finished = new Finished(writer, state, CLIENT);
+
+ if(state->server_hello->supports_session_ticket())
+ state->set_expected_next(NEW_SESSION_TICKET);
+ else
+ state->set_expected_next(HANDSHAKE_CCS);
+ }
+ else if(type == NEW_SESSION_TICKET)
+ {
+ state->new_session_ticket = new New_Session_Ticket(contents);
+
+ state->set_expected_next(HANDSHAKE_CCS);
}
else if(type == HANDSHAKE_CCS)
{
@@ -404,6 +426,8 @@ void Client::process_handshake_msg(Handshake_Type type,
secure_renegotiation.supported(),
state->server_hello->fragment_size(),
peer_certs,
+ state->new_session_ticket ? state->new_session_ticket->ticket() :
+ MemoryVector<byte>(),
state->client_hello->sni_hostname(),
""
);
diff --git a/src/tls/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index 5d345cc9b..ae236d0c5 100644
--- a/src/tls/tls_extensions.cpp
+++ b/src/tls/tls_extensions.cpp
@@ -42,6 +42,9 @@ Extension* make_extension(TLS_Data_Reader& reader,
case TLSEXT_NEXT_PROTOCOL:
return new Next_Protocol_Notification(reader, size);
+ case TLSEXT_SESSION_TICKET:
+ return new Session_Ticket(reader, size);
+
default:
return 0; // not known
}
@@ -501,6 +504,12 @@ Signature_Algorithms::Signature_Algorithms(TLS_Data_Reader& reader,
}
}
+Session_Ticket::Session_Ticket(const TLS_Data_Reader& reader,
+ u16bit extension_size)
+ {
+#warning "can't read session tickets"
+ }
+
}
}
diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h
index 180216b8b..c2b9091db 100644
--- a/src/tls/tls_extensions.h
+++ b/src/tls/tls_extensions.h
@@ -1,6 +1,6 @@
/*
* TLS Extensions
-* (C) 2011 Jack Lloyd
+* (C) 2011-2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/
@@ -210,6 +210,39 @@ class Next_Protocol_Notification : public Extension
std::vector<std::string> m_protocols;
};
+class Session_Ticket : public Extension
+ {
+ public:
+ static Handshake_Extension_Type static_type()
+ { return TLSEXT_SESSION_TICKET; }
+
+ Handshake_Extension_Type type() const { return static_type(); }
+
+ const MemoryVector<byte>& contents() const { return m_ticket; }
+
+ /**
+ * Create empty extension, used by both client and server
+ */
+ Session_Ticket() {}
+
+ /**
+ * Extension with ticket, used by client
+ */
+ Session_Ticket(const MemoryRegion<byte>& session_ticket) :
+ m_ticket(session_ticket) {}
+
+ /**
+ * Deserialize a session ticket
+ */
+ Session_Ticket(const TLS_Data_Reader& reader, u16bit extension_size);
+
+ MemoryVector<byte> serialize() const { return m_ticket; }
+
+ bool empty() const { return false; }
+ private:
+ MemoryVector<byte> m_ticket;
+ };
+
/**
* Supported Elliptic Curves Extension (RFC 4492)
*/
diff --git a/src/tls/tls_handshake_state.cpp b/src/tls/tls_handshake_state.cpp
index 2db97db0a..4a82a1641 100644
--- a/src/tls/tls_handshake_state.cpp
+++ b/src/tls/tls_handshake_state.cpp
@@ -54,12 +54,15 @@ u32bit bitmask_for_handshake_type(Handshake_Type type)
case NEXT_PROTOCOL:
return (1 << 9);
- case HANDSHAKE_CCS:
+ case NEW_SESSION_TICKET:
return (1 << 10);
- case FINISHED:
+ case HANDSHAKE_CCS:
return (1 << 11);
+ case FINISHED:
+ return (1 << 12);
+
// allow explicitly disabling new handshakes
case HANDSHAKE_NONE:
return 0;
@@ -85,6 +88,7 @@ Handshake_State::Handshake_State(Handshake_Reader* reader)
cert_req = 0;
server_hello_done = 0;
next_protocol = 0;
+ new_session_ticket = 0;
client_certs = 0;
client_kex = 0;
@@ -287,6 +291,7 @@ Handshake_State::~Handshake_State()
delete cert_req;
delete server_hello_done;
delete next_protocol;
+ delete new_session_ticket;
delete client_certs;
delete client_kex;
diff --git a/src/tls/tls_handshake_state.h b/src/tls/tls_handshake_state.h
index 206e19096..52bfd24b2 100644
--- a/src/tls/tls_handshake_state.h
+++ b/src/tls/tls_handshake_state.h
@@ -80,6 +80,7 @@ class Handshake_State
class Certificate_Verify* client_verify;
class Next_Protocol* next_protocol;
+ class New_Session_Ticket* new_session_ticket;
class Finished* client_finished;
class Finished* server_finished;
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index 513fdad70..019dafa69 100644
--- a/src/tls/tls_messages.h
+++ b/src/tls/tls_messages.h
@@ -108,6 +108,11 @@ class Client_Hello : public Handshake_Message
size_t fragment_size() const { return m_fragment_size; }
+ bool supports_session_ticket() const { return m_supports_session_ticket; }
+
+ const MemoryRegion<byte>& session_ticket() const
+ { return m_session_ticket; }
+
Client_Hello(Record_Writer& writer,
Handshake_Hash& hash,
const Policy& policy,
@@ -145,6 +150,9 @@ class Client_Hello : public Handshake_Message
std::vector<std::pair<std::string, std::string> > m_supported_algos;
std::vector<std::string> m_supported_curves;
+
+ bool m_supports_session_ticket;
+ MemoryVector<byte> m_session_ticket;
};
/**
@@ -170,6 +178,8 @@ class Server_Hello : public Handshake_Message
bool next_protocol_notification() const { return m_next_protocol; }
+ bool supports_session_ticket() const { return m_supports_session_ticket; }
+
const std::vector<std::string>& next_protocols() const
{ return m_next_protocols; }
@@ -219,6 +229,7 @@ class Server_Hello : public Handshake_Message
MemoryVector<byte> m_renegotiation_info;
bool m_next_protocol;
+ bool m_supports_session_ticket;
std::vector<std::string> m_next_protocols;
};
@@ -454,6 +465,25 @@ class Next_Protocol : public Handshake_Message
std::string m_protocol;
};
+class New_Session_Ticket : public Handshake_Message
+ {
+ public:
+ Handshake_Type type() const { return NEW_SESSION_TICKET; }
+
+ u32bit ticket_lifetime_hint() const { return m_ticket_lifetime_hint; }
+ const MemoryVector<byte>& ticket() const { return m_ticket; }
+
+ New_Session_Ticket(const MemoryVector<byte>& ticket, u32bit lifetime = 0) :
+ m_ticket_lifetime_hint(lifetime), m_ticket(ticket) {}
+
+ New_Session_Ticket(const MemoryRegion<byte>& buf);
+ private:
+ MemoryVector<byte> serialize() const;
+
+ u32bit m_ticket_lifetime_hint;
+ MemoryVector<byte> m_ticket;
+ };
+
}
}
diff --git a/src/tls/tls_reader.h b/src/tls/tls_reader.h
index 162f691aa..f6b0d4088 100644
--- a/src/tls/tls_reader.h
+++ b/src/tls/tls_reader.h
@@ -50,6 +50,15 @@ class TLS_Data_Reader
offset += bytes;
}
+ u16bit get_u32bit()
+ {
+ assert_at_least(4);
+ u16bit result = make_u32bit(buf[offset ], buf[offset+1],
+ buf[offset+2], buf[offset+3]);
+ offset += 4;
+ return result;
+ }
+
u16bit get_u16bit()
{
assert_at_least(2);
diff --git a/src/tls/tls_server.cpp b/src/tls/tls_server.cpp
index eacbc02e0..874aa064c 100644
--- a/src/tls/tls_server.cpp
+++ b/src/tls/tls_server.cpp
@@ -447,6 +447,7 @@ void Server::process_handshake_msg(Handshake_Type type,
secure_renegotiation.supported(),
state->server_hello->fragment_size(),
peer_certs,
+ MemoryVector<byte>(),
m_hostname,
""
);
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp
index 7a32c33d8..a9eb8f95c 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.hmac-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()));
+ }
+ }
+
}
}
+
diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h
index 96b6d6daf..ab11154c9 100644
--- a/src/tls/tls_session.h
+++ b/src/tls/tls_session.h
@@ -1,6 +1,6 @@
/*
* TLS Session
-* (C) 2011 Jack Lloyd
+* (C) 2011-2012 Jack Lloyd
*
* Released under the terms of the Botan license
*/
@@ -13,6 +13,7 @@
#include <botan/tls_ciphersuite.h>
#include <botan/tls_magic.h>
#include <botan/secmem.h>
+#include <botan/symkey.h>
namespace Botan {
@@ -50,6 +51,7 @@ class BOTAN_DLL Session
bool secure_renegotiation_supported,
size_t fragment_size,
const std::vector<X509_Certificate>& peer_certs,
+ const MemoryRegion<byte>& session_ticket,
const std::string& sni_hostname = "",
const std::string& srp_identifier = "");
@@ -71,6 +73,20 @@ class BOTAN_DLL Session
SecureVector<byte> DER_encode() const;
/**
+ * Encrypt a session (useful for serialization or session tickets)
+ */
+ MemoryVector<byte> encrypt(const SymmetricKey& key,
+ RandomNumberGenerator& rng);
+
+ /**
+ * Decrypt a session created by encrypt
+ * @param ctext the ciphertext returned by encrypt
+ * @param key the same key used by the encrypting side
+ */
+ static Session decrypt(const MemoryRegion<byte>& ctext,
+ const SymmetricKey& key);
+
+ /**
* Encode this session data for storage
* @warning if the master secret is compromised so is the
* session traffic
@@ -146,12 +162,18 @@ class BOTAN_DLL Session
*/
u64bit start_time() const { return m_start_time; }
+ /**
+ * Return the session ticket the server gave us
+ */
+ const MemoryVector<byte>& session_ticket() const { return m_session_ticket; }
+
private:
- enum { TLS_SESSION_PARAM_STRUCT_VERSION = 1 };
+ enum { TLS_SESSION_PARAM_STRUCT_VERSION = 0x2994e300 };
u64bit m_start_time;
MemoryVector<byte> m_identifier;
+ MemoryVector<byte> m_session_ticket; // only used by client side
SecureVector<byte> m_master_secret;
Protocol_Version m_version;