Arduino Cryptography Library
XTS.cpp
1 /*
2  * Copyright (C) 2016 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 "XTS.h"
24 #include "Crypto.h"
25 #include "GF128.h"
26 #include <string.h>
27 
42  : sectSize(512)
43 {
44 }
45 
50 {
51  clean(twk);
52 }
53 
62 size_t XTSCommon::keySize() const
63 {
64  return blockCipher1->keySize() * 2;
65 }
66 
73 size_t XTSCommon::tweakSize() const
74 {
75  return 16;
76 }
77 
97 bool XTSCommon::setSectorSize(size_t size)
98 {
99  if (size < 16)
100  return false;
101  sectSize = size;
102  return true;
103 }
104 
119 bool XTSCommon::setKey(const uint8_t *key, size_t len)
120 {
121  if (!blockCipher1->setKey(key, len / 2))
122  return false;
123  return blockCipher2->setKey(key + len / 2, len - (len / 2));
124 }
125 
142 bool XTSCommon::setTweak(const uint8_t *tweak, size_t len)
143 {
144  if (len > 16)
145  return false;
146  memcpy(twk, tweak, len);
147  memset(((uint8_t *)twk) + len, 0, 16 - len);
148  blockCipher2->encryptBlock((uint8_t *)twk, (uint8_t *)twk);
149  return true;
150 }
151 
152 #define xorTweak(output, input, tweak) \
153  do { \
154  for (uint8_t i = 0; i < 16; ++i) \
155  (output)[i] = (input)[i] ^ ((const uint8_t *)(tweak))[i]; \
156  } while (0)
157 
170 void XTSCommon::encryptSector(uint8_t *output, const uint8_t *input)
171 {
172  size_t sectLast = sectSize & ~15;
173  size_t posn = 0;
174  uint32_t t[4];
175  memcpy(t, twk, sizeof(t));
176  while (posn < sectLast) {
177  // Process all complete 16-byte blocks.
178  xorTweak(output, input, t);
179  blockCipher1->encryptBlock(output, output);
180  xorTweak(output, output, t);
181  GF128::dblXTS(t);
182  input += 16;
183  output += 16;
184  posn += 16;
185  }
186  if (posn < sectSize) {
187  // Perform ciphertext stealing on the final partial block.
188  uint8_t leftOver = sectSize - posn;
189  output -= 16;
190  while (leftOver > 0) {
191  // Swap the left-over bytes in the last two blocks.
192  --leftOver;
193  uint8_t temp = input[leftOver];
194  output[leftOver + 16] = output[leftOver];
195  output[leftOver] = temp;
196  }
197  xorTweak(output, output, t);
198  blockCipher1->encryptBlock(output, output);
199  xorTweak(output, output, t);
200  }
201 }
202 
215 void XTSCommon::decryptSector(uint8_t *output, const uint8_t *input)
216 {
217  size_t sectLast = sectSize & ~15;
218  size_t posn = 0;
219  uint32_t t[4];
220  memcpy(t, twk, sizeof(t));
221  if (sectLast != sectSize)
222  sectLast -= 16;
223  while (posn < sectLast) {
224  // Process all complete 16-byte blocks.
225  xorTweak(output, input, t);
226  blockCipher1->decryptBlock(output, output);
227  xorTweak(output, output, t);
228  GF128::dblXTS(t);
229  input += 16;
230  output += 16;
231  posn += 16;
232  }
233  if (posn < sectSize) {
234  // Perform ciphertext stealing on the final two blocks.
235  uint8_t leftOver = sectSize - 16 - posn;
236  uint32_t u[4];
237 
238  // Decrypt the second-last block of ciphertext to recover
239  // the last partial block of plaintext. We need to use
240  // dblXTS(t) as the tweak for this block. Save the current
241  // tweak in "u" for use later.
242  memcpy(u, t, sizeof(t));
243  GF128::dblXTS(t);
244  xorTweak(output, input, t);
245  blockCipher1->decryptBlock(output, output);
246  xorTweak(output, output, t);
247 
248  // Swap the left-over bytes in the last two blocks.
249  while (leftOver > 0) {
250  --leftOver;
251  uint8_t temp = input[leftOver + 16];
252  output[leftOver + 16] = output[leftOver];
253  output[leftOver] = temp;
254  }
255 
256  // Decrypt the second-last block using the second-last tweak.
257  xorTweak(output, output, u);
258  blockCipher1->decryptBlock(output, output);
259  xorTweak(output, output, u);
260  }
261 }
262 
267 {
268  clean(twk);
269  blockCipher1->clear();
270  blockCipher2->clear();
271 }
272 
304 {
305 }
306 
316 {
317  return blockCipher1->keySize();
318 }
319 
334 bool XTSSingleKeyCommon::setKey(const uint8_t *key, size_t len)
335 {
336  return blockCipher1->setKey(key, len);
337 }
338 
virtual void clear()=0
Clears all security-sensitive state from this block cipher.
virtual bool setKey(const uint8_t *key, size_t len)=0
Sets the key to use for future encryption and decryption operations.
virtual void decryptBlock(uint8_t *output, const uint8_t *input)=0
Decrypts a single block using this cipher.
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.
static void dblXTS(uint32_t V[4])
Doubles a value in the GF(2^128) field using XTS conventions.
Definition: GF128.cpp:497
size_t tweakSize() const
Gets the maximum supported size for the tweak.
Definition: XTS.cpp:73
virtual size_t keySize() const
Gets the size of the key for XTS mode.
Definition: XTS.cpp:62
virtual bool setKey(const uint8_t *key, size_t len)
Sets the key to use for XTS mode.
Definition: XTS.cpp:119
bool setTweak(const uint8_t *tweak, size_t len)
Sets the tweak value for the current sector to encrypt or decrypt.
Definition: XTS.cpp:142
void decryptSector(uint8_t *output, const uint8_t *input)
Decrypts an entire sector of data.
Definition: XTS.cpp:215
bool setSectorSize(size_t size)
Sets the size of sectors encrypted or decrypted by this class.
Definition: XTS.cpp:97
void encryptSector(uint8_t *output, const uint8_t *input)
Encrypts an entire sector of data.
Definition: XTS.cpp:170
void clear()
Clears all security-sensitive state from this XTS object.
Definition: XTS.cpp:266
virtual ~XTSCommon()
Clears all sensitive information and destroys this object.
Definition: XTS.cpp:49
XTSCommon()
Constructs an XTS object with a default sector size of 512 bytes.
Definition: XTS.cpp:41
virtual ~XTSSingleKeyCommon()
Clears all sensitive information and destroys this object.
Definition: XTS.cpp:303
size_t keySize() const
Gets the size of the key for single-pkey XTS mode.
Definition: XTS.cpp:315
bool setKey(const uint8_t *key, size_t len)
Sets the key to use for single-keyh XTS mode.
Definition: XTS.cpp:334