esp_aes_gcm_finish(): assert triggered (BUG?)
Posted: Wed Sep 01, 2021 1:04 pm
Hey,
using esp-idf plugin v1.1.1 with code v4.3 I get an assertion while trying to decrypt aes128gcm:
Here's a a stripped down code example with all input data zeroed out that causes this:
The problem seems to be the tag with length 12. Enlarging it to 16 doesn't cause the assertion. With size 12 in file ~/esp/esp-idf/components/mbedtls/port/aes/esp_aes_gcm.c line 488 parameter stream_block is set to zero:
... and so esp_aes_crypt_ctr() calls in line 1001 of ~/esp/esp-idf/components/mbedtls/port/aes/esp_aes.c ...
... which leads to this assertion in function esp_aes_process_dma(), line 308 of file ~/esp/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c:
where stream_bytes = 12 and stream_out = NULL.
I tried to fix it by providing an non-NULL stream in esp_aes_gcm_finish() just as it's done in esp_aes_gcm_update(), but I cannot say if that's actually a fix and doesn't just hide a bug elsewhere leading to wrong results:
Could someone knowledgeable please have a look at this and, ideally, fix it properly?
using esp-idf plugin v1.1.1 with code v4.3 I get an assertion while trying to decrypt aes128gcm:
Code: Select all
assertion "stream_bytes == 0 || stream_out != NULL" failed: file "$HOME/esp/esp-idf/components/mbedtls/port/aes/dma/esp_aes.c", line 308, function: esp_aes_process_dma
Code: Select all
static void test(void)
{
static const uint8_t key[16] = { 0 };
static const uint8_t iv[12] = { 0 };
static const uint8_t aad[16] = { 0 };
static const uint8_t tag[12] = { 0 };
static const uint8_t input[90] = { 0 };
static uint8_t output[90] = { 0 };
mbedtls_gcm_context ctx;
mbedtls_gcm_init(&ctx);
(void)mbedtls_gcm_setkey(&ctx, MBEDTLS_CIPHER_ID_AES, key, 128);
mbedtls_gcm_auth_decrypt(&ctx, sizeof(input),
iv, sizeof(iv),
aad, sizeof(aad),
tag, sizeof(tag),
input, output);
mbedtls_gcm_free(&ctx);
}
Code: Select all
esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, 0, ctx->ghash, tag);
Code: Select all
esp_aes_process_dma(ctx, input, output, 12 /*length*/, 0 /*stream_block*/);
Code: Select all
assert(stream_bytes == 0 || stream_out != NULL);
I tried to fix it by providing an non-NULL stream in esp_aes_gcm_finish() just as it's done in esp_aes_gcm_update(), but I cannot say if that's actually a fix and doesn't just hide a bug elsewhere leading to wrong results:
Code: Select all
diff --git a/components/mbedtls/port/aes/esp_aes_gcm.c b/components/mbedtls/port/aes/esp_aes_gcm.c
old mode 100644
new mode 100755
index b8cb59f22..c20ba9fe6
--- a/components/mbedtls/port/aes/esp_aes_gcm.c
+++ b/components/mbedtls/port/aes/esp_aes_gcm.c
@@ -474,6 +474,7 @@ int esp_aes_gcm_finish( esp_gcm_context *ctx,
{
size_t nc_off = 0;
uint8_t len_block[AES_BLOCK_BYTES] = {0};
+ uint8_t stream[AES_BLOCK_BYTES] = {0};
if ( tag_len > 16 || tag_len < 4 ) {
return ( MBEDTLS_ERR_GCM_BAD_INPUT );
@@ -485,7 +486,7 @@ int esp_aes_gcm_finish( esp_gcm_context *ctx,
esp_gcm_ghash(ctx, len_block, AES_BLOCK_BYTES, ctx->ghash);
/* Tag T = GCTR(J0, ) where T is truncated to tag_len */
- esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, 0, ctx->ghash, tag);
+ esp_aes_crypt_ctr(&ctx->aes_ctx, tag_len, &nc_off, ctx->ori_j0, stream, ctx->ghash, tag);
return 0;
}
Could someone knowledgeable please have a look at this and, ideally, fix it properly?