1. 4kb eeram上的csec密钥和用户数据
使用s32k148,将启用cse模块进行安全引导。根据应用说明(“使用s32k148 flexnvm存储器”,an12003,版本0,2017年7月),在第3.3节中,64 kb的flexnvm用作闪存(eeprom备份和密钥存储在一起),csec使用最多512字节的密钥存储,剩下的3.5 kb eeram用于eeprom和启用csec。在这种用法中,用户数据是否以某种方式通过覆盖或删除注册密钥而保留。简而言之,记录密钥的512字节是随机记录在eeram中,还是记录在特定位置,如4kb flexram的开始/结束位置?
-> 如果分配的csec空间为512b,则flexram(eeprom)中将无法访问空间0x14000e00-0x14000fff。对该区域的任何访问都会生成总线故障异常。
2. 关于csec安全引导和顺序引导模式的问题。
测量从复位引脚释放到高电平的安全启动时间,不同boot_size和clock时钟对于安全启动时间有所不同。当安全启动开始启动时(即csec正在计算cmac),mcu内核保持在复位状态,复位引脚也保持在低电平状态,直到cmac计算完成。
3. 实现 sha256
在s32k1上面的csec 模块支持 aes128 引擎,但不支持 sha256。但是用户可以参考如下代码实现它。
https://github.com/armmbed/mbedtls/blob/v2.16.8/library/sha256.c
4. 当在 s32k146中使用 csec模块的时候,程序访问 cse_pram 空间,在调试模式下它将进入异常中断。
#define reg_write32(address, value) ((*(volatile uint32*)(address))= (value))
#define crypto_pram_hdr_addr32 (0x14001000u)
reg_write32(crypto_pram_hdr_addr32, u32commandheader);
上述代码高亮部分表示写入 pram命令,会导致程序进入异常中断。
-> 通过检查sim_sdid[features]寄存器,判断s32k芯片是否支持 csec。为了使能 csec 模块,内存需要分区用于eeprom,ftfc寄存器需要编程。
5. csec模块pram格式
在应用笔记 an5401中,有的是通过 pram 页1读取数据,而有的是通过 pram页2输出数据,这两种方法有什么不同的吗?
-> 参考手册里面的 csec命令
https://www.nxp.com/docs/en/reference-manual/s32k-rm.pdf
这是cmd_get_id命令的描述,可以在其中看到使用了哪些页及其目的是什么:
如下是 an5401文档中的参考代码部分。
6. csec不能恢复到工厂模式
通过 csec_drv_dbgchal恢复到工厂模式失败,返回 status_sec_key_write_protected。这里keys不能被配置为写保护,否则将不能被擦除。
https://www.nxp.com/docs/en/application-note/an12130.pdf
7. s32k144 闪存分区问题
使用s32k144evb-q100和sdk3.0.0以及s32ds进行arm调试。当使用opensda工具调试闪存时,可以擦除闪存并完成分区闪存,但当使用j-link调试闪存时无法再次擦除闪存和分区闪存,必须先使用类似j-flash的工具擦除闪存。如何使用j-link擦除闪存和分区闪存。是否有调试配置的任何设置?
->在使用sdk api对flexnvm进行分区时,由于启用了csec。
如果启用csec,则无法通过命令“全部擦除”或其他ftfc命令擦除flexnvm。如果要擦除flexnvm,唯一的方法是使用csec命令将flexnvm复位为出厂状态。有关更多信息,请参阅an5401。
https://www.nxp.com/webapp/download?colcode=an5401
https://www.nxp.com/webapp/download?colcode=an5401sw&doclang=en
#include csec_functions.h
#include csec_macros.h
#include csec_keys.h
uint32_t dbg_challenge_out[4] = {0,0,0,0};
int main(void)
{
uint16_t __attribute__((unused)) csec_error = 0; //1 means no error
csec_error = init_rng(); /* initialize the random number generator before generating challenge */
//to erase all keys and reset the part to the factory state
csec_error = dbg_chal(dbg_challenge_out); /* generate the challenge */
csec_error = dbg_auth(dbg_challenge_out); /* issue the authorization */
while(1);
/* to avoid the warning message for ghs and iar: statement is unreachable*/
#if defined (__ghs__)
#pragma ghs nowarning 111
#endif
#if defined (__iccarm__)
#pragma diag_suppress=pe111
#endif
return 0;
}
由于 csec 模块所有密钥都只能 csec 模块管理,这样才能确保密钥安全的安全性。虽然密钥实际存储区域是在模拟 eeprom 中,但由于这段区域是由 csec 管理并且对用户是不可见的,所以也无法通过直接对 dflash 编程的方式写入密钥。在量产时,可以使用一份专用于写入密钥的程序,通过先刷写这份程序,等写入密钥后,再刷写正式的应用程序即可。需要注意的时,两份程序需要有一致的 d-flash 分区策略。当然也可以通过诊断服务的方式加载密钥。先脱机计算出密钥的 m1~m5 值,然后通过诊断服务(如 2eh服务)将 m1~m3 加载至 csec 模块中,并通过 m4 和 m5 验证是否加载成功。由于不能通过 m1~m3 值逆推算出密钥值,所以这种方式也是安全的。由于使能 csec 模块后,只能通过 csec 模块的恢复命令(使用调试器也不行)才能擦除 d-flash 数据并恢复 d-flash 至出厂状态,所以如果在量产后需要再次擦除 d-flash,或者重新对 d-flash 进行分区等,可以在用户代码中加入相关程序,通过触发这段程序来使用 csec 模块的命令擦除 d-flash。csec 模块对 p-flash的重新编程没有影响。
7. 为csec操作分配密钥大小后,需要按照an5401 4.5中列出的步骤将闪存重置为出厂状态。此外,还提供了一些连接/擦除/编程到s32k器件的提示。
(https://www.nxp.com/docs/en/application-note/an12130.pdf )
如果没有按照正确的步骤在分配密钥后擦除flash,器件可能会被锁定,并且无法解锁。
如参考手册所述,分区操作在整个产品周期中最好只执行一次。
可以通过dbg_chal 和 dbg_auth 销毁分区,不用擦除flash。
当未分配csec时,没有办法在不擦除所有键的情况下删除分区? 因为只需要擦除数据flash 以及flash ifr。但是,一旦数据flash 已经为eeprom分区,ftfc擦除flash 块命令就不能擦除数据flash。
运行dbg_chal和dbg_ auth命令会擦除所有密钥,包括boot_mac和boot_ mac_key。在没有这两个参数的情况下,不会执行安全引导过程,因此应用程序可以自由执行,并且mcu 不会处于复位状态。
dbg_chal/dbg_ auth即使在严格启动模式处于活动状态时也可以工作,假设所有密钥都没有写保护。这不会锁定 mcu。
成功执行dbg_chal/dbg_ auth后,所有密钥将被擦除,安全引导处于非活动状态。可以使用任何方式(串行、并行、严格顺序)再次激活安全引导。
注意:对于严格顺序模式,自动mac计算是不可能的。在激活严格顺序引导之前,必须计算并存储boot_mac。否则将锁定器件。mac可通过csec本身或pc离线计算。有关更多详细信息和代码示例,请参阅 an5401。
8. 当执行flash_drv_deflashpartition 函数的时候, ftfx_fstat 是ftfx_fstat_accerr_mask。
while((ftfc->fstat&ftfc_fstat_ccif_mask)==0u)
ftfc_fstat – 异常时,flash状态寄存器是 160, flash access error
flag 标志是 '1',但是正常状态是 128。flash已经分区,有如下原因导致 accerr位被置位。
已通过分区命令启用csec,则此时擦除所有块命令将无效(它也应返回accerr)。是否加载了密钥并不重要。一旦flash 分区,并且密钥大小不是 0,则需要使用cmd_dbg_chal和cmd_ dbg_ auth命令来销毁分区。为此,需要知道master_ecu_key。如果尚未加载master_ecu_key,则需要加载,然后可以使用cmd_dbg_chal和cmd_ dbg_ auth命令,别无选择。可以检查sim模块中的闪存配置寄存器1(fcfg1),查看器件是否已分区。
如果flash已经分区、csec已经使能,flash_drv_eraseallblock不能工作。唯一的方案是在了解master_ecu_key的情况下使用dbg_chal 和 dbg_auth 命令恢复。
可以参考如下例子中的 erasekeys()函数。s32ds.3.4s32dssoftwares32sdk_s32k1xx_rtm_4.0.2exampless32k144driver_examplessystemcsec_keyconfig
在hsrun模式(112mhz下),csec (安全) 或者 eeprom 擦写将触发错误标志。因为在这种情况下不允许同时使用。器件需要切回到 run模式 (80 mhz) 来执行 csec(安全) 或者 eeprom 写/擦除。
flash 内存安全在 csec 和non-csec 器件上都支持,sim_sdid[7]表示 csec 是否在器件上支持。csec 和non csec 用户需要运行 pgmpart 命令来配置 keysize。针对 non csec 用户,key size 必须配置为 0。
整个 eeeram的空间是减小,为了存储用户 keys的需要。用户密钥空间实际上成为eeeram中的不可寻址空间。 针对具有 csec或者没有 csec的器件,如果 key size为0,则csec_pram访问是不允许的。keysize为零时,是普通eeprom分区么,直接mass erase就恢复了。通过操作 flash_drv_eraseallblockunsecure函数恢复,或者硬件将reset引脚短接,然后通过jlink等外部工具擦除mcu内部的 flash。
如果s32k146板默认存在分区,通过判断(sim->fcfg1[feature])确定分区,如果要使用新的分区操作,需要擦除旧的分区,如果不擦,在调试csec init_rng或者erase all key的时候会进入defaultisr中断,可以通过上述mass erase方式恢复(keysize为零的情况)。然后重新分区使能 csec模块,操作初始化随机数以及加解密,预置秘钥操作。
程序分区命令准备flexnvm块用作数据闪存、模拟eeprom备份或两者的组合,并初始化flexram。程序分区命令不能从flash 启动,因为在程序分区命令执行期间无法访问flash 资源。与程序分区命令的执行相关的更改在下次复位后生效。在启动其他ftfc和csec命令之前,预计将为新器件运行程序分区命令。
注意:虽然flexnvm可以用不同分区,但其目的是在给定应用程序的整个生命周期中使用一次分区选择。flexnvm分区代码选择影响器件的耐久性和数据保留特性。中断程序分区操作(由于断电、复位、电源超出指定的操作范围或任何其他原因)会使分区代码处于不确定状态。用户必须采取适当的应对措施,以防止程序分区操作中断时数据丢失。
对于未启用csec的部件,flash keysize的数量必须配置为2'b00。对于启用csec的器件,flash密钥的数量是用户可配置的,但该空间将假设存在master_ecu_key、boot_mac_key和boot_ mac(如果启用了任何密钥),因此将占用可用20个密钥槽空间中的3个密钥槽。这导致在1到17个用户keys的范围内留下键槽。对于未启用csec的部件,密钥分配必须设置为零密钥(2'b00),否则该命令将返回错误。
注:对于具有csec的器件,一旦分配了flash密钥(无论是否初始化),she规范中不带认证将不能擦除flash 密钥的要求将适用。这意味着在擦除数据flash(所有flash 密钥都备份在数据flash中的模拟eeprom中)之前,必须运行并通过身份验证(dbg_chal和dbg_ auth)命令(删除所有 flash密钥)。因此,擦除所有块和擦除所有块解锁将不起作用,如果所选块/扇区包括存储密钥,则擦除flash 块或扇区也不起作用。此外,如果任何 flash密钥受写保护,则无法擦除/删除它们,因此无法擦除数据 flash,身份验证过程也不会通过。
9. 在s32ds环境下,使用如下 rtm3.0.0的example flash_partitioning_s32k144的例子,在debug ram下运行就可以擦除以前老的 eeprom分区。(如果keysize为零,没有使用 csec的情况下)
/* including needed modules to compile this module/procedure */
#include cpu.h
#include clockman1.h
#include flash.h
volatile int exit_code = 0;
/* user includes (#include below this line is not maintained by processor expert) */
#include
#include
/* declare a flash config struct which initialized by flashinit, and will be used by all flash operations */
flash_ssd_config_t flashssdconfig;
/* data source for program operation */
#define buffer_size 0x100u /* size of data source */
#define flash_target1
uint8_t sourcebuffer[buffer_size];
/* function declarations */
void ccif_handler(void);
/* if target is flash, insert this macro to locate callback function into ram */
void ccif_callback(void)
int main(void)
{
/* write your local variable definition here */
status_t ret; /* store the driver apis return code */
uint32_t address;
uint32_t size;
uint32_t failaddr;
uint32_t i;
flash_callback_t pcallback;
#if (feature_fls_has_program_phrase_cmd == 1u)
#ifndef flash_target
uint8_t unsecure_key[ftfx_phrase_size] = {0xffu, 0xffu, 0xffu, 0xffu, 0xfeu, 0xffu, 0xffu, 0xffu};
#endif
#else /* feature_flash_has_program_longword_cmd */
uint8_t unsecure_key[ftfx_longword_size] = {0xfeu, 0xffu, 0xffu, 0xffu};
#endif /* feature_fls_has_program_phrase_cmd */
/*** processor expert internal initialization. don't remove this code!!! ***/
#ifdef pex_rtos_init
pex_rtos_init(); /* initialization of the selected rtos. macro is defined by the rtos component. */
#endif
/*** end of processor expert internal initialization. ***/
clock_sys_init(g_clockmanconfigsarr, clock_manager_config_cnt,
g_clockmancallbacksarr, clock_manager_callback_cnt);
clock_sys_updateconfiguration(0u, clock_manager_policy_agreement);
/* init source data */
for (i = 0u; i ocmdr[0u] |= mscm_ocmdr_ocm1(0x3u);
mscm->ocmdr[1u] |= mscm_ocmdr_ocm1(0x3u);
#endif /* s32k144_series */
#endif /* flash_target */
/* install interrupt for flash command complete event */
int_sys_installhandler(ftfc_irqn, ccif_handler, (isr_t*) 0);
int_sys_enableirq(ftfc_irqn);
/* enable global interrupt */
int_sys_enableirqglobal();
/* always initialize the driver before calling other functions */
ret = flash_drv_init(&flash_initconfig0, &flashssdconfig);
dev_assert(status_success == ret);
#if ((feature_fls_has_flex_nvm == 1u) & (feature_fls_has_flex_ram == 1u))
/* config flexram as eeprom if it is currently used as traditional ram */
if (flashssdconfig.eeesize == 0u)
{
#ifndef flash_target
/* first, erase all flash blocks if code is placed in ram to ensure
* the ifr region is blank before partitioning flexnvm and flexram */
ret = flash_drv_eraseallblock(&flashssdconfig);
dev_assert(status_success == ret);
/* verify the erase operation at margin level value of 1 */
ret = flash_drv_verifyallblock(&flashssdconfig, 1u);
dev_assert(status_success == ret);
/* reprogram secure byte in flash configuration field */
#if (feature_fls_has_program_phrase_cmd == 1u)
address = 0x408u;
size = ftfx_phrase_size;
#else /* feature_flash_has_program_longword_cmd == 1u */
address = 0x40cu;
size = ftfx_longword_size;
#endif /* feature_fls_has_program_phrase_cmd */
ret = flash_drv_program(&flashssdconfig, address, size, unsecure_key);
dev_assert(status_success == ret);
#endif /* flash_target */
/* configure flexram as eeprom and flexnvm as eeprom backup region,
* deflashpartition will be failed if the ifr region isn't blank.
* refer to the device document for valid eeprom data size code
* and flexnvm partition code. for example on s32k144:
* - eeedatasizecode = 0x02u: eeprom size = 4 kbytes
* - departitioncode = 0x08u: eeprom backup size = 64 kbytes */
ret = flash_drv_deflashpartition(&flashssdconfig, 0x02u, 0x08u, 0x0u, false, true);
dev_assert(status_success == ret);
/* re-initialize the driver to update the new eeprom configuration */
ret = flash_drv_init(&flash_initconfig0, &flashssdconfig);
dev_assert(status_success == ret);
/* make flexram available for eeprom */
ret = flash_drv_setflexramfunction(&flashssdconfig, eee_enable, 0x00u, null);
dev_assert(status_success == ret);
}
else /* flexram is already configured as eeprom */
{
ret = flash_drv_eraseallblockunsecure(&flashssdconfig);
dev_assert(status_success == ret);
/* re-initialize the driver to update the new eeprom configuration */
ret = flash_drv_init(&flash_initconfig0, &flashssdconfig);
dev_assert(status_success == ret);
}
#endif /* (feature_fls_has_flex_nvm == 1u) & (feature_fls_has_flex_ram == 1u) */
/* set callback function before a long time consuming flash operation
* (ex: erasing) to let the application code do other tasks while flash
* in operation. in this case we use it to enable interrupt for
* flash command complete event */
pcallback = (flash_callback_t)ccif_callback;
flashssdconfig.callback = pcallback;
/* erase the last pflash sector */
address = feature_fls_pf_block_size - feature_fls_pf_block_sector_size;
size = feature_fls_pf_block_sector_size;
ret = flash_drv_erasesector(&flashssdconfig, address, size);
dev_assert(status_success == ret);
/* disable callback */
flashssdconfig.callback = null_callback;
/* verify the erase operation at margin level value of 1, user read */
ret = flash_drv_verifysection(&flashssdconfig, address, size / ftfx_dphrase_size, 1u);
dev_assert(status_success == ret);
/* write some data to the erased pflash sector */
size = buffer_size;
ret = flash_drv_program(&flashssdconfig, address, size, sourcebuffer);
dev_assert(status_success == ret);
/* verify the program operation at margin level value of 1, user margin */
ret = flash_drv_programcheck(&flashssdconfig, address, size, sourcebuffer, &failaddr, 1u);
dev_assert(status_success == ret);
/* try to write data to eeprom if flexram is configured as eeprom */
if (flashssdconfig.eeesize != 0u)
{
address = flashssdconfig.eerambase;
size = sizeof(uint32_t);
ret = flash_drv_eeewrite(&flashssdconfig, address, size, sourcebuffer);
dev_assert(status_success == ret);
/* verify the written data */
if (*((uint32_t *)sourcebuffer) != *((uint32_t *)address))
{
/* failed to write data to eeprom */
exit_code = 1u;
return exit_code;
}
/* try to update one byte in an eeprom address which isn't aligned */
address = flashssdconfig.eerambase + 1u;
size = sizeof(uint8_t);
sourcebuffer[0u] = 0xffu;
ret = flash_drv_eeewrite(&flashssdconfig, address, size, sourcebuffer);
dev_assert(status_success == ret);
/* then verify */
if (sourcebuffer[0u] != *((uint8_t *)address))
{
/* failed to update data to eeprom */
exit_code = 1u;
return exit_code;
}
}
else
{
#if (feature_fls_has_flex_nvm == 1u)
/* erase a sector in dflash */
address = flashssdconfig.dflashbase;
size = feature_fls_df_block_sector_size;
ret = flash_drv_erasesector(&flashssdconfig, address, size);
dev_assert(status_success == ret);
/* verify the erase operation at margin level value of 1, user read */
ret = flash_drv_verifysection(&flashssdconfig, address, size / ftfx_phrase_size, 1u);
dev_assert(status_success == ret);
/* write some data to the erased dflash sector */
address = flashssdconfig.dflashbase;
size = buffer_size;
ret = flash_drv_program(&flashssdconfig, address, size, sourcebuffer);
dev_assert(status_success == ret);
/* verify the program operation at margin level value of 1, user margin */
ret = flash_drv_programcheck(&flashssdconfig, address, size, sourcebuffer, &failaddr, 1u);
dev_assert(status_success == ret);
#endif /* feature_fls_has_flex_nvm */
}
#ifdef pex_rtos_start
pex_rtos_start(); /* startup of the selected rtos. macro is defined by the rtos component. */
#endif
for(;;) {
if(exit_code != 0) {
break;
}
}
return exit_code;
/*** processor expert end of main routine. don't write code below!!! ***/
} /*** end of main routine. do not modify this text!!! ***/
void ccif_handler(void)
{
/* disable flash command complete interrupt */
ftfx_fcnfg &= (~ftfx_fcnfg_ccie_mask);
return;
}
void ccif_callback(void)
{
/* enable interrupt for flash command complete */
if ((ftfx_fcnfg & ftfx_fcnfg_ccie_mask) == 0u)
{
ftfx_fcnfg |= ftfx_fcnfg_ccie_mask;
}
}
运行调试模式,停止,然后再次运行会进入flash_drv_eraseallblockunsecure,关于 flash组件配置如下。
瑞萨电子株式会社宣布,其集成式开发环境已得到进一步增强
高频逆变器有什么优缺点,它有哪些分类
任意截面构件正截面承载力计算
如何制作一个电容耐压测试仪?
板对板连接器怎么选型?板对板连接器选型指南
关于CSEc安全引导和顺序引导模式的问题
快速ATP荧光检测仪让食品细菌迅速现身的方法
捷拓科技致力于隔离电源模块 洞悉智能设备趋势
中国移动多媒体广播智能网络监测系统的设计与实现[图]
宁畅携手英特尔 以液冷激活绿色算力
邦华U11手机高清箱图赏
美光科技Q3复苏化为泡影 欲持续减产换市场定价权?
科技创新 l 日晟万欣再获国家实用新型专利证书
集成电路编码器
前世界首富比尔盖茨辞去公司董事会职位 未来将专注慈善工作
预测全球晶圆厂投资今年将可到566亿美元
AC-DC电源设计要点剖析
苹果研究智能汽车识别交通员指挥手势
你知道和不知道的参与编程马拉松的十大益处
赛博朋克2077在Steam上开启了预载