当我们使用 LPC55Sxx PRINCE 功能时,我们需要通过设置 SR_ENABLE 寄存器来启用 PRINCE 子区域“加密”。如果我们“加密”启用不连续的子区域并擦除其中的一部分,我们可能会发现我们无法再擦除/读取/写入其他“加密”子区域。本文将讨论如何解决这一现象。
图 1
根据 LPC55Sxx UM,每个 PRINCE 区域都有其 SR_ENABLEx 寄存器。该寄存器支持对加密区域 0 的每个子区域的数据进行 PRINCE 加密和解密。该字段中的每个位都支持加密区域 0 中偏移量为 8kB*n 的子区域,其中 n 是位数。例如,当我们设置SR_ENABLE0=0X00000005时,PRINCE区域0子区域1和子区域3被设置为加密区域。当从这些子区域读出数据时,PRINCE会自动解密数据。
现在我们将测试不连续子区域擦除/读取/写入。
主板:LPC55S16-EVK
IDE: Keil MDK v5.29
步骤1:PRINCE初始化:启用PRINCE区域0和两个不连续的子区域;生成密钥、IV码;启用加密。
//设置 SR_ENABLE , SR_ENABLE=0X28000000,使能子区域(0x30000-0x32000,0x34000-0x36000)加密。
状态=PRINCE_SetRegionSREnable(PRINCE( prince_region_t )region0,0X28000000);
//为 region0 选择 PRINCE 加密
PRINCE_SetRegionBaseAddress(PRINCE_Type*base,prince_region_tregion0,uint32_t0X0)
//生成 PRINCE region0 加密密钥
状态=FFR_KeystoreGetKC(&flashInstance,&keyCode[0],kFFR_KeyTypePrinceRegion0);
状态=PUF_GetHwKey(PUF,keyCode,sizeof(keyCode),kPUF_KeySlot2,rand());
//生成 PRINCE region0 加密 IV_code
status=PRINCE_GenNewIV(kPRINCE_Region0,&prince_iv_code[0],true,&flashInstance)
//将 IV 代码加载到 PRINCE
status=PRINCE_LoadIV(kPRINCE_Region0,&prince_iv_code[0])
//启用 PRINCE 加密
PRINCE_EncryptEnable(PRINCE)
步骤2:选择两个不连续的子区域(0x30000-0x32000,0x34000-0x36000)。擦除其中一个(0x30000-0x32000),然后将数据写入该子区域。
输出:擦除和写入均成功。见图2。
//擦除0x30000-0x32000子区域
status=PRINCE_FlashEraseWithChecker(&flashInstance,0x30000,0x2000,kFLASH_ApiEraseKey);
//写入0x30000-0x32000子区域
status=PRINCE_FlashProgramWithChecker(&flashInstance,0x30000,(uint8_t *)prince_iv_code,0x2000);
步骤3:擦除并写入另一个子区域(0x34000-0x36000)
输出:擦除和写入失败。见图2。
//擦除0x34000-0x36000子区域
status=PRINCE_FlashEraseWithChecker(&flashInstance,0x34000, 0x2000,kFLASH_ApiEraseKey);
//写入0x34000-0x36000子区域
status=PRINCE_FlashProgramWithChecker(&flashInstance,0x34000, (uint8_t *)prince_iv_code,0x2000);
根据UM11126( 49.16.1功能细节) ,每个加密区域都有自己的SKEY和IV代码。PRINCE在加密或解密加密区域子区域中的数据时,会同时使用SKEY和IV。
比如对于PRINCE的region1,每次执行擦除操作后,都会生成新的Skey1和IV1,因此在对另一个子区域执行擦除/读/写操作时,旧的IV1和新的IV1不匹配,导致PRINCE无法正确解密。
我们建议用户使用 SR_ENABLE 来设置连续的加密子区域。当需要进行擦除操作时,将所有加密子区域一起擦除,避免擦除部分子区域。一个子区域大小为8K,请确保擦除/写入地址8K对齐。
感谢johnwu的建议