Botan  2.1.0
Crypto and TLS for C++11
siv.cpp
Go to the documentation of this file.
1 /*
2 * SIV Mode Encryption
3 * (C) 2013 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/cmac.h>
11 #include <botan/ctr.h>
12 #include <botan/parsing.h>
13 
14 namespace Botan {
15 
17  m_name(cipher->name() + "/SIV"),
18  m_ctr(new CTR_BE(cipher->clone())),
19  m_cmac(new CMAC(cipher))
20  {
21  if(cipher->block_size() != 16)
22  throw Invalid_Argument("SIV requires a 128 bit block cipher");
23  }
24 
26  {
27  m_ctr->clear();
28  m_cmac->clear();
29  reset();
30  }
31 
33  {
34  m_nonce.clear();
35  m_msg_buf.clear();
36  m_ad_macs.clear();
37  }
38 
39 std::string SIV_Mode::name() const
40  {
41  return m_name;
42  }
43 
44 bool SIV_Mode::valid_nonce_length(size_t) const
45  {
46  return true;
47  }
48 
50  {
51  /*
52  This value does not particularly matter as regardless SIV_Mode::update
53  buffers all input, so in theory this could be 1. However as for instance
54  Transform_Filter creates update_granularity() uint8_t buffers, use a
55  somewhat large size to avoid bouncing on a tiny buffer.
56  */
57  return 128;
58  }
59 
61  {
62  return m_cmac->key_spec().multiple(2);
63  }
64 
65 void SIV_Mode::key_schedule(const uint8_t key[], size_t length)
66  {
67  const size_t keylen = length / 2;
68  m_cmac->set_key(key, keylen);
69  m_ctr->set_key(key + keylen, keylen);
70  m_ad_macs.clear();
71  }
72 
73 void SIV_Mode::set_associated_data_n(size_t n, const uint8_t ad[], size_t length)
74  {
75  if(n >= m_ad_macs.size())
76  m_ad_macs.resize(n+1);
77 
78  m_ad_macs[n] = m_cmac->process(ad, length);
79  }
80 
81 void SIV_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
82  {
83  if(!valid_nonce_length(nonce_len))
84  throw Invalid_IV_Length(name(), nonce_len);
85 
86  if(nonce_len)
87  m_nonce = m_cmac->process(nonce, nonce_len);
88  else
89  m_nonce.clear();
90 
91  m_msg_buf.clear();
92  }
93 
94 size_t SIV_Mode::process(uint8_t buf[], size_t sz)
95  {
96  // all output is saved for processing in finish
97  m_msg_buf.insert(m_msg_buf.end(), buf, buf + sz);
98  return 0;
99  }
100 
101 secure_vector<uint8_t> SIV_Mode::S2V(const uint8_t* text, size_t text_len)
102  {
103  const uint8_t zero[16] = { 0 };
104 
105  secure_vector<uint8_t> V = m_cmac->process(zero, 16);
106 
107  for(size_t i = 0; i != m_ad_macs.size(); ++i)
108  {
109  V = CMAC::poly_double(V);
110  V ^= m_ad_macs[i];
111  }
112 
113  if(m_nonce.size())
114  {
115  V = CMAC::poly_double(V);
116  V ^= m_nonce;
117  }
118 
119  if(text_len < 16)
120  {
121  V = CMAC::poly_double(V);
122  xor_buf(V.data(), text, text_len);
123  V[text_len] ^= 0x80;
124  return m_cmac->process(V);
125  }
126 
127  m_cmac->update(text, text_len - 16);
128  xor_buf(V.data(), &text[text_len - 16], 16);
129  m_cmac->update(V);
130 
131  return m_cmac->final();
132  }
133 
135  {
136  V[8] &= 0x7F;
137  V[12] &= 0x7F;
138 
139  ctr().set_iv(V.data(), V.size());
140  }
141 
142 void SIV_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
143  {
144  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
145 
146  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
147 
148  secure_vector<uint8_t> V = S2V(buffer.data() + offset, buffer.size() - offset);
149 
150  buffer.insert(buffer.begin() + offset, V.begin(), V.end());
151 
152  set_ctr_iv(V);
153  ctr().cipher1(&buffer[offset + V.size()], buffer.size() - offset - V.size());
154  }
155 
156 void SIV_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
157  {
158  BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
159 
160  buffer.insert(buffer.begin() + offset, msg_buf().begin(), msg_buf().end());
161 
162  const size_t sz = buffer.size() - offset;
163 
164  BOTAN_ASSERT(sz >= tag_size(), "We have the tag");
165 
166  secure_vector<uint8_t> V(buffer.data() + offset, buffer.data() + offset + 16);
167 
168  set_ctr_iv(V);
169 
170  ctr().cipher(buffer.data() + offset + V.size(),
171  buffer.data() + offset,
172  buffer.size() - offset - V.size());
173 
174  secure_vector<uint8_t> T = S2V(buffer.data() + offset, buffer.size() - offset - V.size());
175 
176  if(T != V)
177  throw Integrity_Failure("SIV tag check failed");
178 
179  buffer.resize(buffer.size() - tag_size());
180  }
181 
182 }
void xor_buf(T out[], const T in[], size_t length)
Definition: mem_ops.h:115
secure_vector< uint8_t > & msg_buf()
Definition: siv.h:61
std::string m_name
void cipher1(uint8_t buf[], size_t len)
Definition: stream_cipher.h:65
Key_Length_Specification key_spec() const override
Definition: siv.cpp:60
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len)=0
size_t process(uint8_t buf[], size_t size) override
Definition: siv.cpp:94
std::string name() const override
Definition: siv.cpp:39
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
void reset() override
Definition: siv.cpp:32
size_t update_granularity() const override
Definition: siv.cpp:49
bool valid_nonce_length(size_t) const override
Definition: siv.cpp:44
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:142
Definition: alg_id.cpp:13
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len)
Definition: siv.cpp:73
static secure_vector< uint8_t > poly_double(const secure_vector< uint8_t > &in)
Definition: cmac.cpp:15
size_t tag_size() const override
Definition: siv.h:52
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
Definition: siv.cpp:101
SIV_Mode(BlockCipher *cipher)
Definition: siv.cpp:16
StreamCipher & ctr()
Definition: siv.h:57
void clear() override
Definition: siv.cpp:25
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:134
virtual size_t block_size() const =0
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:156