Arduino Cryptography Library
EAX.cpp
1 /*
2  * Copyright (C) 2015 Southern Storm Software, Pty Ltd.
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
20  * DEALINGS IN THE SOFTWARE.
21  */
22 
23 #include "EAX.h"
24 #include "Crypto.h"
25 #include <string.h>
26 
44 {
45  state.encPosn = 0;
46  state.authMode = 0;
47 }
48 
49 EAXCommon::~EAXCommon()
50 {
51  clean(state);
52 }
53 
54 size_t EAXCommon::keySize() const
55 {
56  return omac.blockCipher()->keySize();
57 }
58 
59 size_t EAXCommon::ivSize() const
60 {
61  // Can use any size but 16 is recommended.
62  return 16;
63 }
64 
65 size_t EAXCommon::tagSize() const
66 {
67  // Tags can be up to 16 bytes in length.
68  return 16;
69 }
70 
71 bool EAXCommon::setKey(const uint8_t *key, size_t len)
72 {
73  return omac.blockCipher()->setKey(key, len);
74 }
75 
76 bool EAXCommon::setIV(const uint8_t *iv, size_t len)
77 {
78  // Must have at least 1 byte for the IV.
79  if (!len)
80  return false;
81 
82  // Hash the IV to create the initial nonce for CTR mode. Also creates B.
83  omac.initFirst(state.counter);
84  omac.update(state.counter, iv, len);
85  omac.finalize(state.counter);
86 
87  // The tag is initially the nonce value. Will be XOR'ed with
88  // the hash of the authenticated and encrypted data later.
89  memcpy(state.tag, state.counter, 16);
90 
91  // Start the hashing context for the authenticated data.
92  omac.initNext(state.hash, 1);
93  state.encPosn = 16;
94  state.authMode = 1;
95 
96  // The EAX context is ready to go.
97  return true;
98 }
99 
100 void EAXCommon::encrypt(uint8_t *output, const uint8_t *input, size_t len)
101 {
102  if (state.authMode)
103  closeAuthData();
104  encryptCTR(output, input, len);
105  omac.update(state.hash, output, len);
106 }
107 
108 void EAXCommon::decrypt(uint8_t *output, const uint8_t *input, size_t len)
109 {
110  if (state.authMode)
111  closeAuthData();
112  omac.update(state.hash, input, len);
113  encryptCTR(output, input, len);
114 }
115 
116 void EAXCommon::addAuthData(const void *data, size_t len)
117 {
118  if (state.authMode)
119  omac.update(state.hash, (const uint8_t *)data, len);
120 }
121 
122 void EAXCommon::computeTag(void *tag, size_t len)
123 {
124  closeTag();
125  if (len > 16)
126  len = 16;
127  memcpy(tag, state.tag, len);
128 }
129 
130 bool EAXCommon::checkTag(const void *tag, size_t len)
131 {
132  // Can never match if the expected tag length is too long.
133  if (len > 16)
134  return false;
135 
136  // Compute the final tag and check it.
137  closeTag();
138  return secure_compare(state.tag, tag, len);
139 }
140 
142 {
143  clean(state);
144 }
145 
150 void EAXCommon::closeAuthData()
151 {
152  // Finalise the OMAC hash and XOR it with the final tag.
153  omac.finalize(state.hash);
154  for (uint8_t index = 0; index < 16; ++index)
155  state.tag[index] ^= state.hash[index];
156  state.authMode = 0;
157 
158  // Initialise the hashing context for the ciphertext data.
159  omac.initNext(state.hash, 2);
160 }
161 
171 void EAXCommon::encryptCTR(uint8_t *output, const uint8_t *input, size_t len)
172 {
173  while (len > 0) {
174  // Do we need to start a new block?
175  if (state.encPosn == 16) {
176  // Encrypt the counter to create the next keystream block.
177  omac.blockCipher()->encryptBlock(state.stream, state.counter);
178  state.encPosn = 0;
179 
180  // Increment the counter, taking care not to reveal
181  // any timing information about the starting value.
182  // We iterate through the entire counter region even
183  // if we could stop earlier because a byte is non-zero.
184  uint16_t temp = 1;
185  uint8_t index = 16;
186  while (index > 0) {
187  --index;
188  temp += state.counter[index];
189  state.counter[index] = (uint8_t)temp;
190  temp >>= 8;
191  }
192  }
193 
194  // Encrypt/decrypt the current input block.
195  uint8_t size = 16 - state.encPosn;
196  if (size > len)
197  size = (uint8_t)len;
198  for (uint8_t index = 0; index < size; ++index)
199  output[index] = input[index] ^ state.stream[(state.encPosn)++];
200 
201  // Move onto the next block.
202  len -= size;
203  input += size;
204  output += size;
205  }
206 }
207 
208 void EAXCommon::closeTag()
209 {
210  // If we were only authenticating, then close off auth mode.
211  if (state.authMode)
212  closeAuthData();
213 
214  // Finalise the hash over the ciphertext and XOR with the final tag.
215  omac.finalize(state.hash);
216  for (uint8_t index = 0; index < 16; ++index)
217  state.tag[index] ^= state.hash[index];
218 }
219 
virtual bool setKey(const uint8_t *key, size_t len)=0
Sets the key to use for future encryption and decryption operations.
virtual void encryptBlock(uint8_t *output, const uint8_t *input)=0
Encrypts a single block using this cipher.
virtual size_t keySize() const =0
Default size of the key for this block cipher, in bytes.
size_t keySize() const
Default size of the key for this cipher, in bytes.
Definition: EAX.cpp:54
bool setIV(const uint8_t *iv, size_t len)
Sets the initialization vector to use for future encryption and decryption operations.
Definition: EAX.cpp:76
size_t tagSize() const
Returns the size of the authentication tag.
Definition: EAX.cpp:65
void decrypt(uint8_t *output, const uint8_t *input, size_t len)
Decrypts an input buffer and writes the plaintext to an output buffer.
Definition: EAX.cpp:108
bool checkTag(const void *tag, size_t len)
Finalizes the decryption process and checks the authentication tag.
Definition: EAX.cpp:130
void encrypt(uint8_t *output, const uint8_t *input, size_t len)
Encrypts an input buffer and writes the ciphertext to an output buffer.
Definition: EAX.cpp:100
void computeTag(void *tag, size_t len)
Finalizes the encryption process and computes the authentication tag.
Definition: EAX.cpp:122
size_t ivSize() const
Size of the initialization vector for this cipher, in bytes.
Definition: EAX.cpp:59
void addAuthData(const void *data, size_t len)
Adds extra data that will be authenticated but not encrypted.
Definition: EAX.cpp:116
EAXCommon()
Constructs a new cipher in EAX mode.
Definition: EAX.cpp:43
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for future encryption and decryption operations.
Definition: EAX.cpp:71
void clear()
Clears all security-sensitive state from this cipher.
Definition: EAX.cpp:141
void initFirst(uint8_t omac[16])
Initialises the first OMAC hashing context and creates the B value.
Definition: OMAC.cpp:101
void update(uint8_t omac[16], const uint8_t *data, size_t size)
Updates an OMAC hashing context with more data.
Definition: OMAC.cpp:143
BlockCipher * blockCipher() const
Gets the block cipher that is in use for this OMAC object.
Definition: OMAC.h:34
void initNext(uint8_t omac[16], uint8_t tag)
Initialises or restarts an OMAC hashing context.
Definition: OMAC.cpp:127
void finalize(uint8_t omac[16])
Finalises an OMAC hashing context.
Definition: OMAC.cpp:172