MCUX CLNS MCUX Crypto Library Normal Secure |

ecc_keygen_sign_verify.c

Example of ECC for key generation, signing and verification using the CSSv2 (CLNS component mcuxClCss)

/*--------------------------------------------------------------------------*/
/* Copyright 2020-2021 NXP */
/* */
/* NXP Confidential. This software is owned or controlled by NXP and may */
/* only be used strictly in accordance with the applicable license terms. */
/* By expressly accepting such terms or by downloading, installing, */
/* activating and/or otherwise using the software, you are agreeing that */
/* you have read, and that you agree to comply with and are bound by, such */
/* license terms. If you do not agree to be bound by the applicable license */
/* terms, then you may not retain, install, activate or otherwise use the */
/* software. */
/*--------------------------------------------------------------------------*/
#include <mcuxClCss.h> // Interface to the entire mcuxClCss component
#include <mcuxCsslFlowProtection.h> // Code flow protection
#include <stdbool.h> // bool type for the example's return code
static uint8_t const ecc_digest[MCUXCLCSS_HASH_OUTPUT_SIZE_SHA_256] = {0x11U, 0x11U, 0x11U, 0x11U,
0x22U, 0x22U, 0x22U, 0x22U,
0x33U, 0x33U, 0x33U, 0x33U,
0x44U, 0x44U, 0x44U, 0x44U,
0x55U, 0x55U, 0x55U, 0x55U,
0x66U, 0x66U, 0x66U, 0x66U,
0x77U, 0x77U, 0x77U, 0x77U,
0x88U, 0x88U, 0x88U, 0x88U};
static mcuxClCss_EccByte_t ecc_public_key[MCUXCLCSS_ECC_PUBLICKEY_SIZE];
static mcuxClCss_EccByte_t ecc_signature[MCUXCLCSS_ECC_SIGNATURE_SIZE];
static mcuxClCss_EccByte_t ecc_signature_r[MCUXCLCSS_ECC_SIGNATURE_R_SIZE];
static mcuxClCss_EccByte_t ecc_signature_and_public_key[MCUXCLCSS_ECC_SIGNATURE_SIZE + MCUXCLCSS_ECC_PUBLICKEY_SIZE];
bool ecc_keygen_sign_verify(
void)
{
/* Enable Css */
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_Enable_Async()); // Enable the CSSv2.
// mcuxClCss_Enable_Async is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_Enable_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_WaitForOperation(MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_Enable_Async operation to complete.
// mcuxClCss_WaitForOperation is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_WaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
/* Generate signing key */
mcuxClCss_EccKeyGenOption_t KeyGenOptions = {0}; // Initialize a new configuration for the planned mcuxClCss_EccKeyGen_Async operation.
KeyGenOptions.bits.kgsrc = MCUXCLCSS_ECC_OUTPUTKEY_RANDOM; // Configure that a non-deterministic key is generated.
mcuxClCss_KeyProp_t GenKeyProp = {0}; // Initialize a new configuration for the mcuxClCss_EccKeyGen_Async generated key properties.
GenKeyProp.bits.upprot_priv = MCUXCLCSS_KEYPROPERTY_PRIVILEGED_FALSE; // Configure that user access rights: non-privileged access
GenKeyProp.bits.upprot_sec = MCUXCLCSS_KEYPROPERTY_SECURE_TRUE; // Configure that user access rights: non-secure access
mcuxClCss_KeyIndex_t keyIdx = 0u; // Set keystore index at which mcuxClCss_EccKeyGen_Async is storing the private key.
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_EccKeyGen_Async( // Perform key generation.
KeyGenOptions, // Set the prepared configuration.
(mcuxClCss_KeyIndex_t) 0U, // This parameter (signingKeyIdx) is ignored, since no signature is requested in the configuration.
keyIdx, // Keystore index at which the generated private key is stored.
GenKeyProp, // Set the generated key properties.
NULL,
ecc_public_key // Output buffer, which the operation will write the public key to.
));
// mcuxClCss_EccKeyGen_Async is a flow-protected function: Check the protection token and the return value
if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_EccKeyGen_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
return false; // Expect that no error occurred, meaning that the mcuxClCss_EccKeyGen_Async operation was started.
MCUX_CSSL_FP_FUNCTION_CALL_END();
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_LimitedWaitForOperation(0x00100000U, MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_EccKeyGen_Async operation to complete.
// mcuxClCss_LimitedWaitForOperation is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_LimitedWaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
mcuxClCss_EccSignOption_t SignOptions = {0}; // Initialize a new configuration for the planned mcuxClCss_EccSign_Async operation.
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_EccSign_Async( // Perform signature generation.
SignOptions, // Set the prepared configuration.
keyIdx, // Set index of private key in keystore.
ecc_digest, NULL, (size_t) 0U, // Pre-hashed data to sign. Note that inputLength parameter is ignored since pre-hashed data has a fixed length.
ecc_signature // Output buffer, which the operation will write the signature to.
));
// mcuxClCss_EccSign_Async is a flow-protected function: Check the protection token and the return value
if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_EccSign_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
return false; // Expect that no error occurred, meaning that the mcuxClCss_EccSign_Async operation was started.
MCUX_CSSL_FP_FUNCTION_CALL_END();
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_LimitedWaitForOperation(0x00100000U, MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_EccSign_Async operation to complete.
// mcuxClCss_LimitedWaitForOperation is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_LimitedWaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
memcpy(&ecc_signature_and_public_key[0], // Prepare the concatenation of signature and public key: First the signature, ...
&ecc_signature[0],
MCUXCLCSS_ECC_SIGNATURE_SIZE);
memcpy(&ecc_signature_and_public_key[MCUXCLCSS_ECC_SIGNATURE_SIZE], // ... then the public key.
&ecc_public_key[0],
MCUXCLCSS_ECC_PUBLICKEY_SIZE);
mcuxClCss_EccVerifyOption_t VerifyOptions = {0}; // Initialize a new configuration for the planned mcuxClCss_EccVerify_Async operation.
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_EccVerify_Async( // Perform signature verification.
VerifyOptions, // Set the prepared configuration.
ecc_digest, NULL, (size_t) 0U, // Pre-hashed data to verify. Note that inputLength parameter is ignored since pre-hashed data has a fixed length.
ecc_signature_and_public_key, // Signature of the pre-hashed data
ecc_signature_r // Output buffer, which the operation will write the signature part r to, to allow external comparison of between given and recalculated r.
));
// mcuxClCss_EccVerify_Async is a flow-protected function: Check the protection token and the return value
if ((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_EccVerify_Async) != token) || (MCUXCLCSS_STATUS_OK_WAIT != result))
return false; // Expect that no error occurred, meaning that the mcuxClCss_EccVerify_Async operation was started.
MCUX_CSSL_FP_FUNCTION_CALL_END();
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_LimitedWaitForOperation(0x00100000U, MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_EccVerify_Async operation to complete.
// mcuxClCss_LimitedWaitForOperation is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_LimitedWaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
mcuxClCss_HwState_t state;
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_GetHwState(&state));
// mcuxClCss_GetHwState is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_GetHwState) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
if (MCUXCLCSS_STATUS_ECDSAVFY_OK != state.bits.ecdsavfy) return false; // Expect that mcuxClCss_EccVerify_Async operation successfully performed the signature verification.
/* Delete key */
mcuxClCss_Status_t del_result = mcuxClCss_KeyDelete_Async( keyIdx );
if (MCUXCLCSS_STATUS_OK_WAIT != del_result)
return false;
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_LimitedWaitForOperation(0x00100000U, MCUXCLCSS_ERROR_FLAGS_CLEAR)); // Wait for the mcuxClCss_KeyDelete_Async operation to complete.
// mcuxClCss_LimitedWaitForOperation is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_LimitedWaitForOperation) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
/* Disable Css */
MCUX_CSSL_FP_FUNCTION_CALL_BEGIN(result, token, mcuxClCss_Disable()); // Disable the CSSv2.
// mcuxClCss_Disable is a flow-protected function: Check the protection token and the return value
if((MCUX_CSSL_FP_FUNCTION_CALLED(mcuxClCss_Disable) != token) || (MCUXCLCSS_STATUS_OK != result))
return false;
MCUX_CSSL_FP_FUNCTION_CALL_END();
return true;
}