test(sha): add test cases for the esp_sm3 API

This commit is contained in:
Ashish Sharma
2026-08-24 14:24:04 +08:00
parent 0eabc80893
commit 62db6dd513

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2023-2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/
@@ -18,6 +18,11 @@
#include "sha_block.h"
#include "sha_dma.h"
#if SOC_SHA_SUPPORT_SM3
#include "esp_sm3.h"
#include "hal/sha_hal.h"
#endif
#if SOC_SHA_SUPPORTED
#if SOC_SHA_SUPPORT_SHA1
@@ -257,6 +262,133 @@ TEST(sha, test_sha256_dma)
#endif /* SOC_SHA_SUPPORT_DMA*/
#endif /* SOC_SHA_SUPPORT_SHA256 */
#if SOC_SHA_SUPPORT_SM3
/* Reference digests for SM3 test inputs (cross-checked with OpenSSL dgst -sm3):
* [0] "abc" (GM/T 0004-2012 spec vector)
* [1] "abcd" x 16 (one full 64-byte block)
* [2] 0xEE x 1030 (multi-block, non-aligned tail)
*/
static const uint8_t sm3_expected[3][32] = {
{
0x66, 0xc7, 0xf0, 0xf4, 0x62, 0xee, 0xed, 0xd9,
0xd1, 0xf2, 0xd4, 0x6b, 0xdc, 0x10, 0xe4, 0xe2,
0x41, 0x67, 0xc4, 0x87, 0x5c, 0xf2, 0xf7, 0xa2,
0x29, 0x7d, 0xa0, 0x2b, 0x8f, 0x4b, 0xa8, 0xe0,
},
{
0xde, 0xbe, 0x9f, 0xf9, 0x22, 0x75, 0xb8, 0xa1,
0x38, 0x60, 0x48, 0x89, 0xc1, 0x8e, 0x5a, 0x4d,
0x6f, 0xdb, 0x70, 0xe5, 0x38, 0x7e, 0x57, 0x65,
0x29, 0x3d, 0xcb, 0xa3, 0x9c, 0x0c, 0x57, 0x32,
},
{
0xfb, 0x7d, 0xd6, 0x4a, 0xd5, 0x0d, 0x5a, 0x16,
0x2e, 0x92, 0x90, 0xa0, 0xd8, 0x3f, 0xa6, 0x01,
0x86, 0x9b, 0x79, 0xf2, 0xda, 0xff, 0xbe, 0x16,
0xac, 0x6b, 0x6c, 0x06, 0x52, 0x21, 0x56, 0x0a,
},
};
/* Skip the esp_sm3 API tests when the chip forbids the SM crypto functions. */
static void sm3_api_skip_if_disabled(void)
{
if (!sha_hal_is_sm3_supported()) {
TEST_IGNORE_MESSAGE("SM crypto disabled by eFuse (DIS_SM_CRYPT)");
}
}
TEST(sha, test_sm3_api_one_shot)
{
uint8_t digest[ESP_SM3_DIGEST_LEN];
sm3_api_skip_if_disabled();
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3("abc", 3, digest, sizeof(digest)));
TEST_ASSERT_EQUAL_HEX8_ARRAY(sm3_expected[0], digest, sizeof(digest));
uint8_t one_block_input[ESP_SM3_BLOCK_LEN];
for (size_t i = 0; i < sizeof(one_block_input); i += 4) {
memcpy(&one_block_input[i], "abcd", 4);
}
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3(one_block_input, sizeof(one_block_input), digest, sizeof(digest)));
TEST_ASSERT_EQUAL_HEX8_ARRAY(sm3_expected[1], digest, sizeof(digest));
uint8_t *buffer = heap_caps_calloc(BUFFER_SZ, sizeof(uint8_t), MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buffer);
memset(buffer, 0xEE, BUFFER_SZ);
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3(buffer, BUFFER_SZ, digest, sizeof(digest)));
TEST_ASSERT_EQUAL_HEX8_ARRAY(sm3_expected[2], digest, sizeof(digest));
heap_caps_free(buffer);
}
/* Feed the message in uneven pieces. Every piece that does not end on a block
boundary forces the driver to save and restore the digest state. */
TEST(sha, test_sm3_api_streaming)
{
static const size_t chunk_sizes[] = { 1, 62, 1, 64, 3, 200, 128, 129 };
uint8_t digest[ESP_SM3_DIGEST_LEN];
esp_sm3_ctx_handle_t ctx;
sm3_api_skip_if_disabled();
uint8_t *buffer = heap_caps_calloc(BUFFER_SZ, sizeof(uint8_t), MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buffer);
memset(buffer, 0xEE, BUFFER_SZ);
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3_create(&ctx));
size_t offset = 0;
size_t index = 0;
while (offset < BUFFER_SZ) {
size_t chunk = chunk_sizes[index % (sizeof(chunk_sizes) / sizeof(chunk_sizes[0]))];
if (chunk > BUFFER_SZ - offset) {
chunk = BUFFER_SZ - offset;
}
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3_update(ctx, buffer + offset, chunk));
offset += chunk;
index++;
}
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3_finish(ctx, digest, sizeof(digest)));
esp_sm3_delete(ctx);
heap_caps_free(buffer);
TEST_ASSERT_EQUAL_HEX8_ARRAY(sm3_expected[2], digest, sizeof(digest));
}
TEST(sha, test_sm3_api_bad_args)
{
uint8_t digest[ESP_SM3_DIGEST_LEN];
sm3_api_skip_if_disabled();
/* A short output buffer must be rejected before any byte reaches it. */
memset(digest, 0xA5, sizeof(digest));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_SIZE,
esp_sm3("abc", 3, digest, ESP_SM3_DIGEST_LEN - 1));
for (size_t i = 0; i < sizeof(digest); i++) {
TEST_ASSERT_EQUAL_HEX8(0xA5, digest[i]);
}
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sm3("abc", 3, NULL, sizeof(digest)));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sm3(NULL, 3, digest, sizeof(digest)));
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_sm3_create(NULL));
/* An empty message is valid input. The digest comes from the padding
block alone, so it proves that the pad-only path works. */
static const uint8_t sm3_expected_empty[ESP_SM3_DIGEST_LEN] = {
0x1a, 0xb2, 0x1d, 0x83, 0x55, 0xcf, 0xa1, 0x7f,
0x8e, 0x61, 0x19, 0x48, 0x31, 0xe8, 0x1a, 0x8f,
0x22, 0xbe, 0xc8, 0xc7, 0x28, 0xfe, 0xfb, 0x74,
0x7e, 0xd0, 0x35, 0xeb, 0x50, 0x82, 0xaa, 0x2b,
};
TEST_ASSERT_EQUAL(ESP_OK, esp_sm3(NULL, 0, digest, sizeof(digest)));
TEST_ASSERT_EQUAL_HEX8_ARRAY(sm3_expected_empty, digest, sizeof(digest));
}
#endif /* SOC_SHA_SUPPORT_SM3 */
#if SOC_SHA_SUPPORT_SHA384
TEST(sha, test_sha384_block)
@@ -329,6 +461,12 @@ TEST_GROUP_RUNNER(sha)
#endif /* SOC_SHA_SUPPORT_DMA*/
#endif /* SOC_SHA_SUPPORT_SHA256 */
#if SOC_SHA_SUPPORT_SM3
RUN_TEST_CASE(sha, test_sm3_api_one_shot);
RUN_TEST_CASE(sha, test_sm3_api_streaming);
RUN_TEST_CASE(sha, test_sm3_api_bad_args);
#endif /* SOC_SHA_SUPPORT_SM3 */
#if SOC_SHA_SUPPORT_SHA384
RUN_TEST_CASE(sha, test_sha384_block);
#if SOC_SHA_SUPPORT_DMA