小猫爪:i.MX RT1050学习笔记17-安全启动1-简介
小猫爪:i.MX RT1050学习笔记17-安全启动1-简介
1 前言
这段时间准备开始学习RT1050的安全启动系列,在简单了解了一下RT的安全机制后,突然意识到这相比之前的文章专题复杂了很多,接下来可能要花好几篇文章来将RT1050的安全启动专题记录下来了,让我们慢慢的开始吧。
2 加密和解密,数字签名
首先让我们简单的了解一下签名,加密和解密的基本知识。
2.1 加密和解密
加密说起来就非常简单了,就是使用相关算法将原始数据变换成另外一种形态。解密是一个加密反过程,使用相同算法将加密后的数据还原成原始数据。
如果光有算法的话,别人知道你使用的加密算法就能将你的数据还原,所以还需要秘钥的存在,我们只有同时知道秘钥和加密算法,才能对数据进行还原。加密秘钥和解密秘钥可以相同也不可能不同。如果相同,则使用的算法称为对称加密算法;如果不同,则使用的算法称为非对称加密算法,加密秘钥称为私钥,解密秘钥称为公钥,有些特殊的算法则可以私钥和公钥同时可以进行加密和解密。
(注意:相关算法的种类有很多,大家可以参考这篇文章了解一下目前的算法有哪些:链接:https://blog.****.net/liudongdong19/article/details/82217431)
2.2 数字签名
数字签名的作用是做数据验证的,说白了就是输入数据和钥匙通过一系列算法最终输出一段数据,这段数据就是数字签名。作用有三个:
①验证数据的完整性
②认证数据来源
③抗否认
举个简单的例子:A想发送一段数据给B,这个时候A需要:
①生成公钥和私钥对(一对一的关系),发布公钥,私钥保密
②使用相关摘要算法针对原始数据计算摘要,得到摘要
③使用私钥通过加密算法对摘要进行签名,得到数字签名,或者叫证书
④把原始数据和数字签名一起打包发送给B
这个时候,B接收A发送的数据后,需要:
①知道A发布的公钥
②使用相同算法计算原始数据的摘要
③使用A的公钥对数字签名进行解密得到A原始的摘要
④对比自己算出的摘要和解密数字签名后的摘要,如果一致,则说明数据合法
如果接收数据不完整,则双方计算出的摘要肯定不一致,而且因为公钥和私钥是钥匙对,也就是说全世界只有一对,私钥全世界又只有A知道,所以B可以通过签名和公钥可以确定数据来源于A,A也不能否认数据是自己发的。
3 RT1050安全简介
对于安全启动,RT1050则支持多种安全保护方式,具体有以下几种方式:
①HAB签名认证
②HAB签名认证与HAB加密
③单引擎BEE加密
④双引擎BEE加密
下面让我对这些方式简单的一一道来:
3.1 HAB签名认证
HAB的全称为High-assurance Boot,直译过来就是高可信度启动,名字很夸张,其实说白了,HAB就是集成在BootROM的一段代码。
这种模式,并不是对Falsh中的image进行加密,而是对烧写到Flash中的image进行合法性认证,检测image是否被恶意破坏或篡改,如果检测到image未经授权,即不合法,则MCU便不会执行该image。
我们使用非对称加密(RSA)来实现HAB功能。加密工具会生成私钥和相应的公钥对。然后私钥用于生成镜像的数字签名也就是证书,公钥也附加到镜像上。在程序启动时,公钥用于解密证书,用于检查比较证书和镜像是否匹配。只有当证书和镜像匹配时,镜像才被视为“受信任”,否则,镜像被视为“不安全”,不允许加载和运行,此过程称为身份验证。黑客只能访问公钥,根据非对称加密的属性,私钥不能从中推断出来。如果没有私钥,黑客就无法为其恶意镜像附加有效证书。我们还将公钥的摘要值(哈希)烧录到RT芯片的eFuses,认证证书前还需要将eFUSE中公钥摘要和镜像中的公钥摘要进行比较来认证公钥的真实性,所以公钥摘要一旦烧写,就无法修改,这可以防止黑客使用另一对私钥和公钥作弊的可能性。
实现HAB签名流程如下:
①产生公钥私钥,并且将公钥摘要值烧写到eFUSE
②使用私钥对镜像摘要加密生成镜像证书
③将带有HAB信息的完整的镜像烧写进FLASH中
所以带有HAB签名的镜像应该具有以下内容:可以看到带有HAB认证的镜像对比普通镜像多了CSF部分,回顾到镜像分解那一章提到了CSF是给安全启动服务的,这个时候首尾呼应了。
接下来来了解一下RT1050 HAB签名的启动过程,流程如下图所示:
①将flash中image摘要进行HASH运算生产一个摘要值;
②使用已经在efuse中的烧写好的公钥的摘要值与flash中的Public Key进行匹配,如果匹配成功,则进行下一步。
③使用公钥解密flash中证书Certificate,得到镜像摘要值与第一步中生成的镜像摘要值进行比对,如果比对成功则说明镜像合法。
3.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还需要另一把钥匙OTPMK(OTP Master Key,也叫做SNVS Key),该钥匙用于创建**的加密区域DEK blob,所以这把钥匙只能由MCU内部的DCP或BEE访问,这意味着每个芯片的DEK blob是唯一的,而且只有i.MX RT上的DCP才能拿到正确的DEK。
所以让我们来对比一下只有HAB签名认证时,镜像发生了哪些变化,第一镜像中的APP数据从一开始的明文变成了密文,第二镜像中多了DEK经过加密后生成的DEK blob。(注意:DEK Blob是不需要我们提前指定的,因为我们不知道OTPMK,这个钥匙在芯片出厂的时候就决定了,而且读不出来的,只能由MCU内部的DCP或BEE访问,所以DEK Blob是Flashloader接收到DEK后会对其进行加密生成相应的DEK Blob并下载至FLASH中。)
所以现在存储在FLASH中的镜像结构如下:
在这种模式下,APP数据加密流程和解密流程如下图(其中认证流程与之前一致,此次省略认证过程,只有APP加密和解密的流程):
加密流程如下:
①生成DEK,对镜像中的APP数据加密形成密文型的APP
②RT1050的DCP得到DEK后通过OTP Master Key对其进行加密并生成DEK Blob
解密流程如下:
①RT1050的DCP对镜像中的DEK Blob进行解密得到DEK
②然后使用DEK对APP密文进行解密得到最终APP明文
3.3 单引擎/ 双引擎 BEE加密
对于HAB加密,该种加密只能用在non-XIP形式下使用,也就是说bootROM先把APP数据密文全部从FLASH中拷贝到RAM中,然后再使用HAB对其进行解密,这个时候的“FLASH”不限种类,也就是所有的启动存储设备都支持。而对于XIP执行来说,HAB加密的方式则是不能使用了,这个时候BEE加密就出现了(BEE加密可以支持XIP和non-XIP,但是只能支持FlexSPI NOR中启动的Image)。
BEE(Bus Encryption Engine)就是总线加密引擎,是集成在RT1050内部的一种硬件加密手段。
在执行BEE加密XIP之前,bootROM需要正确设置BEE控制器,这些配置参数存储在保护区域描述符块PRDB(Protection Region Descriptor Block)中,而整个PRDB使用AES-CBC-128模式加密,这个用于加密PRDB的AES**存储在KIB(Key Info Block)中,而KIB被eFUSE中提供的AES**加密为EKIB(Encrypted KIB)。
整个或部分软件图像使用自定义的私钥(PVK)加密,然后将这个加***烧录到片上eFUSE中,这个**被限制为仅能使用解密引擎(BEE)访问(注意:加密KIB和加密镜像的私钥是一个私钥,也就是BEE控制器指定的私钥)。
在bootROM初始化BEE控制器之后,存储在FLASH中的加密和未加密的数据可以被动态访问。每个芯片都可以使用一个唯一的**来加密程序镜像,因此每个镜像只能用正确的**在芯片上引导,从而防止镜像盗用。
RT内部有两个BEE加密引擎分别为BEE引擎0和BEE引擎1,所以BEE加密又分为单引擎加密和双引擎加密。
单引擎加密: 通过上面的描述中我们知道,BEE加密使用用户自定义的**进行加密,加密时将该**烧录到MCU内部的eFUSE中,其实,也可以使用MCU内部的TIPMK(SVNS Key)作为**,可以通过配置eFUSE来选择,该**在芯片出厂时已预先烧录,无法更改,具有高级别访问权限,只能由内部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加密的镜像来说,它比一般镜像多了EKIB和EPRDB,具体分布地址如下:
Offset | Description |
---|---|
0x0000 - 0x01FF | FlexSPI Serial NOR Configuration Block |
0x0200 - 0x03FF | Reserved |
0x0400 - 0x041F | Encrypted Key Info Block 0 (EKIB0) |
0x0420 - 0x047F | Reserved |
0x0480 - 0x057F | Encrypted Protection Region Descriptor Block 0(EPRDB0) |
0x0580 - 0x07FF | Reserved |
0x0800 - 0x081F | Encrypted Key Info Block 1(EKIB1) |
0x0820 - 0x087F | Reserved |
0x0880 - 0x097F | Encrypted Protection Region Descriptor Block 1(EPRDB1) |
0x0980 - 0x0FFF | Reserved |
所以我们之前在介绍对于FlexSPI Serial NOR FLASH 启动流程的时候,其实漏掉了一个步骤,bootROM在读取FCB数据重新初始化FlexSPI接口后还会读取BOOT_CFG[1]的值判断此次启动是否为加密XIP,如果是加密XIP,则会继续读取EKB和PRDB并对其进行解密,然后初始化BEE,然后继续启动。
关于RT1050的安全启动就介绍到这里了,后面则会介绍这些安全启动的具体实现方法。待续。。。。。。。