xts.c
Go to the documentation of this file.
1 /**
2  * @file xts.c
3  * @brief XEX-based tweaked-codebook mode with ciphertext stealing (XTS)
4  *
5  * @section License
6  *
7  * Copyright (C) 2010-2018 Oryx Embedded SARL. All rights reserved.
8  *
9  * This file is part of CycloneCrypto Open.
10  *
11  * This program is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU General Public License
13  * as published by the Free Software Foundation; either version 2
14  * of the License, or (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software Foundation,
23  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
24  *
25  * @section Description
26  *
27  * XTS is a tweakable block cipher designed for encryption of sector-based
28  * storage. Refer to IEEE Std 1619 and SP 800-38E for more details
29  *
30  * @author Oryx Embedded SARL (www.oryx-embedded.com)
31  * @version 1.9.0
32  **/
33 
34 //Switch to the appropriate trace level
35 #define TRACE_LEVEL CRYPTO_TRACE_LEVEL
36 
37 //Dependencies
38 #include "core/crypto.h"
39 #include "cipher_mode/xts.h"
40 #include "debug.h"
41 
42 //Check crypto library configuration
43 #if (XTS_SUPPORT == ENABLED)
44 
45 
46 /**
47  * @brief Initialize XTS context
48  * @param[in] context Pointer to the XTS context
49  * @param[in] cipherAlgo Cipher algorithm
50  * @param[in] key Pointer to the key
51  * @param[in] keyLen Length of the key
52  * @return Error code
53  **/
54 
55 error_t xtsInit(XtsContext *context, const CipherAlgo *cipherAlgo,
56  const void *key, size_t keyLen)
57 {
58  error_t error;
59  const uint8_t *k1;
60  const uint8_t *k2;
61 
62  //XTS supports only symmetric block ciphers whose block size is 128 bits
63  if(cipherAlgo->type != CIPHER_ALGO_TYPE_BLOCK || cipherAlgo->blockSize != 16)
65 
66  //Invalid key length?
67  if(keyLen != 32 && keyLen != 64)
69 
70  //Cipher algorithm used to perform XTS encryption/decryption
71  context->cipherAlgo = cipherAlgo;
72 
73  //The key is parsed as a concatenation of 2 fields of equal size called K1 and K2
74  k1 = (uint8_t *) key;
75  k2 = (uint8_t *) key + (keyLen / 2);
76 
77  //Initialize first cipher context using K1
78  error = cipherAlgo->init(context->cipherContext1, k1, keyLen / 2);
79  //Any error to report?
80  if(error)
81  return error;
82 
83  //Initialize second cipher context using K2
84  error = cipherAlgo->init(context->cipherContext2, k2, keyLen / 2);
85  //Any error to report?
86  if(error)
87  return error;
88 
89  //Successful initialization
90  return NO_ERROR;
91 }
92 
93 
94 /**
95  * @brief Encrypt a data unit using XTS
96  * @param[in] context Pointer to the XTS context
97  * @param[in] i Value of the 128-bit tweak
98  * @param[in] p Pointer to the data unit to be encrypted (plaintext)
99  * @param[out] c Pointer to the resulting data unit (ciphertext)
100  * @param[in] length Length of the data unit, in bytes
101  * @return Error code
102  **/
103 
104 error_t xtsEncrypt(XtsContext *context, const uint8_t *i, const uint8_t *p,
105  uint8_t *c, size_t length)
106 {
107  uint8_t t[16];
108  uint8_t x[16];
109 
110  //The data unit size shall be at least 128 bits
111  if(length < 16)
113 
114  //Encrypt the tweak using K2
115  context->cipherAlgo->encryptBlock(context->cipherContext2, i, t);
116 
117  //XTS mode operates in a block-by-block fashion
118  while(length >= 16)
119  {
120  //Merge the tweak into the input block
121  xtsXorBlock(x, p, t);
122  //Encrypt the block using K1
123  context->cipherAlgo->encryptBlock(context->cipherContext1, x, x);
124  //Merge the tweak into the output block
125  xtsXorBlock(c, x, t);
126 
127  //Multiply T by x in GF(2^128)
128  xtsMul(t, t);
129 
130  //Next block
131  p += 16;
132  c += 16;
133  length -= 16;
134  }
135 
136  //Any partial block?
137  if(length > 0)
138  {
139  //Copy the final ciphertext bytes
140  cryptoMemcpy(c, c - 16, length);
141  //Copy the final plaintext bytes
142  cryptoMemcpy(x, p, length);
143  //Steal ciphertext to complete the block
144  cryptoMemcpy(x + length, c + length - 16, 16 - length);
145 
146  //Merge the tweak into the input block
147  xtsXorBlock(x, x, t);
148  //Encrypt the final block using K1
149  context->cipherAlgo->encryptBlock(context->cipherContext1, x, x);
150  //Merge the tweak into the output block
151  xtsXorBlock(c - 16, x, t);
152  }
153 
154  //Successful processing
155  return NO_ERROR;
156 }
157 
158 
159 /**
160  * @brief Decrypt a data unit using XTS
161  * @param[in] context Pointer to the XTS context
162  * @param[in] i Value of the 128-bit tweak
163  * @param[in] c Pointer to the data unit to be decrypted (ciphertext)
164  * @param[out] p Pointer to the resulting data unit (plaintext)
165  * @param[in] length Length of the data unit, in bytes
166  * @return Error code
167  **/
168 
169 error_t xtsDecrypt(XtsContext *context, const uint8_t *i, const uint8_t *c,
170  uint8_t *p, size_t length)
171 {
172  uint8_t t[16];
173  uint8_t x[16];
174 
175  //The data unit size shall be at least 128 bits
176  if(length < 16)
178 
179  //Encrypt the tweak using K2
180  context->cipherAlgo->encryptBlock(context->cipherContext2, i, t);
181 
182  //XTS mode operates in a block-by-block fashion
183  while(length >= 32)
184  {
185  //Merge the tweak into the input block
186  xtsXorBlock(x, c, t);
187  //Decrypt the block using K1
188  context->cipherAlgo->decryptBlock(context->cipherContext1, x, x);
189  //Merge the tweak into the output block
190  xtsXorBlock(p, x, t);
191 
192  //Multiply T by x in GF(2^128)
193  xtsMul(t, t);
194 
195  //Next block
196  c += 16;
197  p += 16;
198  length -= 16;
199  }
200 
201  //Any partial block?
202  if(length > 16)
203  {
204  uint8_t tt[16];
205 
206  //Multiply T by x in GF(2^128)
207  xtsMul(tt, t);
208 
209  //Merge the tweak into the input block
210  xtsXorBlock(x, c, tt);
211  //Decrypt the next-to-last block using K1
212  context->cipherAlgo->decryptBlock(context->cipherContext1, x, x);
213  //Merge the tweak into the output block
214  xtsXorBlock(p, x, tt);
215 
216  //Retrieve the length of the final block
217  length -= 16;
218 
219  //Copy the final plaintext bytes
220  cryptoMemcpy(p + 16, p, length);
221  //Copy the final ciphertext bytes
222  cryptoMemcpy(x, c + 16, length);
223  //Steal ciphertext to complete the block
224  cryptoMemcpy(x + length, p + length, 16 - length);
225  }
226  else
227  {
228  //The last block contains exactly 128 bits
229  cryptoMemcpy(x, c, 16);
230  }
231 
232  //Merge the tweak into the input block
233  xtsXorBlock(x, x, t);
234  //Decrypt the final block using K1
235  context->cipherAlgo->decryptBlock(context->cipherContext1, x, x);
236  //Merge the tweak into the output block
237  xtsXorBlock(p, x, t);
238 
239  //Successful processing
240  return NO_ERROR;
241 }
242 
243 
244 /**
245  * @brief Multiplication by x in GF(2^128)
246  * @param[out] x Pointer to the output block
247  * @param[out] a Pointer to the input block
248  **/
249 
250 void xtsMul(uint8_t *x, const uint8_t *a)
251 {
252  size_t i;
253  uint8_t c;
254 
255  //Save the value of the most significant bit
256  c = a[15] >> 7;
257 
258  //The multiplication of a polynomial by x in GF(2^128) corresponds to a
259  //shift of indices
260  for(i = 15; i > 0; i--)
261  {
262  x[i] = (a[i] << 1) | (a[i - 1] >> 7);
263  }
264 
265  //Shift the first byte of the block
266  x[0] = a[0] << 1;
267 
268  //If the highest term of the result is equal to one, then perform reduction
269  x[0] ^= 0x87 & ~(c - 1);
270 }
271 
272 
273 /**
274  * @brief XOR operation
275  * @param[out] x Block resulting from the XOR operation
276  * @param[in] a First input block
277  * @param[in] b Second input block
278  **/
279 
280 void xtsXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b)
281 {
282  size_t i;
283 
284  //Perform XOR operation
285  for(i = 0; i < 16; i++)
286  {
287  x[i] = a[i] ^ b[i];
288  }
289 }
290 
291 #endif
uint8_t c
Definition: ndp.h:510
#define cryptoMemcpy(dest, src, length)
Definition: crypto.h:590
Debugging facilities.
error_t xtsInit(XtsContext *context, const CipherAlgo *cipherAlgo, const void *key, size_t keyLen)
Initialize XTS context.
Definition: xts.c:55
uint8_t p
Definition: ndp.h:295
CipherAlgoEncryptBlock encryptBlock
Definition: crypto.h:1082
General definitions for cryptographic algorithms.
Invalid parameter.
Definition: error.h:45
Common interface for encryption algorithms.
Definition: crypto.h:1073
error_t xtsDecrypt(XtsContext *context, const uint8_t *i, const uint8_t *c, uint8_t *p, size_t length)
Decrypt a data unit using XTS.
Definition: xts.c:169
uint8_t cipherContext2[MAX_CIPHER_CONTEXT_SIZE]
Definition: xts.h:99
CipherAlgoDecryptBlock decryptBlock
Definition: crypto.h:1083
uint8_t a
Definition: ndp.h:407
void xtsXorBlock(uint8_t *x, const uint8_t *a, const uint8_t *b)
XOR operation.
Definition: xts.c:280
size_t blockSize
Definition: crypto.h:1078
CipherAlgoInit init
Definition: crypto.h:1079
void xtsMul(uint8_t *x, const uint8_t *a)
Multiplication by x in GF(2^128)
Definition: xts.c:250
XEX-based tweaked-codebook mode with ciphertext stealing (XTS)
uint8_t cipherContext1[MAX_CIPHER_CONTEXT_SIZE]
Definition: xts.h:98
Success.
Definition: error.h:42
error_t
Error codes.
Definition: error.h:40
error_t xtsEncrypt(XtsContext *context, const uint8_t *i, const uint8_t *p, uint8_t *c, size_t length)
Encrypt a data unit using XTS.
Definition: xts.c:104
XTS context.
Definition: xts.h:95
const CipherAlgo * cipherAlgo
Definition: xts.h:97
CipherAlgoType type
Definition: crypto.h:1077
uint8_t length
Definition: dtls_misc.h:140
uint8_t b[6]
Definition: dtls_misc.h:130