Botan 2.19.3
Crypto and TLS for C&
eax.cpp
Go to the documentation of this file.
1/*
2* EAX Mode Encryption
3* (C) 1999-2007 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/eax.h>
10#include <botan/cmac.h>
11#include <botan/ctr.h>
12
13namespace Botan {
14
15namespace {
16
17/*
18* EAX MAC-based PRF
19*/
20secure_vector<uint8_t> eax_prf(uint8_t tag, size_t block_size,
21 MessageAuthenticationCode& mac,
22 const uint8_t in[], size_t length)
23 {
24 for(size_t i = 0; i != block_size - 1; ++i)
25 {
26 mac.update(0);
27 }
28 mac.update(tag);
29 mac.update(in, length);
30 return mac.final();
31 }
32
33}
34
35/*
36* EAX_Mode Constructor
37*/
38EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) :
39 m_tag_size(tag_size),
40 m_cipher(cipher),
41 m_ctr(new CTR_BE(m_cipher->clone())),
42 m_cmac(new CMAC(m_cipher->clone()))
43 {
44 if(m_tag_size < 8 || m_tag_size > m_cmac->output_length())
45 throw Invalid_Argument(name() + ": Bad tag size " + std::to_string(tag_size));
46 }
47
49 {
50 m_cipher->clear();
51 m_ctr->clear();
52 m_cmac->clear();
53 reset();
54 }
55
57 {
58 m_ad_mac.clear();
59 m_nonce_mac.clear();
60
61 // Clear out any data added to the CMAC calculation
62 try {
63 m_cmac->final();
64 }
65 catch(Key_Not_Set&) {}
66 }
67
68std::string EAX_Mode::name() const
69 {
70 return (m_cipher->name() + "/EAX");
71 }
72
74 {
75 /*
76 * For EAX this actually can be as low as 1 but that causes problems
77 * for applications which use update_granularity as the buffer size.
78 */
79 return m_cipher->parallel_bytes();
80 }
81
83 {
84 return m_cipher->key_spec();
85 }
86
87/*
88* Set the EAX key
89*/
90void EAX_Mode::key_schedule(const uint8_t key[], size_t length)
91 {
92 /*
93 * These could share the key schedule, which is one nice part of EAX,
94 * but it's much easier to ignore that here...
95 */
96 m_ctr->set_key(key, length);
97 m_cmac->set_key(key, length);
98 }
99
100/*
101* Set the EAX associated data
102*/
103void EAX_Mode::set_associated_data(const uint8_t ad[], size_t length)
104 {
105 if(m_nonce_mac.empty() == false)
106 throw Invalid_State("Cannot set AD for EAX while processing a message");
107 m_ad_mac = eax_prf(1, block_size(), *m_cmac, ad, length);
108 }
109
110void EAX_Mode::start_msg(const uint8_t nonce[], size_t nonce_len)
111 {
112 if(!valid_nonce_length(nonce_len))
113 throw Invalid_IV_Length(name(), nonce_len);
114
115 m_nonce_mac = eax_prf(0, block_size(), *m_cmac, nonce, nonce_len);
116
117 m_ctr->set_iv(m_nonce_mac.data(), m_nonce_mac.size());
118
119 for(size_t i = 0; i != block_size() - 1; ++i)
120 m_cmac->update(0);
121 m_cmac->update(2);
122 }
123
124size_t EAX_Encryption::process(uint8_t buf[], size_t sz)
125 {
126 BOTAN_STATE_CHECK(m_nonce_mac.size() > 0);
127 m_ctr->cipher(buf, buf, sz);
128 m_cmac->update(buf, sz);
129 return sz;
130 }
131
133 {
134 BOTAN_ASSERT_NOMSG(m_nonce_mac.empty() == false);
135 update(buffer, offset);
136
137 secure_vector<uint8_t> data_mac = m_cmac->final();
138 xor_buf(data_mac, m_nonce_mac, data_mac.size());
139
140 if(m_ad_mac.empty())
141 {
142 m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
143 }
144
145 xor_buf(data_mac, m_ad_mac, data_mac.size());
146
147 buffer += std::make_pair(data_mac.data(), tag_size());
148 }
149
150size_t EAX_Decryption::process(uint8_t buf[], size_t sz)
151 {
152 BOTAN_STATE_CHECK(m_nonce_mac.size() > 0);
153 m_cmac->update(buf, sz);
154 m_ctr->cipher(buf, buf, sz);
155 return sz;
156 }
157
159 {
160 BOTAN_ASSERT(buffer.size() >= offset, "Offset is sane");
161 const size_t sz = buffer.size() - offset;
162 uint8_t* buf = buffer.data() + offset;
163
164 BOTAN_ASSERT(sz >= tag_size(), "Have the tag as part of final input");
165
166 const size_t remaining = sz - tag_size();
167
168 if(remaining)
169 {
170 m_cmac->update(buf, remaining);
171 m_ctr->cipher(buf, buf, remaining);
172 }
173
174 const uint8_t* included_tag = &buf[remaining];
175
176 secure_vector<uint8_t> mac = m_cmac->final();
177 mac ^= m_nonce_mac;
178
179 if(m_ad_mac.empty())
180 {
181 m_ad_mac = eax_prf(1, block_size(), *m_cmac, nullptr, 0);
182 }
183
184 mac ^= m_ad_mac;
185
186 if(!constant_time_compare(mac.data(), included_tag, tag_size()))
187 throw Invalid_Authentication_Tag("EAX tag check failed");
188
189 buffer.resize(offset + remaining);
190
191 m_nonce_mac.clear();
192 }
193
194}
#define BOTAN_ASSERT_NOMSG(expr)
Definition assert.h:68
#define BOTAN_STATE_CHECK(expr)
Definition assert.h:49
#define BOTAN_ASSERT(expr, assertion_made)
Definition assert.h:55
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition eax.cpp:158
size_t process(uint8_t buf[], size_t size) override
Definition eax.cpp:150
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition eax.cpp:132
size_t process(uint8_t buf[], size_t size) override
Definition eax.cpp:124
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition eax.cpp:103
EAX_Mode(BlockCipher *cipher, size_t tag_size)
Definition eax.cpp:38
size_t block_size() const
Definition eax.h:51
Key_Length_Specification key_spec() const override
Definition eax.cpp:82
void reset() override
Definition eax.cpp:56
std::string name() const override
Definition eax.cpp:68
std::unique_ptr< BlockCipher > m_cipher
Definition eax.h:55
size_t tag_size() const override
Definition eax.h:38
std::unique_ptr< StreamCipher > m_ctr
Definition eax.h:56
bool valid_nonce_length(size_t) const override
Definition eax.h:36
std::unique_ptr< MessageAuthenticationCode > m_cmac
Definition eax.h:57
size_t update_granularity() const override
Definition eax.cpp:73
secure_vector< uint8_t > m_nonce_mac
Definition eax.h:61
void clear() override
Definition eax.cpp:48
secure_vector< uint8_t > m_ad_mac
Definition eax.h:59
int(* update)(CTX *, const void *, CC_LONG len)
bool constant_time_compare(const uint8_t x[], const uint8_t y[], size_t len)
Definition mem_ops.h:82
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition mem_ops.h:262
std::vector< T, secure_allocator< T > > secure_vector
Definition secmem.h:65