GK SDK 源码库: XMIPCLinuxV100R005C00SPC030 (kernel/tools/open_source excluded)

This commit is contained in:
lai
2026-09-06 03:52:57 +08:00
commit b1928b41c0
21813 changed files with 4413081 additions and 0 deletions
@@ -0,0 +1,466 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdint.h>
#include <string.h>
#include <platform_def.h>
#include <common/debug.h>
#include <common/tbbr/cot_def.h>
#include <drivers/auth/auth_common.h>
#include <drivers/auth/auth_mod.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/img_parser_mod.h>
#include <drivers/fwu/fwu.h>
#include <lib/fconf/fconf_tbbr_getter.h>
#include <plat/common/platform.h>
/* ASN.1 tags */
#define ASN1_INTEGER 0x02
#define return_if_error(rc) \
do { \
if (rc != 0) { \
return rc; \
} \
} while (0)
#pragma weak plat_set_nv_ctr2
#pragma weak plat_convert_pk
static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a,
const auth_param_type_desc_t *b)
{
if ((a->type == b->type) && (a->cookie == b->cookie)) {
return 0;
}
return 1;
}
/*
* This function obtains the requested authentication parameter data from the
* information extracted from the parent image after its authentication.
*/
static int auth_get_param(const auth_param_type_desc_t *param_type_desc,
const auth_img_desc_t *img_desc,
void **param, unsigned int *len)
{
int i;
if (img_desc->authenticated_data == NULL)
return 1;
for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) {
if (0 == cmp_auth_param_type_desc(param_type_desc,
img_desc->authenticated_data[i].type_desc)) {
*param = img_desc->authenticated_data[i].data.ptr;
*len = img_desc->authenticated_data[i].data.len;
return 0;
}
}
return 1;
}
/*
* Authenticate an image by matching the data hash
*
* This function implements 'AUTH_METHOD_HASH'. To authenticate an image using
* this method, the image must contain:
*
* - The data to calculate the hash from
*
* The parent image must contain:
*
* - The hash to be matched with (including hash algorithm)
*
* For a successful authentication, both hashes must match. The function calls
* the crypto-module to check this matching.
*
* Parameters:
* param: parameters to perform the hash authentication
* img_desc: pointer to image descriptor so we can know the image type
* and parent image
* img: pointer to image in memory
* img_len: length of image (in bytes)
*
* Return:
* 0 = success, Otherwise = error
*/
static int auth_hash(const auth_method_param_hash_t *param,
const auth_img_desc_t *img_desc,
void *img, unsigned int img_len)
{
void *data_ptr, *hash_der_ptr;
unsigned int data_len, hash_der_len;
int rc = 0;
/* Get the hash from the parent image. This hash will be DER encoded
* and contain the hash algorithm */
rc = auth_get_param(param->hash, img_desc->parent,
&hash_der_ptr, &hash_der_len);
return_if_error(rc);
/* Get the data to be hashed from the current image */
rc = img_parser_get_auth_param(img_desc->img_type, param->data,
img, img_len, &data_ptr, &data_len);
return_if_error(rc);
/* Ask the crypto module to verify this hash */
rc = crypto_mod_verify_hash(data_ptr, data_len,
hash_der_ptr, hash_der_len);
return rc;
}
/*
* Authenticate by digital signature
*
* This function implements 'AUTH_METHOD_SIG'. To authenticate an image using
* this method, the image must contain:
*
* - Data to be signed
* - Signature
* - Signature algorithm
*
* We rely on the image parser module to extract this data from the image.
* The parent image must contain:
*
* - Public key (or a hash of it)
*
* If the parent image contains only a hash of the key, we will try to obtain
* the public key from the image itself (i.e. self-signed certificates). In that
* case, the signature verification is considered just an integrity check and
* the authentication is established by calculating the hash of the key and
* comparing it with the hash obtained from the parent.
*
* If the image has no parent (NULL), it means it has to be authenticated using
* the ROTPK stored in the platform. Again, this ROTPK could be the key itself
* or a hash of it.
*
* Return: 0 = success, Otherwise = error
*/
static int auth_signature(const auth_method_param_sig_t *param,
const auth_img_desc_t *img_desc,
void *img, unsigned int img_len)
{
void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr;
unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len;
unsigned int flags = 0;
int rc = 0;
/* Get the data to be signed from current image */
rc = img_parser_get_auth_param(img_desc->img_type, param->data,
img, img_len, &data_ptr, &data_len);
return_if_error(rc);
/* Get the signature from current image */
rc = img_parser_get_auth_param(img_desc->img_type, param->sig,
img, img_len, &sig_ptr, &sig_len);
return_if_error(rc);
/* Get the signature algorithm from current image */
rc = img_parser_get_auth_param(img_desc->img_type, param->alg,
img, img_len, &sig_alg_ptr, &sig_alg_len);
return_if_error(rc);
/* Get the public key from the parent. If there is no parent (NULL),
* the certificate has been signed with the ROTPK, so we have to get
* the PK from the platform */
if (img_desc->parent) {
rc = auth_get_param(param->pk, img_desc->parent,
&pk_ptr, &pk_len);
} else {
rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len,
&flags);
}
return_if_error(rc);
if (flags & (ROTPK_IS_HASH | ROTPK_NOT_DEPLOYED)) {
/* If the PK is a hash of the key or if the ROTPK is not
deployed on the platform, retrieve the key from the image */
pk_hash_ptr = pk_ptr;
pk_hash_len = pk_len;
rc = img_parser_get_auth_param(img_desc->img_type,
param->pk, img, img_len,
&pk_ptr, &pk_len);
return_if_error(rc);
/* Ask the crypto module to verify the signature */
rc = crypto_mod_verify_signature(data_ptr, data_len,
sig_ptr, sig_len,
sig_alg_ptr, sig_alg_len,
pk_ptr, pk_len);
return_if_error(rc);
if (flags & ROTPK_NOT_DEPLOYED) {
NOTICE("ROTPK is not deployed on platform. "
"Skipping ROTPK verification.\n");
} else {
/* platform may store the hash of a prefixed, suffixed or modified pk */
rc = plat_convert_pk(pk_ptr, pk_len, &pk_ptr, &pk_len);
return_if_error(rc);
/* Ask the crypto-module to verify the key hash */
rc = crypto_mod_verify_hash(pk_ptr, pk_len,
pk_hash_ptr, pk_hash_len);
}
} else {
/* Ask the crypto module to verify the signature */
rc = crypto_mod_verify_signature(data_ptr, data_len,
sig_ptr, sig_len,
sig_alg_ptr, sig_alg_len,
pk_ptr, pk_len);
}
return rc;
}
/*
* Authenticate by Non-Volatile counter
*
* To protect the system against rollback, the platform includes a non-volatile
* counter whose value can only be increased. All certificates include a counter
* value that should not be lower than the value stored in the platform. If the
* value is larger, the counter in the platform must be updated to the new value
* (provided it has been authenticated).
*
* Return: 0 = success, Otherwise = error
* Returns additionally,
* cert_nv_ctr -> NV counter value present in the certificate
* need_nv_ctr_upgrade = 0 -> platform NV counter upgrade is not needed
* need_nv_ctr_upgrade = 1 -> platform NV counter upgrade is needed
*/
static int auth_nvctr(const auth_method_param_nv_ctr_t *param,
const auth_img_desc_t *img_desc,
void *img, unsigned int img_len,
unsigned int *cert_nv_ctr,
bool *need_nv_ctr_upgrade)
{
unsigned char *p;
void *data_ptr = NULL;
unsigned int data_len, len, i;
unsigned int plat_nv_ctr;
int rc = 0;
bool is_trial_run = false;
/* Get the counter value from current image. The AM expects the IPM
* to return the counter value as a DER encoded integer */
rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr,
img, img_len, &data_ptr, &data_len);
return_if_error(rc);
/* Parse the DER encoded integer */
assert(data_ptr);
p = (unsigned char *)data_ptr;
/*
* Integers must be at least 3 bytes: 1 for tag, 1 for length, and 1
* for value. The first byte (tag) must be ASN1_INTEGER.
*/
if ((data_len < 3) || (*p != ASN1_INTEGER)) {
/* Invalid ASN.1 integer */
return 1;
}
p++;
/*
* NV-counters are unsigned integers up to 31 bits. Trailing
* padding is not allowed.
*/
len = (unsigned int)*p;
if ((len > 4) || (data_len - 2 != len)) {
return 1;
}
p++;
/* Check the number is not negative */
if (*p & 0x80) {
return 1;
}
/* Convert to unsigned int. This code is for a little-endian CPU */
*cert_nv_ctr = 0;
for (i = 0; i < len; i++) {
*cert_nv_ctr = (*cert_nv_ctr << 8) | *p++;
}
/* Get the counter from the platform */
rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr);
return_if_error(rc);
if (*cert_nv_ctr < plat_nv_ctr) {
/* Invalid NV-counter */
return 1;
} else if (*cert_nv_ctr > plat_nv_ctr) {
#if PSA_FWU_SUPPORT && IMAGE_BL2
is_trial_run = fwu_is_trial_run_state();
#endif /* PSA_FWU_SUPPORT && IMAGE_BL2 */
*need_nv_ctr_upgrade = !is_trial_run;
}
return 0;
}
int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused,
unsigned int nv_ctr)
{
return plat_set_nv_ctr(cookie, nv_ctr);
}
int plat_convert_pk(void *full_pk_ptr, unsigned int full_pk_len,
void **hashed_pk_ptr, unsigned int *hashed_pk_len)
{
*hashed_pk_ptr = full_pk_ptr;
*hashed_pk_len = full_pk_len;
return 0;
}
/*
* Return the parent id in the output parameter '*parent_id'
*
* Return value:
* 0 = Image has parent, 1 = Image has no parent or parent is authenticated
*/
int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id)
{
const auth_img_desc_t *img_desc = NULL;
assert(parent_id != NULL);
/* Get the image descriptor */
img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
/* Check if the image has no parent (ROT) */
if (img_desc->parent == NULL) {
*parent_id = 0;
return 1;
}
/* Check if the parent has already been authenticated */
if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) {
*parent_id = 0;
return 1;
}
*parent_id = img_desc->parent->img_id;
return 0;
}
/*
* Initialize the different modules in the authentication framework
*/
void auth_mod_init(void)
{
/* Check we have a valid CoT registered */
assert(cot_desc_ptr != NULL);
/* Image parser module */
img_parser_init();
}
/*
* Authenticate a certificate/image
*
* Return: 0 = success, Otherwise = error
*/
int auth_mod_verify_img(unsigned int img_id,
void *img_ptr,
unsigned int img_len)
{
const auth_img_desc_t *img_desc = NULL;
const auth_method_desc_t *auth_method = NULL;
void *param_ptr;
unsigned int param_len;
int rc, i;
unsigned int cert_nv_ctr = 0;
bool need_nv_ctr_upgrade = false;
bool sig_auth_done = false;
const auth_method_param_nv_ctr_t *nv_ctr_param = NULL;
/* Get the image descriptor from the chain of trust */
img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id);
/* Ask the parser to check the image integrity */
rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len);
return_if_error(rc);
/* Authenticate the image using the methods indicated in the image
* descriptor. */
if (img_desc->img_auth_methods == NULL)
return 1;
for (i = 0 ; i < AUTH_METHOD_NUM ; i++) {
auth_method = &img_desc->img_auth_methods[i];
switch (auth_method->type) {
case AUTH_METHOD_NONE:
rc = 0;
break;
case AUTH_METHOD_HASH:
rc = auth_hash(&auth_method->param.hash,
img_desc, img_ptr, img_len);
break;
case AUTH_METHOD_SIG:
rc = auth_signature(&auth_method->param.sig,
img_desc, img_ptr, img_len);
sig_auth_done = true;
break;
case AUTH_METHOD_NV_CTR:
nv_ctr_param = &auth_method->param.nv_ctr;
rc = auth_nvctr(nv_ctr_param,
img_desc, img_ptr, img_len,
&cert_nv_ctr, &need_nv_ctr_upgrade);
break;
default:
/* Unknown authentication method */
rc = 1;
break;
}
return_if_error(rc);
}
/*
* Do platform NV counter upgrade only if the certificate gets
* authenticated, and platform NV-counter upgrade is needed.
*/
if (need_nv_ctr_upgrade && sig_auth_done) {
rc = plat_set_nv_ctr2(nv_ctr_param->plat_nv_ctr->cookie,
img_desc, cert_nv_ctr);
return_if_error(rc);
}
/* Extract the parameters indicated in the image descriptor to
* authenticate the children images. */
if (img_desc->authenticated_data != NULL) {
for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) {
if (img_desc->authenticated_data[i].type_desc == NULL) {
continue;
}
/* Get the parameter from the image parser module */
rc = img_parser_get_auth_param(img_desc->img_type,
img_desc->authenticated_data[i].type_desc,
img_ptr, img_len, &param_ptr, &param_len);
return_if_error(rc);
/* Check parameter size */
if (param_len > img_desc->authenticated_data[i].data.len) {
return 1;
}
/* Copy the parameter for later use */
memcpy((void *)img_desc->authenticated_data[i].data.ptr,
(void *)param_ptr, param_len);
}
}
/* Mark image as authenticated */
auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED;
return 0;
}
@@ -0,0 +1,675 @@
/*
* Copyright (c) 2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <drivers/auth/auth_mod.h>
#include MBEDTLS_CONFIG_FILE
#include <tools_share/cca_oid.h>
#include <platform_def.h>
/*
* Allocate static buffers to store the authentication parameters extracted from
* the certificates.
*/
static unsigned char fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char hw_config_hash_buf[HASH_DER_LEN];
static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char rmm_hash_buf[HASH_DER_LEN];
#ifdef IMAGE_BL2
static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
#if defined(SPD_spmd)
static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
#endif /* SPD_spmd */
static unsigned char core_swd_pk_buf[PK_DER_LEN];
static unsigned char plat_pk_buf[PK_DER_LEN];
#endif /* IMAGE_BL2 */
/*
* Parameter type descriptors.
*/
static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, 0);
static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG, 0);
static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG_ALG, 0);
static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_RAW_DATA, 0);
static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t rmm_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, RMM_HASH_OID);
#ifdef IMAGE_BL2
static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, PROT_PK_OID);
static auth_param_type_desc_t swd_rot_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, SWD_ROT_PK_OID);
static auth_param_type_desc_t core_swd_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, CORE_SWD_PK_OID);
static auth_param_type_desc_t plat_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, PLAT_PK_OID);
static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
#if defined(SPD_spmd)
static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
#endif /* SPD_spmd */
#endif /* IMAGE_BL2 */
/* CCA Content Certificate */
static const auth_img_desc_t cca_content_cert = {
.img_id = CCA_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tb_fw_hash,
.data = {
.ptr = (void *)tb_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tb_fw_config_hash,
.data = {
.ptr = (void *)tb_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &fw_config_hash,
.data = {
.ptr = (void *)fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &hw_config_hash,
.data = {
.ptr = (void *)hw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[4] = {
.type_desc = &soc_fw_hash,
.data = {
.ptr = (void *)soc_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[5] = {
.type_desc = &soc_fw_config_hash,
.data = {
.ptr = (void *)soc_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[6] = {
.type_desc = &rmm_hash,
.data = {
.ptr = (void *)rmm_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
#ifdef IMAGE_BL1
static const auth_img_desc_t bl2_image = {
.img_id = BL2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_hash
}
}
}
};
static const auth_img_desc_t tb_fw_config = {
.img_id = TB_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_config_hash
}
}
}
};
static const auth_img_desc_t fw_config = {
.img_id = FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &fw_config_hash
}
}
}
};
#endif /* IMAGE_BL1 */
#ifdef IMAGE_BL2
/* HW Config */
static const auth_img_desc_t hw_config = {
.img_id = HW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &hw_config_hash
}
}
}
};
/* BL31 */
static const auth_img_desc_t bl31_image = {
.img_id = BL31_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_hash
}
}
}
};
/* BL31 Config */
static const auth_img_desc_t soc_fw_config = {
.img_id = SOC_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_config_hash
}
}
}
};
/* RMM */
static const auth_img_desc_t rmm_image = {
.img_id = RMM_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &cca_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &rmm_hash
}
}
}
};
/* Core SWD Key Certificate */
static const auth_img_desc_t core_swd_key_cert = {
.img_id = CORE_SWD_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL, /* SWD ROOT CERT */
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &swd_rot_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &core_swd_pk,
.data = {
.ptr = (void *)core_swd_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
/* SPMC Content Certificate */
static const auth_img_desc_t trusted_os_fw_content_cert = {
.img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &core_swd_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &core_swd_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tos_fw_hash,
.data = {
.ptr = (void *)tos_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tos_fw_config_hash,
.data = {
.ptr = (void *)tos_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
/* SPMC */
static const auth_img_desc_t bl32_image = {
.img_id = BL32_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_hash
}
}
}
};
/* SPM Config */
static const auth_img_desc_t tos_fw_config = {
.img_id = TOS_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_config_hash
}
}
}
};
/* Platform Key Certificate */
static const auth_img_desc_t plat_key_cert = {
.img_id = PLAT_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL, /* PLATFORM ROOT CERT */
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &prot_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &plat_pk,
.data = {
.ptr = (void *)plat_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
/* Non-Trusted Firmware */
static const auth_img_desc_t non_trusted_fw_content_cert = {
.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &plat_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &plat_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_world_bl_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &nt_fw_config_hash,
.data = {
.ptr = (void *)nt_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl33_image = {
.img_id = BL33_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_world_bl_hash
}
}
}
};
/* NT FW Config */
static const auth_img_desc_t nt_fw_config = {
.img_id = NT_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_fw_config_hash
}
}
}
};
/*
* Secure Partitions
*/
#if defined(SPD_spmd)
static const auth_img_desc_t sip_sp_content_cert = {
.img_id = SIP_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &core_swd_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &core_swd_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &sp_pkg1_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[0],
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &sp_pkg2_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[1],
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &sp_pkg3_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[2],
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &sp_pkg4_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[3],
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
DEFINE_SIP_SP_PKG(1);
DEFINE_SIP_SP_PKG(2);
DEFINE_SIP_SP_PKG(3);
DEFINE_SIP_SP_PKG(4);
static const auth_img_desc_t plat_sp_content_cert = {
.img_id = PLAT_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &plat_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &plat_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &sp_pkg5_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[4],
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &sp_pkg6_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[5],
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &sp_pkg7_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[6],
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &sp_pkg8_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[7],
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
DEFINE_PLAT_SP_PKG(5);
DEFINE_PLAT_SP_PKG(6);
DEFINE_PLAT_SP_PKG(7);
DEFINE_PLAT_SP_PKG(8);
#endif /* SPD_spmd */
#endif /* IMAGE_BL2 */
/*
* Chain of trust definition
*/
#ifdef IMAGE_BL1
static const auth_img_desc_t * const cot_desc[] = {
[CCA_CONTENT_CERT_ID] = &cca_content_cert,
[BL2_IMAGE_ID] = &bl2_image,
[TB_FW_CONFIG_ID] = &tb_fw_config,
[FW_CONFIG_ID] = &fw_config,
};
#else /* IMAGE_BL2 */
static const auth_img_desc_t * const cot_desc[] = {
[CCA_CONTENT_CERT_ID] = &cca_content_cert,
[HW_CONFIG_ID] = &hw_config,
[BL31_IMAGE_ID] = &bl31_image,
[SOC_FW_CONFIG_ID] = &soc_fw_config,
[RMM_IMAGE_ID] = &rmm_image,
[CORE_SWD_KEY_CERT_ID] = &core_swd_key_cert,
[TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
[BL32_IMAGE_ID] = &bl32_image,
[TOS_FW_CONFIG_ID] = &tos_fw_config,
[PLAT_KEY_CERT_ID] = &plat_key_cert,
[NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
[BL33_IMAGE_ID] = &bl33_image,
[NT_FW_CONFIG_ID] = &nt_fw_config,
#if defined(SPD_spmd)
[SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
[PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert,
[SP_PKG1_ID] = &sp_pkg1,
[SP_PKG2_ID] = &sp_pkg2,
[SP_PKG3_ID] = &sp_pkg3,
[SP_PKG4_ID] = &sp_pkg4,
[SP_PKG5_ID] = &sp_pkg5,
[SP_PKG6_ID] = &sp_pkg6,
[SP_PKG7_ID] = &sp_pkg7,
[SP_PKG8_ID] = &sp_pkg8,
#endif
};
#endif /* IMAGE_BL1 */
/* Register the CoT in the authentication module */
REGISTER_COT(cot_desc);
@@ -0,0 +1,175 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */
/*
* The crypto module is responsible for verifying digital signatures and hashes.
* It relies on a crypto library to perform the cryptographic operations.
*
* The crypto module itself does not impose any specific format on signatures,
* signature algorithm, keys or hashes, but most cryptographic libraries will
* take the parameters as the following DER encoded ASN.1 structures:
*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING
* }
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*
* SignatureAlgorithm ::= AlgorithmIdentifier
*
* SignatureValue ::= BIT STRING
*/
/*
* Perform some static checking and call the library initialization function
*/
void crypto_mod_init(void)
{
assert(crypto_lib_desc.name != NULL);
assert(crypto_lib_desc.init != NULL);
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
assert(crypto_lib_desc.verify_signature != NULL);
assert(crypto_lib_desc.verify_hash != NULL);
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
assert(crypto_lib_desc.calc_hash != NULL);
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
/* Initialize the cryptographic library */
crypto_lib_desc.init();
INFO("Using crypto library '%s'\n", crypto_lib_desc.name);
}
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/*
* Function to verify a digital signature
*
* Parameters:
*
* data_ptr, data_len: signed data
* sig_ptr, sig_len: the digital signature
* sig_alg_ptr, sig_alg_len: the digital signature algorithm
* pk_ptr, pk_len: the public key
*/
int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg_ptr, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
assert(data_ptr != NULL);
assert(data_len != 0);
assert(sig_ptr != NULL);
assert(sig_len != 0);
assert(sig_alg_ptr != NULL);
assert(sig_alg_len != 0);
assert(pk_ptr != NULL);
assert(pk_len != 0);
return crypto_lib_desc.verify_signature(data_ptr, data_len,
sig_ptr, sig_len,
sig_alg_ptr, sig_alg_len,
pk_ptr, pk_len);
}
/*
* Verify a hash by comparison
*
* Parameters:
*
* data_ptr, data_len: data to be hashed
* digest_info_ptr, digest_info_len: hash to be compared
*/
int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len)
{
assert(data_ptr != NULL);
assert(data_len != 0);
assert(digest_info_ptr != NULL);
assert(digest_info_len != 0);
return crypto_lib_desc.verify_hash(data_ptr, data_len,
digest_info_ptr, digest_info_len);
}
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/*
* Calculate a hash
*
* Parameters:
*
* alg: message digest algorithm
* data_ptr, data_len: data to be hashed
* output: resulting hash
*/
int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
{
assert(data_ptr != NULL);
assert(data_len != 0);
assert(output != NULL);
return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output);
}
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
/*
* Authenticated decryption of data
*
* Parameters:
*
* dec_algo: authenticated decryption algorithm
* data_ptr, len: data to be decrypted (inout param)
* key, key_len, key_flags: symmetric decryption key
* iv, iv_len: initialization vector
* tag, tag_len: authentication tag
*/
int crypto_mod_auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
assert(crypto_lib_desc.auth_decrypt != NULL);
assert(data_ptr != NULL);
assert(len != 0U);
assert(key != NULL);
assert(key_len != 0U);
assert(iv != NULL);
assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE));
assert(tag != NULL);
assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE));
return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key,
key_len, key_flags, iv, iv_len, tag,
tag_len);
}
@@ -0,0 +1,306 @@
/*
* Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <string.h>
#include <platform_def.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <drivers/arm/cryptocell/712/crypto_driver.h>
#include <drivers/arm/cryptocell/712/rsa.h>
#include <drivers/arm/cryptocell/712/sbrom_bsv_api.h>
#include <drivers/arm/cryptocell/712/secureboot_base_func.h>
#include <drivers/arm/cryptocell/712/secureboot_gen_defs.h>
#include <drivers/arm/cryptocell/712/util.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include <lib/utils.h>
#include <mbedtls/oid.h>
#include <mbedtls/x509.h>
#define LIB_NAME "CryptoCell 712 SBROM"
#define RSA_SALT_LEN 32
#define RSA_EXPONENT 65537
/*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING
* }
*
* RSASSA-PSS-params ::= SEQUENCE {
* hashAlgorithm [0] HashAlgorithm,
* maskGenAlgorithm [1] MaskGenAlgorithm,
* saltLength [2] INTEGER,
* trailerField [3] TrailerField DEFAULT trailerFieldBC
* }
*/
/*
* Initialize the library and export the descriptor
*/
static void init(void)
{
CCError_t ret;
uint32_t lcs;
/* Initialize CC SBROM */
ret = CC_BsvSbromInit((uintptr_t)PLAT_CRYPTOCELL_BASE);
if (ret != CC_OK) {
ERROR("CryptoCell CC_BsvSbromInit() error %x\n", ret);
panic();
}
/* Initialize lifecycle state */
ret = CC_BsvLcsGetAndInit((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs);
if (ret != CC_OK) {
ERROR("CryptoCell CC_BsvLcsGetAndInit() error %x\n", ret);
panic();
}
/* If the lifecyclestate is `SD`, then stop further execution */
if (lcs == CC_BSV_SECURITY_DISABLED_LCS) {
ERROR("CryptoCell LCS is security-disabled\n");
panic();
}
}
/*
* Verify a signature.
*
* Parameters are passed using the DER encoding format following the ASN.1
* structures detailed above.
*/
static int verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
CCError_t error;
CCSbNParams_t pk;
CCSbSignature_t signature;
int rc, exp;
mbedtls_asn1_buf sig_oid, alg_oid, params;
mbedtls_md_type_t md_alg;
mbedtls_pk_type_t pk_alg;
mbedtls_pk_rsassa_pss_options pss_opts;
size_t len;
uint8_t *p, *end;
/* Temp buf to store the public key modulo (N) in LE format */
uint32_t RevN[SB_RSA_MOD_SIZE_IN_WORDS];
/* Verify the signature algorithm */
/* Get pointers to signature OID and parameters */
p = sig_alg;
end = p + sig_alg_len;
rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &params);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* Get the actual signature algorithm (MD + PK) */
rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* The CryptoCell only supports RSASSA-PSS signature */
if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE)
return CRYPTO_ERR_SIGNATURE;
/* Verify the RSASSA-PSS params */
/* The trailer field is verified to be 0xBC internally by this API */
rc = mbedtls_x509_get_rsassa_pss_params(&params, &md_alg,
&pss_opts.mgf1_hash_id,
&pss_opts.expected_salt_len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* The CryptoCell only supports SHA256 as hash algorithm */
if (md_alg != MBEDTLS_MD_SHA256 || pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256)
return CRYPTO_ERR_SIGNATURE;
if (pss_opts.expected_salt_len != RSA_SALT_LEN)
return CRYPTO_ERR_SIGNATURE;
/* Parse the public key */
p = pk_ptr;
end = p + pk_len;
rc = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
end = p + len;
rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0)
return CRYPTO_ERR_SIGNATURE;
if (pk_alg != MBEDTLS_PK_RSA)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (*p == 0) {
p++; len--;
}
if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end))
return CRYPTO_ERR_SIGNATURE;
/*
* The CCSbVerifySignature() API expects N and Np in BE format and
* the signature in LE format. Copy N from certificate.
*/
memcpy(pk.N, p, RSA_MOD_SIZE_IN_BYTES);
/* Verify the RSA exponent */
p += len;
rc = mbedtls_asn1_get_int(&p, end, &exp);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (exp != RSA_EXPONENT)
return CRYPTO_ERR_SIGNATURE;
/*
* Calculate the Np (Barrett n' value). The RSA_CalcNp() API expects
* N in LE format. Hence reverse N into a temporary buffer `RevN`.
*/
UTIL_ReverseMemCopy((uint8_t *)RevN, (uint8_t *)pk.N, sizeof(RevN));
RSA_CalcNp((uintptr_t)PLAT_CRYPTOCELL_BASE, RevN, pk.Np);
/* Np is in LE format. Reverse it to BE */
UTIL_ReverseBuff((uint8_t *)pk.Np, sizeof(pk.Np));
/* Get the signature (bitstring) */
p = sig_ptr;
end = p + sig_len;
rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end))
return CRYPTO_ERR_SIGNATURE;
/*
* The signature is BE format. Convert it to LE before calling
* CCSbVerifySignature().
*/
UTIL_ReverseMemCopy((uint8_t *)signature.sig, p, RSA_MOD_SIZE_IN_BYTES);
/*
* CryptoCell utilises DMA internally to transfer data. Flush the data
* from caches.
*/
flush_dcache_range((uintptr_t)data_ptr, data_len);
/* Verify the signature */
error = CCSbVerifySignature((uintptr_t)PLAT_CRYPTOCELL_BASE,
(uint32_t *)data_ptr, &pk, &signature,
data_len, RSA_PSS);
if (error != CC_OK)
return CRYPTO_ERR_SIGNATURE;
/* Signature verification success */
return CRYPTO_SUCCESS;
}
/*
* Match a hash
*
* Digest info is passed in DER format following the ASN.1 structure detailed
* above.
*/
static int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len)
{
mbedtls_asn1_buf hash_oid, params;
mbedtls_md_type_t md_alg;
uint8_t *p, *end, *hash;
CCHashResult_t pubKeyHash;
size_t len;
int rc;
CCError_t error;
/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
p = digest_info_ptr;
end = p + digest_info_len;
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Get the hash algorithm */
rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
if (rc != 0)
return CRYPTO_ERR_HASH;
rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Verify that hash algorithm is SHA256 */
if (md_alg != MBEDTLS_MD_SHA256)
return CRYPTO_ERR_HASH;
/* Hash should be octet string type */
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Length of hash must match the algorithm's size */
if (len != HASH_RESULT_SIZE_IN_BYTES)
return CRYPTO_ERR_HASH;
/*
* CryptoCell utilises DMA internally to transfer data. Flush the data
* from caches.
*/
flush_dcache_range((uintptr_t)data_ptr, data_len);
hash = p;
error = SBROM_CryptoHash((uintptr_t)PLAT_CRYPTOCELL_BASE,
(uintptr_t)data_ptr, data_len, pubKeyHash);
if (error != CC_OK)
return CRYPTO_ERR_HASH;
rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES);
if (rc != 0)
return CRYPTO_ERR_HASH;
return CRYPTO_SUCCESS;
}
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
@@ -0,0 +1,113 @@
/*
* Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <platform_def.h>
#include <plat/common/platform.h>
#include <tools_share/tbbr_oid.h>
#include <common/debug.h>
#include <drivers/arm/cryptocell/712/sbrom_bsv_api.h>
#include <drivers/arm/cryptocell/712/nvm.h>
#include <drivers/arm/cryptocell/712/nvm_otp.h>
/*
* Return the ROTPK hash
*
* dst: buffer into which the ROTPK hash will be copied into
* len: length of the provided buffer, which must be at least enough for a
* SHA256 hash
* flags: a pointer to integer that will be set to indicate the ROTPK status
*
* Return: 0 = success, Otherwise = error
*/
int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags)
{
CCError_t error;
uint32_t lcs;
assert(dst != NULL);
assert(len >= HASH_RESULT_SIZE_IN_WORDS);
assert(flags != NULL);
error = NVM_GetLCS(PLAT_CRYPTOCELL_BASE, &lcs);
if (error != CC_OK)
return 1;
/* If the lifecycle state is `SD`, return failure */
if (lcs == CC_BSV_SECURITY_DISABLED_LCS)
return 1;
/*
* If the lifecycle state is `CM` or `DM`, ROTPK shouldn't be verified.
* Return success after setting ROTPK_NOT_DEPLOYED flag
*/
if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) ||
(lcs == CC_BSV_DEVICE_MANUFACTURE_LCS)) {
*flags = ROTPK_NOT_DEPLOYED;
return 0;
}
/* Copy the DER header */
error = NVM_ReadHASHPubKey(PLAT_CRYPTOCELL_BASE,
CC_SB_HASH_BOOT_KEY_256B,
(uint32_t *)dst, HASH_RESULT_SIZE_IN_WORDS);
if (error != CC_OK)
return 1;
*flags = ROTPK_IS_HASH;
return 0;
}
/*
* Return the non-volatile counter value stored in the platform. The cookie
* specifies the OID of the counter in the certificate.
*
* Return: 0 = success, Otherwise = error
*/
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
{
CCError_t error = CC_FAIL;
if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_COUNTER1, nv_ctr);
} else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_COUNTER2, nv_ctr);
}
return (error != CC_OK);
}
/*
* Store a new non-volatile counter value in the counter specified by the OID
* in the cookie. This function is not expected to be called if the Lifecycle
* state is RMA as the values in the certificate are expected to always match
* the nvcounter values. But if called when the LCS is RMA, the underlying
* helper functions will return success but without updating the counter.
*
* Return: 0 = success, Otherwise = error
*/
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
{
CCError_t error = CC_FAIL;
if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_COUNTER1, nv_ctr);
} else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_COUNTER2, nv_ctr);
}
return (error != CC_OK);
}
@@ -0,0 +1,276 @@
/*
* Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <platform_def.h>
#include <drivers/arm/cryptocell/713/bsv_api.h>
#include <drivers/arm/cryptocell/713/bsv_crypto_asym_api.h>
#include <drivers/auth/crypto_mod.h>
#include <mbedtls/oid.h>
#include <mbedtls/x509.h>
#define LIB_NAME "CryptoCell 713 SBROM"
#define RSA_SALT_LEN 32
#define RSA_EXPONENT 65537
/*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING
* }
*
* RSASSA-PSS-params ::= SEQUENCE {
* hashAlgorithm [0] HashAlgorithm,
* maskGenAlgorithm [1] MaskGenAlgorithm,
* saltLength [2] INTEGER,
* trailerField [3] TrailerField DEFAULT trailerFieldBC
* }
*/
/*
* Initialize the library and export the descriptor
*/
static void init(void)
{
CCError_t ret;
uint32_t lcs;
/* Initialize CC SBROM */
ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE);
if (ret != CC_OK) {
ERROR("CryptoCell CC_BsvInit() error %x\n", ret);
panic();
}
/* Initialize lifecycle state */
ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs);
if (ret != CC_OK) {
ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret);
panic();
}
}
/*
* Verify a signature.
*
* Parameters are passed using the DER encoding format following the ASN.1
* structures detailed above.
*/
static int verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
CCError_t error;
CCBsvNBuff_t NBuff;
CCBsvSignature_t signature;
int rc, exp;
mbedtls_asn1_buf sig_oid, alg_oid, params;
mbedtls_md_type_t md_alg;
mbedtls_pk_type_t pk_alg;
mbedtls_pk_rsassa_pss_options pss_opts;
size_t len;
uint8_t *p, *end;
CCHashResult_t digest;
CCBool_t is_verified;
/* This is a rather large array, we don't want it on stack */
static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE];
/* Verify the signature algorithm */
/* Get pointers to signature OID and parameters */
p = sig_alg;
end = p + sig_alg_len;
rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &params);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* Get the actual signature algorithm (MD + PK) */
rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* The CryptoCell only supports RSASSA-PSS signature */
if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE)
return CRYPTO_ERR_SIGNATURE;
/* Verify the RSASSA-PSS params */
/* The trailer field is verified to be 0xBC internally by this API */
rc = mbedtls_x509_get_rsassa_pss_params(&params, &md_alg,
&pss_opts.mgf1_hash_id,
&pss_opts.expected_salt_len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
/* The CryptoCell only supports SHA256 as hash algorithm */
if (md_alg != MBEDTLS_MD_SHA256 ||
pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256)
return CRYPTO_ERR_SIGNATURE;
if (pss_opts.expected_salt_len != RSA_SALT_LEN)
return CRYPTO_ERR_SIGNATURE;
/* Parse the public key */
p = pk_ptr;
end = p + pk_len;
rc = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
end = p + len;
rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0)
return CRYPTO_ERR_SIGNATURE;
if (pk_alg != MBEDTLS_PK_RSA)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (*p == 0) {
p++; len--;
}
if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end))
return CRYPTO_ERR_SIGNATURE;
/*
* Copy N from certificate.
*/
memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);
/* Verify the RSA exponent */
p += len;
rc = mbedtls_asn1_get_int(&p, end, &exp);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (exp != RSA_EXPONENT)
return CRYPTO_ERR_SIGNATURE;
/* Get the signature (bitstring) */
p = sig_ptr;
end = p + sig_len;
rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
if (rc != 0)
return CRYPTO_ERR_SIGNATURE;
if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end))
return CRYPTO_ERR_SIGNATURE;
/*
* Copy the signature (in BE format)
*/
memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);
error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE,
data_ptr, data_len, digest);
if (error != CC_OK)
return CRYPTO_ERR_SIGNATURE;
/* Verify the signature */
error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff,
NULL, signature, digest, workspace,
BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified);
if ((error != CC_OK) || (is_verified != CC_TRUE))
return CRYPTO_ERR_SIGNATURE;
/* Signature verification success */
return CRYPTO_SUCCESS;
}
/*
* Match a hash
*
* Digest info is passed in DER format following the ASN.1 structure detailed
* above.
*/
static int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len)
{
mbedtls_asn1_buf hash_oid, params;
mbedtls_md_type_t md_alg;
uint8_t *p, *end, *hash;
CCHashResult_t pubKeyHash;
size_t len;
int rc;
CCError_t error;
/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
p = digest_info_ptr;
end = p + digest_info_len;
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Get the hash algorithm */
rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
if (rc != 0)
return CRYPTO_ERR_HASH;
rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Verify that hash algorithm is SHA256 */
if (md_alg != MBEDTLS_MD_SHA256)
return CRYPTO_ERR_HASH;
/* Hash should be octet string type */
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (rc != 0)
return CRYPTO_ERR_HASH;
/* Length of hash must match the algorithm's size */
if (len != HASH_RESULT_SIZE_IN_BYTES)
return CRYPTO_ERR_HASH;
hash = p;
error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr,
data_len, pubKeyHash);
if (error != CC_OK)
return CRYPTO_ERR_HASH;
rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES);
if (rc != 0)
return CRYPTO_ERR_HASH;
return CRYPTO_SUCCESS;
}
/*
* Register crypto library descriptor
*/
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
@@ -0,0 +1,109 @@
/*
* Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
#include <plat/common/platform.h>
#include <tools_share/tbbr_oid.h>
#include <lib/libc/endian.h>
#include <drivers/arm/cryptocell/713/bsv_api.h>
#include <drivers/arm/cryptocell/713/bsv_error.h>
/*
* Return the ROTPK hash
*
* Return: 0 = success, Otherwise = error
*/
int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags)
{
CCError_t error;
uint32_t lcs;
int i;
uint32_t *key = (uint32_t *)dst;
assert(dst != NULL);
assert(len >= HASH_RESULT_SIZE_IN_WORDS);
assert(flags != NULL);
error = CC_BsvLcsGet(PLAT_CRYPTOCELL_BASE, &lcs);
if (error != CC_OK)
return 1;
if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || (lcs == CC_BSV_RMA_LCS)) {
*flags = ROTPK_NOT_DEPLOYED;
return 0;
}
error = CC_BsvPubKeyHashGet(PLAT_CRYPTOCELL_BASE,
CC_SB_HASH_BOOT_KEY_256B,
key, HASH_RESULT_SIZE_IN_WORDS);
if (error == CC_BSV_HASH_NOT_PROGRAMMED_ERR) {
*flags = ROTPK_NOT_DEPLOYED;
return 0;
}
if (error == CC_OK) {
/* Keys are stored in OTP in little-endian format */
for (i = 0; i < HASH_RESULT_SIZE_IN_WORDS; i++)
key[i] = le32toh(key[i]);
*flags = ROTPK_IS_HASH;
return 0;
}
return 1;
}
/*
* Return the non-volatile counter value stored in the platform. The cookie
* specifies the OID of the counter in the certificate.
*
* Return: 0 = success, Otherwise = error
*/
int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr)
{
CCError_t error = CC_FAIL;
if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_TRUSTED, nv_ctr);
} else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_NON_TRUSTED, nv_ctr);
}
return (error != CC_OK);
}
/*
* Store a new non-volatile counter value in the counter specified by the OID
* in the cookie. This function is not expected to be called if the Lifecycle
* state is RMA as the values in the certificate are expected to always match
* the nvcounter values. But if called when the LCS is RMA, the underlying
* helper functions will return success but without updating the counter.
*
* Return: 0 = success, Otherwise = error
*/
int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr)
{
CCError_t error = CC_FAIL;
if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_TRUSTED, nv_ctr);
} else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) {
error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE,
CC_SW_VERSION_NON_TRUSTED, nv_ctr);
}
return (error != CC_OK);
}
@@ -0,0 +1,40 @@
#
# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include drivers/auth/mbedtls/mbedtls_common.mk
# The algorithm is RSA when using Cryptocell crypto driver
TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA
# Needs to be set to drive mbed TLS configuration correctly
$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID))
$(eval $(call add_define,KEY_SIZE))
# CCSBROM_LIB_PATH must be set to the Cryptocell SBROM library path
ifeq (${CCSBROM_LIB_PATH},)
$(error Error: CCSBROM_LIB_PATH not set)
endif
CRYPTOCELL_VERSION ?= 712
ifeq (${CRYPTOCELL_VERSION},712)
CCSBROM_LIB_FILENAME := cc_712sbromx509
else ifeq (${CRYPTOCELL_VERSION},713)
CCSBROM_LIB_FILENAME := cc_713bsv
else
$(error Error: CRYPTOCELL_VERSION set to invalid version)
endif
CRYPTOCELL_SRC_DIR := drivers/auth/cryptocell/${CRYPTOCELL_VERSION}/
CRYPTOCELL_SOURCES := ${CRYPTOCELL_SRC_DIR}/cryptocell_crypto.c \
${CRYPTOCELL_SRC_DIR}/cryptocell_plat_helpers.c
TF_LDFLAGS += -L$(CCSBROM_LIB_PATH)
LDLIBS += -l$(CCSBROM_LIB_FILENAME)
BL1_SOURCES += ${CRYPTOCELL_SOURCES}
BL2_SOURCES += ${CRYPTOCELL_SOURCES}
@@ -0,0 +1,959 @@
/*
* Copyright (c) 2020-2022, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <platform_def.h>
#include MBEDTLS_CONFIG_FILE
#include <drivers/auth/auth_mod.h>
#include <tools_share/dualroot_oid.h>
/*
* Allocate static buffers to store the authentication parameters extracted from
* the certificates.
*/
static unsigned char fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char hw_config_hash_buf[HASH_DER_LEN];
static unsigned char scp_fw_hash_buf[HASH_DER_LEN];
static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
#ifdef IMAGE_BL2
static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
#if defined(SPD_spmd)
static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
#endif /* SPD_spmd */
static unsigned char trusted_world_pk_buf[PK_DER_LEN];
static unsigned char content_pk_buf[PK_DER_LEN];
#endif
/*
* Parameter type descriptors.
*/
static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, 0);
static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG, 0);
static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG_ALG, 0);
static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_RAW_DATA, 0);
static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
#ifdef IMAGE_BL1
static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, FWU_HASH_OID);
#endif /* IMAGE_BL1 */
#ifdef IMAGE_BL2
static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, PROT_PK_OID);
static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SCP_FW_HASH_OID);
static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
#if defined(SPD_spmd)
static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
#endif /* SPD_spmd */
#endif /* IMAGE_BL2 */
/* BL2 */
static const auth_img_desc_t trusted_boot_fw_cert = {
.img_id = TRUSTED_BOOT_FW_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tb_fw_hash,
.data = {
.ptr = (void *)tb_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tb_fw_config_hash,
.data = {
.ptr = (void *)tb_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &hw_config_hash,
.data = {
.ptr = (void *)hw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &fw_config_hash,
.data = {
.ptr = (void *)fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
#ifdef IMAGE_BL1
static const auth_img_desc_t bl2_image = {
.img_id = BL2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_hash
}
}
}
};
#endif /* IMAGE_BL1 */
/* HW Config */
static const auth_img_desc_t hw_config = {
.img_id = HW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &hw_config_hash
}
}
}
};
/* TB FW Config */
#ifdef IMAGE_BL1
static const auth_img_desc_t tb_fw_config = {
.img_id = TB_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_config_hash
}
}
}
};
static const auth_img_desc_t fw_config = {
.img_id = FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &fw_config_hash
}
}
}
};
#endif /* IMAGE_BL1 */
#ifdef IMAGE_BL2
/* Trusted key certificate */
static const auth_img_desc_t trusted_key_cert = {
.img_id = TRUSTED_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &trusted_world_pk,
.data = {
.ptr = (void *)trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
},
}
};
/* SCP Firmware */
static const auth_img_desc_t scp_fw_key_cert = {
.img_id = SCP_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t scp_fw_content_cert = {
.img_id = SCP_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &scp_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &scp_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_fw_hash,
.data = {
.ptr = (void *)scp_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t scp_bl2_image = {
.img_id = SCP_BL2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &scp_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &scp_fw_hash
}
}
}
};
/* SoC Firmware */
static const auth_img_desc_t soc_fw_key_cert = {
.img_id = SOC_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t soc_fw_content_cert = {
.img_id = SOC_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &soc_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &soc_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_hash,
.data = {
.ptr = (void *)soc_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &soc_fw_config_hash,
.data = {
.ptr = (void *)soc_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl31_image = {
.img_id = BL31_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &soc_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_hash
}
}
}
};
/* SOC FW Config */
static const auth_img_desc_t soc_fw_config = {
.img_id = SOC_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &soc_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_config_hash
}
}
}
};
/* Trusted OS Firmware */
static const auth_img_desc_t trusted_os_fw_key_cert = {
.img_id = TRUSTED_OS_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tos_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t trusted_os_fw_content_cert = {
.img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_os_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &tos_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tos_fw_hash,
.data = {
.ptr = (void *)tos_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tos_fw_extra1_hash,
.data = {
.ptr = (void *)tos_fw_extra1_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &tos_fw_extra2_hash,
.data = {
.ptr = (void *)tos_fw_extra2_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &tos_fw_config_hash,
.data = {
.ptr = (void *)tos_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl32_image = {
.img_id = BL32_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_hash
}
}
}
};
static const auth_img_desc_t bl32_extra1_image = {
.img_id = BL32_EXTRA1_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_extra1_hash
}
}
}
};
static const auth_img_desc_t bl32_extra2_image = {
.img_id = BL32_EXTRA2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_extra2_hash
}
}
}
};
/* TOS FW Config */
static const auth_img_desc_t tos_fw_config = {
.img_id = TOS_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_config_hash
}
}
}
};
/* Non-Trusted Firmware */
static const auth_img_desc_t non_trusted_fw_content_cert = {
.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL, /* Root certificate. */
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &prot_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_world_bl_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &nt_fw_config_hash,
.data = {
.ptr = (void *)nt_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl33_image = {
.img_id = BL33_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_world_bl_hash
}
}
}
};
/* NT FW Config */
static const auth_img_desc_t nt_fw_config = {
.img_id = NT_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_fw_config_hash
}
}
}
};
/*
* Secure Partitions
*/
#if defined(SPD_spmd)
static const auth_img_desc_t sip_sp_content_cert = {
.img_id = SIP_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &sp_pkg1_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[0],
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &sp_pkg2_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[1],
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &sp_pkg3_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[2],
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &sp_pkg4_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[3],
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
DEFINE_SIP_SP_PKG(1);
DEFINE_SIP_SP_PKG(2);
DEFINE_SIP_SP_PKG(3);
DEFINE_SIP_SP_PKG(4);
static const auth_img_desc_t plat_sp_content_cert = {
.img_id = PLAT_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &prot_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &sp_pkg5_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[4],
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &sp_pkg6_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[5],
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &sp_pkg7_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[6],
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &sp_pkg8_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[7],
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
DEFINE_PLAT_SP_PKG(5);
DEFINE_PLAT_SP_PKG(6);
DEFINE_PLAT_SP_PKG(7);
DEFINE_PLAT_SP_PKG(8);
#endif /* SPD_spmd */
#else /* IMAGE_BL2 */
/* FWU auth descriptor */
static const auth_img_desc_t fwu_cert = {
.img_id = FWU_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_bl2u_hash,
.data = {
.ptr = (void *)scp_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &bl2u_hash,
.data = {
.ptr = (void *)tb_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &ns_bl2u_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
/* SCP_BL2U */
static const auth_img_desc_t scp_bl2u_image = {
.img_id = SCP_BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &scp_bl2u_hash
}
}
}
};
/* BL2U */
static const auth_img_desc_t bl2u_image = {
.img_id = BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &bl2u_hash
}
}
}
};
/* NS_BL2U */
static const auth_img_desc_t ns_bl2u_image = {
.img_id = NS_BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &ns_bl2u_hash
}
}
}
};
#endif /* IMAGE_BL2 */
/*
* Chain of trust definition
*/
#ifdef IMAGE_BL1
static const auth_img_desc_t * const cot_desc[] = {
[TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
[BL2_IMAGE_ID] = &bl2_image,
[HW_CONFIG_ID] = &hw_config,
[TB_FW_CONFIG_ID] = &tb_fw_config,
[FW_CONFIG_ID] = &fw_config,
[FWU_CERT_ID] = &fwu_cert,
[SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
[BL2U_IMAGE_ID] = &bl2u_image,
[NS_BL2U_IMAGE_ID] = &ns_bl2u_image
};
#else /* IMAGE_BL2 */
static const auth_img_desc_t * const cot_desc[] = {
[TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
[HW_CONFIG_ID] = &hw_config,
[TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
[SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert,
[SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert,
[SCP_BL2_IMAGE_ID] = &scp_bl2_image,
[SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
[SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
[BL31_IMAGE_ID] = &bl31_image,
[SOC_FW_CONFIG_ID] = &soc_fw_config,
[TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
[TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
[BL32_IMAGE_ID] = &bl32_image,
[BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
[BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
[TOS_FW_CONFIG_ID] = &tos_fw_config,
[NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
[BL33_IMAGE_ID] = &bl33_image,
[NT_FW_CONFIG_ID] = &nt_fw_config,
#if defined(SPD_spmd)
[SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
[PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert,
[SP_PKG1_ID] = &sp_pkg1,
[SP_PKG2_ID] = &sp_pkg2,
[SP_PKG3_ID] = &sp_pkg3,
[SP_PKG4_ID] = &sp_pkg4,
[SP_PKG5_ID] = &sp_pkg5,
[SP_PKG6_ID] = &sp_pkg6,
[SP_PKG7_ID] = &sp_pkg7,
[SP_PKG8_ID] = &sp_pkg8,
#endif
};
#endif
/* Register the CoT in the authentication module */
REGISTER_COT(cot_desc);
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <limits.h>
#include <stdint.h>
#include <string.h>
#include <common/debug.h>
#include <drivers/auth/auth_common.h>
#include <drivers/auth/img_parser_mod.h>
#include <lib/utils_def.h>
IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_START__, PARSER_LIB_DESCS_START);
IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_END__, PARSER_LIB_DESCS_END);
static unsigned int parser_lib_indices[IMG_MAX_TYPES];
static img_parser_lib_desc_t *parser_lib_descs;
#define INVALID_IDX UINT_MAX
static void validate_desc(img_parser_lib_desc_t *desc)
{
assert(desc != NULL);
assert(desc->init != NULL);
assert(desc->name != NULL);
assert(desc->check_integrity != NULL);
assert(desc->get_auth_param != NULL);
}
void img_parser_init(void)
{
unsigned int index, mod_num;
/* Initialise internal variables to invalid state */
for (index = 0; index < IMG_MAX_TYPES; index++) {
parser_lib_indices[index] = INVALID_IDX;
}
/* Calculate how many image parsers are registered. At least one parser
* must be present */
mod_num = PARSER_LIB_DESCS_END - PARSER_LIB_DESCS_START;
mod_num /= sizeof(img_parser_lib_desc_t);
assert(mod_num > 0);
parser_lib_descs = (img_parser_lib_desc_t *) PARSER_LIB_DESCS_START;
for (index = 0; index < mod_num; index++) {
/* Check that the image parser library descriptor is valid */
validate_desc(&parser_lib_descs[index]);
/* Initialize image parser */
parser_lib_descs[index].init();
/* Ensure only one parser is registered for each image type */
assert(parser_lib_indices[parser_lib_descs[index].img_type] ==
INVALID_IDX);
/* Keep the index of this hash calculator */
parser_lib_indices[parser_lib_descs[index].img_type] = index;
}
}
int img_parser_check_integrity(img_type_t img_type,
void *img_ptr, unsigned int img_len)
{
unsigned int idx;
assert(img_ptr != NULL);
assert(img_len != 0);
/* No integrity checks on raw images */
if (img_type == IMG_RAW) {
return IMG_PARSER_OK;
}
/* Find the index of the required image parser */
idx = parser_lib_indices[img_type];
assert(idx != INVALID_IDX);
/* Call the function to check the image integrity */
return parser_lib_descs[idx].check_integrity(img_ptr, img_len);
}
/*
* Extract an authentication parameter from an image
*
* Parameters:
* img_type: image type (certificate, raw image, etc)
* type_desc: provides info to obtain the parameter
* img_ptr: pointer to image data
* img_len: image length
* param_ptr: [out] stores a pointer to the parameter
* param_len: [out] stores the length of the parameter
*/
int img_parser_get_auth_param(img_type_t img_type,
const auth_param_type_desc_t *type_desc,
void *img_ptr, unsigned int img_len,
void **param_ptr, unsigned int *param_len)
{
unsigned int idx;
assert(type_desc != NULL);
assert(img_ptr != NULL);
assert(img_len != 0);
assert(param_ptr != NULL);
assert(param_len != NULL);
/* In a raw image we can only get the data itself */
if (img_type == IMG_RAW) {
assert(type_desc->type == AUTH_PARAM_RAW_DATA);
*param_ptr = img_ptr;
*param_len = img_len;
return IMG_PARSER_OK;
}
/* Find the index of the required image parser library */
idx = parser_lib_indices[img_type];
assert(idx != INVALID_IDX);
/* Call the function to obtain the parameter */
return parser_lib_descs[idx].get_auth_param(type_desc, img_ptr, img_len,
param_ptr, param_len);
}
@@ -0,0 +1,72 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
/* mbed TLS headers */
#include <mbedtls/memory_buffer_alloc.h>
#include <mbedtls/platform.h>
#include <common/debug.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include MBEDTLS_CONFIG_FILE
#include <plat/common/platform.h>
static void cleanup(void)
{
ERROR("EXIT from BL2\n");
panic();
}
/*
* mbed TLS initialization function
*/
void mbedtls_init(void)
{
static int ready;
void *heap_addr;
size_t heap_size = 0;
int err;
if (!ready) {
if (atexit(cleanup))
panic();
err = plat_get_mbedtls_heap(&heap_addr, &heap_size);
/* Ensure heap setup is proper */
if (err < 0) {
ERROR("Mbed TLS failed to get a heap\n");
panic();
}
assert(heap_size >= TF_MBEDTLS_HEAP_SIZE);
/* Initialize the mbed TLS heap */
mbedtls_memory_buffer_alloc_init(heap_addr, heap_size);
#ifdef MBEDTLS_PLATFORM_SNPRINTF_ALT
mbedtls_platform_set_snprintf(snprintf);
#endif
ready = 1;
}
}
/*
* The following helper function simply returns the default allocated heap.
* It can be used by platforms for their plat_get_mbedtls_heap() implementation.
*/
int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size)
{
static unsigned char heap[TF_MBEDTLS_HEAP_SIZE];
assert(heap_addr != NULL);
assert(heap_size != NULL);
*heap_addr = heap;
*heap_size = sizeof(heap);
return 0;
}
@@ -0,0 +1,111 @@
#
# Copyright (c) 2015-2022, Arm Limited. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
ifneq (${MBEDTLS_COMMON_MK},1)
MBEDTLS_COMMON_MK := 1
# MBEDTLS_DIR must be set to the mbed TLS main directory (it must contain
# the 'include' and 'library' subdirectories).
ifeq (${MBEDTLS_DIR},)
$(error Error: MBEDTLS_DIR not set)
endif
MBEDTLS_INC = -I${MBEDTLS_DIR}/include
# Specify mbed TLS configuration file
MBEDTLS_CONFIG_FILE ?= "<drivers/auth/mbedtls/mbedtls_config.h>"
$(eval $(call add_define,MBEDTLS_CONFIG_FILE))
MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c
LIBMBEDTLS_SRCS := $(addprefix ${MBEDTLS_DIR}/library/, \
aes.c \
asn1parse.c \
asn1write.c \
cipher.c \
cipher_wrap.c \
memory_buffer_alloc.c \
oid.c \
platform.c \
platform_util.c \
bignum.c \
gcm.c \
md.c \
pk.c \
pk_wrap.c \
pkparse.c \
pkwrite.c \
sha256.c \
sha512.c \
ecdsa.c \
ecp_curves.c \
ecp.c \
rsa.c \
rsa_internal.c \
x509.c \
x509_crt.c \
constant_time.c \
)
# The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key
# algorithm to use. If the variable is not defined, select it based on
# algorithm used for key generation `KEY_ALG`. If `KEY_ALG` is not defined,
# then it is set to `rsa`.
ifeq (${TF_MBEDTLS_KEY_ALG},)
ifeq (${KEY_ALG}, ecdsa)
TF_MBEDTLS_KEY_ALG := ecdsa
else
TF_MBEDTLS_KEY_ALG := rsa
endif
endif
ifeq (${TF_MBEDTLS_KEY_SIZE},)
ifneq ($(findstring rsa,${TF_MBEDTLS_KEY_ALG}),)
ifeq (${KEY_SIZE},)
TF_MBEDTLS_KEY_SIZE := 2048
else
TF_MBEDTLS_KEY_SIZE := ${KEY_SIZE}
endif
endif
endif
ifeq (${HASH_ALG}, sha384)
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA384
else ifeq (${HASH_ALG}, sha512)
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512
else
TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256
endif
ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa)
TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_ECDSA
else ifeq (${TF_MBEDTLS_KEY_ALG},rsa)
TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA
else ifeq (${TF_MBEDTLS_KEY_ALG},rsa+ecdsa)
TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA_AND_ECDSA
else
$(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS")
endif
ifeq (${DECRYPTION_SUPPORT}, aes_gcm)
TF_MBEDTLS_USE_AES_GCM := 1
else
TF_MBEDTLS_USE_AES_GCM := 0
endif
# Needs to be set to drive mbed TLS configuration correctly
$(eval $(call add_defines,\
$(sort \
TF_MBEDTLS_KEY_ALG_ID \
TF_MBEDTLS_KEY_SIZE \
TF_MBEDTLS_HASH_ALG_ID \
TF_MBEDTLS_USE_AES_GCM \
)))
$(eval $(call MAKE_LIB,mbedtls))
endif
@@ -0,0 +1,394 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stddef.h>
#include <string.h>
/* mbed TLS headers */
#include <mbedtls/gcm.h>
#include <mbedtls/md.h>
#include <mbedtls/memory_buffer_alloc.h>
#include <mbedtls/oid.h>
#include <mbedtls/platform.h>
#include <mbedtls/x509.h>
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include <drivers/auth/mbedtls/mbedtls_config.h>
#include <plat/common/platform.h>
#define LIB_NAME "mbed TLS"
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/*
* CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available
* so make sure that mbed TLS MD maximum size must be lesser than this.
*/
CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE,
assert_mbedtls_md_size_overflow);
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
/*
* AlgorithmIdentifier ::= SEQUENCE {
* algorithm OBJECT IDENTIFIER,
* parameters ANY DEFINED BY algorithm OPTIONAL
* }
*
* SubjectPublicKeyInfo ::= SEQUENCE {
* algorithm AlgorithmIdentifier,
* subjectPublicKey BIT STRING
* }
*
* DigestInfo ::= SEQUENCE {
* digestAlgorithm AlgorithmIdentifier,
* digest OCTET STRING
* }
*/
/*
* Initialize the library and export the descriptor
*/
static void init(void)
{
/* Initialize mbed TLS */
mbedtls_init();
}
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/*
* Verify a signature.
*
* Parameters are passed using the DER encoding format following the ASN.1
* structures detailed above.
*/
static int verify_signature(void *data_ptr, unsigned int data_len,
void *sig_ptr, unsigned int sig_len,
void *sig_alg, unsigned int sig_alg_len,
void *pk_ptr, unsigned int pk_len)
{
mbedtls_asn1_buf sig_oid, sig_params;
mbedtls_asn1_buf signature;
mbedtls_md_type_t md_alg;
mbedtls_pk_type_t pk_alg;
mbedtls_pk_context pk = {0};
int rc;
void *sig_opts = NULL;
const mbedtls_md_info_t *md_info;
unsigned char *p, *end;
unsigned char hash[MBEDTLS_MD_MAX_SIZE];
/* Get pointers to signature OID and parameters */
p = (unsigned char *)sig_alg;
end = (unsigned char *)(p + sig_alg_len);
rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
if (rc != 0) {
return CRYPTO_ERR_SIGNATURE;
}
/* Get the actual signature algorithm (MD + PK) */
rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
if (rc != 0) {
return CRYPTO_ERR_SIGNATURE;
}
/* Parse the public key */
mbedtls_pk_init(&pk);
p = (unsigned char *)pk_ptr;
end = (unsigned char *)(p + pk_len);
rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end2;
}
/* Get the signature (bitstring) */
p = (unsigned char *)sig_ptr;
end = (unsigned char *)(p + sig_len);
signature.tag = *p;
rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end1;
}
signature.p = p;
/* Calculate the hash of the data */
md_info = mbedtls_md_info_from_type(md_alg);
if (md_info == NULL) {
rc = CRYPTO_ERR_SIGNATURE;
goto end1;
}
p = (unsigned char *)data_ptr;
rc = mbedtls_md(md_info, p, data_len, hash);
if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end1;
}
/* Verify the signature */
rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
mbedtls_md_get_size(md_info),
signature.p, signature.len);
if (rc != 0) {
rc = CRYPTO_ERR_SIGNATURE;
goto end1;
}
/* Signature verification success */
rc = CRYPTO_SUCCESS;
end1:
mbedtls_pk_free(&pk);
end2:
mbedtls_free(sig_opts);
return rc;
}
/*
* Match a hash
*
* Digest info is passed in DER format following the ASN.1 structure detailed
* above.
*/
static int verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr, unsigned int digest_info_len)
{
mbedtls_asn1_buf hash_oid, params;
mbedtls_md_type_t md_alg;
const mbedtls_md_info_t *md_info;
unsigned char *p, *end, *hash;
unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
size_t len;
int rc;
/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
p = (unsigned char *)digest_info_ptr;
end = p + digest_info_len;
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
/* Get the hash algorithm */
rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
md_info = mbedtls_md_info_from_type(md_alg);
if (md_info == NULL) {
return CRYPTO_ERR_HASH;
}
/* Hash should be octet string type */
rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
/* Length of hash must match the algorithm's size */
if (len != mbedtls_md_get_size(md_info)) {
return CRYPTO_ERR_HASH;
}
hash = p;
/* Calculate the hash of the data */
p = (unsigned char *)data_ptr;
rc = mbedtls_md(md_info, p, data_len, data_hash);
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
/* Compare values */
rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
if (rc != 0) {
return CRYPTO_ERR_HASH;
}
return CRYPTO_SUCCESS;
}
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#if CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
/*
* Map a generic crypto message digest algorithm to the corresponding macro used
* by Mbed TLS.
*/
static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo)
{
switch (algo) {
case CRYPTO_MD_SHA512:
return MBEDTLS_MD_SHA512;
case CRYPTO_MD_SHA384:
return MBEDTLS_MD_SHA384;
case CRYPTO_MD_SHA256:
return MBEDTLS_MD_SHA256;
default:
/* Invalid hash algorithm. */
return MBEDTLS_MD_NONE;
}
}
/*
* Calculate a hash
*
* output points to the computed hash
*/
static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr,
unsigned int data_len,
unsigned char output[CRYPTO_MD_MAX_SIZE])
{
const mbedtls_md_info_t *md_info;
md_info = mbedtls_md_info_from_type(md_type(md_algo));
if (md_info == NULL) {
return CRYPTO_ERR_HASH;
}
/*
* Calculate the hash of the data, it is safe to pass the
* 'output' hash buffer pointer considering its size is always
* bigger than or equal to MBEDTLS_MD_MAX_SIZE.
*/
return mbedtls_md(md_info, data_ptr, data_len, output);
}
#endif /* CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY || \
CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
#if TF_MBEDTLS_USE_AES_GCM
/*
* Stack based buffer allocation for decryption operation. It could
* be configured to balance stack usage vs execution speed.
*/
#define DEC_OP_BUF_SIZE 128
static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key,
unsigned int key_len, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
mbedtls_gcm_context ctx;
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
unsigned char buf[DEC_OP_BUF_SIZE];
unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE];
unsigned char *pt = data_ptr;
size_t dec_len;
int diff, i, rc;
mbedtls_gcm_init(&ctx);
rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
while (len > 0) {
dec_len = MIN(sizeof(buf), len);
rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf);
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
memcpy(pt, buf, dec_len);
pt += dec_len;
len -= dec_len;
}
rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf));
if (rc != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
/* Check tag in "constant-time" */
for (diff = 0, i = 0; i < tag_len; i++)
diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i];
if (diff != 0) {
rc = CRYPTO_ERR_DECRYPTION;
goto exit_gcm;
}
/* GCM decryption success */
rc = CRYPTO_SUCCESS;
exit_gcm:
mbedtls_gcm_free(&ctx);
return rc;
}
/*
* Authenticated decryption of an image
*/
static int auth_decrypt(enum crypto_dec_algo dec_algo, void *data_ptr,
size_t len, const void *key, unsigned int key_len,
unsigned int key_flags, const void *iv,
unsigned int iv_len, const void *tag,
unsigned int tag_len)
{
int rc;
assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0);
switch (dec_algo) {
case CRYPTO_GCM_DECRYPT:
rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len,
tag, tag_len);
if (rc != 0)
return rc;
break;
default:
return CRYPTO_ERR_DECRYPTION;
}
return CRYPTO_SUCCESS;
}
#endif /* TF_MBEDTLS_USE_AES_GCM */
/*
* Register crypto library descriptor
*/
#if CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
auth_decrypt);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash,
NULL);
#endif
#elif CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_ONLY
#if TF_MBEDTLS_USE_AES_GCM
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash,
auth_decrypt);
#else
REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
#endif
#elif CRYPTO_SUPPORT == CRYPTO_HASH_CALC_ONLY
REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash);
#endif /* CRYPTO_SUPPORT == CRYPTO_AUTH_VERIFY_AND_HASH_CALC */
@@ -0,0 +1,11 @@
#
# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include drivers/auth/mbedtls/mbedtls_common.mk
MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_crypto.c
@@ -0,0 +1,9 @@
#
# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: BSD-3-Clause
#
include drivers/auth/mbedtls/mbedtls_common.mk
MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_x509_parser.c
@@ -0,0 +1,500 @@
/*
* Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*
* X509 parser based on mbed TLS
*
* This module implements functions to check the integrity of a X509v3
* certificate ASN.1 structure and extract authentication parameters from the
* extensions field, such as an image hash or a public key.
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
/* mbed TLS headers */
#include <mbedtls/asn1.h>
#include <mbedtls/oid.h>
#include <mbedtls/platform.h>
#include <arch_helpers.h>
#include <drivers/auth/img_parser_mod.h>
#include <drivers/auth/mbedtls/mbedtls_common.h>
#include <lib/utils.h>
/* Maximum OID string length ("a.b.c.d.e.f ...") */
#define MAX_OID_STR_LEN 64
#define LIB_NAME "mbed TLS X509v3"
/* Temporary variables to speed up the authentication parameters search. These
* variables are assigned once during the integrity check and used any time an
* authentication parameter is requested, so we do not have to parse the image
* again */
static mbedtls_asn1_buf tbs;
static mbedtls_asn1_buf v3_ext;
static mbedtls_asn1_buf pk;
static mbedtls_asn1_buf sig_alg;
static mbedtls_asn1_buf signature;
/*
* Clear all static temporary variables.
*/
static void clear_temp_vars(void)
{
#define ZERO_AND_CLEAN(x) \
do { \
zeromem(&x, sizeof(x)); \
clean_dcache_range((uintptr_t)&x, sizeof(x)); \
} while (0);
ZERO_AND_CLEAN(tbs)
ZERO_AND_CLEAN(v3_ext);
ZERO_AND_CLEAN(pk);
ZERO_AND_CLEAN(sig_alg);
ZERO_AND_CLEAN(signature);
#undef ZERO_AND_CLEAN
}
/*
* Get X509v3 extension
*
* Global variable 'v3_ext' must point to the extensions region
* in the certificate. No need to check for errors since the image has passed
* the integrity check.
*/
static int get_ext(const char *oid, void **ext, unsigned int *ext_len)
{
int oid_len;
size_t len;
unsigned char *end_ext_data, *end_ext_octet;
unsigned char *p;
const unsigned char *end;
char oid_str[MAX_OID_STR_LEN];
mbedtls_asn1_buf extn_oid;
int is_critical;
assert(oid != NULL);
p = v3_ext.p;
end = v3_ext.p + v3_ext.len;
mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
while (p < end) {
zeromem(&extn_oid, sizeof(extn_oid));
is_critical = 0; /* DEFAULT FALSE */
mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
end_ext_data = p + len;
/* Get extension ID */
extn_oid.tag = *p;
mbedtls_asn1_get_tag(&p, end, &extn_oid.len, MBEDTLS_ASN1_OID);
extn_oid.p = p;
p += extn_oid.len;
/* Get optional critical */
mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
/* Extension data */
mbedtls_asn1_get_tag(&p, end_ext_data, &len,
MBEDTLS_ASN1_OCTET_STRING);
end_ext_octet = p + len;
/* Detect requested extension */
oid_len = mbedtls_oid_get_numeric_string(oid_str,
MAX_OID_STR_LEN,
&extn_oid);
if ((oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) || (oid_len < 0)) {
return IMG_PARSER_ERR;
}
if (((size_t)oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) {
*ext = (void *)p;
*ext_len = (unsigned int)len;
return IMG_PARSER_OK;
}
/* Next */
p = end_ext_octet;
}
return IMG_PARSER_ERR_NOT_FOUND;
}
/*
* Check the integrity of the certificate ASN.1 structure.
*
* Extract the relevant data that will be used later during authentication.
*
* This function doesn't clear the static variables located on the top of this
* file in case of an error. It is only called from check_integrity(), which
* performs the cleanup if necessary.
*/
static int cert_parse(void *img, unsigned int img_len)
{
int ret, is_critical;
size_t len;
unsigned char *p, *end, *crt_end;
mbedtls_asn1_buf sig_alg1, sig_alg2;
p = (unsigned char *)img;
len = img_len;
end = p + len;
/*
* Certificate ::= SEQUENCE {
* tbsCertificate TBSCertificate,
* signatureAlgorithm AlgorithmIdentifier,
* signatureValue BIT STRING }
*/
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
if (len > (size_t)(end - p)) {
return IMG_PARSER_ERR_FORMAT;
}
crt_end = p + len;
/*
* TBSCertificate ::= SEQUENCE {
*/
tbs.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
end = p + len;
tbs.len = end - tbs.p;
/*
* Version ::= INTEGER { v1(0), v2(1), v3(2) }
*/
ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 0);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/*
* CertificateSerialNumber ::= INTEGER
*/
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/*
* signature AlgorithmIdentifier
*/
sig_alg1.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
if ((end - p) < 1) {
return IMG_PARSER_ERR_FORMAT;
}
sig_alg1.len = (p + len) - sig_alg1.p;
p += len;
/*
* issuer Name
*/
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/*
* Validity ::= SEQUENCE {
* notBefore Time,
* notAfter Time }
*
*/
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/*
* subject Name
*/
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/*
* SubjectPublicKeyInfo
*/
pk.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
pk.len = (p + len) - pk.p;
p += len;
/*
* issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL,
*/
ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 1);
if (ret != 0) {
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return IMG_PARSER_ERR_FORMAT;
}
} else {
p += len;
}
/*
* subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL,
*/
ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 2);
if (ret != 0) {
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return IMG_PARSER_ERR_FORMAT;
}
} else {
p += len;
}
/*
* extensions [3] EXPLICIT Extensions OPTIONAL
* }
*
* X.509 and RFC5280 allow omitting the extensions entirely.
* However, in TF-A, a certificate with no extensions would
* always fail later on, as the extensions contain the
* information needed to authenticate the next stage in the
* boot chain. Furthermore, get_ext() assumes that the
* extensions have been parsed into v3_ext, and allowing
* there to be no extensions would pointlessly complicate
* the code. Therefore, just reject certificates without
* extensions. This is also why version 1 and 2 certificates
* are rejected above.
*/
ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONTEXT_SPECIFIC |
MBEDTLS_ASN1_CONSTRUCTED | 3);
if ((ret != 0) || (len != (size_t)(end - p))) {
return IMG_PARSER_ERR_FORMAT;
}
/*
* Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension
* -- must use all remaining bytes in TBSCertificate
*/
v3_ext.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if ((ret != 0) || (len != (size_t)(end - p))) {
return IMG_PARSER_ERR_FORMAT;
}
v3_ext.len = end - v3_ext.p;
/*
* Check extensions integrity. At least one extension is
* required: the ASN.1 specifies a minimum size of 1, and at
* least one extension is needed to authenticate the next stage
* in the boot chain.
*/
do {
unsigned char *end_ext_data;
ret = mbedtls_asn1_get_tag(&p, end, &len,
MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
end_ext_data = p + len;
/* Get extension ID */
ret = mbedtls_asn1_get_tag(&p, end_ext_data, &len, MBEDTLS_ASN1_OID);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
p += len;
/* Get optional critical */
ret = mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical);
if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) {
return IMG_PARSER_ERR_FORMAT;
}
/*
* Data should be octet string type and must use all bytes in
* the Extension.
*/
ret = mbedtls_asn1_get_tag(&p, end_ext_data, &len,
MBEDTLS_ASN1_OCTET_STRING);
if ((ret != 0) || ((p + len) != end_ext_data)) {
return IMG_PARSER_ERR_FORMAT;
}
p = end_ext_data;
} while (p < end);
if (p != end) {
return IMG_PARSER_ERR_FORMAT;
}
end = crt_end;
/*
* }
* -- end of TBSCertificate
*
* signatureAlgorithm AlgorithmIdentifier
*/
sig_alg2.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
MBEDTLS_ASN1_SEQUENCE);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
if ((end - p) < 1) {
return IMG_PARSER_ERR_FORMAT;
}
sig_alg2.len = (p + len) - sig_alg2.p;
p += len;
/* Compare both signature algorithms */
if (sig_alg1.len != sig_alg2.len) {
return IMG_PARSER_ERR_FORMAT;
}
if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) {
return IMG_PARSER_ERR_FORMAT;
}
memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg));
/*
* signatureValue BIT STRING
*/
signature.p = p;
ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_BIT_STRING);
if (ret != 0) {
return IMG_PARSER_ERR_FORMAT;
}
signature.len = (p + len) - signature.p;
p += len;
/* Check certificate length */
if (p != end) {
return IMG_PARSER_ERR_FORMAT;
}
return IMG_PARSER_OK;
}
/* Exported functions */
static void init(void)
{
mbedtls_init();
}
/*
* Wrapper for cert_parse() that clears the static variables used by it in case
* of an error.
*/
static int check_integrity(void *img, unsigned int img_len)
{
int rc = cert_parse(img, img_len);
if (rc != IMG_PARSER_OK)
clear_temp_vars();
return rc;
}
/*
* Extract an authentication parameter from an X509v3 certificate
*
* This function returns a pointer to the extracted data and its length.
* Depending on the type of parameter, a pointer to the data stored in the
* certificate may be returned (i.e. an octet string containing a hash). Other
* data may need to be copied and formatted (i.e. integers). In the later case,
* a buffer of the correct type needs to be statically allocated, filled and
* returned.
*/
static int get_auth_param(const auth_param_type_desc_t *type_desc,
void *img, unsigned int img_len,
void **param, unsigned int *param_len)
{
int rc = IMG_PARSER_OK;
/* We do not use img because the check_integrity function has already
* extracted the relevant data (v3_ext, pk, sig_alg, etc) */
switch (type_desc->type) {
case AUTH_PARAM_RAW_DATA:
/* Data to be signed */
*param = (void *)tbs.p;
*param_len = (unsigned int)tbs.len;
break;
case AUTH_PARAM_HASH:
case AUTH_PARAM_NV_CTR:
/* All these parameters are included as X509v3 extensions */
rc = get_ext(type_desc->cookie, param, param_len);
break;
case AUTH_PARAM_PUB_KEY:
if (type_desc->cookie != 0) {
/* Get public key from extension */
rc = get_ext(type_desc->cookie, param, param_len);
} else {
/* Get the subject public key */
*param = (void *)pk.p;
*param_len = (unsigned int)pk.len;
}
break;
case AUTH_PARAM_SIG_ALG:
/* Get the certificate signature algorithm */
*param = (void *)sig_alg.p;
*param_len = (unsigned int)sig_alg.len;
break;
case AUTH_PARAM_SIG:
/* Get the certificate signature */
*param = (void *)signature.p;
*param_len = (unsigned int)signature.len;
break;
default:
rc = IMG_PARSER_ERR_NOT_FOUND;
break;
}
return rc;
}
REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \
check_integrity, get_auth_param);
@@ -0,0 +1,184 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <platform_def.h>
#include MBEDTLS_CONFIG_FILE
#include <drivers/auth/auth_mod.h>
#include <drivers/auth/tbbr_cot_common.h>
#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
#else
#include <platform_oid.h>
#endif
static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID);
static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID);
static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, FWU_HASH_OID);
static const auth_img_desc_t bl2_image = {
.img_id = BL2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_hash
}
}
}
};
/*
* FWU auth descriptor.
*/
static const auth_img_desc_t fwu_cert = {
.img_id = FWU_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_bl2u_hash,
.data = {
.ptr = (void *)scp_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &bl2u_hash,
.data = {
.ptr = (void *)tb_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &ns_bl2u_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
/*
* SCP_BL2U
*/
static const auth_img_desc_t scp_bl2u_image = {
.img_id = SCP_BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &scp_bl2u_hash
}
}
}
};
/*
* BL2U
*/
static const auth_img_desc_t bl2u_image = {
.img_id = BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &bl2u_hash
}
}
}
};
/*
* NS_BL2U
*/
static const auth_img_desc_t ns_bl2u_image = {
.img_id = NS_BL2U_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &fwu_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &ns_bl2u_hash
}
}
}
};
/*
* TB_FW_CONFIG
*/
static const auth_img_desc_t tb_fw_config = {
.img_id = TB_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tb_fw_config_hash
}
}
}
};
static const auth_img_desc_t fw_config = {
.img_id = FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &fw_config_hash
}
}
}
};
/*
* TBBR Chain of trust definition
*/
static const auth_img_desc_t * const cot_desc[] = {
[TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
[BL2_IMAGE_ID] = &bl2_image,
[HW_CONFIG_ID] = &hw_config,
[TB_FW_CONFIG_ID] = &tb_fw_config,
[FW_CONFIG_ID] = &fw_config,
[FWU_CERT_ID] = &fwu_cert,
[SCP_BL2U_IMAGE_ID] = &scp_bl2u_image,
[BL2U_IMAGE_ID] = &bl2u_image,
[NS_BL2U_IMAGE_ID] = &ns_bl2u_image
};
/* Register the CoT in the authentication module */
REGISTER_COT(cot_desc);
@@ -0,0 +1,177 @@
/*
* Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <drivers/auth/auth_mod.h>
#include MBEDTLS_CONFIG_FILE
#include <drivers/auth/tbbr_cot_common.h>
#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
#else
#include <platform_oid.h>
#endif
#include <platform_def.h>
static unsigned char trusted_world_pk_buf[PK_DER_LEN];
static unsigned char non_trusted_world_pk_buf[PK_DER_LEN];
static unsigned char content_pk_buf[PK_DER_LEN];
static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
/*
* Trusted key certificate
*/
static const auth_img_desc_t trusted_key_cert = {
.img_id = TRUSTED_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &trusted_world_pk,
.data = {
.ptr = (void *)trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
},
[1] = {
.type_desc = &non_trusted_world_pk,
.data = {
.ptr = (void *)non_trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
/*
* Non-Trusted Firmware
*/
static const auth_img_desc_t non_trusted_fw_key_cert = {
.img_id = NON_TRUSTED_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &non_trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t non_trusted_fw_content_cert = {
.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &non_trusted_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &nt_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_world_bl_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &nt_fw_config_hash,
.data = {
.ptr = (void *)nt_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl33_image = {
.img_id = BL33_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_world_bl_hash
}
}
}
};
static const auth_img_desc_t * const cot_desc[] = {
[TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
[NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert,
[NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
[BL33_IMAGE_ID] = &bl33_image,
};
/* Register the CoT in the authentication module */
REGISTER_COT(cot_desc);
@@ -0,0 +1,688 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <platform_def.h>
#include MBEDTLS_CONFIG_FILE
#include <drivers/auth/auth_mod.h>
#include <drivers/auth/tbbr_cot_common.h>
#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
#else
#include <platform_oid.h>
#endif
static unsigned char soc_fw_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN];
static unsigned char trusted_world_pk_buf[PK_DER_LEN];
static unsigned char non_trusted_world_pk_buf[PK_DER_LEN];
static unsigned char content_pk_buf[PK_DER_LEN];
static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN];
#if defined(SPD_spmd)
static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN];
#endif /* SPD_spmd */
static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID);
static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID);
static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID);
static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID);
static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SCP_FW_HASH_OID);
static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID);
static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID);
static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID);
static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID);
static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID);
static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID);
static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID);
#if defined(SPD_spmd)
static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG1_HASH_OID);
static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG2_HASH_OID);
static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG3_HASH_OID);
static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG4_HASH_OID);
static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG5_HASH_OID);
static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG6_HASH_OID);
static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG7_HASH_OID);
static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, SP_PKG8_HASH_OID);
#endif /* SPD_spmd */
/*
* Trusted key certificate
*/
static const auth_img_desc_t trusted_key_cert = {
.img_id = TRUSTED_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &trusted_world_pk,
.data = {
.ptr = (void *)trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
},
[1] = {
.type_desc = &non_trusted_world_pk,
.data = {
.ptr = (void *)non_trusted_world_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
/*
* SCP Firmware
*/
static const auth_img_desc_t scp_fw_key_cert = {
.img_id = SCP_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t scp_fw_content_cert = {
.img_id = SCP_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &scp_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &scp_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &scp_fw_hash,
.data = {
.ptr = (void *)scp_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t scp_bl2_image = {
.img_id = SCP_BL2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &scp_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &scp_fw_hash
}
}
}
};
/*
* SoC Firmware
*/
static const auth_img_desc_t soc_fw_key_cert = {
.img_id = SOC_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t soc_fw_content_cert = {
.img_id = SOC_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &soc_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &soc_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &soc_fw_hash,
.data = {
.ptr = (void *)soc_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &soc_fw_config_hash,
.data = {
.ptr = (void *)soc_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl31_image = {
.img_id = BL31_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &soc_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_hash
}
}
}
};
/* SOC FW Config */
static const auth_img_desc_t soc_fw_config = {
.img_id = SOC_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &soc_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &soc_fw_config_hash
}
}
}
};
/*
* Trusted OS Firmware
*/
static const auth_img_desc_t trusted_os_fw_key_cert = {
.img_id = TRUSTED_OS_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tos_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t trusted_os_fw_content_cert = {
.img_id = TRUSTED_OS_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_os_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &tos_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tos_fw_hash,
.data = {
.ptr = (void *)tos_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tos_fw_extra1_hash,
.data = {
.ptr = (void *)tos_fw_extra1_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &tos_fw_extra2_hash,
.data = {
.ptr = (void *)tos_fw_extra2_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &tos_fw_config_hash,
.data = {
.ptr = (void *)tos_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl32_image = {
.img_id = BL32_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_hash
}
}
}
};
static const auth_img_desc_t bl32_extra1_image = {
.img_id = BL32_EXTRA1_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_extra1_hash
}
}
}
};
static const auth_img_desc_t bl32_extra2_image = {
.img_id = BL32_EXTRA2_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_extra2_hash
}
}
}
};
/* TOS FW Config */
static const auth_img_desc_t tos_fw_config = {
.img_id = TOS_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_os_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &tos_fw_config_hash
}
}
}
};
/*
* Non-Trusted Firmware
*/
static const auth_img_desc_t non_trusted_fw_key_cert = {
.img_id = NON_TRUSTED_FW_KEY_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &non_trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_fw_content_pk,
.data = {
.ptr = (void *)content_pk_buf,
.len = (unsigned int)PK_DER_LEN
}
}
}
};
static const auth_img_desc_t non_trusted_fw_content_cert = {
.img_id = NON_TRUSTED_FW_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &non_trusted_fw_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &nt_fw_content_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &non_trusted_nv_ctr,
.plat_nv_ctr = &non_trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &nt_world_bl_hash,
.data = {
.ptr = (void *)nt_world_bl_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &nt_fw_config_hash,
.data = {
.ptr = (void *)nt_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
static const auth_img_desc_t bl33_image = {
.img_id = BL33_IMAGE_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_world_bl_hash
}
}
}
};
/* NT FW Config */
static const auth_img_desc_t nt_fw_config = {
.img_id = NT_FW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &non_trusted_fw_content_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &nt_fw_config_hash
}
}
}
};
/* Secure Partitions */
#if defined(SPD_spmd)
static const auth_img_desc_t sip_sp_content_cert = {
.img_id = SIP_SP_CONTENT_CERT_ID,
.img_type = IMG_CERT,
.parent = &trusted_key_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &trusted_world_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &sp_pkg1_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[0],
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &sp_pkg2_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[1],
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &sp_pkg3_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[2],
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &sp_pkg4_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[3],
.len = (unsigned int)HASH_DER_LEN
}
},
[4] = {
.type_desc = &sp_pkg5_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[4],
.len = (unsigned int)HASH_DER_LEN
}
},
[5] = {
.type_desc = &sp_pkg6_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[5],
.len = (unsigned int)HASH_DER_LEN
}
},
[6] = {
.type_desc = &sp_pkg7_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[6],
.len = (unsigned int)HASH_DER_LEN
}
},
[7] = {
.type_desc = &sp_pkg8_hash,
.data = {
.ptr = (void *)sp_pkg_hash_buf[7],
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
DEFINE_SIP_SP_PKG(1);
DEFINE_SIP_SP_PKG(2);
DEFINE_SIP_SP_PKG(3);
DEFINE_SIP_SP_PKG(4);
DEFINE_SIP_SP_PKG(5);
DEFINE_SIP_SP_PKG(6);
DEFINE_SIP_SP_PKG(7);
DEFINE_SIP_SP_PKG(8);
#endif /* SPD_spmd */
static const auth_img_desc_t * const cot_desc[] = {
[TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert,
[HW_CONFIG_ID] = &hw_config,
[TRUSTED_KEY_CERT_ID] = &trusted_key_cert,
[SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert,
[SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert,
[SCP_BL2_IMAGE_ID] = &scp_bl2_image,
[SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert,
[SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert,
[BL31_IMAGE_ID] = &bl31_image,
[SOC_FW_CONFIG_ID] = &soc_fw_config,
[TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert,
[TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert,
[BL32_IMAGE_ID] = &bl32_image,
[BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image,
[BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image,
[TOS_FW_CONFIG_ID] = &tos_fw_config,
[NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert,
[NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert,
[BL33_IMAGE_ID] = &bl33_image,
[NT_FW_CONFIG_ID] = &nt_fw_config,
#if defined(SPD_spmd)
[SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert,
[SP_PKG1_ID] = &sp_pkg1,
[SP_PKG2_ID] = &sp_pkg2,
[SP_PKG3_ID] = &sp_pkg3,
[SP_PKG4_ID] = &sp_pkg4,
[SP_PKG5_ID] = &sp_pkg5,
[SP_PKG6_ID] = &sp_pkg6,
[SP_PKG7_ID] = &sp_pkg7,
[SP_PKG8_ID] = &sp_pkg8,
#endif
};
/* Register the CoT in the authentication module */
REGISTER_COT(cot_desc);
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stddef.h>
#include <platform_def.h>
#include MBEDTLS_CONFIG_FILE
#include <drivers/auth/auth_mod.h>
#include <drivers/auth/tbbr_cot_common.h>
#if USE_TBBR_DEFS
#include <tools_share/tbbr_oid.h>
#else
#include <platform_oid.h>
#endif
/*
* The platform must allocate buffers to store the authentication parameters
* extracted from the certificates. In this case, because of the way the CoT is
* established, we can reuse some of the buffers on different stages
*/
static unsigned char fw_config_hash_buf[HASH_DER_LEN];
static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN];
static unsigned char hw_config_hash_buf[HASH_DER_LEN];
unsigned char tb_fw_hash_buf[HASH_DER_LEN];
unsigned char scp_fw_hash_buf[HASH_DER_LEN];
unsigned char nt_world_bl_hash_buf[HASH_DER_LEN];
/*
* common Parameter type descriptors across BL1 and BL2
*/
auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID);
auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_PUB_KEY, 0);
auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG, 0);
auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_SIG_ALG, 0);
auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_RAW_DATA, 0);
/* common hash used across BL1 and BL2 */
auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID);
auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID);
auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, FW_CONFIG_HASH_OID);
static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC(
AUTH_PARAM_HASH, HW_CONFIG_HASH_OID);
/* trusted_boot_fw_cert */
const auth_img_desc_t trusted_boot_fw_cert = {
.img_id = TRUSTED_BOOT_FW_CERT_ID,
.img_type = IMG_CERT,
.parent = NULL,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_SIG,
.param.sig = {
.pk = &subject_pk,
.sig = &sig,
.alg = &sig_alg,
.data = &raw_data
}
},
[1] = {
.type = AUTH_METHOD_NV_CTR,
.param.nv_ctr = {
.cert_nv_ctr = &trusted_nv_ctr,
.plat_nv_ctr = &trusted_nv_ctr
}
}
},
.authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) {
[0] = {
.type_desc = &tb_fw_hash,
.data = {
.ptr = (void *)tb_fw_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[1] = {
.type_desc = &tb_fw_config_hash,
.data = {
.ptr = (void *)tb_fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[2] = {
.type_desc = &hw_config_hash,
.data = {
.ptr = (void *)hw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
},
[3] = {
.type_desc = &fw_config_hash,
.data = {
.ptr = (void *)fw_config_hash_buf,
.len = (unsigned int)HASH_DER_LEN
}
}
}
};
/* HW Config */
const auth_img_desc_t hw_config = {
.img_id = HW_CONFIG_ID,
.img_type = IMG_RAW,
.parent = &trusted_boot_fw_cert,
.img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) {
[0] = {
.type = AUTH_METHOD_HASH,
.param.hash = {
.data = &raw_data,
.hash = &hw_config_hash
}
}
}
};