Botan  2.6.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 
10 #include <iterator>
11 
12 namespace Botan {
13 
14 size_t SP800_108_Counter::kdf(uint8_t key[], size_t key_len,
15  const uint8_t secret[], size_t secret_len,
16  const uint8_t salt[], size_t salt_len,
17  const uint8_t label[], size_t label_len) const
18  {
19  const std::size_t prf_len = m_prf->output_length();
20  const uint8_t delim = 0;
21  const uint32_t length = static_cast<uint32_t>(key_len * 8);
22 
23  uint8_t *p = key;
24  uint32_t counter = 1;
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  copy_mem(p, tmp.data(), to_copy);
46  p += to_copy;
47 
48  ++counter;
49  if(counter == 0)
50  throw Invalid_Argument("Can't process more than 4GB");
51  }
52 
53  return key_len;
54  }
55 
56 size_t SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
57  const uint8_t secret[], size_t secret_len,
58  const uint8_t salt[], size_t salt_len,
59  const uint8_t label[], size_t label_len) const
60  {
61  const uint32_t length = static_cast<uint32_t>(key_len * 8);
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  uint8_t be_len[4] = { 0 };
69  secure_vector< uint8_t > prev(salt, salt + iv_len);
70  secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
71 
72  store_be(length, be_len);
73  m_prf->set_key(secret, secret_len);
74 
75  while(p < key + key_len && counter != 0)
76  {
77  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
78  uint8_t be_cnt[4] = { 0 };
79 
80  store_be(counter, be_cnt);
81 
82  m_prf->update(prev);
83  m_prf->update(be_cnt,4);
84  m_prf->update(label,label_len);
85  m_prf->update(delim);
86  m_prf->update(ctx);
87  m_prf->update(be_len,4);
88  m_prf->final(prev);
89 
90  copy_mem(p, prev.data(), to_copy);
91  p += to_copy;
92 
93  ++counter;
94 
95  if(counter == 0)
96  throw Invalid_Argument("Can't process more than 4GB");
97  }
98 
99  return key_len;
100  }
101 
102 size_t SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
103  const uint8_t secret[], size_t secret_len,
104  const uint8_t salt[], size_t salt_len,
105  const uint8_t label[], size_t label_len) const
106  {
107  const uint32_t length = static_cast<uint32_t>(key_len * 8);
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  uint8_t be_len[4] = { 0 };
114  secure_vector<uint8_t> ai, ki;
115 
116  store_be(length, be_len);
117  m_prf->set_key(secret,secret_len);
118 
119  // A(0)
120  std::copy(label,label + label_len,std::back_inserter(ai));
121  ai.emplace_back(delim);
122  std::copy(salt,salt + salt_len,std::back_inserter(ai));
123  std::copy(be_len,be_len + 4,std::back_inserter(ai));
124 
125  while(p < key + key_len && counter != 0)
126  {
127  // A(i)
128  m_prf->update(ai);
129  m_prf->final(ai);
130 
131  // K(i)
132  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
133  uint8_t be_cnt[4] = { 0 };
134 
135  store_be(counter, be_cnt);
136 
137  m_prf->update(ai);
138  m_prf->update(be_cnt,4);
139  m_prf->update(label, label_len);
140  m_prf->update(delim);
141  m_prf->update(salt, salt_len);
142  m_prf->update(be_len,4);
143  m_prf->final(ki);
144 
145  copy_mem(p, ki.data(), to_copy);
146  p += to_copy;
147 
148  ++counter;
149 
150  if(counter == 0)
151  throw Invalid_Argument("Can't process more than 4GB");
152  }
153 
154  return key_len;
155  }
156 }
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:434
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:56
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:102
size_t salt_len
Definition: x509_obj.cpp:26
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:108
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:14
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88