Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

sp800_56a.cpp
Go to the documentation of this file.
1 /*
2 * KDF defined in NIST SP 800-56a (Approved Alternative 1)
3 *
4 * (C) 2017 Ribose Inc. Written by Krzysztof Kwiatkowski.
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8
9 #include <botan/sp800_56a.h>
10 #include <botan/scan_name.h>
11 #include <botan/exceptn.h>
12
13 namespace Botan {
14
15 namespace {
16
17 template<class AuxiliaryFunction_t>
18 size_t SP800_56A_kdf(
19 AuxiliaryFunction_t& auxfunc,
20 uint8_t key[], size_t key_len,
21 const uint8_t secret[], size_t secret_len,
22 const uint8_t label[], size_t label_len)
23 {
24 const uint64_t kRepsUpperBound = (1ULL << 32);
25
26 const size_t digest_len = auxfunc.output_length();
27
28 const size_t reps = key_len / digest_len + ((key_len % digest_len) ? 1 : 0);
29
30 if (reps >= kRepsUpperBound)
31 {
32 // See SP-800-56A, point 5.8.1
33 throw Invalid_Argument("SP800-56A KDF requested output too large");
34 }
35
36 uint32_t counter = 1;
37 secure_vector<uint8_t> result;
38 for(size_t i = 0; i < reps; i++)
39 {
40 auxfunc.update_be(counter++);
41 auxfunc.update(secret, secret_len);
42 auxfunc.update(label, label_len);
43 auxfunc.final(result);
44
45 const size_t offset = digest_len * i;
46 const size_t len = std::min(result.size(), key_len - offset);
47 copy_mem(&key[offset], result.data(), len);
48 }
49
50 return key_len;
51 }
52
53 }
54
55 size_t SP800_56A_Hash::kdf(uint8_t key[], size_t key_len,
56 const uint8_t secret[], size_t secret_len,
57 const uint8_t salt[], size_t salt_len,
58 const uint8_t label[], size_t label_len) const
59 {
60 /*
61 * TODO: should we reject a non-empty salt with an exception?
62 * Ignoring the salt seems quite dangerous to applications which
63 * don't expect it.
64 */
65 BOTAN_UNUSED(salt, salt_len);
66
67 return SP800_56A_kdf(*m_hash, key, key_len, secret, secret_len, label, label_len);
68 }
69
70 SP800_56A_HMAC::SP800_56A_HMAC(MessageAuthenticationCode* mac) : m_mac(mac)
71 {
72 // TODO: we need a MessageAuthenticationCode::is_hmac
73 const SCAN_Name req(m_mac->name());
74 if(req.algo_name() != "HMAC")
75 {
76 throw Algorithm_Not_Found("Only HMAC can be used with KDF SP800-56A");
77 }
78 }
79
80 size_t SP800_56A_HMAC::kdf(uint8_t key[], size_t key_len,
81 const uint8_t secret[], size_t secret_len,
82 const uint8_t salt[], size_t salt_len,
83 const uint8_t label[], size_t label_len) const
84 {
85 /*
86 * SP 800-56A specifies if the salt is empty then a block of zeros
87 * equal to the hash's underlying block size are used. However this
88 * is equivalent to setting a zero-length key, so the same call
89 * works for either case.
90 */
91 m_mac->set_key(salt, salt_len);
92
93 return SP800_56A_kdf(*m_mac, key, key_len, secret, secret_len, label, label_len);
94 }
95
96
97
98 }
Botan::MessageAuthenticationCode
Definition: mac.h:21
Botan::SP800_56A_Hash::kdf
size_t 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 override
Definition: sp800_56a.cpp:55
salt_len
size_t salt_len
Definition: x509_obj.cpp:25
Botan::copy_mem
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:132
Botan
Definition: alg_id.cpp:13
BOTAN_UNUSED
#define BOTAN_UNUSED(...)
Definition: assert.h:142
Botan::SCAN_Name
Definition: scan_name.h:23
Botan::SP800_56A_HMAC::SP800_56A_HMAC
SP800_56A_HMAC(MessageAuthenticationCode *mac)
Definition: sp800_56a.cpp:70
Botan::SP800_56A_HMAC::kdf
size_t 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 override
Definition: sp800_56a.cpp:80
Botan::Algorithm_Not_Found
Definition: exceptn.h:265