diff options
Diffstat (limited to 'src')
-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 |
3 files changed, 51 insertions, 0 deletions
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 |