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
  • I have followed same steps as mentioned in the link. The code also builds well. The problem is that the psa_generate_key function is returning an error. My problem is similar to this question link. The nrf5340 is able to generate keys with the sample code but after I add certain configurations to my config file, it still builds but the board is not able to generate keys and throws error -134

Children
  • I suggest to try to narrow it down a bit by finding which kconfig options or board target (secure or non-secure) that caused the problem to appear. Hopefully comparing working and failing \build\zephyr\.config can give some suggestions.

    Kenneth

  • After Enabling and disabling various configs, I have deduced the problem to be associated with 
    #CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y; enabling this causes the psa_generate_key() function to throw an error

    I am including the .config files in the example and in my code. I have checked the differences in diff check er online.
    My.config
    Example.config
    7002.example.config



    I have also cleaned up my prj.conf
    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
    
    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_PK_C=y
    CONFIG_MBEDTLS_PK_WRITE_C=y
    CONFIG_MBEDTLS_PK_PARSE_C=y
    CONFIG_MBEDTLS_PK_PARSE_EC_EXTENDED=y
    CONFIG_MBEDTLS_LEGACY_CRYPTO_C=y
    
    CONFIG_PSA_CRYPTO_DRIVER_OBERON=n
    CONFIG_PSA_CRYPTO_DRIVER_CC3XX=y
    #CONFIG_MBEDTLS_LIBRARY_NRF_SECURITY=y
    CONFIG_MBEDTLS_USE_PSA_CRYPTO=y
    
    CONFIG_MBEDTLS_TLS_LIBRARY=y
    CONFIG_MBEDTLS_X509_USE_C=y
    CONFIG_MBEDTLS_X509_LIBRARY=y
    CONFIG_MBEDTLS_X509_CREATE_C=y
    CONFIG_MBEDTLS_X509_CSR_PARSE_C=y
    CONFIG_MBEDTLS_X509_CSR_WRITE_C=y

  • Hi,

    CSR generation is currently not supported in SDK 2.6.1 nor in 2.7 and is not trivial to add. We are working on it though and plan to be able to support it in a future release.

  • Hi, 

    can you please elaborate more? Is there any way I can "workaround" this issue? I need to generate CSRs and use the keys generated by PSA.

Related