Botan 2.1.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
16 SIV_Mode::SIV_Mode(BlockCipher* cipher) :
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
25 void SIV_Mode::clear()
26 {
27 m_ctr->clear();
28 m_cmac->clear();
29 reset();
30 }
31
32 void SIV_Mode::reset()
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
49 size_t SIV_Mode::update_granularity() const
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
60 Key_Length_Specification SIV_Mode::key_spec() const
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
134 void SIV_Mode::set_ctr_iv(secure_vector<uint8_t> V)
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 }
Botan::xor_buf
void xor_buf(T out[], const T in[], size_t length)
Definition: mem_ops.h:115
Botan::SIV_Mode::msg_buf
secure_vector< uint8_t > & msg_buf()
Definition: siv.h:61
Botan::Invalid_Argument
Definition: exceptn.h:34
m_name
std::string m_name
Definition: openssl_hash.cpp:69
Botan::StreamCipher::cipher1
void cipher1(uint8_t buf[], size_t len)
Definition: stream_cipher.h:65
Botan::SIV_Mode::key_spec
Key_Length_Specification key_spec() const override
Definition: siv.cpp:60
Botan::Integrity_Failure
Definition: exceptn.h:198
Botan::Key_Length_Specification
Definition: key_spec.h:18
Botan::CTR_BE
Definition: ctr.h:19
Botan::StreamCipher::cipher
virtual void cipher(const uint8_t in[], uint8_t out[], size_t len)=0
Botan::SIV_Mode::process
size_t process(uint8_t buf[], size_t size) override
Definition: siv.cpp:94
Botan::Invalid_IV_Length
Definition: exceptn.h:109
Botan::SIV_Mode::name
std::string name() const override
Definition: siv.cpp:39
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:27
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:121
Botan::SIV_Mode::reset
void reset() override
Definition: siv.cpp:32
Botan::SIV_Mode::update_granularity
size_t update_granularity() const override
Definition: siv.cpp:49
Botan::SIV_Mode::valid_nonce_length
bool valid_nonce_length(size_t) const override
Definition: siv.cpp:44
Botan::SIV_Encryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:142
Botan
Definition: alg_id.cpp:13
Botan::SIV_Mode::set_associated_data_n
void set_associated_data_n(size_t n, const uint8_t ad[], size_t ad_len)
Definition: siv.cpp:73
Botan::CMAC::poly_double
static secure_vector< uint8_t > poly_double(const secure_vector< uint8_t > &in)
Definition: cmac.cpp:15
Botan::SIV_Mode::tag_size
size_t tag_size() const override
Definition: siv.h:52
Botan::CMAC
Definition: cmac.h:19
Botan::SIV_Mode::S2V
secure_vector< uint8_t > S2V(const uint8_t text[], size_t text_len)
Definition: siv.cpp:101
Botan::SIV_Mode::SIV_Mode
SIV_Mode(BlockCipher *cipher)
Definition: siv.cpp:16
Botan::SIV_Mode::ctr
StreamCipher & ctr()
Definition: siv.h:57
Botan::SIV_Mode::clear
void clear() override
Definition: siv.cpp:25
Botan::StreamCipher::set_iv
virtual void set_iv(const uint8_t iv[], size_t iv_len)=0
Botan::SIV_Mode::set_ctr_iv
void set_ctr_iv(secure_vector< uint8_t > V)
Definition: siv.cpp:134
Botan::BlockCipher::block_size
virtual size_t block_size() const =0
Botan::SIV_Decryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: siv.cpp:156
Botan::BlockCipher
Definition: block_cipher.h:19