Botan  2.7.0
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 
81 void SIV_Mode::set_associated_data_n(size_t n, const uint8_t ad[], size_t length)
82  {
83  const size_t max_ads = block_size() * 8 - 2;
84  if(n > max_ads)
85  throw Invalid_Argument(name() + " allows no more than " + std::to_string(max_ads) + " ADs");
86 
87  if(n >= m_ad_macs.size())
88  m_ad_macs.resize(n+1);
89 
90  m_ad_macs[n] = m_mac->process(ad, length);
91  }
92 
93 void SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
94  {
95  if(!valid_nonce_length(nonce_len))
96  throw Invalid_IV_Length(name(), nonce_len);
97 
98  if(nonce_len)
99  m_nonce = m_mac->process(nonce, nonce_len);
100  else
101  m_nonce.clear();
102 
103  m_msg_buf.clear();
104  }
105 
106 size_t SIV_Mode::process(uint8_t buf[], size_t sz)
107  {
108  // all output is saved for processing in finish
109  m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
110  return 0;
111  }
112 
113 secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
114  {
115  const std::vector<uint8_t> zeros(block_size());
116 
117  secure_vector<uint8_t> V = m_mac->process(zeros.data(), zeros.size());
118 
119  for(size_t i = 0; i != m_ad_macs.size(); ++i)
120  {
121  poly_double_n(V.data(), V.size());
122  V ^= m_ad_macs[i];
123  }
124 
125  if(m_nonce.size())
126  {
127  poly_double_n(V.data(), V.size());
128  V ^= m_nonce;
129  }
130 
131  if(text_len < block_size())
132  {
133  poly_double_n(V.data(), V.size());
134  xor_buf(V.data(), text, text_len);
135  V[text_len] ^= 0x80;
136  return m_mac->process(V);
137  }
138 
139  m_mac->update(text, text_len - block_size());
140  xor_buf(V.data(), &text[text_len - block_size()], block_size());
141  m_mac->update(V);
142 
143  return m_mac->final();
144  }
145 
147  {
148  V[m_bs-8] &= 0x7F;
149  V[m_bs-4] &= 0x7F;
150 
151  ctr().set_iv(V.data(), V.size());
152  }
153 
154 void SIV_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
155  {
156  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
157 
158  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
159  msg_buf().clear();
160 
161  const secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
162 
163  buffer.insert(buffer.begin() + offset, V.begin(), V.end());
164 
165  if(buffer.size() != offset + V.size())
166  {
167  set_ctr_iv(V);
168  ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
169  }
170  }
171 
172 void SIV_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
173  {
174  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
175 
176  if(msg_buf().size() > 0)
177  {
178  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
179  msg_buf().clear();
180  }
181 
182  const size_t sz = buffer.size() - offset;
183 
184  BOTAN_ASSERT(sz >= tag_size(), "We have the tag");
185 
186  secure_vector<uint8_t> V(buffer.data() + offset,
187  buffer.data() + offset + block_size());
188 
189  if(buffer.size() != offset + V.size())
190  {
191  set_ctr_iv(V);
192 
193  ctr().cipher(buffer.data() + offset + V.size(),
194  buffer.data() + offset,
195  buffer.size() - offset - V.size());
196  }
197 
198  const secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
199 
200  if(!constant_time_compare(T.data(), V.data(), T.size()))
201  throw Integrity_Failure("SIV tag check failed");
202 
203  buffer.resize(buffer.size() - tag_size());
204  }
205 
206 }
secure_vector< uint8_t > & msg_buf()
Definition: siv.h:66
void cipher1(uint8_t buf[], size_t len)
Definition: stream_cipher.h:66
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
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.cpp:51
size_t process(uint8_t buf[], size_t size) override
Definition: siv.cpp:106
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:210
std::string name() const override
Definition: siv.cpp:47
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:43
void reset() override
Definition: siv.cpp:40
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:174
size_t update_granularity() const override
Definition: siv.cpp:57
size_t block_size() const
Definition: siv.h:60
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:154
Definition: alg_id.cpp:13
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len)
Definition: siv.cpp:81
size_t tag_size() const override
Definition: siv.h:53
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
Definition: siv.cpp:113
SIV_Mode(BlockCipher *cipher)
Definition: siv.cpp:17
StreamCipher & ctr()
Definition: siv.h:62
void clear() override
Definition: siv.cpp:33
fe T
Definition: ge.cpp:37
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:88
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:146
void poly_double_n(uint8_t out[], const uint8_t in[], size_t n)
Definition: poly_dbl.cpp:63
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:172