Botan  2.19.1
Crypto and TLS for C++11
siv.cpp
Go to the documentation of this file.
1 /*
2 * SIV Mode Encryption
3 * (C) 2013,2017 Jack Lloyd
4 * (C) 2016 Daniel Neus, Rohde & Schwarz Cybersecurity
5 *
6 * Botan is released under the Simplified BSD License (see license.txt)
7 */
8 
9 #include <botan/siv.h>
10 #include <botan/block_cipher.h>
11 #include <botan/cmac.h>
12 #include <botan/internal/poly_dbl.h>
13 #include <botan/ctr.h>
14 
15 namespace Botan {
16 
18  m_name(cipher->name() + "/SIV"),
19  m_ctr(new CTR_BE(cipher->clone(), 8)),
20  m_mac(new CMAC(cipher)),
21  m_bs(cipher->block_size())
22  {
23  // Not really true but only 128 bit allowed at the moment
24  if(m_bs != 16)
25  throw Invalid_Argument("SIV requires a 128 bit block cipher");
26  }
27 
29  {
30  // for ~unique_ptr
31  }
32 
34  {
35  m_ctr->clear();
36  m_mac->clear();
37  reset();
38  }
39 
41  {
42  m_nonce.clear();
43  m_msg_buf.clear();
44  m_ad_macs.clear();
45  }
46 
47 std::string SIV_Mode::name() const
48  {
49  return m_name;
50  }
51 
52 bool SIV_Mode::valid_nonce_length(size_t) const
53  {
54  return true;
55  }
56 
58  {
59  /*
60  This value does not particularly matter as regardless SIV_Mode::update
61  buffers all input, so in theory this could be 1. However as for instance
62  Transform_Filter creates update_granularity() uint8_t buffers, use a
63  somewhat large size to avoid bouncing on a tiny buffer.
64  */
65  return 128;
66  }
67 
69  {
70  return m_mac->key_spec().multiple(2);
71  }
72 
73 void SIV_Mode::key_schedule(const uint8_t key[], size_t length)
74  {
75  const size_t keylen = length / 2;
76  m_mac->set_key(key, keylen);
77  m_ctr->set_key(key + keylen, keylen);
78  m_ad_macs.clear();
79  }
80 
82  {
83  return block_size() * 8 - 2;
84  }
85 
86 void SIV_Mode::set_associated_data_n(size_t n, const uint8_t ad[], size_t length)
87  {
88  const size_t max_ads = maximum_associated_data_inputs();
89  if(n > max_ads)
90  throw Invalid_Argument(name() + " allows no more than " + std::to_string(max_ads) + " ADs");
91 
92  if(n >= m_ad_macs.size())
93  m_ad_macs.resize(n+1);
94 
95  m_ad_macs[n] = m_mac->process(ad, length);
96  }
97 
98 void SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
99  {
100  if(!valid_nonce_length(nonce_len))
101  throw Invalid_IV_Length(name(), nonce_len);
102 
103  if(nonce_len)
104  m_nonce = m_mac->process(nonce, nonce_len);
105  else
106  m_nonce.clear();
107 
108  m_msg_buf.clear();
109  }
110 
111 size_t SIV_Mode::process(uint8_t buf[], size_t sz)
112  {
113  // all output is saved for processing in finish
114  m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
115  return 0;
116  }
117 
118 secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
119  {
120  const std::vector<uint8_t> zeros(block_size());
121 
122  secure_vector<uint8_t> V = m_mac->process(zeros.data(), zeros.size());
123 
124  for(size_t i = 0; i != m_ad_macs.size(); ++i)
125  {
126  poly_double_n(V.data(), V.size());
127  V ^= m_ad_macs[i];
128  }
129 
130  if(m_nonce.size())
131  {
132  poly_double_n(V.data(), V.size());
133  V ^= m_nonce;
134  }
135 
136  if(text_len < block_size())
137  {
138  poly_double_n(V.data(), V.size());
139  xor_buf(V.data(), text, text_len);
140  V[text_len] ^= 0x80;
141  return m_mac->process(V);
142  }
143 
144  m_mac->update(text, text_len - block_size());
145  xor_buf(V.data(), &text[text_len - block_size()], block_size());
146  m_mac->update(V);
147 
148  return m_mac->final();
149  }
150 
152  {
153  V[m_bs-8] &= 0x7F;
154  V[m_bs-4] &= 0x7F;
155 
156  ctr().set_iv(V.data(), V.size());
157  }
158 
159 void SIV_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
160  {
161  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
162 
163  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
164  msg_buf().clear();
165 
166  const secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
167 
168  buffer.insert(buffer.begin() + offset, V.begin(), V.end());
169 
170  if(buffer.size() != offset + V.size())
171  {
172  set_ctr_iv(V);
173  ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
174  }
175  }
176 
177 void SIV_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
178  {
179  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
180 
181  if(msg_buf().size() > 0)
182  {
183  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
184  msg_buf().clear();
185  }
186 
187  const size_t sz = buffer.size() - offset;
188 
189  BOTAN_ASSERT(sz >= tag_size(), "We have the tag");
190 
191  secure_vector<uint8_t> V(buffer.data() + offset,
192  buffer.data() + offset + block_size());
193 
194  if(buffer.size() != offset + V.size())
195  {
196  set_ctr_iv(V);
197 
198  ctr().cipher(buffer.data() + offset + V.size(),
199  buffer.data() + offset,
200  buffer.size() - offset - V.size());
201  }
202 
203  const secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
204 
205  if(!constant_time_compare(T.data(), V.data(), T.size()))
206  throw Invalid_Authentication_Tag("SIV tag check failed");
207 
208  buffer.resize(buffer.size() - tag_size());
209  }
210 
211 }
secure_vector< uint8_t > & msg_buf()
Definition: siv.h:70
std::string m_name
void cipher1(uint8_t buf[], size_t len)
Definition: stream_cipher.h:78
Key_Length_Specification key_spec() const override
Definition: siv.cpp:68
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len)=0
size_t maximum_associated_data_inputs() const override
Definition: siv.cpp:81
void poly_double_n(uint8_t out[], const uint8_t in[], size_t n)
Definition: poly_dbl.cpp:73
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
size_t process(uint8_t buf[], size_t size) override
Definition: siv.cpp:111
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
size_t block_size() const
Definition: siv.h:64
std::string name() const override
Definition: siv.cpp:47
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
std::string name
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
void reset() override
Definition: siv.cpp:40
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:262
size_t update_granularity() const override
Definition: siv.cpp:57
bool valid_nonce_length(size_t) const override
Definition: siv.cpp:52
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:159
Definition: alg_id.cpp:13
size_t tag_size() const override
Definition: siv.h:57
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
Definition: siv.cpp:118
SIV_Mode(BlockCipher *cipher)
Definition: siv.cpp:17
StreamCipher & ctr()
Definition: siv.h:66
void clear() override
Definition: siv.cpp:33
fe T
Definition: ge.cpp:37
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len) override
Definition: siv.cpp:86
virtual void set_iv(const uint8_t iv[], size_t iv_len)=0
void set_ctr_iv(secure_vector< uint8_t > V)
Definition: siv.cpp:151
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:177