Botan  2.12.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  const uint8_t delim = 0;
22  const uint32_t length = static_cast<uint32_t>(key_len * 8);
23 
24  uint8_t *p = key;
25  uint32_t counter = 1;
26  uint8_t be_len[4] = { 0 };
28 
29  store_be(length, be_len);
30  m_prf->set_key(secret, secret_len);
31 
32  while(p < key + key_len && counter != 0)
33  {
34  const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
35  uint8_t be_cnt[4] = { 0 };
36 
37  store_be(counter, be_cnt);
38 
39  m_prf->update(be_cnt,4);
40  m_prf->update(label,label_len);
41  m_prf->update(delim);
42  m_prf->update(salt,salt_len);
43  m_prf->update(be_len,4);
44  m_prf->final(tmp);
45 
46  copy_mem(p, tmp.data(), to_copy);
47  p += to_copy;
48 
49  ++counter;
50  if(counter == 0)
51  throw Invalid_Argument("Can't process more than 4GB");
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 uint32_t length = static_cast<uint32_t>(key_len * 8);
63  const std::size_t prf_len = m_prf->output_length();
64  const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
65  const uint8_t delim = 0;
66 
67  uint8_t *p = key;
68  uint32_t counter = 1;
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  copy_mem(p, prev.data(), to_copy);
92  p += to_copy;
93 
94  ++counter;
95 
96  if(counter == 0)
97  throw Invalid_Argument("Can't process more than 4GB");
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 uint32_t length = static_cast<uint32_t>(key_len * 8);
109  const std::size_t prf_len = m_prf->output_length();
110  const uint8_t delim = 0;
111 
112  uint8_t *p = key;
113  uint32_t counter = 1;
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  copy_mem(p, ki.data(), to_copy);
147  p += to_copy;
148 
149  ++counter;
150 
151  if(counter == 0)
152  throw Invalid_Argument("Can't process more than 4GB");
153  }
154 
155  return key_len;
156  }
157 }
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
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
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
size_t salt_len
Definition: x509_obj.cpp:25
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:122
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
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65