aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tls/tls_channel.cpp33
-rw-r--r--src/tls/tls_channel.h11
-rw-r--r--src/utils/stl_util.h7
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