Merge branch 'feature/add_aes_xts_to_util' into 'master'

util: add AES XTS and its unit test

See merge request sdk/ESP8266_RTOS_SDK!1114
This commit is contained in:
Dong Heng
2019-09-25 10:30:22 +08:00
3 changed files with 321 additions and 3 deletions

View File

@ -27,6 +27,10 @@ typedef struct esp_aes {
uint32_t buf[68]; /*!< The AES calculation cache */
} esp_aes_t;
typedef struct esp_aes_xts {
esp_aes_t crypt; /*!< The AES context to use for AES block encryption or decryption. */
esp_aes_t tweak; /*!< The AES context used for tweak computation. */
} esp_aes_xts_t;
/**
* @brief Set AES encrypt key
@ -225,6 +229,42 @@ static inline int esp_aes_decrypt_ctr(esp_aes_t *aes, size_t *nc_off, void *p_no
return esp_aes_encrypt_ctr(aes, nc_off, p_nonce_counter, p_stream_block, p_src, slen, p_dst, dlen);
}
/**
* @brief Set AES XTS encrypt key
*
* @param aes AES XTS contex pointer
* @param p_key AES XTS key data buffer
* @param keybits number of AES XTS key bits
*
* @return 0 if success or fail
*/
int esp_aes_xts_set_encrypt_key(esp_aes_xts_t *aes, const void *p_key, size_t keybits);
/**
* @brief Set AES XTS decrypt key
*
* @param aes AES XTS contex pointer
* @param p_key AES XTS key data buffer
* @param keybits number of AES XTS key bits
*
* @return 0 if success or fail
*/
int esp_aes_xts_set_decrypt_key(esp_aes_xts_t *aes, const void *p_key, size_t keybits);
/**
* @brief AES XTS encrypt/decrypt calculation
*
* @param aes AES contex pointer
* @param encrypt 1 : encrypt, 0 : decrypt
* @param length data unit data length by bytes
* @param p_data_unit data unit buffer
* @param p_src input data buffer
* @param p_dst output data buffer
*
* @return 0 if success or fail
*/
int esp_aes_crypt_xts(esp_aes_xts_t *aes, int encrypt, size_t length, const void *p_data_unit, const void *p_src, void *p_dst);
#ifdef __cplusplus
}
#endif

View File

@ -528,7 +528,7 @@ static void __esp_aes_encrypt(esp_aes_t *aes, const void *p_src, void *p_dst)
PUT_UINT32_LE(X3, output, 12);
}
static int __esp_aes_decrypt(esp_aes_t *aes, const void *p_src, void *p_dst)
static void __esp_aes_decrypt(esp_aes_t *aes, const void *p_src, void *p_dst)
{
int i;
uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
@ -573,8 +573,6 @@ static int __esp_aes_decrypt(esp_aes_t *aes, const void *p_src, void *p_dst)
PUT_UINT32_LE(X1, output, 4);
PUT_UINT32_LE(X2, output, 8);
PUT_UINT32_LE(X3, output, 12);
return 0;
}
int esp_aes_encrypt(esp_aes_t *aes,
@ -864,3 +862,147 @@ int esp_aes_encrypt_ctr(esp_aes_t *aes,
return 0;
}
static void aes_xts_decode_keys(const uint8_t *key,
size_t keybits,
const uint8_t **key1,
size_t *key1bits,
const uint8_t **key2,
size_t *key2bits)
{
const size_t half_keybits = keybits / 2;
const size_t half_keybytes = half_keybits / 8;
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
}
static void aes_gf128mul_x_ble(uint8_t *r, const uint8_t *i)
{
uint64_t x[2], y[2];
memcpy(x, i, 16);
y[0] = (x[0] << 1) ^ 0x0087 >> (8 - ((x[1] >> 63 ) << 3));
y[1] = (x[0] >> 63) | (x[1] << 1);
memcpy(r, y, 16);
}
int esp_aes_xts_set_encrypt_key(esp_aes_xts_t *ctx, const void *p_key, size_t keybits)
{
int ret;
const uint8_t *key1, *key2;
size_t key1bits, key2bits;
const uint8_t *key = (const uint8_t *)p_key;
util_assert(ctx);
util_assert(key);
if (keybits != 256 && keybits != 512)
return -EINVAL;
aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits);
ret = esp_aes_set_encrypt_key(&ctx->tweak, key2, key2bits);
if (ret)
return ret;
return esp_aes_set_encrypt_key(&ctx->crypt, key1, key1bits);
}
int esp_aes_xts_set_decrypt_key(esp_aes_xts_t *ctx, const void *p_key, size_t keybits)
{
int ret;
const uint8_t *key1, *key2;
size_t key1bits, key2bits;
const uint8_t *key = (const uint8_t *)p_key;
util_assert(ctx);
util_assert(key);
if (keybits != 256 && keybits != 512)
return -EINVAL;
aes_xts_decode_keys(key, keybits, &key1, &key1bits, &key2, &key2bits);
ret = esp_aes_set_encrypt_key(&ctx->tweak, key2, key2bits);
if (ret)
return ret;
return esp_aes_set_decrypt_key(&ctx->crypt, key1, key1bits);
}
int esp_aes_crypt_xts(esp_aes_xts_t *ctx,
int encrypt,
size_t length,
const void *p_data_unit,
const void *p_src,
void *p_dst)
{
size_t blocks = length / 16;
size_t leftover = length % 16;
uint8_t tweak[16];
uint8_t prev_tweak[16];
uint8_t tmp[16];
void (*crypt_func)(esp_aes_t *aes, const void *p_src, void *p_dst);
const uint8_t *data_unit = (const uint8_t *)p_data_unit;
const uint8_t *input = (const uint8_t *)p_src;
uint8_t *output = (uint8_t *)p_dst;
util_assert(ctx);
util_assert(data_unit);
util_assert(input);
util_assert(output);
if (length < 16 || (length > (1 << 20) * 16))
return -EINVAL;
crypt_func = encrypt ? __esp_aes_encrypt : __esp_aes_decrypt;
__esp_aes_encrypt(&ctx->tweak, data_unit, tweak);
while (blocks--) {
if (blocks == 0 && leftover && !encrypt) {
memcpy(prev_tweak, tweak, sizeof(tweak));
aes_gf128mul_x_ble(tweak, tweak);
}
for (int i = 0; i < 16; i++)
tmp[i] = input[i] ^ tweak[i];
crypt_func(&ctx->crypt, tmp, tmp);
for (int i = 0; i < 16; i++)
output[i] = tmp[i] ^ tweak[i];
aes_gf128mul_x_ble(tweak, tweak);
output += 16;
input += 16;
}
if (leftover) {
int i;
uint8_t *t = encrypt ? tweak : prev_tweak;
uint8_t *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];
crypt_func(&ctx->crypt, tmp, tmp);
for (i = 0; i < 16; i++)
prev_output[i] = tmp[i] ^ t[i];
}
return 0;
}

View File

@ -112,6 +112,95 @@ static const uint32_t s_aes_ctr_result[3][8] = {
}
};
static const uint8_t aes_test_xts_key[][32] = {
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
},
{
0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8,
0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22
},
};
static const uint8_t aes_test_xts_pt32[][32] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44
},
{
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44
},
};
static const uint8_t aes_test_xts_ct32[][32] =
{
{
0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec,
0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92,
0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85,
0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e
},
{
0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e,
0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b,
0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4,
0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0
},
{
0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a,
0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2,
0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53,
0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89
},
};
static const uint8_t aes_test_xts_data_unit[][16] =
{
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
{
0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
},
};
TEST_CASE("Test AES-ECB", "[AES]")
{
uint32_t buf[4];
@ -451,3 +540,50 @@ TEST_CASE("Test AES-CTR", "[AES]")
// align: AES-CRT test cost time totally encode 344845 us and decode 344421 us, once cost is about encode 336 us and decode 336 us
// no align: AES-CRT test cost time totally encode 639256 us and decode 635343 us, once cost is about encode 624 us and decode 620 us
TEST_CASE("Test AES-XTS", "[AES]")
{
uint32_t encode_time = 0, decode_time = 0;
const int num_tests = sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key);
extern uint32_t esp_get_time(void);
for (int cnt = 0; cnt < TEST_AES_COUNT; cnt++) {
for (int i = 0; i < num_tests; i++) {
const int len = sizeof(*aes_test_xts_ct32);
uint32_t buf[8];
uint8_t key[32];
const uint8_t *data_unit = aes_test_xts_data_unit[i];
esp_aes_xts_t ctx_xts;
memcpy(key, aes_test_xts_key[i], 32);
TEST_ASSERT_TRUE(esp_aes_xts_set_encrypt_key(&ctx_xts, key, 256) == 0);
memcpy(buf, aes_test_xts_pt32[i], len);
uint32_t tmp = esp_get_time();
TEST_ASSERT_TRUE(esp_aes_crypt_xts(&ctx_xts, 1, len, data_unit, buf, buf) == 0);
encode_time += esp_get_time() - tmp;
TEST_ASSERT_TRUE(memcmp(buf, aes_test_xts_ct32[i], len) == 0);
TEST_ASSERT_TRUE(esp_aes_xts_set_decrypt_key(&ctx_xts, key, 256) == 0);
memcpy(buf, aes_test_xts_ct32[i], len);
tmp = esp_get_time();
TEST_ASSERT_TRUE(esp_aes_crypt_xts(&ctx_xts, 0, len, data_unit, buf, buf) == 0);
decode_time += esp_get_time() - tmp;
TEST_ASSERT_TRUE(memcmp(buf, aes_test_xts_pt32[i], len) == 0);
}
}
#if TEST_AES_DEBUG_TIME
printf("AES-XTS test cost time totally encode %u us and decode %u us, once cost is about encode %u us and decode %u us\n",
encode_time, decode_time, encode_time / TEST_AES_COUNT, decode_time / TEST_AES_COUNT);
#endif
}
// align: AES-XTS test cost time totally encode 723197 us and decode 533441 us, once cost is about encode 706 us and decode 520 us
// no align: AES-XTS test cost time totally encode 675249 us and decode 645998 us, once cost is about encode 659 us and decode 630 us