一、背景
NXP宣布推出i.MX RT系列处理器,内核基于 Arm-Cortex M7,运行主频高达600MHz,3020的coremark跑分,令人咋舌。i.MX RT1020/1050/1060系列MCU没有片内FLASH,从而可以让用户根据实际需要灵活搭配不同容量、不同厂家的外置FLASH 存储器。飞凌嵌入式刚刚发布的OK1061-S、OK1052-C采用的是4MB/16MB串行NorFlash,QSPI接口。使用外置FLASH的方案,也不用担心里面的程序有被窃取的风险,这些问题,NXP在设计芯片之初,都已经考虑在内。下面我们来了解一下,如何给外置Falsh进行加密。
二、我们来介绍一下Flash加密的几种方法:
1、HAB(High-Assurance Boot)签名认证
这种模式,并不是对Falsh中的image进行加密,而是对烧写到Flash中的image进行合法性认证,检测image是否被恶意破坏或篡改,如果检测到image未经授权,即不合法,则MCU便不会执行该image。
我们使用非对称加密来实现HAB功能。加密工具会生成私钥和相应的公钥对。然后私钥用于加密我们想要发布的镜像,此加密为镜像生成唯一标识符,称为证书。公钥也附加到镜像上。在程序启动时,公钥用于解密证书。用于检查比较证书和镜像是否匹配。只有当证书和镜像匹配时,镜像才被视为“受信任”。否则,镜像被视为“不安全”,不允许加载和运行。此过程称为身份验证。黑客只能访问公钥,根据非对称加密的属性,私钥不能从中推断出来。如果没有私钥,黑客就无法为其恶意镜像附加有效证书。我们将公钥的摘要值(哈希)烧录到RT芯片的eFuses。一旦烧写,就无法修改。这可以防止黑客使用另一对私钥和公钥作弊的可能性。
下面我们通过图标来简单描述一下此过程。
1)产生公钥私钥,并且将公钥摘要值烧写到efuse:
2)使用私钥对镜像摘要加密生成镜像证书:
3)安全启动时,对镜像证书进行认证的过程:
上图中,一个正常做过签名的镜像文件在flash存在形式应该是由image(包括ivt,bootdata、dcd和应用image),HABdata(包括Public Key、Certificate和CSF)两部分组成,如图:
系统启动时,MCU内部ROM的BootLoader启动程序主要进行如下工作:
1) 将flash中image摘要进行HASH运算生产一个摘要值;
2) 使用已经在efuse中的烧写好的Public Key的摘要值与flash中的Public Key进行匹配,如果匹配成功,则进行下一步。
3) 使用Public Key解密flash中证书Certificate,得到镜像摘要值与第一步中生成的镜像摘要值进行比对,如果比对成功则说明镜像合法。
2、加密启动(HAB签名认证与HAB加密)
加密启动是签名认证与加密的组合启动。
这种模式属于中级安全模式,签名认证是对iamge合法性验证,而HAB加密就是对flash中的用户image明文通过加密算法转换为密文。HAB加密使用的AES-128算法,其对应的128bits的AES-128 Key不是由用户自定义的,而是HAB加密工具自动随机生成的,并且每一次加密操作生成的AES-128 Key都是不一样的,即使你没有更换输入的原始image。我们的image实际就是使用AES-128 Key这把钥匙进行加密的,我们称这把钥匙为:DEK(Data Encryption Key),这把钥匙存在于加密工具所在的PC机。既然DEK每一次都不一样而且存在于个人电脑中,那么MCU在启动的时候是怎么找到这把钥匙解密的呢?对,我们需要把这把钥匙的信息附加在image里面,烧写到flash中,待到启动的时候MCU的bootLoder程序会先把钥匙从image中取出来。那么问题来了,既然bootLoder能够取出钥匙,那么作为黑客的你我能不能也读出flash中的image取出DEK呢,当然没那么简单,因为这块存储DEK的区域也是经过加密的,想要取出DEK还需要另一把钥匙Master Secret Key,该钥匙用于创建密钥的加密区域blob(DEK blob),这把钥匙只能由MCU内部的DCP或BEE访问。这意味着每个芯片的blob是唯一的。在启动引导时,blob以这样的方式封装,即只有i.MX RT上的DCP才能访问DEK。下面的这个图显示了加密解密的过程:
所以一个做过加密启动的镜像存在与flash中应该是组织结构:
3、加密XIP(单引擎/双引擎BEE加密)
i.MX RT boot rom支持串行nor flash上的XIP(Execute-In-Place,在flash本地执行代码),直接使用BEE控制器提供的动态解密功能(使用aes-ctr-128或aes-ecb-128加密算法)。在执行加密XIP之前,引导ROM需要正确设置BEE控制器,这些配置参数存储在保护区域描述符块prdb中,而整个prdb使用aes-cbc-128模式加密,这个用于加密prodb的aes密钥存储在密钥信息块(kib)中,而kid使用efuse中提供的aes密钥加密为ekib)。整个或部分软件图像使用自定义的私钥(pvk)加密(然后将密钥烧录到片上efuse块中),这个密钥被限制为仅能使用qspi解密引擎(bee)访问。在ROM代码初始化BEE块之后的引导过程中,存储在qspi flash中的加密和未加密的数据可以被动态访问。每个芯片都可以使用一个唯一的密钥来加密程序镜像,因此每个镜像只能用正确的密钥在芯片上引导,从而防止镜像盗用。
i.MX RT内部有两个BEE加密引擎分别为BEE引擎0和BEE引擎1,所以BEE加密又分为单引擎加密和双引擎加密。
单引擎加密: 通过上面的描述中我们知道,BEE加密使用用户自定义的密钥进行加密,加密时将该密钥烧录到MCU内部的efuse中,其实,也可以使用MCU内部的SVNS Key作为密钥,该密钥在芯片出厂时已预先烧录,无法更改,具有高级别访问权限,只能由内部DCP或BEE模块访问。
单引擎加密可以自定义设置加密区域和选择BEE加密引擎(使用 SVNS Key作为密钥时只能选择引擎0,使用自定义密钥时,即可选择引擎0也可选择引擎1)。在加密过程中,加密工具会将这些配置信息存储到prdb块中。密钥信息存储在kib信息块中。
双引擎加密: 双引擎加密使用两个用户自定义的密钥,分别赋予引擎0和引擎1使用,用户可以分别自定义设置他们的加密区域,加密时加密工具会将这些信息分别存储在prdb0和prdb1中。密钥信息存储在kib0和kib1中。
下面简单看一下解密流程:
BEE控制器通过读取MCU内部efuse烧录的用户密钥PVK,使用该PVK解密EKIB(Encrtpted KIB)密钥信息块,将其中的密钥取出,用于解密EPRDB(Encrtpted PRDB),获得BEE控制器的参数配置信息,BEE控制器通过此配置信息将密文image进行动态解密。
做过BEE加密的镜像存在于flash中应该是这种组织结构:
三、总结
上面简单介绍了一些关于Flash加密原理,现在我们总结一下一共有四中加密模式。
模式一:HAB签名认证。
模式二:HAB签名认证和HAB加密。
模式三:SNVS Key单引擎BEE加密。
模式四:用户自定义Key单引擎BEE或双引擎BEE加密。
这四种加密模式安全等级依次升高。其中HAB加密属于静态加密,是由片内ROM里的Boot程序将加密后的密文image全部解密成明文image,copy到MCU内存ram中再执行,而BEE加密是由MCU芯片内部的BEE控制器对密文image进行边解密边执行,属于动态加密(如果是Non-XIP Image,则解密执行流程与HAB加密类似)。
原文链接:https://www.forlinx.com/article-new-c22/346.html