STM32 应用程序加密的一种设计方案
0、前言
STM32編譯后的代碼存在FLASH中,通過外部工具可以讀出來全部數據,一旦硬件抄板一樣,再將FLASH數據全部拷貝至抄板單片機中,既可以完全實現硬件和軟件功能抄襲。因此,需要對自己的應用程序加密,即使被抄板和讀取FLASH數據,拷貝過后仍然無法執行相應的功能。【ps:沒有解不開的單片機,主要看解密的經濟效益】
主要思路:利用每個芯片的96位唯一ID,進行一定的計算和單向加密,得到唯一的應用AppKey并保存至FLASH,運行APP時讀取該FLASH位置的AppKey,并與計算得到的AppKey比較是否相同,如果相同則正常運行,不相同則退出。
因此,在正確運行APP之前,需要保證FLASH保存有AppKey,可以在設備出廠前提前通過代碼方式寫入FLASH,再燒寫正常的APP代碼。為了減小代碼燒寫的工作量,采用IAP的方式實現自動出廠配置,方案包括三個工程:BootLoader,Encrypt,APP。三個工程在FLASH中的內存分配與OTA-IAP相同。
一、計算AppKey
step1 :為避免出現UID_BASE的明文,在讀取UID時,對其地址進行一定的簡單運算,再讀取UID。
#define ADDRSEED (0x20170620) #define METHORDADDR (ADDRSEED^1+1) #define METHORDEUID (ADDRSEED|0x12345678)volatile const uint32_t uidaddr[3] = {UID_BASE+METHORDADDR,UID_BASE+4-METHORDADDR,UID_BASE+8+METHORDADDR};//get uid, by calc uidbase //uid: ptr, 96byte length static void Getuid(volatile uint32_t *uid) {volatile uint32_t addrtemp;addrtemp = uidaddr[0] - METHORDADDR;uid[0] = *(volatile uint32_t*)(addrtemp);addrtemp = uidaddr[1] + METHORDADDR;uid[1] = *(volatile uint32_t*)(addrtemp);addrtemp = uidaddr[2] - METHORDADDR;uid[2] = *(volatile uint32_t*)(addrtemp); }step2 :對UID進一步簡單加密。
//encrypt uid //euid: ptr, 96byte length static void Encryptuid(volatile uint32_t *euid) {uint32_t uid[3];Getuid(uid);euid[0] = uid[0] + METHORDEUID;euid[0] ^= ADDRSEED;euid[1] = uid[1] + METHORDEUID;euid[1] ^= ADDRSEED;euid[2] = uid[2] + METHORDEUID;euid[2] ^= ADDRSEED; }step3 :對EncryptUID計算MD5,計算128bit單向散列值。
//generate md5 by euid //key: ptr, 16byte length void GenerateMD5(uint8_t *md5) {uint32_t *euid;Encryptuid(euid);MD5_Init(&Context);MD5_Update(&Context,(uint8_t *)euid,96);MD5_Final(&Context,md5); }step4 :根據FLASH頁容量大小,將MD5擴充至1024Byte,采用隨機數擴充。
//generate key //key: ptr, 1024 length, md5 extend to 1024 void GenerateKey(uint8_t *key) {uint16_t i,j;uint8_t md5val[16];GenerateMD5(md5val);j = 0;for(i = 0; i < 1024; i++){if(i%64 == 0){key[i] = md5val[j++];}else{srand1(HAL_GetTick());key[i] = randr(0,0xFF);}} }二、自動配置流程
Encrypt工程代碼只在出廠時運行一次,目的是利用UID產生AppKey,并將其提前寫入指定FLASH中,因此,該段代碼執行一次后將擦除。可設置Encrypt在APPA區中運行,利用IAP功能,將APPB區的APP固件在執行完Encrypt固件后,搬移至APPA區。
具體地,出廠自動配置密鑰流程如下:
Step1:上電啟動單片機,首先執行BootLoader程序。
Step2:BootLoader讀取Parameter參數區,此時參數區設置為無升級任務,BootLoader執行APPA區的代碼,進入 Step3 。存在升級任務時,執行 Step6, Step7 。
Step3:BootLoader跳轉至APPA,執行Encrypt代碼,根據UID計算AppKey,執行 Step4 和 Step5 。
Step4:將計算的AppKey存入Parameter區指定的位置,并寫入升級標志和APPB區相關固件參數。
Step5:重啟單片機,進入BootLoader。
Step6:清除升級任務標志。
Step7:拷貝APPB代碼至APPA區,即擦除Encrypt代碼,最后執行重啟進入 Step5 ,重啟后運行真正的APP代碼。
三、出廠固件合并
出廠前需要在STM32中燒寫BootLoader、Encrypt和APP三份Hex固件,加大了時間開銷,三份Hex固件存在FlASH的不同位置,地址容易出錯。因此,可將三份Hex進行合并成一個Hex,進行一次燒寫,按照自動配置流程完成加密和代碼搬運工作。
BootLoader工程在程序一開始運行,其地址和空間大小分配仍然按照0x08000000和20kB分配,編譯生成boot.hex。Encrypt工程和APP都在APPA區運行,因此,兩者地址和空間大小分配為相同的0x08005000和50kB。APP.Hex只是保存在APPB區,帶加密執行完成后通知Bootloader進行搬移。
出廠固件按照boot.Hex,encrypt.Hex,app.Hex的順序合并,打開Hex文件,分別用后一個文件的全部內容替換前一個文件的最后一行,保存為hex格式就可以。
總結
以上是生活随笔為你收集整理的STM32 应用程序加密的一种设计方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 小白的入门之——汇编语言程序设计教程
- 下一篇: 文治者必有武备不然长大了挨欺负_【博古斋