KMU import ECDSA public key

Hi Nordic Team,

in our project we want to write/read cryptographic keys to/from the KMU.

One of the algorithms we are going to use is ECDSA.

My naive approach was to just modify the existing nrf/samples/crypto/ecdsa code.

 

Another ticket in the developer zone (see https://devzone.nordicsemi.com/f/nordic-q-a/118434/kmu-psa-persistent-key-generation) reveals, that there's a bug in SDK v2.9.0.

Therefore, I switched ncs to the main branch (commit a95e127c906afef92e36e79120d2ec127c250b87).

My prj.conf equals:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#
# Copyright (c) 2024 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#
# The Zephyr CMSIS emulation assumes that ticks are ms, currently
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_REBOOT=y
# Enable logging
CONFIG_CONSOLE=y
CONFIG_LOG=y
# Enable nordic security backend and PSA APIs
CONFIG_NRF_SECURITY=y
CONFIG_MBEDTLS_PSA_CRYPTO_C=y
# Enable persistent storage APIs
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

 My modified generate_ecdsa_keypair() succeeds to generate a new keypair in the KMU resp. read an existing keypair from the KMU:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int generate_ecdsa_keypair(void)
{
psa_status_t status;
size_t olen;
LOG_INF("Generating/read random persistent ECDSA key pair...");
/* Configure the key attributes */
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_SIGN_MESSAGE);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
psa_set_key_lifetime(
&key_attributes,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_DEFAULT,
PSA_KEY_LOCATION_CRACEN_KMU
)
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

But my modified import_ecdsa_pub_key() function fails:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
int import_ecdsa_pub_key(void)
{
/* Configure the key attributes */
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_status_t status;
/* Configure the key attributes */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY_HASH | PSA_KEY_USAGE_VERIFY_MESSAGE);
psa_set_key_lifetime(
&key_attributes,
PSA_KEY_LIFETIME_FROM_PERSISTENCE_AND_LOCATION(
PSA_KEY_PERSISTENCE_DEFAULT,
PSA_KEY_LOCATION_CRACEN_KMU
)
);
psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_ANY_HASH));
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
psa_set_key_bits(&key_attributes, 256);
psa_set_key_id(
&key_attributes,
PSA_KEY_HANDLE_FROM_CRACEN_KMU_SLOT(
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

psa_import_key() returns PSA_ERROR_INVALID_ARGUMENT.

The error code comes from nrf/subsys/nrf_security/src/drivers/cracen/cracenpsa/src/kmu.c:837ff

Fullscreen
1
2
3
4
5
6
case CRACEN_KMU_KEY_USAGE_SCHEME_RAW:
push_address = (uint8_t *)kmu_push_area;
if (key_buffer_size != 16 && key_buffer_size != 24 && key_buffer_size != 32) {
return PSA_ERROR_INVALID_ARGUMENT;
}
break;
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

The buffer size for the ECDSA public key (i.e. m_ecdsa_pub_key) is 65 bytes.

Am I doing something wrong?

Best regards,

Christian