feat: update mbedTLS test apps to PSA APIs

This commit is contained in:
Ashish Sharma
2025-12-23 11:00:13 +08:00
committed by Mahavir Jain
parent 1d7c30c533
commit 45966c2009
31 changed files with 2724 additions and 4576 deletions
@@ -16,7 +16,7 @@
#define IDF_PERFORMANCE_MAX_TIME_SHA1_32KB 900
#define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 13500
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 15500
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 650000
#define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 36000
#define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 960000
@@ -14,7 +14,7 @@
#define IDF_PERFORMANCE_MAX_TIME_SHA1_32KB 1000
#define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 18000
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 23000
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 700000
#define IDF_PERFORMANCE_MAX_RSA_3072KEY_PUBLIC_OP 45000
#define IDF_PERFORMANCE_MAX_RSA_3072KEY_PRIVATE_OP 1300000
@@ -3,8 +3,13 @@ set(TEST_CRTS "crts/server_cert_chain.pem"
"crts/server_cert_bundle"
"crts/bad_md_crt.pem"
"crts/wrong_sig_crt_esp32_com.pem"
"crts/correct_sig_crt_esp32_com.pem")
idf_component_register(SRC_DIRS "."
"crts/correct_sig_crt_esp32_com.pem"
"crts/ecdsa_cert_bundle"
"crts/ecdsa_correct_sig_crt.pem"
"crts/ecdsa_wrong_sig_crt.pem")
idf_component_register(
SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES efuse cmock test_utils mbedtls esp_timer unity spi_flash esp_psram esp_security
EMBED_TXTFILES ${TEST_CRTS}
@@ -13,7 +18,6 @@ idf_component_register(SRC_DIRS "."
idf_component_get_property(mbedtls mbedtls COMPONENT_LIB)
target_compile_definitions(${mbedtls} INTERFACE "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedtls PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedcrypto PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")
target_compile_definitions(mbedx509 PUBLIC "-DMBEDTLS_DEPRECATED_WARNING")
# Add linker wrap option to override esp_ds_finish_sign
+25 -4
View File
@@ -1,15 +1,19 @@
/*
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <string.h>
#include "psa/crypto.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "unity.h"
#include "mbedtls/aes.h"
#include "memory_checks.h"
#include "soc/soc_caps.h"
#include "esp_newlib.h"
#include "esp_random.h"
#define CALL_SZ (32 * 1024)
/* setUp runs before every test */
void setUp(void)
@@ -17,8 +21,25 @@ void setUp(void)
// Execute mbedtls_aes_init operation to allocate AES interrupt
// allocation memory which is considered as leak otherwise
#if SOC_AES_SUPPORTED
mbedtls_aes_context ctx;
mbedtls_aes_init(&ctx);
uint8_t iv[16];
uint8_t key[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_ECB_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
psa_import_key(&attributes, key, sizeof(key), &key_id);
size_t output_length = 0;
psa_cipher_encrypt(key_id, PSA_ALG_ECB_NO_PADDING, buf, CALL_SZ, buf, CALL_SZ, &output_length);
heap_caps_free(buf);
psa_destroy_key(key_id);
#endif // SOC_AES_SUPPORTED
test_utils_record_free_mem();
@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICQjCCAcmgAwIBAgIUTbvKUa+55zFxQhgDIQ91RdGXEXIwCgYIKoZIzj0EAwQw
YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxFjAU
BgNVBAoMDVRlc3QgRUNEU0EgQ0ExGzAZBgNVBAMMElRlc3QgRUNEU0EgUm9vdCBD
QTAeFw0yNTExMDMwODAzNTdaFw0yNjExMDMwODAzNTdaMGIxCzAJBgNVBAYTAlVT
MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRQwEgYDVQQKDAtUZXN0IFNl
cnZlcjEfMB0GA1UEAwwWZWNkc2EtdGVzdC5leGFtcGxlLmNvbTB2MBAGByqGSM49
AgEGBSuBBAAiA2IABFd+Bd6HtASMpEytx+QfDk8I0DX73EKQ3tR2TUJuhg7B2epc
qqmMXZ5KQpOY/+V0kv1WyLCDisw7vP6d4yQjokSJqEnaO3af5TJh0WCjWJsVtNZy
VAQMS9lxSZW1a1lle6NCMEAwHQYDVR0OBBYEFNJ2LzJjqMZXRjY0NNvVTS3Crsjh
MB8GA1UdIwQYMBaAFElMhoUHf0Loi7Kzcpp0t4AfUBsuMAoGCCqGSM49BAMEA2cA
MGQCMCiXh9m1BOkedod4lVzKLx535sLbFM7OxnYFxYOCK4Q3djtgxjy0OFmlyD5I
YLUfxAIwO35NHh06OMyOI85NJbOYD2oPDiju/1JYHhER9rPAFrJJtwKGhNlMufqk
V+9SwUK2
-----END CERTIFICATE-----
@@ -0,0 +1,15 @@
-----BEGIN CERTIFICATE-----
MIICQjCCAcmgAwIBAgIUTbvKUa+55zFxQhgDIQ91RdGXEXIwCgYIKoZIzj0EAwQw
YDELMAkGA1UEBhMCVVMxDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3QxFjAU
BgNVBAoMDVRlc3QgRUNEU0EgQ0ExGzAZBgNVBAMMElRlc3QgRUNEU0EgUm9vdCBD
QTAeFw0yNTExMDMwODAzNTdaFw0yNjExMDMwODAzNTdaMGIxCzAJBgNVBAYTAlVT
MQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0MRQwEgYDVQQKDAtUZXN0IFNl
cnZlcjEfMB0GA1UEAwwWZWNkc2EtdGVzdC5leGFtcGxlLmNvbTB2MBAGByqGSM49
AgEGBSuBBAAiA2IABFd+Bd6HtASMpEytx+QfDk8I0DX73EKQ3tR2TUJuhg7B2epc
qqmMXZ5KQpOY/+V0kv1WyLCDisw7vP6d4yQjokSJqEnaO3af5TJh0WCjWJsVtNZy
VAQMS9lxSZW1a1lle6NCMEAwHQYDVR0OBBYEFNJ2LzJjqMZXRjY0NNvVTS3Crsjh
MB8GA1UdIwQYMBaAFElMhoUHf0Loi7Kzcpp0t4AfUBsuMAoGCCqGSM49BAMEA2cA
MGQCMCiXh9m1BOkedod4lVzKMx535sLbFM7OxnYFxYOCK4Q3djtgxjy0OFmlyD5I
YLUfxAIwO35NHh06OMyOI85NJbOYD2oPDiju/1JYHhER9rPAFrJJtwKGhNlMufqk
V+9SwUK2
-----END CERTIFICATE-----
File diff suppressed because it is too large Load Diff
@@ -1,885 +0,0 @@
/* mbedTLS GCM test
*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "ccomp_timer.h"
#include "sys/param.h"
#if CONFIG_MBEDTLS_HARDWARE_AES
/*
Python example code for generating test vectors
import os, binascii
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def as_c_array(byte_arr):
hex_str = ''
for idx, byte in enumerate(byte_arr):
hex_str += "0x{:02x}, ".format(byte)
bytes_per_line = 8
if idx % bytes_per_line == bytes_per_line - 1:
hex_str += '\n'
return hex_str
key = b'\x44' * 16
iv = b'\xEE' * 16
data = b'\xAA' * 3200
aad = b'\x76' * 16
aesgcm = AESGCM(key)
ct = aesgcm.encrypt(iv, data, aad)
print(as_c_array(ct))
*/
TEST_CASE("mbedtls GCM stream test", "[aes-gcm]")
{
const unsigned SZ = 100;
mbedtls_gcm_context ctx;
uint8_t nonce[16];
uint8_t key[16];
uint8_t tag[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
const uint8_t expected_cipher[] = {
0x03, 0x92, 0x13, 0x49, 0x1f, 0x1f, 0x24, 0x41,
0xe8, 0xeb, 0x89, 0x47, 0x50, 0x0a, 0xce, 0xa3,
0xc7, 0x1c, 0x10, 0x70, 0xb0, 0x89, 0x82, 0x5e,
0x0f, 0x4a, 0x23, 0xee, 0xd2, 0xfc, 0xff, 0x45,
0x61, 0x4c, 0xd1, 0xfb, 0x6d, 0xe2, 0xbe, 0x67,
0x6f, 0x94, 0x72, 0xa3, 0xe7, 0x04, 0x99, 0xb3,
0x4a, 0x46, 0xf9, 0x2b, 0xaf, 0xac, 0xa9, 0x0e,
0x43, 0x7e, 0x8b, 0xc4, 0xbf, 0x49, 0xa4, 0x83,
0x9c, 0x31, 0x11, 0x1c, 0x09, 0xac, 0x90, 0xdf,
0x00, 0x34, 0x08, 0xe5, 0x70, 0xa3, 0x7e, 0x4b,
0x36, 0x48, 0x5a, 0x3f, 0x28, 0xc7, 0x1c, 0xd9,
0x1b, 0x1b, 0x49, 0x96, 0xe9, 0x7c, 0xea, 0x54,
0x7c, 0x71, 0x29, 0x0d
};
const uint8_t expected_tag[] = {
0x35, 0x1c, 0x21, 0xc6, 0xbc, 0x6b, 0x18, 0x52,
0x90, 0xe1, 0xf2, 0x5b, 0xe1, 0xf6, 0x15, 0xee,
};
memset(nonce, 0x89, 16);
memset(key, 0x56, 16);
// allocate internal memory
uint8_t *ciphertext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
memset(plaintext, 0xAB, SZ);
/* Test that all the end results are the same
no matter how many bytes we encrypt each call
*/
for (int bytes_to_process = 16; bytes_to_process < SZ; bytes_to_process = bytes_to_process + 16) {
memset(nonce, 0x89, 16);
memset(ciphertext, 0x0, SZ);
memset(decryptedtext, 0x0, SZ);
memset(tag, 0x0, 16);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, nonce, sizeof(nonce) );
mbedtls_gcm_update_ad( &ctx, NULL, 0 );
size_t olen;
// Encrypt
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, plaintext + idx, length, ciphertext + idx, length, &olen);
}
mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag, sizeof(tag));
// Decrypt
memset(nonce, 0x89, 16);
mbedtls_gcm_free( &ctx );
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey(&ctx, cipher, key, 128);
mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, nonce, sizeof(nonce));
mbedtls_gcm_update_ad( &ctx, NULL, 0 );
for (int idx = 0; idx < SZ; idx = idx + bytes_to_process) {
// Limit length of last call to avoid exceeding buffer size
size_t length = (idx + bytes_to_process > SZ) ? (SZ - idx) : bytes_to_process;
mbedtls_gcm_update(&ctx, ciphertext + idx, length, decryptedtext + idx, length, &olen);
}
mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag, sizeof(tag) );
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_gcm_free( &ctx );
}
free(plaintext);
free(ciphertext);
free(decryptedtext);
}
TEST_CASE("mbedtls AES GCM self-tests", "[aes-gcm]")
{
TEST_ASSERT_FALSE_MESSAGE(mbedtls_gcm_self_test(1), "AES GCM self-test should pass.");
}
typedef struct {
uint8_t *plaintext;
size_t plaintext_length;
uint32_t output_caps;
uint8_t *add_buf;
size_t add_length;
uint8_t *iv;
size_t iv_length;
uint8_t *key;
size_t key_bits;
size_t tag_len;
} aes_gcm_test_cfg_t;
typedef struct {
const uint8_t *expected_tag;
const uint8_t *ciphertext_last_block; // Last block of the ciphertext
} aes_gcm_test_expected_res_t;
typedef enum {
AES_GCM_TEST_CRYPT_N_TAG,
AES_GCM_TEST_START_UPDATE_FINISH,
} aes_gcm_test_type_t;
static void aes_gcm_test(aes_gcm_test_cfg_t *cfg, aes_gcm_test_expected_res_t *res, aes_gcm_test_type_t aes_gcm_type)
{
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
mbedtls_gcm_context ctx;
uint8_t tag_buf_encrypt[16] = {};
uint8_t tag_buf_decrypt[16] = {};
uint8_t iv_buf[16] = {};
uint8_t *ciphertext = heap_caps_malloc(cfg->plaintext_length, cfg->output_caps);
uint8_t *output = heap_caps_malloc(cfg->plaintext_length, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
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);
mbedtls_gcm_setkey(&ctx, cipher, cfg->key, cfg->key_bits);
size_t olen;
/* Encrypt and tag */
if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, cfg->plaintext, ciphertext, cfg->tag_len, tag_buf_encrypt);
} else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH) {
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv_buf, cfg->iv_length) == 0 );
TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, cfg->add_buf, cfg->add_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, NULL, 0, &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);
/* Decrypt and authenticate */
if (aes_gcm_type == AES_GCM_TEST_CRYPT_N_TAG) {
TEST_ASSERT(mbedtls_gcm_auth_decrypt(&ctx, cfg->plaintext_length, iv_buf, cfg->iv_length, cfg->add_buf, cfg->add_length, res->expected_tag, cfg->tag_len, ciphertext, output) == 0);
} else if (aes_gcm_type == AES_GCM_TEST_START_UPDATE_FINISH) {
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_DECRYPT, iv_buf, cfg->iv_length) == 0 );
TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, cfg->add_buf, cfg->add_length) == 0 );
TEST_ASSERT(mbedtls_gcm_update( &ctx, ciphertext, cfg->plaintext_length, output, cfg->plaintext_length, &olen) == 0 );
TEST_ASSERT(mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf_decrypt, cfg->tag_len) == 0 );
/* mbedtls_gcm_auth_decrypt already checks tag so only needed for AES_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 AES GCM", "[aes-gcm]")
{
uint8_t iv[16];
uint8_t key[16];
uint8_t add[30];
memset(iv, 0xB1, sizeof(iv));
memset(key, 0x27, sizeof(key));
memset(add, 0x90, sizeof(add));
size_t length[] = {10, 16, 500, 5000, 12345};
const uint8_t expected_last_block[][16] = {
{
0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
0x60, 0x72
},
{
0x37, 0x99, 0x4b, 0x16, 0x5f, 0x8d, 0x27, 0xb1,
0x60, 0x72, 0x9a, 0x81, 0x8d, 0x3c, 0x69, 0x66
},
{
0x9d, 0x7a, 0xac, 0x84, 0xe3, 0x70, 0x43, 0x0f,
0xa7, 0x83, 0x43, 0xc9, 0x04, 0xf8, 0x7d, 0x48
},
{
0xee, 0xfd, 0xab, 0x2a, 0x09, 0x44, 0x41, 0x6a,
0x91, 0xb0, 0x74, 0x24, 0xee, 0x35, 0xb1, 0x39
},
{
0x51, 0xf7, 0x1f, 0x67, 0x1a, 0x4a, 0x12, 0x37,
0x60, 0x3b, 0x68, 0x01, 0x20, 0x4f, 0xf3, 0xd9
},
};
const uint8_t expected_tag[][16] = {
{
0x06, 0x4f, 0xb5, 0x91, 0x12, 0x24, 0xb4, 0x24,
0x0b, 0xc2, 0x85, 0x59, 0x6a, 0x7c, 0x1f, 0xc9
},
{
0x45, 0xc2, 0xa8, 0xfe, 0xff, 0x49, 0x1f, 0x45,
0x8e, 0x29, 0x74, 0x41, 0xed, 0x9b, 0x54, 0x28
},
{
0xe1, 0xf9, 0x40, 0xfa, 0x29, 0x6f, 0x30, 0xae,
0xb6, 0x9b, 0x33, 0xdb, 0x8a, 0xf9, 0x70, 0xc4
},
{
0x22, 0xe1, 0x22, 0x34, 0x0c, 0x91, 0x0b, 0xcf,
0xa3, 0x42, 0xe0, 0x48, 0xe6, 0xfe, 0x2e, 0x28
},
{
0xfb, 0xfe, 0x5a, 0xed, 0x26, 0x5c, 0x5e, 0x66,
0x4e, 0xb2, 0x48, 0xce, 0xe9, 0x88, 0x1c, 0xe0
},
};
aes_gcm_test_cfg_t cfg = {
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.iv = iv,
.iv_length = sizeof(iv),
.key = key,
.key_bits = 8 * sizeof(key),
.add_buf = add,
.add_length = sizeof(add),
.tag_len = 16
};
aes_gcm_test_expected_res_t res = {
};
for (int i = 0; i < sizeof(length) / sizeof(length[0]); i++) {
printf("Test AES-GCM with plaintext length = %d\n", length[i]);
uint8_t *input = heap_caps_malloc(length[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(input != NULL || length[i] == 0);
memset(input, 0x36, length[i]);
cfg.plaintext = input;
cfg.plaintext_length = length[i];
res.expected_tag = expected_tag[i];
res.ciphertext_last_block = expected_last_block[i],
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
free(input);
}
}
TEST_CASE("mbedtls AES GCM - Different add messages", "[aes-gcm]")
{
const unsigned CALL_SZ = 160;
uint8_t iv[16];
uint8_t key[16];
uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(input);
memset(input, 0x67, CALL_SZ);
memset(iv, 0xA2, sizeof(iv));
memset(key, 0x48, sizeof(key));
const uint8_t expected_last_block[] = {
0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d,
0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed
};
size_t add_len[] = {0, 10, 16, 500, 5000};
const uint8_t expected_tag[][16] = {
{
0xe3, 0x91, 0xad, 0x40, 0x96, 0xb7, 0x8c, 0x53,
0x4d, 0x15, 0x7d, 0x55, 0x15, 0xdf, 0x10, 0x69
},
{
0xc2, 0x38, 0x36, 0xe9, 0x12, 0x72, 0x5b, 0x31,
0x0c, 0xde, 0xb5, 0xc9, 0x8c, 0xa3, 0xcb, 0xe7
},
{
0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba,
0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac
},
{
0x3c, 0x28, 0x03, 0xc2, 0x14, 0x40, 0xec, 0xb6,
0x25, 0xfb, 0xdd, 0x55, 0xa0, 0xb2, 0x47, 0x7b
},
{
0xfa, 0x66, 0x4a, 0x97, 0x2d, 0x02, 0x32, 0x5b,
0x92, 0x94, 0xf1, 0x00, 0x1c, 0xfa, 0xe3, 0x07
}
};
aes_gcm_test_cfg_t cfg = {
.plaintext = input,
.plaintext_length = CALL_SZ,
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.iv = iv,
.iv_length = sizeof(iv),
.key = key,
.key_bits = 8 * sizeof(key),
.tag_len = 16
};
aes_gcm_test_expected_res_t res = {
.ciphertext_last_block = expected_last_block,
};
for (int i = 0; i < sizeof(add_len) / sizeof(add_len[0]); i++) {
printf("Test AES-GCM with add length = %d\n", add_len[i]);
uint8_t *add = heap_caps_malloc(add_len[i], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(add != NULL || add_len[i] == 0);
memset(add, 0x12, add_len[i]);
cfg.add_buf = add;
cfg.add_length = add_len[i];
res.expected_tag = expected_tag[i];
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
free(add);
}
free(input);
}
TEST_CASE("mbedtls AES GCM performance, start, update, ret", "[aes-gcm]")
{
const unsigned CALL_SZ = 16 * 3200;
mbedtls_gcm_context ctx;
float elapsed_usec;
unsigned char tag_buf[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
uint8_t aad[16];
size_t olen;
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
memset(aad, 0x76, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
ccomp_timer_start();
memset(buf, 0xAA, CALL_SZ);
TEST_ASSERT(mbedtls_gcm_starts( &ctx, MBEDTLS_AES_ENCRYPT, iv, sizeof(iv) ) == 0 );
TEST_ASSERT(mbedtls_gcm_update_ad( &ctx, aad, sizeof(aad)) == 0 );
TEST_ASSERT(mbedtls_gcm_update( &ctx, buf, CALL_SZ, buf, CALL_SZ, &olen) == 0 );
TEST_ASSERT(mbedtls_gcm_finish( &ctx, NULL, 0, &olen, tag_buf, 16 ) == 0 );
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
*/
const uint8_t expected_last_block[] = {
0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
};
const uint8_t expected_tag[] = {
0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
free(buf);
// bytes/usec = MB/sec
float mb_sec = CALL_SZ / elapsed_usec;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
// Don't put a hard limit on software AES performance
TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_GCM_UPDATE_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}
TEST_CASE("mbedtls AES GCM performance, crypt-and-tag", "[aes-gcm]")
{
const unsigned CALL_SZ = 16 * 3200;
mbedtls_gcm_context ctx;
float elapsed_usec;
unsigned char tag_buf[16] = {};
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
uint8_t aad[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
memset(aad, 0x76, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
memset(buf, 0xAA, CALL_SZ);
ccomp_timer_start();
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), aad, sizeof(aad), buf, buf, 16, tag_buf);
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
*/
const uint8_t expected_last_block[] = {
0xd4, 0x25, 0x88, 0xd4, 0x32, 0x52, 0x3d, 0x6f,
0xae, 0x49, 0x19, 0xb5, 0x95, 0x01, 0xde, 0x7d,
};
const uint8_t expected_tag[] = {
0xf5, 0x10, 0x1f, 0x21, 0x5b, 0x07, 0x0d, 0x3f,
0xac, 0xc9, 0xd0, 0x42, 0x45, 0xef, 0xc7, 0xfa,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_tag, tag_buf, 16);
free(buf);
// bytes/usec = MB/sec
float mb_sec = CALL_SZ / elapsed_usec;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
// Don't put a hard limit on software AES performance
TEST_PERFORMANCE_CCOMP_GREATER_THAN(AES_GCM_CRYPT_TAG_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif
}
TEST_CASE("mbedtls AES GCM - Combine different IV/Key/Plaintext/AAD lengths", "[aes-gcm]")
{
#define IV_BYTES_VALUE 0xA2
#define KEY_BYTES_VALUE 0x48
#define INPUT_BYTES_VALUE 0x36
#define ADD_BYTES_VALUE 0x12
uint8_t iv[16];
uint8_t key[32];
memset(iv, IV_BYTES_VALUE, sizeof(iv));
memset(key, KEY_BYTES_VALUE, sizeof(key));
/* Key length is: 16 bytes, 32 bytes */
size_t key_length[] = {16, 32};
/* IV length is: 12 bytes (standard), 16 bytes */
size_t iv_length[] = {12, 16};
/* Plaintext length is: a multiple of 16 bytes, a non-multiple of 16 bytes */
size_t length[] = {160, 321};
/* Add len is: 0, a multiple of 16 bytes, a non-multiple of 16 bytes */
size_t add_len[] = {0, 160, 321};
/*indexes: Key - IV - Plaintext */
const uint8_t expected_last_block[2][2][2][16] = {
{
/* 16 byte key */
{
{
0xa2, 0x1e, 0x23, 0x3c, 0xfc, 0x7c, 0xec, 0x9a,
0x91, 0xe5, 0xdb, 0x3a, 0xe5, 0x0c, 0x3f, 0xc2,
},
{
0xa8, 0xeb, 0x40, 0x9b, 0x7b, 0x87, 0x07,
0x68, 0x17, 0x5c, 0xc0, 0xb7, 0xb4, 0xb3, 0x81,
0xbe,
}
},
{
{
0x9c, 0xe8, 0xfc, 0x3e, 0x98, 0x64, 0x70, 0x5c,
0x98, 0x0c, 0xbb, 0x88, 0xa6, 0x4c, 0x12, 0xbc
},
{
0x8b, 0x66, 0xf5, 0xbc, 0x56, 0x59, 0xae,
0xf0, 0x9e, 0x5c, 0xdb, 0x6d, 0xfc, 0x1f, 0x2e,
0x00
}
},
},
{
/* 32 byte key */
{
{
0xde, 0xc2, 0xd3, 0xeb, 0x5e, 0x03, 0x53, 0x4b,
0x04, 0x0d, 0x63, 0xf1, 0xd8, 0x5b, 0x1f, 0x85,
},
{
0xb5, 0x53, 0x8e, 0xd3, 0xab, 0x10, 0xf1,
0x77, 0x41, 0x92, 0xea, 0xdd, 0xdd, 0x9e, 0x5d,
0x40,
}
},
{
{
0x3b, 0xc7, 0xf0, 0x3f, 0xba, 0x97, 0xbd, 0xa0,
0xa5, 0x48, 0xf3, 0x7a, 0xde, 0x23, 0x19, 0x7a,
},
{
0x57, 0xc7, 0x4d, 0xe3, 0x79, 0x5e, 0xbd,
0x0d, 0xd7, 0x6a, 0xef, 0x1f, 0x54, 0x29, 0xa6,
0xd7,
}
},
},
};
/*indexes: Key - IV - Plaintext - Add len*/
const uint8_t expected_tag[2][2][2][3][16] = {
{
{
{
// Plaintext 160 bytes
{
0x67, 0x92, 0xb1, 0x7f, 0x44, 0x1f, 0x95, 0xfb,
0x33, 0x76, 0x66, 0xb7, 0x4f, 0x3e, 0xec, 0x4d,
},
{
0xb1, 0x99, 0xed, 0x1b, 0x4e, 0x12, 0x87, 0x5e,
0xf4, 0xe3, 0x81, 0xd8, 0x96, 0x07, 0xda, 0xff,
},
{
0x73, 0x35, 0x0c, 0xf5, 0x70, 0x1e, 0xc0, 0x99,
0x34, 0xba, 0x1a, 0x50, 0x23, 0xac, 0x21, 0x33,
},
},
{
// Plaintext 321 bytes
{
0x2d, 0xf6, 0xd0, 0x7a, 0x75, 0x4d, 0x9d,
0xb5, 0x9d, 0x43, 0xbf, 0x57, 0x10, 0xa3, 0xff,
0x3d
},
{
0x06, 0x91, 0xe4, 0x38, 0x3a, 0xe1, 0x6e,
0x2d, 0x83, 0x68, 0x2e, 0xb0, 0x26, 0x2f, 0xe4,
0x78
},
{
0x1b, 0x58, 0x2f, 0x9b, 0xe9, 0xe0, 0xe0,
0x43, 0x83, 0x08, 0xec, 0x58, 0x3a, 0x78, 0xe9,
0x69,
}
}
},
{
{
// Plaintext 160 bytes
{
0x77, 0xe5, 0x2e, 0x2d, 0x94, 0xb8, 0x03, 0x61,
0x7a, 0xd5, 0x0c, 0x3c, 0x9c, 0x40, 0x92, 0x9b
},
{
0xa1, 0xee, 0x72, 0x49, 0x9e, 0xb5, 0x11, 0xc4,
0xbd, 0x40, 0xeb, 0x53, 0x45, 0x79, 0xa4, 0x29
},
{
0x63, 0x42, 0x93, 0xa7, 0xa0, 0xb9, 0x56, 0x03,
0x7d, 0x19, 0x70, 0xdb, 0xf0, 0xd2, 0x5f, 0xe5
},
},
{
// Plaintext 321 bytes
{
0x50, 0xa3, 0x79, 0xfc, 0x17, 0xb8, 0xf4,
0xf6, 0x14, 0xaa, 0x4a, 0xe7, 0xd4, 0xa0, 0xea,
0xee
},
{
0x7b, 0xc4, 0x4d, 0xbe, 0x58, 0x14, 0x07,
0x6e, 0x0a, 0x81, 0xdb, 0x00, 0xe2, 0x2c, 0xf1,
0xab
},
{
0x66, 0x0d, 0x86, 0x1d, 0x8b, 0x15, 0x89,
0x00, 0x0a, 0xe1, 0x19, 0xe8, 0xfe, 0x7b, 0xfc,
0xba
}
}
},
},
{
{
{
// Plaintext 160 bytes
{
0x04, 0x04, 0x15, 0xb1, 0xd3, 0x98, 0x15, 0x45,
0xa2, 0x44, 0xba, 0x4a, 0xde, 0xc2, 0x8d, 0xd6,
},
{
0x94, 0x3e, 0xc3, 0x5d, 0xdc, 0x42, 0xf6, 0x4c,
0x80, 0x15, 0xe4, 0xb9, 0x0b, 0xc9, 0x87, 0x01,
},
{
0x93, 0x6e, 0x26, 0x5b, 0x7e, 0x17, 0xc8, 0x73,
0x9b, 0x71, 0x31, 0x7a, 0x8b, 0x0e, 0x19, 0x89,
}
},
{
// Plaintext 321 bytes
{
0x99, 0x5e, 0x77, 0x28, 0x8b, 0xa8, 0x9b,
0xb3, 0x35, 0xc3, 0x99, 0x90, 0xd4, 0x5d, 0x63,
0xa7,
},
{
0xbc, 0xc2, 0x9f, 0xe6, 0x38, 0xef, 0xf5,
0x11, 0x76, 0x09, 0x17, 0x3a, 0xd4, 0x91, 0xee,
0xfe,
},
{
0x9f, 0xa6, 0x23, 0x5a, 0x4d, 0x78, 0xae,
0xce, 0x10, 0x35, 0xc1, 0x0c, 0x6e, 0xc2, 0x4e,
0xe8,
}
}
},
{
{
// Plaintext 160 bytes
{
0xfb, 0x74, 0x7e, 0x21, 0xf2, 0xe7, 0xe3, 0xf5,
0xfa, 0xc8, 0x23, 0xab, 0x54, 0x9a, 0xb9, 0xcf,
},
{
0x6b, 0x4e, 0xa8, 0xcd, 0xfd, 0x3d, 0x00, 0xfc,
0xd8, 0x99, 0x7d, 0x58, 0x81, 0x91, 0xb3, 0x18,
},
{
0x6c, 0x1e, 0x4d, 0xcb, 0x5f, 0x68, 0x3e, 0xc3,
0xc3, 0xfd, 0xa8, 0x9b, 0x01, 0x56, 0x2d, 0x90,
},
},
{
// Plaintext 321 bytes
{
0xcd, 0x49, 0x75, 0x4c, 0x2a, 0x62, 0x65,
0x6f, 0xfe, 0x14, 0xc2, 0x5d, 0x41, 0x07, 0x24,
0x55
},
{
0xe8, 0xd5, 0x9d, 0x82, 0x99, 0x25, 0x0b,
0xcd, 0xbd, 0xde, 0x4c, 0xf7, 0x41, 0xcb, 0xa9,
0x0c,
},
{
0xcb, 0xb1, 0x21, 0x3e, 0xec, 0xb2, 0x50,
0x12, 0xdb, 0xe2, 0x9a, 0xc1, 0xfb, 0x98, 0x09,
0x1a,
}
}
},
},
};
aes_gcm_test_cfg_t cfg = {
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.tag_len = 16
};
for (int i_key = 0; i_key < sizeof(key_length) / sizeof(key_length[0]); i_key++) {
printf("Test AES-GCM with key length = %d\n", key_length[i_key]);
cfg.key = key;
cfg.key_bits = 8 * key_length[i_key];
for (int i_iv = 0; i_iv < sizeof(iv_length) / sizeof(iv_length[0]); i_iv++) {
printf("Test AES-GCM with IV length = %d\n", iv_length[i_iv]);
cfg.iv = iv;
cfg.iv_length = iv_length[i_iv];
for (int i_len = 0; i_len < sizeof(length) / sizeof(length[0]); i_len++) {
printf("Test AES-GCM with plaintext length = %d\n", length[i_len]);
uint8_t *input = heap_caps_malloc(length[i_len], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(input != NULL || length[i_len] == 0);
memset(input, INPUT_BYTES_VALUE, length[i_len]);
cfg.plaintext = input;
cfg.plaintext_length = length[i_len];
aes_gcm_test_expected_res_t res = {0};
for (int i_add = 0; i_add < sizeof(add_len) / sizeof(add_len[0]); i_add++) {
printf("Test AES-GCM with add length = %d\n", add_len[i_add]);
uint8_t *add = heap_caps_malloc(add_len[i_add], MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT(add != NULL || add_len[i_add] == 0);
memset(add, ADD_BYTES_VALUE, add_len[i_add]);
cfg.add_buf = add;
cfg.add_length = add_len[i_add];
res.expected_tag = expected_tag[i_key][i_iv][i_len][i_add];
res.ciphertext_last_block = expected_last_block[i_key][i_iv][i_len],
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
free(add);
}
free(input);
}
}
}
}
TEST_CASE("mbedtls AES GCM - Different Authentication Tag lengths", "[aes-gcm]")
{
const unsigned CALL_SZ = 160;
uint8_t iv[16];
uint8_t key[16];
uint8_t aad[16];
uint8_t *input = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(input);
memset(input, 0x67, CALL_SZ);
memset(iv, 0xA2, sizeof(iv));
memset(key, 0x48, sizeof(key));
memset(aad, 0x12, sizeof(aad));
size_t tag_len[] = {4, 8, 11, 16};
const uint8_t expected_last_block[] = {
0xcd, 0xb9, 0xad, 0x6f, 0xc9, 0x35, 0x21, 0x0d,
0xc9, 0x5d, 0xea, 0xd9, 0xf7, 0x1d, 0x43, 0xed
};
const uint8_t expected_tag[16] = {
0x57, 0x10, 0x22, 0x91, 0x65, 0xfa, 0x89, 0xba,
0x0a, 0x3e, 0xc1, 0x7c, 0x93, 0x6e, 0x35, 0xac
};
aes_gcm_test_cfg_t cfg = {
.plaintext = input,
.plaintext_length = CALL_SZ,
.output_caps = MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL,
.add_buf = aad,
.add_length = sizeof(aad),
.iv = iv,
.iv_length = sizeof(iv),
.key = key,
.key_bits = 8 * sizeof(key),
};
aes_gcm_test_expected_res_t res = {
.expected_tag = expected_tag,
.ciphertext_last_block = expected_last_block,
};
for (int i = 0; i < sizeof(tag_len) / sizeof(tag_len[0]); i++) {
printf("Test AES-GCM with tag length = %d\n", tag_len[i]);
cfg.tag_len = tag_len[i];
aes_gcm_test(&cfg, &res, AES_GCM_TEST_CRYPT_N_TAG);
aes_gcm_test(&cfg, &res, AES_GCM_TEST_START_UPDATE_FINISH);
}
free(input);
}
#endif //CONFIG_MBEDTLS_HARDWARE_AES
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
@@ -9,8 +9,8 @@
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "psa/crypto.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
@@ -22,25 +22,48 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
{
const unsigned CALLS = 256;
const unsigned CALL_SZ = 32 * 1024;
mbedtls_aes_context ctx;
float elapsed_usec;
uint8_t iv[16];
uint8_t key[16];
psa_status_t status;
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key, 128);
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CBC_NO_PADDING);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
status = psa_import_key(&attributes, key, sizeof(key), &key_id);
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("Failed to import key");
}
psa_cipher_operation_t operation = PSA_CIPHER_OPERATION_INIT;
status = psa_cipher_encrypt_setup(&operation, key_id, PSA_ALG_CBC_NO_PADDING);
if (status != PSA_SUCCESS) {
printf("Failed to setup AES encryption with status: %ld\n", status);
TEST_FAIL_MESSAGE("Failed to setup AES encryption");
}
status = psa_cipher_set_iv(&operation, iv, sizeof(iv));
if (status != PSA_SUCCESS) {
TEST_FAIL_MESSAGE("Failed to set IV for AES encryption");
}
ccomp_timer_start();
size_t output_length = 0;
for (int c = 0; c < CALLS; c++) {
memset(buf, 0xAA, CALL_SZ);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, buf, buf);
psa_cipher_update(&operation, buf, CALL_SZ, buf, CALL_SZ, &output_length);
}
psa_cipher_finish(&operation, buf + output_length, CALL_SZ - output_length, &output_length);
elapsed_usec = ccomp_timer_stop();
/* Sanity check: make sure the last ciphertext block matches
@@ -63,7 +86,8 @@ TEST_CASE("mbedtls AES performance", "[aes][timeout=60]")
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
mbedtls_aes_free(&ctx);
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
free(buf);
// bytes/usec = MB/sec
@@ -1,13 +1,11 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/sha256.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
@@ -15,6 +13,7 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "psa/crypto.h"
#if CONFIG_MBEDTLS_HARDWARE_AES || CONFIG_MBEDTLS_HARDWARE_SHA
@@ -29,18 +28,20 @@ static const uint8_t sha256_thousand_bs[32] = {
static void tskRunSHA256Test(void *pvParameters)
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t status;
size_t hash_length = 0;
for (int i = 0; i < 1000; i++) {
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
status = psa_hash_setup(&operation, PSA_ALG_SHA_256);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
for (int j = 0; j < 10; j++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100));
status = psa_hash_update(&operation, (unsigned char *)one_hundred_bs, 100);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
mbedtls_sha256_free(&sha256_ctx);
status = psa_hash_finish(&operation, sha256, sizeof(sha256), &hash_length);
operation = psa_hash_operation_init();
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation");
}
xSemaphoreGive(done_sem);
@@ -62,10 +63,20 @@ static void tskRunAES256Test(void *pvParameters)
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
for (int i = 0; i <1000; i++)
{
const unsigned SZ = 1600;
mbedtls_aes_context ctx;
psa_cipher_operation_t ctx = PSA_CIPHER_OPERATION_INIT;
uint8_t nonce[16];
const uint8_t expected_cipher_end[] = {
@@ -86,24 +97,28 @@ static void tskRunAES256Test(void *pvParameters)
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(decryptedtext);
mbedtls_aes_init(&ctx);
mbedtls_aes_setkey_enc(&ctx, key_256, 256);
psa_cipher_encrypt_setup(&ctx, key_id, PSA_ALG_CBC_NO_PADDING);
psa_cipher_set_iv(&ctx, nonce, sizeof(nonce));
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
// Encrypt
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, SZ, nonce, plaintext, ciphertext);
size_t enc_len = 0;
psa_cipher_update(&ctx, plaintext, SZ, ciphertext, SZ, &enc_len);
psa_cipher_finish(&ctx, ciphertext + enc_len, SZ - enc_len, &enc_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - 32, 32);
// Decrypt
memcpy(nonce, iv, 16);
mbedtls_aes_setkey_dec(&ctx, key_256, 256);
mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, SZ, nonce, ciphertext, decryptedtext);
psa_cipher_decrypt_setup(&ctx, key_id, PSA_ALG_CBC_NO_PADDING);
psa_cipher_set_iv(&ctx, nonce, sizeof(nonce));
psa_cipher_update(&ctx, ciphertext, SZ, decryptedtext, SZ, &enc_len);
psa_cipher_finish(&ctx, decryptedtext + enc_len, SZ - enc_len, &enc_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
mbedtls_aes_free(&ctx);
psa_cipher_abort(&ctx);
free(plaintext);
free(ciphertext);
free(decryptedtext);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -9,7 +9,7 @@
#include <sdkconfig.h>
#if CONFIG_IDF_TARGET_ESP32
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "esp_types.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -22,8 +22,7 @@
#include "esp_log.h"
#include "sha/sha_parallel_engine.h"
#include "aes/esp_aes.h"
#include "mbedtls/rsa.h"
#include "mbedtls/sha256.h"
#include "psa/crypto.h"
static const char *TAG = "test";
static volatile bool exit_flag = false;
@@ -74,27 +73,33 @@ static void mbedtls_sha256_task(void *pvParameters)
SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters;
ESP_LOGI(TAG, "mbedtls_sha256_task is started");
const char *input = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[]^_abcdefghijklmnopqrstuvwxyz~DEL0123456789Space!#$%&()*+,-.0123456789:;<=>?";
mbedtls_sha256_context sha256_ctx;
unsigned char output[32];
unsigned char output_origin[32];
mbedtls_sha256_init(&sha256_ctx);
psa_hash_operation_t sha256_op = PSA_HASH_OPERATION_INIT;
psa_status_t status = psa_hash_setup(&sha256_op, PSA_ALG_SHA_256);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
memset(output, 0, sizeof(output));
mbedtls_sha256_starts(&sha256_ctx, false);
for (int i = 0; i < 3; ++i) {
mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100);
status = psa_hash_update(&sha256_op, (const uint8_t *)input, 100);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
mbedtls_sha256_finish(&sha256_ctx, output);
size_t hash_length = 0;
status = psa_hash_finish(&sha256_op, output, sizeof(output), &hash_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
memcpy(output_origin, output, sizeof(output));
while (exit_flag == false) {
mbedtls_sha256_init(&sha256_ctx);
psa_hash_operation_t sha256_operation = PSA_HASH_OPERATION_INIT;
status = psa_hash_setup(&sha256_operation, PSA_ALG_SHA_256);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
memset(output, 0, sizeof(output));
mbedtls_sha256_starts(&sha256_ctx, false);
for (int i = 0; i < 3; ++i) {
mbedtls_sha256_update(&sha256_ctx, (unsigned char *)input, 100);
status = psa_hash_update(&sha256_operation, (const uint8_t *)input, 100);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
mbedtls_sha256_finish(&sha256_ctx, output);
status = psa_hash_finish(&sha256_operation, output, sizeof(output), &hash_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(output, output_origin, sizeof(output), "MBEDTLS SHA256 must match");
}
@@ -146,7 +151,6 @@ static void rsa_task(void *pvParameters)
SemaphoreHandle_t *sema = (SemaphoreHandle_t *) pvParameters;
ESP_LOGI(TAG, "rsa_task is started");
while (exit_flag == false) {
mbedtls_rsa_self_test(0);
}
xSemaphoreGive(*sema);
vTaskDelete(NULL);
@@ -6,7 +6,7 @@
#include <string.h>
#include "unity.h"
#include "mbedtls/rsa.h"
#include "mbedtls/private/rsa.h"
#include "esp_random.h"
#include "sdkconfig.h"
@@ -38,9 +38,12 @@ TEST_CASE("ds sign test pkcs1_v15", "[ds_rsa]")
mbedtls_esp_random(NULL, hash, sizeof(hash)); // Fill hash with random data
unsigned int hashlen = sizeof(hash);
unsigned char signature[256] = {0};
mbedtls_pk_context pk;
mbedtls_pk_init(&pk);
pk.MBEDTLS_PRIVATE(pk_ctx) = &rsa_ctx;
// esp_ds is not initialized, so we expect an error
int err = esp_ds_rsa_sign(&rsa_ctx, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
int err = esp_ds_rsa_sign(&pk, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
TEST_ASSERT_EQUAL(-1, err);
// Initialize the esp_ds context
@@ -55,7 +58,7 @@ TEST_CASE("ds sign test pkcs1_v15", "[ds_rsa]")
TEST_ASSERT_EQUAL(ESP_OK, err);
// Now we can call esp_ds_rsa_sign again
err = esp_ds_rsa_sign(&rsa_ctx, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
err = esp_ds_rsa_sign(&pk, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
TEST_ASSERT_EQUAL(0, err);
TEST_ASSERT_NOT_NULL(signature);
@@ -89,9 +92,12 @@ TEST_CASE("ds sign test pkcs1_v21", "[ds_rsa]")
mbedtls_esp_random(NULL, hash, sizeof(hash)); // Fill hash with random data
unsigned int hashlen = sizeof(hash);
unsigned char signature[256] = {0};
mbedtls_pk_context pk;
mbedtls_pk_init(&pk);
pk.MBEDTLS_PRIVATE(pk_ctx) = &rsa_ctx;
// esp_ds is not initialized, so we expect an error
int err = esp_ds_rsa_sign(&rsa_ctx, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
int err = esp_ds_rsa_sign(&pk, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
TEST_ASSERT_EQUAL(-1, err);
// Initialize the esp_ds context
@@ -106,7 +112,7 @@ TEST_CASE("ds sign test pkcs1_v21", "[ds_rsa]")
TEST_ASSERT_EQUAL(ESP_OK, err);
// Now we can call esp_ds_rsa_sign again
err = esp_ds_rsa_sign(&rsa_ctx, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
err = esp_ds_rsa_sign(&pk, mbedtls_esp_random, NULL, MBEDTLS_MD_SHA256, hashlen, hash, signature);
TEST_ASSERT_EQUAL(0, err);
TEST_ASSERT_NOT_NULL(signature);
+18 -32
View File
@@ -12,12 +12,12 @@
#include <stdbool.h>
#include <inttypes.h>
#include <esp_random.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecdsa.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include <mbedtls/private/ecdh.h>
#include <mbedtls/private/ecdsa.h>
#include <mbedtls/error.h>
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#include "test_utils.h"
#include "ccomp_timer.h"
@@ -54,24 +54,20 @@
TEST_CASE("mbedtls ECDH Generate Key", "[mbedtls]")
{
mbedtls_ecdh_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
psa_key_attributes_t key_attributes;
psa_key_id_t key_id;
mbedtls_ecdh_init(&ctx);
mbedtls_ctr_drbg_init(&ctr_drbg);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_MONTGOMERY));
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_DERIVE);
psa_set_key_bits(&key_attributes, 255);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDH);
mbedtls_entropy_init(&entropy);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) );
psa_status_t status = psa_generate_key(&key_attributes, &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecp_group_load(ACCESS_ECDH(&ctx, grp), MBEDTLS_ECP_DP_CURVE25519) );
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdh_gen_public(ACCESS_ECDH(&ctx, grp), ACCESS_ECDH(&ctx, d), ACCESS_ECDH(&ctx, Q),
mbedtls_ctr_drbg_random, &ctr_drbg ) );
mbedtls_ecdh_free(&ctx);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
psa_reset_key_attributes(&key_attributes);
psa_destroy_key(key_id);
}
TEST_CASE("mbedtls ECP self-tests", "[mbedtls]")
@@ -82,29 +78,19 @@ TEST_CASE("mbedtls ECP self-tests", "[mbedtls]")
TEST_CASE("mbedtls ECP mul w/ koblitz", "[mbedtls]")
{
/* Test case code via https://github.com/espressif/esp-idf/issues/1556 */
mbedtls_entropy_context ctxEntropy;
mbedtls_ctr_drbg_context ctxRandom;
mbedtls_ecdsa_context ctxECDSA;
const char* pers = "myecdsa";
mbedtls_entropy_init(&ctxEntropy);
mbedtls_ctr_drbg_init(&ctxRandom);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ctr_drbg_seed(&ctxRandom, mbedtls_entropy_func, &ctxEntropy,
(const unsigned char*) pers, strlen(pers)) );
mbedtls_ecdsa_init(&ctxECDSA);
TEST_ASSERT_MBEDTLS_OK( mbedtls_ecdsa_genkey(&ctxECDSA, MBEDTLS_ECP_DP_SECP256K1,
mbedtls_ctr_drbg_random, &ctxRandom) );
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE) );
TEST_ASSERT_MBEDTLS_OK(mbedtls_ecp_mul(&ctxECDSA.MBEDTLS_PRIVATE(grp), &ctxECDSA.MBEDTLS_PRIVATE(Q),
&ctxECDSA.MBEDTLS_PRIVATE(d), &ctxECDSA.MBEDTLS_PRIVATE(grp).G,
mbedtls_ctr_drbg_random, &ctxRandom) );
mbedtls_psa_get_random, MBEDTLS_PSA_RANDOM_STATE) );
mbedtls_ecdsa_free(&ctxECDSA);
mbedtls_ctr_drbg_free(&ctxRandom);
mbedtls_entropy_free(&ctxEntropy);
}
#if CONFIG_MBEDTLS_HARDWARE_ECC
@@ -6,7 +6,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2019-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2019-2025 Espressif Systems (Shanghai) CO LTD
*/
#include <string.h>
#include "esp_err.h"
@@ -15,9 +15,6 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "entropy_poll.h"
@@ -29,6 +26,8 @@
#include "esp_crt_bundle.h"
#include "esp_random.h"
#include "psa/crypto.h"
#include "unity.h"
#include "test_utils.h"
#include "unity_test_utils.h"
@@ -55,15 +54,21 @@ extern const uint8_t wrong_sig_crt_pem_end[] asm("_binary_wrong_sig_crt_esp32_
extern const uint8_t correct_sig_crt_pem_start[] asm("_binary_correct_sig_crt_esp32_com_pem_start");
extern const uint8_t correct_sig_crt_pem_end[] asm("_binary_correct_sig_crt_esp32_com_pem_end");
// ECDSA test certificates
extern const uint8_t ecdsa_correct_sig_crt_pem_start[] asm("_binary_ecdsa_correct_sig_crt_pem_start");
extern const uint8_t ecdsa_correct_sig_crt_pem_end[] asm("_binary_ecdsa_correct_sig_crt_pem_end");
extern const uint8_t ecdsa_wrong_sig_crt_pem_start[] asm("_binary_ecdsa_wrong_sig_crt_pem_start");
extern const uint8_t ecdsa_wrong_sig_crt_pem_end[] asm("_binary_ecdsa_wrong_sig_crt_pem_end");
extern const uint8_t ecdsa_cert_bundle_start[] asm("_binary_ecdsa_cert_bundle_start");
extern const uint8_t ecdsa_cert_bundle_end[] asm("_binary_ecdsa_cert_bundle_end");
#define SEM_TIMEOUT 10000
typedef struct {
mbedtls_ssl_context ssl;
mbedtls_net_context listen_fd;
mbedtls_net_context client_fd;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_config conf;
mbedtls_x509_crt cert;
mbedtls_pk_context pkey;
@@ -84,12 +89,6 @@ static volatile bool exit_flag;
esp_err_t endpoint_teardown(mbedtls_endpoint_t *endpoint);
static int myrand(void *rng_state, unsigned char *output, size_t len)
{
size_t olen;
return mbedtls_hardware_poll(rng_state, output, len, &olen);
}
esp_err_t server_setup(mbedtls_endpoint_t *server)
{
int ret;
@@ -102,8 +101,6 @@ esp_err_t server_setup(mbedtls_endpoint_t *server)
mbedtls_ssl_init( &server->ssl );
mbedtls_x509_crt_init( &server->cert );
mbedtls_pk_init( &server->pkey );
mbedtls_entropy_init( &server->entropy );
mbedtls_ctr_drbg_init( &server->ctr_drbg );
ESP_LOGI(TAG, "Loading the server cert and key");
ret = mbedtls_x509_crt_parse( &server->cert, server_cert_chain_pem_start,
@@ -115,7 +112,7 @@ esp_err_t server_setup(mbedtls_endpoint_t *server)
}
ret = mbedtls_pk_parse_key( &server->pkey, (const unsigned char *)server_pk_start,
server_pk_end - server_pk_start, NULL, 0, myrand, NULL );
server_pk_end - server_pk_start, NULL, 0);
if ( ret != 0 ) {
ESP_LOGE(TAG, "mbedtls_pk_parse_key returned %d", ret );
return ESP_FAIL;
@@ -128,13 +125,6 @@ esp_err_t server_setup(mbedtls_endpoint_t *server)
}
mbedtls_net_set_nonblock(&server->listen_fd);
ESP_LOGI(TAG, "Seeding the random number generator");
if ( ( ret = mbedtls_ctr_drbg_seed( &server->ctr_drbg, mbedtls_entropy_func, &server->entropy,
NULL, 0) ) != 0 ) {
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret );
return ESP_FAIL;
}
ESP_LOGI(TAG, "Setting up the SSL data");
if ( ( ret = mbedtls_ssl_config_defaults( &server->conf,
MBEDTLS_SSL_IS_SERVER,
@@ -144,8 +134,6 @@ esp_err_t server_setup(mbedtls_endpoint_t *server)
return ESP_FAIL;
}
mbedtls_ssl_conf_rng( &server->conf, mbedtls_ctr_drbg_random, &server->ctr_drbg );
if (( ret = mbedtls_ssl_conf_own_cert( &server->conf, &server->cert, &server->pkey ) ) != 0 ) {
ESP_LOGE(TAG, "mbedtls_ssl_conf_own_cert returned %d", ret );
return ESP_FAIL;
@@ -209,9 +197,6 @@ esp_err_t endpoint_teardown(mbedtls_endpoint_t *endpoint)
mbedtls_ssl_free( &endpoint->ssl );
mbedtls_ssl_config_free( &endpoint->conf );
mbedtls_ctr_drbg_free( &endpoint->ctr_drbg );
mbedtls_entropy_free( &endpoint->entropy );
return ESP_OK;
}
@@ -223,19 +208,10 @@ esp_err_t client_setup(mbedtls_endpoint_t *client)
mbedtls_esp_enable_debug_log( &client->conf, CONFIG_MBEDTLS_DEBUG_LEVEL );
#endif
mbedtls_net_init( &client->client_fd );
mbedtls_net_init( &client->listen_fd );
mbedtls_ssl_init( &client->ssl );
mbedtls_x509_crt_init( &client->cert );
mbedtls_pk_init( &client->pkey );
mbedtls_entropy_init( &client->entropy );
mbedtls_ctr_drbg_init( &client->ctr_drbg );
ESP_LOGI(TAG, "Seeding the random number generator");
if ((ret = mbedtls_ctr_drbg_seed(&client->ctr_drbg, mbedtls_entropy_func, &client->entropy,
NULL, 0)) != 0) {
ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret);
return ESP_FAIL;
}
ESP_LOGI(TAG, "Setting hostname for TLS session...");
/* Hostname set here should match CN in server certificate */
if ((ret = mbedtls_ssl_set_hostname(&client->ssl, SERVER_ADDRESS)) != 0) {
@@ -251,7 +227,6 @@ esp_err_t client_setup(mbedtls_endpoint_t *client)
ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret);
return ESP_FAIL;
}
mbedtls_ssl_conf_rng(&client->conf, mbedtls_ctr_drbg_random, &client->ctr_drbg);
if ((ret = mbedtls_ssl_setup(&client->ssl, &client->conf)) != 0) {
ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x", -ret);
@@ -266,26 +241,26 @@ void client_task(void *pvParameters)
SemaphoreHandle_t *client_signal_sem = (SemaphoreHandle_t *) pvParameters;
int ret = ESP_FAIL;
mbedtls_endpoint_t client;
mbedtls_endpoint_t *client = calloc(1, sizeof(mbedtls_endpoint_t));
esp_crt_validate_res_t res = ESP_CRT_VALIDATE_UNKNOWN;
if (client_setup(&client) != ESP_OK) {
if (client_setup(client) != ESP_OK) {
ESP_LOGE(TAG, "SSL client setup failed");
goto exit;
}
/* Test with default crt bundle that does not contain the ca crt */
ESP_LOGI(TAG, "Connecting to %s:%s...", SERVER_ADDRESS, SERVER_PORT);
if ((ret = mbedtls_net_connect(&client.client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
if ((ret = mbedtls_net_connect(&client->client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret);
goto exit;
}
ESP_LOGI(TAG, "Connected.");
mbedtls_ssl_set_bio(&client.ssl, &client.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_set_bio(&client->ssl, &client->client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
ESP_LOGI(TAG, "Performing the SSL/TLS handshake with bundle that is missing the server root certificate");
while ( ( ret = mbedtls_ssl_handshake( &client.ssl ) ) != 0 ) {
while ( ( ret = mbedtls_ssl_handshake( &client->ssl ) ) != 0 ) {
if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) {
printf( "mbedtls_ssl_handshake failed with -0x%x\n", -ret );
break;
@@ -293,7 +268,7 @@ void client_task(void *pvParameters)
}
ESP_LOGI(TAG, "Verifying peer X.509 certificate for bundle ...");
ret = mbedtls_ssl_get_verify_result(&client.ssl);
ret = mbedtls_ssl_get_verify_result(&client->ssl);
res = (ret == 0) ? ESP_CRT_VALIDATE_OK : ESP_CRT_VALIDATE_FAIL;
@@ -305,25 +280,30 @@ void client_task(void *pvParameters)
TEST_ASSERT_EQUAL(ESP_CRT_VALIDATE_FAIL, res);
// Reset session before new connection
mbedtls_ssl_close_notify(&client.ssl);
mbedtls_ssl_session_reset(&client.ssl);
mbedtls_net_free( &client.client_fd);
mbedtls_ssl_close_notify(&client->ssl);
mbedtls_ssl_session_reset(&client->ssl);
mbedtls_net_free( &client->client_fd);
/* Test with bundle that does contain the CA crt */
esp_crt_bundle_attach(&client.conf);
esp_crt_bundle_set(server_cert_bundle_start, server_cert_bundle_end - server_cert_bundle_start);
ret = esp_crt_bundle_attach(&client->conf);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ret = esp_crt_bundle_set(server_cert_bundle_start, server_cert_bundle_end - server_cert_bundle_start);
TEST_ASSERT_EQUAL(ESP_OK, ret);
ESP_LOGI(TAG, "Connecting to %s:%s...", SERVER_ADDRESS, SERVER_PORT);
if ((ret = mbedtls_net_connect(&client.client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
if ((ret = mbedtls_net_connect(&client->client_fd, SERVER_ADDRESS, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret);
goto exit;
}
ESP_LOGI(TAG, "Connected.");
mbedtls_ssl_set_bio(&client.ssl, &client.client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_ssl_set_bio(&client->ssl, &client->client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
size_t available_before_handshake = uxTaskGetStackHighWaterMark(NULL);
ESP_LOGI(TAG, "Available stack before handshake: %d", available_before_handshake);
ESP_LOGI(TAG, "Performing the SSL/TLS handshake with bundle that is missing the server root certificate");
while ( ( ret = mbedtls_ssl_handshake( &client.ssl ) ) != 0 ) {
while ( ( ret = mbedtls_ssl_handshake( &client->ssl ) ) != 0 ) {
if ( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE ) {
printf( "mbedtls_ssl_handshake failed with -0x%x\n", -ret );
break;
@@ -331,7 +311,7 @@ void client_task(void *pvParameters)
}
ESP_LOGI(TAG, "Verifying peer X.509 certificate for bundle ...");
ret = mbedtls_ssl_get_verify_result(&client.ssl);
ret = mbedtls_ssl_get_verify_result(&client->ssl);
res = (ret == 0) ? ESP_CRT_VALIDATE_OK : ESP_CRT_VALIDATE_FAIL;
@@ -343,17 +323,18 @@ void client_task(void *pvParameters)
TEST_ASSERT_EQUAL(ESP_CRT_VALIDATE_OK, res);
// Reset session before new connection
mbedtls_ssl_close_notify(&client.ssl);
mbedtls_ssl_session_reset(&client.ssl);
mbedtls_net_free( &client.client_fd);
mbedtls_ssl_close_notify(&client->ssl);
mbedtls_ssl_session_reset(&client->ssl);
mbedtls_net_free( &client->client_fd);
exit:
mbedtls_ssl_close_notify(&client.ssl);
mbedtls_ssl_session_reset(&client.ssl);
esp_crt_bundle_detach(&client.conf);
endpoint_teardown(&client);
mbedtls_ssl_close_notify(&client->ssl);
mbedtls_ssl_session_reset(&client->ssl);
esp_crt_bundle_detach(&client->conf);
endpoint_teardown(client);
xSemaphoreGive(*client_signal_sem);
free(client);
vTaskSuspend(NULL);
}
@@ -441,6 +422,48 @@ TEST_CASE("custom certificate bundle - wrong signature", "[mbedtls]")
esp_crt_bundle_detach(NULL);
}
TEST_CASE("custom certificate bundle - ECDSA signature verification", "[mbedtls]")
{
/* Verify that ECDSA certificates with SHA-512 work correctly with PSA-based verification.
* This tests both the ECDSA algorithm path and a different hash algorithm (SHA-512) than
* the RSA tests which use SHA-256. */
mbedtls_x509_crt crt;
uint32_t flags = 0;
esp_crt_bundle_attach(NULL);
// Set the ECDSA bundle
esp_crt_bundle_set(ecdsa_cert_bundle_start, ecdsa_cert_bundle_end - ecdsa_cert_bundle_start);
// Test: ECDSA certificate with wrong signature should FAIL
mbedtls_x509_crt_init(&crt);
printf("Testing ECDSA certificate with wrong signature\n");
mbedtls_x509_crt_parse(&crt, ecdsa_wrong_sig_crt_pem_start,
ecdsa_wrong_sig_crt_pem_end - ecdsa_wrong_sig_crt_pem_start);
// Verify with the ECDSA bundle - this should fail
int verify_result = mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags,
esp_crt_verify_callback, NULL);
TEST_ASSERT_NOT_EQUAL(0, verify_result);
mbedtls_x509_crt_free(&crt);
// Test: ECDSA certificate with correct signature should PASS
mbedtls_x509_crt_init(&crt);
printf("Testing ECDSA certificate with correct signature\n");
mbedtls_x509_crt_parse(&crt, ecdsa_correct_sig_crt_pem_start,
ecdsa_correct_sig_crt_pem_end - ecdsa_correct_sig_crt_pem_start);
// Verify with the ECDSA bundle - this should succeed
verify_result = mbedtls_x509_crt_verify(&crt, NULL, NULL, NULL, &flags,
esp_crt_verify_callback, NULL);
TEST_ASSERT_EQUAL(0, verify_result);
mbedtls_x509_crt_free(&crt);
esp_crt_bundle_detach(NULL);
}
TEST_CASE("custom certificate bundle init API - bound checking - NULL certificate bundle", "[mbedtls]")
{
esp_err_t esp_ret;
@@ -6,8 +6,10 @@
#include <stdio.h>
#include <string.h>
#include "sys/param.h"
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "esp_heap_caps.h"
#include "mbedtls/gcm.h"
#include "mbedtls/private/gcm.h"
#include "sdkconfig.h"
#include "unity.h"
@@ -14,12 +14,9 @@
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "mbedtls/aes.h"
#include "mbedtls/bignum.h"
#include "mbedtls/rsa.h"
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "mbedtls/private/aes.h"
#include "mbedtls/private/rsa.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
@@ -48,16 +45,3 @@ TEST_CASE("mbedtls RSA self-tests", "[bignum]")
TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass.");
verify_apb_access_loop();
}
TEST_CASE("mbedtls SHA self-tests", "[mbedtls]")
{
start_apb_access_loop();
#if CONFIG_MBEDTLS_SHA1_C
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass.");
#endif
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha256_self_test(1), "SHA256 self-tests should pass.");
#if CONFIG_MBEDTLS_SHA512_C
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
#endif
verify_apb_access_loop();
}
@@ -9,12 +9,12 @@
#include <stdbool.h>
#include <inttypes.h>
#include <esp_log.h>
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include <mbedtls/ecdh.h>
#include <mbedtls/ecdsa.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include <mbedtls/private/ecdh.h>
#include <mbedtls/private/ecdsa.h>
#include <mbedtls/private/pk_private.h>
#include <mbedtls/error.h>
#include "psa/crypto.h"
#include "hal/efuse_ll.h"
#include "esp_efuse.h"
@@ -194,6 +194,31 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), pub_y, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1));
psa_key_id_t key_id;
psa_key_attributes_t key_attr = PSA_KEY_ATTRIBUTES_INIT;
if (id != MBEDTLS_ECP_DP_SECP192R1) {
psa_key_type_t curve_family = PSA_ECC_FAMILY_SECP_R1;
psa_set_key_type(&key_attr, PSA_KEY_TYPE_ECC_PUBLIC_KEY(curve_family));
if (id == MBEDTLS_ECP_DP_SECP256R1) {
psa_set_key_bits(&key_attr, 256);
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
psa_set_key_bits(&key_attr, 384);
}
#endif /* SOC_ECDSA_SUPPORT_CURVE_P384 */
psa_set_key_usage_flags(&key_attr, PSA_KEY_USAGE_VERIFY_HASH);
psa_set_key_algorithm(&key_attr, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
uint8_t psa_key[2 * plen + 1];
psa_key[0] = 0x04; // Uncompressed point indicator
memcpy(&psa_key[1], pub_x, plen);
memcpy(&psa_key[1 + plen], pub_y, plen);
psa_status_t status = psa_import_key(&key_attr, psa_key, sizeof(psa_key), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
if (id == MBEDTLS_ECP_DP_SECP192R1 || id == MBEDTLS_ECP_DP_SECP256R1) {
hash_len = HASH_LEN;
}
@@ -218,6 +243,31 @@ void test_ecdsa_verify(mbedtls_ecp_group_id id, const uint8_t *hash, const uint8
}
#endif
if (id != MBEDTLS_ECP_DP_SECP192R1) {
uint8_t signature[2 * plen];
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&r, signature, plen));
TEST_ASSERT_MBEDTLS_OK(mbedtls_mpi_write_binary(&s, signature + plen, plen));
ccomp_timer_start();
psa_status_t status = psa_verify_hash(key_id, PSA_ALG_ECDSA(PSA_ALG_SHA_256), hash, hash_len,
signature, sizeof(signature));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
elapsed_time = ccomp_timer_stop();
if (id == MBEDTLS_ECP_DP_SECP192R1) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P192_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
} else if (id == MBEDTLS_ECP_DP_SECP256R1) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P256_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
}
#if SOC_ECDSA_SUPPORT_CURVE_P384
else if (id == MBEDTLS_ECP_DP_SECP384R1) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(ECDSA_P384_VERIFY_OP, "%" NEWLIB_NANO_COMPAT_FORMAT" us", NEWLIB_NANO_COMPAT_CAST(elapsed_time));
}
#endif
psa_destroy_key(key_id);
psa_reset_key_attributes(&key_attr);
}
mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa_context);
@@ -553,8 +603,8 @@ void test_ecdsa_export_pubkey(mbedtls_ecp_group_id id, const uint8_t *pub_x, con
TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_x, export_pub_x, len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(pub_y, export_pub_y, len);
mbedtls_ecdsa_free(keypair);
mbedtls_pk_free(&key_ctx);
/* Use esp_ecdsa_free_pk_context instead of manual cleanup to avoid memory leak */
esp_ecdsa_free_pk_context(&key_ctx);
}
TEST_CASE("mbedtls ECDSA export public key on SECP192R1", "[mbedtls][efuse_key]")
@@ -9,6 +9,7 @@
#include <stdbool.h>
#include <sys/param.h>
#include <esp_system.h>
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "mbedtls/bignum.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@@ -1,607 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* mbedTLS SHA unit tests
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "sdkconfig.h"
#include "test_apb_dport_access.h"
#include "soc/soc_caps.h"
#include "test_utils.h"
#include "esp_memory_utils.h"
#if CONFIG_MBEDTLS_HARDWARE_SHA
static const unsigned char *one_hundred_as = (unsigned char *)
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
static const unsigned char *one_hundred_bs = (unsigned char *)
"bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb";
static const uint8_t sha256_thousand_as[32] = {
0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c,
0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3
};
static const uint8_t sha256_thousand_bs[32] = {
0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b
};
static const uint8_t sha512_thousand_bs[64] = {
0xa6, 0x68, 0x68, 0xa3, 0x73, 0x53, 0x2a, 0x5c, 0xc3, 0x3f, 0xbf, 0x43, 0x4e, 0xba, 0x10, 0x86, 0xb3, 0x87, 0x09, 0xe9, 0x14, 0x3f, 0xbf, 0x37, 0x67, 0x8d, 0x43, 0xd9, 0x9b, 0x95, 0x08, 0xd5, 0x80, 0x2d, 0xbe, 0x9d, 0xe9, 0x1a, 0x54, 0xab, 0x9e, 0xbc, 0x8a, 0x08, 0xa0, 0x1a, 0x89, 0xd8, 0x72, 0x68, 0xdf, 0x52, 0x69, 0x7f, 0x1c, 0x70, 0xda, 0xe8, 0x3f, 0xe5, 0xae, 0x5a, 0xfc, 0x9d
};
static const uint8_t sha384_thousand_bs[48] = {
0x6d, 0xe5, 0xf5, 0x88, 0x57, 0x60, 0x83, 0xff, 0x7c, 0x94, 0x61, 0x5f, 0x8d, 0x96, 0xf2, 0x76, 0xd5, 0x3f, 0x77, 0x0c, 0x8e, 0xc1, 0xbf, 0xb6, 0x04, 0x27, 0xa4, 0xba, 0xea, 0x6c, 0x68, 0x44, 0xbd, 0xb0, 0x9c, 0xef, 0x6a, 0x09, 0x28, 0xe8, 0x1f, 0xfc, 0x95, 0x03, 0x69, 0x99, 0xab, 0x1a
};
static const uint8_t sha1_thousand_as[20] = {
0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5,
0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba
};
TEST_CASE("mbedtls SHA interleaving", "[mbedtls]")
{
mbedtls_sha1_context sha1_ctx;
mbedtls_sha256_context sha256_ctx;
mbedtls_sha512_context sha512_ctx;
unsigned char sha1[20], sha256[32], sha512[64];
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha256_init(&sha256_ctx);
mbedtls_sha512_init(&sha512_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts(&sha1_ctx));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&sha512_ctx, false));
for (int i = 0; i < 10; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha1_update(&sha1_ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&sha512_ctx, one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish(&sha1_ctx, sha1));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&sha512_ctx, sha512));
mbedtls_sha1_free(&sha1_ctx);
mbedtls_sha256_free(&sha256_ctx);
mbedtls_sha512_free(&sha512_ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 calculation");
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
#define SHA_TASK_STACK_SIZE (10*1024)
static SemaphoreHandle_t done_sem;
static void tskRunSHA1Test(void *pvParameters)
{
mbedtls_sha1_context sha1_ctx;
unsigned char sha1[20];
for (int i = 0; i < 1000; i++) {
mbedtls_sha1_init(&sha1_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha1_starts(&sha1_ctx));
for (int j = 0; j < 10; j++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha1_update(&sha1_ctx, (unsigned char *)one_hundred_as, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha1_finish(&sha1_ctx, sha1));
mbedtls_sha1_free(&sha1_ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_thousand_as, sha1, 20, "SHA1 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
static void tskRunSHA256Test(void *pvParameters)
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
for (int i = 0; i < 1000; i++) {
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
for (int j = 0; j < 10; j++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, (unsigned char *)one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
mbedtls_sha256_free(&sha256_ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_bs, sha256, 32, "SHA256 calculation");
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA multithreading", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(4, 0);
xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA1Test, "SHA1Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHA256Test, "SHA256Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
for (int i = 0; i < 4; i++) {
if (!xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
void tskRunSHASelftests(void *param)
{
for (int i = 0; i < 5; i++) {
#if CONFIG_MBEDTLS_SHA1_C
if (mbedtls_sha1_self_test(1)) {
printf("SHA1 self-tests failed.\n");
while (1) {}
}
#endif
if (mbedtls_sha256_self_test(1)) {
printf("SHA256 self-tests failed.\n");
while (1) {}
}
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
if (mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while (1) {}
}
if (mbedtls_sha512_self_test(1)) {
printf("SHA512 self-tests failed.\n");
while (1) {}
}
#endif //SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
}
xSemaphoreGive(done_sem);
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(2, 0);
xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
const int TIMEOUT_MS = 40000;
for (int i = 0; i < 2; i++) {
if (!xSemaphoreTake(done_sem, TIMEOUT_MS / portTICK_PERIOD_MS)) {
TEST_FAIL_MESSAGE("done_sem not released by test task");
}
}
vSemaphoreDelete(done_sem);
}
TEST_CASE("mbedtls SHA512 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha512[64];
mbedtls_sha512_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100));
}
mbedtls_sha512_init(&clone);
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&clone, one_hundred_bs, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&ctx, sha512));
mbedtls_sha512_free(&ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&clone, sha512));
mbedtls_sha512_free(&clone);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA384 clone", "[mbedtls]")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha384[48];
mbedtls_sha512_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&ctx, true));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100));
}
mbedtls_sha512_init(&clone);
mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&ctx, one_hundred_bs, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&clone, one_hundred_bs, 100));
}
/* intended warning suppression: is384 == true */
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&ctx, sha384));
#pragma GCC diagnostic pop
mbedtls_sha512_free(&ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation");
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wstringop-overflow"
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&clone, sha384));
#pragma GCC diagnostic pop
mbedtls_sha512_free(&clone);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 cloned calculation");
}
TEST_CASE("mbedtls SHA256 clone", "[mbedtls]")
{
mbedtls_sha256_context ctx;
mbedtls_sha256_context clone;
unsigned char sha256[64];
mbedtls_sha256_init(&ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&ctx, one_hundred_as, 100));
}
mbedtls_sha256_init(&clone);
mbedtls_sha256_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&ctx, one_hundred_as, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&clone, one_hundred_as, 100));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&ctx, sha256));
mbedtls_sha256_free(&ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&clone, sha256));
mbedtls_sha256_free(&clone);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation");
}
typedef struct {
mbedtls_sha256_context ctx;
uint8_t result[32];
int ret;
bool done;
} finalise_sha_param_t;
static void tskFinaliseSha(void *v_param)
{
finalise_sha_param_t *param = (finalise_sha_param_t *)v_param;
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&param->ctx, one_hundred_as, 100));
}
param->ret = mbedtls_sha256_finish(&param->ctx, param->result);
mbedtls_sha256_free(&param->ctx);
param->done = true;
vTaskDelete(NULL);
}
TEST_CASE("mbedtls SHA session passed between tasks", "[mbedtls]")
{
finalise_sha_param_t param = { 0 };
mbedtls_sha256_init(&param.ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&param.ctx, false));
for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&param.ctx, one_hundred_as, 100));
}
// pass the SHA context off to a different task
//
// note: at the moment this doesn't crash even if a mutex semaphore is used as the
// engine lock, but it can crash...
xTaskCreate(tskFinaliseSha, "SHAFinalise", SHA_TASK_STACK_SIZE, &param, 3, NULL);
while (!param.done) {
vTaskDelay(1);
}
TEST_ASSERT_EQUAL(0, param.ret);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, param.result, 32, "SHA256 result from other task");
}
/* Random input generated and hashed using python:
import hashlib
import os, binascii
input = bytearray(os.urandom(150))
arr = ''
for idx, b in enumerate(input):
if idx % 8 == 0:
arr += '\n'
arr += "{}, ".format(hex(b))
digest = hashlib.sha256(input).hexdigest()
*/
const uint8_t test_vector[] = {
0xe4, 0x1a, 0x1a, 0x30, 0x71, 0xd3, 0x94, 0xb0,
0xc3, 0x7e, 0x99, 0x9f, 0x1a, 0xde, 0x4a, 0x36,
0xb1, 0x1, 0x81, 0x2b, 0x41, 0x91, 0x11, 0x7f,
0xd8, 0xe1, 0xd5, 0xe5, 0x52, 0x6d, 0x92, 0xee,
0x6c, 0xf7, 0x70, 0xea, 0x3a, 0xb, 0xc9, 0x97,
0xc0, 0x12, 0x6f, 0x10, 0x5b, 0x90, 0xd8, 0x52,
0x91, 0x69, 0xea, 0xc4, 0x1f, 0xc, 0xcf, 0xc6,
0xf0, 0x43, 0xc6, 0xa3, 0x1f, 0x46, 0x3c, 0x3d,
0x25, 0xe5, 0xa8, 0x27, 0x86, 0x85, 0x32, 0x3f,
0x33, 0xd8, 0x40, 0xc4, 0x41, 0xf6, 0x4b, 0x12,
0xd8, 0x5e, 0x4, 0x27, 0x42, 0x90, 0x73, 0x4,
0x8, 0x42, 0xd1, 0x64, 0xd, 0x84, 0x3, 0x1,
0x76, 0x88, 0xe4, 0x95, 0xdf, 0xe7, 0x62, 0xb4,
0xb3, 0xb2, 0x7e, 0x6d, 0x78, 0xca, 0x79, 0x82,
0xcc, 0xba, 0x22, 0xd2, 0x90, 0x2e, 0xe3, 0xa8,
0x2a, 0x53, 0x3a, 0xb1, 0x9a, 0x7f, 0xb7, 0x8b,
0xfa, 0x32, 0x47, 0xc1, 0x5c, 0x6, 0x4f, 0x7b,
0xcd, 0xb3, 0xf4, 0xf1, 0xd0, 0xb5, 0xbf, 0xfb,
0x7c, 0xc3, 0xa5, 0xb2, 0xc4, 0xd4,
};
const uint8_t test_vector_digest[] = {
0xff, 0x1c, 0x60, 0xcb, 0x21, 0xf0, 0x63, 0x68,
0xb9, 0xfc, 0xfe, 0xad, 0x3e, 0xb0, 0x2e, 0xd1,
0xf9, 0x08, 0x82, 0x82, 0x83, 0x06, 0xc1, 0x8a,
0x98, 0x5d, 0x36, 0xc0, 0xb7, 0xeb, 0x35, 0xe0,
};
TEST_CASE("mbedtls SHA, input in flash", "[mbedtls]")
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, test_vector, sizeof(test_vector)));
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
mbedtls_sha256_free(&sha256_ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(test_vector_digest, sha256, 32, "SHA256 calculation");
}
/* Function are not implemented in SW */
#if CONFIG_MBEDTLS_HARDWARE_SHA && SOC_SHA_SUPPORT_SHA512_T
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha512T_test_buf[2][113] = {
{ "abc" },
{
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
}
};
static const size_t sha512T_test_buflen[2] = {
3, 112
};
static const esp_sha_type sha512T_algo[4] = {
SHA2_512224, SHA2_512256, SHA2_512T, SHA2_512T
};
static const size_t sha512T_t_len[4] = { 224, 256, 224, 256 };
static const unsigned char sha512_test_sum[4][32] = {
/* SHA512-224 */
{
0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54,
0xda, 0xae, 0x75, 0x30, 0x46, 0x08, 0x42, 0xe2,
0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4,
0x3e, 0x89, 0x24, 0xaa
},
{
0x23, 0xfe, 0xc5, 0xbb, 0x94, 0xd6, 0x0b, 0x23,
0x30, 0x81, 0x92, 0x64, 0x0b, 0x0c, 0x45, 0x33,
0x35, 0xd6, 0x64, 0x73, 0x4f, 0xe4, 0x0e, 0x72,
0x68, 0x67, 0x4a, 0xf9
},
/* SHA512-256 */
{
0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9,
0x9b, 0x2e, 0x29, 0xb7, 0x6b, 0x4c, 0x7d, 0xab,
0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46,
0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23
},
{
0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8,
0x40, 0xda, 0x39, 0x88, 0x12, 0x1d, 0x31, 0xbe,
0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14,
0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a
}
/* For SHA512_T testing we use t=224 & t=256
* so the hash digest should be same as above
*/
};
/* This will run total of 8 test cases, 2 for each of the below MODE
* SHA512/224, SHA512/256, SHA512/t with t=224 & SHA512/t with t=256
*
* Test is disabled for ESP32 as there is no hardware for SHA512/t
*/
TEST_CASE("mbedtls SHA512/t", "[mbedtls]")
{
mbedtls_sha512_context sha512_ctx;
unsigned char sha512[64], k;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 2; j++) {
k = i * 2 + j;
mbedtls_sha512_init(&sha512_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts(&sha512_ctx, false));
esp_sha512_set_mode(&sha512_ctx, sha512T_algo[i]);
if (i > 1) {
k = (i - 2) * 2 + j;
esp_sha512_set_t(&sha512_ctx, sha512T_t_len[i]);
}
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update(&sha512_ctx, sha512T_test_buf[j], sha512T_test_buflen[j]));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish(&sha512_ctx, sha512));
mbedtls_sha512_free(&sha512_ctx);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_test_sum[k], sha512, sha512T_t_len[i] / 8, "SHA512t calculation");
}
}
}
#endif //CONFIG_MBEDTLS_HARDWARE_SHA
#ifdef CONFIG_SPIRAM_USE_MALLOC
#include "test_mbedtls_utils.h"
TEST_CASE("mbedtls SHA256 PSRAM DMA", "[mbedtls]")
{
const unsigned CALLS = 256;
const unsigned CALL_SZ = 16 * 1024;
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
// allocate external memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
TEST_ASSERT(esp_ptr_external_ram(buf));
memset(buf, 0x54, CALL_SZ);
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
for (int c = 0; c < CALLS; c++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, buf, CALL_SZ));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
free(buf);
mbedtls_sha256_free(&sha256_ctx);
/* Check the result. Reference value can be calculated using:
* dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\124' | sha256sum
*/
const char *expected_hash = "8d031167bd706ac337e07aa9129c34ae4ae792d0a79a2c70e7f012102e8adc3d";
char hash_str[sizeof(sha256) * 2 + 1];
utils_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256));
TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str);
}
#if SOC_SHA_SUPPORT_DMA
TEST_CASE("mbedtls SHA256 PSRAM DMA large buffer", "[hw_crypto]")
{
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
const size_t SZ = 257984; // specific size to cover issue in https://github.com/espressif/esp-idf/issues/11915
void *buffer = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
TEST_ASSERT_NOT_NULL(buffer);
memset(buffer, 0x55, SZ);
mbedtls_sha256_init(&sha256_ctx);
int r = mbedtls_sha256_starts(&sha256_ctx, false);
TEST_ASSERT_EQUAL(0, r);
r = mbedtls_sha256_update(&sha256_ctx, buffer, SZ);
TEST_ASSERT_EQUAL(0, r);
r = mbedtls_sha256_finish(&sha256_ctx, sha256);
TEST_ASSERT_EQUAL(0, r);
mbedtls_sha256_free(&sha256_ctx);
free(buffer);
/* Check the result. Reference value can be calculated using:
* dd if=/dev/zero bs=257984 count=1 | tr '\000' '\125' | sha256sum
*/
const char *expected_hash = "f2330c9f81ff1c8f0515247faa82be8b6f9685601de6f5dae79172766f136c33";
char hash_str[sizeof(sha256) * 2 + 1];
utils_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256));
TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str);
}
#endif // SOC_SHA_SUPPORT_DMA
#endif //CONFIG_SPIRAM_USE_MALLOC
#if CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK && !CONFIG_IDF_TARGET_ESP32H2
// Not enough rtc memory for test on H2
TEST_CASE("mbedtls SHA stack in RTC RAM", "[mbedtls]")
{
done_sem = xSemaphoreCreateBinary();
static StaticTask_t rtc_task;
size_t STACK_SIZE = 3072;
uint8_t *rtc_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_RTCRAM);
TEST_ASSERT(esp_ptr_in_rtc_dram_fast(rtc_stack));
TEST_ASSERT_NOT_NULL(xTaskCreateStatic(tskRunSHA256Test, "tskRunSHA256Test_task", STACK_SIZE, NULL,
3, rtc_stack, &rtc_task));
TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS));
/* Give task time to cleanup before freeing stack */
vTaskDelay(1000 / portTICK_PERIOD_MS);
free(rtc_stack);
vSemaphoreDelete(done_sem);
}
#endif //CONFIG_ESP_SYSTEM_RTC_FAST_MEM_AS_HEAP_DEPCHECK
#if CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC
TEST_CASE("mbedtls SHA stack in PSRAM", "[mbedtls]")
{
done_sem = xSemaphoreCreateBinary();
static StaticTask_t psram_task;
size_t STACK_SIZE = 3072;
uint8_t *psram_stack = heap_caps_calloc(STACK_SIZE, 1, MALLOC_CAP_SPIRAM);
TEST_ASSERT(esp_ptr_external_ram(psram_stack));
TEST_ASSERT_NOT_NULL(xTaskCreateStatic(tskRunSHA256Test, "tskRunSHA256Test_task", STACK_SIZE, NULL,
3, psram_stack, &psram_task));
TEST_ASSERT_TRUE(xSemaphoreTake(done_sem, 10000 / portTICK_PERIOD_MS));
/* Give task time to cleanup before freeing stack */
vTaskDelay(1000 / portTICK_PERIOD_MS);
free(psram_stack);
vSemaphoreDelete(done_sem);
}
#endif //CONFIG_FREERTOS_TASK_CREATE_ALLOW_EXT_MEM && CONFIG_SPIRAM_USE_MALLOC
#endif // CONFIG_MBEDTLS_HARDWARE_SHA
@@ -0,0 +1,869 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_heap_caps.h"
#include "esp_log.h"
#include "esp_private/periph_ctrl.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
TEST_CASE("PSA AES-CTR multipart", "[psa-aes]")
{
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CTR;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-ECB multipart", "[psa-aes]")
{
const size_t SZ = 112;
const size_t iv_SZ = 16;
const size_t part_size = 16;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_ECB_NO_PADDING;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-CBC multipart", "[psa-aes]")
{
const size_t SZ = 112; // Multiple of block size (16)
const size_t iv_SZ = 16;
const size_t part_size = 16; // Process one block at a time
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-CBC-PKCS7 multipart", "[psa-aes]")
{
// Test both aligned and unaligned sizes
const size_t SZ1 = 112; // Multiple of block size (16)
const size_t SZ2 = 123; // Not a multiple of block size
const size_t iv_SZ = 16;
const size_t part_size = 16;
uint8_t *plaintext1 = malloc(SZ1);
uint8_t *ciphertext1 = malloc(SZ1 + 16); // Extra block for padding
uint8_t *decryptedtext1 = malloc(SZ1 + 16); // Extra space for intermediate buffering
uint8_t *plaintext2 = malloc(SZ2);
uint8_t *ciphertext2 = malloc(SZ2 + 16); // Extra block for padding
uint8_t *decryptedtext2 = malloc(SZ2 + 16); // Extra space for intermediate buffering
uint8_t iv[iv_SZ];
// Initialize test data
memset(plaintext1, 0x3A, SZ1);
memset(plaintext2, 0x3B, SZ2);
memset(ciphertext1, 0x0, SZ1 + 16);
memset(ciphertext2, 0x0, SZ2 + 16);
memset(decryptedtext1, 0x0, SZ1 + 16);
memset(decryptedtext2, 0x0, SZ2 + 16);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_PKCS7;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Test 1: Block-aligned input */
{
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3C, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
// Process all blocks except the last one
for (size_t offset = 0; offset < SZ1 - part_size; offset += part_size) {
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext1 + offset, part_size,
ciphertext1 + total_out_len, SZ1 + 16 - total_out_len, &out_len));
total_out_len += out_len;
}
// Process the last block separately
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext1 + SZ1 - part_size, part_size,
ciphertext1 + total_out_len, SZ1 + 16 - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext1 + total_out_len,
SZ1 + 16 - total_out_len, &out_len)); // Space for padding block
total_out_len += out_len;
// The output size should be the input size rounded up to the next multiple of 16
TEST_ASSERT_EQUAL_size_t((SZ1 + 16), total_out_len); // Should include padding block
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
size_t dec_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < total_out_len; offset += part_size) {
size_t this_part = total_out_len - offset < part_size ? total_out_len - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext1 + offset, this_part,
decryptedtext1 + dec_len, SZ1 + 16 - dec_len, &out_len));
dec_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext1 + dec_len,
SZ1 + 16 - dec_len, &out_len));
dec_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ1, dec_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext1, decryptedtext1, SZ1);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
}
/* Test 2: Non-block-aligned input */
{
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3D, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ2; offset += part_size) {
size_t this_part = SZ2 - offset < part_size ? SZ2 - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext2 + offset, this_part,
ciphertext2 + total_out_len, SZ2 + 16 - total_out_len, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext2 + total_out_len,
SZ2 + 16 - total_out_len, &out_len));
total_out_len += out_len;
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
size_t dec_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < total_out_len; offset += part_size) {
size_t this_part = total_out_len - offset < part_size ? total_out_len - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext2 + offset, this_part,
decryptedtext2 + dec_len, SZ2 + 16 - dec_len, &out_len));
dec_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext2 + dec_len,
SZ2 + 16 - dec_len, &out_len));
dec_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ2, dec_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext2, decryptedtext2, SZ2);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
}
/* Cleanup */
free(plaintext1);
free(ciphertext1);
free(decryptedtext1);
free(plaintext2);
free(ciphertext2);
free(decryptedtext2);
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-CFB multipart", "[psa-aes]")
{
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CFB;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-OFB multipart", "[psa-aes]")
{
const size_t SZ = 100;
const size_t iv_SZ = 16;
const size_t part_size = 8;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_OFB;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len, total_out_len = 0;
memset(iv, 0x3B, iv_SZ); // Initialize IV with known value
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out_len,
SZ - total_out_len, &out_len));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-CTR streaming chunk invariance", "[psa-aes]")
{
const size_t SZ = 100;
const size_t iv_SZ = 16;
// Vectors match legacy mbedtls CTR stream test
const uint8_t expected_cipher[] = {
0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b,
0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09,
0xde, 0xaf, 0x37, 0x19, 0x32, 0x4d, 0xca, 0xf6,
0xff, 0x6e, 0xd2, 0x5d, 0x87, 0x51, 0xaa, 0x8c,
0x1c, 0xe3, 0x3b, 0xbb, 0x18, 0xf5, 0xa0, 0x1b,
0xdc, 0x29, 0x52, 0x63, 0xf6, 0x5d, 0x49, 0x85,
0x29, 0xf1, 0xf0, 0x69, 0x8f, 0xa6, 0x9f, 0x38,
0x5c, 0xdd, 0x26, 0xf8, 0x9d, 0x40, 0xa1, 0xff,
0x52, 0x46, 0xe1, 0x72, 0x70, 0x39, 0x73, 0xff,
0xd0, 0x5e, 0xe5, 0x3f, 0xc5, 0xed, 0x5c, 0x18,
0xa7, 0x84, 0xd8, 0xdf, 0x9d, 0xb5, 0x06, 0xb1,
0xa7, 0xcf, 0x2e, 0x7a, 0x51, 0xfc, 0x44, 0xc5,
0xb9, 0x5f, 0x22, 0x47,
};
uint8_t key[16];
uint8_t iv[iv_SZ];
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
memset(key, 0x44, sizeof(key));
memset(iv, 0xEE, iv_SZ);
memset(plaintext, 0xAA, SZ);
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CTR);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key, sizeof(key), &key_id));
psa_reset_key_attributes(&attributes);
for (size_t chunk = 1; chunk < SZ; chunk++) {
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len = 0, total_out = 0;
memset(iv, 0xEE, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, PSA_ALG_CTR));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += chunk) {
size_t this_part = SZ - offset < chunk ? SZ - offset : chunk;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out,
SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ);
psa_cipher_abort(&enc_op);
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out = 0;
memset(iv, 0xEE, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, PSA_ALG_CTR));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += chunk) {
size_t this_part = SZ - offset < chunk ? SZ - offset : chunk;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out,
SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
psa_cipher_abort(&dec_op);
}
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-OFB streaming chunk invariance", "[psa-aes]")
{
const size_t SZ = 100;
const size_t iv_SZ = 16;
// Vectors match legacy mbedtls OFB stream test
const uint8_t expected_cipher[] = {
0xc5, 0x78, 0xa7, 0xb4, 0xf3, 0xb9, 0xcb, 0x8b,
0x09, 0xe0, 0xd6, 0x89, 0x14, 0x6a, 0x19, 0x09,
0x0a, 0x33, 0x8b, 0xab, 0x82, 0xcb, 0x20, 0x8f,
0x74, 0x2a, 0x6c, 0xb3, 0xc6, 0xe8, 0x18, 0x89,
0x09, 0xb6, 0xaf, 0x20, 0xcd, 0xea, 0x74, 0x14,
0x48, 0x61, 0xe8, 0x4d, 0x50, 0x12, 0x9f, 0x5e,
0xb8, 0x10, 0x53, 0x3b, 0x74, 0xd9, 0xd0, 0x95,
0x13, 0xdc, 0x14, 0xcf, 0x0c, 0xa1, 0x90, 0xfd,
0xa2, 0x58, 0x12, 0xb2, 0x00, 0x2c, 0x5b, 0x7a,
0x2a, 0x76, 0x80, 0x20, 0x82, 0x39, 0xa2, 0x21,
0xf8, 0x7a, 0xec, 0xae, 0x82, 0x6a, 0x5c, 0xd3,
0x04, 0xd9, 0xbd, 0xe4, 0x53, 0xc9, 0xdf, 0x67,
0xaa, 0x5c, 0xaf, 0xa6,
};
uint8_t key[16];
uint8_t iv[iv_SZ];
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
memset(key, 0x44, sizeof(key));
memset(iv, 0xEE, iv_SZ);
memset(plaintext, 0xAA, SZ);
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_OFB);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key, sizeof(key), &key_id));
psa_reset_key_attributes(&attributes);
for (size_t chunk = 1; chunk < SZ; chunk++) {
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len = 0, total_out = 0;
memset(iv, 0xEE, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, PSA_ALG_OFB));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += chunk) {
size_t this_part = SZ - offset < chunk ? SZ - offset : chunk;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out,
SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher, ciphertext, SZ);
psa_cipher_abort(&enc_op);
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out = 0;
memset(iv, 0xEE, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, PSA_ALG_OFB));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
for (size_t offset = 0; offset < SZ; offset += chunk) {
size_t this_part = SZ - offset < chunk ? SZ - offset : chunk;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out += out_len;
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out,
SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
psa_cipher_abort(&dec_op);
}
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-CFB-128", "[psa-aes]")
{
const size_t SZ = 1000;
const size_t iv_SZ = 16;
const uint8_t expected_cipher_end[] = {
0xf3, 0x64, 0x20, 0xa1, 0x70, 0x2a, 0xd9, 0x3f,
0xb7, 0x48, 0x8c, 0x2c, 0x1f, 0x65, 0x53, 0xc2,
0xac, 0xfd, 0x82, 0xe5, 0x31, 0x24, 0x1f, 0x30,
0xaf, 0xcc, 0x8d, 0xb3, 0xf3, 0x63, 0xe1, 0xa0,
};
const uint8_t iv_seed[] = {
0x10, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09,
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01,
};
uint8_t iv[iv_SZ];
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
memcpy(iv, iv_seed, iv_SZ);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, PSA_ALG_CFB);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
psa_cipher_operation_t enc_op = PSA_CIPHER_OPERATION_INIT;
size_t out_len = 0, total_out = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_encrypt_setup(&enc_op, key_id, PSA_ALG_CFB));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&enc_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&enc_op, plaintext, SZ, ciphertext, SZ, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&enc_op, ciphertext + total_out, SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cipher_end, ciphertext + SZ - sizeof(expected_cipher_end), sizeof(expected_cipher_end));
psa_cipher_operation_t dec_op = PSA_CIPHER_OPERATION_INIT;
total_out = 0;
memcpy(iv, iv_seed, iv_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_decrypt_setup(&dec_op, key_id, PSA_ALG_CFB));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_set_iv(&dec_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_update(&dec_op, ciphertext, SZ, decryptedtext, SZ, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_cipher_finish(&dec_op, decryptedtext + total_out, SZ - total_out, &out_len));
total_out += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
psa_cipher_abort(&enc_op);
psa_cipher_abort(&dec_op);
psa_destroy_key(key_id);
free(plaintext);
free(ciphertext);
free(decryptedtext);
}
TEST_CASE("PSA AES-CBC one-shot", "[psa-aes]")
{
const size_t SZ = 1600;
const size_t iv_SZ = 16;
// allocate internal memory
uint8_t *plaintext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *ciphertext = heap_caps_malloc(SZ + iv_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
uint8_t *decryptedtext = heap_caps_malloc(SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_CBC_NO_PADDING;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(psa_import_key(&attributes, key_256, sizeof(key_256), &key_id), PSA_SUCCESS);
psa_reset_key_attributes(&attributes);
size_t ciphertext_len = 0;
/* Encrypt the plaintext */
TEST_ASSERT_EQUAL(psa_cipher_encrypt(key_id, alg, plaintext, SZ, ciphertext, SZ + iv_SZ, &ciphertext_len), PSA_SUCCESS);
TEST_ASSERT_EQUAL_size_t(ciphertext_len, SZ + iv_SZ);
size_t decryptedtext_len = 0;
/* Decrypt the ciphertext */
TEST_ASSERT_EQUAL(psa_cipher_decrypt(key_id, alg, ciphertext, SZ + iv_SZ, decryptedtext, SZ, &decryptedtext_len), PSA_SUCCESS);
TEST_ASSERT_EQUAL_size_t(decryptedtext_len, SZ);
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
free(plaintext);
free(ciphertext);
free(decryptedtext);
/* Destroy the key */
psa_destroy_key(key_id);
}
@@ -0,0 +1,203 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
TEST_CASE("PSA AES-GCM multipart", "[psa-aes-gcm]")
{
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
const size_t part_size = 8;
size_t tag_length = 0;
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t iv[iv_SZ];
uint8_t tag[tag_SZ];
uint8_t aad[aad_SZ];
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_aead_operation_t enc_op = PSA_AEAD_OPERATION_INIT;
size_t out_len, total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&enc_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&enc_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&enc_op, aad, aad_SZ));
// Process the plaintext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Finish encryption and get the tag
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_finish(&enc_op,
ciphertext + total_out_len,
SZ - total_out_len,
&out_len,
tag,
tag_SZ,
&tag_length));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
/* Decrypt */
psa_aead_operation_t dec_op = PSA_AEAD_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&dec_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&dec_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&dec_op, aad, aad_SZ));
// Process the ciphertext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Verify the tag and finish decryption
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_verify(&dec_op,
decryptedtext + total_out_len,
SZ - total_out_len,
&out_len,
tag,
tag_SZ));
total_out_len += out_len;
TEST_ASSERT_EQUAL_size_t(SZ, total_out_len);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
psa_aead_abort(&enc_op);
psa_aead_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
}
TEST_CASE("PSA AES-GCM one-shot", "[psa-aes-gcm]")
{
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
size_t output_length;
/* One-shot encrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
plaintext, SZ,
ciphertext, SZ + tag_SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ + tag_SZ, output_length);
/* One-shot decrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
ciphertext, SZ + tag_SZ,
decryptedtext, SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ, output_length);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
/* Destroy the key */
psa_destroy_key(key_id);
}
@@ -0,0 +1,398 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* PSA CMAC test
*/
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <esp_system.h>
#include "psa/crypto.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "esp_memory_utils.h"
#if CONFIG_MBEDTLS_CMAC_C
static const uint8_t key_128[] = {
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
};
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
static const uint8_t test_data[] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
};
// Expected CMAC values from the mbedtls implementation
static const uint8_t expected_cmac_128[] = {
0x93, 0xae, 0x18, 0x36, 0xdf, 0xbd, 0x91, 0x06,
0xa5, 0xd1, 0x84, 0x5c, 0xe5, 0x61, 0x02, 0xe2,
};
static const uint8_t expected_cmac_256[] = {
0x35, 0x17, 0x99, 0xb0, 0xfd, 0xb1, 0x5b, 0x47,
0x98, 0xe3, 0x47, 0xef, 0xa3, 0xb4, 0xe1, 0x89,
};
static const uint8_t expected_cmac_zero_length[] = {
0xd8, 0xa8, 0x58, 0x43, 0x62, 0xe9, 0x93, 0xf8,
0xd5, 0x29, 0x24, 0xf6, 0x39, 0x07, 0xc4, 0x88,
};
TEST_CASE("PSA CMAC AES-128 test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
ESP_LOGI("PSA CMAC AES-128", "Status: %ld", status);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
ESP_LOG_BUFFER_HEXDUMP("CMAC AES-128", cmac, cmac_length, ESP_LOG_INFO);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_128, sizeof(expected_cmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-256 test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 256);
// Import the key
status = psa_import_key(&attributes, key_256, sizeof(key_256), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 256, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_256, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_256, sizeof(expected_cmac_256));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-128 multipart test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
psa_mac_operation_t operation = PSA_MAC_OPERATION_INIT;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Test multipart operation with different chunk sizes
for (size_t chunk_size = 1; chunk_size < sizeof(test_data); chunk_size++) {
// Setup operation
status = psa_mac_sign_setup(&operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Process data in chunks
for (size_t offset = 0; offset < sizeof(test_data); offset += chunk_size) {
size_t current_chunk_size = (offset + chunk_size > sizeof(test_data)) ?
(sizeof(test_data) - offset) : chunk_size;
status = psa_mac_update(&operation, test_data + offset, current_chunk_size);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
// Finish operation
status = psa_mac_sign_finish(&operation, cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
// Verify result
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
}
// Cleanup
psa_destroy_key(key_id);
free(cmac);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC AES-128 multipart verify test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac, 16);
// Verify CMAC multipart
psa_mac_operation_t verify_operation = PSA_MAC_OPERATION_INIT;
status = psa_mac_verify_setup(&verify_operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(&verify_operation, test_data, sizeof(test_data));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify_finish(&verify_operation, cmac, cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Modify one byte of cmac and check for failure
cmac[0] = cmac[0] + 1;
status = psa_mac_verify_setup(&verify_operation, key_id, PSA_ALG_CMAC);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_update(&verify_operation, test_data, sizeof(test_data));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify_finish(&verify_operation, cmac, cmac_length);
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC zero-length test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate internal memory for CMAC output
uint8_t *cmac = heap_caps_malloc(PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(cmac);
size_t cmac_length = 0;
// Calculate CMAC on zero-length data
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
NULL, 0,
cmac, PSA_MAC_LENGTH(PSA_KEY_TYPE_AES, 128, PSA_ALG_CMAC),
&cmac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_zero_length, cmac, 16);
// Verify CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
NULL, 0,
expected_cmac_zero_length, sizeof(expected_cmac_zero_length));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
free(cmac);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC memory alignment test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Allocate memory with different capabilities
uint8_t *cmac_internal = heap_caps_malloc(16, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
uint8_t *cmac_dma = heap_caps_malloc(16, MALLOC_CAP_DMA|MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(cmac_internal);
TEST_ASSERT_NOT_NULL(cmac_dma);
size_t cmac_length_internal = 0;
size_t cmac_length_dma = 0;
// Calculate CMAC with internal memory
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac_internal, 16,
&cmac_length_internal);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length_internal);
// Calculate CMAC with DMA-capable memory
status = psa_mac_compute(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
cmac_dma, 16,
&cmac_length_dma);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
TEST_ASSERT_EQUAL(16, cmac_length_dma);
// Results should be identical
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac_internal, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_cmac_128, cmac_dma, 16);
TEST_ASSERT_EQUAL_HEX8_ARRAY(cmac_internal, cmac_dma, 16);
// Cleanup
psa_destroy_key(key_id);
free(cmac_internal);
free(cmac_dma);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA CMAC verify failure test", "[psa_cmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_CMAC);
psa_set_key_type(&attributes, PSA_KEY_TYPE_AES);
psa_set_key_bits(&attributes, 128);
// Import the key
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Create an invalid CMAC by modifying one byte
uint8_t invalid_cmac[16];
memcpy(invalid_cmac, expected_cmac_128, 16);
invalid_cmac[0] ^= 0x01; // Flip one bit
// Verify should fail with the modified CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
invalid_cmac, sizeof(invalid_cmac));
TEST_ASSERT_EQUAL(PSA_ERROR_INVALID_SIGNATURE, status);
// Verify should succeed with the correct CMAC
status = psa_mac_verify(key_id, PSA_ALG_CMAC,
test_data, sizeof(test_data),
expected_cmac_128, sizeof(expected_cmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Cleanup
psa_destroy_key(key_id);
// mbedtls_psa_crypto_free();
}
#endif /* CONFIG_MBEDTLS_CMAC_C */
@@ -0,0 +1,210 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_256[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
};
TEST_CASE("PSA ARIA-GCM multipart", "[psa-gcm]")
{
// TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
const size_t part_size = 8;
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ARIA);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
/* Encrypt */
psa_aead_operation_t enc_op = PSA_AEAD_OPERATION_INIT;
size_t out_len, total_out_len = 0;
size_t tag_length = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt_setup(&enc_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&enc_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&enc_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&enc_op, aad, aad_SZ));
// Process the plaintext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&enc_op, plaintext + offset, this_part,
ciphertext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Finish encryption and get the tag
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_finish(&enc_op,
ciphertext + total_out_len,
SZ + tag_SZ - total_out_len,
&out_len,
ciphertext + SZ,
tag_SZ,
&tag_length));
total_out_len += out_len;
/* Decrypt */
psa_aead_operation_t dec_op = PSA_AEAD_OPERATION_INIT;
total_out_len = 0;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt_setup(&dec_op, key_id, alg));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_lengths(&dec_op, aad_SZ, SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_set_nonce(&dec_op, iv, iv_SZ));
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update_ad(&dec_op, aad, aad_SZ));
// Process the ciphertext in parts
for (size_t offset = 0; offset < SZ; offset += part_size) {
size_t this_part = SZ - offset < part_size ? SZ - offset : part_size;
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_update(&dec_op, ciphertext + offset, this_part,
decryptedtext + offset, this_part, &out_len));
total_out_len += out_len;
}
// Verify the tag and finish decryption
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_verify(&dec_op,
decryptedtext + total_out_len,
SZ - total_out_len,
&out_len,
ciphertext + SZ,
tag_SZ));
total_out_len += out_len;
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
psa_aead_abort(&enc_op);
psa_aead_abort(&dec_op);
/* Destroy the key */
psa_destroy_key(key_id);
// mbedtls_psa_crypto_free();
}
TEST_CASE("PSA ARIA-GCM one-shot", "[psa-gcm]")
{
// TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_crypto_init());
const size_t SZ = 100;
const size_t iv_SZ = 12; // GCM typically uses 12 bytes IV
const size_t tag_SZ = 16; // GCM tag size
const size_t aad_SZ = 16; // Size of Additional Authenticated Data
// Allocate memory with proper alignment
uint8_t *plaintext = malloc(SZ);
uint8_t *ciphertext = malloc(SZ + tag_SZ);
uint8_t *decryptedtext = malloc(SZ);
uint8_t *iv = malloc(iv_SZ);
uint8_t *aad = malloc(aad_SZ);
TEST_ASSERT_NOT_NULL(plaintext);
TEST_ASSERT_NOT_NULL(ciphertext);
TEST_ASSERT_NOT_NULL(decryptedtext);
TEST_ASSERT_NOT_NULL(iv);
TEST_ASSERT_NOT_NULL(aad);
// Initialize test data
memset(plaintext, 0x3A, SZ);
memset(ciphertext, 0, SZ + tag_SZ);
memset(decryptedtext, 0x0, SZ);
memset(iv, 0x3B, iv_SZ);
memset(aad, 0x3C, aad_SZ);
/* Import a key */
psa_key_id_t key_id;
psa_algorithm_t alg = PSA_ALG_GCM;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_algorithm(&attributes, alg);
psa_set_key_type(&attributes, PSA_KEY_TYPE_ARIA);
psa_set_key_bits(&attributes, sizeof(key_256) * 8);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_import_key(&attributes, key_256, sizeof(key_256), &key_id));
psa_reset_key_attributes(&attributes);
size_t output_length;
/* One-shot encrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_encrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
plaintext, SZ,
ciphertext, SZ + tag_SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ + tag_SZ, output_length);
/* One-shot decrypt */
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_aead_decrypt(key_id, alg,
iv, iv_SZ,
aad, aad_SZ,
ciphertext, SZ + tag_SZ,
decryptedtext, SZ,
&output_length));
TEST_ASSERT_EQUAL_size_t(SZ, output_length);
// Verify the decrypted data matches the original plaintext
TEST_ASSERT_EQUAL_HEX8_ARRAY(plaintext, decryptedtext, SZ);
/* Cleanup */
free(plaintext);
free(ciphertext);
free(decryptedtext);
free(iv);
free(aad);
/* Destroy the key */
psa_destroy_key(key_id);
// mbedtls_psa_crypto_free();
}
@@ -0,0 +1,63 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* PSA HMAC test
*/
#include "psa/crypto.h"
#include "unity.h"
static const uint8_t key_128[] = {
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
};
static const uint8_t test_data[] = {
0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a,
0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c,
0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51
};
static const uint8_t expected_hmac_128[] = {
0x00, 0x7a, 0x5a, 0xd6, 0x54, 0x96, 0x5b, 0xcd,
0x30, 0xc1, 0x60, 0x62, 0xec, 0xac, 0x75, 0xfb,
0x87, 0x71, 0x0e, 0x13
};
TEST_CASE("PSA HMAC SHA-1 test", "[psa_hmac]")
{
psa_status_t status;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_id_t key_id = 0;
// Initialize PSA Crypto
status = PSA_SUCCESS;
// TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// Set up key attributes
psa_set_key_usage_flags(&attributes, PSA_KEY_USAGE_SIGN_MESSAGE | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_algorithm(&attributes, PSA_ALG_HMAC(PSA_ALG_SHA_1));
psa_set_key_type(&attributes, PSA_KEY_TYPE_HMAC);
psa_set_key_bits(&attributes, 128);
uint8_t *hmac = malloc(PSA_HASH_LENGTH(PSA_ALG_SHA_1));
TEST_ASSERT_NOT_NULL(hmac);
status = psa_import_key(&attributes, key_128, sizeof(key_128), &key_id);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
size_t mac_length = 0;
status = psa_mac_compute(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_1),
test_data, sizeof(test_data),
hmac, PSA_HASH_LENGTH(PSA_ALG_SHA_1), &mac_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
status = psa_mac_verify(key_id, PSA_ALG_HMAC(PSA_ALG_SHA_1),
test_data, sizeof(test_data),
expected_hmac_128, sizeof(expected_hmac_128));
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
psa_destroy_key(key_id);
psa_reset_key_attributes(&attributes);
free(hmac);
}
@@ -0,0 +1,303 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "esp_log.h"
#include "psa/crypto.h"
#include "mbedtls/pk.h"
#include "mbedtls/pem.h"
#include "mbedtls/error.h"
#include "unity.h"
#include "ccomp_timer.h"
#include "test_utils.h"
typedef enum {
PSA_RSA_KEY_SIZE_2048,
PSA_RSA_KEY_SIZE_3072,
PSA_RSA_KEY_SIZE_4096,
} psa_rsa_key_size_t;
static const char privkey_4096_buf[] = "-----BEGIN RSA PRIVATE KEY-----\n"
"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\n"
"-----END RSA PRIVATE KEY-----";
static const char privkey_2048_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEA8N8hdkemvj6Tpk975/OWhv9BrTsCBCu+ZYfDb5VI7U2meKBg\r\n"
"3dAkyyhRlY3fNwSRzBUMCzsHjpgnsB40wxOgiwlB9n6PMhq0qUVKAdCpKwFztsKd\r\n"
"JJAsCUC+Zlwxn4RpH6ZnMl3a/njRYjuDyI32kucMP/lBRo7ks1798Gy/j+x1h5xA\r\n"
"vZSlFoEXKjCC6S1DWhALePuZnk4m/jGP6g+YfyJXSTqsenKa/DcWndfn/JoElZ0J\r\n"
"nhud8lBXwVe6mMheE1yqfL+VTU1nwg/TPNZrZsFz2sXig/RQCKt6LuSuzhRpsLp+\r\n"
"BdwqEs9xrwlhZnp7j4kQBomISd6kAxQfYVROHQIDAQABAoIBAHgtO4rB8QWWPyCJ\r\n"
"I670r7OnA2OkvzrJgHMzq2SuvPX4+gfRLMM+qDzcXugZIrdWhk+maJ3p07lnXNXY\r\n"
"HEcAMedstQaA2n0LKfwSX/xL2TtlvBABRVoKvI3ZSaXUdcW60KBD69ULUsoICZ/T\r\n"
"Rcr4WX+t20TH3bOQc7ayvEwKVgE95xIUpTH9asw8uOPvKxW2j5OLQgZuWrWyUDg0\r\n"
"MFh92PhWtw3i5zq6OpTTsFJeceKYV/VstIYjZ+FslmhjQxJbr+2DJRbpHXKceqy6\r\n"
"9yWlSV0EM7neFCHlDa2WPhK8we+6IvMiNVQKj46fHGYNBaW/ZSX7TiG5J0Uqj2e9\r\n"
"0MUGJ8ECgYEA+frJabhfzW5+JfGjTObeznJZE6fAOjFzaBIwFu8Kz2mIjYpQlwVK\r\n"
"EepMkv2KkrJuqS4GnI+Nkq7G0BAUyUj9tTJ3HQzvtJrxsnxVi99Yofx1s1P4YAnu\r\n"
"c8t3ElJoQ4BRoQIs/hIvyYn22IxllBHiGESrnPQ38D82xyXQgd6S8JkCgYEA9qww\r\n"
"j7jx6Xpy/D1Dq8Dvalm7pz3J+yHnti4w2cqZ67grUoyGnNPtciNDdfi4JzLiKkUu\r\n"
"SDS3DacvFpFyND0m8sbpMjnR8Rvhj+bfH8KcOAowD+YR/+6vSb/P/aBt6gYXcaBn\r\n"
"cjepx+sE81mnC7UrHb4TjG4hO5t3ZTc6X28gyCUCgYAMZn9lSisecrO5SCJUp0M4\r\n"
"NH3stq6XdGqIKBbQnG0J2u9WLh1PUIjbGKdRx1f/bPCGXe0gCRL5yse7/IA7d+51\r\n"
"9ZnpDAI8EE+bDgXkWWD5MB/alHjGstdsURSICSR47L2f4g6/T8GlGr3vAg/r53My\r\n"
"xv1IXOkFdu1NtbeBKbxaSQKBgENDmw5mAVmIcXiFAEICn4ahp4EoYT6g9T2BhQKu\r\n"
"s6BKnU2qUj7Lr5ETOp8dzqGpx3B9Yux/q3cGotmFmd3S2x8SzJ5MlAoqbyy9aRSR\r\n"
"DeZeKNL9CuV+YcA7lOz1ZWOOe7AZbHwB38NLPBNb3CheI769iTkfAuLtNvabw8go\r\n"
"VokdAoGBALyvBhW+Squ5tx8NOEgAisakhAVOnT6jcoeKy6FyjcvKaWagmCOCC7Gz\r\n"
"QB9Yf1tJ+3di+aLtWWdmU494iKJHBtPMhfrYltCpxHHQGlUc/GLPY3Z5bBYYYWpb\r\n"
"Wzw4ZvDraKlAs7a9CRwS5cpktk5ptK4rc5noSXkvV+yOT75zXat2\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
static const char privkey_3072_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n"
"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\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
// Keep the old version for reference (has issues with PSA-based PK)
static int pem_to_der_rsa_key(const char *pem_key, size_t pem_key_len,
uint8_t *der_buf, size_t der_buf_size,
uint8_t **der_data_ptr, size_t *der_len)
{
// Use direct PEM parsing instead of PK layer for PSA compatibility
// return pem_to_der_rsa_key_direct(pem_key, pem_key_len, der_buf, der_buf_size,
// der_data_ptr, der_len);
mbedtls_pk_context pk;
int ret;
mbedtls_pk_init(&pk);
// Parse PEM key
ret = mbedtls_pk_parse_key(&pk,
(const uint8_t *)pem_key,
pem_key_len,
NULL, 0); // No password
if (ret != 0) {
char error_buf[100];
mbedtls_strerror(ret, error_buf, sizeof(error_buf));
printf("mbedtls_pk_parse_key failed: -0x%04x - %s\n", -ret, error_buf);
mbedtls_pk_free(&pk);
return ret;
}
// Write key to DER format
// NOTE: mbedtls_pk_write_key_der writes to the END of the buffer!
// Returns the length on success, or negative error code
printf("Attempting to write DER key (buffer size: %zu)...\n", der_buf_size);
ret = mbedtls_pk_write_key_der(&pk, der_buf, der_buf_size);
if (ret < 0) {
char error_buf[100];
mbedtls_strerror(ret, error_buf, sizeof(error_buf));
printf("mbedtls_pk_write_key_der failed: -0x%04x - %s\n", -ret, error_buf);
mbedtls_pk_free(&pk);
return ret;
}
printf("DER key written successfully, length: %d\n", ret);
// ret contains the length of DER data
*der_len = ret;
// Calculate the start position of DER data (at end of buffer)
*der_data_ptr = der_buf + der_buf_size - ret;
mbedtls_pk_free(&pk);
return 0;
}
static psa_key_id_t import_rsa_key(psa_rsa_key_size_t key_size)
{
psa_key_id_t key_id;
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
int ret;
// Convert PEM to DER format
uint8_t *der_buf = calloc(1, 10000); // Buffer for DER-encoded key (data written at end)
uint8_t *der_key = NULL; // Pointer to actual DER data location
size_t der_key_len = 0;
char *key_buf = NULL;
if (key_size == PSA_RSA_KEY_SIZE_2048) {
key_buf = (char *)privkey_2048_buf;
} else if (key_size == PSA_RSA_KEY_SIZE_3072) {
key_buf = (char *)privkey_3072_buf;
} else if (key_size == PSA_RSA_KEY_SIZE_4096) {
key_buf = (char *)privkey_4096_buf;
} else {
printf("Unsupported key size for import_rsa_key\n");
free(der_buf);
return 0;
}
ret = pem_to_der_rsa_key(key_buf,
strlen(key_buf) + 1, // Include null terminator
der_buf,
10000,
&der_key, // Returns pointer to DER data
&der_key_len);
TEST_ASSERT_EQUAL(0, ret);
// Configure key attributes for RSA encryption/decryption
psa_set_key_type(&attributes, PSA_KEY_TYPE_RSA_KEY_PAIR);
psa_set_key_algorithm(&attributes, PSA_ALG_RSA_PKCS1V15_CRYPT);
psa_set_key_usage_flags(&attributes,
PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
psa_set_key_lifetime(&attributes, PSA_KEY_LIFETIME_VOLATILE);
size_t key_bits = 0;
if (key_size == PSA_RSA_KEY_SIZE_2048) {
key_bits = 2048;
} else if (key_size == PSA_RSA_KEY_SIZE_3072) {
key_bits = 3072;
} else if (key_size == PSA_RSA_KEY_SIZE_4096) {
key_bits = 4096;
}
psa_set_key_bits(&attributes, key_bits);
status = psa_import_key(&attributes,
der_key, // Pointer to DER data (at end of buffer)
der_key_len,
&key_id);
if (status != PSA_SUCCESS) {
printf("PSA import failed with error: %ld (0x%x)\n", status, (unsigned int)status);
printf("Expected error codes:\n");
printf(" PSA_ERROR_INVALID_ARGUMENT = %ld\n", PSA_ERROR_INVALID_ARGUMENT);
printf(" PSA_ERROR_NOT_SUPPORTED = %ld\n", PSA_ERROR_NOT_SUPPORTED);
printf(" PSA_ERROR_INSUFFICIENT_MEMORY = %ld\n", PSA_ERROR_INSUFFICIENT_MEMORY);
}
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
free(der_buf);
psa_reset_key_attributes(&attributes);
return key_id;
}
TEST_CASE("test performance RSA key operations", "[bignum]")
{
psa_status_t status;
psa_rsa_key_size_t keysize = PSA_RSA_KEY_SIZE_2048;
for (int i = 0; i < 3; i++) {
// Use der_key (not der_buf) as it points to the actual DER data at end of buffer
psa_key_id_t key_id = import_rsa_key(keysize);
printf("RSA key imported successfully (key_id: %u)\n", (unsigned int)key_id);
size_t ciphertext_size = 0;
if (keysize == PSA_RSA_KEY_SIZE_2048) {
ciphertext_size = 256; // 2048 bits / 8
} else if (keysize == PSA_RSA_KEY_SIZE_3072) {
ciphertext_size = 384; // 3072 bits / 8
} else if (keysize == PSA_RSA_KEY_SIZE_4096) {
ciphertext_size = 512; // 4096 bits / 8
} else {
printf("Unsupported key size for ciphertext size calculation\n");
return;
}
uint8_t plaintext[] = "Test message for RSA encryption";
size_t plaintext_len = sizeof(plaintext);
uint8_t ciphertext[ciphertext_size]; // RSA 2048-bit key produces 256-byte ciphertext
size_t ciphertext_len = sizeof(ciphertext);
uint8_t decrypted[ciphertext_size];
size_t decrypted_len = sizeof(decrypted);
size_t encrypt_len = 0;
#ifdef SOC_CCOMP_TIMER_SUPPORTED
int public_perf, private_perf;
ccomp_timer_start();
#endif
// Encrypt the plaintext
status = psa_asymmetric_encrypt(key_id,
PSA_ALG_RSA_PKCS1V15_CRYPT,
plaintext,
plaintext_len,
NULL,
0,
ciphertext,
ciphertext_len,
&encrypt_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
#ifdef SOC_CCOMP_TIMER_SUPPORTED
public_perf = ccomp_timer_stop();
#endif // SOC_CCOMP_TIMER_SUPPORTED
size_t decrypt_len = 0;
#ifdef SOC_CCOMP_TIMER_SUPPORTED
ccomp_timer_start();
#endif
// Decrypt the ciphertext
status = psa_asymmetric_decrypt(key_id,
PSA_ALG_RSA_PKCS1V15_CRYPT,
ciphertext,
encrypt_len,
NULL,
0,
decrypted,
decrypted_len,
&decrypt_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
#ifdef SOC_CCOMP_TIMER_SUPPORTED
private_perf = ccomp_timer_stop();
#endif // SOC_CCOMP_TIMER_SUPPORTED
// Verify decrypted data matches original plaintext
TEST_ASSERT_EQUAL(plaintext_len, decrypt_len);
#ifdef SOC_CCOMP_TIMER_SUPPORTED
printf("RSA Key Size: %d bits\n", (keysize == PSA_RSA_KEY_SIZE_2048) ? 2048 :
(keysize == PSA_RSA_KEY_SIZE_3072) ? 3072 : 4096);
printf("Encryption took %d us, Decryption took %d us\n", public_perf, private_perf);
if (keysize == PSA_RSA_KEY_SIZE_2048) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PUBLIC_OP, "%d us", public_perf);
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PRIVATE_OP, "%d us", private_perf);
} else if (keysize == 4096) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PUBLIC_OP, "%d us", public_perf);
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PRIVATE_OP, "%d us", private_perf);
}
#endif // SOC_CCOMP_TIMER_SUPPORTED
psa_destroy_key(key_id);
keysize++;
}
}
@@ -1,611 +0,0 @@
/* mbedTLS RSA functionality tests
*
* Focus on testing functionality where we use ESP32 hardware
* accelerated crypto features
*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdbool.h>
#include "esp_system.h"
#include "esp_task_wdt.h"
#include "mbedtls/rsa.h"
#include "mbedtls/pk.h"
#include "mbedtls/x509_crt.h"
#include <mbedtls/entropy.h>
#include <mbedtls/ctr_drbg.h>
#include "entropy_poll.h"
#include "freertos/FreeRTOS.h"
#include "unity.h"
#include "test_utils.h"
#include "memory_checks.h"
#include "ccomp_timer.h"
#define PRINT_DEBUG_INFO
/* Taken from openssl s_client -connect api.gigafive.com:443 -showcerts
*/
static const char *rsa4096_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIExzCCA6+gAwIBAgIBAzANBgkqhkiG9w0BAQsFADCBkjELMAkGA1UEBhMCVVMx\n"\
"CzAJBgNVBAgMAkNBMRQwEgYDVQQHDAtTYW50YSBDbGFyYTElMCMGA1UECgwcR2ln\n"\
"YWZpdmUgVGVjaG5vbG9neSBQYXJ0bmVyczEZMBcGA1UEAwwQR2lnYWZpdmUgUm9v\n"\
"dCBDQTEeMBwGCSqGSIb3DQEJARYPY2FAZ2lnYWZpdmUuY29tMB4XDTE2MDgyNzE2\n"\
"NDYyM1oXDTI2MDgyNTE2NDYyM1owgZcxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJD\n"\
"QTEUMBIGA1UEBwwLU2FudGEgQ2xhcmExKTAnBgNVBAoMIEdpZ2FmaXZlIFRlY2hu\n"\
"b2xvZ3kgUGFydG5lcnMgTExDMRkwFwYDVQQDDBBhcGkuZ2lnYWZpdmUuY29tMR8w\n"\
"HQYJKoZIhvcNAQkBFhBjcmxAZ2lnYWZpdmUuY29tMIICIjANBgkqhkiG9w0BAQEF\n"\
"AAOCAg8AMIICCgKCAgEAof82VrEpXMpsI/ddW6RLeTeSYtxiXZZkRbDKN6otYgEk\n"\
"vA8yRbzei2cO2A/8+Erhe9beYLAMXWF+bjoUAFwnuIcbmufgHprOYzX/7CYXCsrH\n"\
"LrJfVF6kvjCXy2W3xSvgh8ZgHNWnBGzl13tq19Fz8x0AhK5GQ9608oJCbnQjpVSI\n"\
"lZDl3JVOifCeXf2c7nMhVOC/reTeto0Gbchs8Ox50WyojmfYbVjOQcA7f8p1eI+D\n"\
"XUJK01cUGVu6/KarVArGHh5LsiyXOadbyeyOXPmjyrgarG3IIBeQSNECfJZPc/OW\n"\
"lFszjU4YLDckI4x+tReiuFQbQPN5sDplcEldmZZm/8XD36ddvAaDds+SYlPXxDK7\n"\
"7L8RBVUG2Ylc9YZf7RE6IMDmdQmsCZDX0VxySYEmzv5lnAx4mzzaXcgS+kHMOLyK\n"\
"n9UxmpzwQoqqC9tMZqwRaeKW1njR1dSwQLqirBPfGCWKkpkpm7C3HEfeeLrasral\n"\
"aPf6LAwN3A4ZKHa5Jmne7W+1eYS1aTXOAOLIPcXRAh1B80H+SusIdM9d6vk2YTIg\n"\
"khwGQV3sgM6nIO5+T/8z141UEjWbtP7pb/u0+G9Cg7TwvRoO2UukxdvOwNto1G2e\n"\
"J3rKB/JSYsYWnPHvvh9XR+55PZ4iCf9Rqw/IP82uyGipR9gxlHqN8WhMTj9tNEkC\n"\
"AwEAAaMhMB8wHQYDVR0OBBYEFISCemcSriz1HFhRXluw9H+Bv9lEMA0GCSqGSIb3\n"\
"DQEBCwUAA4IBAQCMetK0xe6Y/uZpb1ARh+hHYcHI3xI+IG4opWJeoB1gDh/xpNAW\n"\
"j6t5MGbLoqNMBXbqL26hnKVspyvCxw7ebI5ZJgjtbrD1t+0D8yrgIZzr7AWGA9Hj\n"\
"WIHqDHGDxwkmfjVVPmuO3l5RtJmL6KV6kVL2bOvVI6gECpFLddmOTtg+iXDfSw3x\n"\
"0+ueMYKr8QLF+TCxfzQTHvTHvOJtcZHecc1n7PYbRmI2p7tV6RoBpV69oM6NAVUV\n"\
"i2QoSxm0pYzDzavOaxwhEPHT34Tpg6fwXy1QokFD9OtxRFtdpTjL3bMWpatZE+ba\n"\
"cjvvf0utMW5fNjTTxu1nnpuxZM3ifTCqZJ+9\n"\
"-----END CERTIFICATE-----\n";
static const char *rsa3072_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIEszCCAxugAwIBAgIUNTBsyv59/rRarOVm3KBA29zqEtUwDQYJKoZIhvcNAQEL\n"\
"BQAwaTELMAkGA1UEBhMCQ04xETAPBgNVBAgMCFNoYW5naGFpMREwDwYDVQQHDAhT\n"\
"aGFuZ2hhaTESMBAGA1UECgwJRXNwcmVzc2lmMQwwCgYDVQQLDANJREYxEjAQBgNV\n"\
"BAMMCWVzcHJlc3NpZjAeFw0yMDA3MTQwODQ5NDdaFw0yMTA3MTQwODQ5NDdaMGkx\n"\
"CzAJBgNVBAYTAkNOMREwDwYDVQQIDAhTaGFuZ2hhaTERMA8GA1UEBwwIU2hhbmdo\n"\
"YWkxEjAQBgNVBAoMCUVzcHJlc3NpZjEMMAoGA1UECwwDSURGMRIwEAYDVQQDDAll\n"\
"c3ByZXNzaWYwggGiMA0GCSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDMj3ZwPd2y\n"\
"+UxzmMUdZC5I5JQIzvUmHRNJWUe99Vht/rIEQuNSGg7xjyvuZoyeFo+Yg+QYUICa\n"\
"Ipe4y2bZS12QsTxUmeoEhYORDSeQXFEo4aUmWuKIs6Y41dBOL7eDYDL3FRmIgmcn\n"\
"qMonyCrSzXlcgHOVtMd8U8ifkX5u+nTigQLSIHVeAFz8CvC0tIiPm9YFurtMN15p\n"\
"P1K/AH17ljtwVqacrI/asZgX+ECY5rauNJLigEYgfr7+xV6GofaXp6rUpGgWbVxM\n"\
"hqKe/dbDuIzte3VK+zRDNDCeE5gPQjgoSDblOVmPemrq7KKjZ/PKmP47ct5a/0Ov\n"\
"zWcdCgaXDRoPiwbpmz3Z6uh3JdvsDf214svLK+z4EDIRzpvggM0pfDvOADatiPkr\n"\
"KmnFD1ZZx3R29/7IZ5OVvQL1hgWbm3cL4JADOc8PQKcqCzBE9JDdAVoa228ESaJ/\n"\
"n4b63qaqfgBnoaFzCEruEcXj5nuXBxlk19WWtgY1tZtAgoA8hTWxxH0CAwEAAaNT\n"\
"MFEwHQYDVR0OBBYEFPlwrvgkde/r+F8VRMMtpDUIxAtgMB8GA1UdIwQYMBaAFPlw\n"\
"rvgkde/r+F8VRMMtpDUIxAtgMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL\n"\
"BQADggGBAH9nBaEP+FWyaZnmxCblKhs8eIEYXzjxbnRUPo5b3uL/PAv1XD1kEUwY\n"\
"GWnJ7Z5HOSCdVMgo1opmKGLWuiVP6Vlt9QuA/tWh0bGScL4QfriPXuA7aXAcLbW/\n"\
"BqHNJ9Z+H2Fq09XktkZE4Nfnv3iTMMqfNCchM3t3iWZRf2sRVYIdd5OjhM+CLLUK\n"\
"kYNiseAgbcBX0/kqTdHlC6OS8Mcu9btJ/663DZy8tndf+PH+EB6fexQd9T31jWoj\n"\
"OkEkJ4vDRZP+0LceK7kNcMOcLx8DnF9LwUyHQitW7NMFServoTfxy8A0yep7nIOH\n"\
"M/ndECzirQ6WkR9jMG3cw0Jm5mZvA9IAvnLhUO45AyZGC8mShJ0AaXtqejqPg9ng\n"\
"//5VIpzoqwVkrMYlMA7ZrccQiRsd2nlBHr+64PRwRCp7y5FOxIzhGzsJibXUpO/V\n"\
"FNwuPz+VcnPvJE7r4gB1oRViiGYojMDQV3G+jbgvpTHKUKP6zzavSAKs+FlfEAmh\n"\
"EtmuT/beDA==\n"\
"-----END CERTIFICATE-----\n";
/* Root cert from openssl s_client -connect google.com:443 -showcerts
*/
static const char *rsa2048_cert = "-----BEGIN CERTIFICATE-----\n"\
"MIIFCzCCAvOgAwIBAgIQf/AFoHxM3tEArZ1mpRB7mDANBgkqhkiG9w0BAQsFADBH\n"\
"MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM\n"\
"QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMjMxMjEzMDkwMDAwWhcNMjkwMjIw\n"\
"MTQwMDAwWjA7MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNl\n"\
"cnZpY2VzMQwwCgYDVQQDEwNXUjIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\n"\
"AoIBAQCp/5x/RR5wqFOfytnlDd5GV1d9vI+aWqxG8YSau5HbyfsvAfuSCQAWXqAc\n"\
"+MGr+XgvSszYhaLYWTwO0xj7sfUkDSbutltkdnwUxy96zqhMt/TZCPzfhyM1IKji\n"\
"aeKMTj+xWfpgoh6zySBTGYLKNlNtYE3pAJH8do1cCA8Kwtzxc2vFE24KT3rC8gIc\n"\
"LrRjg9ox9i11MLL7q8Ju26nADrn5Z9TDJVd06wW06Y613ijNzHoU5HEDy01hLmFX\n"\
"xRmpC5iEGuh5KdmyjS//V2pm4M6rlagplmNwEmceOuHbsCFx13ye/aoXbv4r+zgX\n"\
"FNFmp6+atXDMyGOBOozAKql2N87jAgMBAAGjgf4wgfswDgYDVR0PAQH/BAQDAgGG\n"\
"MB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/\n"\
"AgEAMB0GA1UdDgQWBBTeGx7teRXUPjckwyG77DQ5bUKyMDAfBgNVHSMEGDAWgBTk\n"\
"rysmcRorSCeFL1JmLO/wiRNxPjA0BggrBgEFBQcBAQQoMCYwJAYIKwYBBQUHMAKG\n"\
"GGh0dHA6Ly9pLnBraS5nb29nL3IxLmNydDArBgNVHR8EJDAiMCCgHqAchhpodHRw\n"\
"Oi8vYy5wa2kuZ29vZy9yL3IxLmNybDATBgNVHSAEDDAKMAgGBmeBDAECATANBgkq\n"\
"hkiG9w0BAQsFAAOCAgEARXWL5R87RBOWGqtY8TXJbz3S0DNKhjO6V1FP7sQ02hYS\n"\
"TL8Tnw3UVOlIecAwPJQl8hr0ujKUtjNyC4XuCRElNJThb0Lbgpt7fyqaqf9/qdLe\n"\
"SiDLs/sDA7j4BwXaWZIvGEaYzq9yviQmsR4ATb0IrZNBRAq7x9UBhb+TV+PfdBJT\n"\
"DhEl05vc3ssnbrPCuTNiOcLgNeFbpwkuGcuRKnZc8d/KI4RApW//mkHgte8y0YWu\n"\
"ryUJ8GLFbsLIbjL9uNrizkqRSvOFVU6xddZIMy9vhNkSXJ/UcZhjJY1pXAprffJB\n"\
"vei7j+Qi151lRehMCofa6WBmiA4fx+FOVsV2/7R6V2nyAiIJJkEd2nSi5SnzxJrl\n"\
"Xdaqev3htytmOPvoKWa676ATL/hzfvDaQBEcXd2Ppvy+275W+DKcH0FBbX62xevG\n"\
"iza3F4ydzxl6NJ8hk8R+dDXSqv1MbRT1ybB5W0k8878XSOjvmiYTDIfyc9acxVJr\n"\
"Y/cykHipa+te1pOhv7wYPYtZ9orGBV5SGOJm4NrB3K1aJar0RfzxC3ikr7Dyc6Qw\n"\
"qDTBU39CluVIQeuQRgwG3MuSxl7zRERDRilGoKb8uY45JzmxWuKxrfwT/478JuHU\n"\
"/oTxUFqOl2stKnn7QGTq8z29W+GgBLCXSBxC9epaHM0myFH/FJlniXJfHeytWt0=\n"\
"-----END CERTIFICATE-----\n";
/* Some random input bytes to public key encrypt */
static const uint8_t pki_input[4096/8] = {
0, 1, 4, 6, 7, 9, 33, 103, 49, 11, 56, 211, 67, 92 };
/* Result of an RSA4096 operation using cert's public key
(raw PKI, no padding/etc) */
static const uint8_t pki_rsa4096_output[] = {
0x91, 0x87, 0xcd, 0x04, 0x80, 0x7c, 0x8b, 0x0b,
0x0c, 0xc0, 0x38, 0x37, 0x7a, 0xe3, 0x2c, 0x94,
0xea, 0xc4, 0xcb, 0x83, 0x2c, 0x77, 0x71, 0x14,
0x11, 0x85, 0x16, 0x61, 0xd3, 0x64, 0x2a, 0x0f,
0xf9, 0x6b, 0x45, 0x04, 0x66, 0x5d, 0x15, 0xf1,
0xcf, 0x69, 0x77, 0x90, 0xb9, 0x41, 0x68, 0xa9,
0xa6, 0xfd, 0x94, 0xdc, 0x6a, 0xce, 0xc7, 0xb6,
0x41, 0xd9, 0x44, 0x3c, 0x02, 0xb6, 0xc7, 0x26,
0xce, 0xec, 0x66, 0x21, 0xa8, 0xe8, 0xf4, 0xa9,
0x33, 0x4a, 0x6c, 0x28, 0x0f, 0x50, 0x30, 0x32,
0x28, 0x00, 0xbb, 0x2c, 0xc3, 0x44, 0x72, 0x31,
0x93, 0xd4, 0xde, 0x29, 0x6b, 0xfa, 0x31, 0xfd,
0x3a, 0x05, 0xc6, 0xb1, 0x28, 0x43, 0x57, 0x20,
0xf7, 0xf8, 0x13, 0x0c, 0x4a, 0x80, 0x00, 0xab,
0x1f, 0xe8, 0x88, 0xad, 0x56, 0xf2, 0xda, 0x5a,
0x50, 0xe9, 0x02, 0x09, 0x21, 0x2a, 0xfc, 0x82,
0x68, 0x34, 0xf9, 0x04, 0xa3, 0x25, 0xe1, 0x0f,
0xa8, 0x77, 0x29, 0x94, 0xb6, 0x9d, 0x5a, 0x08,
0x33, 0x8d, 0x27, 0x6a, 0xc0, 0x3b, 0xad, 0x91,
0x8a, 0x83, 0xa9, 0x2e, 0x48, 0xcd, 0x67, 0xa3,
0x3a, 0x35, 0x41, 0x85, 0xfa, 0x3f, 0x61, 0x1f,
0x80, 0xeb, 0xcd, 0x5a, 0xc5, 0x14, 0x7b, 0xab,
0x9c, 0x45, 0x11, 0xd2, 0x25, 0x9a, 0x16, 0xeb,
0x9c, 0xfa, 0xbe, 0x73, 0x18, 0xbd, 0x25, 0x8e,
0x99, 0x6d, 0xb3, 0xbc, 0xac, 0x2d, 0xa2, 0x53,
0xe8, 0x7c, 0x38, 0x1b, 0x7a, 0x75, 0xff, 0x76,
0x4f, 0x48, 0x5b, 0x39, 0x20, 0x5a, 0x7b, 0x82,
0xd3, 0x33, 0x33, 0x2a, 0xab, 0x6a, 0x7a, 0x42,
0x1d, 0x1f, 0xd1, 0x61, 0x58, 0xd7, 0x38, 0x52,
0xdf, 0xb0, 0x61, 0x98, 0x63, 0xb7, 0xa1, 0x4e,
0xdb, 0x9b, 0xcb, 0xb7, 0x85, 0xc4, 0x3e, 0x03,
0xe5, 0x59, 0x50, 0x28, 0x5a, 0x4d, 0x7f, 0x53,
0x2e, 0x99, 0x1d, 0x6d, 0x85, 0x27, 0x78, 0x34,
0x5e, 0xae, 0xc9, 0x1b, 0x37, 0x96, 0xde, 0x40,
0x87, 0x35, 0x3c, 0x1f, 0xe0, 0x8f, 0xfb, 0x3a,
0x58, 0x0e, 0x60, 0xe9, 0x06, 0xbd, 0x83, 0x03,
0x92, 0xde, 0x5e, 0x69, 0x28, 0xb1, 0x00, 0xeb,
0x44, 0xca, 0x3c, 0x49, 0x03, 0x10, 0xa8, 0x84,
0xa6, 0xbb, 0xd5, 0xda, 0x98, 0x8c, 0x6f, 0xa3,
0x0f, 0x39, 0xf3, 0xa7, 0x7d, 0xd5, 0x3b, 0xe2,
0x85, 0x12, 0xda, 0xa4, 0x4d, 0x80, 0x97, 0xcb,
0x11, 0xe0, 0x89, 0x90, 0xff, 0x5b, 0x72, 0x19,
0x59, 0xd1, 0x39, 0x23, 0x9f, 0xb0, 0x00, 0xe2,
0x45, 0x72, 0xc6, 0x9a, 0xbc, 0xe1, 0xd1, 0x51,
0x6b, 0x35, 0xd2, 0x49, 0xbf, 0xb6, 0xfe, 0xab,
0x09, 0xf7, 0x9d, 0xa4, 0x6e, 0x69, 0xb6, 0xf9,
0xde, 0xe3, 0x57, 0x0c, 0x1a, 0x96, 0xf1, 0xcc,
0x1c, 0x92, 0xdb, 0x44, 0xf4, 0x45, 0xfa, 0x8f,
0x87, 0xcf, 0xf4, 0xd2, 0xa1, 0xf8, 0x69, 0x18,
0xcf, 0xdc, 0xa0, 0x1f, 0xb0, 0x26, 0xad, 0x81,
0xab, 0xdf, 0x78, 0x18, 0xa2, 0x74, 0xba, 0x2f,
0xec, 0x70, 0xa2, 0x1f, 0x56, 0xee, 0xff, 0xc9,
0xfe, 0xb1, 0xe1, 0x9b, 0xea, 0x0e, 0x33, 0x14,
0x5f, 0x6e, 0xca, 0xee, 0x02, 0x56, 0x5a, 0x67,
0x42, 0x9a, 0xbf, 0x55, 0xc0, 0x0f, 0x8e, 0x01,
0x67, 0x63, 0x6e, 0xd1, 0x57, 0xf7, 0xf1, 0xc6,
0x92, 0x9e, 0xb5, 0x45, 0xe1, 0x50, 0x58, 0x94,
0x20, 0x90, 0x6a, 0x29, 0x2d, 0x4b, 0xd1, 0xb5,
0x68, 0x63, 0xb5, 0xe6, 0xd8, 0x6e, 0x84, 0x80,
0xad, 0xe6, 0x03, 0x1e, 0x51, 0xc2, 0xa8, 0x6d,
0x84, 0xec, 0x2d, 0x7c, 0x61, 0x02, 0xd1, 0xda,
0xf5, 0x94, 0xfa, 0x2d, 0xa6, 0xed, 0x89, 0x6a,
0x6a, 0xda, 0x07, 0x5d, 0x83, 0xfc, 0x43, 0x76,
0x7c, 0xca, 0x8c, 0x00, 0xfc, 0xb9, 0x2c, 0x23,
};
static const uint8_t pki_rsa3072_output[] = {
0x86, 0xc0, 0xe4, 0xa5, 0x4b, 0x45, 0xe4, 0xd4, 0x0f, 0xb7, 0xe3, 0x10, 0x4f, 0xea, 0x88, 0x91,
0x3d, 0xad, 0x43, 0x86, 0x90, 0xf0, 0xd8, 0xf0, 0x29, 0x21, 0xc7, 0x5c, 0x75, 0x49, 0x91, 0xce,
0xf8, 0x34, 0x91, 0xbd, 0x89, 0x61, 0xcf, 0x47, 0x0e, 0x4d, 0x3f, 0x29, 0xd1, 0x02, 0xa7, 0xa8,
0x8f, 0x6a, 0xda, 0x1a, 0xf2, 0xf1, 0x18, 0x92, 0x35, 0xf6, 0x0c, 0x07, 0x5a, 0x84, 0xfa, 0x65,
0xd3, 0x02, 0xe0, 0x53, 0x17, 0x5d, 0xf7, 0x45, 0x26, 0xcc, 0xf9, 0x26, 0xf5, 0x6a, 0x66, 0xbb,
0xef, 0x33, 0xcb, 0x03, 0x6e, 0x6a, 0x93, 0x6c, 0x2a, 0x27, 0xa7, 0xf7, 0x2c, 0xdc, 0x00, 0xdd,
0x98, 0x52, 0xfb, 0xce, 0x31, 0xe2, 0x96, 0x20, 0x98, 0x0a, 0xf4, 0x19, 0x0f, 0xbf, 0x22, 0xed,
0x37, 0xb2, 0x14, 0x10, 0x88, 0xa3, 0x6a, 0x43, 0x26, 0xb8, 0x54, 0xf1, 0xb8, 0xc6, 0x56, 0xb7,
0x89, 0x34, 0xc0, 0xba, 0xae, 0x38, 0x35, 0x2c, 0x13, 0x57, 0x7a, 0xa4, 0x4b, 0xf2, 0x21, 0x82,
0xf4, 0xea, 0x1a, 0x2c, 0xd8, 0x32, 0xe8, 0x5f, 0x37, 0x04, 0x52, 0x3d, 0xff, 0xc2, 0x85, 0x00,
0xd2, 0x8d, 0x84, 0x36, 0x61, 0x61, 0x7b, 0xea, 0x7c, 0x3d, 0xeb, 0x51, 0xea, 0xf2, 0x67, 0xc9,
0xb8, 0xa6, 0x98, 0x54, 0x3f, 0x5b, 0x8f, 0x1a, 0x8a, 0x93, 0x81, 0x05, 0xa3, 0x15, 0xf8, 0x54,
0x8f, 0x75, 0xe2, 0x01, 0xc3, 0x47, 0xc3, 0x8f, 0xc7, 0x6d, 0x04, 0xbc, 0x05, 0x88, 0xd9, 0x62,
0xcc, 0x14, 0xea, 0x30, 0x68, 0x73, 0xd5, 0xe5, 0x53, 0x7c, 0xb1, 0xa0, 0xe5, 0x6c, 0xd0, 0xa3,
0x07, 0x2a, 0x5e, 0x2a, 0x0f, 0x89, 0x39, 0xea, 0xf9, 0xf5, 0xfb, 0x3b, 0xee, 0x66, 0xd9, 0xd4,
0x04, 0x2d, 0x1b, 0xc9, 0xc2, 0x37, 0xc8, 0xa8, 0x71, 0xea, 0xa8, 0xf6, 0xe6, 0xc1, 0xdc, 0x5b,
0x70, 0x68, 0x89, 0xa5, 0x69, 0xc0, 0x7f, 0x15, 0x8b, 0x6d, 0xc6, 0x88, 0x41, 0x8b, 0x25, 0x8f,
0x2f, 0x5c, 0x81, 0x94, 0x1b, 0x8c, 0x52, 0x3f, 0xe5, 0x97, 0x6d, 0x4a, 0xc6, 0x42, 0x35, 0x0e,
0x59, 0xce, 0x00, 0x3c, 0x2b, 0x0f, 0x5a, 0xc5, 0x1b, 0x01, 0xf3, 0x02, 0x70, 0xb1, 0x88, 0xda,
0x7b, 0x5b, 0x4d, 0x3e, 0xd1, 0x15, 0x57, 0xc8, 0x39, 0x14, 0xff, 0x8d, 0x2b, 0x12, 0xf5, 0x5b,
0xaf, 0x78, 0x2e, 0x0b, 0xcd, 0x27, 0x83, 0xdb, 0x4e, 0xe1, 0x5d, 0xa5, 0xbd, 0xfe, 0x2b, 0x6e,
0x8b, 0x54, 0x7d, 0x14, 0x6f, 0x4d, 0xe1, 0x14, 0xc8, 0x30, 0x0e, 0x10, 0x23, 0x2a, 0xe1, 0xe5,
0xee, 0xa3, 0x69, 0x8d, 0xe2, 0x9a, 0xed, 0x0c, 0x23, 0x16, 0x8e, 0x95, 0xae, 0x1a, 0xa2, 0x28,
0x61, 0x25, 0xa2, 0x15, 0x74, 0xc4, 0xec, 0x6b, 0x73, 0xb2, 0x8c, 0xd2, 0x64, 0xfd, 0x2b, 0x92,
};
static const uint8_t pki_rsa2048_output[] = {
0x3c, 0xd6, 0xc2, 0xbf, 0x01, 0x4a, 0x00, 0x95,
0x2c, 0x32, 0x11, 0xc0, 0xc9, 0x7e, 0x8f, 0x0a,
0x15, 0xee, 0xfb, 0x34, 0x1d, 0xaa, 0xae, 0x15,
0x11, 0x6d, 0x99, 0x2b, 0x09, 0xeb, 0x3f, 0x89,
0x46, 0x98, 0x08, 0x2f, 0x10, 0x13, 0xa1, 0x17,
0xc7, 0xec, 0x67, 0x3a, 0x34, 0x4f, 0x40, 0xcd,
0xe2, 0xc0, 0xbe, 0x99, 0xc7, 0xe7, 0xff, 0xea,
0xd0, 0x82, 0xd2, 0x62, 0x73, 0xde, 0x56, 0xe8,
0xb6, 0xa7, 0xe7, 0xe1, 0x64, 0x90, 0x00, 0x56,
0x1d, 0x2c, 0x1c, 0xc5, 0xec, 0x7f, 0xb1, 0x87,
0x59, 0xb1, 0xd6, 0x44, 0x0f, 0x67, 0x35, 0xb4,
0x91, 0x49, 0xed, 0x10, 0x4c, 0xef, 0xe5, 0xc8,
0xea, 0x0d, 0xbd, 0xaf, 0xb9, 0xad, 0x12, 0x41,
0xaa, 0xf4, 0x68, 0x54, 0x08, 0xec, 0x70, 0x8c,
0xac, 0x6b, 0x57, 0xcf, 0x0a, 0x0c, 0x08, 0x34,
0x28, 0x29, 0x27, 0xa4, 0x71, 0x80, 0x43, 0x59,
0xd9, 0x35, 0x88, 0x28, 0x1d, 0xfa, 0x0b, 0x72,
0xa0, 0xe1, 0x03, 0x65, 0x7a, 0xf8, 0x1c, 0x76,
0x9a, 0xad, 0x21, 0x23, 0x11, 0x2f, 0x45, 0x40,
0x72, 0x05, 0x69, 0x1b, 0x2a, 0x74, 0x9f, 0x95,
0x44, 0x60, 0x05, 0x6a, 0x17, 0x80, 0x4a, 0xa0,
0xed, 0x23, 0xa6, 0xef, 0x79, 0x5d, 0x83, 0xd8,
0x8d, 0xd8, 0xe1, 0x4c, 0x5e, 0xf8, 0xfa, 0x11,
0x57, 0xbe, 0xca, 0x22, 0x93, 0x5b, 0xe6, 0x8b,
0xe1, 0x31, 0xde, 0x70, 0x80, 0x4a, 0xa2, 0xd3,
0x91, 0xe8, 0xde, 0x88, 0xa2, 0x98, 0x73, 0x49,
0x0d, 0x26, 0xe1, 0x42, 0xd7, 0xb9, 0x5e, 0xf6,
0x05, 0x09, 0x27, 0xc6, 0x8c, 0xc2, 0xb1, 0x53,
0x5f, 0x19, 0xaf, 0x2b, 0xfe, 0xac, 0x6a, 0x27,
0xde, 0x89, 0xbc, 0x72, 0x3e, 0xd5, 0x9f, 0x36,
0xc2, 0x91, 0x68, 0x30, 0xe7, 0x76, 0x96, 0x56,
0x8f, 0x01, 0xc4, 0x5b, 0xb7, 0xb3, 0x90, 0x7f,
};
#ifdef CONFIG_MBEDTLS_HARDWARE_MPI
/* Pregenerated RSA 4096 size keys using openssl */
static const char privkey_4096_buf[] = "-----BEGIN RSA PRIVATE KEY-----\n"
"MIIJKAIBAAKCAgEA1blr9wfIzTylroJHxcoq+YFA765gF5vj9b6tfaPG0XQExSkjndHv5sra4ar7T+k2sBB4OcKKeGHkNk6wk8tGmOS79r2L74XZs1eB0UruG+huV7Sd+YiWzwN8y9jGImA9hIkf1qxIvkco5WTmT7cVwUnCQ7qiiVadD/LgyeGD04yKZpzv9UJzfjXz5ITTn/ejcn7423M9qz41nhRWwK4zw1jv7IB57d1dWOCbN3RO4dvfVndCz8DOmLzJrZAkLsz39vppbIwbMqTXKFxWqzZY2xrYmnMx9p3v4hLeju7ls3fsekESonoP0C76u50wJfZWO2XcIUo4pue/jHi2o9KouhLXW/vyasplXvE6FFrBjSpsm1Nar4KQMUolEkUbO9baGcQvH9G5WOH0kwPt7AOSqM2EUPvBd7Jv0tbMI/BRZVVltC/t6WhannCM/I6nZrlNe5tie/qYlFu474jp5/tpa8RykkDxwl9whejIqd4iQbvDiP/GXgBYtDJ9VU/S2KqHJhQFLDi+F3+ewOcF391fgt1e1J2vNYLKZOfxTOl/1vJbU/2IjRWTRQ7cXnmpR/GNCRfgH2as6Z/0oknBSVephguDnO5QlveP4Cx2EOVY/A/KgDpu8PumSrlIk+YQgLxdKsXaVI6eDY4rY7q2uCJH3yIAfZJXEeD+ResUuSZltvECAwEAAQKCAgBwR89+oipOGHR6b5tBP+q/1bXFtXhqLs3eBuSiQu5qj2cKJYi+mtJMD3paYDdTThQa/ywKPDf+8n6wQTrnCj32iQRupjnkBg/O9kQPLixVoRCHJy5vL+D6tLxVY3cEDEeFX3zIjQ5SWJQVn6KXcnoNZ7CVYHGPcV9mR5TsuntFImp7aituUBDY14NgJKABRFosBqS6tZpKYo5MlCbXZy1ujUTOnNhxrIAj9yvUQFhIs/hrNpB1ELf46gWSF03LAIesyvWjvx9yxcL7QzeNDyozQbFVwvsWsvaZcIxXzw4B8RjdSV5+2V2BY4z6D6SB7R50ahjxrEqC9PFe3PQmsL9OvFjV9idYwFOhxiWXGjIm3wwFFLOj3e0TShscj2Iw+Ghd3wApvSdBZxzdjap1NHC+Q6yYU+BnivxUHcopVPPM3rsLndyRC6zfrQw/OkOlAP3bNL1hRedPRmRDOz0V1ihEpgC1VfXx6XOu4eg8xWiJgWX+BGvT5GWjfQg2hB1Jm344r3l0eLhr25dO80GIac2QGT2+WmYkXcsQ3AiqAn2VF8UB5mU+Iyh96jmSFVVltGZgfp98yFYN63/7wB++lhVQmJZwbglutng1qjQBFslIULddIHiYvF+AVvkrO3Hc2zg8rT91tbE13k06A1zlNGcQuQKLax8e+2/BNjsZU2E4uQKCAQEA7L4obKWYRHgG6j1VEDRrQU8Vkm4L11B+ZD/rsEh3q7LbzViOPv+1dZ40jX2qYScWyaefI46bukJlk/mlNv4Dh3EnSFvHPCInDM3oImCYImwUx0hkbSRyRNwlwRwx81LJzIR84cCqpNWrXXcplomUSM62ea1E1vtNSZs9Bg2OLoWvFOTPgk/xDi6ezdb6JFiId6cARup/bmZ363mg8jCq0wpTLVdUGrezfMj4GpB1uQET5xqXleumQu/04cHPOfXwpV0ikIOId/ldY/PetiRd86B32aB2Xd4fHUpxHMY+63MFmL6SsqMQJMPubv+eIrOId4HhT+nXNFBZXolT5XG5NwKCAQEA5xvvccHNyCTL0AebxD6EihWnp0/Dd0DwXWxZw0Yhhc9xa/W/QtygB6kPb35oKGvCKdm4dWCIGln03dU5D6CMNkJlbkxpo8gybz34SJ/6OvU836rBLHZXE3Xiqbe5XkdMdarA7kTEhEUqekDXPxhws9dWh0YjtAnBPpm1GQppiykI2edkiIhRgju5ghe+/UjAjxrEgCKZeAODh46hwZHERRKQN2MFUOFcOVDq+2wTJem9r3h1uBQAiZn8PDyx0rlRkwH2dZSSauVW+I713N0JGucOV7FeMO0ebioqqckh0i91ZJNH//Io8Sp8WuBsU/vcP9jT+5BDkCbc71BRO/AFFwKCAQBj4a6oeA0QBhvUw9+ZoKQHv9f4GZnBU+KfZSCJFWn39NQrhMsu5S+n2gGOGJDDwHwqxB+uHsKxCMZWciM0WmMex6ytKJucUURscIsZxespyrPRiEdmjNPxHXiISt8AK9OcB+GwVVsphERygI35Rz5aoWv3VhUPJqNrBKXwYdO06Q3/ILIz5oprU1wIuER9BSU+ZiUFxnXRHEZIAN7Yj5Piyh5hqNCBHTQK17dlbcFdNokxHdUKmYth/l8wyFYnvA21lt+4XOY8x+aQ/xjde+ZvnSozlTGbVNWHxBqI61MsfzDDStQVrhpniIqWJh6PwXM4CIII9z2mgqfR7NqKmTptAoIBAQDTYQOigmZbFvyrayoXVi8XtTLAnv3jByxR5pY7OtvSbagJ3J1w5CYim4iYq39M6TKP4KkMApy5rWl/tFQabPeRcS0gsxc0TBmFEaMTme7fGgrxcFZ6+koubHZCUN5k0sWmIeWQiKlNaY2uf7vf49TBSMXFuGtTclCjlybCnnlmZMPJuhCDqFsUyNelm15+f5pPyWXM5NiFooEc7WIZj996Zb4uSo1EKruVWONzzqe814s9AOp60SCkuoiv97uVRxbLZNItPRSmXNktQmSx/CEl0AuYPYwvJ9HbZQncfTBH9ExlDyidernjyr4uyHGMZyJN614ICy0gncsZv9ZtAd1FAoIBAA4toGPU/VcKFmK92zgO05jsg5vJzw5xeoxRWKrLg7iby6Su6BuNgaVwfYWeZuOhnXakid7FvFXKH6x44o9gyFm5bKqFhaXDzAnxzqcLeM5V+gititOsstpZCbVOoKQOhgTHyxpFNVX3E/nB8EunydWyhQMxKme//NsRroFm1vWljQKyL3zER82AzyseEpEYZoB/6g0n5uF2lR7KllxeBlINsceQ8g3JkmJTdS1hoXcyUSsZ+EgrRbCykNB5aVC5G3/W1OSZsFHbbMrYHCMnaYKwMqLmOkb11o6nOrJJ4pgHj8CVcp2TNjfy3y0Ru6RZ42b0Q+3LktJBGu9r5d04FgI=\n"
"-----END RSA PRIVATE KEY-----";
static const char privkey_2048_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n"
"MIIEowIBAAKCAQEA8N8hdkemvj6Tpk975/OWhv9BrTsCBCu+ZYfDb5VI7U2meKBg\r\n"
"3dAkyyhRlY3fNwSRzBUMCzsHjpgnsB40wxOgiwlB9n6PMhq0qUVKAdCpKwFztsKd\r\n"
"JJAsCUC+Zlwxn4RpH6ZnMl3a/njRYjuDyI32kucMP/lBRo7ks1798Gy/j+x1h5xA\r\n"
"vZSlFoEXKjCC6S1DWhALePuZnk4m/jGP6g+YfyJXSTqsenKa/DcWndfn/JoElZ0J\r\n"
"nhud8lBXwVe6mMheE1yqfL+VTU1nwg/TPNZrZsFz2sXig/RQCKt6LuSuzhRpsLp+\r\n"
"BdwqEs9xrwlhZnp7j4kQBomISd6kAxQfYVROHQIDAQABAoIBAHgtO4rB8QWWPyCJ\r\n"
"I670r7OnA2OkvzrJgHMzq2SuvPX4+gfRLMM+qDzcXugZIrdWhk+maJ3p07lnXNXY\r\n"
"HEcAMedstQaA2n0LKfwSX/xL2TtlvBABRVoKvI3ZSaXUdcW60KBD69ULUsoICZ/T\r\n"
"Rcr4WX+t20TH3bOQc7ayvEwKVgE95xIUpTH9asw8uOPvKxW2j5OLQgZuWrWyUDg0\r\n"
"MFh92PhWtw3i5zq6OpTTsFJeceKYV/VstIYjZ+FslmhjQxJbr+2DJRbpHXKceqy6\r\n"
"9yWlSV0EM7neFCHlDa2WPhK8we+6IvMiNVQKj46fHGYNBaW/ZSX7TiG5J0Uqj2e9\r\n"
"0MUGJ8ECgYEA+frJabhfzW5+JfGjTObeznJZE6fAOjFzaBIwFu8Kz2mIjYpQlwVK\r\n"
"EepMkv2KkrJuqS4GnI+Nkq7G0BAUyUj9tTJ3HQzvtJrxsnxVi99Yofx1s1P4YAnu\r\n"
"c8t3ElJoQ4BRoQIs/hIvyYn22IxllBHiGESrnPQ38D82xyXQgd6S8JkCgYEA9qww\r\n"
"j7jx6Xpy/D1Dq8Dvalm7pz3J+yHnti4w2cqZ67grUoyGnNPtciNDdfi4JzLiKkUu\r\n"
"SDS3DacvFpFyND0m8sbpMjnR8Rvhj+bfH8KcOAowD+YR/+6vSb/P/aBt6gYXcaBn\r\n"
"cjepx+sE81mnC7UrHb4TjG4hO5t3ZTc6X28gyCUCgYAMZn9lSisecrO5SCJUp0M4\r\n"
"NH3stq6XdGqIKBbQnG0J2u9WLh1PUIjbGKdRx1f/bPCGXe0gCRL5yse7/IA7d+51\r\n"
"9ZnpDAI8EE+bDgXkWWD5MB/alHjGstdsURSICSR47L2f4g6/T8GlGr3vAg/r53My\r\n"
"xv1IXOkFdu1NtbeBKbxaSQKBgENDmw5mAVmIcXiFAEICn4ahp4EoYT6g9T2BhQKu\r\n"
"s6BKnU2qUj7Lr5ETOp8dzqGpx3B9Yux/q3cGotmFmd3S2x8SzJ5MlAoqbyy9aRSR\r\n"
"DeZeKNL9CuV+YcA7lOz1ZWOOe7AZbHwB38NLPBNb3CheI769iTkfAuLtNvabw8go\r\n"
"VokdAoGBALyvBhW+Squ5tx8NOEgAisakhAVOnT6jcoeKy6FyjcvKaWagmCOCC7Gz\r\n"
"QB9Yf1tJ+3di+aLtWWdmU494iKJHBtPMhfrYltCpxHHQGlUc/GLPY3Z5bBYYYWpb\r\n"
"Wzw4ZvDraKlAs7a9CRwS5cpktk5ptK4rc5noSXkvV+yOT75zXat2\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
static const char privkey_3072_buf[] = "-----BEGIN RSA PRIVATE KEY-----\r\n"
"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\r\n"
"-----END RSA PRIVATE KEY-----\r\n";
#endif
_Static_assert(sizeof(pki_rsa2048_output) == 2048/8, "rsa2048 output is wrong size");
_Static_assert(sizeof(pki_rsa3072_output) == 3072/8, "rsa3072 output is wrong size");
_Static_assert(sizeof(pki_rsa4096_output) == 4096/8, "rsa4096 output is wrong size");
void mbedtls_mpi_printf(const char *name, const mbedtls_mpi *X);
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len);
TEST_CASE("mbedtls RSA4096 cert", "[mbedtls]")
{
test_cert(rsa4096_cert, pki_rsa4096_output, 4096/8);
}
TEST_CASE("mbedtls RSA3072 cert", "[mbedtls]")
{
test_cert(rsa3072_cert, pki_rsa3072_output, 3072/8);
}
TEST_CASE("mbedtls RSA2048 cert", "[mbedtls]")
{
test_cert(rsa2048_cert, pki_rsa2048_output, 2048/8);
}
static void test_cert(const char *cert, const uint8_t *expected_output, size_t output_len)
{
mbedtls_x509_crt crt;
mbedtls_rsa_context *rsa;
char buf[output_len];
int res;
bzero(buf, output_len);
mbedtls_x509_crt_init(&crt);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-mbedtls_x509_crt_parse(&crt,
(const uint8_t *)cert,
strlen(cert)+1),
"parse cert");
rsa = mbedtls_pk_rsa(crt.pk);
TEST_ASSERT_NOT_NULL(rsa);
res = mbedtls_rsa_check_pubkey(rsa);
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-res,
"check cert pubkey");
mbedtls_x509_crt_info(buf, sizeof(buf), "", &crt);
puts(buf);
res = mbedtls_rsa_public(rsa, pki_input, (uint8_t *)buf);
if (res == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE + MBEDTLS_ERR_RSA_PUBLIC_FAILED) {
mbedtls_x509_crt_free(&crt);
TEST_IGNORE_MESSAGE("Hardware does not support this key length");
}
TEST_ASSERT_EQUAL_HEX16_MESSAGE(0,
-res,
"RSA PK operation");
/*
// Dump buffer for debugging
for(int i = 0; i < output_len; i++) {
printf("0x%02x, ", buf[i]);
}
printf("\n");
*/
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_output, buf, output_len);
mbedtls_x509_crt_free(&crt);
}
#ifdef CONFIG_MBEDTLS_HARDWARE_MPI
static void rsa_key_operations(int keysize, bool check_performance, bool generate_new_rsa);
static int myrand(void *rng_state, unsigned char *output, size_t len)
{
size_t olen;
return mbedtls_hardware_poll(rng_state, output, len, &olen);
}
#ifdef PRINT_DEBUG_INFO
static void print_rsa_details(mbedtls_rsa_context *rsa)
{
mbedtls_mpi X[5];
for (int i=0; i<5; ++i) {
mbedtls_mpi_init( &X[i] );
}
if (0 == mbedtls_rsa_export(rsa, &X[0], &X[1], &X[2], &X[3], &X[4])) {
for (int i=0; i<5; ++i) {
mbedtls_mpi_printf((char*)"N\0P\0Q\0D\0E" + 2*i, &X[i]);
mbedtls_mpi_free( &X[i] );
}
}
}
#endif
#if CONFIG_FREERTOS_SMP // IDF-5826
TEST_CASE("test performance RSA key operations", "[bignum][timeout=60]")
#else
TEST_CASE("test performance RSA key operations", "[bignum]")
#endif
{
/** NOTE:
* For ESP32-S3, CONFIG_ESP_CONSOLE_SECONDARY_USB_SERIAL_JTAG is enabled
* by default; allocating a lock of 92 bytes, which is never freed.
*
* MR !18574 adds the MPI crypto lock for S3 increasing the leakage by
* 92 bytes. This caused the RSA UT to fail with a leakage more than
* 1024 bytes.
*
* The allocations made by ESP32-S2 (944 bytes) and ESP32-S3 are the same,
* except for the JTAG lock (92 + 944 > 1024).
*/
TEST_ESP_OK(test_utils_set_leak_level(1088, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
for (int keysize = 2048; keysize <= SOC_RSA_MAX_BIT_LEN; keysize += 1024) {
rsa_key_operations(keysize, true, false);
}
}
#if CONFIG_FREERTOS_SMP // IDF-5826
TEST_CASE("test RSA-3072 calculations", "[bignum][timeout=60]")
#else
TEST_CASE("test RSA-3072 calculations", "[bignum]")
#endif
{
// use pre-genrated keys to make the test run a bit faster
rsa_key_operations(3072, false, false);
}
#if CONFIG_FREERTOS_SMP // IDF-5826
TEST_CASE("test RSA-2048 calculations", "[bignum][timeout=60]")
#else
TEST_CASE("test RSA-2048 calculations", "[bignum]")
#endif
{
// use pre-genrated keys to make the test run a bit faster
rsa_key_operations(2048, false, false);
}
#if CONFIG_FREERTOS_SMP // IDF-5826
TEST_CASE("test RSA-4096 calculations", "[bignum][timeout=60]")
#else
TEST_CASE("test RSA-4096 calculations", "[bignum]")
#endif
{
// use pre-genrated keys to make the test run a bit faster
rsa_key_operations(4096, false, false);
}
static void rsa_key_operations(int keysize, bool check_performance, bool generate_new_rsa)
{
mbedtls_pk_context clientkey;
mbedtls_rsa_context rsa;
unsigned char orig_buf[4096 / 8];
unsigned char encrypted_buf[4096 / 8];
unsigned char decrypted_buf[4096 / 8];
int res = 0;
printf("First, orig_buf is encrypted by the public key, and then decrypted by the private key\n");
printf("keysize=%d check_performance=%d generate_new_rsa=%d\n", keysize, check_performance, generate_new_rsa);
memset(orig_buf, 0xAA, sizeof(orig_buf));
orig_buf[0] = 0; // Ensure that orig_buf is smaller than rsa.N
if (generate_new_rsa) {
mbedtls_rsa_init(&rsa);
TEST_ASSERT_EQUAL(0, mbedtls_rsa_gen_key(&rsa, myrand, NULL, keysize, 65537));
} else {
mbedtls_pk_init(&clientkey);
switch(keysize) {
case 4096:
res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_4096_buf, sizeof(privkey_4096_buf), NULL, 0, myrand, NULL);
break;
case 3072:
res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_3072_buf, sizeof(privkey_3072_buf), NULL, 0, myrand, NULL);
break;
case 2048:
res = mbedtls_pk_parse_key(&clientkey, (const uint8_t *)privkey_2048_buf, sizeof(privkey_2048_buf), NULL, 0, myrand, NULL);
break;
default:
TEST_FAIL_MESSAGE("unsupported keysize, pass generate_new_rsa=true or update test");
}
TEST_ASSERT_EQUAL_HEX16(0, -res);
memcpy(&rsa, mbedtls_pk_rsa(clientkey), sizeof(mbedtls_rsa_context));
}
#ifdef PRINT_DEBUG_INFO
print_rsa_details(&rsa);
#endif
TEST_ASSERT_EQUAL(keysize, (int)rsa.MBEDTLS_PRIVATE(len) * 8);
TEST_ASSERT_EQUAL(keysize, (int)rsa.MBEDTLS_PRIVATE(D).MBEDTLS_PRIVATE(n) * sizeof(mbedtls_mpi_uint) * 8); // The private exponent
#ifdef SOC_CCOMP_TIMER_SUPPORTED
int public_perf, private_perf;
ccomp_timer_start();
res = mbedtls_rsa_public(&rsa, orig_buf, encrypted_buf);
public_perf = ccomp_timer_stop();
if (res == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE + MBEDTLS_ERR_RSA_PUBLIC_FAILED) {
mbedtls_rsa_free(&rsa);
TEST_IGNORE_MESSAGE("Hardware does not support this key length");
}
TEST_ASSERT_EQUAL_HEX16(0, -res);
ccomp_timer_start();
res = mbedtls_rsa_private(&rsa, myrand, NULL, encrypted_buf, decrypted_buf);
private_perf = ccomp_timer_stop();
TEST_ASSERT_EQUAL_HEX16(0, -res);
if (check_performance && keysize == 2048) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PUBLIC_OP, "%d us", public_perf);
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_2048KEY_PRIVATE_OP, "%d us", private_perf);
} else if (check_performance && keysize == 4096) {
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PUBLIC_OP, "%d us", public_perf);
TEST_PERFORMANCE_CCOMP_LESS_THAN(RSA_4096KEY_PRIVATE_OP, "%d us", private_perf);
}
#else
res = mbedtls_rsa_public(&rsa, orig_buf, encrypted_buf);
TEST_ASSERT_EQUAL_HEX16(0, -res);
res = mbedtls_rsa_private(&rsa, myrand, NULL, encrypted_buf, decrypted_buf);
TEST_ASSERT_EQUAL_HEX16(0, -res);
TEST_IGNORE_MESSAGE("Performance check skipped! (soc doesn't support ccomp timer)");
#endif
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(orig_buf, decrypted_buf, keysize / 8, "RSA operation");
mbedtls_rsa_free(&rsa);
}
TEST_CASE("mbedtls RSA Generate Key", "[mbedtls][timeout=60]")
{
mbedtls_rsa_context ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
const unsigned int key_size = 2048;
const int exponent = 65537;
#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT
/* Check that generating keys doesn't starve the watchdog if interrupt-based driver is used */
esp_task_wdt_config_t twdt_config = {
.timeout_ms = 1000,
.idle_core_mask = (1 << 0), // Watch core 0 idle
.trigger_panic = true,
};
TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_init(&twdt_config));
#endif // CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT
mbedtls_rsa_init(&ctx);
mbedtls_ctr_drbg_init(&ctr_drbg);
mbedtls_entropy_init(&entropy);
TEST_ASSERT_FALSE( mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, NULL, 0) );
TEST_ASSERT_FALSE( mbedtls_rsa_gen_key(&ctx, mbedtls_ctr_drbg_random, &ctr_drbg, key_size, exponent) );
mbedtls_rsa_free(&ctx);
mbedtls_ctr_drbg_free(&ctr_drbg);
mbedtls_entropy_free(&entropy);
#if CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT
TEST_ASSERT_EQUAL(ESP_OK, esp_task_wdt_deinit());
#endif // CONFIG_MBEDTLS_MPI_USE_INTERRUPT && CONFIG_ESP_TASK_WDT_EN && !CONFIG_ESP_TASK_WDT_INIT
}
#endif // CONFIG_MBEDTLS_HARDWARE_MPI
+325 -196
View File
@@ -16,256 +16,385 @@
#include "spi_flash_mmap.h"
#include "soc/soc_caps.h"
#define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
#include "unity.h"
#include "test_utils.h"
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#if SOC_SHA_SUPPORT_SHA512
#include "mbedtls/sha512.h"
#endif
#include "sha/sha_parallel_engine.h"
/* Note: Most of the SHA functions are called as part of mbedTLS, so
are tested as part of mbedTLS tests. Only esp_sha() is different.
*/
#include "psa/crypto.h"
#include "mbedtls/md.h"
#define TAG "sha_test"
#if SOC_SHA_SUPPORTED && CONFIG_MBEDTLS_HARDWARE_SHA
TEST_CASE("Test esp_sha()", "[hw_crypto]")
// New test for PSA SHA-512 implementation
TEST_CASE("Test PSA SHA-512 with known test vectors", "[hw_crypto][psa]")
{
const size_t BUFFER_SZ = 32 * 1024 + 6; // NB: not an exact multiple of SHA block size
ESP_LOGI(TAG, "Testing PSA SHA-512 implementation with known test vectors");
int64_t elapsed;
uint32_t us_sha1;
uint8_t sha1_result[20] = { 0 };
// Test Vector 1: SHA-512("abc")
// Expected: ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f
const unsigned char test1_input[] = "abc";
const size_t test1_input_len = 3;
const unsigned char test1_expected[64] = {
0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49, 0xae, 0x20, 0x41, 0x31,
0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2, 0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a,
0x21, 0x92, 0x99, 0x2a, 0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f, 0xa5, 0x4c, 0xa4, 0x9f
};
#if SOC_SHA_SUPPORT_SHA512
uint32_t us_sha512;
uint8_t sha512_result[64] = { 0 };
#endif
// Test Vector 2: SHA-512("")
// Expected: cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e
const unsigned char test2_input[] = "";
const size_t test2_input_len = 0;
const unsigned char test2_expected[64] = {
0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07,
0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce,
0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f,
0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e
};
void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buffer);
memset(buffer, 0xEE, BUFFER_SZ);
unsigned char psa_output[64];
unsigned char mbedtls_output[64];
size_t psa_output_len;
psa_status_t psa_status;
int mbedtls_ret;
const uint8_t sha1_expected[20] = { 0xc7, 0xbb, 0xd3, 0x74, 0xf2, 0xf6, 0x20, 0x86,
0x61, 0xf4, 0x50, 0xd5, 0xf5, 0x18, 0x44, 0xcc,
0x7a, 0xb7, 0xa5, 0x4a };
#if SOC_SHA_SUPPORT_SHA512
const uint8_t sha512_expected[64] = { 0xc7, 0x7f, 0xda, 0x8c, 0xb3, 0x58, 0x14, 0x8a,
0x52, 0x3b, 0x46, 0x04, 0xc0, 0x85, 0xc5, 0xf0,
0x46, 0x64, 0x14, 0xd5, 0x96, 0x7a, 0xa2, 0x80,
0x20, 0x9c, 0x04, 0x27, 0x7d, 0x3b, 0xf9, 0x1f,
0xb2, 0xa3, 0x45, 0x3c, 0xa1, 0x6a, 0x8d, 0xdd,
0x35, 0x5e, 0x35, 0x57, 0x76, 0x22, 0x74, 0xd8,
0x1e, 0x07, 0xc6, 0xa2, 0x9e, 0x3b, 0x65, 0x75,
0x80, 0x7d, 0xe6, 0x6e, 0x47, 0x61, 0x2c, 0x94 };
#endif
ESP_LOGI(TAG, "=== Test 1: SHA-512(\"abc\") ===");
ccomp_timer_start();
esp_sha(SHA1, buffer, BUFFER_SZ, sha1_result);
elapsed = ccomp_timer_stop();
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, sha1_result, sizeof(sha1_expected));
us_sha1 = elapsed;
ESP_LOGI(TAG, "esp_sha() 32KB SHA1 in %" PRIu32 " us", us_sha1);
// Test with PSA
ESP_LOGI(TAG, "Testing PSA psa_hash_compute()...");
psa_status = psa_hash_compute(PSA_ALG_SHA_512, test1_input, test1_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
ESP_LOGI(TAG, "PSA status: 0x%x, output_len: %zu", (unsigned int)psa_status, psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(64, psa_output_len);
#if SOC_SHA_SUPPORT_SHA512
ccomp_timer_start();
esp_sha(SHA2_512, buffer, BUFFER_SZ, sha512_result);
elapsed = ccomp_timer_stop();
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha512_expected, sha512_result, sizeof(sha512_expected));
ESP_LOGI(TAG, "PSA result: %02x %02x %02x %02x %02x %02x %02x %02x...",
psa_output[0], psa_output[1], psa_output[2], psa_output[3],
psa_output[4], psa_output[5], psa_output[6], psa_output[7]);
ESP_LOGI(TAG, "Expected result: %02x %02x %02x %02x %02x %02x %02x %02x...",
test1_expected[0], test1_expected[1], test1_expected[2], test1_expected[3],
test1_expected[4], test1_expected[5], test1_expected[6], test1_expected[7]);
us_sha512 = elapsed;
ESP_LOGI(TAG, "esp_sha() 32KB SHA512 in %" PRIu32 " us", us_sha512);
#endif
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, psa_output, 64);
ESP_LOGI(TAG, "✓ PSA SHA-512(\"abc\") PASSED");
/* NOTE: The Mbed TLS ROM implementation needs to updated to support SHA224 operations */
#if !CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL
#if SOC_SHA_SUPPORT_SHA224
uint8_t sha224_result[28] = { 0 };
const uint8_t sha224_expected[28] = { 0xc0, 0x2a, 0x54, 0x2f, 0x70, 0x93, 0xaa, 0x3e,
0xb6, 0xec, 0xe6, 0xb2, 0xb8, 0xe6, 0x57, 0x27,
0xf9, 0x34, 0x9e, 0xb7, 0xbc, 0x96, 0x0d, 0xf5,
0xd9, 0x87, 0xa8, 0x17 };
esp_sha(SHA2_224, buffer, BUFFER_SZ, sha224_result);
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha224_expected, sha224_result, sizeof(sha224_expected));
#endif
#endif
// Test with mbedtls_md
ESP_LOGI(TAG, "Testing mbedtls_md()...");
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
TEST_ASSERT_NOT_NULL(md_info);
#if SOC_SHA_SUPPORT_SHA384
uint8_t sha384_result[48] = { 0 };
const uint8_t sha384_expected[48] = { 0x72, 0x13, 0xc8, 0x09, 0x7b, 0xbc, 0x9e, 0x65,
0x02, 0xf8, 0x1d, 0xd2, 0x02, 0xd3, 0xd1, 0x80,
0x48, 0xb9, 0xfb, 0x10, 0x2f, 0x1b, 0xd1, 0x40,
0x4c, 0xc6, 0x3c, 0xfe, 0xcf, 0xa0, 0x83, 0x1b,
0x6e, 0xfb, 0x97, 0x17, 0x65, 0x08, 0x28, 0x04,
0x2f, 0x06, 0x2c, 0x97, 0x4e, 0xf8, 0x26, 0x86 };
esp_sha(SHA2_384, buffer, BUFFER_SZ, sha384_result);
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha384_expected, sha384_result, sizeof(sha384_expected));
#endif
mbedtls_ret = mbedtls_md(md_info, test1_input, test1_input_len, mbedtls_output);
ESP_LOGI(TAG, "mbedtls_md return: %d", mbedtls_ret);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
free(buffer);
ESP_LOGI(TAG, "mbedtls result: %02x %02x %02x %02x %02x %02x %02x %02x...",
mbedtls_output[0], mbedtls_output[1], mbedtls_output[2], mbedtls_output[3],
mbedtls_output[4], mbedtls_output[5], mbedtls_output[6], mbedtls_output[7]);
TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA1_32KB, "%" PRId32 " us", us_sha1);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, mbedtls_output, 64);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-512(\"abc\") PASSED");
#if SOC_SHA_SUPPORT_SHA512
TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA512_32KB, "%" PRId32 " us", us_sha512);
#endif
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 64);
ESP_LOGI(TAG, "✓ PSA and mbedtls_md results match");
ESP_LOGI(TAG, "=== Test 2: SHA-512(\"\") (empty string) ===");
// Test with PSA
psa_status = psa_hash_compute(PSA_ALG_SHA_512, test2_input, test2_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(64, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, psa_output, 64);
ESP_LOGI(TAG, "✓ PSA SHA-512(\"\") PASSED");
// Test with mbedtls_md
mbedtls_ret = mbedtls_md(md_info, test2_input, test2_input_len, mbedtls_output);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, mbedtls_output, 64);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-512(\"\") PASSED");
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 64);
ESP_LOGI(TAG, "✓ All PSA SHA-512 tests PASSED!");
}
/* NOTE: This test attempts to mmap 1MB of flash starting from address 0x00, which overlaps
* the entire TEE protected region, causing the mmap operation to fail and triggering an
* exception in the subsequent steps.
*/
#if !CONFIG_SECURE_ENABLE_TEE
TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
TEST_CASE("Test PSA SHA-256 with known test vectors", "[hw_crypto][psa]")
{
int r = -1;
const void* ptr;
spi_flash_mmap_handle_t handle;
#if CONFIG_MBEDTLS_SHA1_C
uint8_t sha1_espsha[20] = { 0 };
uint8_t sha1_mbedtls[20] = { 0 };
#endif
uint8_t sha256_espsha[32] = { 0 };
uint8_t sha256_mbedtls[32] = { 0 };
ESP_LOGI(TAG, "Testing PSA SHA-256 implementation with known test vectors");
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
uint8_t sha512_espsha[64] = { 0 };
uint8_t sha512_mbedtls[64] = { 0 };
#endif
// Test Vector 1: SHA-256("abc")
// Expected: ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad
const unsigned char test1_input[] = "abc";
const size_t test1_input_len = 3;
const unsigned char test1_expected[32] = {
0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea,
0x41, 0x41, 0x40, 0xde, 0x5d, 0xae, 0x22, 0x23,
0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad
};
const size_t LEN = 1024 * 1024;
// Test Vector 2: SHA-256("")
// Expected: e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
const unsigned char test2_input[] = "";
const size_t test2_input_len = 0;
const unsigned char test2_expected[32] = {
0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14,
0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24,
0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c,
0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55
};
/* mmap() 1MB of flash, we don't care what it is really */
esp_err_t err = spi_flash_mmap(0x0, LEN, SPI_FLASH_MMAP_DATA, &ptr, &handle);
// Test Vector 3: SHA-256("hello world")
// Expected: b94d27b9934d3e08a52e52d7da7dabfac484efe37a5380ee9088f7ace2efcde9
const unsigned char test3_input[] = "hello world";
const unsigned char test3_expected[32] = {
0xb9, 0x4d, 0x27, 0xb9, 0x93, 0x4d, 0x3e, 0x08,
0xa5, 0x2e, 0x52, 0xd7, 0xda, 0x7d, 0xab, 0xfa,
0xc4, 0x84, 0xef, 0xe3, 0x7a, 0x53, 0x80, 0xee,
0x90, 0x88, 0xf7, 0xac, 0xe2, 0xef, 0xcd, 0xe9
};
TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
TEST_ASSERT_NOT_NULL(ptr);
unsigned char psa_output[32];
unsigned char mbedtls_output[32];
size_t psa_output_len;
psa_status_t psa_status;
int mbedtls_ret;
/* Compare esp_sha() result to the mbedTLS result, should always be the same */
#if CONFIG_MBEDTLS_SHA1_C
esp_sha(SHA1, ptr, LEN, sha1_espsha);
r = mbedtls_sha1(ptr, LEN, sha1_mbedtls);
TEST_ASSERT_EQUAL(0, r);
#endif
ESP_LOGI(TAG, "=== Test 1: SHA-256(\"abc\") ===");
esp_sha(SHA2_256, ptr, LEN, sha256_espsha);
r = mbedtls_sha256(ptr, LEN, sha256_mbedtls, 0);
TEST_ASSERT_EQUAL(0, r);
// Test with PSA
ESP_LOGI(TAG, "Testing PSA psa_hash_compute()...");
psa_status = psa_hash_compute(PSA_ALG_SHA_256, test1_input, test1_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
ESP_LOGI(TAG, "PSA status: 0x%x, output_len: %zu", (unsigned int)psa_status, psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(32, psa_output_len);
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
esp_sha(SHA2_512, ptr, LEN, sha512_espsha);
r = mbedtls_sha512(ptr, LEN, sha512_mbedtls, 0);
TEST_ASSERT_EQUAL(0, r);
#endif
ESP_LOGI(TAG, "PSA result: %02x %02x %02x %02x %02x %02x %02x %02x...",
psa_output[0], psa_output[1], psa_output[2], psa_output[3],
psa_output[4], psa_output[5], psa_output[6], psa_output[7]);
ESP_LOGI(TAG, "Expected result: %02x %02x %02x %02x %02x %02x %02x %02x...",
test1_expected[0], test1_expected[1], test1_expected[2], test1_expected[3],
test1_expected[4], test1_expected[5], test1_expected[6], test1_expected[7]);
/* munmap() 1MB of flash when the usge of memory-mapped ptr is over */
spi_flash_munmap(handle);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, psa_output, 32);
ESP_LOGI(TAG, "✓ PSA SHA-256(\"abc\") PASSED");
#if CONFIG_MBEDTLS_SHA1_C
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_espsha, sha1_mbedtls, sizeof(sha1_espsha), "SHA1 results should match");
#endif
// Test with mbedtls_md
ESP_LOGI(TAG, "Testing mbedtls_md()...");
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
TEST_ASSERT_NOT_NULL(md_info);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_espsha, sha256_mbedtls, sizeof(sha256_espsha), "SHA256 results should match");
mbedtls_ret = mbedtls_md(md_info, test1_input, test1_input_len, mbedtls_output);
ESP_LOGI(TAG, "mbedtls_md return: %d", mbedtls_ret);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
#if SOC_SHA_SUPPORT_SHA512 && CONFIG_MBEDTLS_SHA512_C
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_espsha, sha512_mbedtls, sizeof(sha512_espsha), "SHA512 results should match");
#endif
ESP_LOGI(TAG, "mbedtls result: %02x %02x %02x %02x %02x %02x %02x %02x...",
mbedtls_output[0], mbedtls_output[1], mbedtls_output[2], mbedtls_output[3],
mbedtls_output[4], mbedtls_output[5], mbedtls_output[6], mbedtls_output[7]);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, mbedtls_output, 32);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-256(\"abc\") PASSED");
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 32);
ESP_LOGI(TAG, "✓ PSA and mbedtls_md results match");
ESP_LOGI(TAG, "=== Test 2: SHA-256(\"\") (empty string) ===");
// Test with PSA
psa_status = psa_hash_compute(PSA_ALG_SHA_256, test2_input, test2_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(32, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, psa_output, 32);
ESP_LOGI(TAG, "✓ PSA SHA-256(\"\") PASSED");
// Test with mbedtls_md
mbedtls_ret = mbedtls_md(md_info, test2_input, test2_input_len, mbedtls_output);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, mbedtls_output, 32);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-256(\"\") PASSED");
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 32);
ESP_LOGI(TAG, "✓ All PSA SHA-256 tests PASSED!");
// Test Vector 3: SHA-256("hello world")
// This will do with PSA only but _update will be called multiple time
ESP_LOGI(TAG, "=== Test 3: SHA-256(\"hello world\") ===");
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status = psa_hash_setup(&operation, PSA_ALG_SHA_256);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&operation, (const uint8_t *)test3_input, 5); // "hello"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&operation, (const uint8_t *)(test3_input + 5), 6); // " world"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_finish(&operation, psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(32, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test3_expected, psa_output, 32);
ESP_LOGI(TAG, "✓ PSA SHA-256(\"hello world\") PASSED");
}
#endif
#if CONFIG_MBEDTLS_HARDWARE_SHA
TEST_CASE("Test mbedtls_internal_sha_process()", "[hw_crypto]")
TEST_CASE("Test PSA SHA-384 with known test vectors", "[hw_crypto][psa]")
{
const size_t BUFFER_SZ = 128;
int ret;
unsigned char output[64] = { 0 };
void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buffer);
memset(buffer, 0xEE, BUFFER_SZ);
ESP_LOGI(TAG, "Testing PSA SHA-384 implementation with known test vectors");
mbedtls_sha1_context sha1_ctx;
// Test Vector 1: SHA-384("abc")
// Expected: cb00753f45a35e8bb5a03d699ac65007272c32ab0eded1631a8b605a43ff5bed8086072ba1e7cc2358baeca134c825a7
const unsigned char test1_input[] = "abc";
const size_t test1_input_len = 3;
const unsigned char test1_expected[48] = {
0xcb, 0x00, 0x75, 0x3f, 0x45, 0xa3, 0x5e, 0x8b,
0xb5, 0xa0, 0x3d, 0x69, 0x9a, 0xc6, 0x50, 0x07,
0x27, 0x2c, 0x32, 0xab, 0x0e, 0xde, 0xd1, 0x63,
0x1a, 0x8b, 0x60, 0x5a, 0x43, 0xff, 0x5b, 0xed,
0x80, 0x86, 0x07, 0x2b, 0xa1, 0xe7, 0xcc, 0x23,
0x58, 0xba, 0xec, 0xa1, 0x34, 0xc8, 0x25, 0xa7
};
const uint8_t sha1_expected[20] = { 0x41, 0x63, 0x12, 0x5b, 0x9c, 0x68, 0x85, 0xc8,
0x01, 0x40, 0xf4, 0x03, 0x5d, 0x0d, 0x84, 0x0e,
0xa4, 0xae, 0x4d, 0xe9 };
// Test Vector 2: SHA-384("")
// Expected: 38b060a751ac96384cd9327eb1b1e36a21fdb71114be07434c0cc7bf63f6e1da274edebfe76f65fbd51ad2f14898b95b
const unsigned char test2_input[] = "";
const size_t test2_input_len = 0;
const unsigned char test2_expected[48] = {
0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38,
0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a,
0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43,
0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda,
0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb,
0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b
};
mbedtls_sha1_init(&sha1_ctx);
mbedtls_sha1_starts(&sha1_ctx);
// Test Vector 3: SHA-384("hello world")
// Expected: fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3e417cb71ce646efd0819dd8c088de1bd
const unsigned char test3_input[] = "hello world";
const unsigned char test3_expected[48] = {
0xfd, 0xbd, 0x8e, 0x75, 0xa6, 0x7f, 0x29, 0xf7,
0x01, 0xa4, 0xe0, 0x40, 0x38, 0x5e, 0x2e, 0x23,
0x98, 0x63, 0x03, 0xea, 0x10, 0x23, 0x92, 0x11,
0xaf, 0x90, 0x7f, 0xcb, 0xb8, 0x35, 0x78, 0xb3,
0xe4, 0x17, 0xcb, 0x71, 0xce, 0x64, 0x6e, 0xfd,
0x08, 0x19, 0xdd, 0x8c, 0x08, 0x8d, 0xe1, 0xbd
};
ret = mbedtls_internal_sha1_process(&sha1_ctx, buffer);
TEST_ASSERT_EQUAL(0, ret);
unsigned char psa_output[48];
unsigned char mbedtls_output[48];
size_t psa_output_len;
psa_status_t psa_status;
int mbedtls_ret;
ret = mbedtls_internal_sha1_process(&sha1_ctx, buffer);
TEST_ASSERT_EQUAL(0, ret);
ESP_LOGI(TAG, "=== Test 1: SHA-384(\"abc\") ===");
#if SOC_SHA_ENDIANNESS_BE
for (int i = 0; i < sizeof(sha1_ctx.state)/sizeof(sha1_ctx.state[0]); i++)
{
*(uint32_t *)(output + i*4) = __builtin_bswap32(sha1_ctx.state[i]);
}
#else
memcpy(output, sha1_ctx.state, 20);
#endif
// Test with PSA
ESP_LOGI(TAG, "Testing PSA psa_hash_compute()...");
psa_status = psa_hash_compute(PSA_ALG_SHA_384, test1_input, test1_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
ESP_LOGI(TAG, "PSA status: 0x%x, output_len: %zu", (unsigned int)psa_status, psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(48, psa_output_len);
// Check if the intermediate states are correct
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, output, sizeof(sha1_expected));
ESP_LOGI(TAG, "PSA result: %02x %02x %02x %02x %02x %02x %02x %02x...",
psa_output[0], psa_output[1], psa_output[2], psa_output[3],
psa_output[4], psa_output[5], psa_output[6], psa_output[7]);
ESP_LOGI(TAG, "Expected result: %02x %02x %02x %02x %02x %02x %02x %02x...",
test1_expected[0], test1_expected[1], test1_expected[2], test1_expected[3],
test1_expected[4], test1_expected[5], test1_expected[6], test1_expected[7]);
ret = mbedtls_sha1_finish(&sha1_ctx, output);
TEST_ASSERT_EQUAL(0, ret);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, psa_output, 48);
ESP_LOGI(TAG, "✓ PSA SHA-384(\"abc\") PASSED");
mbedtls_sha1_free(&sha1_ctx);
// Test with mbedtls_md
ESP_LOGI(TAG, "Testing mbedtls_md()...");
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
TEST_ASSERT_NOT_NULL(md_info);
#if SOC_SHA_SUPPORT_SHA512
mbedtls_sha512_context sha512_ctx;
mbedtls_ret = mbedtls_md(md_info, test1_input, test1_input_len, mbedtls_output);
ESP_LOGI(TAG, "mbedtls_md return: %d", mbedtls_ret);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
const uint8_t sha512_expected[64] = { 0x3c, 0x77, 0x5f, 0xb0, 0x3b, 0x25, 0x8d, 0x3b,
0xa9, 0x28, 0xa2, 0x29, 0xf2, 0x14, 0x7d, 0xb3,
0x64, 0x1e, 0x76, 0xd5, 0x0b, 0xbc, 0xdf, 0xb4,
0x75, 0x1d, 0xe7, 0x7f, 0x62, 0x83, 0xdd, 0x78,
0x6b, 0x0e, 0xa4, 0xd2, 0xbe, 0x51, 0x56, 0xd4,
0xfe, 0x3b, 0xa3, 0x3a, 0xd7, 0xf6, 0xd3, 0xb3,
0xe7, 0x9d, 0xb5, 0xe6, 0x76, 0x35, 0x2a, 0xae,
0x07, 0x0a, 0x3a, 0x03, 0x44, 0xf0, 0xb8, 0xfe };
ESP_LOGI(TAG, "mbedtls result: %02x %02x %02x %02x %02x %02x %02x %02x...",
mbedtls_output[0], mbedtls_output[1], mbedtls_output[2], mbedtls_output[3],
mbedtls_output[4], mbedtls_output[5], mbedtls_output[6], mbedtls_output[7]);
mbedtls_sha512_init(&sha512_ctx);
mbedtls_sha512_starts(&sha512_ctx, 0);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test1_expected, mbedtls_output, 48);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-384(\"abc\") PASSED");
ret = mbedtls_internal_sha512_process(&sha512_ctx, buffer);
TEST_ASSERT_EQUAL(0, ret);
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 48);
ESP_LOGI(TAG, "✓ PSA and mbedtls_md results match");
ret = mbedtls_internal_sha512_process(&sha512_ctx, buffer);
TEST_ASSERT_EQUAL(0, ret);
ESP_LOGI(TAG, "=== Test 2: SHA-384(\"\") (empty string) ===");
#if SOC_SHA_ENDIANNESS_BE
for (int i = 0; i < sizeof(sha512_ctx.state)/sizeof(sha512_ctx.state[0]); i++)
{
*(uint64_t *)(output + i*8) = __builtin_bswap64(sha512_ctx.state[i]);
}
#else
memcpy(output, sha512_ctx.state, 64);
#endif
// Test with PSA
psa_status = psa_hash_compute(PSA_ALG_SHA_384, test2_input, test2_input_len,
psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(48, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, psa_output, 48);
ESP_LOGI(TAG, "✓ PSA SHA-384(\"\") PASSED");
// Check if the intermediate states are correct
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha512_expected, output, sizeof(sha512_expected));
// Test with mbedtls_md
mbedtls_ret = mbedtls_md(md_info, test2_input, test2_input_len, mbedtls_output);
TEST_ASSERT_EQUAL(0, mbedtls_ret);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test2_expected, mbedtls_output, 48);
ESP_LOGI(TAG, "✓ mbedtls_md SHA-384(\"\") PASSED");
ret = mbedtls_sha512_finish(&sha512_ctx, output);
TEST_ASSERT_EQUAL(0, ret);
// Verify both methods produce the same result
TEST_ASSERT_EQUAL_MEMORY(psa_output, mbedtls_output, 48);
ESP_LOGI(TAG, "✓ All PSA SHA-384 tests PASSED!");
mbedtls_sha512_free(&sha512_ctx);
#endif
free(buffer);
// Test Vector 3: SHA-384("hello world")
// This will do with PSA only but _update will be called multiple time
ESP_LOGI(TAG, "=== Test 3: SHA-384(\"hello world\") ===");
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status = psa_hash_setup(&operation, PSA_ALG_SHA_384);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&operation, (const uint8_t *)test3_input, 5); // "hello"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&operation, (const uint8_t *)(test3_input + 5), 6); // " world"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_finish(&operation, psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(48, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test3_expected, psa_output, 48);
ESP_LOGI(TAG, "✓ PSA SHA-384(\"hello world\") PASSED");
}
#endif
#endif // SOC_SHA_SUPPORTED && CONFIG_MBEDTLS_HARDWARE_SHA
TEST_CASE("Test PSA SHA-384 with clone", "[hw_crypto][psa]")
{
// Test Vector 1: SHA-384("hello world")
// Expected: fdbd8e75a67f29f701a4e040385e2e23986303ea10239211af907fcbb83578b3e417cb71ce646efd0819dd8c088de1bd
const unsigned char test3_input[] = "hello world";
const unsigned char test3_expected[48] = {
0xfd, 0xbd, 0x8e, 0x75, 0xa6, 0x7f, 0x29, 0xf7,
0x01, 0xa4, 0xe0, 0x40, 0x38, 0x5e, 0x2e, 0x23,
0x98, 0x63, 0x03, 0xea, 0x10, 0x23, 0x92, 0x11,
0xaf, 0x90, 0x7f, 0xcb, 0xb8, 0x35, 0x78, 0xb3,
0xe4, 0x17, 0xcb, 0x71, 0xce, 0x64, 0x6e, 0xfd,
0x08, 0x19, 0xdd, 0x8c, 0x08, 0x8d, 0xe1, 0xbd
};
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t psa_status = psa_hash_setup(&operation, PSA_ALG_SHA_384);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&operation, (const uint8_t *)test3_input, 5); // "hello"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_hash_operation_t clone = PSA_HASH_OPERATION_INIT;
psa_status = psa_hash_clone(&operation, &clone);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
psa_status = psa_hash_update(&clone, (const uint8_t *)(test3_input + 5), 6); // " world"
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
unsigned char psa_output[48];
size_t psa_output_len;
psa_status = psa_hash_finish(&clone, psa_output, sizeof(psa_output), &psa_output_len);
TEST_ASSERT_EQUAL(PSA_SUCCESS, psa_status);
TEST_ASSERT_EQUAL(48, psa_output_len);
TEST_ASSERT_EQUAL_HEX8_ARRAY(test3_expected, psa_output, 48);
ESP_LOGI(TAG, "✓ PSA SHA-384(\"hello world\") with original PASSED");
}
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -10,39 +10,45 @@
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include "mbedtls/sha256.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_heap_caps.h"
#include "test_utils.h"
#include "ccomp_timer.h"
#include "test_mbedtls_utils.h"
#include "psa/crypto.h"
#include "psa/crypto.h"
#if CONFIG_MBEDTLS_HARDWARE_SHA
TEST_CASE("mbedtls SHA performance", "[mbedtls]")
TEST_CASE("psa SHA256 performance", "[mbedtls]")
{
const unsigned CALLS = 256;
const unsigned CALL_SZ = 16 * 1024;
mbedtls_sha256_context sha256_ctx;
float elapsed_usec;
unsigned char sha256[32];
psa_hash_operation_t operation = PSA_HASH_OPERATION_INIT;
psa_status_t status = psa_hash_setup(&operation, PSA_ALG_SHA_256);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_DMA | MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
memset(buf, 0x55, CALL_SZ);
mbedtls_sha256_init(&sha256_ctx);
ccomp_timer_start();
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts(&sha256_ctx, false));
for (int c = 0; c < CALLS; c++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update(&sha256_ctx, buf, CALL_SZ));
status = psa_hash_update(&operation, buf, CALL_SZ);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish(&sha256_ctx, sha256));
size_t hash_length;
status = psa_hash_finish(&operation, sha256, sizeof(sha256), &hash_length);
TEST_ASSERT_EQUAL(PSA_SUCCESS, status);
elapsed_usec = ccomp_timer_stop();
free(buf);
mbedtls_sha256_free(&sha256_ctx);
/* Check the result. Reference value can be calculated using:
* dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\125' | sha256sum
@@ -91,17 +91,18 @@ def test_mbedtls_ecdsa_sign(dut: Dut) -> None:
dut.run_all_single_board_cases(group='efuse_key')
@pytest.mark.generic
@pytest.mark.parametrize(
'config',
[
'rom_impl',
],
indirect=True,
)
@idf_parametrize('target', ['esp32c2'], indirect=['target'])
def test_mbedtls_rom_impl_esp32c2(dut: Dut) -> None:
dut.run_all_single_board_cases()
# TODO: IDF-15012
# @pytest.mark.generic
# @pytest.mark.parametrize(
# 'config',
# [
# 'rom_impl',
# ],
# indirect=True,
# )
# @idf_parametrize('target', ['esp32c2'], indirect=['target'])
# def test_mbedtls_rom_impl_esp32c2(dut: Dut) -> None:
# dut.run_all_single_board_cases()
@pytest.mark.generic
@@ -1,2 +1,3 @@
CONFIG_IDF_TARGET="esp32c2"
CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL=y
# TODO: IDF-15012
# CONFIG_MBEDTLS_USE_CRYPTO_ROM_IMPL=y