Botan  2.1.0
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/hmac.h>
10 
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  const uint8_t delim = 0;
22  uint8_t *p = key;
23  uint32_t counter = 1;
24  uint32_t length = key_len * 8;
25  uint8_t be_len[4] = { 0 };
27 
28  store_be(length, be_len);
29  m_prf->set_key(secret, secret_len);
30 
31  while(p < key + key_len && counter != 0)
32  {
33  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
34  uint8_t be_cnt[4] = { 0 };
35 
36  store_be(counter, be_cnt);
37 
38  m_prf->update(be_cnt,4);
39  m_prf->update(label,label_len);
40  m_prf->update(delim);
41  m_prf->update(salt,salt_len);
42  m_prf->update(be_len,4);
43  m_prf->final(tmp);
44 
45  std::move(tmp.begin(), tmp.begin() + to_copy, p);
46  ++counter;
47 
48  if (counter == 0)
49  throw Invalid_Argument("Can't process more than 4GB");
50 
51  p += to_copy;
52  }
53 
54  return key_len;
55  }
56 
57 size_t SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
58  const uint8_t secret[], size_t secret_len,
59  const uint8_t salt[], size_t salt_len,
60  const uint8_t label[], size_t label_len) const
61  {
62  const std::size_t prf_len = m_prf->output_length();
63  const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
64  const uint8_t delim = 0;
65 
66  uint8_t *p = key;
67  uint32_t counter = 1;
68  uint32_t length = key_len * 8;
69  uint8_t be_len[4] = { 0 };
70  secure_vector< uint8_t > prev(salt, salt + iv_len);
71  secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
72 
73  store_be(length, be_len);
74  m_prf->set_key(secret, secret_len);
75 
76  while(p < key + key_len && counter != 0)
77  {
78  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
79  uint8_t be_cnt[4] = { 0 };
80 
81  store_be(counter, be_cnt);
82 
83  m_prf->update(prev);
84  m_prf->update(be_cnt,4);
85  m_prf->update(label,label_len);
86  m_prf->update(delim);
87  m_prf->update(ctx);
88  m_prf->update(be_len,4);
89  m_prf->final(prev);
90 
91  std::copy(prev.begin(), prev.begin() + to_copy, p);
92  ++counter;
93 
94  if (counter == 0)
95  throw Invalid_Argument("Can't process more than 4GB");
96 
97  p += to_copy;
98  }
99 
100  return key_len;
101  }
102 
103 size_t SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
104  const uint8_t secret[], size_t secret_len,
105  const uint8_t salt[], size_t salt_len,
106  const uint8_t label[], size_t label_len) const
107  {
108  const std::size_t prf_len = m_prf->output_length();
109  const uint8_t delim = 0;
110 
111  uint8_t *p = key;
112  uint32_t counter = 1;
113  uint32_t length = key_len * 8;
114  uint8_t be_len[4] = { 0 };
115  secure_vector<uint8_t> ai, ki;
116 
117  store_be(length, be_len);
118  m_prf->set_key(secret,secret_len);
119 
120  // A(0)
121  std::copy(label,label + label_len,std::back_inserter(ai));
122  ai.emplace_back(delim);
123  std::copy(salt,salt + salt_len,std::back_inserter(ai));
124  std::copy(be_len,be_len + 4,std::back_inserter(ai));
125 
126  while(p < key + key_len && counter != 0)
127  {
128  // A(i)
129  m_prf->update(ai);
130  m_prf->final(ai);
131 
132  // K(i)
133  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
134  uint8_t be_cnt[4] = { 0 };
135 
136  store_be(counter, be_cnt);
137 
138  m_prf->update(ai);
139  m_prf->update(be_cnt,4);
140  m_prf->update(label, label_len);
141  m_prf->update(delim);
142  m_prf->update(salt, salt_len);
143  m_prf->update(be_len,4);
144  m_prf->final(ki);
145 
146  std::copy(ki.begin(), ki.begin() + to_copy, p);
147  ++counter;
148 
149  if (counter == 0)
150  throw Invalid_Argument("Can't process more than 4GB");
151 
152  p += to_copy;
153  }
154 
155  return key_len;
156  }
157 }
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:441
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:57
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
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:103
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