1、聊一聊
? ? 演員這首歌大家應(yīng)該再熟悉不過(guò)了,其中印象最為深刻的歌詞是:"簡(jiǎn)單點(diǎn),說(shuō)話的方式簡(jiǎn)單點(diǎn)......",說(shuō)話真的是一門(mén)技術(shù),同時(shí)也是門(mén)藝術(shù)!
? ? 今天跟大家?guī)?lái)的知識(shí)不算難,現(xiàn)在非常多MCU都有全球唯一標(biāo)識(shí)碼這個(gè)東西,可能大家都了解過(guò),不過(guò)具體怎么用并沒(méi)有實(shí)際設(shè)計(jì)過(guò)!下面重點(diǎn)對(duì)其加密方面的應(yīng)用跟大家理一理。
2、stm32的標(biāo)識(shí)碼UID
? ? 對(duì)于目前大部分MCU都會(huì)存在一個(gè)唯一標(biāo)識(shí)碼供用戶使用,同樣stm32也是一樣,通過(guò)查找對(duì)應(yīng)的數(shù)據(jù)手冊(cè)便可以得到該唯一標(biāo)識(shí)碼的具體信息。
? ? 這里以stm32F103為例,其他型號(hào)的stm32性能也可能不存在該唯一標(biāo)識(shí),具體需要根據(jù)對(duì)應(yīng)的數(shù)據(jù)手冊(cè)進(jìn)行查閱,如果存在可能基地址稍有不同。如下圖所示:
分析一下:
1 ) stm32的標(biāo)識(shí)碼放在了唯一設(shè)備ID寄存器里面,一共96個(gè)bit也就是12個(gè)字節(jié)且只能讀取。
2 ) 通過(guò)手冊(cè)上的說(shuō)明可以大致了解到該唯一標(biāo)識(shí)碼的應(yīng)用場(chǎng)景。
3)一般的量產(chǎn)產(chǎn)品都會(huì)有一個(gè)設(shè)備的條碼,那么這個(gè)唯一的標(biāo)識(shí)碼便可以作為條碼的一部分來(lái)供查找。
4 ) 在通信協(xié)議中該唯一標(biāo)識(shí)碼可以作為一種標(biāo)識(shí)序列號(hào)來(lái)進(jìn)行設(shè)備的加載和區(qū)分。
5 ) 當(dāng)然最后就是把其作為一個(gè)安全密鑰,然后與軟件加密算法結(jié)合起來(lái)以降低固件被惡意復(fù)制的風(fēng)險(xiǎn)。
2、讀取UID
? ? 對(duì)于該唯一標(biāo)識(shí)ID,bug菌這里談兩點(diǎn)注意的:
? ? 1、唯一標(biāo)識(shí)ID只是stm32里面一種ID,其實(shí)一款芯片內(nèi)部還有很多其他ID,比如設(shè)備ID和其他內(nèi)部組件的ID等;
? ? ?2、UID一共是96位具有唯一性,而截取中間的幾位不一定具有唯一性。
? ? ?3、對(duì)于UID的讀取非常簡(jiǎn)單,上面的手冊(cè)截圖也說(shuō)明了,可以通過(guò)字節(jié)、半字和字來(lái)進(jìn)行讀取,也就是說(shuō)可以用8位、16位、32位來(lái)讀取。
參考Demo:
?
1uint32_t??Unique[3]?=?{0}; 2uint8_t???unique[12]?=?{0}; 3 4?int?main(void) 5?{???????? 6?????uint8_t?i; 7 8?????Unique[0]?=?*(uint32_t*)(0x1FFFF7E8); 9?????Unique[1]?=?*(uint32_t*)(0x1FFFF7E8?+?4); 10?????Unique[2]?=?*(uint32_t*)(0x1FFFF7E8?+?8); 11 12?????printf("以u(píng)int32_t讀: ");//插入換行 13?????printf("ID??0-31?:%x ",Unique[0]);//插入換行 14?????printf("ID?32-63?:%x ",Unique[1]);//插入換行 15?????printf("ID?64-95?:%x ",Unique[2]);//插入換行 16 17?????for(i?=?0?;i?12;i++) 18?????{ 19?????????unique[i]?=?*(uint8_t*)(0x1FFFF7E8?+?i); 20?????} 21 22?????printf("以u(píng)int8_t讀: ");//插入換行 23 24?????for(i?=?0;i<12;i++) 25?????{? 26?????????printf("ID?byte%d?:%x???",i,unique[i]);//插入換行 27?????????if(i%4?==?3)?printf(" ");//插入換行? 28?????} 29 30?????printf(" 公眾號(hào):最后一個(gè)bug ");//插入換行
?
輸出結(jié)果:
3、UID加密簡(jiǎn)易版
? ? 之前bug菌整理過(guò)一篇單片機(jī)解密的文章<【整理】一文帶你了解"單片機(jī)解密"技術(shù)>,對(duì)于解密的辦法可以說(shuō)是無(wú)比的殘忍,其實(shí)芯片的加密與解密跟網(wǎng)絡(luò)安全的攻防是一樣的。
? ? 所謂:"道高一尺魔高一丈",只有不斷的更新加密技術(shù)以增加解密成本或許在一定程度上能夠遏制不正規(guī)解密行為在,下面就先介紹一下UID的一種簡(jiǎn)易加密方案,為什么說(shuō)簡(jiǎn)易呢?可以說(shuō)修改部分固件實(shí)現(xiàn)一個(gè)跳轉(zhuǎn)功能就解密了,不過(guò)對(duì)于一般的小型產(chǎn)品還是能夠在一定程度上起到保密效果的。
解釋兩句:
1 )左邊是在芯片外部實(shí)現(xiàn)的,可以通過(guò)編寫(xiě)一個(gè)上位機(jī)來(lái)自動(dòng)生成密鑰并保存到芯片中的存儲(chǔ)介質(zhì)中。
2 )上面所說(shuō)的UID與密鑰的隱式獲取是指 : 其讀取過(guò)程中的地址等信息不要顯式的暴露在固件中,比如上面提到的UID的地址或許是密鑰的地址,可以通過(guò)數(shù)據(jù)變換、運(yùn)算等等進(jìn)行隱藏。
3 )最后一步如果密鑰不一致進(jìn)行自動(dòng)清除固件,該思想有點(diǎn)類似于我們平時(shí)密碼輸入,如果輸入次數(shù)較多就會(huì)鎖定無(wú)法解鎖,這樣對(duì)解密過(guò)程造成阻礙。
4、加強(qiáng)版本
? ? 對(duì)于上面的加密方法其關(guān)卡點(diǎn)就一個(gè)位置,如果在固件空白區(qū)域安插一些跳轉(zhuǎn)指令跳轉(zhuǎn)到正常運(yùn)行的位置,你的固件就解密了。
? ? 所以目前比較常用的是對(duì)整個(gè)固件進(jìn)行完整性標(biāo)識(shí)序列與UID組合進(jìn)行加密的辦法。
? ? ?所以對(duì)于未使用的存儲(chǔ)區(qū)域最好是都填充完,避免被解密者利用。
4、另類版本
? ? ?出于關(guān)卡點(diǎn)過(guò)于單一的問(wèn)題考慮,我們需要進(jìn)行多處的關(guān)卡點(diǎn)處理,同樣各個(gè)關(guān)卡點(diǎn)的復(fù)雜度也會(huì)給解密者帶來(lái)困難,每一處關(guān)卡點(diǎn)都帶有解密信息,相當(dāng)于每次都會(huì)需要判斷機(jī)密,從而讓跳轉(zhuǎn)這種辦法失效。
? ? ?最簡(jiǎn)單的處理辦法就是定義一些宏處理,比如:
?
1#define?Sect_TURE??(UIDCODE?-?SAVECODE??+?1) 2#define?Sect_FALSE?(UIDCODE?-?SAVECODE) 3 4#define?Sect_NUM_1?(UIDCODE?-?SAVECODE??+?1) 5#define?Sect_NUM_2?(UIDCODE?-?SAVECODE??+?2) 6......
?
? ? 當(dāng)然不僅僅只有上面的處理,我們還可以通過(guò)替換為其他變量來(lái)隱藏一些處理辦法,從而達(dá)到迷惑解密著的目的。這樣我們就可以把加密分布到程序的各個(gè)角落,加強(qiáng)了固件的安全性。
? ? 不過(guò)這樣的辦法如果放在訪問(wèn)較為頻繁的位置,勢(shì)必會(huì)影響系統(tǒng)的性能,如果所使用的芯片性能一般,可以選擇部分關(guān)鍵關(guān)卡點(diǎn)處理。
? ? 好吧,所以一切安全的前提是唯一標(biāo)識(shí)碼UID無(wú)法被修改,否則也是徒勞,不過(guò)既然芯片都是人造的,那肯定就有辦法進(jìn)行解密,只是成本問(wèn)題。
5、最后小結(jié)
? ? ?本文到這里就結(jié)束了,對(duì)于MCU的加密和解密是一個(gè)永恒的話題,同樣對(duì)于一個(gè)成熟的產(chǎn)品加密也是必須要考慮的技術(shù)問(wèn)題,看看大家還有什么好的MCU加密辦法,歡迎大家分享留言討論!
審核編輯:湯梓紅
評(píng)論
查看更多