Merge branch 'bugfix/cleanup_hmac_ds_testapps' into 'master'

fix(esp_hw_support): fix redudancy in hmac and ds test apps

Closes IDF-7993

See merge request espressif/esp-idf!25781
This commit is contained in:
Mahavir Jain 2023-09-20 18:45:30 +08:00
commit 46a692fd22
22 changed files with 16 additions and 613 deletions

View File

@ -41,9 +41,3 @@ components/esp_hw_support/test_apps/rtc_power_modes:
- if: IDF_TARGET in ["esp32s2", "esp32s3", "esp32c2", "esp32c3"]
temporary: true
reason: the other targets are not tested yet
components/esp_hw_support/test_apps/security_support/esp_hw_support_unity_tests:
disable_test:
- if: IDF_TARGET in ["esp32h2"]
temporary: true
reason: H2 fails IDF-6898

View File

@ -3,6 +3,9 @@ set(srcs "test_app_main.c"
"test_fp.c"
"test_intr_alloc.c"
"test_dport_xt_highint5.S"
"test_ds.c"
"test_hmac.c"
"test_random.c"
)
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -16,7 +16,9 @@
#include "esp_heap_trace.h"
#endif
#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT -400
/* During merging of DS and HMAC testapps to this directory, maximum memory leak during running is 404,
so, updating TEST_MEMORY_LEAK_THRESHOLD_DEFAULT */
#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT -416
static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
void set_leak_threshold(int threshold)

View File

@ -415,11 +415,7 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#elif CONFIG_IDF_TARGET_ESP32C3
TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
ds_data.iv[bit / 8] ^= 1 << (bit % 8);
@ -435,11 +431,7 @@ TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#elif CONFIG_IDF_TARGET_ESP32C3
TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
ds_data.c[bit / 8] ^= 1 << (bit % 8);

View File

@ -41,7 +41,7 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]")
{
int ets_status;
setup_keyblock(EFUSE_BLK_KEY3, ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
// Results calculated with Python:
//
@ -64,7 +64,7 @@ TEST_CASE("HMAC 'downstream' JTAG Enable mode", "[hw_crypto]")
TEST_ASSERT_MESSAGE(ESP_OK == esp_efuse_batch_write_commit(),
"Error programming security efuse.\n");
TEST_ASSERT_EQUAL_HEX32_MESSAGE(ESP_OK, esp_hmac_jtag_enable(HMAC_KEY3, token_data),
TEST_ASSERT_EQUAL_HEX32_MESSAGE(ESP_OK, esp_hmac_jtag_enable(HMAC_KEY4, token_data),
"JTAG should be re-enabled now, please manually verify");
}
@ -78,7 +78,7 @@ TEST_CASE("HMAC 'upstream' MAC generation with zeroes", "[hw_crypto]")
{
uint8_t hmac[32];
setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
setup_keyblock(EFUSE_BLK_KEY5, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
const uint8_t zeroes[128] = { };
// Produce the HMAC of various numbers of zeroes
@ -163,7 +163,7 @@ TEST_CASE("HMAC 'upstream' MAC generation with zeroes", "[hw_crypto]")
const size_t num_zero_results = sizeof(zero_results) / sizeof(hmac_result);
for (int i = 0; i < num_zero_results; i++) {
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY4, zeroes, zero_results[i].msglen, hmac));
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY5, zeroes, zero_results[i].msglen, hmac));
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero_results[i].result, hmac, sizeof(hmac));
}
}
@ -173,7 +173,7 @@ TEST_CASE("HMAC 'upstream' MAC generation from data", "[hw_crypto]")
{
uint8_t hmac[32];
setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
setup_keyblock(EFUSE_BLK_KEY5, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
// 257 characters of pseudo-Latin from lipsum.com (not Copyright)
const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque..";
@ -961,7 +961,7 @@ TEST_CASE("HMAC 'upstream' MAC generation from data", "[hw_crypto]")
};
for (int i = 0; i < sizeof(results)/sizeof(hmac_result); i++) {
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY4, message, results[i].msglen, hmac));
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY5, message, results[i].msglen, hmac));
TEST_ASSERT_EQUAL_HEX8_ARRAY(results[i].result, hmac, sizeof(hmac));
}
}
@ -973,7 +973,7 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]")
// 257 characters of pseudo-Latin from lipsum.com (not Copyright)
const char *message = "Deleniti voluptas explicabo et assumenda. Sed et aliquid minus quis. Praesentium cupiditate quia nemo est. Laboriosam pariatur ut distinctio tenetur. Sunt architecto iure aspernatur soluta ut recusandae. Ut quibusdam occaecati ut qui sit dignissimos eaque..";
setup_keyblock(EFUSE_BLK_KEY4, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
setup_keyblock(EFUSE_BLK_KEY5, ESP_EFUSE_KEY_PURPOSE_HMAC_UP);
static const hmac_result results[] = {
{ .msglen = 255,
@ -985,7 +985,7 @@ TEST_CASE("HMAC 'upstream' wait lock", "[hw_crypto]")
};
for (int i = 0; i < sizeof(results)/sizeof(hmac_result); i++) {
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY4, message, results[i].msglen, hmac));
TEST_ESP_OK(esp_hmac_calculate(HMAC_KEY5, message, results[i].msglen, hmac));
TEST_ASSERT_EQUAL_HEX8_ARRAY(results[i].result, hmac, sizeof(hmac));
}
}

View File

@ -16,4 +16,4 @@ from pytest_embedded import Dut
indirect=True,
)
def test_esp_hw_support(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=120)
dut.run_all_single_board_cases(timeout=180)

View File

@ -1,10 +0,0 @@
# This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.16)
set(COMPONENTS main)
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
list(PREPEND SDKCONFIG_DEFAULTS "$ENV{IDF_PATH}/tools/test_apps/configs/sdkconfig.debug_helpers" "sdkconfig.defaults")
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(test_app_security_support)

View File

@ -1,2 +0,0 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -1,11 +0,0 @@
set(srcs "test_app_main.c"
"test_ds.c"
"test_hmac.c"
"test_random.c"
)
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
REQUIRES unity driver test_utils efuse
WHOLE_ARCHIVE)

View File

@ -1,75 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "unity.h"
#include "unity_test_runner.h"
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "test_config.h"
#ifdef CONFIG_HEAP_TRACING
#include "memory_checks.h"
#include "esp_heap_trace.h"
#endif
#define TEST_MEMORY_LEAK_THRESHOLD_DEFAULT -400
static int leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
void set_leak_threshold(int threshold)
{
leak_threshold = threshold;
}
static size_t before_free_8bit;
static size_t before_free_32bit;
static const char* TAG = "esp_hw_support_test_app";
static void check_leak(size_t before_free, size_t after_free, const char *type)
{
ssize_t delta = after_free - before_free;
printf("MALLOC_CAP_%s: Before %u bytes free, After %u bytes free (delta %d)\n", type, before_free, after_free, delta);
TEST_ASSERT_MESSAGE(delta >= leak_threshold, "memory leak");
}
void setUp(void)
{
// If heap tracing is enabled in kconfig, leak trace the test
#ifdef CONFIG_HEAP_TRACING
setup_heap_record();
heap_trace_start(HEAP_TRACE_LEAKS);
#endif
leak_threshold = TEST_MEMORY_LEAK_THRESHOLD_DEFAULT;
before_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
before_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
}
void tearDown(void)
{
/*Give idle task time to clean up*/
vTaskDelay(10);
#ifdef CONFIG_HEAP_TRACING
heap_trace_stop();
heap_trace_dump();
#endif
size_t after_free_8bit = heap_caps_get_free_size(MALLOC_CAP_8BIT);
size_t after_free_32bit = heap_caps_get_free_size(MALLOC_CAP_32BIT);
check_leak(before_free_8bit, after_free_8bit, "8BIT");
check_leak(before_free_32bit, after_free_32bit, "32BIT");
}
void app_main(void)
{
vTaskPrioritySet(NULL, TEST_TASK_PRIORITY);
ESP_LOGI(TAG, "Running esp-hw-support test app");
unity_run_menu();
}

View File

@ -1,9 +0,0 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#define TEST_TASK_PRIORITY 5

View File

@ -1,450 +0,0 @@
/*
* SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "unity.h"
#include "soc/soc_caps.h"
#if SOC_DIG_SIGN_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/efuse.h"
#include "esp32s2/rom/digital_signature.h"
#include "esp32s2/rom/aes.h"
#include "esp32s2/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C3
#include "esp32c3/rom/efuse.h"
#include "esp32c3/rom/digital_signature.h"
#include "esp32c3/rom/hmac.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/efuse.h"
#include "esp32s3/rom/digital_signature.h"
#include "esp32s3/rom/aes.h"
#include "esp32s3/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32C6
#include "esp32c6/rom/efuse.h"
#include "esp32c6/rom/digital_signature.h"
#include "esp32c6/rom/aes.h"
#include "esp32c6/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32H2
#include "esp32h2/rom/efuse.h"
#include "esp32h2/rom/digital_signature.h"
#include "esp32h2/rom/aes.h"
#include "esp32h2/rom/sha.h"
#elif CONFIG_IDF_TARGET_ESP32P4
#include "esp32p4/rom/efuse.h"
#include "esp32p4/rom/digital_signature.h"
#include "esp32p4/rom/aes.h"
#include "esp32p4/rom/sha.h"
#endif
#include "esp_ds.h"
#define NUM_RESULTS 10
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define DS_MAX_BITS (4096)
#else
#define DS_MAX_BITS (ETS_DS_MAX_BITS)
#endif
typedef struct {
uint8_t iv[ETS_DS_IV_LEN];
ets_ds_p_data_t p_data;
uint8_t expected_c[ETS_DS_C_LEN];
uint8_t hmac_key_idx;
uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS / 32];
} encrypt_testcase_t;
// Generated header digital_signature_test_cases_<bits>.h (by gen_digital_signature_tests.py) defines
// NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[]
// Some adaptations were made: removed the 512 bit case and changed RSA lengths to the enums from esp_ds.h
#if DS_MAX_BITS == 4096
#define RSA_LEN (ESP_DS_RSA_4096)
#include "digital_signature_test_cases_4096.h"
#elif DS_MAX_BITS == 3072
#define RSA_LEN (ESP_DS_RSA_3072)
#include "digital_signature_test_cases_3072.h"
#endif
_Static_assert(NUM_RESULTS == NUM_MESSAGES, "expected_results size should be the same as NUM_MESSAGES in generated header");
TEST_CASE("Digital Signature Parameter Encryption data NULL", "[hw_crypto] [ds]")
{
const char iv [32] = {0};
esp_ds_p_data_t p_data = {0};
const char key [32] = {0};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(NULL, iv, &p_data, key));
}
TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]")
{
esp_ds_data_t data = {0};
esp_ds_p_data_t p_data = {0};
const char key [32] = {0};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, NULL, &p_data, key));
}
TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds]")
{
esp_ds_data_t data = {0};
const char iv [32] = {0};
const char key [32] = {0};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, NULL, key));
}
TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]")
{
esp_ds_data_t data = {0};
const char iv [32] = {0};
esp_ds_p_data_t p_data = {0};
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, &p_data, NULL));
}
TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]")
{
for (int i = 0; i < NUM_CASES; i++) {
printf("Encrypting test case %d...\n", i);
const encrypt_testcase_t *t = &test_cases[i];
esp_ds_data_t result = { };
esp_ds_p_data_t p_data;
memcpy(p_data.Y, t->p_data.Y, DS_MAX_BITS / 8);
memcpy(p_data.M, t->p_data.M, DS_MAX_BITS / 8);
memcpy(p_data.Rb, t->p_data.Rb, DS_MAX_BITS / 8);
p_data.M_prime = t->p_data.M_prime;
p_data.length = t->p_data.length;
esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data,
test_hmac_keys[t->hmac_key_idx]);
printf("Encrypting test case %d done\n", i);
TEST_ASSERT_EQUAL(ESP_OK, r);
TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->iv, result.iv, ETS_DS_IV_LEN);
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_c, result.c, ETS_DS_C_LEN);
}
}
TEST_CASE("Digital Signature start Invalid message", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = { };
ds_data.rsa_length = RSA_LEN;
esp_ds_context_t *ctx;
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(NULL, &ds_data, HMAC_KEY1, &ctx));
}
TEST_CASE("Digital Signature start Invalid data", "[hw_crypto] [ds]")
{
const char *message = "test";
esp_ds_context_t *ctx;
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, NULL, HMAC_KEY1, &ctx));
}
TEST_CASE("Digital Signature start Invalid context", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = RSA_LEN;
const char *message = "test";
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
}
TEST_CASE("Digital Signature RSA length 0", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = 0;
const char *message = "test";
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
}
TEST_CASE("Digital Signature RSA length too long", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = 128;
const char *message = "test";
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
}
TEST_CASE("Digital Signature start HMAC key out of range", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = RSA_LEN;
esp_ds_context_t *ctx;
const char *message = "test";
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY5 + 1, &ctx));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY0 - 1, &ctx));
}
TEST_CASE("Digital Signature finish Invalid signature ptr", "[hw_crypto] [ds]")
{
esp_ds_context_t *ctx = NULL;
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(NULL, ctx));
}
TEST_CASE("Digital Signature finish Invalid context", "[hw_crypto] [ds]")
{
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(signature_data, NULL));
}
TEST_CASE("Digital Signature Blocking Invalid message", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = { };
ds_data.rsa_length = RSA_LEN;
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(NULL, &ds_data, HMAC_KEY1, signature_data));
}
TEST_CASE("Digital Signature Blocking Invalid data", "[hw_crypto] [ds]")
{
const char *message = "test";
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, NULL, HMAC_KEY1, signature_data));
}
TEST_CASE("Digital Signature Blocking Invalid signature ptr", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = RSA_LEN;
const char *message = "test";
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, NULL));
}
TEST_CASE("Digital Signature Blocking RSA length 0", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = 0;
const char *message = "test";
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
}
TEST_CASE("Digital Signature Blocking RSA length too long", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = 128;
const char *message = "test";
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
}
TEST_CASE("Digital Signature Blocking HMAC key out of range", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = 127;
const char *message = "test";
uint8_t signature_data [128 * 4];
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY5 + 1, signature_data));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY0 - 1, signature_data));
}
#if CONFIG_IDF_ENV_FPGA
static void burn_hmac_keys(void)
{
printf("Burning %d HMAC keys to efuse...\n", NUM_HMAC_KEYS);
for (int i = 0; i < NUM_HMAC_KEYS; i++) {
// TODO: vary the purpose across the keys
ets_efuse_purpose_t purpose = ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE;
// starting from block 1, block 0 occupied with HMAC upstream test key
int __attribute__((unused)) ets_status = ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i,
purpose,
test_hmac_keys[i], 32);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (ets_status == ESP_OK) {
printf("written DS test key to block [%d]!\n", ETS_EFUSE_BLOCK_KEY1 + i);
} else {
printf("writing DS test key to block [%d] failed, maybe written already\n", ETS_EFUSE_BLOCK_KEY1 + i);
}
#endif
}
#if CONFIG_IDF_TARGET_ESP32C3
/* verify the keys are what we expect (possibly they're already burned, doesn't matter but they have to match) */
uint8_t block_compare[32];
for (int i = 0; i < NUM_HMAC_KEYS; i++) {
printf("Checking key %d...\n", i);
memcpy(block_compare, (void *)ets_efuse_get_read_register_address(ETS_EFUSE_BLOCK_KEY1 + i), 32);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test_hmac_keys[i], block_compare, 32);
}
#endif
}
// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = RSA_LEN;
esp_ds_context_t *ctx;
const char *message = "test";
// HMAC fails in that case because it checks for the correct purpose
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx));
}
// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
{
esp_ds_data_t ds_data = {};
ds_data.rsa_length = RSA_LEN;
const char *message = "test";
uint8_t signature_data [128 * 4];
// HMAC fails in that case because it checks for the correct purpose
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data));
}
TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]")
{
burn_hmac_keys();
for (int i = 0; i < NUM_CASES; i++) {
printf("Running test case %d...\n", i);
const encrypt_testcase_t *t = &test_cases[i];
// copy encrypt parameter test case into ds_data structure
esp_ds_data_t ds_data = { };
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
ds_data.rsa_length = t->p_data.length;
for (int j = 0; j < NUM_MESSAGES; j++) {
uint8_t signature[DS_MAX_BITS / 8] = { 0 };
printf(" ... message %d\n", j);
esp_ds_context_t *esp_ds_ctx;
esp_err_t ds_r = esp_ds_start_sign(test_messages[j],
&ds_data,
t->hmac_key_idx + 1,
&esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[j], signature, sizeof(signature));
}
#if CONFIG_IDF_TARGET_ESP32C3
ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
#endif
}
}
TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]")
{
burn_hmac_keys();
for (int i = 0; i < NUM_CASES; i++) {
printf("Running test case %d...\n", i);
const encrypt_testcase_t *t = &test_cases[i];
// copy encrypt parameter test case into ds_data structure
esp_ds_data_t ds_data = { };
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
ds_data.rsa_length = t->p_data.length;
uint8_t signature[DS_MAX_BITS / 8] = { 0 };
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
esp_ds_context_t *esp_ds_ctx;
esp_err_t ds_r = esp_ds_start_sign(test_messages[0],
&ds_data,
t->hmac_key_idx + 1,
&esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
#else
esp_err_t ds_r = esp_ds_sign(test_messages[0],
&ds_data,
t->hmac_key_idx + 1,
signature);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[0], signature, sizeof(signature));
}
}
TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
{
burn_hmac_keys();
// Set up a valid test case
const encrypt_testcase_t *t = &test_cases[0];
esp_ds_data_t ds_data = { };
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
ds_data.rsa_length = t->p_data.length;
uint8_t signature[DS_MAX_BITS / 8] = { 0 };
const uint8_t zero[DS_MAX_BITS / 8] = { 0 };
// Corrupt the IV one bit at a time, rerun and expect failure
for (int bit = 0; bit < 128; bit++) {
printf("Corrupting IV bit %d...\n", bit);
ds_data.iv[bit / 8] ^= 1 << (bit % 8);
esp_ds_context_t *esp_ds_ctx;
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#elif CONFIG_IDF_TARGET_ESP32C3
TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
ds_data.iv[bit / 8] ^= 1 << (bit % 8);
}
// Corrupt encrypted key data one bit at a time, rerun and expect failure
printf("Corrupting C...\n");
for (int bit = 0; bit < ETS_DS_C_LEN * 8; bit++) {
printf("Corrupting C bit %d...\n", bit);
ds_data.c[bit / 8] ^= 1 << (bit % 8);
esp_ds_context_t *esp_ds_ctx;
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
TEST_ASSERT_EQUAL(ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#elif CONFIG_IDF_TARGET_ESP32C3
TEST_ASSERT_EQUAL(ESP32C3_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS / 8);
ds_data.c[bit / 8] ^= 1 << (bit % 8);
}
}
#endif // CONFIG_IDF_ENV_FPGA
#endif // SOC_DIG_SIGN_SUPPORTED

View File

@ -1,18 +0,0 @@
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: CC0-1.0
import pytest
from pytest_embedded import Dut
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
pytest.param('default', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='test failed IDF-6898')]),
pytest.param('release', marks=[pytest.mark.supported_targets, pytest.mark.temp_skip_ci(targets=['esp32h2'], reason='test failed IDF-6898')]),
],
indirect=True,
)
def test_security_support(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=120)

View File

@ -1 +0,0 @@
# Empty file to be able to parametrize "default" config

View File

@ -1,6 +0,0 @@
# set compiler optimization level
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_SIZE=y
# we can silent the assertion to save the binary footprint
CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y

View File

@ -1,2 +0,0 @@
CONFIG_ESP_TASK_WDT_INIT=n
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

View File

@ -1,2 +0,0 @@
# Set CPU frequency to max for performance tests
# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

View File

@ -1,2 +0,0 @@
# Set CPU frequency to max for performance tests
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y