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.
181 lines
4.3 KiB
181 lines
4.3 KiB
4 years ago
|
/*
|
||
|
* 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);
|