aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/kdf/sp800_56a/sp800_56a.cpp
diff options
context:
space:
mode:
authorKrzysztof Kwiatkowski <[email protected]>2017-04-30 15:48:47 +0100
committerKrzysztof Kwiatkowski <[email protected]>2017-05-03 00:44:28 +0100
commit576ada6d0b1ae20b781d487ba9bbeaadef17b202 (patch)
treeef0122d482dd6bbb36fe6a5fa82138bc6599dcaf /src/lib/kdf/sp800_56a/sp800_56a.cpp
parent29cc6bebe132a34f882d450b35a69bf71bb3e27b (diff)
Adds KDF based on SP 800-56A. Currently it is revision 1 (alternative 1). It should be extended to revision 2.
Diffstat (limited to 'src/lib/kdf/sp800_56a/sp800_56a.cpp')
-rw-r--r--src/lib/kdf/sp800_56a/sp800_56a.cpp51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/lib/kdf/sp800_56a/sp800_56a.cpp b/src/lib/kdf/sp800_56a/sp800_56a.cpp
new file mode 100644
index 000000000..9f5c1b1c5
--- /dev/null
+++ b/src/lib/kdf/sp800_56a/sp800_56a.cpp
@@ -0,0 +1,51 @@
+/*
+* KDF defined in NIST SP 800-56a (Approved Alternative 1)
+* (C) 2017 Krzysztof Kwiatkowski
+*
+* Botan is released under the Simplified BSD License (see license.txt)
+*/
+
+#include <botan/sp800_56a.h>
+#include <botan/hmac.h>
+#include <botan/assert.h>
+#include <botan/mem_ops.h>
+
+namespace Botan {
+
+static const size_t MAX_REPS = (2ULL << 32);
+
+size_t SP800_56A::kdf( uint8_t key[], size_t key_len,
+ const uint8_t secret[], size_t secret_len,
+ const uint8_t salt[], size_t salt_len,
+ const uint8_t label[], size_t label_len) const
+{
+ // Salt is not used by this algorithm
+ BOTAN_UNUSED(salt, salt_len);
+
+ secure_vector<uint8_t> h;
+ const size_t digest_len = m_hash->output_length();
+
+ size_t reps = key_len / digest_len + !!(key_len % digest_len);
+ if (reps >= MAX_REPS) {
+ // See SP-800-56A, point 5.8.1
+ throw Invalid_Argument(
+ "key_len / digest output size "
+ "can't be bigger than 2^32 - 1");
+ }
+
+ uint32_t counter = 1;
+ for(size_t i = 0; i < reps; i++) {
+ m_hash->update_be(counter++);
+ m_hash->update(secret, secret_len);
+ m_hash->update(label, label_len);
+ m_hash->final(h);
+
+ const size_t offset = digest_len * i;
+ const size_t len = std::min(h.size(), key_len - offset);
+ copy_mem(&key[offset], h.data(), len);
+ }
+
+ return key_len;
+}
+
+}