1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
28
29
30
35
36
42
43
48
49
54
55
56
57
58
59
60
61
62
63
64
65
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
92
93
94
95
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
116
117
118
119
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
200
201
202
205
206
207
208
209
212
213
214
215
216
225
226
229
230
231
234
235
238
239
240
241
242
243
244
245
246
247
249
250
251
253
254
255
256
260
264
265
267
270
271
272
275
276
278
281
282
283
284
/* ... */
/* ... */
/* ... */
#include <stdio.h>
#include <string.h>
#include <sys/lock.h>
#include "mbedtls/aes.h"
#include "aes/esp_aes.h"5 includes
void esp_aes_xts_init( esp_aes_xts_context *ctx )
{
esp_aes_init( &ctx->crypt );
esp_aes_init( &ctx->tweak );
}{ ... }
void esp_aes_xts_free( esp_aes_xts_context *ctx )
{
esp_aes_free( &ctx->crypt );
esp_aes_free( &ctx->tweak );
}{ ... }
static int esp_aes_xts_decode_keys( const unsigned char *key,
unsigned int keybits,
const unsigned char **key1,
unsigned int *key1bits,
const unsigned char **key2,
unsigned int *key2bits )
{
const unsigned int half_keybits = keybits / 2;
const unsigned int half_keybytes = half_keybits / 8;
switch ( keybits ) {
case 256: break;
case 512: break;
default : return ( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}{...}
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
return 0;
}{ ... }
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if ( ret != 0 ) {
return ( ret );
}{...}
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if ( ret != 0 ) {
return ( ret );
}{...}
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}{ ... }
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if ( ret != 0 ) {
return ( ret );
}{...}
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if ( ret != 0 ) {
return ( ret );
}{...}
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}{ ... }
#ifndef GET_UINT64_LE
#define GET_UINT64_LE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
| ( (uint64_t) (b)[(i) ] ); \
}{...}
...#endif/* ... */
#ifndef PUT_UINT64_LE
#define PUT_UINT64_LE(n,b,i) \
{ \
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) ] = (unsigned char) ( (n) ); \
}{...}
...#endif/* ... */
/* ... */
static void esp_gf128mul_x_ble( unsigned char r[16],
const unsigned char x[16] )
{
uint64_t a, b, ra, rb;
GET_UINT64_LE( a, x, 0 );
GET_UINT64_LE( b, x, 8 );
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
rb = ( a >> 63 ) | ( b << 1 );
PUT_UINT64_LE( ra, r, 0 );
PUT_UINT64_LE( rb, r, 8 );
}{ ... }
/* ... */
int esp_aes_crypt_xts( esp_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
unsigned char prev_tweak[16];
unsigned char tmp[16];
if ( length < 16 ) {
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}{...}
if ( length > ( 1 << 20 ) * 16 ) {
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}{...}
ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
data_unit, tweak );
if ( ret != 0 ) {
return ( ret );
}{...}
while ( blocks-- ) {
size_t i;
if ( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) {
/* ... */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
esp_gf128mul_x_ble( tweak, tweak );
}{...}
for ( i = 0; i < 16; i++ ) {
tmp[i] = input[i] ^ tweak[i];
}{...}
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if ( ret != 0 ) {
return ( ret );
}{...}
for ( i = 0; i < 16; i++ ) {
output[i] = tmp[i] ^ tweak[i];
}{...}
esp_gf128mul_x_ble( tweak, tweak );
output += 16;
input += 16;
}{...}
if ( leftover ) {
/* ... */
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
/* ... */
size_t i;
unsigned char *prev_output = output - 16;
/* ... */
for ( i = 0; i < leftover; i++ ) {
output[i] = prev_output[i];
tmp[i] = input[i] ^ t[i];
}{...}
/* ... */
for ( ; i < 16; i++ ) {
tmp[i] = prev_output[i] ^ t[i];
}{...}
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if ( ret != 0 ) {
return ret;
}{...}
/* ... */
for ( i = 0; i < 16; i++ ) {
prev_output[i] = tmp[i] ^ t[i];
}{...}
}{...}
return ( 0 );
}{ ... }