Botan 2.19.2
Crypto and TLS for C&
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
13namespace Botan {
14
15size_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
62size_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
112size_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 };
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}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
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
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
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
Definition: alg_id.cpp:13
void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:438
void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:133
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
size_t salt_len
Definition: x509_obj.cpp:25