Botan 2.19.5 Crypto and TLS for C&

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
17 SIV_Mode::SIV_Mode(BlockCipher* cipher) :
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
28 SIV_Mode::~SIV_Mode()
29 {
30 // for ~unique_ptr
31 }
32
33 void SIV_Mode::clear()
34 {
35 m_ctr->clear();
36 m_mac->clear();
37 reset();
38 }
39
40 void SIV_Mode::reset()
41 {
42 m_nonce.clear();
43 m_msg_buf.clear();
44 m_ad_macs.clear();
45 }
46
47std::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
57 size_t SIV_Mode::update_granularity() const
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
68 Key_Length_Specification SIV_Mode::key_spec() const
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 size_t SIV_Mode::maximum_associated_data_inputs() const
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
151 void SIV_Mode::set_ctr_iv(secure_vector<uint8_t> V)
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}
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::BlockCipher
Definition: block_cipher.h:22
Botan::CMAC
Definition: cmac.h:22
Botan::CTR_BE
Definition: ctr.h:22
Botan::Invalid_Argument
Definition: exceptn.h:137
Botan::Invalid_Authentication_Tag
Definition: exceptn.h:291
Botan::Invalid_IV_Length
Definition: exceptn.h:162
Botan::Key_Length_Specification
Definition: sym_algo.h:20
Botan::SIV_Decryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:177
Botan::SIV_Encryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:159
Botan::SIV_Mode::set_associated_data_n
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len) override
Definition: siv.cpp:86
Botan::SIV_Mode::SIV_Mode
SIV_Mode(BlockCipher *cipher)
Definition: siv.cpp:17
Botan::SIV_Mode::block_size
size_t block_size() const
Definition: siv.h:64
Botan::SIV_Mode::clear
void clear() override
Definition: siv.cpp:33
Botan::SIV_Mode::name
std::string name() const override
Definition: siv.cpp:47
Botan::SIV_Mode::set_ctr_iv
void set_ctr_iv(secure_vector< uint8_t > V)
Definition: siv.cpp:151
Botan::SIV_Mode::key_spec
Key_Length_Specification key_spec() const override
Definition: siv.cpp:68
Botan::SIV_Mode::S2V
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
Definition: siv.cpp:118
Botan::SIV_Mode::ctr
StreamCipher & ctr()
Definition: siv.h:66
Botan::SIV_Mode::update_granularity
size_t update_granularity() const override
Definition: siv.cpp:57
Botan::SIV_Mode::tag_size
size_t tag_size() const override
Definition: siv.h:57
Botan::SIV_Mode::process
size_t process(uint8_t buf[], size_t size) override
Definition: siv.cpp:111
Botan::SIV_Mode::~SIV_Mode
~SIV_Mode()
Definition: siv.cpp:28
Botan::SIV_Mode::maximum_associated_data_inputs
size_t maximum_associated_data_inputs() const override
Definition: siv.cpp:81
Botan::SIV_Mode::reset
void reset() override
Definition: siv.cpp:40
Botan::SIV_Mode::msg_buf
secure_vector< uint8_t > & msg_buf()
Definition: siv.h:70
Botan::SIV_Mode::valid_nonce_length
bool valid_nonce_length(size_t) const override
Definition: siv.cpp:52
Botan::StreamCipher::cipher1
void cipher1(uint8_t buf[], size_t len)
Definition: stream_cipher.h:78
Botan::StreamCipher::cipher
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len)=0
Botan::StreamCipher::set_iv
virtual void set_iv(const uint8_t iv[], size_t iv_len)=0
name
std::string name
Definition: commoncrypto_hash.cpp:24
T
fe T
Definition: ge.cpp:37
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
Botan
Definition: alg_id.cpp:13
Botan::constant_time_compare
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition: mem_ops.h:82
Botan::xor_buf
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:262
Botan::poly_double_n
void poly_double_n(uint8_t out[], const uint8_t in[], size_t n)
Definition: poly_dbl.cpp:73
Botan::secure_vector
std::vector< T, secure_allocator< T > > secure_vector
Definition: secmem.h:65