Files
2025-12-24 17:21:08 +09:00

523 lines
17 KiB
C

/*******************************************************************************
* DISCLAIMER
* This software is supplied by Renesas Electronics Corporation and is only
* intended for use with Renesas products. No other uses are authorized. This
* software is owned by Renesas Electronics Corporation and is protected under
* all applicable laws, including copyright laws.
* THIS SOFTWARE IS PROVIDED "AS IS" AND RENESAS MAKES NO WARRANTIES REGARDING
* THIS SOFTWARE, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT
* LIMITED TO WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* AND NON-INFRINGEMENT. ALL SUCH WARRANTIES ARE EXPRESSLY DISCLAIMED.
* TO THE MAXIMUM EXTENT PERMITTED NOT PROHIBITED BY LAW, NEITHER RENESAS
* ELECTRONICS CORPORATION NOR ANY OF ITS AFFILIATED COMPANIES SHALL BE LIABLE
* FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES FOR
* ANY REASON RELATED TO THIS SOFTWARE, EVEN IF RENESAS OR ITS AFFILIATES HAVE
* BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
* Renesas reserves the right, without notice, to make changes to this software
* and to discontinue the availability of this software. By using this software,
* you agree to the additional terms and conditions found by accessing the
* following link:
* http://www.renesas.com/disclaimer
* Copyright 2018-2025 Renesas Electronics Corporation All rights reserved.
*******************************************************************************/
/*******************************************************************************
* DESCRIPTION : ICUMIF control function
******************************************************************************/
/******************************************************************************
* @file secure_boot.c
* - Version : 0.08
* @brief ICUMIF controller.
* .
*****************************************************************************/
/******************************************************************************
* History : DD.MM.YYYY Version Description
* : 16.06.2022 0.01 First Release
* : 22.07.2022 0.02 Change CMAC address settings
* Added include file
* Changed for Warning measures
* : 31.10.2022 0.03 License notation change.
* : 07.12.2022 0.04 Warning support when log output is disabled
* : 15.02.2023 0.05 Added final_hash_cmp function.
* : 04.04.2023 0.06 Removed stdio.h.
* : 21.08.2023 0.07 Add support for V4M.
* : 14.01.2024 0.08 Add parameter setting process for RTOS#1/#2.
*****************************************************************************/
#include "log.h"
#include "timer.h"
#include "r_icumif_api.h"
#include "r_icumif_pub.h"
#include "icum_d_comm_pe_pub.h"
#include "shared.h"
#include "image_load.h"
#include "secure_boot.h"
#include "rst_register.h"
#define LCS_CM (0x00000000U) /* CM */
#define LCS_DM (0x00000001U) /* DM */
#define LCS_SD (0x00000003U) /* SD */
#define LCS_SE (0x00000005U) /* SE */
#define LCS_FA (0x00000007U) /* FA */
#define RST_MODEMR0_MD5 (0x00000020U)
#define CX_CMAC_COPY (4U)
#define CX_ICUMIF_STATUS (0x1000F800UL)
#define CX_SIZEOF_CNT (4U)
#define CX_CMAC_SIZE (16U)
/* Definitions for hash_cmp */
#define HASH_CMP_NUM (0x2U) /* The number of hash check images */
#define HASH_SIZE (32U) /* Hash size (32-bytes) */
#define CR52_IPL_HASH_SAVE_ADDR (0xE635FF40U) /* Hash save address for CR52 IPL */
#define SECURE_FW_HASH_SAVE_ADDR (0xE635FFC0U) /* Hash save address for Secure FW */
static void secureboot_memset(void *buff, uint32_t data, uint32_t cnt);
static void secureboot_service(r_icumif_isd_t *p_ISD);
void secureboot_init(void)
{
int32_t r_errno;
volatile uint32_t *status;
status = (volatile uint32_t *)R_ICUMIF_GetStatus();
/* Wait until the ICU-M system intialization is complete */
while(true)
{
if((*status & CX_ICUMIF_STATUS) != 0UL)
{
break;
}
else
{
micro_wait(100U); /* 100 micro sec */
}
}
r_errno = R_ICUMIF_Init((uint32_t *)((uintptr_t)MEM_INFO_SERVICEQUE_1_ADDR));
if(r_errno != R_ICUMIF_ER_OK)
{
ERROR("R_ICUMIF_Init:Error code = (0x%x).\n", (unsigned int)r_errno);
panic;
}
}
/* End of function secureboot_init(void) */
uint32_t judge_bootmode(void)
{
uint32_t *p_lcs;
r_icumif_isd_t *p_ISD;
uint32_t md;
uint32_t is_verify = SECURE_BOOT;
__attribute__((unused))const char *lcs_name[8U] = {
[LCS_CM] = "CM",
[LCS_DM] = "DM",
[LCS_SD] = "SD",
[LCS_SE] = "SE",
[LCS_FA] = "FA",
};
secureboot_memset(ISD_BUFFER, 0U, SIZE_OF_ISD_BUFFER);
secureboot_memset(LCS_BUFFER, 0U, SIZE_OF_LCS_BUFFER);
/* initialize the global icum service header */
p_ISD = (r_icumif_isd_t *)ISD_BUFFER;
p_lcs = (uint32_t *)LCS_BUFFER;
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id = ROM_GET_LCS;
p_ISD->prm.SECURE_BOOT_API.api.get_lcs.ptr.p_lcs = p_lcs;
p_ISD->prm.SECURE_BOOT_API.api.get_lcs.lcs_size_in_bytes = SIZE_OF_LCS_BUFFER;
/* trigger the service request */
secureboot_service(p_ISD);
if(ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value)
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
panic;
}
else
{
/* LCM Status check */
if(( LCS_CM != *p_lcs)
&& ( LCS_DM != *p_lcs)
&& ( LCS_SD != *p_lcs)
&& ( LCS_SE != *p_lcs)
&& ( LCS_FA != *p_lcs))
{
ERROR("LCM state error. LCS = 0x%x\n", (unsigned int)*p_lcs );
panic;
}
else
{
NOTICE("LCM state is %s\n",lcs_name[*p_lcs]);
}
}
md = (mem_read32(RST_MODEMR0) & RST_MODEMR0_MD5) >> 5U;
if (LCS_SD == *p_lcs)
{
/* LCS=SD => Normal boot */
is_verify = NORMAL_BOOT;
}
else if ((LCS_SE != *p_lcs) && ( 1U == md))
{
/* LCS=CM/DM/FA and MD5=1 => Normal boot */
is_verify = NORMAL_BOOT;
}
else
{
/* LCS=SE => Secure boot */
/* LCS=CM/DM/FA and MD5=0 => Secure boot */
is_verify = SECURE_BOOT;
}
if (NORMAL_BOOT != is_verify)
{
#if (RCAR_LSI == RCAR_S4)
NOTICE("Secure boot(CA55 Loader)\n");
#elif ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
#ifdef AARCH64
NOTICE("Secure boot(CA76 Loader)\n");
#else
NOTICE("Secure boot(CR52 Loader)\n");
#endif
#endif /* RCAR_LSI == RCAR_S4 */
}
else
{
#if (RCAR_LSI == RCAR_S4)
NOTICE("Normal boot(CA55 Loader)\n");
#elif ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
#ifdef AARCH64
NOTICE("Normal boot(CA76 Loader)\n");
#else
NOTICE("Normal boot(CR52 Loader)\n");
#endif
#endif /* RCAR_LSI == RCAR_S4 */
}
return is_verify;
}
/* End of function judge_bootmode(void) */
void secureboot_verify(LOAD_INFO* li, uint32_t start, uint32_t end)
{
uint32_t *p_cmac;
r_icumif_isd_t *p_ISD;
uint32_t loop;
uint32_t i;
volatile uintptr_t p_content_cert;
volatile uintptr_t p_key_cert;
secureboot_memset(ISD_BUFFER, 0U, SIZE_OF_ISD_BUFFER);
p_ISD = (r_icumif_isd_t *)ISD_BUFFER;
/* Set Load info parameter */
for (loop = start; loop < end; loop++)
{
secureboot_memset(CMAC_BUFFER, 0U, SIZE_OF_CMAC_BUFFER);
p_cmac = (uint32_t *)CMAC_BUFFER;
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id
= ROM_SECURE_BOOT_VERIFY;
p_key_cert = li[loop].key_cert_addr;
p_content_cert = li[loop].cnt_cert_addr;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr1.p_key_cert = (uint32_t*)p_key_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr2.p_content_cert = (uint32_t*)p_content_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr3.p_cmac = p_cmac;
/* trigger the service request */
secureboot_service(p_ISD);
if(ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value)
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
panic;
}
else
{
for (i = 0U; i < CX_CMAC_COPY; i++)
{
li[loop].cmac[i] = *(p_cmac++);
}
}
}
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
/* Set Load info parameter */
/* For RTOS#0 */
secureboot_memset(CMAC_BUFFER, 0U, CX_CMAC_SIZE);
p_cmac = (uint32_t *)CMAC_BUFFER;
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id
= ROM_SECURE_BOOT_VERIFY;
p_key_cert = li[RTOS_ID].key_cert_addr;
p_content_cert = li[RTOS_ID].cnt_cert_addr;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr1.p_key_cert = (uint32_t*)p_key_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr2.p_content_cert = (uint32_t*)p_content_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr3.p_cmac = p_cmac;
/* trigger the service request */
secureboot_service(p_ISD);
if(ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value)
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
panic;
}
else
{
for (i = 0U; i < CX_CMAC_COPY; i++)
{
li[RTOS_ID].cmac[i] = *(p_cmac++);
}
}
#if (RTOS_LOAD_NUM == RTOS_LOAD_NUM_3)
/* For RTOS#1,RTOS#2 */
for (loop = RTOS1_ID; loop <= RTOS2_ID; loop++)
{
secureboot_memset(CMAC_BUFFER, 0U, CX_CMAC_SIZE);
p_cmac = (uint32_t *)CMAC_BUFFER;
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id
= ROM_SECURE_BOOT_VERIFY;
p_key_cert = li[loop].key_cert_addr;
p_content_cert = li[loop].cnt_cert_addr;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr1.p_key_cert = (uint32_t*)p_key_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr2.p_content_cert = (uint32_t*)p_content_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_verify.ptr3.p_cmac = p_cmac;
/* trigger the service request */
secureboot_service(p_ISD);
if(ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value)
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
panic;
}
else
{
for (i = 0U; i < CX_CMAC_COPY; i++)
{
li[loop].cmac[i] = *(p_cmac++);
}
}
}
#endif /* RTOS_LOAD_NUM == RTOS_LOAD_NUM_3 */
#endif /* RCAR_LSI == RCAR_V4H || RCAR_LSI == RCAR_V4M */
}
/* End of function secureboot_verify(void) */
int secureboot_image(LOAD_INFO* li, int do_panic)
{
uint32_t *p_cmac;
uint32_t *p_hash;
r_icumif_isd_t *p_ISD;
uint32_t i;
volatile uintptr_t p_content_cert;
secureboot_memset(ISD_BUFFER, 0U, SIZE_OF_ISD_BUFFER);
secureboot_memset(CMAC_BUFFER, 0U, SIZE_OF_CMAC_BUFFER);
secureboot_memset(HASH_BUFFER, 0U, SIZE_OF_HASH_BUFFER);
/* initialize the global icum service header */
p_ISD = (r_icumif_isd_t *)ISD_BUFFER;
p_cmac = (uint32_t *)CMAC_BUFFER;
p_hash = (uint32_t *)HASH_BUFFER;
for (i = 0U; i < CX_CMAC_COPY; i++)
{
*(p_cmac++) = li->cmac[i];
}
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id = ROM_SECURE_BOOT_DECRYPT;
p_content_cert = li->cnt_cert_addr;
p_ISD->prm.SECURE_BOOT_API.api.
boot_decrypt.ptr1.p_content_cert = (uint32_t*)p_content_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_decrypt.ptr2.p_cmac = (uint32_t *)CMAC_BUFFER;
/* trigger the service request */
secureboot_service(p_ISD);
if(( ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value) &&
(ROM_ERR_IMG_VERIFIER_NO_ENCRYPT_IMG != p_ISD->prm.SECURE_BOOT_API.api_return_value))
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
if (do_panic)
panic;
else
return -1;
}
p_ISD->service_id = SERVICE_00_SECURE_BOOT_API;
p_ISD->ptr.p_callbackfunc = NULL;
p_ISD->job_id = 0U;
p_ISD->res_nointerrupt = R_ICUMIF_REQRES_NOINTERRPUT;
p_ISD->prm.SECURE_BOOT_API.boot_api_id = ROM_SECURE_BOOT_COMPARE;
p_ISD->prm.SECURE_BOOT_API.api.
boot_compare.ptr1.p_content_cert = (uint32_t*)p_content_cert;
p_ISD->prm.SECURE_BOOT_API.api.
boot_compare.ptr2.p_hash = p_hash;
p_ISD->prm.SECURE_BOOT_API.api.
boot_compare.hash_size_in_bytes = SIZE_OF_HASH_BUFFER;
p_ISD->prm.SECURE_BOOT_API.api.
boot_compare.ptr3.p_cmac = (uint32_t *)CMAC_BUFFER;
/* trigger the service request */
secureboot_service(p_ISD);
if(ROMAPI_OK != p_ISD->prm.SECURE_BOOT_API.api_return_value)
{
ERROR("SECURE_BOOT_API:Error code = (0x%x).\n",
(unsigned int)p_ISD->prm.SECURE_BOOT_API.api_return_value);
if (do_panic)
panic;
else
return -1;
}
return 0;
}
/* End of function secureboot_image(LOAD_INFO* li) */
static void secureboot_memset(void *buff, uint32_t data, uint32_t cnt)
{
uint32_t *tmp = NULL;
uint32_t loop = cnt / CX_SIZEOF_CNT; /* Copy 4 bytes at a time */
tmp = (uint32_t *)buff;
if (buff == NULL)
{
return;
}
while (loop > 0U)
{
*tmp = data;
tmp++;
loop--;
}
}/* End of function secureboot_memset(void *buff, uint32_t data, uint32_t cnt) */
static void secureboot_service(r_icumif_isd_t *p_ISD)
{
int32_t r_errno;
/* trigger the service request */
r_errno = R_ICUMIF_ServiceRequest(p_ISD);
if(R_ICUMIF_ER_OK != r_errno)
{
ERROR("R_ICUMIF_ServiceRequest:Error code = (0x%x).\n", (unsigned int)r_errno);
panic;
}
/* wait for response */
while(true)
{
r_errno = R_ICUMIF_IsServiceCompleted(p_ISD);
if(r_errno != R_ICUMIF_RTN_SERV_RUNNING)
{
break;
}
}
if(SERV_OK != p_ISD->service_result)
{
ERROR("R_ICUMIF_IsServiceCompleted:Error code = (0x%x).\n", p_ISD->service_result);
panic;
}
r_errno = R_ICUMIF_ServiceResponse();
if(R_ICUMIF_ER_OK != r_errno)
{
ERROR("R_ICUMIF_ServiceResponse:Error code = (0x%x).\n", (unsigned int)r_errno);
panic;
}
}
/* End of function secureboot_service(r_icumif_isd_t *p_ISD) */
void final_hash_cmp(void)
{
#if ((RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M))
uint32_t i;
uint32_t j;
uint8_t *hash1;
uint8_t *hash2;
uintptr_t hash_addr[HASH_CMP_NUM] = {SECURE_FW_HASH_SAVE_ADDR, CR52_IPL_HASH_SAVE_ADDR};
for(i = 0U; i < HASH_CMP_NUM; i++)
{
/* Hash is placed SystemRAM by ICUMX IPL. */
hash1 = (uint8_t *)(hash_addr[i]);
hash2 = (uint8_t *)(hash_addr[i] + HASH_SIZE);
for(j = 0U; j < HASH_SIZE; j++)
{
/* Compare Hash */
if(*hash1 != *hash2)
{
/* Hash unmatch. */
ERROR("Final Hash compare error!!\n");
panic;
}
hash1++;
hash2++;
}
}
#endif /* (RCAR_LSI == RCAR_V4H) || (RCAR_LSI == RCAR_V4M) */
}
/* End of function final_hash_cmp(void) */