證)
1. 項(xiàng)目概述當(dāng)芯片到云端不再是一句口號(hào)CENTRI 在 ST MCU 上做了一套完整的 Chip-to-Cloud 安全演示這名字聽(tīng)著挺高大上拆開(kāi)看其實(shí)就是把 IoT 設(shè)備從硬件底層到云平臺(tái)這條鏈路全都管起來(lái)。以前我們做物聯(lián)網(wǎng)設(shè)備最頭疼的就是安全老是補(bǔ)丁式地打固件加個(gè)殼、通信加個(gè) TLS、設(shè)備端焊顆安全芯片各干各的出了問(wèn)題互相甩鍋。CENTRI 這套方案想解決的就是這件事——從設(shè)備出廠到云端接入每一步都有信任關(guān)系在而不是靠事后堵漏。這次演示跑在 ST MCU 上說(shuō)明這套東西不是給那些跑 Linux 的高端網(wǎng)關(guān)準(zhǔn)備的而是瞄準(zhǔn)了資源受限的單片機(jī)設(shè)備。ST 的 STM32 系列在工業(yè)、消費(fèi)、汽車后裝市場(chǎng)占有率太高了幾乎能代表主流 MCU 的算力天花板。能在 STM32 這種級(jí)別的小芯片上把 Chip-to-Cloud 安全全鏈路打通意味著大部分中低端物聯(lián)網(wǎng)設(shè)備都能參考這套思路落地。這篇文章我想從方案架構(gòu)、關(guān)鍵選型、實(shí)操步驟和踩坑經(jīng)驗(yàn)幾個(gè)維度拆一拆給正在做 IoT 安全的工程師一點(diǎn)可以直接抄作業(yè)的參考。2. 架構(gòu)拆解Chip-to-Cloud 安全鏈路的分層設(shè)計(jì)與關(guān)鍵選型2.1 安全的分層邏輯為什么不能只靠一把鎖Chip-to-Cloud 這個(gè)詞現(xiàn)在很多廠家都在講但真正落地要看它是不是把安全拆成了多個(gè)信任層。我自己的理解一套完整的設(shè)備安全體系至少要覆蓋四層硬件信任根、設(shè)備側(cè)運(yùn)行時(shí)安全、通信安全、云端身份管理。這四層缺一個(gè)都不行。拿我們?nèi)粘I钪械拈T鎖來(lái)類比硬件信任根是鎖芯設(shè)備端固件是門板通信安全是傳遞鑰匙的人云端是物業(yè)的登記系統(tǒng)。你光換一個(gè)好鎖芯但門板是紙做的或者送鑰匙的人半路被掉包照樣出事。CENTRI 這套方案的優(yōu)勢(shì)在于它把這四層串成了一個(gè)閉環(huán)每一層都產(chǎn)生可驗(yàn)證的證據(jù)而不是各管各的。這個(gè)思路很重要因?yàn)楹芏嘧匝邪踩桨傅膯?wèn)題恰恰出在信任斷層上——設(shè)備端做了安全存儲(chǔ)但云端不認(rèn)云端做了認(rèn)證但設(shè)備端沒(méi)有安全啟動(dòng)。2.2 為什么落在 ST MCU 上更有說(shuō)服力ST MCU 選得很有講究。STM32 生態(tài)太成熟了從低功耗的 L 系列到高性能的 H 系列再到主打安全的 U5 系列幾乎覆蓋了 IoT 設(shè)備的主流算力范圍。而且 ST 官方提供了 STM32Trust 安全框架里面已經(jīng)把安全啟動(dòng)、密鑰存儲(chǔ)、加密加速這些基礎(chǔ)能力包好了開(kāi)發(fā)者不用從零造輪子。另一個(gè)關(guān)鍵點(diǎn)是 STM32U5 這類型號(hào)自帶硬件信任根相關(guān)的特性比如獨(dú)有的物理不可克隆函數(shù)PUF、安全密鑰存儲(chǔ)、加密算法硬件加速。我在實(shí)際評(píng)估項(xiàng)目時(shí)最怕的是方案說(shuō)支持某個(gè) MCU結(jié)果跑起來(lái)發(fā)現(xiàn)要外掛一顆安全芯片才能用那就失去意義了。CENTRI 在 ST MCU 上演示意味著它可以只靠芯片內(nèi)置的資源就把安全鏈路搭起來(lái)這對(duì)成本敏感的產(chǎn)品來(lái)說(shuō)很關(guān)鍵。當(dāng)然如果產(chǎn)品對(duì)安全等級(jí)有更高要求也可以外接 SE 芯片增強(qiáng)信任根但至少不是必需項(xiàng)了。2.3 設(shè)備端與云端的信任握手不只是 TLS很多團(tuán)隊(duì)到現(xiàn)在還覺(jué)得我上了 TLS 就安全了這是最大的誤區(qū)。TLS 能保證數(shù)據(jù)在傳輸過(guò)程中不被竊聽(tīng)和篡改但我們常用的 TLS 是單向認(rèn)證即客戶端校驗(yàn)服務(wù)器證書服務(wù)器并不驗(yàn)證設(shè)備身份。在物聯(lián)網(wǎng)場(chǎng)景里設(shè)備端往往處在物理暴露的環(huán)境中攻擊者可以拆機(jī)、讀存儲(chǔ)、偽造設(shè)備接入云端這時(shí)候如果云端不做設(shè)備身份認(rèn)證就等于把大門鑰匙放在門口墊子底下。CENTRI 這類方案做的是一套基于證書的雙向 TLSmTLS認(rèn)證體系。設(shè)備出廠時(shí)燒錄唯一的身份證書和密鑰云端只認(rèn)持有合法證書的設(shè)備。設(shè)備每次上報(bào)數(shù)據(jù)、接收指令之前云端都要先驗(yàn)證設(shè)備的證書鏈和簽名確保說(shuō)話的是真設(shè)備。這套體系要落地牽扯到 PKI 證書簽發(fā)、設(shè)備生命周期管理、密鑰輪換等一整套流程不是裝個(gè) OpenSSL 就能搞定的。這是 Chip-to-Cloud 之所以復(fù)雜、也之所以值錢的地方。3. ST MCU 上的實(shí)操實(shí)現(xiàn)從工程配置到跑通全鏈路3.1 搭建工程環(huán)境與整體目錄規(guī)劃如果從零開(kāi)始做我建議先搭好工程骨架再碰安全邏輯。CENTRI 的 SDK 一般會(huì)提供幾個(gè)層次的代碼平臺(tái)抽象層負(fù)責(zé)對(duì)接具體 MCU 的 HAL 驅(qū)動(dòng)、核心安全庫(kù)證書管理、簽名驗(yàn)簽、密鑰存儲(chǔ)、協(xié)議層TLS/mQTTS 封裝、云端對(duì)接層。在 STM32 上標(biāo)準(zhǔn)流程是先在 STM32CubeMX 里選好芯片型號(hào)配置時(shí)鐘、UART、SPI 或 I2C如果要外接 Secure Element、隨機(jī)數(shù)發(fā)生器然后生成 CubeIDE 工程再把 SDK 的庫(kù)加進(jìn)來(lái)。我習(xí)慣把工程分成這幾個(gè)目錄app/放業(yè)務(wù)邏輯security/放證書、密鑰管理相關(guān)代碼net/放網(wǎng)絡(luò)協(xié)議棧適配drivers/放 MCU 底層驅(qū)動(dòng)。別把安全代碼和業(yè)務(wù)代碼混在一起后面做安全評(píng)審、證書升級(jí)、問(wèn)題排查時(shí)你會(huì)感謝自己當(dāng)初分的目錄。編譯優(yōu)化級(jí)別建議開(kāi)-O2有些安全計(jì)算對(duì)時(shí)間敏感開(kāi)-O0跑 TLS 握手會(huì)明顯偏慢但也不要貿(mào)然開(kāi)-O3有些編譯器優(yōu)化會(huì)導(dǎo)致時(shí)序行為變化給調(diào)試埋坑。3.2 設(shè)備身份的生成與注入設(shè)備身份是整個(gè) Chip-to-Cloud 安全的源頭。每一臺(tái)設(shè)備出廠時(shí)都要有一對(duì)公私鑰和一個(gè) X.509 證書公鑰和證書可以公開(kāi)私鑰必須鎖死在設(shè)備內(nèi)部。在 STM32 上我推薦把密鑰放到芯片內(nèi)置的 OTP 區(qū)域或者安全存儲(chǔ)區(qū)。如果你用的是 STM32U5它自帶的安全密鑰存儲(chǔ)可以直接把私鑰放在硬件保護(hù)的區(qū)域里軟件讀不出來(lái)只能使用——這屬于標(biāo)準(zhǔn)做法。如果是沒(méi)有安全存儲(chǔ)區(qū)的普通 MCU需要外接 SE 芯片來(lái)保管私鑰不然私鑰暴露整個(gè)安全體系就崩了。生成密鑰的環(huán)節(jié)建議放在產(chǎn)線上做。兩種方式一種是預(yù)生成即你在產(chǎn)線工具里批量生成密鑰對(duì)和證書再通過(guò)調(diào)試口或者燒錄器注入到芯片另一種是設(shè)備端首次啟動(dòng)時(shí)自己生成再由工廠工具簽名并頒發(fā)證書。前者適合快速量產(chǎn)后者安全性更高。CENTRI 演示里通常用的是后者因?yàn)樵O(shè)備自生成密鑰的話私鑰從未離開(kāi)過(guò)硬件這是最理想的狀態(tài)。不過(guò)實(shí)際量產(chǎn)時(shí)很多工廠的產(chǎn)能和工位環(huán)境不一定適合跑這類流程需要和產(chǎn)線團(tuán)隊(duì)提前溝通好。注入完密鑰和證書后記得做一次回讀驗(yàn)證。我曾見(jiàn)過(guò)一批設(shè)備燒錯(cuò)了證書域?qū)е律暇€后所有設(shè)備都無(wú)法通過(guò)云端認(rèn)證排查了很久才發(fā)現(xiàn)是產(chǎn)線腳本把測(cè)試證書當(dāng)正式證書用了。所以出廠前的第一道自檢一定是設(shè)備端現(xiàn)場(chǎng)簽名一個(gè)隨機(jī)挑戰(zhàn)數(shù)據(jù)把簽名結(jié)果和證書一起上報(bào)到測(cè)試云服務(wù)驗(yàn)證通過(guò)才放行。3.3 固件簽名與安全啟動(dòng)安全啟動(dòng)是一臺(tái)設(shè)備值得信任的前提。沒(méi)有安全啟動(dòng)攻擊者替換了固件后續(xù)所有安全措施都能被繞過(guò)。在 STM32 上做安全啟動(dòng)本質(zhì)上就是三段式信任ROM 里的 BootLoader 校驗(yàn)用戶 BootLoader用戶 BootLoader 再校驗(yàn) Application。芯片出廠時(shí)燒入一個(gè)根公鑰哈希到 OTP 區(qū)域每次上電都從固件頭部拿簽名用根公鑰驗(yàn)簽驗(yàn)簽通過(guò)才跳轉(zhuǎn)執(zhí)行。實(shí)現(xiàn)時(shí)我通常用 ST 官方的 X-CUBE-SBSFU 或者原廠的 OEMiROT 這類方案。SBSFU 會(huì)自動(dòng)生成三段鏡像還會(huì)處理密鑰管理和回滾保護(hù)比自己寫校驗(yàn)邏輯靠譜得多。簽名算法建議用 ECDSA P-256在 STM32 上計(jì)算速度還能接受安全性也足夠哈希用 SHA-256這些配合起來(lái)是當(dāng)前 MCU 安全啟動(dòng)的主流組合。這里有一個(gè)很反直覺(jué)的細(xì)節(jié)安全啟動(dòng)不只能驗(yàn)簽還能負(fù)責(zé)加密。固件可以加密存儲(chǔ)到 FlashBootLoader 啟動(dòng)時(shí)先解密再加載防止攻擊者用邏輯分析儀從 Flash 引腳上抄板抄固件。這個(gè)功能叫安全固件更新的一部分它和驗(yàn)簽是兩回事要單獨(dú)開(kāi)。我見(jiàn)過(guò)不少團(tuán)隊(duì)只做驗(yàn)簽不做加密其實(shí)固件被抄走也是重大安全事故尤其當(dāng)你的產(chǎn)品算法有競(jìng)爭(zhēng)力的時(shí)候。3.4 mbedTLS 雙向認(rèn)證與云端接入網(wǎng)絡(luò)層安全主要靠 TLS在 MCU 上最常用的庫(kù)就是 mbedTLS。CENTRI 的 SDK 一般已經(jīng)集成了 mbedTLS你要做的主要是配置和調(diào)用。關(guān)鍵幾點(diǎn)啟用MBEDTLS_SSL_VERIFY_OPTIONAL或者在握手前加載自己的 CA 證書鏈來(lái)校驗(yàn)服務(wù)端同時(shí)必須加載設(shè)備證書和私鑰讓客戶端在 ServerHelloDone 之后把證書發(fā)過(guò)去實(shí)現(xiàn)雙向認(rèn)證。不要只校驗(yàn)服務(wù)端就完事那還是單向 TLS設(shè)備身份照樣不保。我踩過(guò)一個(gè)坑mbedTLS 的內(nèi)存開(kāi)銷在 TLS 1.2 握手階段比較大需要約 16~32KB 的堆空間。默認(rèn)的MBEDTLS_SSL_IN_BUFFER_LENGTH和MBEDTLS_SSL_OUT_BUFFER_LENGTH是 16KB 左右對(duì) STM32U5 這種大 RAM 機(jī)型還好但如果用的是 STM32L4 這種小 RAM 機(jī)型就要手動(dòng)調(diào)小緩沖區(qū)或者把 mbedTLS 配置成使用外部?jī)?nèi)存池。還有一個(gè)細(xì)節(jié)TLS 握手時(shí)證書鏈的解析會(huì)消耗不少 RAM建議在握手完成后立刻釋放掉證書相關(guān)的臨時(shí)緩存這個(gè)選項(xiàng)在mbedtls_ssl_conf_session_cache里可以設(shè)置。連接云端時(shí)協(xié)議上建議走 mQTTS。MQTT 報(bào)頭小、支持 QoS 等級(jí)、斷線重連機(jī)制成熟非常適合資源受限設(shè)備。CENTRI 的云端對(duì)接層一般會(huì)幫你處理 MQTT 的 connect 報(bào)文里嵌入證書信息你要做的是把設(shè)備證書的序列號(hào)、頒發(fā)者信息等注冊(cè)到云端設(shè)備臺(tái)賬里讓云端能根據(jù)這些信息找到對(duì)應(yīng)的設(shè)備主體。記得把設(shè)備上線、下線、異常斷開(kāi)的日志都發(fā)到云端這些數(shù)據(jù)后面做設(shè)備行為分析時(shí)非常有用。3.5 密鑰輪換與證書過(guò)期處理證書不比永久密鑰它有生命周期到了有效期就得換。很多團(tuán)隊(duì)第一次做 IoT 安全時(shí)完全沒(méi)考慮證書輪換結(jié)果產(chǎn)品上線半年后一夜之間全網(wǎng)掉線就是因?yàn)樽C書過(guò)期了。在 CENTRI 的架構(gòu)里這屬于云端的自動(dòng)化流程但也需要設(shè)備端配合設(shè)備要能夠接收新的證書和密鑰并在安全存儲(chǔ)區(qū)內(nèi)完成原子替換不能出現(xiàn)新證書寫一半、舊證書已刪除的尷尬狀態(tài)。具體實(shí)現(xiàn)上我一般預(yù)留一個(gè)安全固件更新證書更新的聯(lián)合通道。設(shè)備收到云端下發(fā)的證書更新指令后先在校驗(yàn)區(qū)存好新證書再做一次簽名驗(yàn)證驗(yàn)證通過(guò)才覆蓋舊證書。更新的私鑰建議直接在設(shè)備內(nèi)部生成云端只要簽發(fā)對(duì)應(yīng)的新證書即可私鑰不出設(shè)備的理念要貫徹到底。整個(gè)更新過(guò)程要支持事務(wù)回滾萬(wàn)一更新失敗還能退回舊證書重新聯(lián)網(wǎng)。4. 常見(jiàn)問(wèn)題與排查技巧實(shí)錄4.1 高頻問(wèn)題速查表現(xiàn)象可能原因排查方法解決參考設(shè)備無(wú)法完成 TLS 握手證書鏈不完整或設(shè)備時(shí)間錯(cuò)誤打開(kāi) mbedTLS 調(diào)試日志查看握手中斷在哪一步確保證書鏈完整校準(zhǔn)設(shè)備 RTC暫時(shí)允許 5 分鐘時(shí)鐘偏移安全啟動(dòng)反復(fù)跳到 BootLoader固件簽名不合法或根公鑰哈希不匹配用工具重新計(jì)算鏡像哈希對(duì)比 OTP 區(qū)存儲(chǔ)值重新簽名鏡像注意產(chǎn)線有沒(méi)有燒錯(cuò) OTP 值私鑰無(wú)法寫入安全存儲(chǔ)區(qū)安全區(qū)容量滿或?qū)懭霗?quán)限被鎖查看安全區(qū)狀態(tài)寄存器嘗試先擦除測(cè)試數(shù)據(jù)預(yù)留至少 4KB 安全區(qū)用于密鑰存儲(chǔ)云端拒絕設(shè)備認(rèn)證設(shè)備證書和云端臺(tái)賬信息不一致在云端后臺(tái)查設(shè)備證書序列號(hào)和設(shè)備 ID重新注冊(cè)證書與設(shè)備的綁定關(guān)系握手耗時(shí)過(guò)長(zhǎng)證書鏈校驗(yàn)用太多 CPU或沒(méi)有開(kāi)硬件加速確認(rèn)是否啟用了 MCU 的 CRYP/RNG 硬件外設(shè)開(kāi)啟硬件加速減小證書鏈深度固件升級(jí)后設(shè)備變磚簽名校驗(yàn)失敗或版本回滾保護(hù)未配置檢查 BootLoader 階段的錯(cuò)誤碼增加版本號(hào)保護(hù)開(kāi)啟回滾防護(hù)4.2 排查思路與現(xiàn)場(chǎng)實(shí)錄講一個(gè)我自己碰到的案例。有一批使用 STM32U5 的設(shè)備在客戶現(xiàn)場(chǎng)經(jīng)常掉線重連錯(cuò)誤日志顯示 TLS 握手在 CertificateVerify 階段失敗。一開(kāi)始懷疑是網(wǎng)絡(luò)丟包后來(lái)用 PC 端模擬客戶端連同一個(gè)云服務(wù)完全正常問(wèn)題被鎖定在設(shè)備端。打開(kāi) mbedTLS 的完整調(diào)試輸出發(fā)現(xiàn)設(shè)備端報(bào)的是MBEDTLS_ERR_X509_CERT_VERIFY_FAILED。我第一反應(yīng)是證書鏈沒(méi)加載全但檢查后發(fā)現(xiàn)設(shè)備本地確實(shí)存了完整的 CA 鏈。后來(lái)懷疑是設(shè)備 RTC 時(shí)間跑偏了導(dǎo)致證書有效期校驗(yàn)失敗。結(jié)果時(shí)間也沒(méi)問(wèn)題。最后用了二分法把證書校驗(yàn)的回調(diào)函數(shù)打點(diǎn)進(jìn)去才發(fā)現(xiàn)設(shè)備私鑰在做簽名時(shí)類型不匹配——私鑰是 ECDSA P-256但證書里的公鑰是 RSA這明顯是產(chǎn)線把兩類設(shè)備的密鑰搞混了。這種問(wèn)題在開(kāi)發(fā)環(huán)境里很難復(fù)現(xiàn)因?yàn)槟闶诸^那塊板子是精心配置過(guò)的。建議在 SDK 里加一個(gè)自檢函數(shù)上電時(shí)對(duì)設(shè)備證書公鑰做一次算法指紋校驗(yàn)再拿私鑰做一次簽名自測(cè)。一旦不匹配直接上報(bào)錯(cuò)誤代碼。這個(gè)自檢成本不高但能省掉大量遠(yuǎn)程排查的時(shí)間。還有一個(gè)經(jīng)驗(yàn)mbedTLS 的mbedtls_ssl_set_hostname在有的移植代碼里會(huì)被忽略導(dǎo)致 SNI 對(duì)不上云端的網(wǎng)關(guān)會(huì)直接 Reset 連接。這個(gè)問(wèn)題非常隱蔽因?yàn)楸镜販y(cè)試時(shí)服務(wù)器不強(qiáng)制校驗(yàn) SNI但上了生產(chǎn)環(huán)境就炸。排查時(shí)要用 Wireshark 抓 TLS ClientHello看看 SNI 擴(kuò)展里帶的域名是不是你想要的那個(gè)。4.3 千萬(wàn)別忽視的產(chǎn)線與物流環(huán)節(jié)很多設(shè)備安全問(wèn)題不是技術(shù)導(dǎo)致的而是流程漏洞。我曾見(jiàn)過(guò)一個(gè)團(tuán)隊(duì)設(shè)備端安全做得無(wú)懈可擊但產(chǎn)線為了圖省事用同一個(gè)測(cè)試證書刷了整批設(shè)備導(dǎo)致所有設(shè)備出廠時(shí)的身份一模一樣。上線后云端只能把它們當(dāng)成同一臺(tái)設(shè)備一臺(tái)下線全部下線場(chǎng)面極其慘烈。所以產(chǎn)線環(huán)節(jié)一定要有獨(dú)立的設(shè)備身份注入工位每臺(tái)設(shè)備的證書和密鑰都要唯一并且要在產(chǎn)線本地做一個(gè)一物一證的抽檢測(cè)試。物流環(huán)節(jié)同樣會(huì)被忽略。有些設(shè)備出廠后要存放幾個(gè)月才到用戶手里證書從簽發(fā)到首連之間的時(shí)間差如果太長(zhǎng)設(shè)備端 RTC 走偏或者證書鏈的 CRL證書吊銷列表更新不及時(shí)都可能導(dǎo)致首次上線失敗。建議證書有效期設(shè)置兩到三年并讓設(shè)備在首次聯(lián)網(wǎng)時(shí)優(yōu)先做一個(gè)時(shí)間同步把 NTP 或云端時(shí)間校準(zhǔn)放到安全握手之前。時(shí)間不同步會(huì)導(dǎo)致整個(gè) PKI 體系失效這是 IoT 設(shè)備最常見(jiàn)也是最致命的問(wèn)題。5. 寫在最后幾點(diǎn)真實(shí)體會(huì)CENTRI 在 ST MCU 上這套 Chip-to-Cloud 演示價(jià)值不在于某個(gè)算法多前沿而在于它把安全從單點(diǎn)功能變成了貫穿產(chǎn)品全生命周期的體系。我做 IoT 安全的這幾年最大的感受是安全沒(méi)有銀彈不可能靠某一顆芯片或者某一段代碼解決所有問(wèn)題。真正的安全感來(lái)自每一層都有信任根、每一次升級(jí)都有驗(yàn)證、每一臺(tái)設(shè)備都有不可冒充的身份。如果讓我給正在規(guī)劃產(chǎn)品安全的團(tuán)隊(duì)一個(gè)建議那就是不要等設(shè)備量上來(lái)了才補(bǔ)安全。從原型階段就把硬件信任根、證書簽發(fā)、安全啟動(dòng)和雙向 TLS 放進(jìn)架構(gòu)里后面付出的運(yùn)維成本會(huì)低一個(gè)數(shù)量級(jí)。我見(jiàn)過(guò)太多先上線再補(bǔ)安全的項(xiàng)目最后都逃不過(guò)推倒重來(lái)的命運(yùn)。最后再分享一個(gè)小技巧在 STM32 上做安全相關(guān)開(kāi)發(fā)時(shí)盡量把安全組件的日志等級(jí)和業(yè)務(wù)日志分開(kāi)。線上環(huán)境只開(kāi)錯(cuò)誤日志但保留一套可以遠(yuǎn)程開(kāi)關(guān)的調(diào)試日志機(jī)制通過(guò)控制命令觸發(fā)輸出。這樣既能保證線上問(wèn)題可追溯又不會(huì)因?yàn)槿罩舅⑵镣下O(shè)備。安全是一條長(zhǎng)跑跑得久比跑得快重要。