blob: da5420c9d009482ef09120873b821b14c5e8fa8a [file] [log] [blame]
/*
* Copyright (c) 2019,2020 Linaro Limited
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdio.h>
#include <zephyr/zephyr.h>
#include <zephyr/logging/log_ctrl.h>
#include <zephyr/logging/log.h>
#include <zephyr/data/json.h>
#include "mbedtls/pk.h"
#include "mbedtls/x509.h"
#include "mbedtls/x509_csr.h"
#include "psa_crypto.h"
#include "util_app_log.h"
#include "util_sformat.h"
/** Declare a reference to the application logging interface. */
LOG_MODULE_DECLARE(app, CONFIG_LOG_DEFAULT_LEVEL);
/* Formatting details for displaying hex dumps. */
struct sf_hex_tbl_fmt crp_fmt = {
.ascii = true,
.addr_label = true,
.addr = 0
};
struct csr_json_struct {
const char *CSR;
};
static const struct json_obj_descr csr_json_descr[] = {
JSON_OBJ_DESCR_PRIM(struct csr_json_struct, CSR, JSON_TOK_STRING)
};
/**
* @brief Extracts the public key from the specified persistent key id.
*
* @param key_id The permanent identifier for the generated key.
* @param key Pointer to the buffer where the public key data
* will be written.
* @param key_buf_size Size of key buffer in bytes.
* @param key_len Number of bytes written into key by this function.
*/
static psa_status_t crp_get_pub_key(psa_key_id_t key_id,
uint8_t *key, size_t key_buf_size,
size_t *key_len)
{
psa_status_t status;
psa_key_handle_t key_handle;
LOG_INF("Retrieving public key for key #%d", key_id);
al_dump_log();
/* Now try to re-open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Export the persistent key's public key part. */
status = al_psa_status(
psa_export_public_key(key_handle, key, key_buf_size, key_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to export public key.");
goto err;
}
/* Display the binary key data for debug purposes. */
sf_hex_tabulate_16(&crp_fmt, key, *key_len);
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
return status;
err:
al_dump_log();
return status;
}
#if CONFIG_PSA_IMPORT_KEY
/**
* @brief Stores a new persistent secp256r1 key (usage: ecdsa-with-SHA256)
* in ITS, associating it with the specified unique key identifier.
*
* This function will store a new persistent secp256r1 key in internal trusted
* storage. Cryptographic operations can then be performed using the key
* identifier (key_id) associated with this persistent key. Only the 32-byte
* private key needs to be supplied, the public key can be derived using
* the supplied private key value.
*
* @param key_id The permament identifier for the generated key.
* @param key_usage The usage policy for the key.
* @param key_data Pointer to the 32-byte private key data.
*/
static psa_status_t crp_imp_key_secp256r1(psa_key_id_t key_id,
psa_key_usage_t key_usage,
uint8_t *key_data)
{
psa_status_t status = PSA_SUCCESS;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type =
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
psa_key_handle_t key_handle;
size_t key_len = 32;
size_t data_len;
uint8_t data_out[65] = { 0 }; /* ECDSA public key = 65 bytes. */
int comp_result;
LOG_INF("Persisting SECP256R1 key as #%d", (uint32_t)key_id);
al_dump_log();
/* Setup the key's attributes before the creation request. */
psa_set_key_id(&key_attributes, key_id);
psa_set_key_usage_flags(&key_attributes, key_usage);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_algorithm(&key_attributes, alg);
psa_set_key_type(&key_attributes, key_type);
/* Import the private key, creating the persistent key on success */
status = al_psa_status(
psa_import_key(&key_attributes, key_data, key_len, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to import key.");
goto err;
}
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
/* Try to retrieve the public key. */
status = crp_get_pub_key(key_id, data_out, sizeof(data_out), &data_len);
/* Export the private key if usage includes PSA_KEY_USAGE_EXPORT. */
if (key_usage & PSA_KEY_USAGE_EXPORT) {
/* Re-open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Read the original (private) key data back. */
status = al_psa_status(
psa_export_key(key_handle, data_out,
sizeof(data_out), &data_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to export key.");
goto err;
}
/* Check key len. */
if (data_len != key_len) {
LOG_ERR("Unexpected number of bytes in exported key.");
goto err;
}
/* Verify that the exported private key matches input data. */
comp_result = memcmp(data_out, key_data, key_len);
if (comp_result != 0) {
LOG_ERR("Imported/exported private key mismatch.");
goto err;
}
/* Display the private key. */
LOG_INF("Private key data:");
al_dump_log();
sf_hex_tabulate_16(&crp_fmt, data_out, data_len);
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
}
return status;
err:
al_dump_log();
return status;
}
#else /* !CONFIG_PSA_IMPORT_KEY */
/**
* @brief Generates a new permanent, persistent prime256v1 (ecdsa-with-SHA256)
* key in ITS, associating it with the specified unique key identifier.
*
* This function will generate a new permanent prime256v1 key in internal trusted
* storage. Cryptographic operations can then be performed using the key
* identifier (key_id) associated with this persistent key.
*
* @param key_id The permanent identifier for the generated key.
* @param key_usage The usage policy for the key.
*/
static psa_status_t crp_gen_key_secp256r1(psa_key_id_t key_id,
psa_key_usage_t key_usage)
{
psa_status_t status = PSA_SUCCESS;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_key_type_t key_type =
PSA_KEY_TYPE_ECC_KEY_PAIR(PSA_ECC_FAMILY_SECP_R1);
psa_algorithm_t alg = PSA_ALG_ECDSA(PSA_ALG_SHA_256);
psa_key_handle_t key_handle;
size_t key_len = 32;
size_t data_len;
uint8_t data_out[65] = { 0 }; /* ECDSA public key = 65 bytes. */
LOG_INF("Persisting SECP256R1 key as #%d", (uint32_t)key_id);
al_dump_log();
/* Setup the key's attributes before the creation request. */
psa_set_key_id(&key_attributes, key_id);
psa_set_key_usage_flags(&key_attributes, key_usage);
psa_set_key_lifetime(&key_attributes, PSA_KEY_LIFETIME_PERSISTENT);
psa_set_key_algorithm(&key_attributes, alg);
psa_set_key_type(&key_attributes, key_type);
psa_set_key_bits(&key_attributes, 256);
/* Generate the private key, creating the persistent key on success */
status = al_psa_status(
psa_generate_key(&key_attributes, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to generate key.");
goto err;
}
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
/* Try to retrieve the public key. */
status = crp_get_pub_key(key_id, data_out, sizeof(data_out), &data_len);
/* Export the private key if usage includes PSA_KEY_USAGE_EXPORT. */
if (key_usage & PSA_KEY_USAGE_EXPORT) {
/* Re-open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Read the original (private) key data back. */
status = al_psa_status(
psa_export_key(key_handle, data_out,
sizeof(data_out), &data_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to export key.");
goto err;
}
/* Check key len. */
if (data_len != key_len) {
LOG_ERR("Unexpected number of bytes in exported key.");
goto err;
}
/* Display the private key. */
LOG_INF("Private key data:");
al_dump_log();
sf_hex_tabulate_16(&crp_fmt, data_out, data_len);
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
}
return status;
err:
al_dump_log();
return status;
}
#endif /* CONFIG_PSA_IMPORT_KEY */
/**
* @brief PSA Random number generator wrapper for Mbed TLS
*/
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);
}
/**
* @brief Generates device certificate signing request (CSR) using Mbed TLS
* X.509 and TF-M crypto service.
*/
void crp_generate_csr(void)
{
psa_status_t status;
psa_key_id_t key_slot = 1;
psa_key_handle_t key_handle;
unsigned char output_buf[1024];
unsigned char json_encoded_buf[1024];
mbedtls_pk_context pk_key_container;
mbedtls_x509write_csr req;
struct csr_json_struct csr_json = {
.CSR = output_buf
};
/* Initialize Mbed TLS structures. */
mbedtls_x509write_csr_init(&req);
mbedtls_pk_init(&pk_key_container);
memset(output_buf, 0, sizeof(output_buf));
/* Initialize crypto API. */
LOG_INF("Initialising PSA crypto");
al_dump_log();
status = al_psa_status(psa_crypto_init(), __func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Crypto init failed.");
goto err;
}
LOG_INF("PSA crypto init completed");
al_dump_log();
/* prime256v1 (ecdsa-with-SHA256) private key. */
#if CONFIG_PSA_IMPORT_KEY
#if CONFIG_PRIVATE_KEY_STATIC
/* This value is based on the private key in user.pem,
* which can be viewed viw the following command:
*
* $ openssl ec -in user.pem -text -noout
*/
uint8_t priv_key_data[32] = {
0x14, 0xbc, 0xb9, 0x53, 0xa4, 0xee, 0xed, 0x50,
0x09, 0x36, 0x92, 0x07, 0x1d, 0xdb, 0x24, 0x2c,
0xef, 0xf9, 0x57, 0x92, 0x40, 0x4f, 0x49, 0xaa,
0xd0, 0x7c, 0x5b, 0x3f, 0x26, 0xa7, 0x80, 0x48
};
#else /* !CONFIG_PRIVATE_KEY_STATIC */
/* Randomly generate the private key. */
uint8_t priv_key_data[32] = { 0 };
LOG_INF("Generate rnadom data for private key");
al_dump_log();
psa_generate_random(priv_key_data, sizeof(priv_key_data));
LOG_INF("Random data generation for private key completed");
al_dump_log();
#endif /* CONFIG_PRIVATE_KEY_STATIC */
/* Generate persistent prime256v1 (ecdsa-with-SHA256) key w/ID #1. */
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
status = al_psa_status(
crp_imp_key_secp256r1(key_slot,
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH,
priv_key_data),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to create persistent key #%d", key_slot);
goto err;
}
#else /* !CONFIG_PSA_IMPORT_KEY */
/* NOTE: The certificate signing request (CSR) can be generated using
* openssl by using following commands:
*
* Generate a new key:
*
* $ openssl ecparam -name secp256k1 -genkey -out USER.key
*
* Generate a certificate signing request, containing the user public key
* and required details to be inserted into the user certificate.
* openssl req -new -key USER.key -out USER.csr \
* -subj "/O=Linaro/CN=$(uuidgen | tr '[:upper:]' '[:lower:]')"
*
*/
/* Generate persistent prime256v1 (ecdsa-with-SHA256) key w/ID #1. */
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
status = al_psa_status(
crp_gen_key_secp256r1(key_slot,
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to create persistent key #%d", key_slot);
goto err;
}
#endif /* CONFIG_PSA_IMPORT_KEY */
status = al_psa_status(
psa_open_key(key_slot, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_slot);
goto err;
}
psa_key_attributes_t attributes = PSA_KEY_ATTRIBUTES_INIT;
psa_get_key_attributes(key_handle, &attributes);
mbedtls_x509write_csr_set_md_alg(&req, MBEDTLS_MD_SHA256);
LOG_INF("Adding subject name to CSR");
al_dump_log();
status = mbedtls_x509write_csr_set_subject_name(&req, "O=Linaro,CN=Device Certificate");
if (status != 0) {
LOG_ERR("failed! mbedtls_x509write_csr_set_subject_name returned %d", status);
goto err;
}
LOG_INF("Adding subject name to CSR completed");
al_dump_log();
LOG_INF("Adding EC key to PK container");
al_dump_log();
status = mbedtls_pk_setup_opaque(&pk_key_container, key_handle);
if (status != 0) {
LOG_ERR("failed! mbedtls_pk_setup_opaque returned -0x%04x", (unsigned int) -status);
goto err;
}
LOG_INF("Adding EC key to PK container completed");
al_dump_log();
mbedtls_x509write_csr_set_key(&req, &pk_key_container);
LOG_INF("Create device Certificate Signing Request");
al_dump_log();
status = mbedtls_x509write_csr_pem(&req, output_buf, sizeof(output_buf),
psa_rng_for_mbedtls, NULL);
if (status < 0) {
LOG_ERR("failed! mbedtls_x509write_csr_pem returned -0x%04x",
(unsigned int) -status);
goto err;
}
LOG_INF("Create device Certificate Signing Request completed");
al_dump_log();
LOG_INF("Certificate Signing Request:\n");
al_dump_log();
printf("%s\n", output_buf);
/*
* 1.3. Encoding CSR as JSON
*/
LOG_INF("Encoding CSR as json");
al_dump_log();
status = json_obj_encode_buf(csr_json_descr, ARRAY_SIZE(csr_json_descr),
&csr_json, json_encoded_buf, sizeof(json_encoded_buf));
if (status != 0) {
LOG_ERR("failed! json_obj_encode_buf returned 0x%04x", status);
goto err;
}
LOG_INF("Encoding CSR as json completed");
al_dump_log();
LOG_INF("Certificate Signing Request in JSON:\n");
al_dump_log();
printf("%s\n", json_encoded_buf);
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
err:
al_dump_log();
mbedtls_x509write_csr_free(&req);
mbedtls_pk_free(&pk_key_container);
}
/**
* @brief Calculates the SHA256 hash for the supplied message.
*
* @param msg Pointer to the buffer to read when generating the hash.
* @param msg_len Number of bytes in msg.
* @param hash Pointer to the buffer where the hash should be written.
* @param hash_buf_size Size of hash in bytes.
* @param hash_len Placeholder for the number of hash bytes written.
*/
static psa_status_t crp_hash_payload(uint8_t *msg, size_t msg_len,
uint8_t *hash, size_t hash_buf_size,
size_t *hash_len)
{
psa_status_t status;
psa_hash_operation_t hash_handle = psa_hash_operation_init();
psa_algorithm_t alg = PSA_ALG_SHA_256;
LOG_INF("Calculating SHA-256 hash of value");
al_dump_log();
/* Display the input message */
sf_hex_tabulate_16(&crp_fmt, msg, msg_len);
/* Setup the hash object. */
status = al_psa_status(psa_hash_setup(&hash_handle, alg),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to setup hash op.");
goto err;
}
/* Update object with all the message chunks. */
/* For the moment, the message is passed in a single operation, */
/* but this can be broken up in chunks for larger messages. */
status = al_psa_status(psa_hash_update(&hash_handle, msg, msg_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to update hash.");
goto err;
}
/* Finalize the hash calculation. */
status = al_psa_status(psa_hash_finish(&hash_handle,
hash, hash_buf_size, hash_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to finalize hash op.");
goto err;
}
/* Display the SHA-256 hash for debug purposes */
sf_hex_tabulate_16(&crp_fmt, hash, (size_t)(PSA_HASH_MAX_SIZE));
return status;
err:
psa_hash_abort(&hash_handle);
al_dump_log();
return status;
}
/**
* @brief Signs the supplied hash using the specified persistent key.
*
* @param key_id The identifier of the key to use when signing.
* @param hash Pointer to the buffer where the hash should be written.
* @param hash_buf_size Size of hash in bytes.
* @param sig Pointer to the buffer to read when generating the sig.
* @param sig_buf_size Size of sig buffer in bytes.
* @param sig_len Number of bytes written to sig.
*/
static psa_status_t crp_sign_hash(psa_key_id_t key_id,
uint8_t *hash, size_t hash_buf_size,
uint8_t *sig, size_t sig_buf_size,
size_t *sig_len)
{
psa_status_t status;
psa_key_handle_t key_handle;
LOG_INF("Signing SHA-256 hash");
al_dump_log();
/* Try to open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Sign using psa_sign_hash. */
status = al_psa_status(
psa_sign_hash(key_handle,
PSA_ALG_ECDSA(PSA_ALG_SHA_256),
hash, hash_buf_size,
sig, sig_buf_size, sig_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to sign hash w/persistent key #%d", key_id);
goto err;
}
/* Display the ECDSA signature for debug purposes */
sf_hex_tabulate_16(&crp_fmt, sig, *sig_len);
/* You can test this same operation with openssl as follows:
*
* $ openssl dgst -sha256 -sign
*/
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
return status;
err:
al_dump_log();
return status;
}
/**
* @brief Verifies the hash signature using the public key associated
* with key_id.
*
* @param key_id The identifier for the persistent key.
* @param hash Pointer to the hash data to verify.
* @param hash_len Size of the hash buffer in bytes.
* @param sig Pointer to the signature buffer.
* @param sig_len Size of the signature buffer in bytes.
*/
static psa_status_t crp_verify_sign(psa_key_id_t key_id,
uint8_t *hash, size_t hash_len,
uint8_t *sig, size_t sig_len)
{
psa_status_t status;
psa_key_handle_t key_handle;
LOG_INF("Verifying signature for SHA-256 hash");
al_dump_log();
/* Try to open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Verify the hash signature. */
status = al_psa_status(
psa_verify_hash(key_handle,
PSA_ALG_ECDSA(PSA_ALG_SHA_256),
hash, hash_len,
sig, sig_len),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Signature verification failed!");
goto err;
}
LOG_INF("Signature verified.");
al_dump_log();
/* Close the key to free up the volatile slot. */
status = al_psa_status(
psa_close_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to close persistent key.");
goto err;
}
return status;
err:
al_dump_log();
return status;
}
/**
* @brief Destroys the specified persistent key.
*
* @param key_id The identifier for the persistent key.
*/
static psa_status_t crp_dest_key(psa_key_id_t key_id)
{
psa_status_t status;
psa_key_handle_t key_handle;
/* Try to open the persisted key based on the key ID. */
status = al_psa_status(
psa_open_key(key_id, &key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to open persistent key #%d", key_id);
goto err;
}
/* Destroy the persistent key */
status = al_psa_status(
psa_destroy_key(key_handle),
__func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to destroy a persistent key");
goto err;
}
LOG_INF("Destroyed persistent key #%d", (uint32_t)key_id);
al_dump_log();
return status;
err:
al_dump_log();
return status;
}
void crp_test(void)
{
psa_status_t status;
uint8_t msg[] = "Please hash and sign this message.";
uint8_t hash[PSA_HASH_MAX_SIZE] = { 0 };
size_t hash_len;
uint8_t sig[PSA_VENDOR_ECDSA_SIGNATURE_MAX_SIZE] = { 0 };
size_t sig_len;
/* secp256r1 private key. */
#if CONFIG_PSA_IMPORT_KEY
#if CONFIG_PRIVATE_KEY_STATIC
/* This value is based on the private key in user.pem,
* which can be viewed viw the following command:
*
* $ openssl ec -in user.pem -text -noout
*/
uint8_t priv_key_data[32] = {
0x14, 0xbc, 0xb9, 0x53, 0xa4, 0xee, 0xed, 0x50,
0x09, 0x36, 0x92, 0x07, 0x1d, 0xdb, 0x24, 0x2c,
0xef, 0xf9, 0x57, 0x92, 0x40, 0x4f, 0x49, 0xaa,
0xd0, 0x7c, 0x5b, 0x3f, 0x26, 0xa7, 0x80, 0x48
};
#else /* !CONFIG_PRIVATE_KEY_STATIC */
/* Randomly generate the private key. */
uint8_t priv_key_data[32] = { 0 };
psa_generate_random(priv_key_data, sizeof(priv_key_data));
#endif /* CONFIG_PRIVATE_KEY_STATIC */
#endif /* CONFIG_PSA_IMPORT_KEY */
/* Initialize crypto API. */
status = al_psa_status(psa_crypto_init(), __func__);
if (status != PSA_SUCCESS) {
LOG_ERR("Crypto init failed.");
return;
}
/* NOTE: The same key generation, SHA256 hash, sign, and verify
* operations performed in this file can be also performed with
* openssl using the commands described below.
*
* Generate a new key:
*
* The curve `prime256v1` is same as `secp256r1` in OpenSSL
* (https://github.com/openssl/openssl/blob/master/apps/ecparam.c#L216)
* $ openssl ecparam -name prime256v1 -genkey -out user.pem
*
* Display the public and private keys in hexadecimal format:
*
* $ openssl ec -in user.pem -text -noout
*
* Update the private key value in priv_key_data with the hexadecimal
* values from "priv:" to be able to compare the PSA API and openssl
* output.
*
* Generate a PEM file with the public key (which will be used to
* verify any data signed with the private key):
*
* $ openssl ec -in user.pem -pubout -out user_pub.pem
*
* Hash the message with SHA256, and sign it with the private key:
*
* $ echo "Please hash and sign this message." > message.txt
* $ openssl dgst -sha256 -sign user.pem message.txt > signature.der
*
* Verify the signature using the public key and message file:
*
* $ openssl dgst -sha256 -verify user_pub.pem \
* -signature signature.der message.txt
*
* If everything ws OK you should see "Verified OK".
*/
/* Generate persistent secp256r1 key w/ID #1. */
/* PSA_KEY_USAGE_EXPORT can be added for debug purposes. */
#if CONFIG_PSA_IMPORT_KEY
status = crp_imp_key_secp256r1(1,
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH,
priv_key_data);
#else /* !CONFIG_PSA_IMPORT_KEY */
status = crp_gen_key_secp256r1(1,
PSA_KEY_USAGE_SIGN_HASH |
PSA_KEY_USAGE_VERIFY_HASH);
#endif
/* Hash some data with the key using SHA256. */
status = crp_hash_payload(msg, strlen(msg),
hash, sizeof(hash), &hash_len);
/* Sign the hash using key #1. */
status = crp_sign_hash(1,
hash, hash_len,
sig, sizeof(sig), &sig_len);
/* Verify the hash signature using the public key. */
status = crp_verify_sign(1, hash, hash_len, sig, sig_len);
/* Destroy the key. */
status = crp_dest_key(1);
}
/**
* @brief Generates random values using the TF-M crypto service.
*/
void crp_test_rng(void)
{
psa_status_t status;
uint8_t outbuf[256] = { 0 };
struct sf_hex_tbl_fmt fmt = {
.ascii = true,
.addr_label = true,
.addr = 0
};
status = al_psa_status(psa_generate_random(outbuf, 256), __func__);
LOG_INF("Generating 256 bytes of random data.");
al_dump_log();
sf_hex_tabulate_16(&fmt, outbuf, 256);
}