简述
当前boot的设计逻辑是:一级boot对二级boot的进行验签,通过后,启动二级boot;二级boot启动后,首先查看是否有刷新请求,如果有,进入刷写流程,刷写完毕后,在线校验APP的hash值和签名,校验通过启动APP,如果没有,则进入APP的hash验证流程,验证通过后启动APP。
一级boot对二级boot校验过程详解
根据Secure Boot Part 1 ------ Flash分区-CSDN博客,我可以知道二级boot中有一个区域结构如下:
typedef struct {
uint32_t magic; // 标志位,如 0x544F4F42 (BOOT)
uint32_t firmware_len; // 2级 Boot 实际代码长度
uint8_t signature64; // ECDSA R+S 签名
uint8_t sha256_hash32; // 预留,可选
} fw_header_t;
一级boot根据二级boot的长度firmware_len,读取flash中二级boot的内容,然后在线计算二级boot的hash值,然后将计算出来的hash值和对应公钥作为输入,进行非对称加密计算,得出一个结果,将该结果与signature64进行比较,如果相同,则验证通过。这一步通过不仅可以验证二级boot的完整性,还可以验证二级boot身份的有效性,因为先计算了二级boot的hash值,如果二级boot被篡改过,那么hash值就对不上,后续身份肯定也过不了,如果二级boot被黑客篡改了,那么即使hash值验证没有问题,由于黑客没有正确的私钥对app进行签名,所以在用公钥对app进行验签时,必然也不能通过。
二级boot对APP的校验过程详解
如上所述,二级boot的启动流程主要分两路,有刷写请求和没有刷写请求。同样APP区域中有这样一个结构的区域:
typedef struct {
uint32_t magic;
uint32_t length;
uint8_t hash32;
uint32_t version;
uint8_t reserved20;
} FlashConfig_t;
没有刷写请求时,根据会length计算hash值,并将该值和hash32进行比较,对APP进行验证,并且当前设计中只验证了hash值,也就是说只对APP的完整性进行了验证,并没有验证APP的身份(这一点后续可以继续论证)
有刷写请求时,会首先进行刷写,当刷写完毕时,首先会对刷写的数据进行完整性校验,如果校验没有问题,会继续校验签名,如果都没有问题,才会将该结构FlashConfig_t区域进行更新。