下面使用LPC55S16-EVK和KEIL对非连续子区域的擦除和读写进行了测试:
步骤一:PRINCE初始化(使能PRINCE区域0和两个非连续的子区域;生成Key,IV码;使能加密功能)
//设置SR_ENABLE寄存器,SR_ENABLE=0X28000000,使能子区域(0x30000-0x32000,0x34000-0x36000)加密特性。
status=PRINCE_SetRegionSREnable(PRINCE(prince_region_t)region0,0X28000000);
//选择PRINCE加密区域region0
PRINCE_SetRegionBaseAddress(PRINCE_Type*base,prince_region_tregion0,uint32_t 0X0)
//生成PRINCE region0加密区域的key
Status=FFR_KeystoreGetKC(&flashInstance,&keyCode[0],kFFR_KeyTypePrinceRegion0);
status=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)
步骤二:选择两块非连续的子区域(0x30000-0x32000,0x34000-0x36000)。先对其中一块子区域0x30000-0x32000进行擦除然后向该区域写入数据。输出结果: 擦除和写操作全部成功正确,见图二。
//擦除0x30000-0x32000地址区域
status=PRINCE_FlashEraseWithChecker(&flashInstance,0x30000,0x2000,kFLASH_ApiEraseKey);
//对0x30000-0x32000地址区域执行写操作
status=PRINCE_FlashProgramWithChecker(&flashInstance,0x30000,(uint8_t*)prince_iv_code,0x2000);
步骤三:再对另一块子区域0x34000-0x36000擦除然后写入数据,擦除和写入操作失败,输出结果如图二所示。
//擦除0x34000-0x36000地址区域
status=PRINCE_FlashEraseWithChecker(&flashInstance,0x34000,0x2000,kFLASH_ApiEraseKey);
//对0x34000-0x36000地址区域执行写操作
status=PRINCE_FlashProgramWithChecker(&flashInstance,0x34000,(uint8_t *)prince_iv_code,0x2000);
图二
2. 错误原因分析
根据用户手册相关相关章节(49.16.1 Functional details 部分),每个加密区域( Region )都有对应的key和IV码,Key和IV码共同起作用实现了PRINCE的加解密功能。
以PRINCE的region 1为例,每次对该区域的子区域进行擦写操作时都要生成相应的key1和IV1。在执行非连续的子区域进行操作时,如果对其中一块子区域进行擦除操作,操作完成后会更新IV code,这样在对另一块子区域进行读写操作时原有IV和更新后的IV不匹配导致无法正确加解密。
3. 使用建议
使用PRINCE功能,用SR_ENABLE寄存器设置加密区域时,建议设置加密子区域为连续的。在对加密子区域执行擦除时,要对所有使能的连续加密区域进行统一擦除操作,避免对其中部分加密子区域单独操作。一个子区域的大小为8K,故我们要保证写入的数据与加密区域8K对齐。