Coverage Report

Created: 2021-04-07 06:07

/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
void 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
0
   }
59
60
void 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
0
   {
65
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
66
0
   const std::size_t prf_len =  m_prf->output_length();
67
0
   const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
68
0
   const uint8_t delim = 0;
69
70
0
   const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
71
72
0
   if(blocks_required > 0xFFFFFFFF)
73
0
      throw Invalid_Argument("SP800_108_Feedback output size too large");
74
75
0
   uint8_t *p = key;
76
0
   uint32_t counter = 1;
77
0
   uint8_t be_len[4] = { 0 };
78
0
   secure_vector< uint8_t > prev(salt, salt + iv_len);
79
0
   secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
80
81
0
   store_be(length, be_len);
82
0
   m_prf->set_key(secret, secret_len);
83
84
0
   while(p < key + key_len)
85
0
      {
86
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
87
0
      uint8_t be_cnt[4] = { 0 };
88
89
0
      store_be(counter, be_cnt);
90
91
0
      m_prf->update(prev);
92
0
      m_prf->update(be_cnt,4);
93
0
      m_prf->update(label,label_len);
94
0
      m_prf->update(delim);
95
0
      m_prf->update(ctx);
96
0
      m_prf->update(be_len,4);
97
0
      m_prf->final(prev);
98
99
0
      copy_mem(p, prev.data(), to_copy);
100
0
      p += to_copy;
101
102
0
      ++counter;
103
104
0
      BOTAN_ASSERT(counter != 0, "No overflow");
105
0
      }
106
0
   }
107
108
void 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
0
   {
113
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
114
0
   const std::size_t prf_len =  m_prf->output_length();
115
0
   const uint8_t delim = 0;
116
117
0
   const uint64_t blocks_required = (key_len + prf_len - 1) / prf_len;
118
119
0
   if(blocks_required > 0xFFFFFFFF)
120
0
      throw Invalid_Argument("SP800_108_Feedback output size too large");
121
122
0
   uint8_t *p = key;
123
0
   uint32_t counter = 1;
124
0
   uint8_t be_len[4] = { 0 };
125
0
   secure_vector<uint8_t> ai, ki;
126
127
0
   store_be(length, be_len);
128
0
   m_prf->set_key(secret,secret_len);
129
130
   // A(0)
131
0
   std::copy(label,label + label_len,std::back_inserter(ai));
132
0
   ai.emplace_back(delim);
133
0
   std::copy(salt,salt + salt_len,std::back_inserter(ai));
134
0
   std::copy(be_len,be_len + 4,std::back_inserter(ai));
135
136
0
   while(p < key + key_len)
137
0
      {
138
      // A(i)
139
0
      m_prf->update(ai);
140
0
      m_prf->final(ai);
141
142
      // K(i)
143
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
144
0
      uint8_t be_cnt[4] = { 0 };
145
146
0
      store_be(counter, be_cnt);
147
148
0
      m_prf->update(ai);
149
0
      m_prf->update(be_cnt,4);
150
0
      m_prf->update(label, label_len);
151
0
      m_prf->update(delim);
152
0
      m_prf->update(salt, salt_len);
153
0
      m_prf->update(be_len,4);
154
0
      m_prf->final(ki);
155
156
0
      copy_mem(p, ki.data(), to_copy);
157
0
      p += to_copy;
158
159
0
      ++counter;
160
161
0
      BOTAN_ASSERT(counter != 0, "No overflow");
162
0
      }
163
0
   }
164
}