blob: 1441351a3894d56a05fefa17f60b9ed2736aaaa2 [file] [log] [blame]
/*
*
* Copyright 2018-2020 NXP
* SPDX-License-Identifier: Apache-2.0
*/
/* ************************************************************************** */
/* Includes */
/* ************************************************************************** */
#include <ex_sss.h>
#include <ex_sss_boot.h>
#include <fsl_sss_se05x_apis.h>
#include <nxEnsure.h>
#include <nxLog_App.h>
/* ************************************************************************** */
/* Local Defines */
/* ************************************************************************** */
#define EC_KEY_NIST256_BIT_LEN 256
#define EC_KEY_NIST256_HEADER_LEN 26
/* ************************************************************************** */
/* Structures and Typedefs */
/* ************************************************************************** */
/* ************************************************************************** */
/* Global Variables */
/* ************************************************************************** */
static ex_sss_boot_ctx_t gex_sss_ecc_boot_ctx;
sss_object_t ecc_key;
sss_object_t attestation_ecc_key;
sss_algorithm_t attst_algorithm = kAlgorithm_SSS_ECDSA_SHA256;
sss_se05x_attst_data_t attestation_data;
/* ************************************************************************** */
/* Static function declarations */
/* ************************************************************************** */
static sss_status_t ex_sss_initialise_attst_data(sss_se05x_attst_data_t *attst_data);
static sss_status_t ex_sss_verify_attested_key(ex_sss_boot_ctx_t *pCtx, uint8_t *publicKey, size_t publicKeyByteLen);
/* ************************************************************************** */
/* Private Functions */
/* ************************************************************************** */
/* ************************************************************************** */
/* Public Functions */
/* ************************************************************************** */
#define EX_SSS_BOOT_PCONTEXT (&gex_sss_ecc_boot_ctx)
#define EX_SSS_BOOT_DO_ERASE 1
#define EX_SSS_BOOT_EXPOSE_ARGC_ARGV 0
#include <ex_sss_main_inc.h>
/* clang-format off */
const uint8_t ecc_keyPairData[] = {
0x30, 0x81, 0x87, 0x02, 0x01, 0x00, 0x30, 0x13,
0x06, 0x07, 0x2A, 0x86, 0x48, 0xCE, 0x3D, 0x02,
0x01, 0x06, 0x08, 0x2A, 0x86, 0x48, 0xCE, 0x3D,
0x03, 0x01, 0x07, 0x04, 0x6D, 0x30, 0x6B, 0x02,
0x01, 0x01, 0x04, 0x20, 0x78, 0xE5, 0x20, 0x6A,
0x08, 0xED, 0xD2, 0x52, 0x36, 0x33, 0x8A, 0x24,
0x84, 0xE4, 0x2F, 0x1F, 0x7D, 0x1F, 0x6D, 0x94,
0x37, 0xA9, 0x95, 0x86, 0xDA, 0xFC, 0xD2, 0x23,
0x6F, 0xA2, 0x87, 0x35, 0xA1, 0x44, 0x03, 0x42,
0x00, 0x04, 0xED, 0xA7, 0xE9, 0x0B, 0xF9, 0x20,
0xCF, 0xFB, 0x9D, 0xF6, 0xDB, 0xCE, 0xF7, 0x20,
0xE1, 0x23, 0x8B, 0x3C, 0xEE, 0x84, 0x86, 0xD2,
0x50, 0xE4, 0xDF, 0x30, 0x11, 0x50, 0x1A, 0x15,
0x08, 0xA6, 0x2E, 0xD7, 0x49, 0x52, 0x78, 0x63,
0x6E, 0x61, 0xE8, 0x5F, 0xED, 0xB0, 0x6D, 0x87,
0x92, 0x0A, 0x04, 0x19, 0x14, 0xFE, 0x76, 0x63,
0x55, 0xDF, 0xBD, 0x68, 0x61, 0x59, 0x31, 0x8E,
0x68, 0x7C
};
const uint8_t ecc_PubKeyData[] =
{
0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2A, 0x86,
0x48, 0xCE, 0x3D, 0x02, 0x01, 0x06, 0x08, 0x2A,
0x86, 0x48, 0xCE, 0x3D, 0x03, 0x01, 0x07, 0x03,
0x42, 0x00, 0x04, 0xED, 0xA7, 0xE9, 0x0B, 0xF9,
0x20, 0xCF, 0xFB, 0x9D, 0xF6, 0xDB, 0xCE, 0xF7,
0x20, 0xE1, 0x23, 0x8B, 0x3C, 0xEE, 0x84, 0x86,
0xD2, 0x50, 0xE4, 0xDF, 0x30, 0x11, 0x50, 0x1A,
0x15, 0x08, 0xA6, 0x2E, 0xD7, 0x49, 0x52, 0x78,
0x63, 0x6E, 0x61, 0xE8, 0x5F, 0xED, 0xB0, 0x6D,
0x87, 0x92, 0x0A, 0x04, 0x19, 0x14, 0xFE, 0x76,
0x63, 0x55, 0xDF, 0xBD, 0x68, 0x61, 0x59, 0x31,
0x8E, 0x68, 0x7C
};
/* clang-format on */
sss_status_t ex_sss_entry(ex_sss_boot_ctx_t *pCtx)
{
sss_status_t status = kStatus_SSS_Success;
uint8_t publicKey[256] = {0};
size_t publicKeyByteLen = sizeof(publicKey);
size_t publicKeyBitLen = sizeof(publicKey) * 8;
uint8_t random[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2, 3, 4, 5, 6, 7};
const sss_policy_u ecc_key_pol = {.type = KPolicy_Asym_Key,
.auth_obj_id = 0,
.policy = {.asymmkey = {
.can_Sign = 1,
.can_Verify = 1,
.can_Encrypt = 1,
.can_Decrypt = 1,
.can_KD = 1,
.can_Wrap = 1,
.can_Write = 1,
.can_Gen = 1,
.can_Import_Export = 1,
.can_KA = 1,
.can_Read = 1,
.can_Attest = 1,
}}};
const sss_policy_u common = {.type = KPolicy_Common,
.auth_obj_id = 0,
.policy = {.common = {
.can_Delete = 1,
}}};
sss_policy_t attestation_ecc_key_pol = {.nPolicies = 2, .policies = {&ecc_key_pol, &common}};
LOG_I("Running ECC key attestation example ex_sss_attest_ecc.c ");
LOG_I("Inject ECC key pair - 'ecc_key'");
status = sss_key_object_init(&ecc_key, &pCtx->ks);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_object_allocate_handle(&ecc_key,
MAKE_TEST_ID(__LINE__),
kSSS_KeyPart_Pair,
kSSS_CipherType_EC_NIST_P,
256,
kKeyObject_Mode_Persistent);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_store_set_key(
&pCtx->ks, &ecc_key, ecc_keyPairData, sizeof(ecc_keyPairData), EC_KEY_NIST256_BIT_LEN, NULL, 0);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_I("Create a attestation ECC key pair - 'attestation_ecc_key'");
status = sss_key_object_init(&attestation_ecc_key, &pCtx->ks);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_key_object_allocate_handle(&attestation_ecc_key,
MAKE_TEST_ID(__LINE__),
kSSS_KeyPart_Pair,
kSSS_CipherType_EC_NIST_P,
256,
kKeyObject_Mode_Persistent);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status =
sss_key_store_generate_key(&pCtx->ks, &attestation_ecc_key, EC_KEY_NIST256_BIT_LEN, &attestation_ecc_key_pol);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = ex_sss_initialise_attst_data(&attestation_data);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_I("Read public key from ECC key pair 'ecc_key' with attestation");
status = sss_se05x_key_store_get_key_attst((sss_se05x_key_store_t *)(&pCtx->ks),
(sss_se05x_object_t *)(&ecc_key),
publicKey,
&publicKeyByteLen,
&publicKeyBitLen,
(sss_se05x_object_t *)(&attestation_ecc_key),
attst_algorithm,
random,
sizeof(random),
&attestation_data);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_I("Attested Key -->");
LOG_MAU8_I("Public Key", publicKey, publicKeyByteLen);
LOG_MAU8_I("Attribute", attestation_data.data[0].attribute, attestation_data.data[0].attributeLen);
LOG_MAU8_I("Time Stamp", attestation_data.data[0].timeStamp.ts, attestation_data.data[0].timeStampLen);
LOG_MAU8_I("Out Random Value", attestation_data.data[0].outrandom, attestation_data.data[0].outrandomLen);
LOG_MAU8_I("Chip Id", attestation_data.data[0].chipId, attestation_data.data[0].chipIdLen);
LOG_MAU8_I("Signature", attestation_data.data[0].signature, attestation_data.data[0].signatureLen);
/********* Verify attestation signature *********/
LOG_I("Verify attestation signature using 'attestation_ecc_key' key");
/* Singing is done on public key without header */
status = ex_sss_verify_attested_key(
pCtx, (publicKey + EC_KEY_NIST256_HEADER_LEN), (publicKeyByteLen - EC_KEY_NIST256_HEADER_LEN));
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
LOG_I("Verification success ");
cleanup:
if (kStatus_SSS_Success == status) {
LOG_I("ex_sss_attest_ecc Example Success !!!...");
}
else {
LOG_E("ex_sss_attest_ecc Example Failed !!!...");
}
return status;
}
static sss_status_t ex_sss_verify_attested_key(ex_sss_boot_ctx_t *pCtx, uint8_t *publicKey, size_t publicKeyByteLen)
{
sss_status_t status = kStatus_SSS_Success;
sss_digest_t digest_ctx = {
0,
};
sss_asymmetric_t asymVerifyCtx = {
0,
};
uint8_t plainData[1024] = {0};
size_t plainDateLen = sizeof(plainData);
uint8_t digest[64] = {0}; /* Max - SHA512 */
size_t digestLen = sizeof(digest);
sss_algorithm_t digest_algorithm = kAlgorithm_SSS_SHA256;
if (plainDateLen < publicKeyByteLen + attestation_data.data[0].attributeLen +
attestation_data.data[0].timeStampLen + attestation_data.data[0].outrandomLen +
attestation_data.data[0].chipIdLen) {
return kStatus_SSS_Fail;
}
else {
memcpy(plainData, publicKey, publicKeyByteLen);
memcpy(plainData + publicKeyByteLen, attestation_data.data[0].attribute, attestation_data.data[0].attributeLen);
memcpy(plainData + publicKeyByteLen + attestation_data.data[0].attributeLen,
&(attestation_data.data[0].timeStamp),
attestation_data.data[0].timeStampLen);
memcpy(plainData + publicKeyByteLen + attestation_data.data[0].attributeLen +
attestation_data.data[0].timeStampLen,
attestation_data.data[0].outrandom,
attestation_data.data[0].outrandomLen);
memcpy(plainData + publicKeyByteLen + attestation_data.data[0].attributeLen +
attestation_data.data[0].timeStampLen + attestation_data.data[0].outrandomLen,
attestation_data.data[0].chipId,
attestation_data.data[0].chipIdLen);
plainDateLen = publicKeyByteLen + attestation_data.data[0].attributeLen +
attestation_data.data[0].timeStampLen + attestation_data.data[0].outrandomLen +
attestation_data.data[0].chipIdLen;
}
status = sss_digest_context_init(&digest_ctx, &pCtx->session, digest_algorithm, kMode_SSS_Digest);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_digest_one_go(&digest_ctx, plainData, plainDateLen, digest, &digestLen);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
/* verify the attestation signature */
status = sss_asymmetric_context_init(
&asymVerifyCtx, &pCtx->session, &attestation_ecc_key, attst_algorithm, kMode_SSS_Verify);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
status = sss_asymmetric_verify_digest(
&asymVerifyCtx, digest, digestLen, attestation_data.data[0].signature, attestation_data.data[0].signatureLen);
ENSURE_OR_GO_CLEANUP(status == kStatus_SSS_Success);
cleanup:
if (digest_ctx.session != NULL)
sss_digest_context_free(&digest_ctx);
if (asymVerifyCtx.session != NULL)
sss_asymmetric_context_free(&asymVerifyCtx);
if (kStatus_SSS_Success != status) {
LOG_I("Verification of attestation signature failed !!!...");
}
return status;
}
static sss_status_t ex_sss_initialise_attst_data(sss_se05x_attst_data_t *attst_data)
{
sss_status_t status = kStatus_SSS_Fail;
size_t i;
if (attst_data != NULL) {
memset(attst_data, 0, sizeof(sss_se05x_attst_data_t));
for (i = 0; i < SE05X_MAX_ATTST_DATA; i++) {
attst_data->data[i].outrandomLen = sizeof(attst_data->data[i].outrandom);
attst_data->data[i].timeStampLen = sizeof(attst_data->data[i].timeStamp);
attst_data->data[i].chipIdLen = sizeof(attst_data->data[i].chipId);
attst_data->data[i].attributeLen = sizeof(attst_data->data[i].attribute);
attst_data->data[i].signatureLen = sizeof(attst_data->data[i].signature);
}
attst_data->valid_number = SE05X_MAX_ATTST_DATA;
status = kStatus_SSS_Success;
}
return status;
}