mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
46a692fd22
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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)
|
||||
|
@ -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)
|
@ -1,2 +0,0 @@
|
||||
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- | -------- | -------- |
|
@ -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)
|
@ -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();
|
||||
}
|
@ -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
|
@ -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
|
@ -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)
|
@ -1 +0,0 @@
|
||||
# Empty file to be able to parametrize "default" config
|
@ -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
|
@ -1,2 +0,0 @@
|
||||
CONFIG_ESP_TASK_WDT_INIT=n
|
||||
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
|
@ -1,2 +0,0 @@
|
||||
# Set CPU frequency to max for performance tests
|
||||
# CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
@ -1,2 +0,0 @@
|
||||
# Set CPU frequency to max for performance tests
|
||||
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
|
Loading…
Reference in New Issue
Block a user