Coverage Report

Created: 2020-02-14 15:38

/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/sp800_108.h>
9
#include <botan/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
0
   const uint8_t delim = 0;
22
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
23
0
24
0
   uint8_t *p = key;
25
0
   uint32_t counter = 1;
26
0
   uint8_t be_len[4] = { 0 };
27
0
   secure_vector<uint8_t> tmp;
28
0
29
0
   store_be(length, be_len);
30
0
   m_prf->set_key(secret, secret_len);
31
0
32
0
   while(p < key + key_len && counter != 0)
33
0
      {
34
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
35
0
      uint8_t be_cnt[4] = { 0 };
36
0
37
0
      store_be(counter, be_cnt);
38
0
39
0
      m_prf->update(be_cnt,4);
40
0
      m_prf->update(label,label_len);
41
0
      m_prf->update(delim);
42
0
      m_prf->update(salt,salt_len);
43
0
      m_prf->update(be_len,4);
44
0
      m_prf->final(tmp);
45
0
46
0
      copy_mem(p, tmp.data(), to_copy);
47
0
      p += to_copy;
48
0
49
0
      ++counter;
50
0
      if(counter == 0)
51
0
         throw Invalid_Argument("Can't process more than 4GB");
52
0
      }
53
0
54
0
   return key_len;
55
0
   }
56
57
size_t SP800_108_Feedback::kdf(uint8_t key[], size_t key_len,
58
                               const uint8_t secret[], size_t secret_len,
59
                               const uint8_t salt[], size_t salt_len,
60
                               const uint8_t label[], size_t label_len) const
61
0
   {
62
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
63
0
   const std::size_t prf_len =  m_prf->output_length();
64
0
   const std::size_t iv_len = (salt_len >= prf_len ? prf_len : 0);
65
0
   const uint8_t delim = 0;
66
0
67
0
   uint8_t *p = key;
68
0
   uint32_t counter = 1;
69
0
   uint8_t be_len[4] = { 0 };
70
0
   secure_vector< uint8_t > prev(salt, salt + iv_len);
71
0
   secure_vector< uint8_t > ctx(salt + iv_len, salt + salt_len);
72
0
73
0
   store_be(length, be_len);
74
0
   m_prf->set_key(secret, secret_len);
75
0
76
0
   while(p < key + key_len && counter != 0)
77
0
      {
78
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
79
0
      uint8_t be_cnt[4] = { 0 };
80
0
81
0
      store_be(counter, be_cnt);
82
0
83
0
      m_prf->update(prev);
84
0
      m_prf->update(be_cnt,4);
85
0
      m_prf->update(label,label_len);
86
0
      m_prf->update(delim);
87
0
      m_prf->update(ctx);
88
0
      m_prf->update(be_len,4);
89
0
      m_prf->final(prev);
90
0
91
0
      copy_mem(p, prev.data(), to_copy);
92
0
      p += to_copy;
93
0
94
0
      ++counter;
95
0
96
0
      if(counter == 0)
97
0
         throw Invalid_Argument("Can't process more than 4GB");
98
0
      }
99
0
100
0
   return key_len;
101
0
   }
102
103
size_t SP800_108_Pipeline::kdf(uint8_t key[], size_t key_len,
104
                               const uint8_t secret[], size_t secret_len,
105
                               const uint8_t salt[], size_t salt_len,
106
                               const uint8_t label[], size_t label_len) const
107
0
   {
108
0
   const uint32_t length = static_cast<uint32_t>(key_len * 8);
109
0
   const std::size_t prf_len =  m_prf->output_length();
110
0
   const uint8_t delim = 0;
111
0
112
0
   uint8_t *p = key;
113
0
   uint32_t counter = 1;
114
0
   uint8_t be_len[4] = { 0 };
115
0
   secure_vector<uint8_t> ai, ki;
116
0
117
0
   store_be(length, be_len);
118
0
   m_prf->set_key(secret,secret_len);
119
0
120
0
   // A(0)
121
0
   std::copy(label,label + label_len,std::back_inserter(ai));
122
0
   ai.emplace_back(delim);
123
0
   std::copy(salt,salt + salt_len,std::back_inserter(ai));
124
0
   std::copy(be_len,be_len + 4,std::back_inserter(ai));
125
0
126
0
   while(p < key + key_len && counter != 0)
127
0
      {
128
0
      // A(i)
129
0
      m_prf->update(ai);
130
0
      m_prf->final(ai);
131
0
132
0
      // K(i)
133
0
      const std::size_t to_copy = std::min< std::size_t >(key + key_len - p, prf_len);
134
0
      uint8_t be_cnt[4] = { 0 };
135
0
136
0
      store_be(counter, be_cnt);
137
0
138
0
      m_prf->update(ai);
139
0
      m_prf->update(be_cnt,4);
140
0
      m_prf->update(label, label_len);
141
0
      m_prf->update(delim);
142
0
      m_prf->update(salt, salt_len);
143
0
      m_prf->update(be_len,4);
144
0
      m_prf->final(ki);
145
0
146
0
      copy_mem(p, ki.data(), to_copy);
147
0
      p += to_copy;
148
0
149
0
      ++counter;
150
0
151
0
      if(counter == 0)
152
0
         throw Invalid_Argument("Can't process more than 4GB");
153
0
      }
154
0
155
0
   return key_len;
156
0
   }
157
}