文档路径:ReleaseDoc\zh\01.software\board\Hi3519AV100╱Hi3556AV100 V100 安全启动使用指南.pdf
从文档中截下的boot image的结构图如下:
依据上图可以知道,secure boot 可以保护ddr_init.bin 和 uboot.bin。保证这两部分没有被篡改。
但是,secure boot 也仅仅只是保护了这两部分,当uboot运行完后,会条用后面的kernel,rootfs等等,这些部分secure boot是没有保护的。
那么如果想保护后面的分区,怎么做呢?
将后面的分区用RSA算法对其签名,公钥的hash保存起来(可以存在海思OTP中供用户使用的部分,也可以明文保存在uboot中,因为secure boot 确保了uboot不能被别人修改),然后在uboot中去验证后面分区的签名是否正确,签名正确才表示后面分区的内容没有被篡改,才将控制权交给kernel。
最开始研究secure boot的时候是真的痛苦,现在回想起来是因为很多细节都不清楚导致。
Flash 的编程原理都是只能将 1 写为 0,而不能将 0 写为 1。所以在 Flash 编程之前,必须将对应的块擦除,而擦除的过程就是把所有位都写为 1 的过程,块内的所有字节变为 0xFF。
它是个存储器,可以保存数据,你可以把它当做一个特殊的flash。
往里面写数据具有不可逆性。
什么叫不可逆性?上面已经介绍了,flash在烧写过程中只能将1写成0。而OTP这个特殊的flash里面最开始全部是1,你只能将1写成0。
你可能在想,无全部擦除不就行了?不行,OTP将1写成0的过程,是在内部就是用高温将连接丝烧断。这个过程不可逆!
用户可以在OTP里保存一些特定的信息,例如软件版本号,硬件版本号,密钥等信息。这些信息肯定是不希望被别人修改的,所以用OTP保存。
1.对于海思芯片里面的OTP,是包含在海思芯片内部的,是整个芯片的一部分,不是一个外围设备。
2.OTP中有一部分是只供CPU用的。
3.OTP中还有一部分是供用户用的。
我们保存在OTP中的密钥肯定是不希望别人知道的,对吧,密钥,肯定得保密(不可读)呀。也就是说:
1.这个OTP我们要可写,因为我们要往OTP中写如密钥。
2.这个OTP我们希望不可读,如果可读,别人也去读取OTP里面的内容,我的密钥不就泄露了嘛。
上面两点听起来好像很合理是吧。但是仔细想一想,如果OTP完全不可读,那要它干嘛?反正没人,也没东西知道它里面到底存了些啥。
所以,这个OTP不是不可读,而是不可以被除了CPU以外的东西读。也就是说,OTP里面存的信息(密钥)我们只希望被CPU知道,其他人/东西一概不知道。
这就是那部分只供CPU使用的OTP。笼统的说,它是writeonly的。但是严格来说,它可读,只是只能被CPU读。
这部分很好理解,有些信息不是秘密,只是不希望让别人修改(例如软件版本号,硬件版本号)等,这些写在供用户使用的OTP区域即可。这样可读写,但是不能修改。
这个问题在最开始研究的时候我也没整明白,所以总觉得很难受。
CPU在上电之后会地址0x0开始执行,好多资料都是这样说的,是吧。怎么说呢,这句话也对,但是很容易引起误解。
我对这句话的误解就是,0x0对应的是flash的起始地址,所以老是以为CPU上电之后就直接去执行flash里面的内容,也就是我们编译出来的固件的内容。
然而实际情况并不是这样!!!在芯片内部有一段固化在芯片中的代码,CPU上电首先会执行里面的固化代码。然后再去执行flash上的内容。固化的代码中具体有些什么我也不得而知,但是要知道,secure boot的逻辑代码就在固化代码中。
上图是secure boot的流程图,但是有些细节需要说明一下,帮助理解。
1.secure boot的标志位在供CPU使用的OTP中,内部固化代码读取到标志位就会走secure boot流程,否则走正常的boot流程。所以secure boot 一旦开启,将无法关闭(因为OTP不可逆)。
2.secure boot 流程中的ddr_init验签(验证签名)和uboot验签需要RSA的PK(public key,公钥)hash和 AES的key(可选)。这些信息保存在供CPU使用的OTP的指定区域。固化代码需要这些信息会去这些指定区域去读取。
3.这些信息如何烧入OTP,可以参考最上面提到的 Hi3519AV100╱Hi3556AV100 V100 安全启动使用指南.pdf 的第三章: OTP 烧写步骤。
3519加密研究
secure boot可以保证uboot的安全性,但是除了uboot,其他的分区都是没有管的,所以如果想保护后面的分区,需要再uboot中加入后面文件校验的程序。
最好的办法是在uboot中保存后面的PK/PK hash(看空间),然后对后面的kernel+rootfs+rest 的整体做签名
具体image结构(类似secure boot):幻数+image总长度+PK长度+PK+image+签名
流程:
1.PK校验,保证PK没有篡改
2.签名认证,知道image总长度,就能求出image的sha256。然后,
签名+PK == sha256?可以判断image是否被修改。
将PK(2048bits)的hash256(256bits)写入OTP,将AES的key写入OTP,然后呢?
A: 芯片内部在最开始启动的时候,最先加载自己内部ROM的BootLoader,这部分程序会读取OTP中的secure boot、AES等标志位。读取到对应标志位就执行对应的操作。所以如果设置了secure boot 标志位,就一定要给PK的hash,因为程序会去读,并且去做校验。如果设置了AES标志位,就一定要烧key,程序会自动去执行解密操作。
安全模块的OTP操作中将key加载到加密模块中,啥意思?加载到那儿了?说从CPU/硬件中加载,啥意思??
是算从CPU还是硬件中加载(我猜CPU)
那么硬件中加载就是OTP?