You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

180 lines
4.3 KiB

/*
* Copyright (c) 2014-2016, Freescale Semiconductor, Inc.
* Copyright 2017-2021 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <arch_helpers.h>
#include <common/debug.h>
#include <csf_hdr.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/auth/img_parser_mod.h>
#include <lib/utils.h>
#include <sfp.h>
/* 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.
*/
/* Hash of Image + CSF Header + SRK table */
uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE);
uint32_t hash_len;
/* Key being used for authentication
* Points to the key in CSF header copied in DDR
* ESBC client key
*/
void *img_key;
uint32_t key_len;
/* ESBC client signature */
void *img_sign;
uint32_t sign_len;
enum sig_alg alg;
/* Maximum OID string length ("a.b.c.d.e.f ...") */
#define MAX_OID_STR_LEN 64
#define LIB_NAME "NXP CSFv2"
/*
* 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(img_key);
ZERO_AND_CLEAN(img_sign);
ZERO_AND_CLEAN(img_hash);
ZERO_AND_CLEAN(key_len);
ZERO_AND_CLEAN(hash_len);
ZERO_AND_CLEAN(sign_len);
#undef ZERO_AND_CLEAN
}
/* Exported functions */
static void init(void)
{
clear_temp_vars();
}
/*
* This function would check the integrity of the CSF header
*/
static int check_integrity(void *img, unsigned int img_len)
{
int ret;
/*
* The image file has been successfully loaded till here.
*
* Flush the image to main memory so that it can be authenticated
* by CAAM, a HW accelerator regardless of cache and MMU state.
*/
flush_dcache_range((uintptr_t) img, img_len);
/*
* Image is appended at an offset of 16K (IMG_OFFSET) to the header.
* So the size in header should be equal to img_len - IMG_OFFSET
*/
VERBOSE("Barker code is %x\n", *(unsigned int *)img);
ret = validate_esbc_header(img, &img_key, &key_len, &img_sign,
&sign_len, &alg);
if (ret < 0) {
ERROR("Header authentication failed\n");
clear_temp_vars();
return IMG_PARSER_ERR;
}
/* Calculate the hash of various components from the image */
ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ,
img_len - CSF_HDR_SZ, img_hash, &hash_len);
if (ret != 0) {
ERROR("Issue in hash calculation %d\n", ret);
clear_temp_vars();
return IMG_PARSER_ERR;
}
return IMG_PARSER_OK;
}
/*
* Extract an authentication parameter from CSF header
*
* CSF header has already been parsed and the required information like
* hash of data, signature, length stored in global variables has been
* extracted in chek_integrity function. This data
* is returned back to the caller.
*/
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 ( pk, sig_alg, etc)
*/
switch (type_desc->type) {
/* Hash will be returned for comparison with signature */
case AUTH_PARAM_HASH:
*param = (void *)img_hash;
*param_len = (unsigned int)SHA256_BYTES;
break;
/* Return the public key used for signature extracted from the SRK table
* after checks with key revocation
*/
case AUTH_PARAM_PUB_KEY:
/* Get the subject public key */
/* For a 1K key - the length would be 2k/8 = 0x100 bytes
* 2K RSA key - 0x200 , 4K RSA - 0x400
*/
*param = img_key;
*param_len = (unsigned int)key_len;
break;
/* Call a function to tell if signature is RSA or ECDSA. ECDSA to be
* supported in later platforms like LX2 etc
*/
case AUTH_PARAM_SIG_ALG:
/* Algo will be signature - RSA or ECDSA on hash */
*param = (void *)&alg;
*param_len = 4U;
break;
/* Return the signature */
case AUTH_PARAM_SIG:
*param = img_sign;
*param_len = (unsigned int)sign_len;
break;
case AUTH_PARAM_NV_CTR:
default:
rc = IMG_PARSER_ERR_NOT_FOUND;
break;
}
return rc;
}
REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init,
check_integrity, get_auth_param);