aboutsummaryrefslogtreecommitdiffstats
path: root/src/tls
diff options
context:
space:
mode:
authorlloyd <[email protected]>2012-03-16 17:36:54 +0000
committerlloyd <[email protected]>2012-03-16 17:36:54 +0000
commit79119349636d195f8787384b72a7fc3f6935d784 (patch)
treee43f994b65ee453c9affa5a75ea722dc34b64e7a /src/tls
parent9309bf44ca05e70100a4ef1653faf602e456cdd9 (diff)
parent1fce3fe2274cf3368e1f29827ed0f41cebba3726 (diff)
propagate from branch 'net.randombit.botan.tls-state-machine' (head 9a12f28252f9b0a051a85c4647679a715161d06c)
to branch 'net.randombit.botan.tls-session-ticket' (head ebf45d24a44fb4d1e66e59fe8abefe6f8a53cf02)
Diffstat (limited to 'src/tls')
-rw-r--r--src/tls/c_hello.cpp19
-rw-r--r--src/tls/tls_extensions.cpp3
-rw-r--r--src/tls/tls_extensions.h33
-rw-r--r--src/tls/tls_messages.h32
-rw-r--r--src/tls/tls_session.cpp91
-rw-r--r--src/tls/tls_session.h14
6 files changed, 189 insertions, 3 deletions
diff --git a/src/tls/c_hello.cpp b/src/tls/c_hello.cpp
index 35389f37b..e0fce03b5 100644
--- a/src/tls/c_hello.cpp
+++ b/src/tls/c_hello.cpp
@@ -207,6 +207,10 @@ void Client_Hello::deserialize_sslv2(const MemoryRegion<byte>& buf)
m_secure_renegotiation =
value_exists(m_suites, static_cast<u16bit>(TLS_EMPTY_RENEGOTIATION_INFO_SCSV));
+
+ m_fragment_size = 0;
+ m_next_protocol = false;
+ m_supports_session_ticket = false;
}
/*
@@ -300,6 +304,21 @@ void Client_Hello::deserialize(const MemoryRegion<byte>& buf)
m_supported_algos.push_back(std::make_pair("SHA-1", "DSA"));
m_supported_algos.push_back(std::make_pair("SHA-1", "ECDSA"));
}
+ else if(Maximum_Fragment_Length* frag = dynamic_cast<Maximum_Fragment_Length*>(extn))
+ {
+ m_fragment_size = frag->fragment_size();
+ }
+ else if(Session_Ticket* ticket = dynamic_cast<Session_Ticket*>(extn))
+ {
+ m_supports_session_ticket = true;
+ m_session_ticket = ticket->contents();
+ }
+ else if(Renegotation_Extension* reneg = dynamic_cast<Renegotation_Extension*>(extn))
+ {
+ // 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/tls_extensions.cpp b/src/tls/tls_extensions.cpp
index 5d345cc9b..d0d5b2c62 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
}
diff --git a/src/tls/tls_extensions.h b/src/tls/tls_extensions.h
index 180216b8b..a9e85221e 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,37 @@ class Next_Protocol_Notification : public Extension
std::vector<std::string> m_protocols;
};
+class Session_Ticket : public TLS_Extension
+ {
+ public:
+ TLS_Handshake_Extension_Type type() const
+ { return TLSEXT_SESSION_TICKET; }
+
+ const MemoryVector<byte>& contents() const { return m_contents; }
+
+ /**
+ * 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_contents(session_ticket) {}
+
+ /**
+ * Deserialize a session ticket
+ */
+ Session_Ticket(const TLS_Data_Reader& reader, u16bit extension_size);
+
+ MemoryVector<byte> serialize() const { return m_contents; }
+
+ bool empty() const { return false; }
+ private:
+ MemoryVector<byte> m_contents;
+ };
+
/**
* Supported Elliptic Curves Extension (RFC 4492)
*/
diff --git a/src/tls/tls_messages.h b/src/tls/tls_messages.h
index 513fdad70..617b03813 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;
};
/**
@@ -454,6 +462,30 @@ 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; }
+
+ static TLS_Session decrypt(const MemoryRegion<byte>& ctext,
+ const SymmetricKey& key,
+ const MemoryRegion<byte>& key_name);
+
+ const MemoryVector<byte>& contents() const { return m_contents; }
+
+ New_Session_Ticket(const TLS_Session& session_info,
+ const SymmetricKey& key,
+ const MemoryRegion<byte>& key_name,
+ RandomNumberGenerator& rng);
+
+ New_Session_Ticket(const MemoryRegion<byte>& buf) { deserialize(buf); }
+ private:
+ MemoryVector<byte> serialize() const;
+ void deserialize(const MemoryRegion<byte>&);
+
+ MemoryVector<byte> m_contents;
+ };
+
}
}
diff --git a/src/tls/tls_session.cpp b/src/tls/tls_session.cpp
index 320f3c004..f8e686a4a 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,8 @@
#include <botan/asn1_str.h>
#include <botan/pem.h>
#include <botan/time.h>
+#include <botan/lookup.h>
+#include <memory>
namespace Botan {
@@ -128,4 +130,91 @@ std::string Session::PEM_encode() const
}
+MemoryVector<byte>
+TLS_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("TLS_Session master_key not set");
+
+ std::auto_ptr<KDF> kdf(get_kdf("KDF2(SHA-256)"));
+
+ SymmetricKey aes_key = kdf->derive_key(16, master_key.bits_of(),
+ "session-ticket.cipher-key");
+
+ SymmetricKey hmac_key = kdf->derive_key(32, master_key.bits_of(),
+ "session-ticket.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-128/CBC", aes_key, aes_iv, ENCRYPTION));
+ pipe.process_msg(BER_encode());
+ MemoryVector<byte> ctext = pipe.read_all(0);
+
+ MemoryVector<byte> out;
+ out += key_name;
+ out += aes_iv.bits_of();
+ out += ctext;
+
+ mac->update(out);
+
+ out += mac->final();
+ return out;
+ }
+
+TLS_Session TLS_Session::decrypt(const MemoryRegion<byte>& buf,
+ const SymmetricKey& master_key,
+ const MemoryRegion<byte>& key_name)
+ {
+ 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("TLS_Session master_key not set");
+
+ if(key_name.size() != 16)
+ throw Decoding_Error("Bad length " + to_string(key_name.size()) +
+ " for key_name");
+
+ 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");
+
+ 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");
+
+ SymmetricKey aes_key = kdf->derive_key(16, master_key.bits_of(),
+ "session-ticket.cipher-key");
+
+ InitializationVector aes_iv(&buf[16], 16);
+
+ Pipe pipe(get_cipher("AES-128/CBC", aes_key, aes_iv, DECRYPTION));
+ pipe.process_msg(&buf[16], buf.size() - (16 + 32));
+ MemoryVector<byte> ber = pipe.read_all();
+
+ return TLS_Session(&ber[0], ber.size());
+ }
+ catch(...)
+ {
+ throw Decoding_Error("Failed to decrypt encrypted session");
+ }
+ }
+
}
diff --git a/src/tls/tls_session.h b/src/tls/tls_session.h
index 96b6d6daf..40aaee278 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 {
@@ -71,6 +72,17 @@ class BOTAN_DLL Session
SecureVector<byte> DER_encode() const;
/**
+ * Encrypt a session (useful for serialization or session tickets)
+ */
+ MemoryVector<byte> encrypt(const SymmetricKey& key,
+ const MemoryRegion<byte>& key_name,
+ RandomNumberGenerator& rng);
+
+ static TLS_Session decrypt(const MemoryRegion<byte>& ctext,
+ const SymmetricKey& key,
+ const MemoryRegion<byte>& key_name);
+
+ /**
* Encode this session data for storage
* @warning if the master secret is compromised so is the
* session traffic