www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當前位置:首頁 > 物聯(lián)網(wǎng) > 嵌入式與Linux那些事
[導讀]FIT 格式支持存儲鏡像的hash值,并且在加載鏡像時會校驗hash值。這可以保護鏡像免受破壞,但是,它并不能保護鏡像不被替換。而如果對hash值使用私鑰簽名,在加載鏡像時使用公鑰驗簽則可以保護鏡像不被替換。因此,公鑰必須保存在一個絕對安全的地方。

FIT 格式支持存儲鏡像的hash值,并且在加載鏡像時會校驗hash值。這可以保護鏡像免受破壞,但是,它并不能保護鏡像不被替換。

而如果對hash值使用私鑰簽名,在加載鏡像時使用公鑰驗簽則可以保護鏡像不被替換。因此,公鑰必須保存在一個絕對安全的地方。

接下來的內(nèi)容要求大家了解一些密碼學的內(nèi)容,之前也介紹過一些,可以看這篇文章

secure boot (一)FIT Image

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

secure boot簽名的大致流程:

  • 計算鏡像的hash值
  • 利用私鑰對hash值簽名
  • 簽名結(jié)果存在FIT Image 中。

secure boot驗簽的大致流程:

  • 讀取FIT Image
  • 獲得pubkey
  • 從FIT Image 提取簽名
  • 計算鏡像的hash
  • 使用公鑰驗簽獲得hash值,與計算得到的hash值進行對比

簽名是由mkimage工具完成的,驗簽由uboot完成。

簽名算法

原則上講,任何合適的算法都可以用來簽名和驗簽。在uboot中,目前只支持一類算法:SHA&RSA。

RSA 算法使用提前準備好的公鑰就可以完成驗簽,驗簽相關(guān)的代碼量也很少。在驗簽時,RSA只是在FDT中提取必要的數(shù)據(jù)進行校驗。

當然也可以在uboot中添加合適的算法,如果有其他簽名算法(如DSA),可以直接替換rsa.c,并在image-sig.c中添加對應(yīng)算法即可。

創(chuàng)建RSA key和證書

openssl 創(chuàng)建一副2048的密鑰對:

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

創(chuàng)建包含pubkey的證書:

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

查看pubkey的值:

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

綁定設(shè)備樹

在FIT Image的簽名節(jié)點中需要添加以下 屬性,簽名節(jié)點與哈希節(jié)點處于同一級別,被稱為signature@1, signature@2等。

  • algo: 算法名稱

  • key-name-hint:用來簽名的key。密鑰對必須存放在單獨的文件夾(mkimage 使用-k 參數(shù)指定),私鑰被命名為 .key,證書命名為.crt。

鏡像被簽名后,以下這些屬性都會被自動強制添加:

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

以下這些屬性是可選的:

  • timestamp:簽名的時間

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

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

  • comment:簽名者或者鏡像的額外信息

  • sign-images:簽名鏡像的列表

  • hashed-nodes:簽名者簽名的節(jié)點列表,一般是包含節(jié)點完整路徑的字符串。例如:

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應(yīng)該作為一個子節(jié)點存放在/signature節(jié)點中。節(jié)點中要加上以下特性:

  • algo:算法名稱

  • key-name-hint: 簽名使用的key的名稱

  • required: 校驗?zāi)撑渲盟褂玫墓€

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

  • rsa,num-bits:key的位數(shù)

  • rsa,modulus:N,多字節(jié)的整數(shù)

  • rsa,exponent:E,64位的無符號整數(shù)

  • 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節(jié)點由mkimage工具自動插入生成,節(jié)點里保存了RSA-SHA算法類型、RSA核心因子參
   //數(shù)等信息。
        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";
};
};

簽名方案

上一節(jié)內(nèi)容提到過,在secure boot中一般使用RSA簽名方案。

要完成對鏡像的簽名,就必須使用私鑰。而私鑰一般是存在服務(wù)器上的,在本地PC上只存公鑰。要想完成對鏡像的簽名,就必須把所有鏡像上傳到服務(wù)器重新打包。這種方案上傳的文件太多,比較繁瑣。下面我們介紹一種常用的簽名方案。

在PC上,存放一把公鑰和臨時私鑰,公鑰是打包進dtb中的,安全啟動時使用。臨時私鑰是為了生成簽名數(shù)據(jù)。

在本地打包時,使用臨時私鑰對非安全鏡像簽名,將簽名數(shù)據(jù)上傳到服務(wù)器使用真正的私鑰進行二次簽名。將二次簽名的數(shù)據(jù)和非安全鏡像打包在一起,就得到了安全鏡像。安全啟動時,從dtb中拿出公鑰對安全鏡像進行校驗即可。

這樣既可以保證私鑰的安全,又避免了上傳所有鏡像簽名的繁瑣。

簽名鏡像+簽名配置

在secure boot中,除了對各個獨立鏡像簽名外,還要對FIT Image中的配置項進行簽名。

有些情況下,已經(jīng)簽名的鏡像也有可能遭到破壞。例如,也可以使用相同的簽名鏡像創(chuàng)建一個FIT image,但是,其配置已經(jīng)被改變,從而可以選擇不同的鏡像去加載(混合式匹配攻擊)。也有可能拿舊版本的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 都已經(jīng)被簽名了,但是,攻擊者可以很容易的將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";
  };
 };

攻擊者可以拿到簽名的鏡像,并且鏡像是正確的。這種組合式攻擊會給設(shè)備帶來很大風險。

因此,為了解決這個問題,除了給鏡像簽名外,我們可以把配置選項也簽名,每個鏡像都有自己的簽名,在給配置選項簽名時,把鏡像的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' 指定了驗簽的公鑰,則會使用這把公鑰校驗該配置對應(yīng)的所有鏡像。

為了支持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的區(qū)域,這部分區(qū)域比較特殊,只可以寫入一次,寫入后就再也不可以修改了。把公鑰存儲在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進行校驗。

本站聲明: 本文章由作者或相關(guān)機構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

自2014年ST公司推出STM32CubeMX以來,這款圖形化配置工具憑借“一鍵生成初始化代碼”“跨IDE兼容”“中間件集成”等特性,迅速成為78%的STM32開發(fā)者首選工具。然而,伴隨其普及的爭議始終未息:STM32C...

關(guān)鍵字: STM32CubeMX ST公司

在工業(yè)自動化領(lǐng)域,Modbus協(xié)議憑借其開放性和易用性成為設(shè)備通信的"通用語言"。然而,當工程師面對Modbus RTU、ASCII和TCP三種變體時,如何根據(jù)具體場景做出最優(yōu)選擇?本文將從編碼機制、通信效率、錯誤檢測等...

關(guān)鍵字: Modbus協(xié)議 TCP

在工業(yè)自動化、能源管理等實時性要求嚴苛的場景中,Modbus通信系統(tǒng)的響應(yīng)延遲直接關(guān)系到設(shè)備控制的精度與系統(tǒng)穩(wěn)定性。從智能電表的功率調(diào)節(jié)到機器人關(guān)節(jié)的同步控制,微秒級的響應(yīng)偏差都可能引發(fā)連鎖故障。本文從硬件架構(gòu)、軟件設(shè)計...

關(guān)鍵字: Modbus 通信系統(tǒng)

在新能源發(fā)電、電動汽車、數(shù)據(jù)中心等直流供電系統(tǒng)中,過壓故障是導致設(shè)備損壞的主要誘因之一。據(jù)統(tǒng)計,電力電子設(shè)備故障中約35%與過壓事件相關(guān),其中直流側(cè)過壓占比達62%。本文以基于TVS二極管與MOSFET的復合型直流過壓保...

關(guān)鍵字: 直流過壓 保護電路

在工業(yè)物聯(lián)網(wǎng)(IIoT)與邊緣計算快速發(fā)展的背景下,Modbus協(xié)議憑借其輕量化特性成為微控制器(MCU)設(shè)備互聯(lián)的首選方案。然而,在資源受限的MCU(如STM32F0系列、ESP8266等,RAM通常小于32KB,F(xiàn)l...

關(guān)鍵字: 微控制器 Modbus 工業(yè)物聯(lián)網(wǎng)

在工業(yè)控制系統(tǒng)中,Modbus RTU協(xié)議的CRC校驗如同通信網(wǎng)絡(luò)的"免疫系統(tǒng)",某石化廠DCS系統(tǒng)曾因CRC計算錯誤導致0.3%的數(shù)據(jù)包丟失,引發(fā)連鎖控制故障。本文將深入解析CRC-16/MODBUS算法原理,對比軟件...

關(guān)鍵字: Modbus RTU CRC 算法

在工業(yè)自動化領(lǐng)域,Modbus協(xié)議憑借其簡潔高效的設(shè)計,已成為設(shè)備間通信的"通用語言"。某智能電網(wǎng)項目通過Modbus RTU協(xié)議實現(xiàn)2000臺電表的數(shù)據(jù)采集,通信成功率高達99.97%,這背后正是對消息結(jié)構(gòu)的精準把控。...

關(guān)鍵字: Modbus 工業(yè)自動化

在工業(yè)物聯(lián)網(wǎng)設(shè)備開發(fā)中,Modbus從站功能已成為微控制器(MCU)的標配能力。某智能電表項目通過在STM32上實現(xiàn)Modbus RTU從站,成功將設(shè)備接入現(xiàn)有SCADA系統(tǒng),開發(fā)周期縮短40%。本文將系統(tǒng)解析MCU實現(xiàn)...

關(guān)鍵字: 微控制器 Modbus 協(xié)議棧優(yōu)化

在嵌入式系統(tǒng)中,F(xiàn)lash存儲器因其非易失性、高密度和低成本特性,成為代碼存儲和關(guān)鍵數(shù)據(jù)保存的核心組件。然而,MCU驅(qū)動Flash讀寫時,開發(fā)者常因?qū)τ布匦岳斫獠蛔慊虿僮髁鞒淌韬?,陷入性能下降、?shù)據(jù)損壞甚至硬件損壞的陷...

關(guān)鍵字: MCU驅(qū)動 Flash

在嵌入式開發(fā)中,STM32的時鐘系統(tǒng)因其靈活性和復雜性成為開發(fā)者關(guān)注的焦點。然而,看似簡單的時鐘配置背后,隱藏著諸多易被忽視的陷阱,輕則導致系統(tǒng)不穩(wěn)定,重則引發(fā)硬件損壞。本文從時鐘源選擇、PLL配置、總線時鐘分配等關(guān)鍵環(huán)...

關(guān)鍵字: STM32 時鐘系統(tǒng)
關(guān)閉