diff options
author | lloyd <lloyd@randombit.net> | 2012-09-07 20:43:26 +0000 |
---|---|---|
committer | lloyd <lloyd@randombit.net> | 2012-09-07 20:43:26 +0000 |
commit | 463c9fee5bc2035e012d230f44abf7e1778fdbf5 (patch) | |
tree | 89b8e7adf5fa9a6e7cc94d0ccb90bf08f2c64ed9 | |
parent | 9126c751ce89bf8a6c226e4a73d68cb59fa8a8b6 (diff) |
Add support for key material export
-rw-r--r-- | doc/relnotes/1_11_1.rst | 3 | ||||
-rw-r--r-- | doc/tls.rst | 15 | ||||
-rw-r--r-- | src/tls/tls_channel.cpp | 33 | ||||
-rw-r--r-- | src/tls/tls_channel.h | 11 | ||||
-rw-r--r-- | src/utils/stl_util.h | 7 |
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 |