tf-a/tf-a-stm32mp-2.2.r1/plat/st/common/stm32mp_crypto_lib.c

175 lines
4.3 KiB
C

/*
* Copyright (c) 2020, STMicroelectronics - All Rights Reserved
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <errno.h>
#include <platform_def.h>
#include <common/debug.h>
#include <drivers/auth/crypto_mod.h>
#include <drivers/io/io_storage.h>
#include <drivers/st/bsec.h>
#include <drivers/st/stm32_hash.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include <plat/common/platform.h>
struct stm32mp_auth_ops {
uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out);
uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in,
uint8_t *signature, uint32_t ecc_algo);
};
static struct stm32mp_auth_ops auth_ops;
static void crypto_lib_init(void)
{
boot_api_context_t *boot_context =
(boot_api_context_t *)stm32mp_get_boot_ctx_address();
if (!stm32mp_is_auth_supported()) {
return;
}
auth_ops.check_key = boot_context->bootrom_ecdsa_check_key;
auth_ops.verify_signature =
boot_context->bootrom_ecdsa_verify_signature;
if (stm32_hash_register() != 0) {
panic();
}
}
static int crypto_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)
{
uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
uint32_t option_flags;
uint32_t ecc_algo_type;
uint32_t header_len;
int result;
boot_api_image_header_t *header = stm32mp_get_loaded_header();
header_len = sizeof(boot_api_image_header_t) - sizeof(header->magic) -
sizeof(header->image_signature) -
sizeof(header->payload_checksum);
if ((((size_t)sig_alg % __alignof__(uint32_t)) != 0) ||
(sig_alg_len != sizeof(option_flags) + sizeof(ecc_algo_type))) {
return -EINVAL;
}
option_flags = ((uint32_t *)sig_alg)[0];
ecc_algo_type = ((uint32_t *)sig_alg)[1];
/* Check security status */
if (!stm32mp_is_closed_device()) {
if (option_flags != 0U) {
WARN("Skip signature check (header option)\n");
stm32mp_delete_loaded_header();
return 0;
}
INFO("Check signature on Open device\n");
}
/* Check key/sign size */
if ((pk_len != BOOT_API_ECDSA_PUB_KEY_LEN_IN_BYTES) ||
(sig_len != BOOT_API_ECDSA_SIGNATURE_LEN_IN_BYTES)) {
return -EINVAL;
}
result = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE,
STM32MP_ROM_SIZE, MT_CODE | MT_SECURE);
if (result != 0) {
return result;
}
if (!stm32mp_is_closed_device()) {
/*
* Check public key here in case of non-secure device
* It is done in the generic framework in case of close
* device.
*/
if (auth_ops.check_key(pk_ptr, NULL) != BOOT_API_RETURN_OK) {
ERROR("ROTPK verification failed\n");
result = -EINVAL;
goto out;
} else {
NOTICE("ROTPK verification forced and checked OK\n");
}
}
/* Compute hash for the data covered by the signature */
stm32_hash_init(HASH_SHA256);
result = stm32_hash_update((void *)&header->header_version, header_len);
if (result != 0) {
VERBOSE("Hash of header failed, %i\n", result);
goto out;
}
result = stm32_hash_final_update((uint8_t *)data_ptr,
data_len, image_hash);
if (result != 0) {
VERBOSE("Hash of payload failed, %i\n", result);
goto out;
}
/* Verify signature */
if (auth_ops.verify_signature(image_hash, pk_ptr, sig_ptr,
ecc_algo_type) != BOOT_API_RETURN_OK) {
result = -EAUTH;
}
out:
mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE);
if (result != 0) {
stm32mp_delete_loaded_header();
}
return result;
}
static int crypto_verify_hash(void *data_ptr, unsigned int data_len,
void *digest_info_ptr,
unsigned int digest_info_len)
{
int ret;
uint8_t calc_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES];
if (digest_info_len != BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES) {
VERBOSE("%s: unexpected digest_len\n", __func__);
ret = -EINVAL;
goto out;
}
stm32_hash_init(HASH_SHA256);
ret = stm32_hash_final_update(data_ptr, data_len, calc_hash);
if (ret != 0) {
VERBOSE("%s: hash failed\n", __func__);
goto out;
}
ret = memcmp(calc_hash, digest_info_ptr, digest_info_len);
if (ret != 0) {
VERBOSE("%s: not expected digest\n", __func__);
ret = -EAUTH;
}
out:
/* Clean header as no more used */
stm32mp_delete_loaded_header();
return ret;
}
REGISTER_CRYPTO_LIB("stm32_crypto_lib",
crypto_lib_init,
crypto_verify_signature,
crypto_verify_hash);