Coverage Report

Created: 2020-11-21 08:34

/src/botan/src/lib/kdf/sp800_108/sp800_108.cpp
Line
Count
Source (jump to first uncovered line)
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
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
0
   {
20
0
   const std::size_t prf_len =  m_prf->output_length();
21
22
0
   const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
23
24
0
   if(blocks_required > 0xFFFFFFFF)
25
0
      throw Invalid_Argument("SP800_108_Counter output size too large");
26
27
0
   const uint8_t delim = 0;
28
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
29
30
0
   uint8_t *p = key;
31
0
   uint32_t counter = 1;
32
0
   uint8_t be_len[4] = { 0 };
33
0
   secure_vector<uint8_t> tmp;
34
35
0
   store_be(length, be_len);
36
0
   m_prf->set_key(secret, secret_len);
37
38
0
   while(p < key + key_len)
39
0
      {
40
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
41
0
      uint8_t be_cnt[4] = { 0 };
42
43
0
      store_be(counter, be_cnt);
44
45
0
      m_prf->update(be_cnt,4);
46
0
      m_prf->update(label,label_len);
47
0
      m_prf->update(delim);
48
0
      m_prf->update(salt,salt_len);
49
0
      m_prf->update(be_len,4);
50
0
      m_prf->final(tmp);
51
52
0
      copy_mem(p, tmp.data(), to_copy);
53
0
      p += to_copy;
54
55
0
      ++counter;
56
0
      BOTAN_ASSERT(counter != 0, "No counter overflow");
57
0
      }
58
59
0
   return key_len;
60
0
   }
61
62
size_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
0
   {
67
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
68
0
   const std::size_t prf_len =  m_prf->output_length();
69
0
   const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
70
0
   const uint8_t delim = 0;
71
72
0
   const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
73
74
0
   if(blocks_required > 0xFFFFFFFF)
75
0
      throw Invalid_Argument("SP800_108_Feedback output size too large");
76
77
0
   uint8_t *p = key;
78
0
   uint32_t counter = 1;
79
0
   uint8_t be_len[4] = { 0 };
80
0
   secure_vector< uint8_t > prev(salt, salt + iv_len);
81
0
   secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
82
83
0
   store_be(length, be_len);
84
0
   m_prf->set_key(secret, secret_len);
85
86
0
   while(p < key + key_len)
87
0
      {
88
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
89
0
      uint8_t be_cnt[4] = { 0 };
90
91
0
      store_be(counter, be_cnt);
92
93
0
      m_prf->update(prev);
94
0
      m_prf->update(be_cnt,4);
95
0
      m_prf->update(label,label_len);
96
0
      m_prf->update(delim);
97
0
      m_prf->update(ctx);
98
0
      m_prf->update(be_len,4);
99
0
      m_prf->final(prev);
100
101
0
      copy_mem(p, prev.data(), to_copy);
102
0
      p += to_copy;
103
104
0
      ++counter;
105
106
0
      BOTAN_ASSERT(counter != 0, "No overflow");
107
0
      }
108
109
0
   return key_len;
110
0
   }
111
112
size_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
0
   {
117
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
118
0
   const std::size_t prf_len =  m_prf->output_length();
119
0
   const uint8_t delim = 0;
120
121
0
   const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
122
123
0
   if(blocks_required > 0xFFFFFFFF)
124
0
      throw Invalid_Argument("SP800_108_Feedback output size too large");
125
126
0
   uint8_t *p = key;
127
0
   uint32_t counter = 1;
128
0
   uint8_t be_len[4] = { 0 };
129
0
   secure_vector<uint8_t> ai, ki;
130
131
0
   store_be(length, be_len);
132
0
   m_prf->set_key(secret,secret_len);
133
134
   // A(0)
135
0
   std::copy(label,label + label_len,std::back_inserter(ai));
136
0
   ai.emplace_back(delim);
137
0
   std::copy(salt,salt + salt_len,std::back_inserter(ai));
138
0
   std::copy(be_len,be_len + 4,std::back_inserter(ai));
139
140
0
   while(p < key + key_len)
141
0
      {
142
      // A(i)
143
0
      m_prf->update(ai);
144
0
      m_prf->final(ai);
145
146
      // K(i)
147
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
148
0
      uint8_t be_cnt[4] = { 0 };
149
150
0
      store_be(counter, be_cnt);
151
152
0
      m_prf->update(ai);
153
0
      m_prf->update(be_cnt,4);
154
0
      m_prf->update(label, label_len);
155
0
      m_prf->update(delim);
156
0
      m_prf->update(salt, salt_len);
157
0
      m_prf->update(be_len,4);
158
0
      m_prf->final(ki);
159
160
0
      copy_mem(p, ki.data(), to_copy);
161
0
      p += to_copy;
162
163
0
      ++counter;
164
165
0
      BOTAN_ASSERT(counter != 0, "No overflow");
166
0
      }
167
168
0
   return key_len;
169
0
   }
170
}