当前位置:首页 > 公众号精选 > 嵌入式与Linux那些事
[导读]FIT 格式支持存储镜像的hash值,并且在加载镜像时会校验hash值。这可以保护镜像免受破坏,但是,它并不能保护镜像不被替换。而如果对hash值使用私钥签名,在加载镜像时使用公钥验签则可以保护镜像不被替换。因此,公钥必须保存在一个绝对安全的地方。

FIT 格式支持存储镜像的hash值,并且在加载镜像时会校验hash值。这可以保护镜像免受破坏,但是,它并不能保护镜像不被替换。

而如果对hash值使用私钥签名,在加载镜像时使用公钥验签则可以保护镜像不被替换。因此,公钥必须保存在一个绝对安全的地方。

接下来的内容要求大家了解一些密码学的内容,之前也介绍过一些,可以看这篇文章

secure boot (一)FIT Image

secure boot (二)基本概念和框架

secure boot签名的大致流程:

  • 计算镜像的hash值
  • 利用私钥对hash值签名
  • 签名结果存在FIT Image 中。

secure boot验签的大致流程:

  • 读取FIT Image
  • 获得pubkey
  • 从FIT Image 提取签名
  • 计算镜像的hash
  • 使用公钥验签获得hash值,与计算得到的hash值进行对比

签名是由mkimage工具完成的,验签由uboot完成。

签名算法

原则上讲,任何合适的算法都可以用来签名和验签。在uboot中,目前只支持一类算法:SHA&RSA。

RSA 算法使用提前准备好的公钥就可以完成验签,验签相关的代码量也很少。在验签时,RSA只是在FDT中提取必要的数据进行校验。

当然也可以在uboot中添加合适的算法,如果有其他签名算法(如DSA),可以直接替换rsa.c,并在image-sig.c中添加对应算法即可。

创建RSA key和证书

openssl 创建一副2048的密钥对:

$ openssl genpkey -algorithm RSA -out keys/dev.key  -pkeyopt rsa_keygen_bits:2048 -pkeyopt rsa_keygen_pubexp:65537

创建包含pubkey的证书:

$ openssl req -batch -new -x509 -key keys/dev.key -out keys/dev.crt

查看pubkey的值:

$ openssl rsa -in keys/dev.key -pubout

绑定设备树

在FIT Image的签名节点中需要添加以下 属性,签名节点与哈希节点处于同一级别,被称为signature@1, signature@2等。

  • algo: 算法名称

  • key-name-hint:用来签名的key。密钥对必须存放在单独的文件夹(mkimage 使用-k 参数指定),私钥被命名为 .key,证书命名为.crt。

镜像被签名后,以下这些属性都会被自动强制添加:

  • value: 签名后的值(RSA-2048 占256 bytes)

以下这些属性是可选的:

  • timestamp:签名的时间

  • signer-name:签名者的名字(例如mkimage)

  • signer-version:签名的版本(例如"2013.01")

  • comment:签名者或者镜像的额外信息

  • sign-images:签名镜像的列表

  • hashed-nodes:签名者签名的节点列表,一般是包含节点完整路径的字符串。例如:

hashed-nodes = "/", "/configurations/conf@1", "/images/kernel@1", "/images/kernel@1/hash@1", "/images/fdt@1", "/images/fdt@1/hash@1";

以下是一个待签名镜像的its配置。

/dts-v1/;

/ {
 description = "Chrome OS kernel image with one or more FDT blobs"; #address-cells =; images {
  kernel@1 {
   data = /incbin/("test-kernel.bin"); type = "kernel_noload";
   arch = "sandbox";
   os = "linux";
   compression = "none";
   load =;
   entry =;
   kernel-version =;
   signature@1 {
    algo = "sha1,rsa2048";
    key-name-hint = "dev";
   };
  };
  fdt@1 {
   description = "snow";
   data = /incbin/("sandbox-kernel.dtb"); type = "flat_dt";
   arch = "sandbox";
   compression = "none";
   fdt-version =;
   signature@1 {
    algo = "sha1,rsa2048";
    key-name-hint = "dev";
   };
  };
 };
 configurations {
  default = "conf@1";
  conf@1 {
   kernel = "kernel@1";
   fdt = "fdt@1";
  };
 };
};

以下是配置项签名后的its文件。

/dts-v1/;

/ {
 description = "Chrome OS kernel image with one or more FDT blobs"; #address-cells =; images {
  kernel@1 {
   data = /incbin/("test-kernel.bin"); type = "kernel_noload";
   arch = "sandbox";
   os = "linux";
   compression = "lzo";
   load =;
   entry =;
   kernel-version =; hash@1 {
    algo = "sha1";
   };
  };
  fdt@1 {
   description = "snow";
   data = /incbin/("sandbox-kernel.dtb"); type = "flat_dt";
   arch = "sandbox";
   compression = "none";
   fdt-version =; hash@1 {
    algo = "sha1";
   };
  };
 };
 configurations {
  default = "conf@1";
  conf@1 {
   kernel = "kernel@1";
   fdt = "fdt@1";
   signature@1 {
    algo = "sha1,rsa2048";
    key-name-hint = "dev";
    sign-images = "fdt", "kernel";
   };
  };
 };
};

pubkey的存储

为了校验签名后的镜像,必须把pubkey存放在可信赖的位置。将pubkey存在镜像中是不安全的,很容易被破解。一般我们将其存放在uboot的FDT中(CONFIG_OF_CONTROL)。

pubkey应该作为一个子节点存放在/signature节点中。节点中要加上以下特性:

  • algo:算法名称

  • key-name-hint: 签名使用的key的名称

  • required: 校验某配置所使用的公钥

除此之外,每个算法都有一些必要的特性。RSA算法中,以下特性必须被添加:

  • rsa,num-bits:key的位数

  • rsa,modulus:N,多字节的整数

  • rsa,exponent:E,64位的无符号整数

  • rsa,r-squared:(2^num-bits)^2

  • rsa,n0-inverse:-1 / modulus[0] mod 2^32

下面看一个例子,以下是一个uboot.dtb存放RSA的例子。RSA key被mkimage打包在u-boot.dtb和u-boot-spl.dtb中,然后它们再被打包进u-boot.bin和u-boot-spl.bin。

ubuntu:~/uboot-nextdev$ fdtdump u-boot.dtb | less
/dts-v1/;
....
/ { #address-cells =; #size-cells =; compatible = "rockchip,rv1126-evb", "rockchip,rv1126";
        model = "Rockchip RV1126 Evaluation Board";
        // signature节点由mkimage工具自动插入生成,节点里保存了RSA-SHA算法类型、RSA核心因子参
   //数等信息。
        signature {
         key-dev {
    required = "conf";
          algo = "sha256,rsa2048";
          rsa,np =;
          rsa,c =;
          rsa,r-squared =;
          rsa,modulus =;
          rsa,exponent-BN =;
          rsa,exponent =;
          rsa,n0-inverse =;
          rsa,num-bits =;
          key-name-hint = "dev";
};
};

签名方案

上一节内容提到过,在secure boot中一般使用RSA签名方案。

要完成对镜像的签名,就必须使用私钥。而私钥一般是存在服务器上的,在本地PC上只存公钥。要想完成对镜像的签名,就必须把所有镜像上传到服务器重新打包。这种方案上传的文件太多,比较繁琐。下面我们介绍一种常用的签名方案。

在PC上,存放一把公钥和临时私钥,公钥是打包进dtb中的,安全启动时使用。临时私钥是为了生成签名数据。

在本地打包时,使用临时私钥对非安全镜像签名,将签名数据上传到服务器使用真正的私钥进行二次签名。将二次签名的数据和非安全镜像打包在一起,就得到了安全镜像。安全启动时,从dtb中拿出公钥对安全镜像进行校验即可。

这样既可以保证私钥的安全,又避免了上传所有镜像签名的繁琐。

签名镜像+签名配置

在secure boot中,除了对各个独立镜像签名外,还要对FIT Image中的配置项进行签名。

有些情况下,已经签名的镜像也有可能遭到破坏。例如,也可以使用相同的签名镜像创建一个FIT image,但是,其配置已经被改变,从而可以选择不同的镜像去加载(混合式匹配攻击)。也有可能拿旧版本的FIT Image去替换新的FIT image(回滚式攻击)。

下面举个例子。

/ {
 images {
  kernel@1 {
   data = for kernel1>
   signature@1 {
    algo = "sha1,rsa2048"; # kernel image镜像的哈希值,由mkiamge工具自动生成 value = <...kernel signature 1...>
   };
  };
  kernel@2 {
   data = for kernel2>
   signature@1 {
    algo = "sha1,rsa2048";
    value = <...kernel signature 2...>
   };
  };
  fdt@1 {
   data = for fdt1>;
   signature@1 {
    algo = "sha1,rsa2048";
    vaue = <...fdt signature 1...>
   };
  };
  fdt@2 {
   data = for fdt2>;
   signature@1 {
    algo = "sha1,rsa2048";
    vaue = <...fdt signature 2...>
   };
  };
 };
 configurations {
  default = "conf@1";
  conf@1 {
   kernel = "kernel@1";
   fdt = "fdt@1";
  };
  conf@1 {
   kernel = "kernel@2";
   fdt = "fdt@2";
  };
 };
};

两个kernel image 都已经被签名了,但是,攻击者可以很容易的将kernel1 和fdt2 作为configuration 3去加载。

configurations {
  default = "conf@1";
  conf@1 {
   kernel = "kernel@1";
   fdt = "fdt@1";
  };
  conf@1 {
   kernel = "kernel@2";
   fdt = "fdt@2";
  };
  conf@3 {
   kernel = "kernel@1";
   fdt = "fdt@2";
  };
 };

攻击者可以拿到签名的镜像,并且镜像是正确的。这种组合式攻击会给设备带来很大风险。

因此,为了解决这个问题,除了给镜像签名外,我们可以把配置选项也签名,每个镜像都有自己的签名,在给配置选项签名时,把镜像的hash值也包含进去。具体例子如下:

/ {
 images {
  kernel@1 {
   data = for kernel1> hash@1 {
    algo = "sha1";
    value = <...kernel hash 1...>
   };
  };
  kernel@2 {
   data = for kernel2> hash@1 {
    algo = "sha1";
    value = <...kernel hash 2...>
   };
  };
  fdt@1 {
   data = for fdt1>; hash@1 {
    algo = "sha1";
    value = <...fdt hash 1...>
   };
  };
  fdt@2 {
   data = for fdt2>; hash@1 {
    algo = "sha1";
    value = <...fdt hash 2...>
   };
  };
 };
 configurations {
  default = "conf@1";
  conf@1 {
   kernel = "kernel@1";
   fdt = "fdt@1";
   signature@1 {
    algo = "sha1,rsa2048"; # 对配置项签名,由mkimage工具自动生成 value = <...conf 1 signature...>;
   };
  };
  conf@2 {
   kernel = "kernel@2";
   fdt = "fdt@2";
   signature@1 {
    algo = "sha1,rsa2048";
    value = <...conf 1 signature...>;
   };
  };
 };
};

如上所示,除了给所有镜像添加了hash值,还为每个配置添加了签名。mkimage将会对configurations/conf@1签名(/images/kernel@1, /images/kernel@1/hash@1,/images/fdt@1, /images/fdt@1/hash@1)。签名会被写入  /configurations/conf@1/signature@1/value。

验签

FIT image 在加载时会验签。如果'required' 指定了验签的公钥,则会使用这把公钥校验该配置对应的所有镜像。

为了支持FIT格式,以下配置项必须被选上。

CONFIG_FIT_SIGNATURE :使能FIT image的签名和验签

CONFIG_RSA :使能RSA签名算法

默认情况下,使能FIT Image的签名和验签后,CONFIG_IMAGE_FORMAT_LEGACY会被禁用。即FIT uboot image的只能引导FIT kernel Image。

如果需要引导legacy kernel image,需要手动添加CONFIG_IMAGE_FORMAT_LEGACY 定义。

测试

为了校验签名和验签是否正确,可以使用测试脚本test/vboot/vboot_test.sh。下面以sandbox为例子来说明bootm的启动和对镜像的验签。

$ make O=sandbox sandbox_config
$ make O=sandbox
$ O=sandbox ./test/vboot/vboot_test.sh
/home/hs/ids/u-boot/sandbox/tools/mkimage -D -I dts -O dtb -p 2000
Build keys do sha1 test Build FIT with signed images
Test Verified Boot Run: unsigned signatures:: OK
Sign images
Test Verified Boot Run: signed images: OK
Build FIT with signed configuration
Test Verified Boot Run: unsigned config: OK
Sign images
Test Verified Boot Run: signed config: OK
check signed config on the host
Signature check OK
OK
Test Verified Boot Run: signed config: OK
Test Verified Boot Run: signed config with bad hash: OK do sha256 test Build FIT with signed images
Test Verified Boot Run: unsigned signatures:: OK
Sign images
Test Verified Boot Run: signed images: OK
Build FIT with signed configuration
Test Verified Boot Run: unsigned config: OK
Sign images
Test Verified Boot Run: signed config: OK
check signed config on the host
Signature check OK
OK
Test Verified Boot Run: signed config: OK
Test Verified Boot Run: signed config with bad hash: OK

Test passed

完整校验流程

OTP校验loader

那么,这种镜像校验方式有个很重要的问题,公钥存在哪里才是安全的呢?

一般SOC中会有一个叫OTP或EFUSE的区域,这部分区域比较特殊,只可以写入一次,写入后就再也不可以修改了。把公钥存储在OTP中,就可以很好地保证其不能被修改。

OTP的存储空间很小,一般只有几KB,因此并不适合直接存放RSA公钥。一般都是将RSA公钥的hash val 存放在OTP中。像sha256的hash值仅为256 bits,而RSA 公钥本身一般存放在镜像中。

在使用公钥之前,只需要使用OTP中的公钥hash值验证镜像附带公钥的完整性,即可确定公钥是否合法。

RSA公钥需要一般使用芯片厂家的工具写入loader。安全启动时,bootrom首先从loader固件头中获取RSA公钥并校验合法性;然后再使用该公钥校验SPL的固件签名。

spl校验uboot

SPL把RSA公钥保存在u-boot-spl.dtb中,u-boot-spl.dtb会被打包进u-boot-spl.bin文件(最后打包进loader);安全启动时SPL从自己的dtb文件中拿出RSA公钥对uboot.img进行安全校验。

uboot校验kernel

U-Boot把RSA公钥保存在u-boot.dtb中,u-boot.dtb会被打包进u-boot.bin文件(最后打包为uboot.img);安全启动时U-Boot从自己的dtb文件中拿RSA公钥对boot.img进行校验。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

9月2日消息,不造车的华为或将催生出更大的独角兽公司,随着阿维塔和赛力斯的入局,华为引望愈发显得引人瞩目。

关键字: 阿维塔 塞力斯 华为

加利福尼亚州圣克拉拉县2024年8月30日 /美通社/ -- 数字化转型技术解决方案公司Trianz今天宣布,该公司与Amazon Web Services (AWS)签订了...

关键字: AWS AN BSP 数字化

伦敦2024年8月29日 /美通社/ -- 英国汽车技术公司SODA.Auto推出其旗舰产品SODA V,这是全球首款涵盖汽车工程师从创意到认证的所有需求的工具,可用于创建软件定义汽车。 SODA V工具的开发耗时1.5...

关键字: 汽车 人工智能 智能驱动 BSP

北京2024年8月28日 /美通社/ -- 越来越多用户希望企业业务能7×24不间断运行,同时企业却面临越来越多业务中断的风险,如企业系统复杂性的增加,频繁的功能更新和发布等。如何确保业务连续性,提升韧性,成...

关键字: 亚马逊 解密 控制平面 BSP

8月30日消息,据媒体报道,腾讯和网易近期正在缩减他们对日本游戏市场的投资。

关键字: 腾讯 编码器 CPU

8月28日消息,今天上午,2024中国国际大数据产业博览会开幕式在贵阳举行,华为董事、质量流程IT总裁陶景文发表了演讲。

关键字: 华为 12nm EDA 半导体

8月28日消息,在2024中国国际大数据产业博览会上,华为常务董事、华为云CEO张平安发表演讲称,数字世界的话语权最终是由生态的繁荣决定的。

关键字: 华为 12nm 手机 卫星通信

要点: 有效应对环境变化,经营业绩稳中有升 落实提质增效举措,毛利润率延续升势 战略布局成效显著,战新业务引领增长 以科技创新为引领,提升企业核心竞争力 坚持高质量发展策略,塑强核心竞争优势...

关键字: 通信 BSP 电信运营商 数字经济

北京2024年8月27日 /美通社/ -- 8月21日,由中央广播电视总台与中国电影电视技术学会联合牵头组建的NVI技术创新联盟在BIRTV2024超高清全产业链发展研讨会上宣布正式成立。 活动现场 NVI技术创新联...

关键字: VI 传输协议 音频 BSP

北京2024年8月27日 /美通社/ -- 在8月23日举办的2024年长三角生态绿色一体化发展示范区联合招商会上,软通动力信息技术(集团)股份有限公司(以下简称"软通动力")与长三角投资(上海)有限...

关键字: BSP 信息技术
关闭