Botan 3.4.0
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/internal/sp800_108.h>
9
10#include <botan/exceptn.h>
11#include <botan/internal/fmt.h>
12#include <botan/internal/loadstor.h>
13#include <iterator>
14
15namespace Botan {
16
17std::string SP800_108_Counter::name() const {
18 return fmt("SP800-108-Counter({})", m_prf->name());
19}
20
21std::unique_ptr<KDF> SP800_108_Counter::new_object() const {
22 return std::make_unique<SP800_108_Counter>(m_prf->new_object());
23}
24
25void SP800_108_Counter::kdf(uint8_t key[],
26 size_t key_len,
27 const uint8_t secret[],
28 size_t secret_len,
29 const uint8_t salt[],
30 size_t salt_len,
31 const uint8_t label[],
32 size_t label_len) const {
33 const std::size_t prf_len = m_prf->output_length();
34
35 const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
36
37 if(blocks_required > 0xFFFFFFFF) {
38 throw Invalid_Argument("SP800_108_Counter output size too large");
39 }
40
41 const uint8_t delim = 0;
42 const uint32_t length = static_cast<uint32_t>(key_len * 8);
43
44 uint8_t* p = key;
45 uint32_t counter = 1;
46 uint8_t be_len[4] = {0};
48
49 store_be(length, be_len);
50 m_prf->set_key(secret, secret_len);
51
52 while(p < key + key_len) {
53 const std::size_t to_copy = std::min<std::size_t>(key + key_len - p, prf_len);
54 uint8_t be_cnt[4] = {0};
55
56 store_be(counter, be_cnt);
57
58 m_prf->update(be_cnt, 4);
59 m_prf->update(label, label_len);
60 m_prf->update(delim);
61 m_prf->update(salt, salt_len);
62 m_prf->update(be_len, 4);
63 m_prf->final(tmp);
64
65 copy_mem(p, tmp.data(), to_copy);
66 p += to_copy;
67
68 ++counter;
69 BOTAN_ASSERT(counter != 0, "No counter overflow");
70 }
71}
72
73std::string SP800_108_Feedback::name() const {
74 return fmt("SP800-108-Feedback({})", m_prf->name());
75}
76
77std::unique_ptr<KDF> SP800_108_Feedback::new_object() const {
78 return std::make_unique<SP800_108_Feedback>(m_prf->new_object());
79}
80
81void SP800_108_Feedback::kdf(uint8_t key[],
82 size_t key_len,
83 const uint8_t secret[],
84 size_t secret_len,
85 const uint8_t salt[],
86 size_t salt_len,
87 const uint8_t label[],
88 size_t label_len) const {
89 const uint32_t length = static_cast<uint32_t>(key_len * 8);
90 const std::size_t prf_len = m_prf->output_length();
91 const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
92 const uint8_t delim = 0;
93
94 const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
95
96 if(blocks_required > 0xFFFFFFFF) {
97 throw Invalid_Argument("SP800_108_Feedback output size too large");
98 }
99
100 uint8_t* p = key;
101 uint32_t counter = 1;
102 uint8_t be_len[4] = {0};
103 secure_vector<uint8_t> prev(salt, salt + iv_len);
104 secure_vector<uint8_t> ctx(salt + iv_len, salt + salt_len);
105
106 store_be(length, be_len);
107 m_prf->set_key(secret, secret_len);
108
109 while(p < key + key_len) {
110 const std::size_t to_copy = std::min<std::size_t>(key + key_len - p, prf_len);
111 uint8_t be_cnt[4] = {0};
112
113 store_be(counter, be_cnt);
114
115 m_prf->update(prev);
116 m_prf->update(be_cnt, 4);
117 m_prf->update(label, label_len);
118 m_prf->update(delim);
119 m_prf->update(ctx);
120 m_prf->update(be_len, 4);
121 m_prf->final(prev);
122
123 copy_mem(p, prev.data(), to_copy);
124 p += to_copy;
125
126 ++counter;
127
128 BOTAN_ASSERT(counter != 0, "No overflow");
129 }
130}
131
132std::string SP800_108_Pipeline::name() const {
133 return fmt("SP800-108-Pipeline({})", m_prf->name());
134}
135
136std::unique_ptr<KDF> SP800_108_Pipeline::new_object() const {
137 return std::make_unique<SP800_108_Pipeline>(m_prf->new_object());
138}
139
140void SP800_108_Pipeline::kdf(uint8_t key[],
141 size_t key_len,
142 const uint8_t secret[],
143 size_t secret_len,
144 const uint8_t salt[],
145 size_t salt_len,
146 const uint8_t label[],
147 size_t label_len) const {
148 const uint32_t length = static_cast<uint32_t>(key_len * 8);
149 const std::size_t prf_len = m_prf->output_length();
150 const uint8_t delim = 0;
151
152 const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
153
154 if(blocks_required > 0xFFFFFFFF) {
155 throw Invalid_Argument("SP800_108_Feedback output size too large");
156 }
157
158 uint8_t* p = key;
159 uint32_t counter = 1;
160 uint8_t be_len[4] = {0};
162
163 store_be(length, be_len);
164 m_prf->set_key(secret, secret_len);
165
166 // A(0)
167 std::copy(label, label + label_len, std::back_inserter(ai));
168 ai.emplace_back(delim);
169 std::copy(salt, salt + salt_len, std::back_inserter(ai));
170 std::copy(be_len, be_len + 4, std::back_inserter(ai));
171
172 while(p < key + key_len) {
173 // A(i)
174 m_prf->update(ai);
175 m_prf->final(ai);
176
177 // K(i)
178 const std::size_t to_copy = std::min<std::size_t>(key + key_len - p, prf_len);
179 uint8_t be_cnt[4] = {0};
180
181 store_be(counter, be_cnt);
182
183 m_prf->update(ai);
184 m_prf->update(be_cnt, 4);
185 m_prf->update(label, label_len);
186 m_prf->update(delim);
187 m_prf->update(salt, salt_len);
188 m_prf->update(be_len, 4);
189 m_prf->final(ki);
190
191 copy_mem(p, ki.data(), to_copy);
192 p += to_copy;
193
194 ++counter;
195
196 BOTAN_ASSERT(counter != 0, "No overflow");
197 }
198}
199} // namespace Botan
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:50
void 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:25
std::string name() const override
Definition sp800_108.cpp:17
std::unique_ptr< KDF > new_object() const override
Definition sp800_108.cpp:21
std::string name() const override
Definition sp800_108.cpp:73
void 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:81
std::unique_ptr< KDF > new_object() const override
Definition sp800_108.cpp:77
std::unique_ptr< KDF > new_object() const override
std::string name() const override
void 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
std::string fmt(std::string_view format, const T &... args)
Definition fmt.h:53
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:61
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition mem_ops.h:146
constexpr auto store_be(ParamTs &&... params)
Definition loadstor.h:711