作者:Ricky Su,Xilinx Employee
在電影里,黑客遠程控制一個城市中所有的汽車,讓它們追逐指定的目標,這樣的場景讓人感覺不寒而栗。在現實中,某個大網站的用書數據泄露的新聞也已經屢見不鮮。保護系統安全,之前是網絡安全工程師的職責,似乎大多數工程師不太關心這個領域。但其實在產品越來越網絡化、智能化的現在,安全的意義已經越來越重要,畢竟我們不希望電影里黑客控制汽車的場景真的發生。除了汽車,任何聯網的設備,都會給黑客遠程訪問的可能性;除了放在保險柜里,任何設備只要能被黑客物理接觸到,篡改系統或者復制系統也不是沒有。
在我之前接觸的客戶中,也只有少量公司在使用 Xilinx FPGA 和 SoC 芯片所提供的安全功能。其他的情況,可能是有物理環境能保證產品不被別人接觸到;但更多可能是工程師覺得安全功能不是必須的,或者使用安全功能太復雜。
攥寫本文,我希望能讓大家看到:
1. 在產品中加入安全功能通常都是有需求的、有價值的,而且需求會越來越大。
2. 為產品添加安全功能,達到一定的安全級別,流程步驟和復雜程度是可控的。
就我了解到的情況,大多數使用 ZYNQ-7000 或 ZYNQ UltraScale+ MPSoC 的用戶并沒有打開 Secure Boot 功能。如果你能看完全文,照著步驟做一下,打開安全啟動功能,就能“免費”提升產品安全等級,就是“加量不加價”啦。
上面講到“達到一定的安全級別”,是因為安全保護是有代價的,黑客破解也是有代價的,我們需要保證以盡可能低的安全保護的代價,使黑客破解系統的代價比他攻破系統能獲取到的價值更高,這樣黑客就沒有攻擊系統的動力,達到了自我保護的目的。
因此本文只描述最容易理解、用做小的代價能把 MPSoC 提供的安全啟動的功能用起來的部分。MPSoC 的安全啟動還可以有很多定制化的空間,更多高級功能比如 PPK Revoke 等,都可以參考本文最后列出的參考文檔,Xilinx 官方文檔中有更多詳細解釋。
全文將從以下幾個方面討論安全啟動
一、常見芯片攻擊類型與防護思路
二、MPSoC 采用的防御方法
三、實戰使用指南
四、常見問題和錯誤
五、參考文檔
注:本人并不是安全專家。本文僅是對安全啟動的操作記錄以及對安全保護的個人理解。對于使用本文描述的方法進行設計生產的后果請恕本人無法對其負責。技術問題歡迎在賽靈思論壇中討論,但我不保證能全部解答,還請見諒。
一、常見芯片攻擊類型與防護思路
產品克隆
競爭對手購買一份樣機,找人復制 PCB (俗稱抄板),購買到所有的元器件,復制 Flash 中的內容,如果這樣就能讓系統啟動并且完成所有預定功能,這樣就輕易完成了產品克隆。由于沒有研發成本,可以使用低價傾銷,損害產品設計者的利益。
現在的主芯片一般都有一些機制,在授權的主芯片上特制一些信息,讓Flash上的程序和芯片上的信息互相驗證。這樣只要對方不能復制主芯片上的特制信息,就不能做到克隆。
破解軟件
當產品無法直接克隆,競爭對手/黑客可以通過查詢軟件具體實現來了解系統的運行機制,尋找可能的漏洞,或者獲取受知識產權保護的信息。
為了不讓對方看到軟件原始信息,可以對軟件進行加密。加密信息存在 Flash 上,芯片上電后解密后運行。黑客僅僅讀取 Flash 上的內容無法了解軟件原始信息。
增加惡意代碼
如果整體或部分替換 Flash 上的軟件,或讓操作系統運行自己開發的惡意代碼,有可能可以獲取到系統的關鍵信息。在聯網的設備中,惡意代碼能獲取到的信息可能會更多。在帶人工智能功能的設備上,惡意代碼能實現的破壞力也可能比傳統的攻擊更嚴重。因此控制軟件運行權限,確保只有授權應用能夠運行,不讓非授權的應用在系統中運行,對系統安全也非常重要。
認證,或者稱為授權 (Authentication) ,是防止惡意代碼運行的重要步驟。
打磨芯片獲取密鑰
加密和認證一般的實現方法都是通過在芯片內部布置只可以燒寫一次的反熔絲,用這些熔絲位來非易失地存儲密鑰。反熔絲相對普通邏輯來說是區別比較明顯的,理論上來說,打開芯片封裝后是有可能通過顯微鏡是有可能查找出反熔絲的密鑰位,然后用它解密的。
要防護通過這種方式獲取密鑰,主要有兩種方法:
1. 采用非對稱方式的公鑰-私鑰對,在芯片中只存儲公鑰,或公鑰的Hash。對方獲得公鑰是沒有意義的。
2. 對于必須采用對稱加密的方式,可以將密鑰再次加密。只要再次加密的密鑰只能通過某種不能被窺探的方法解密成原始密鑰,就可以防護這種方式。
旁路攻擊
所謂旁路攻擊,就是攻擊者并不真正“看”到存儲在芯片中的密鑰,而是通過其他方式計算出來。一個比較容易理解的例子就是最近在網絡上流行一個應用,通過電腦的麥克風采集音頻,算出敲擊鍵盤的字符。采集的信息不是直接從鍵盤的輸入的來,而是從麥克風得來,就是一種旁路攻擊。
對于獲取芯片密鑰的旁路攻擊,比較常見的是通過監測電源功耗的簡單功耗分析、差分功耗分析。
要防止類似的旁路攻擊,防護思路主要是讓一個密鑰所對應的解密數據盡可能少,這樣就能避免攻擊者采集到足夠多的用于統計的信息。
二、MPSoC 采用的防御方法
攻擊方法 防御方式 MPSoC 上的對應硬件和措施
注意:這里提到的防御方式和 MPSoC 上的對應硬件措施并不是完備的列表,只是實際應用中最常用的方式。
比如 MPSoC 上儲存密鑰還可以存在 BBRAM (Battery Backed RAM) 中,系統掉電可以繼續保存密鑰,而且由于它基于 RAM 結構,不是 eFUSE,所以即使打開芯片也不能獲取到密鑰。但大多數系統都不能容忍產品發布后,支持 BBRAM 的電池耗盡后,系統無法啟動的限制,因此暫不介紹。
什么是 AES Black Key
AES 是一種對稱加密技術。所謂對稱加密,就是加密和解密用的是同一個密鑰。這樣的話,保護密鑰就變得尤為重要。把 AES Key 直接燒錄到 eFUSE 中被稱為 Red Key,如果有人能夠打開芯片探測到 eFUSE 的燒錄情況,就可以獲得密鑰。為了防止這種情況發生,Xilinx 提供了 Black Key 方案。
每片 MPSoC 芯片中都有一個硬件模塊叫做 PUF: Physical Uncloneable Function。它可以根據每片芯片物理上本身工藝尺度上的微小差異,對 Red Key 進行加密生成 Black Key。當 Black Key 燒錄在 eFUSE 后,這片芯片的 PUF 模塊通過一些輸入信息還可以將 Red Key 還原回來,再用得到的 Red Key 解密安全啟動的鏡像。因為燒錄在 eFUSE 中的是 Black Key 而不是 Red Key,它不能通過簡單的方法還原出黑客希望獲得的密鑰來解密鏡像,整個解密過程只能在芯片內部進行,使用 Black Key 技術相當于為產品的安全再增加了一堵墻。
什么是 Key Rolling
像功耗分析這樣的旁路攻擊,是通過統計學原理從密文推算出密鑰,再還原成原文。為了不給攻擊者足夠的信息推算密鑰,Key Rolling 的主要想法是一個密鑰只用于有線長度的原文。原文切成很多小份,每一小份原文加一個新的密鑰打包后用密鑰加密,新的密鑰用于加密后面的一份原文和密鑰,這樣滾動前進。
解密時就反向操作,eFUSE 里的密鑰只用于解密 section 1,解密出原文1 和密鑰1,再用密鑰1 解密 section 2,得到原文2 和密鑰2,依此類推。
了解了基本的攻擊路數和防御方法,會感覺到這些方法其實就是魔高一尺道高一丈。很多防御功能都已經內置在芯片里了,使用成本很低,只要把他們用起來,就能把自己的知識產權保護起來。下面我們就了解一下怎么做實戰操作。
三、全局觀:做一個適合你的安全啟動的方案
做一個安全啟動方案,可能涉及到做許多選擇和決定。每一個決定,都有一定的選擇依據。
第一個選擇:要保護哪些內容
要知道需要保護哪些內容,先要知道有哪些內容可以保護。在一個通常的 MPSoC 設計中,軟件邏輯組件有這些:
- FSBL
- PMU Firmware (PMUFW)
- ARM Trusted Firmware (ATF)
- FPGA Bit File
- U-boot
- Linux Kernel + device tree + rootfs
- User Data (Used by u-boot or Linux)
啟動加載流程有些可以調換,但主要是通過以上的順序加載的。FPGA Bit 可以在 FSBL、 U-boot、 Linux 階段被加載。
每一個組件都可以選擇 1) 同時做認證和加密 2) 只做認證 3) 只做加密 4) 什么都不做 (就是 Non-secure boot)。
上面的四種選項意味著,加密和認證是兩個獨立的變量。但實際使用中“只做加密”這種情況比較少用到。由于 MPSoC 中有硬件加速的 RSA 認證模塊,認證對啟動時間的影響比較低;由于認證的機制就是在鏡像最后加上checksum,對存儲空間的需求也很低,所以即使只需要加密功能,順便也把認證功能加上了。
對于安全啟動有一個概念叫做 Root of Trust,信任是要從根部就開始的,或者叫 Chain of Trust,信任鏈,都是一個意思。要保證某個步驟是安全可靠的,必須前面所有的步驟都是安全可靠的。比如某個應用場景需要保證 FPGA Bit 文件是安全可靠的,Bit 文件是 U-boot 加載的,那么 Bit 文件和從啟動到加載 Bit 文件之前的所有步驟都需要經過認證,之后的可以不做,在這個例子中, FSBL,PMUFW,ATF,U-boot 和 Bit 都需要經過認證,Linux 不一定需要。
有一種說法是,如果代碼完全是開源的,不包含用戶的知識產權,那么這個部分可以只做認證,不做加密,以盡可能少地用到 eFUSE 中的 AES Key;但另一種想法認為,沒修改的就不加密,就等于暴露了自己沒有修改開源代碼這件事,而這個信息本身也是有價值的。兩種說法都有道理,怎么選擇看自己取舍吧。
第二個選擇:怎樣打包組件
打包的時候,可以把所有內容整個一起打包成 Boot.bin,UG1209 中的例子就是這樣做的,這樣做完整的安全啟動最容易實現,但也意味著這些內容都不可以隨意動態變更,每次重啟系統恢復到原樣。一般特定功能的嵌入式系統傾向這種設計。
但開放式系統不允許這中完整打包,每次復原的設計。用戶可能希望把在系統中做的操作保存在 Flash 中,重啟后仍然能夠訪問到。于是另一種常見方案是從 FSBL 到 u-boot 用認證加密的方式打包成一個 Boot.bin,Linux 部分存在獨立的 Flash 分區中。怎么保證可讀寫的 Linux 分區安全是另一個復雜的話題,用戶場景和解決方法也多種多樣,就像醫生得看到病人才能開藥,具體怎么做沒辦法簡單一句概括,有機會后續再聊了。
如果將所有內容都打包進 Boot.bin,這樣 Boot.bin 可能很大,一個典型的PetaLinux Kernel + Rootfs 有大約60MB,加上 MPSoC 的 Bit 文件大約 10-20 MB,如果需要再添加一些應用程序,可能一套 Boot.bin 有100MB。如果需要一個功能完整的 Linux,甚至可能到 1GB。這就對 Flash 容量有一些挑戰,現在最大的 QSPI 芯片只有 128MB,如果 Boot.bin 超過了 QSPI Flash 容量,就只能選其他啟動方式,比如 eMMC。由于使用 NOR Flash 技術的 QSPI 比使用 NAND 技術的 eMMC和 SD 更可靠一些,如果考慮到可靠性一定要用 QSPI Flash 啟動,就可以將除了 Linux 以外的部分打包成 Boot.bin,放在 QSPI Flash,Linux 部分放在其他介質,比如 eMMC 或 SD 卡。
第三個選擇:在哪一步做安全認證和解密
前面講到一個例子,FPGA Bit 可以由 FSBL、U-boot 或 Linux 加載。如果有用戶自定義數據需要在安全啟動過程中加載,也可以用同樣的流程。
最終做認證和解密的都是 PMU。選擇在哪一步加載,就需要在這步調用安全啟動的 API,與 PMU 通信,由 PMU 進行認證、解密后再加載。
- 由 FSBL 加載的組件需要都打包在 Boot.bin 中,打包過程中指定每個組件的加密、認證方式,FSBL 會根據這些配置在運行時做認證和解密。
- U-boot 定義了一套 API 與 PMU 通信,將認證和解密的任務交給 PMU 執行。如果需要 U-boot 過程中認證、解密,需要使用 Xilinx 特殊的 U-boot 命令 zynqmp secure。打包 U-boot 能識別的安全組件也是通過 bootgen,與上面 Boot.bin 的打包方式類似。普通文件和 FPGA Bit 都可以打包成 Boot.bin 供 U-boot 加載。具體方法說明見參考文檔5。
- Linux 和 U-boot 類似,都是通過驅動與 PMU 通信。但是截至到目前最新版本 (2018.3),Linux 只支持對 FPGA Bit 文件進行認證、解密后直接加載,不支持用戶數據的認證和解密。具體操作方法見參考文檔6。
三個選擇全都做完,用戶可以自己整理出一個表格,比如這樣:
組件 認證 加密 打包
FSBL | Y | Y | Boot.bin |
PMUFW | Y | Y | Boot.bin |
ATF | Y | Y | Boot.bin |
U-Boot | Y | Y | Boot.bin |
Linux Kernel | Y | Y | image.ub.bin |
Linux Device Tree | Y | Y | image.ub.bin |
Linux RootFS | Y | Y | image.ub.bin |
FSBL、PMUFW、ATF、U-boot 打包成 Boot.bin,所有組件全都進行認證和加密。Linux 的各組件由 PetaLinux 打包成 image.ub,用 bootgen 整體進行認證和加密,生成 image.ub.bin。
沒有后悔藥:安全為上的測試流程
由于 eFUSE 只可以燒寫一次,如果由于不熟悉流程,設置出錯的話會導致芯片無法正常使用,因此燒寫 eFUSE 需要比較謹慎,盡量先把需要驗證的部分驗證通過,最后才真正在 eFUSE 中燒寫密鑰和對應的設置位。
為了讓用戶能夠再不燒寫 eFUSE 的情況下提前能驗證流程以及密鑰的組合,Xilinx 提供了 Boot Header 方法,簡稱 BH。在生成鏡像的時候,將密鑰暫存于鏡像的頭部。啟動時,軟件從鏡像頭部尋找密鑰,跳過從 eFUSE 硬件讀取的過程。BH 流程會使用鏡像頭部中暫存的密鑰與鏡像匹配進行認證和解密操作。用戶可以在熟悉BH流程后,最后再將密鑰燒錄到 eFUSE 中。
注意:
1. Boot Header 流程是可選的,不是必須的。它只是給用戶檢驗流程用的。既做 BH 流程又做 eFUSE 流程可能會把人弄暈,如果真是這樣的話建議不要做 BH 流程直接做 eFUSE 流程。
2. Boot Header 流程不可以用在真實產品中,因為密鑰在鏡像頭部,仍然可以被提取。
總體測試流程可以梳理為以下步驟:
1. 確認自己的安全啟動模式:每個組件用那種加密模式和認證模式,可以列成一個表格。AES 使用 Black Key 還是 Red Key;AES Only 還是 AES + RSA;Key 存在 eFUSE 還是 BBRAM 等。
2. 生成所需的密鑰
- RSA Private Key 和 Public Key
- AES Key 0 (用于燒錄 eFUSE 的 Key)
3. (可選)用 BH 模式生成 BOOT.BIN,進行 RSA 和 AES 在 Boot Header 中的測試
4. 用 eFUSE 模式生成 BOOT.BIN
5. 將 BOOT.BIN 寫入 SD 卡或 Flash
6. 從 JTAG 模式啟動,將 RSA PPK Hash 和 AES Key (red or black) 寫入 eFUSE。用 Flash/SD 模式重啟后驗證安全啟動流程。 a) RSA PPK 和 AES Red Key 可以同時寫入 b) 如果使用 AES Black Key,分別使用兩個程序,先燒錄 Blackkey (這個過程稱為 PUF Registration),再燒錄 RSA PPK Hash
注意:如果啟動模式是 SD 卡,萬一鏡像和 eFUSE 中的密鑰不匹配,由于更換 SD 卡中的啟動鏡像比較容易,那么多次嘗試也不會遇到什么困難。與之相對,如果啟動設備只有 Flash,則需要先燒錄 Flash 后燒錄密鑰,因為燒錄密鑰后 JTAG 將不能使用,不能再使用 SDK 自帶的 Flash Programmer 工具燒錄 Flash。如果燒錄 Flash 的鏡像錯誤,無法完成安全啟動,但是 eFUSE 又已經燒錄,只能通過焊接更換 Flash,離線燒錄正確的鏡像,再焊接回板上,才能繼續使用這個系統。
四、實戰使用指南
以下幾種典型使用模式中,生成密鑰和生成加密鏡像的流程都是一樣的,不同的是需要使用不同的 BIF 配置文件。生成工具是 Vivado 或 SDK 中的命令行小工具 bootgen。燒錄 eFUSE 使用 SDK 中自帶的例子程序,只需要對頭文件進行很少的修改,就能執行。如果使用 Blackkey,額外需要一個注冊的操作,輸入 red key,運行程序時 MPSoC 產生 Black Key。
讓 FSBL 能打印出詳細啟動信息
在調試階段,主要的安全啟動狀態信息是由 FSBL 打印出來的。默認 FSBL 并不打印詳細調試信息,需要在 FSBL 編譯的時候定義 FSBL_DEBUG_INFO,才會有詳細信息打印。
生成密鑰和鏡像
這一節主要描述這幾件事:Bootgen 工具、BIF 描述文件和密鑰文件。
BOOTGEN 命令
Bootgen 可以實現很多功能,最主要的功能是產生用于啟動的 Boot.bin。它可以用來生成帶安全啟動功能的鏡像,也可以是不帶安全啟動功能的。以下是我們在制作安全啟動功能 Boot.bin 時常用的一步到位命令:
bootgen -arch zynqmp -image secureboot.bif -efuseppkbits ppk0_digest.txt -w -o BOOT.bin -encryption_dump
1. 指定 ZYNQ UltraScale+ MPSoC 架構。具體哪個型號的芯片不用關心。
2. image 選項指定輸入文件。BIF 是 Boot.bin 結構的描述文件,后面章節馬上就會介紹。
3. efuseppkbits 選項將為 RSA Primary Public Key 產生 Hash,并保存到指定文件。這個 Hash 是將要寫入 eFUSE 在 RSA 認證時使用的。
4. o 指定輸出的 Boot.bin 文件名,w表示可以覆蓋文件。
5. encryption_dump 指定將每個分區 AES 加密的詳細過程輸出到 aes_log.txt 中。
6. 所謂“一步到位”命令,就是它能只能識別 BIF 中所指定的密鑰文件是否已經存在,以及互相之間是否匹配。如果
- 如果密鑰已經存在,bootgen 會使用現有密鑰
- 如果密鑰不存在,或部分不存在,bootgen 會生成所有需要的密鑰
- 如果發現已有密鑰不符合規則,比如所有 AES Key nky 文件的的 Key 0 不一致,bootgen 會報告錯誤,因為 Key 0 指的是將要寫入 eFUSE 的密鑰,所有分區的 Key 0 必須一致。
如果只需要其中某一步操作結果,這些參數也可以分開使用。
bootgen -p zcu9eg -arch zynqmp -image secureboot.bif // 生成 Key
bootgen -p zcu9eg -arch zynqmp -efuseppkbits ppk0_digest.txt -image secureboot.bif // 生成 PPK Hash
bootgen -p zcu9eg -arch zynqmp -image secureboot.bif -w -o BOOT.bin -encryption_dump // 生成 BOOT.BIN 和 aes_log.txt
BIF 結構
BIF 是 bootgen 的輸入描述文件。它描述了需要生成 boot.bin 的結構,比如 boot.bin 中有哪些 partition,每個 partition 的源來自哪些文件,這些 partition 由誰引導,會在哪個 target device 上運行,怎樣認證,以及怎樣加密。基本它就是上述第三章總結的表格的文字描述。
BIF 的結構大致是這樣
the_ROM_image:
{
[文件屬性]文件名
[參數類型]參數值
}
具體的文件屬性、參數類型、參數值的可選項,可以參考 UG1137 第 16 章。
參考的 BIF: 使用 RSA + AES (Red Key)
the_ROM_image:
{
[pskfile]psk0.pem
[sskfile]ssk0.pem
[auth_params]spk_id = 0; ppk_select = 0
[keysrc_encryption]efuse_red_key
[fsbl_config]a53_x64
[aeskeyfile]red.nky
[bootloader, authentication = rsa, encryption = aes]FSBL_1112.elf
[aeskeyfile]pmu_fw.nky
[destination_cpu = pmu, authentication = rsa, encryption = aes]pmu_fw.elf
[aeskeyfile]fpga.nky
[destination_device = pl, authentication = rsa, encryption = aes]top.bit
[destination_cpu = a53-0, exception_level = el-3, trustzone, authentication = rsa]bl31.elf
[aeskeyfile]uboot.nky
[destination_cpu = a53-0, exception_level = el-2, authentication = rsa, encryption = aes]u-boot.elf
}
用本章第一節的 Bootgen 命令就能生成 Boot.bin。
從上面的BIF的例子中可以看到:
- 所有 Partition 都加密了,每個 Partition 都對應了一個 nky 文件,這些 nky 文件的 Key 0 一致, Key 1 各不相同。Key 0 解出 Key 1,然后 Key 1 解密對應的 Partition。
- 當 PMUFW 和 FSBL 都加密的情況下,PMUFW 需要由 FSBL 來加載,而不是由 CSU BootROM 來加載,所以使用了 [destination_cpu = pmu],而不是[pmufw_image]。參考 AR 70622
- Bit 文件需要加密的情況下,Bit 要寫在 ATF (bl31.elf) 的前面,因為解密 Bit 需要用的 OCM 空間與存放 ATF 的空間是同一個。參考 UG1137 v8.0 P114
參考的 BIF: 使用 RSA + AES (Black Key)
the_ROM_image:
{
[pskfile]psk0.pem
[sskfile]ssk0.pem
[auth_params]spk_id = 0; ppk_select = 0
[keysrc_encryption]efuse_blk_key
[fsbl_config]a53_x64
[aeskeyfile]red.nky
[bootloader, authentication = rsa, encryption = aes]FSBL_1112.elf
[aeskeyfile]pmu_fw.nky
[destination_cpu = pmu, authentication = rsa, encryption = aes]pmu_fw.elf
[aeskeyfile]fpga.nky
[destination_device = pl, authentication = rsa, encryption = aes]top.bit
[destination_cpu = a53-0, exception_level = el-3, trustzone, authentication = rsa]bl31.elf
[aeskeyfile]uboot.nky
[destination_cpu = a53-0, exception_level = el-2, authentication = rsa, encryption = aes]u-boot.elf
[bh_key_iv] black_iv.txt
}
Black Key 的 BIF 與 Red Key 相比只有微小的改動:
- [keysrc_encryption]改為了efuse_blk_key
- 最后增加了[bh_key_iv],一個 Initialization Vector。
如果只想做非破壞性的實驗,請用附3中著名“Boot Header”的例子BIF。
燒錄鏡像
接下來我們先燒錄鏡像到 Flash,再燒錄密鑰到 eFUSE。如果使用 QSPI Flash, NAND Flash 或 eMMC 啟動,由于燒錄密鑰后 JTAG 將無法方便地使用,先燒鏡像會方便很多。如果使用 SD 卡啟動,先后沒有關系。
這一步和非安全啟動的操作一樣,只是將燒錄的內容替換成上一節產生的帶有安全啟動功能的 Boot.bin。這個 Boot.bin 至少帶有 u-boot,因此后續如果還需要燒寫更多內容,也會比較方便。
燒錄 Flash 可以用 SDK 自帶的工具 SDK -> Xilinx Tools -> Program Flash,也可以使用 u-boot。U-boot 可以事先存放在 Flash 或 SD 卡中,或者使用這個腳本從 JTAG 加載 u-boot。
燒錄密鑰 生成密鑰燒錄程序
燒錄密鑰不需要使用特殊的軟硬件工具,只需要在 MPSoC 上運行一個 Standalone 程序。這個程序可以用 Xilinx Software Development Kit (SDK) 生成。
Xapp1333 的 RSA eFUSE Configuration 章節很詳細地描述了怎樣在 SDK 中生成 xilskey_efuseps_zynqmp_example 以及配置頭文件的過程。這個例子程序可以燒錄 RSA Key 和/或 AES Red Key。Black Key 需要用下面一節講的 xilskey_puf_registration 程序。
簡要描述流程就是:
1. 創建 SDK Workspace, 導入 Vivado HDF 文件
2. 在 BSP Settings 中使能 Library: XilSKey 和 XilSecure
3. 雙擊 BSP 的 MSS 文件,找到 Library - XilSKey, 在 Import Examples 彈出的對話框中選擇需要導入的例子程序
- RSA 和 AES Red Key 使用 xilskey_efuse_zynqmp_example
- AES Black Key 使用 xilskey_puf_registration
4. 修改例子程序中的頭文件中的參數,以符合自己的需求
5. 編譯工程,在板上運行,觀察串口輸出
- 如果使用 Black Key,先運行 xilskey_puf_registration,再運行xilskey_efuse_zynqmp_example
頭文件中每個參數的意義在頂部都有詳細解釋。某些參數僅在使能了其他參數時才有效,具體可以參考C代碼,并不是很難讀。在這里對必要的選項做個概述。
使用 RSA + AES Red Key 的方案,要修改 xilskey_efuse_zynqmp_example 中 RSA 的部分參數和 AES 部分參數;使用 RSA + AES Black Key 的方案,要修改 xilskey_efuse_zynqmp_example 中 RSA 的部分參數和 xilskey_puf_registration 中的部分參數。
xilskey_efuse_zynqmp_example 中 RSA 的部分參數。
參數 目標值 說明
XSK_EFUSEPS_RSA_ENABLE | TRUE | 燒寫 RSA_ENABLE 位。燒錄后沒有 RSA 功能的 Boot.bin 將不能啟動系統;JTAG 也只有在啟動成功后才能使用 |
XSK_EFUSEPS_WRITE_PPK0_HASH | TRUE | 燒錄 RSA PPK0 Hash |
XSK_EFUSEPS_PPK0_HASH | 上文 ppk0_digest.txt 中的內容 | 由 Bootgen 產生的 PPK0 的 SHA3 Hash |
XSK_EFUSEPS_PPK0_IS_SHA3 | TRUE | bootgen 默認生成 SHA3 Hash |
xilskey_efuse_zynqmp_example 中 AES Red Key 的部分參數:
參數 目標值 說明
XSK_EFUSEPS_RSA_ENABLE | TRUE | 燒寫 RSA_ENABLE 位。燒錄后沒有 RSA 功能的 Boot.bin 將不能啟動系統;JTAG 也只有在啟動成功后才能使用 |
XSK_EFUSEPS_WRITE_AES_KEY | TRUE | 燒錄 AES Key |
XSK_EFUSEPS_AES_KEY | red.nky 中的 Key 0 |
xilskey_puf_registration 中需要修改的部分參數:
參數 目標值 說明
XSK_PUF_INFO_ON_UART | TRUE | 輸出打印到串口 |
XSK_PUF_PROGRAM_EFUSE | TRUE | 燒錄 RSA PPK0 Hash |
XSK_PUF_PROGRAM_SECUREBITS | TRUE | 由 Bootgen 產生的 PPK0 的 SHA3 Hash |
XSK_PUF_AES_KEY | red.nky 中的 Key 0 | bootgen 默認生成 SHA3 Hash |
XSK_PUF_IV | 任意 | 完全任意,與其他值沒有關系 |
在真實量產環境中,最好也將以下的鎖鎖上,因為 eFUSE 的燒錄是用反熔絲技術將 0 改寫成 1,沒有燒錄過的比特仍然能繼續修改,知道所有比特都是1為止。將 LOCK 設置為 1 后,對應的 eFUSE 比特就無法再改寫,達到最高的安全性。
xilskey_efuse_zynqmp_example 中防止 eFUSE 再次寫入的鎖
參數 目標值 說明
XSK_EFUSEPS_PPK0_WR_LOCK | TRUE | 防止再次寫入 PPK0 |
XSK_EFUSEPS_AES_WR_LOCK | TRUE | 防止再次寫入 AES Key |
xilskey_puf_registration中的鎖
參數 目標值 說明
XSK_PUF_PROGRAM_SECUREBITS | TRUE | 后續幾個鎖將被寫入 |
XSK_PUF_SYN_WRLK | TRUE | 防止再次寫入 syndrome data |
xilskey_efuse_zynqmp_example 默認的燒錄流程中如果只燒錄 RSA Key(XSK_EFUSEPS_RSA_ENABLE == TRUE)而沒有燒錄 AES Key,AES Key CRC Check 仍然會執行,如果此時 AES Key 并沒有燒錄過,會報告錯誤而退出程序。手工修改代碼,注釋掉這部分即可。2018.2 中仍然有以上問題,后續版本中會修復。
eFUSE 燒錄完成后,斷電重啟,就能看到帶安全啟動功能的Boot.bin中FSBL打印出的內容了。
讓 U-boot 加載安全啟動文件
下面將嘗試只在 Boot.bin 中啟動到 U-boot,讓 U-boot 在繼續保持安全的模式下,獲取 Bit 和 Linux 文件,進一步進行啟動。這樣做的好處是 Linux 和 FPGA Bit 不需要打包到 Boot.bin 中,有利于升級時的文件管理,也可以將不同的部分存放在不同的 Flash 中,降低對啟動 Flash 的容量要求。
U-boot 可以調用 PMU 對安全啟動文件進行認證和解密,可以用來獲取簽名且加密的 FPGA Bit 文件、Linux 鏡像或用戶自定義數據。使用步驟分為兩步:制作文件和加載。具體過程在Xilinx Wiki - Authentication and decryption at u-boot中有詳細解釋。
制作能讓 U-boot 加載的安全啟動文件
像上文一樣通過寫一個BIF文件描述需要簽名和加密的源文件,經過 bootgen 就能產生安全啟動文件。至于 BIF 的寫法,基本和上文上電啟動時一致,只是我們一般不需要 FSBL, PMUFW 和 ATF,去掉那些段即可。
bootgen 命令的使用方法也一致:
bootgen -image Data.bif -w -o Output.bin -arch zynqmp
U-boot 加載安全啟動文件
對于數據文件,比如 Linux 鏡像,使用 zynqmp 命令加載:
zynqmp secure
對于 Bit 文件,使用 fpga load 命令加載:
fpga loads [dev] [address] [size] [auth] [enc] [Userkey address]
關于每個參數的意義,請參考 Wiki 中的詳細解釋。
附錄
附1: RSA Key 樣例
Bootgen 可以根據類似 [pskfile]psk0.pem的 BIF 描述生成 RSA Key psk0.pem。如果密鑰文件已經存在,bootgen 就會使用這個密鑰,而不會生成新密鑰。
RSA Private Key psk0.pem 大致內容如下
-----BEGIN RSA PRIVATE KEY-----
bi4TvfJuikXSAjJ3XoHDCwGZ8SerGMKSJ8gPWFbN/Ay0x27qBGaoAUNjySyWRPQC
...
tWnmtk/l6E1kGvZXvGRr1BJSDh3IV4k/LehTj+zSHD/vZ0GNFUjqAC4RbEkj7t17
-----END RSA PRIVATE KEY-----
附2: AES Key 樣例
Bootgen 可以根據 [aeskeyfile]key.nky生成 AES Key 文件: key.nky。
AES Key 大致內容如下:
Device zcu9eg;
Key 0 A98B3BC6BBA48E2F992C20DB28CB498EB17F3B8D9219AAB6689B726A107F8A70;
IV 0 F18CAED66C8BDA74F8A2DC65;
Key 1 630A30B2815E2518792B3C0CAD84824D7B61586030EE0648FCE363DBC0C03234;
IV 1 43BE7AAAD6631BDB692EB64F;
其中 Key 0 是將要燒錄到 eFUSE 中的 AES Key。
啟動時用 eFUSE 中的 AES Key 解密存于 boot header 中的已經加密了的 Key 1,得到 Key 1 后再用 Key 1 解密這個 Partition。這樣保證盡可能少地使用 eFUSE 中的 AES Key,防止 DPA 攻擊。
附3:常見用法的 BIF 例子
- BIF File with eFUSE Red Key: UG1137 (v8.0) P103
- BIF File with an Operational Key: UG1137 (v8.0) P103
- BIF File for Black Key Stored in eFUSE: UG1137 (v8.0) P106
- BIF File for Black Key Stored in Boot Header: UG1137 (v8.0) P107
- Bif File for Obfuscated Form (Gray) key stored in eFUSE: UG1137 (v8.0) P107
- BIF File with SHA-3 eFUSE RSA Authentication and PPK0: UG1137 (v8.0) P112
五、常見問題和錯誤
只燒 RSA Key,不燒 RSA_EN,導致 FSBL 無法啟動后續 partition
要讓帶 RSA 認證的 Image 成功啟動,必須將 RSA Key 和 RSA_EN 的 eFUSE 位全部燒錄。只燒錄 RSA Key 不燒錄 RSA_EN會導致 FSBL 無法對后續 Partition 做認證。
對應 Error Log
======= In Stage 3, Partition No:1 =======
UnEncrypted data Length: 0x49E1
Data word offset: 0x49E1
Total Data word length: 0x4DA0
Destination Load Address: 0xFFDC0000
Execution Address: 0xFFDC8C68
Data word offset: 0x7A70
Partition Attributes: 0x883E
QSPI Reading Src 0x31180, Dest FFFDC490, Length EC0
.QSPI Reading Src 0x1E9C0, Dest FFDC0000, Length 127C0
.Authentication Enabled
Auth: Partition Offset FFDC0000, PartitionLen 13680, AcOffset FFFDC490, HashLen 30
XFsbl_SpkVer: XFSBL_ERROR_SPK_RSA_DECRYPT
Partition 1 Load Failed, 0x2F
RSA 認證成功后 JTAG 無法使用,無法用 SDK 燒錄Flash
當系統從經過RSA認證的鏡像啟動成功,JTAG 是可以使用的,但是默認并沒有打開,這導致了一些不方便,比如使用 SDK 燒錄其他鏡像,或者用 SDK 進行程序調試等。
通過在 FSBL 中增加AR 68391中提示的代碼,就可以打開 JTAG。一般將它放在 hook before handoff 就可以。
Xil_Out32(0xffca0038,0x3F);
Xil_Out32(0xffca003C,0xFF);
Xil_Out32(0xffca0030,0x3);
Xil_Out32(0xFF5E00B0,0x01002002);
Xil_Out32(0xFF5E0240,0x0);
Xil_Out32(0xFFCA3000,0x1);
注意:由于這些代碼修改 CSU 寄存器,需要運行在 EL3 等級,所以如果放在 U-boot 或者 Linux 代碼中是不工作的。
用燒寫 RSA Key 的程序不能燒錄 Blackkey
libSKey 用于燒寫 MPSoC 的 eFUSE key,有兩個常用程序,分別是 xilskey_efuseps_zynqmpe_example 和 xilskey_puf_registration。后者能燒寫 Blackkey 和 Helperdata。前者能燒寫 RSA PPK 和 Redkey 等除了 Blackkey 以外的情況,因為它不處理 helperdata。
啟動后什么也沒顯示,改怎么調試?
如果已經燒錄了 RSA_EN,但是鏡像認證出錯,芯片會關閉大部分 JTAG 通道,XSCT 無法掃描 JTAG 上的器件,也就無法進一步debug。在這種情況下只有一個通道被留了下來協助調試,他就是 JTAG Error Status 寄存器。
1. 怎樣讀取 JTAG Error Status
請聯系 FAE 了解怎樣獲取 JTAG Error Status 信息,并提供參考資料號碼AR68515 。
2. 獲取 CSU Error Code
JTAG Error Status 是一個 121 位的狀態信息。根據 AR68515 找出 CSU BootROM Errors (CSU_BR_ERR.ERR_TYPE)。
3. 分析錯誤原因
UG1085 Table 11-8 和 11-9 描述了它的意義。找到對應的錯誤模式,再修正錯誤。
不同的安全啟動模式能不能混用?
安全啟動模式有很多中,比如只用 RSA,只用 AES,或同時使用 RSA 和 AES;RSA 和 AES 的情況下,還有使用 eFUSE key, BBRAM Key, Red Key, Gray Key, Black Key 等情況。
以上各種組合,在一次 POR 的情況下,只能保持使用同一種組合。POR 是 Power on Reset,相當于系統完全斷電,或 PS_POR_b 信號拉低,不包含內部通過寄存器重啟的情況。
- 由于 Multiboot 使用內部寄存器重啟機制,所以如果使用 Multiboot,需要保證所有的鏡像使用相同的安全啟動模式。
- 如果 U-boot 需要加載一些經過 RSA 或 AES 加密的鏡像,也需要保證加載的鏡像與啟動鏡像使用同樣的安全啟動模式。
一個完備的安全啟動還需要考慮哪些因素
怎樣保證從頭到尾的安全啟動
本文描述的只是安全啟動的最簡單的幾種方式。如果需要考慮其他方式,比如 Linux 文件系統需要直接存在 Flash 中,要保證黑客無法攻擊、修改 Flash 上的文件保證系統安全就會更難一些。一只雞蛋只要有一條裂縫,它就會變臭的。
怎樣安全升級
遠程系統升級是一個很常見的需求,即使沒有安全啟動的需求,也可能考慮遠程升級和升級失敗的恢復。在需要安全啟動的狀況下,需要保證傳輸通道可靠安全、傳輸內容不能包含私鑰,用帶安全啟動功能的 Boot.bin 燒錄到 Flash 上,做好燒錄失敗的恢復機制即可。
怎樣安全生產
生產主要需要考慮兩方面內容,一是生產廠商是否可以信任,哪些內容可以交給廠商,密鑰泄露的風險有多大;二是生產效率,怎樣以更快的速度、更方便的流程,將密鑰燒入 eFUSE,將加密鏡像燒如 Flash。
六、總結
?本文從講解常用攻擊方法入手,隨后介紹了 MPSoC 如何防御以上講到的常用攻擊手段,怎樣規劃安全啟動,加上實際的操作指南,并附上常見問題及解釋。希望你看完后能了解到,堵上系統中的安全隱患是有必要的,以及在 MPSoC 上使用安全啟動功能,使用成本是很低的,只需要通過一些簡單的學習實驗,就可以讓你的系統更加安全可靠。
七、參考文檔
- UG1085: MPSoC Technical Reference Manual
-
UG1209: Zynq UltraScale+ MPSoC: Embedded Design Tutorial
- Ch.5 -> Secure Boot Sequence
-
UG1137: Zynq UltraScale+ MPSoC Software Developer Guide
- Ch.7 -> Boot Flow -> Secure Boot Flow
- Ch.8 -> Boot Time Security
- Ch.16 Bootgen Image Creation
- Appx. I: XilSecure Library
- Appx. J: XilSKey Library
- Xapp1333: External Secure Storage Using the PUF
- Wiki - Authentication and decryption at u-boot
- Wiki - Solution ZynqMP PL Programming
- XAPP1319: Programming BBRAM and eFUSEs
編輯:hfy
-
FPGA
+關注
關注
1630文章
21799瀏覽量
606147 -
soc
+關注
關注
38文章
4207瀏覽量
219131 -
Xilinx
+關注
關注
71文章
2171瀏覽量
122175
發布評論請先 登錄
相關推薦
國產網絡安全主板在防御網絡攻擊中的實際應用
IDS、IPS與網安防御
服務器被ddos攻擊多久能恢復?具體怎么操作
香港高防服務器是如何防ddos攻擊的
恒訊科技分析:高防ip攻擊超過了防御峰值怎么辦?
無人機主動防御系統有什么作用
無人機主動防御系統有哪些
無人機主動防御系統安裝需要備案嗎
以守為攻,零信任安全防護能力的新范式
![以守為攻,零信任<b class='flag-5'>安全</b>防護能力的新范式](https://file1.elecfans.com/web2/M00/C5/02/wKgaomXxDNCAHfrtAAJNwl2eJDI027.png)
華為提出業界首個L4級AI安全智能體,邁入智能防御新時代
虹科干貨 | 長文預警!使用ntopng和NetFlow/IPFIX檢測Dos攻擊(上)
![虹科干貨 | 長文預警!使用ntopng和NetFlow/IPFIX檢測Dos<b class='flag-5'>攻擊</b>(上)](https://file1.elecfans.com/web2/M00/C9/71/wKgaomYc3JKARcizAAmiKCBDfi4754.png)
評論