大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是i.MXRT 系列中數(shù)據(jù)協(xié)處理器 DCP 使用 SNVS Master Key 加解密的注意事項。
?
i.MXRT 不僅僅是處理性能超強的 MCU,也是安全等級極高的 MCU。如果大家用過痞子衡開發(fā)的一站式安全啟動工具?NXP-MCUBootUtility,應(yīng)該會從其 用戶手冊 3.3 節(jié)中了解到 i.MXRT 支持的幾種安全啟動等級,其中 HAB 加密啟動方式和 BEE/OTFAD 加密啟動方式中都提及了一種神秘的密鑰 - SNVS Master Key,今天痞子衡就跟大家聊聊這個密鑰用于 DCP 模塊的注意事項(文中僅以 i.MXRT1060 為例,其他 RT10xx 型號或許有微小差別)。
?
一、DCP 模塊簡介
先來給大家科普下 DCP 模塊,DCP 是 Data Co-Processor 的簡稱,從名字上看是個通用數(shù)據(jù)協(xié)處理器。在 i.MXRT1060 Security Reference Manual 中有一張系統(tǒng)整體安全架構(gòu)簡圖,這個簡圖中標出了 DCP 模塊的主要功能 ?:CRC-32 算法、AES 算法、Hash 算法、類 DMA 數(shù)據(jù)搬移。
?
?
看到 DCP 支持的功能,你就能明白其模塊命名的由來了。本質(zhì)上它就是一個數(shù)據(jù)處理加速器,如果說 CRC-32/Hash 算法只是算出一個結(jié)果(下圖中 Mode3),而 AES 算法則是明文數(shù)據(jù)到密文數(shù)據(jù)的轉(zhuǎn)換(存在數(shù)據(jù)遷移,下圖中 Mode2),DMA 式數(shù)據(jù)搬移則更明顯了(下圖中 Mode1),DCP 內(nèi)部集成了 memcopy 功能,可以實現(xiàn)比普通 DMA 方式效率更高的內(nèi)存到內(nèi)存數(shù)據(jù)塊搬移,memcopy 功能還支持 blit 模式,支持傳輸矩形數(shù)據(jù)塊到 frame buffer 用于 LCD 顯示。
?
?
我們今天主要是聊 DCP 的 AES 加解密功能,其支持 AES-128 算法,包含 Electronic Code Book (ECB)和 Cipher Block Chaining (CBC)模式,算法標準符合 NIST US FIPS PUB 197 (2001)規(guī)范,AES 運算的最小單元是 16 字節(jié)。
?
二、DCP-AES 密鑰來源
對于加解密而言,一個很重要的特性就是密鑰管理。DCP 的 AES 密鑰(長度均為 128bits)來源很豐富,按性質(zhì)可分成四類:
?
SRAM-based keys: 用戶自定義的存放于 SRAM 中的密鑰,最終會被寫入 DCP 的 KEY_DATA 寄存器中,最多四組。
?
Payload key: 用戶自定義的跟加解密數(shù)據(jù)放一起的密鑰,操作時 DCP 直接解析。
?
eFuse SW_GP2 key: 用戶燒錄到 eFuse SW_GP2 區(qū)域的密鑰,可鎖定住讓軟件無法訪問,但 DCP 可通過內(nèi)置專用途徑獲取到。
?
SNVS Master key: 芯片出廠時預(yù)存的唯一密鑰,密鑰值無法獲知,DCP 可通過內(nèi)置專用途徑獲取到。
?
選用 SRAM-based keys 和 Payload key 僅需要在 DCP 模塊內(nèi)部配置即可,而選用 eFuse SW_GP2 key 和 SNVS Master key 則要在如下 IOMUXC_GPR 寄存器中額外設(shè)置。
?
IOMUXC_GPR_GPR10 寄存器用于選擇 Key 是來自 eFuse SW_GP2 還是 SNVS Master Key:
?
?
IOMUXC_GPR_GPR3 寄存器用于選擇 Key 是來自 SNVS Master Key(總 256bits)的低 128bit 還是高 128bit(注意此寄存器對 eFuse SW_GP2 其實不生效,因為 SW_GP2 僅 128bits):
?
?
三、什么是 SNVS Master Key?
SNVS 全稱 Secure Non-Volatile Storage,它既是 DCP 的配套模塊,也是芯片系統(tǒng)的安全事務(wù)監(jiān)測中心。它能夠提供一個獨特的 Master Key 給 DCP 模塊,這個 Master Key 可有三種產(chǎn)生方式(在 SNVS_LPMKCR 中設(shè)置):
?
?
OTPMK:這種就是直接使用 eFuse 里出廠預(yù)燒錄的 OTPMK(256bits),這個 OTPMK 是每個芯片唯一的,并且被鎖住了軟件不可訪問
?
ZMK:這種是利用存在 SNVS_LP ZMKRx 寄存器組中的密鑰,該秘鑰可由用戶寫入,此密鑰在芯片主電源斷掉時會繼續(xù)保留(因為在 LP 域可由紐扣電池供電),在芯片受到安全攻擊時密鑰會被自動擦除。
?
CMK:前兩者組合后的 Key,即 OTPMK 和 ZMK 的異或結(jié)果。
?
一般來說,使用最多的 SNVS Master Key 就是默認的 OTPMK。
?
四、兩種 DCP 驅(qū)動
關(guān)于 DCP 模塊的驅(qū)動,在下載的芯片 SDK 包里有兩種:
?
ROM 版本:SDK_2.x.x_EVK-MIMXRT1060devicesMIMXRT1062driversfsl_dcp.c
?
SDK 版本:SDK_2.x.x_EVK-MIMXRT1060middlewaremcu-bootsrcdriversdcpfsl_dcp.c
?
middleware 里的 DCP 驅(qū)動是 ROM team 負責(zé)的,他們是在芯片 Tapeout 之前寫的,屬于早期驅(qū)動;device 包里的 DCP 驅(qū)動才是 SDK team 負責(zé)的,是芯片 Tapeout 之后寫的,是正式版本。
?
兩版驅(qū)動都實現(xiàn)了 AES 加解密,不過代碼風(fēng)格不同。比如 ROM 版本驅(qū)動的 dcp_aes_ecb_crypt()函數(shù)同時支持加密和解密模式,而在 SDK 版本驅(qū)動里則分成兩個函數(shù):DCP_AES_EncryptEcb() - 加密 、DCP_AES_DecryptEcb() - 解密。
?
五、DCP 正確獲取 SNVS Master Key
前面鋪墊了那么多,終于來到正題了。DCP 模塊如何拿到正確的 SNVS Master Key?讓我們以 SDK_2.x.x_EVK-MIMXRT1060boardsevkmimxrt1060driver_examplesdcp 例程來做個測試。
?
這個 dcp 例程演示了五種 DCP 工作模式,我們就測試第一種 TestAesEcb(),將宏 DCP_TEST_USE_OTP_KEY 改為 1,即使用 OTPMK 低 128bits 作為 DCP 的密鑰:
#define?DCP_TEST_USE_OTP_KEY?1?/*?Set?to?1?to?select?OTP?key?for?AES?encryption/decryption.?*/
int?main(void)
{
????dcp_config_t?dcpConfig;
????//?...
????/*?Initialize?DCP?*/
????DCP_GetDefaultConfig(&dcpConfig);
#if?DCP_TEST_USE_OTP_KEY
????/*?Set?OTP?key?type?in?IOMUX?registers?before?initializing?DCP.?*/
????/*?Software?reset?of?DCP?must?be?issued?after?changing?the?OTP?key?type.?*/
????DCP_OTPKeySelect(kDCP_OTPMKKeyLow);
#endif
????/*?Reset?and?initialize?DCP?*/
????DCP_Init(DCP,?&dcpConfig);
????/*?Call?DCP?APIs?*/
????TestAesEcb();
????//?...
}
在初始芯片狀態(tài)(Hab Open)下,使用 J-Link 下載工程進 RAM 直接單步調(diào)試看一看,在執(zhí)行完 DCP_AES_EncryptEcb()函數(shù)后查看 cipher[]數(shù)組,可以看到其值為 0xCF, 0x2E, 0xA3...,好吧我們根本不知道 SNVS Master Key 到底是多少,所以這個密文是否正確也無從知曉。
?
?
既然無法得知 SNVS Master Key,那我們做個小實驗,使用 SRAM-based keys 來做一次加密,密鑰姑且設(shè)個全 0 吧,再看一下結(jié)果,你發(fā)現(xiàn)了什么,cipher[]的值是不是很熟悉?跟之前 SNVS Master Key 加密的結(jié)果一致,難道這顆芯片的 SNVS Master Key 是全 0?想想不可能,肯定是流程哪里出了問題!
?
?
現(xiàn)在讓我們再回憶 MCUBootUtility 用戶手冊里關(guān)于測試 HAB 加密以及 BEE/OTFAD 加密使用 SNVS Master Key 的前提條件,是的,芯片狀態(tài)需要先設(shè)置為 Hab Close,好,讓我們現(xiàn)在在 eFuse 里將 SEC_CONFIG[1:0]設(shè)為 2'b10(Hab Close),然后再次使用 J-Link 調(diào)試進去看一看,怎么回事?cipher[]值依舊是 0xCF, 0x2E, 0xA3...
?
?
上面的測試對 TestAesEcb()函數(shù)做了一個簡單的修改,將 cipher[]值通過串口打印出來,那我們就將程序通過 NXP-MCUBootUtility 下載到 Flash 里由 ROM 來啟動運行吧(退出調(diào)試狀態(tài)),我們再來看串口打印,哈哈,終于值變了,這意味著 DCP 終于拿到了正確的 SNVS Master Key(非 0)。
?
?
總結(jié)一下,SNVS Master Key 僅在芯片 Hab 狀態(tài)是 Close 并且非調(diào)試狀態(tài)下才能被 DCP 正常獲取,否則 DCP 獲取到的是全 0 的假 Key。
?
至此,i.MXRT 系列中數(shù)據(jù)協(xié)處理器 DCP 使用 SNVS Master Key 加解密的注意事項痞子衡便介紹完畢了,掌聲在哪里~~~