aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/prf/hkdf/hkdf.cpp62
-rw-r--r--src/prf/hkdf/hkdf.h51
-rw-r--r--src/prf/hkdf/info.txt1
3 files changed, 114 insertions, 0 deletions
diff --git a/src/prf/hkdf/hkdf.cpp b/src/prf/hkdf/hkdf.cpp
new file mode 100644
index 000000000..0a1f7cb31
--- /dev/null
+++ b/src/prf/hkdf/hkdf.cpp
@@ -0,0 +1,62 @@
+/*
+* HKDF
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#include <botan/hkdf.h>
+
+namespace Botan {
+
+std::string HKDF::name() const
+ {
+ return "HKDF(" + m_prf->name() + ")";
+ }
+
+void HKDF::clear()
+ {
+ m_extractor->clear();
+ m_prf->clear();
+ }
+
+void HKDF::start_extract(const byte salt[], size_t salt_len)
+ {
+ m_extractor->set_key(salt, salt_len);
+ }
+
+void HKDF::extract(const byte input[], size_t input_len)
+ {
+ m_extractor->update(input, input_len);
+ }
+
+void HKDF::finish_extract()
+ {
+ m_prf->set_key(m_extractor->final());
+ }
+
+void HKDF::expand(byte output[], size_t output_len,
+ const byte info[], size_t info_len)
+ {
+ if(output_len > m_prf->output_length() * 255)
+ throw std::invalid_argument("HKDF requested output too large");
+
+ byte counter = 1;
+
+ secure_vector<byte> T;
+
+ while(output_len)
+ {
+ m_prf->update(T);
+ m_prf->update(info, info_len);
+ m_prf->update(counter++);
+ T = m_prf->final();
+
+ const size_t to_write = std::min(T.size(), output_len);
+ copy_mem(&output[0], &T[0], to_write);
+ output += to_write;
+ output_len -= to_write;
+ }
+ }
+
+}
diff --git a/src/prf/hkdf/hkdf.h b/src/prf/hkdf/hkdf.h
new file mode 100644
index 000000000..e0b5a7376
--- /dev/null
+++ b/src/prf/hkdf/hkdf.h
@@ -0,0 +1,51 @@
+/*
+* HKDF
+* (C) 2013 Jack Lloyd
+*
+* Distributed under the terms of the Botan license
+*/
+
+#ifndef BOTAN_HKDF_H__
+#define BOTAN_HKDF_H__
+
+#include <botan/mac.h>
+#include <botan/hash.h>
+#include <memory>
+
+namespace Botan {
+
+/**
+* HKDF, see @rfc 5869 for details
+*/
+class BOTAN_DLL HKDF
+ {
+ public:
+ HKDF(MessageAuthenticationCode* extractor,
+ MessageAuthenticationCode* prf) :
+ m_extractor(extractor), m_prf(prf) {}
+
+ HKDF(MessageAuthenticationCode* prf) :
+ m_extractor(prf), m_prf(m_extractor->clone()) {}
+
+ void start_extract(const byte salt[], size_t salt_len);
+ void extract(const byte input[], size_t input_len);
+ void finish_extract();
+
+ /**
+ * Only call after extract
+ * @param output_len must be less than 256*hashlen
+ */
+ void expand(byte output[], size_t output_len,
+ const byte info[], size_t info_len);
+
+ std::string name() const;
+
+ void clear();
+ private:
+ std::unique_ptr<MessageAuthenticationCode> m_extractor;
+ std::unique_ptr<MessageAuthenticationCode> m_prf;
+ };
+
+}
+
+#endif
diff --git a/src/prf/hkdf/info.txt b/src/prf/hkdf/info.txt
new file mode 100644
index 000000000..fa124bca4
--- /dev/null
+++ b/src/prf/hkdf/info.txt
@@ -0,0 +1 @@
+define HKDF