Botan  2.19.1
Crypto and TLS for C++11
sp800_108.cpp
Go to the documentation of this file.
1 /*
2 * KDFs defined in NIST SP 800-108
3 * (C) 2016 Kai Michaelis
4 *
5 * Botan is released under the Simplified BSD License (see license.txt)
6 */
7 
8 #include <botan/sp800_108.h>
9 #include <botan/loadstor.h>
10 #include <botan/exceptn.h>
11 #include <iterator>
12 
13 namespace Botan {
14 
15 size_t SP800_108_Counter::kdf(uint8_t key[], size_t key_len,
16  const uint8_t secret[], size_t secret_len,
17  const uint8_t salt[], size_t salt_len,
18  const uint8_t label[], size_t label_len) const
19  {
20  const std::size_t prf_len = m_prf->output_length();
21 
22  const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
23 
24  if(blocks_required > 0xFFFFFFFF)
25  throw Invalid_Argument("SP800_108_Counter output size too large");
26 
27  const uint8_t delim = 0;
28  const uint32_t length = static_cast<uint32_t>(key_len * 8);
29 
30  uint8_t *p = key;
31  uint32_t counter = 1;
32  uint8_t be_len[4] = { 0 };
34 
35  store_be(length, be_len);
36  m_prf->set_key(secret, secret_len);
37 
38  while(p < key + key_len)
39  {
40  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
41  uint8_t be_cnt[4] = { 0 };
42 
43  store_be(counter, be_cnt);
44 
45  m_prf->update(be_cnt,4);
46  m_prf->update(label,label_len);
47  m_prf->update(delim);
48  m_prf->update(salt,salt_len);
49  m_prf->update(be_len,4);
50  m_prf->final(tmp);
51 
52  copy_mem(p, tmp.data(), to_copy);
53  p += to_copy;
54 
55  ++counter;
56  BOTAN_ASSERT(counter != 0, "No counter overflow");
57  }
58 
59  return key_len;
60  }
61 
62 size_t SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
63  const uint8_t secret[], size_t secret_len,
64  const uint8_t salt[], size_t salt_len,
65  const uint8_t label[], size_t label_len) const
66  {
67  const uint32_t length = static_cast<uint32_t>(key_len * 8);
68  const std::size_t prf_len = m_prf->output_length();
69  const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
70  const uint8_t delim = 0;
71 
72  const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
73 
74  if(blocks_required > 0xFFFFFFFF)
75  throw Invalid_Argument("SP800_108_Feedback output size too large");
76 
77  uint8_t *p = key;
78  uint32_t counter = 1;
79  uint8_t be_len[4] = { 0 };
80  secure_vector< uint8_t > prev(salt, salt + iv_len);
81  secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
82 
83  store_be(length, be_len);
84  m_prf->set_key(secret, secret_len);
85 
86  while(p < key + key_len)
87  {
88  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
89  uint8_t be_cnt[4] = { 0 };
90 
91  store_be(counter, be_cnt);
92 
93  m_prf->update(prev);
94  m_prf->update(be_cnt,4);
95  m_prf->update(label,label_len);
96  m_prf->update(delim);
97  m_prf->update(ctx);
98  m_prf->update(be_len,4);
99  m_prf->final(prev);
100 
101  copy_mem(p, prev.data(), to_copy);
102  p += to_copy;
103 
104  ++counter;
105 
106  BOTAN_ASSERT(counter != 0, "No overflow");
107  }
108 
109  return key_len;
110  }
111 
112 size_t SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
113  const uint8_t secret[], size_t secret_len,
114  const uint8_t salt[], size_t salt_len,
115  const uint8_t label[], size_t label_len) const
116  {
117  const uint32_t length = static_cast<uint32_t>(key_len * 8);
118  const std::size_t prf_len = m_prf->output_length();
119  const uint8_t delim = 0;
120 
121  const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
122 
123  if(blocks_required > 0xFFFFFFFF)
124  throw Invalid_Argument("SP800_108_Feedback output size too large");
125 
126  uint8_t *p = key;
127  uint32_t counter = 1;
128  uint8_t be_len[4] = { 0 };
129  secure_vector<uint8_t> ai, ki;
130 
131  store_be(length, be_len);
132  m_prf->set_key(secret,secret_len);
133 
134  // A(0)
135  std::copy(label,label + label_len,std::back_inserter(ai));
136  ai.emplace_back(delim);
137  std::copy(salt,salt + salt_len,std::back_inserter(ai));
138  std::copy(be_len,be_len + 4,std::back_inserter(ai));
139 
140  while(p < key + key_len)
141  {
142  // A(i)
143  m_prf->update(ai);
144  m_prf->final(ai);
145 
146  // K(i)
147  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
148  uint8_t be_cnt[4] = { 0 };
149 
150  store_be(counter, be_cnt);
151 
152  m_prf->update(ai);
153  m_prf->update(be_cnt,4);
154  m_prf->update(label, label_len);
155  m_prf->update(delim);
156  m_prf->update(salt, salt_len);
157  m_prf->update(be_len,4);
158  m_prf->final(ki);
159 
160  copy_mem(p, ki.data(), to_copy);
161  p += to_copy;
162 
163  ++counter;
164 
165  BOTAN_ASSERT(counter != 0, "No overflow");
166  }
167 
168  return key_len;
169  }
170 }
A store_be(out)
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_108.cpp:62
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
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_108.cpp:112
size_t salt_len
Definition: x509_obj.cpp:25
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
Definition: alg_id.cpp:13
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_108.cpp:15