Botan 2.13.0 Crypto and TLS for C++11

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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
13 namespace Botan {
14
15 namespace {
16
17 /*
18 * EAX MAC-based PRF
19 */
20 secure_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 */
38 EAX_Mode::EAX_Mode(BlockCipher* cipher, size_t tag_size) :
39 m_tag_size(tag_size ? tag_size : cipher->block_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
48 void EAX_Mode::clear()
49 {
50 m_cipher->clear();
51 m_ctr->clear();
52 m_cmac->clear();
53 reset();
54 }
55
56 void EAX_Mode::reset()
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
68 std::string EAX_Mode::name() const
69 {
70 return (m_cipher->name() + "/EAX");
71 }
72
73 size_t EAX_Mode::update_granularity() const
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
82 Key_Length_Specification EAX_Mode::key_spec() const
83 {
84 return m_cipher->key_spec();
85 }
86
87 /*
88 * Set the EAX key
89 */
90 void 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 */
103 void 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
110 void 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
124 size_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
132 void EAX_Encryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
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
150 size_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
158 void EAX_Decryption::finish(secure_vector<uint8_t>& buffer, size_t offset)
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 }
Botan::EAX_Decryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: eax.cpp:158
Botan::Invalid_Argument
Definition: exceptn.h:136
m_cipher
CCCryptorRef m_cipher
Definition: commoncrypto_mode.cpp:50
Botan::EAX_Mode::key_spec
Key_Length_Specification key_spec() const override
Definition: eax.cpp:82
Botan::EAX_Encryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: eax.cpp:124
Botan::Key_Not_Set
Definition: exceptn.h:236
Botan::EAX_Mode::name
std::string name() const override
Definition: eax.cpp:68
Botan::EAX_Mode::clear
void clear() override
Definition: eax.cpp:48
Botan::Invalid_IV_Length
Definition: exceptn.h:161
Botan::Cipher_Mode::update
void update(secure_vector< uint8_t > &buffer, size_t offset=0)
Definition: cipher_mode.h:112
Botan::Key_Length_Specification
Definition: key_spec.h:18
Botan::CTR_BE
Definition: ctr.h:21
Botan::EAX_Mode::m_ad_mac
secure_vector< uint8_t > m_ad_mac
Definition: eax.h:59
Botan::EAX_Mode::m_nonce_mac
secure_vector< uint8_t > m_nonce_mac
Definition: eax.h:61
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_STATE_CHECK
#define BOTAN_STATE_CHECK(expr)
Definition: assert.h:49
BOTAN_ASSERT_NOMSG
#define BOTAN_ASSERT_NOMSG(expr)
Definition: assert.h:68
Botan::ASN1::to_string
std::string to_string(const BER_Object &obj)
Definition: asn1_obj.cpp:213
BOTAN_ASSERT
#define BOTAN_ASSERT(expr, assertion_made)
Definition: assert.h:55
Botan::secure_vector
std::vector< T, secure_allocator< T >> secure_vector
Definition: secmem.h:65
Botan::xor_buf
void xor_buf(uint8_t out[], const uint8_t in[], size_t length)
Definition: mem_ops.h:232
Botan::EAX_Mode::valid_nonce_length
bool valid_nonce_length(size_t) const override
Definition: eax.h:36
Botan::EAX_Mode::EAX_Mode
EAX_Mode(BlockCipher *cipher, size_t tag_size)
Definition: eax.cpp:38
Botan::EAX_Decryption::process
size_t process(uint8_t buf[], size_t size) override
Definition: eax.cpp:150
Botan
Definition: alg_id.cpp:13
Botan::EAX_Mode::block_size
size_t block_size() const
Definition: eax.h:51
Botan::EAX_Mode::m_cipher
std::unique_ptr< BlockCipher > m_cipher
Definition: eax.h:55
Botan::CMAC
Definition: cmac.h:21
Botan::Invalid_State
Definition: exceptn.h:215
Botan::EAX_Mode::tag_size
size_t tag_size() const override
Definition: eax.h:38
Botan::EAX_Mode::reset
void reset() override
Definition: eax.cpp:56
Botan::EAX_Mode::m_cmac
std::unique_ptr< MessageAuthenticationCode > m_cmac
Definition: eax.h:57
Botan::EAX_Mode::update_granularity
size_t update_granularity() const override
Definition: eax.cpp:73
Botan::EAX_Mode::set_associated_data
void set_associated_data(const uint8_t ad[], size_t ad_len) override
Definition: eax.cpp:103
Botan::EAX_Mode::m_ctr
std::unique_ptr< StreamCipher > m_ctr
Definition: eax.h:56
Botan::Invalid_Authentication_Tag
Definition: exceptn.h:290
Botan::EAX_Encryption::finish
void finish(secure_vector< uint8_t > &final_block, size_t offset=0) override
Definition: eax.cpp:132
Botan::BlockCipher
Definition: block_cipher.h:21