aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorlloyd <lloyd@randombit.net>2012-09-07 20:43:26 +0000
committerlloyd <lloyd@randombit.net>2012-09-07 20:43:26 +0000
commit463c9fee5bc2035e012d230f44abf7e1778fdbf5 (patch)
tree89b8e7adf5fa9a6e7cc94d0ccb90bf08f2c64ed9
parent9126c751ce89bf8a6c226e4a73d68cb59fa8a8b6 (diff)
Add support for key material export
-rw-r--r--doc/relnotes/1_11_1.rst3
-rw-r--r--doc/tls.rst15
-rw-r--r--src/tls/tls_channel.cpp33
-rw-r--r--src/tls/tls_channel.h11
-rw-r--r--src/utils/stl_util.h7
5 files changed, 69 insertions, 0 deletions
diff --git a/doc/relnotes/1_11_1.rst b/doc/relnotes/1_11_1.rst
index 8300c4a17..622d5f57a 100644
--- a/doc/relnotes/1_11_1.rst
+++ b/doc/relnotes/1_11_1.rst
@@ -35,6 +35,9 @@ A bug caused heartbeat requests sent by the counterparty during a
handshake to be passed to the application callback as if they were
heartbeat responses.
+Support for TLS key material export as specified in :rfc:`5057`
+has been added, called via :cpp:func:`TLS::Channel::key_material_export`
+
New Feature: Public Key Strength Checking
""""""""""""""""""""""""""""""""""""""""""
diff --git a/doc/tls.rst b/doc/tls.rst
index 53972acaa..118bf7fac 100644
--- a/doc/tls.rst
+++ b/doc/tls.rst
@@ -135,6 +135,21 @@ available:
ordinarily be empty, unless the server requested a certificate
and the client responded with one.
+ .. cpp:function:: SymmetricKey key_material_export( \
+ const std::string& label, \
+ const std::string& context, \
+ size_t length)
+
+ Returns an exported key of *length* bytes derived from *label*,
+ *context*, and the session's master secret and client and server
+ random values. This key will be unique to this connection, and
+ as long as the session master secret remains secure an attacker
+ should not be able to guess the key.
+
+ Per :rfc:`5057`, *label* should begin with "EXPERIMENTAL" unless
+ the label has been standardized in an RFC.
+
+
.. _tls_client:
TLS Clients
diff --git a/src/tls/tls_channel.cpp b/src/tls/tls_channel.cpp
index 6d90ed47f..cb811278a 100644
--- a/src/tls/tls_channel.cpp
+++ b/src/tls/tls_channel.cpp
@@ -12,6 +12,7 @@
#include <botan/internal/tls_record.h>
#include <botan/internal/assert.h>
#include <botan/internal/rounding.h>
+#include <botan/internal/stl_util.h>
#include <botan/loadstor.h>
namespace Botan {
@@ -526,6 +527,38 @@ bool Channel::secure_renegotiation_supported() const
return m_secure_renegotiation;
}
+SymmetricKey Channel::key_material_export(const std::string& label,
+ const std::string& context,
+ size_t length) const
+ {
+ if(!m_active_state)
+ throw std::runtime_error("Channel::key_material_export connection not active");
+
+ Handshake_State& state = *m_active_state;
+
+ std::unique_ptr<KDF> prf(state.protocol_specific_prf());
+
+ const secure_vector<byte>& master_secret =
+ state.session_keys().master_secret();
+
+ std::vector<byte> salt;
+ salt += to_byte_vector(label);
+ salt += state.client_hello()->random();
+ salt += state.server_hello()->random();
+
+ if(context != "")
+ {
+ size_t context_size = context.length();
+ if(context_size > 0xFFFF)
+ throw std::runtime_error("key_material_export context is too long");
+ salt.push_back(get_byte<u16bit>(0, context_size));
+ salt.push_back(get_byte<u16bit>(1, context_size));
+ salt += to_byte_vector(context);
+ }
+
+ return prf->derive_key(length, master_secret, salt);
+ }
+
}
}
diff --git a/src/tls/tls_channel.h b/src/tls/tls_channel.h
index 1ea6b06eb..8b495fcd4 100644
--- a/src/tls/tls_channel.h
+++ b/src/tls/tls_channel.h
@@ -85,6 +85,17 @@ class BOTAN_DLL Channel
*/
std::vector<X509_Certificate> peer_cert_chain() const;
+ /**
+ * Key material export (RFC 5705)
+ * @param label a disambiguating label string
+ * @param context a per-association context value
+ * @param length the length of the desired key in bytes
+ * @return key of length bytes
+ */
+ SymmetricKey key_material_export(const std::string& label,
+ const std::string& context,
+ size_t length) const;
+
Channel(std::function<void (const byte[], size_t)> socket_output_fn,
std::function<void (const byte[], size_t, Alert)> proc_fn,
std::function<bool (const Session&)> handshake_complete,
diff --git a/src/utils/stl_util.h b/src/utils/stl_util.h
index 1a62e8fe7..690d2af01 100644
--- a/src/utils/stl_util.h
+++ b/src/utils/stl_util.h
@@ -9,10 +9,17 @@
#define BOTAN_STL_UTIL_H__
#include <vector>
+#include <string>
#include <map>
namespace Botan {
+std::vector<byte> to_byte_vector(const std::string& s)
+ {
+ return std::vector<byte>(reinterpret_cast<const byte*>(&s[0]),
+ reinterpret_cast<const byte*>(&s[s.size()]));
+ }
+
/*
* Searching through a std::map
* @param mapping the map to search