forked from espressif/esp-idf
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'fix/support_gcm_soft_fallback_for_non_aes_ciphers_v5.2'…
… into 'release/v5.2' fix(mbedtls/gcm): Add support for software fallback for non-AES ciphers in a GCM operation (v5.2) See merge request espressif/esp-idf!29250
- Loading branch information
Showing
7 changed files
with
316 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
#pragma once | ||
|
||
#include_next "mbedtls/gcm.h" | ||
#include "sdkconfig.h" | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
#endif | ||
|
||
#if defined(MBEDTLS_GCM_ALT) && defined(MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK) | ||
|
||
/** | ||
* When the MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK is defined, for non-AES GCM | ||
* operations we need to fallback to the software function definitions of the | ||
* mbedtls GCM layer. | ||
* Thus in this case we need declarations for the software funtions. | ||
* Please refer mbedtls/include/mbedtls/gcm.h for function documentations | ||
*/ | ||
|
||
void mbedtls_gcm_init_soft(mbedtls_gcm_context_soft *ctx); | ||
|
||
|
||
int mbedtls_gcm_setkey_soft(mbedtls_gcm_context_soft *ctx, | ||
mbedtls_cipher_id_t cipher, | ||
const unsigned char *key, | ||
unsigned int keybits); | ||
|
||
int mbedtls_gcm_starts_soft(mbedtls_gcm_context_soft *ctx, | ||
int mode, | ||
const unsigned char *iv, size_t iv_len); | ||
|
||
int mbedtls_gcm_update_ad_soft(mbedtls_gcm_context_soft *ctx, | ||
const unsigned char *add, size_t add_len); | ||
|
||
int mbedtls_gcm_update_soft(mbedtls_gcm_context_soft *ctx, | ||
const unsigned char *input, size_t input_length, | ||
unsigned char *output, size_t output_size, | ||
size_t *output_length); | ||
|
||
int mbedtls_gcm_finish_soft(mbedtls_gcm_context_soft *ctx, | ||
unsigned char *output, size_t output_size, | ||
size_t *output_length, | ||
unsigned char *tag, size_t tag_len); | ||
|
||
|
||
int mbedtls_gcm_crypt_and_tag_soft(mbedtls_gcm_context_soft *ctx, | ||
int mode, | ||
size_t length, | ||
const unsigned char *iv, | ||
size_t iv_len, | ||
const unsigned char *add, | ||
size_t add_len, | ||
const unsigned char *input, | ||
unsigned char *output, | ||
size_t tag_len, | ||
unsigned char *tag); | ||
|
||
|
||
int mbedtls_gcm_auth_decrypt_soft(mbedtls_gcm_context_soft *ctx, | ||
size_t length, | ||
const unsigned char *iv, | ||
size_t iv_len, | ||
const unsigned char *add, | ||
size_t add_len, | ||
const unsigned char *tag, | ||
size_t tag_len, | ||
const unsigned char *input, | ||
unsigned char *output); | ||
|
||
void mbedtls_gcm_free_soft(mbedtls_gcm_context_soft *ctx); | ||
|
||
#endif /* MBEDTLS_GCM_ALT && MBEDTLS_GCM_NON_AES_CIPHER_SOFT_FALLBACK*/ | ||
|
||
#ifdef __cplusplus | ||
} | ||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
* SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD | ||
* | ||
* SPDX-License-Identifier: Unlicense OR CC0-1.0 | ||
*/ | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include "sys/param.h" | ||
#include "esp_heap_caps.h" | ||
#include "mbedtls/gcm.h" | ||
#include "sdkconfig.h" | ||
#include "unity.h" | ||
|
||
|
||
#if CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER | ||
|
||
typedef struct { | ||
uint8_t *plaintext; | ||
size_t plaintext_length; | ||
uint8_t *aad_buf; | ||
size_t aad_length; | ||
uint8_t *iv; | ||
size_t iv_length; | ||
uint8_t *key; | ||
size_t key_bits; | ||
size_t tag_len; | ||
} gcm_test_cfg_t; | ||
|
||
typedef struct { | ||
const uint8_t *expected_tag; | ||
const uint8_t *ciphertext_last_block; // Last block of the ciphertext | ||
} gcm_test_expected_res_t; | ||
|
||
typedef enum { | ||
GCM_TEST_CRYPT_N_TAG, | ||
GCM_TEST_START_UPDATE_FINISH, | ||
} gcm_test_type_t; | ||
|
||
static void gcm_test(gcm_test_cfg_t *cfg, gcm_test_expected_res_t *res, gcm_test_type_t gcm_type) | ||
{ | ||
mbedtls_gcm_context ctx; | ||
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_ARIA; | ||
|
||
uint8_t tag_buf_encrypt[16] = {}; | ||
uint8_t tag_buf_decrypt[16] = {}; | ||
uint8_t iv_buf[16] = {}; | ||
uint8_t *ciphertext = malloc(cfg->plaintext_length); | ||
uint8_t *output = malloc(cfg->plaintext_length); | ||
size_t olen; | ||
|
||
if (cfg->plaintext_length != 0) { | ||
TEST_ASSERT_NOT_NULL(ciphertext); | ||
TEST_ASSERT_NOT_NULL(output); | ||
} | ||
|
||
memset(ciphertext, 0, cfg->plaintext_length); | ||
memset(output, 0, cfg->plaintext_length); | ||
memcpy(iv_buf, cfg->iv, cfg->iv_length); | ||
|
||
mbedtls_gcm_init(&ctx); | ||
TEST_ASSERT(mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits) == 0); | ||
|
||
if (gcm_type == GCM_TEST_CRYPT_N_TAG) { | ||
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_GCM_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt); | ||
} else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { | ||
TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_ENCRYPT, iv_buf, cfg->iv_length) == 0); | ||
TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); | ||
TEST_ASSERT(mbedtls_gcm_update(&ctx, cfg->plaintext, cfg->plaintext_length, ciphertext, cfg->plaintext_length, &olen) == 0); | ||
TEST_ASSERT(mbedtls_gcm_finish(&ctx, ciphertext, cfg->plaintext_length, &olen, tag_buf_encrypt, cfg->tag_len) == 0); | ||
} | ||
|
||
size_t offset = cfg->plaintext_length > 16 ? cfg->plaintext_length - 16 : 0; | ||
/* Sanity check: make sure the last ciphertext block matches what we expect to see. */ | ||
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->ciphertext_last_block, ciphertext + offset, MIN(16, cfg->plaintext_length)); | ||
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_encrypt, cfg->tag_len); | ||
|
||
|
||
if (gcm_type == GCM_TEST_CRYPT_N_TAG) { | ||
TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->aad_buf, cfg->aad_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0); | ||
} else if (gcm_type == GCM_TEST_START_UPDATE_FINISH) { | ||
TEST_ASSERT(mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv_buf, cfg->iv_length) == 0); | ||
TEST_ASSERT(mbedtls_gcm_update_ad(&ctx, cfg->aad_buf, cfg->aad_length) == 0); | ||
TEST_ASSERT(mbedtls_gcm_update(&ctx, ciphertext, cfg->plaintext_length, output, cfg->plaintext_length, &olen) == 0); | ||
TEST_ASSERT(mbedtls_gcm_finish(&ctx, output, cfg->plaintext_length, &olen, tag_buf_decrypt, cfg->tag_len) == 0); | ||
|
||
/* mbedtls_gcm_auth_decrypt already checks tag so only needed for GCM_TEST_START_UPDATE_FINISH */ | ||
TEST_ASSERT_EQUAL_HEX8_ARRAY(res->expected_tag, tag_buf_decrypt, cfg->tag_len); | ||
} | ||
|
||
TEST_ASSERT_EQUAL_HEX8_ARRAY(cfg->plaintext, output, cfg->plaintext_length); | ||
|
||
mbedtls_gcm_free(&ctx); | ||
free(ciphertext); | ||
free(output); | ||
} | ||
|
||
|
||
TEST_CASE("mbedtls ARIA GCM test", "[gcm]") | ||
{ | ||
const unsigned SZ = 1600; | ||
uint8_t aad[16]; | ||
uint8_t iv[16]; | ||
uint8_t key[16]; | ||
|
||
const uint8_t expected_last_block[] = { | ||
0xbe, 0x96, 0xf1, 0x57, 0x34, 0x07, 0x3f, 0x9d, | ||
0x87, 0x6b, 0x39, 0x22, 0xe4, 0xef, 0xff, 0xf0, | ||
}; | ||
const uint8_t expected_tag[] = { | ||
0xef, 0x4e, 0xa8, 0x24, 0x07, 0x65, 0x36, 0x12, | ||
0xb1, 0xde, 0x7e, 0x23, 0xda, 0xea, 0x7c, 0x6b, | ||
}; | ||
|
||
uint8_t *plaintext = malloc(SZ); | ||
TEST_ASSERT_NOT_NULL(plaintext); | ||
|
||
memset(plaintext, 0xAA, SZ); | ||
memset(iv, 0xEE, 16); | ||
memset(key, 0x44, 16); | ||
memset(aad, 0x76, 16); | ||
|
||
gcm_test_cfg_t cfg = { | ||
.plaintext = plaintext, | ||
.plaintext_length = SZ, | ||
.iv = iv, | ||
.iv_length = sizeof(iv), | ||
.key = key, | ||
.key_bits = 8 * sizeof(key), | ||
.aad_buf = aad, | ||
.aad_length = sizeof(aad), | ||
.tag_len = 16 | ||
}; | ||
|
||
gcm_test_expected_res_t res = { | ||
.expected_tag = expected_tag, | ||
.ciphertext_last_block = expected_last_block, | ||
}; | ||
|
||
gcm_test(&cfg, &res, GCM_TEST_CRYPT_N_TAG); | ||
gcm_test(&cfg, &res, GCM_TEST_START_UPDATE_FINISH); | ||
free(plaintext); | ||
} | ||
|
||
#endif /* CONFIG_MBEDTLS_GCM_SUPPORT_NON_AES_CIPHER */ |