STM32 加密思考

STM32的加密思路

  1. 使用系统启动程序STM32 Flash Loader demonstrator将Flash设置为读保护。
    所有以调试工具、内置SRAM或FSMC执行代码等方式对主存储器访问的操作将被禁止,只允许用户代码对主Flash存储器的读操作和编程操作(除了Flash开始的4KB区域不能编程)。用户代码允许自主编程可以实现IAP或者数据存储等功能。
    这样破解者将不能用调试工具、内置SRAM或者FSMC执行代码等方式读出Flash中的代码。破解者也不能使用系统启动程序读取代码,因为要解除读保护,将执行整个芯片的擦除操作。
  2. 主程序中使用设备ID保护
    即使将Flash设置为读保护,破解者也可以通过IAP下载自己的一段小程序,从而读出Flash中的内容。因此,还需要利用设备的唯一ID进行加密保护。在主程序中,加入对设备唯一ID的检测,这样即使破解者读出了芯片中的二进制码,也不能用这个二进制码去复制新的器件。
    具体实现方法:
    a. 在应用程序中定义1个(32位甚至更多)const变量,变量值全为0xFF。每次启动程序时,检查const变量值如果全为0xFF,就读器件的唯一ID,通过Flash编程写入该const变量中(因为全是0xFF,所以可以编程写入)。
    b. 在程序中多个地方检查const变量,如果变量值不为0xFF并且与设备ID不一致,就执行与功能无关代码(比如自擦除)。
    这样,即使破解者读出了芯片中的二进制码,因为这份二进制码包含了设备唯一ID,具有唯一性,所以不能复制到其他芯片中。
    为了避免破解者利用反汇编,根据芯片ID数据在二进制文件中查找对应相同数据的位置从而破解,可以将ID拆散成不同的组合,并且写到不同且不连续的地方。更进一步,可在程序中检测多份这样的分散ID,以增加反汇编的难度。或者将CPUID进行加密,Flash中存储加密后的结果。
  3. 固件的加密。有两种方案:一是传输过程的加密,另外一种是固件镜像的加密。具体方案待补充。

程序加密的实现

//加密后的CPUID
volatile const static uint32 CPUIDEncrypt = 0xFFFFFFFF;

//写入加密数据
void WriteEncrypt(void)
{
    //第一次烧写:将UID写入到Flash中
    if(CPUIDEncrypt==0xFFFFFFFF)
   {
        uint32_t CpuID[3];
        //获取CPU唯一的ID
        CpuID[0]=*(vu32*)(UID_BASE);
        CpuID[1]=*(vu32*)(UID_BASE+4);
        CpuID[2]=*(vu32*)(UID_BASE+8);

        //加密算法,很简单的加密算法
        uint32_t EncryptCode=(CpuID[0]>>3)+(CpuID[1]>>1)+(CpuID[2]>>2);
        FLASH_Unlock();
        FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
        FLASH_ProgramWord((uint32_t)&CPUIDEncrypt, EncryptCode);
        FLASH_Lock();
    }
}
//判断加密
bool JudgeEncrypt(void)
{
    uint32_t CpuID[4];
    //获取CPU唯一的ID
    CpuID[0]=*(vu32*)(UID_BASE);
    CpuID[1]=*(vu32*)(UID_BASE+4);
    CpuID[2]=*(vu32*)(UID_BASE+8);
    //加密算法,很简单的加密算法
    CpuID[3]=(CpuID[0]>>3)+(CpuID[1]>>1)+(CpuID[2]>>2);
    //检查Flash中的UID是否合法
    return (CPUIDEncrypt == CpuID[3]);
}
  • 将写入加密数据和判断加密两个功能分开。写入加密在PrsCtrlTask开始的地方;而判断加密分布到程序的各个角落。
  • 非常重要的是CPUID加密值的定义一定要加“volatile”类型,否则按速度优化编译,在判断加密值,不会重新读取加密值,导致判断出错。
volatile const static uint32 CPUIDEncrypt = 0xFFFFFFFF;
  • 在工程选项Options->Debugger->Download中选择: use flash loader,否则主程序中对Flash编程将不成功。
    [未完待续]
上一篇:go 获取linux cpuId 的方法


下一篇:、M/C/U/简单加/密方法、