psa_generate_key failed with error (-134)

When running the ECDSA Example from Nordic, the keys are generated successfully. But when I add the code for generating CSR it fails with the error code -134 which bby my knowledge is PSA_ERROR_NOT_SUPPORTED. Requesting help with this issue. 

using NRF Connect v2.6.1 and board nrf5340 in secure environment.

# The Zephyr CMSIS emulation assumes that ticks are ms, currently
CONFIG_SYS_CLOCK_TICKS_PER_SEC=1000

CONFIG_MAIN_STACK_SIZE=8192
CONFIG_HEAP_MEM_POOL_SIZE=8192

# 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
CONFIG_MBEDTLS_PSA_CRYPTO_STORAGE_C=y
#CONFIG_PSA_NATIVE_ITS=y

CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=8192

CONFIG_PSA_WANT_ALG_ECDSA=y
CONFIG_PSA_WANT_KEY_TYPE_ECC_KEY_PAIR=y
CONFIG_PSA_WANT_ECC_SECP_R1_256=y
CONFIG_PSA_WANT_ALG_SHA_256=y

# For key generation
CONFIG_PSA_WANT_GENERATE_RANDOM=y

CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_USE_PSA_CRYPTO=y
CONFIG_MBEDTLS_PK_C=y
CONFIG_MBEDTLS_TLS_LIBRARY=y
CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y

CONFIG_MBEDTLS_X509_USE_C=y
CONFIG_MBEDTLS_X509_CSR_WRITE_C=y
CONFIG_MBEDTLS_X509_LIBRARY=y

CONFIG_MBEDTLS_PK_WRITE_C=y
CONFIG_MBEDTLS_X509_CRT_PARSE_C=y
CONFIG_MBEDTLS_X509_CREATE_C=y
CONFIG_MBEDTLS_X509_CSR_PARSE_C=y

CONFIG_MBEDTLS_PK_PARSE_C=y
CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y

CONFIG_MBEDTLS_KEY_EXCHANGE_ALL_ENABLED=y
CONFIG_PSA_CRYPTO_DRIVER_OBERON=n
CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y

CONFIG_MBEDTLS_LIBRARY_NRF_SECURITY=y
CONFIG_MBEDTLS_SHA256_C=y
CONFIG_MBEDTLS_ECP_C=y
CONFIG_MBEDTLS_ECDSA_C=y
CONFIG_MBEDTLS_ECDH_C=y

CONFIG_MBEDTLS_CTR_DRBG_C=y
CONFIG_MBEDTLS_MD_C=y
CONFIG_PSA_WANT_ALG_ECDSA_ANY=y

And my code is :

/*
 * Copyright (c) 2021 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
 */

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/logging/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <psa/crypto.h>
#include <psa/crypto_extra.h>

#ifdef CONFIG_BUILD_WITH_TFM
#include <tfm_ns_interface.h>
#endif

#include <mbedtls/pk.h>
#include <mbedtls/x509.h>
#include <mbedtls/x509_csr.h>


#define APP_SUCCESS		(0)
#define APP_ERROR		(-1)
#define APP_SUCCESS_MESSAGE "Example finished successfully!"
#define APP_ERROR_MESSAGE "Example exited with error!"
#define SEC_LIB_CSR_SUBJECT_NAME "C=TIH Foundation for IoT and IoE,O=TIH,OU=Networking,CN=TIH-IoT"
#define PRINT_HEX(p_label, p_text, len)\
	({\
		LOG_INF("---- %s (len: %u): ----", p_label, len);\
		LOG_HEXDUMP_INF(p_text, len, "Content:");\
		LOG_INF("---- %s end  ----", p_label);\
	})

LOG_MODULE_REGISTER(ecdsa, LOG_LEVEL_DBG);

/* ====================================================================== */
/*				Global variables/defines for the ECDSA example			  */

#define NRF_CRYPTO_EXAMPLE_ECDSA_TEXT_SIZE (100)

#define NRF_CRYPTO_EXAMPLE_ECDSA_PUBLIC_KEY_SIZE (65)
#define NRF_CRYPTO_EXAMPLE_ECDSA_SIGNATURE_SIZE (64)
#define NRF_CRYPTO_EXAMPLE_ECDSA_HASH_SIZE (32)

/* Below text is used as plaintext for signing/verification */
//static uint8_t m_plain_text[NRF_CRYPTO_EXAMPLE_ECDSA_TEXT_SIZE] = {
//	"Example string to demonstrate basic usage of ECDSA."
//};

static uint8_t m_pub_key[NRF_CRYPTO_EXAMPLE_ECDSA_PUBLIC_KEY_SIZE];

//static uint8_t m_signature[NRF_CRYPTO_EXAMPLE_ECDSA_SIGNATURE_SIZE];
//static uint8_t m_hash[NRF_CRYPTO_EXAMPLE_ECDSA_HASH_SIZE];

static psa_key_id_t keypair_id;
static psa_key_id_t pub_key_id;
/* ====================================================================== */

int crypto_init(void)
{
	psa_status_t status;

	/* Initialize PSA Crypto */
	status = psa_crypto_init();
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_crypto_init failed! (Error: %d)", status);
		return APP_ERROR;
	}

	return APP_SUCCESS;
}

int crypto_finish(void)
{
	psa_status_t status;

	/* Destroy the key handle */
	status = psa_destroy_key(keypair_id);
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_destroy_key failed! (Error: %d)", status);
		return APP_ERROR;
	}

	status = psa_destroy_key(pub_key_id);
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_destroy_key failed! (Error: %d)", status);
		return APP_ERROR;
	}

	return APP_SUCCESS;
}

int generate_ecdsa_keypair(void)
{
	psa_status_t status;
	size_t olen;

	LOG_INF("Generating random ECDSA keypair...");

	/* Configure the key attributes */
	psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;

	/* Configure the key attributes */
	psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_SIGN_HASH);
	psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
	psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
	psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1));
	psa_set_key_bits(&key_attributes, 256);

	/* Generate a random keypair. The keypair is not exposed to the application,
	 * we can use it to sign hashes.
	 */
	#define SAMPLE_PERS_KEY_ID PSA_KEY_ID_USER_MIN
	psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
	psa_set_key_id(&key_attributes, SAMPLE_PERS_KEY_ID);
	psa_destroy_key(SAMPLE_PERS_KEY_ID);

	status = psa_generate_key(&key_attributes, &keypair_id);
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_generate_key failed! (Error: %d)", status);
		return APP_ERROR;
	}

	/* Export the public key */
	status = psa_export_public_key(keypair_id, m_pub_key, sizeof(m_pub_key), &olen);
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_export_public_key failed! (Error: %d)", status);
		return APP_ERROR;
	}

	/* Reset key attributes and free any allocated resources. */
	psa_reset_key_attributes(&key_attributes);

	return APP_SUCCESS;
}

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_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_VOLATILE);
	psa_set_key_algorithm(&key_attributes, PSA_ALG_ECDSA(PSA_ALG_SHA_256));
	psa_set_key_type(&key_attributes, PSA_KEY_TYPE_ECC_PUBLIC_KEY(PSA_ECC_FAMILY_SECP_R1));
	psa_set_key_bits(&key_attributes, 256);

	status = psa_import_key(&key_attributes, m_pub_key, sizeof(m_pub_key), &pub_key_id);
	if (status != PSA_SUCCESS) {
		LOG_INF("psa_import_key failed! (Error: %d)", status);
		return APP_ERROR;
	}

	/* Reset key attributes and free any allocated resources. */
	psa_reset_key_attributes(&key_attributes);

	return APP_SUCCESS;
}

// int sign_message(void)
// {
// 	uint32_t output_len;
// 	psa_status_t status;

// 	LOG_INF("Signing a message using ECDSA...");

// 	/* Compute the SHA256 hash*/
// 	status = psa_hash_compute(PSA_ALG_SHA_256,
// 				  m_plain_text,
// 				  sizeof(m_plain_text),
// 				  m_hash,
// 				  sizeof(m_hash),
// 				  &output_len);
// 	if (status != PSA_SUCCESS) {
// 		LOG_INF("psa_hash_compute failed! (Error: %d)", status);
// 		return APP_ERROR;
// 	}

// 	/* Sign the hash */
// 	status = psa_sign_hash(keypair_id,
// 			       PSA_ALG_ECDSA(PSA_ALG_SHA_256),
// 			       m_hash,
// 			       sizeof(m_hash),
// 			       m_signature,
// 			       sizeof(m_signature),
// 			       &output_len);
// 	if (status != PSA_SUCCESS) {
// 		LOG_INF("psa_sign_hash failed! (Error: %d)", status);
// 		return APP_ERROR;
// 	}

// 	LOG_INF("Message signed successfully!");
// 	PRINT_HEX("Plaintext", m_plain_text, sizeof(m_plain_text));
// 	PRINT_HEX("SHA256 hash", m_hash, sizeof(m_hash));
// 	PRINT_HEX("Signature", m_signature, sizeof(m_signature));

// 	return APP_SUCCESS;
// }

// int verify_message(void)
// {
// 	psa_status_t status;

// 	LOG_INF("Verifying ECDSA signature...");

// 	/* Verify the signature of the hash */
// 	status = psa_verify_hash(pub_key_id,
// 				 PSA_ALG_ECDSA(PSA_ALG_SHA_256),
// 				 m_hash,
// 				 sizeof(m_hash),
// 				 m_signature,
// 				 sizeof(m_signature));
// 	if (status != PSA_SUCCESS) {
// 		LOG_INF("psa_verify_hash failed! (Error: %d)", status);
// 		return APP_ERROR;
// 	}

// 	LOG_INF("Signature verification was successful!");

// 	return APP_SUCCESS;
// }

static int psa_rng_for_mbedtls(void *p_rng,
			       unsigned char *output, size_t output_len)
{
	(void)p_rng;

	return psa_generate_random(output, output_len);
}

int generate_csr()
{
	psa_status_t status;
	//psa_key_handle_t key_handle;
	
	unsigned char output_buf[1024];
	memset(output_buf, 0, sizeof(output_buf));

	mbedtls_pk_context pk_key_container;
	mbedtls_x509write_csr csr_ctx;
	mbedtls_pk_init(&pk_key_container);
	// pk_key_container.private_pk_ctx=m_pub_key;
	// pk_key_container.private_pk_info=pub_key_id;
	mbedtls_pk_setup_opaque(&pk_key_container, keypair_id);
	//mbedtls_pk_setup(&pk_key_container, &key_handle);

	// Prepare CSR context
	mbedtls_x509write_csr_init(&csr_ctx); LOG_INF("Write CSR initialised");
    mbedtls_x509write_csr_set_key_usage(&csr_ctx, MBEDTLS_X509_KU_DIGITAL_SIGNATURE); 		LOG_INF("Key usage of CSR is set");
    mbedtls_x509write_csr_set_subject_name(&csr_ctx, SEC_LIB_CSR_SUBJECT_NAME); 			LOG_INF("Added subject name to CSR");
    mbedtls_x509write_csr_set_md_alg(&csr_ctx, MBEDTLS_MD_SHA256); 							LOG_INF(" Hashing algorithm of CSR is set");
    mbedtls_x509write_csr_set_key(&csr_ctx, &pk_key_container);

	// Create CSR
	status = mbedtls_x509write_csr_der(&csr_ctx,output_buf,sizeof(output_buf),psa_rng_for_mbedtls, NULL);

	if(status != 0)
    {
        return APP_ERROR;
    }

	mbedtls_x509write_csr_free(&csr_ctx);
	mbedtls_pk_free(&pk_key_container);
	printk("%s",&output_buf);
	return	APP_SUCCESS;
}


int main(void)
{
	int status;

	LOG_INF("Starting ECDSA example...");

	status = crypto_init();
	if (status != APP_SUCCESS) {
		LOG_INF(APP_ERROR_MESSAGE);
		return APP_ERROR;
	}

	status = generate_ecdsa_keypair();
	if (status != APP_SUCCESS) {
		LOG_INF(APP_ERROR_MESSAGE);
		return APP_ERROR;
	}

	status = import_ecdsa_pub_key();
	if (status != APP_SUCCESS) {
		LOG_INF(APP_ERROR_MESSAGE);
		return APP_ERROR;
	}

	status = generate_csr();
	if (status != APP_SUCCESS) {
		LOG_INF(APP_ERROR_MESSAGE);
		return APP_ERROR;
	}

	// status = sign_message();
	// if (status != APP_SUCCESS) {
	// 	LOG_INF(APP_ERROR_MESSAGE);
	// 	return APP_ERROR;
	// }

	// status = verify_message();
	// if (status != APP_SUCCESS) {
	// 	LOG_INF(APP_ERROR_MESSAGE);
	// 	return APP_ERROR;
	// }

	status = crypto_finish();
	if (status != APP_SUCCESS) {
		LOG_INF(APP_ERROR_MESSAGE);
		return APP_ERROR;
	}

	LOG_INF(APP_SUCCESS_MESSAGE);

	return APP_SUCCESS;
}

Parents Reply Children
Related