Botan 3.0.0-alpha0
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#include <botan/internal/loadstor.h>
10#include <botan/exceptn.h>
11#include <iterator>
12
13namespace Botan {
14
15void 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
60void SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
61 const uint8_t secret[], size_t secret_len,
62 const uint8_t salt[], size_t salt_len,
63 const uint8_t label[], size_t label_len) const
64 {
65 const uint32_t length = static_cast<uint32_t>(key_len * 8);
66 const std::size_t prf_len = m_prf->output_length();
67 const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
68 const uint8_t delim = 0;
69
70 const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
71
72 if(blocks_required > 0xFFFFFFFF)
73 throw Invalid_Argument("SP800_108_Feedback output size too large");
74
75 uint8_t *p = key;
76 uint32_t counter = 1;
77 uint8_t be_len[4] = { 0 };
78 secure_vector< uint8_t > prev(salt, salt + iv_len);
79 secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
80
81 store_be(length, be_len);
82 m_prf->set_key(secret, secret_len);
83
84 while(p < key + key_len)
85 {
86 const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
87 uint8_t be_cnt[4] = { 0 };
88
89 store_be(counter, be_cnt);
90
91 m_prf->update(prev);
92 m_prf->update(be_cnt,4);
93 m_prf->update(label,label_len);
94 m_prf->update(delim);
95 m_prf->update(ctx);
96 m_prf->update(be_len,4);
97 m_prf->final(prev);
98
99 copy_mem(p, prev.data(), to_copy);
100 p += to_copy;
101
102 ++counter;
103
104 BOTAN_ASSERT(counter != 0, "No overflow");
105 }
106 }
107
108void SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
109 const uint8_t secret[], size_t secret_len,
110 const uint8_t salt[], size_t salt_len,
111 const uint8_t label[], size_t label_len) const
112 {
113 const uint32_t length = static_cast<uint32_t>(key_len * 8);
114 const std::size_t prf_len = m_prf->output_length();
115 const uint8_t delim = 0;
116
117 const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
118
119 if(blocks_required > 0xFFFFFFFF)
120 throw Invalid_Argument("SP800_108_Feedback output size too large");
121
122 uint8_t *p = key;
123 uint32_t counter = 1;
124 uint8_t be_len[4] = { 0 };
126
127 store_be(length, be_len);
128 m_prf->set_key(secret,secret_len);
129
130 // A(0)
131 std::copy(label,label + label_len,std::back_inserter(ai));
132 ai.emplace_back(delim);
133 std::copy(salt,salt + salt_len,std::back_inserter(ai));
134 std::copy(be_len,be_len + 4,std::back_inserter(ai));
135
136 while(p < key + key_len)
137 {
138 // A(i)
139 m_prf->update(ai);
140 m_prf->final(ai);
141
142 // K(i)
143 const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
144 uint8_t be_cnt[4] = { 0 };
145
146 store_be(counter, be_cnt);
147
148 m_prf->update(ai);
149 m_prf->update(be_cnt,4);
150 m_prf->update(label, label_len);
151 m_prf->update(delim);
152 m_prf->update(salt, salt_len);
153 m_prf->update(be_len,4);
154 m_prf->final(ki);
155
156 copy_mem(p, ki.data(), to_copy);
157 p += to_copy;
158
159 ++counter;
160
161 BOTAN_ASSERT(counter != 0, "No overflow");
162 }
163 }
164}
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:54
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:15
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:60
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:108
Definition: alg_id.cpp:13
constexpr void copy_mem(T *out, const T *in, size_t n)
Definition: mem_ops.h:126
constexpr void store_be(uint16_t in, uint8_t out[2])
Definition: loadstor.h:449
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65
size_t salt_len
Definition: x509_obj.cpp:25