STM32 的加密实现(转)
目的:对运行于STM32的嵌入式代码程序进行加密
编译环境:IAR Embedded System for ARM5.5
一.STM32Flash组织
STM32的Flash包括主存储器(HD版本,512KB)+信息块。信息块包括2KB的系统存储器(用于系统自举启动代码)和16字节的选项字节(8个字节数据+8个字节数据的反码)。
二、STM32读保护
STM32读保护是通过设置RDP选项字节,然后在系统重新复位加载了新的RDP选项字节后启动的。当保护字节被写入相应的值以后:
●通过从内置SRAM或FSMC执行代码访问主闪存存储器的操作,通过DMA1、DMA2、JTAG、SWV(串行线观察器)、SWD(串行线调试)、ETM和边界扫描方式对闪存的访问都将被禁止。
●只允许从用户代码中对主闪存存储器的读操作(以非调试方式从主闪存存储器启动)。
●第0~3页(小容量和中容量产品),或第0~1页(大容量和互联型产品)被自动加上了写保护,其它部分的存储器可以通过在主闪存存储器中执行的代码进行编程(实现IAP或数据存储等功能),但不允许在调试模式下或在从内部SRAM启动后执行写或擦除操作(整片擦除除外)。
●所有通过JTAG/SWD向内置SRAM装载代码并执行代码的功能依然有效,亦可以通过JTAG/SWD从内置SRAM启动,这个功能可以用来解除读保护。当读保护的选项字节转变为存储器未保护的数值时,将会执行整片擦除过程。
●可以使用系统启动程序解除读保护(此时只需执行系统复位即可重新加载选项字节),芯片自动擦除Flash所有内容。
三.STM32的加密
1.使用系统启动程序STM32 Flash Loader demonstrator将Flash设置为读保护。
所有以调试工具、内置SRAM或FSMC执行代码等方式对主存储器访问的操作将被禁止,只允许用户代码对主Flash存储器的读操作和编程操作(除了Flash开始的4KB区域不能编程)。用户代码允许自主编程可以实现IAP或者数据存储等功能。
这样破解者将不能用调试工具、内置SRAM或者FSMC执行代码等方式读出Flash中的代码。破解者也不能使用系统启动程序读取代码,因为要解除读保护,将执行整个芯片的擦除操作。
2.主程序中使用设备ID保护
即使将Flash设置为读保护,破解者也可以通过IAP下载自己的一段小程序,从而读出Flash中的内容。因此,还需要利用设备的唯一ID进行加密保护。在主程序中,加入对设备唯一ID的检测,这样即使破解者读出了芯片中的二进制码,也不能用这个二进制码去复制新的器件。具体实现方法:
(1)在应用程序中定义1个(32位甚至更多)const变量,变量值全为0xFF。每次启动程序时,检查const变量值如果全为0xFF,就读器件的唯一ID,通过Flash编程写入该const变量中(因为全是0xFF,所以可以编程写入)。
(2)在程序中多个地方检查const变量,如果变量值不为0xFF并且与设备ID不一致,就执行与功能无关代码(比如自擦除)。
这样,即使破解者读出了芯片中的二进制码,因为这份二进制码包含了设备唯一ID,具有唯一性,所以不能复制到其他芯片中。
为了避免破解者利用反汇编,根据芯片ID数据在二进制文件中查找对应相同数据的位置从而破解,可以将ID拆散成不同的组合,并且写到不同且不连续的地方。更进一步,可在程序中检测多份这样的分散ID,以增加反汇编的难度。或者将CPUID进行加密,Flash中存储加密后的结果。
四.程序加密的实现
//加密后的CPUID
volatile const static uint32 CPUIDEncrypt = 0xFFFFFFFF; //写入加密数据
void WriteEncrypt(void)
{
//第一次烧写:将UID写入到Flash中
if(CPUIDEncrypt==0xFFFFFFFF)
{
uint32_t CpuID[];
//获取CPU唯一的ID
CpuID[]=*(vu32*)(UID_BASE);
CpuID[]=*(vu32*)(UID_BASE+);
CpuID[]=*(vu32*)(UID_BASE+); //加密算法,很简单的加密算法
uint32_t EncryptCode=(CpuID[]>>)+(CpuID[]>>)+(CpuID[]>>);
FLASH_Unlock();
FLASH_ClearFlag(FLASH_FLAG_BSY|FLASH_FLAG_EOP|FLASH_FLAG_PGERR|FLASH_FLAG_WRPRTERR);
FLASH_ProgramWord((uint32_t)&CPUIDEncrypt, EncryptCode);
FLASH_Lock();
}
}
//判断加密
bool JudgeEncrypt(void)
{
uint32_t CpuID[];
//获取CPU唯一的ID
CpuID[]=*(vu32*)(UID_BASE);
CpuID[]=*(vu32*)(UID_BASE+);
CpuID[]=*(vu32*)(UID_BASE+);
//加密算法,很简单的加密算法
CpuID[]=(CpuID[]>>)+(CpuID[]>>)+(CpuID[]>>);
//检查Flash中的UID是否合法
return (CPUIDEncrypt == CpuID[]);
}
1、将写入加密数据和判断加密两个功能分开。写入加密在PrsCtrlTask开始的地方;而判断加密分布到程序的各个角落。
2、非常重要的是CPUID加密值的定义一定要加“volatile”类型:
volatile const static uint32 CPUIDEncrypt = 0xFFFFFFFF;
否则按速度优化编译,在判断加密值,不会重新读取加密值,导致判断出错。
3、在工程选项Options->Debugger->Download中选择: use flash loader
否则主程序中对Flash编程将不成功。
参考资料:
STM32F10x微控制器参考手册(2009年12月第10版).pdf
STM32 的加密实现(转)的更多相关文章
- 【转】安全加密(一):这些MCU加密方法你都知道吗?
本文导读 随着物联网和边缘计算的出现,五花八门的MCU也被应用其中,如何保证我们的程序安全和知识产权不受侵犯呢,本文我们将对主流MCU的程序加密进行讲解,希望能够帮助你选择最适合自己应用的微处理器. ...
- 详解NXP Cortex-M3加密设置
加密芯片是对内部集成了各类对称与非对称算法,自身具有极高安全等级,可以保证内部储存的密钥和信息数据不被非法读取与篡改的一类安全芯片的通称.使用到安全加密芯片的产品:银行加密U盾.刻录机.加密硬盘.P ...
- 、M/C/U/简单加/密方法、
............................... 一.STM32Flash组织 STM32的Flash包括主存储器(HD版本,512KB)+信息块.信息块包括2KB的系统存储器(用于系统 ...
- STM32的FLASH ID加密
#define FLASH_ID_OFFSET 30000 //任意定义一个数 //把地址直接减去或者加上一个数是不要程序中直接出现这个地址 volatile u32 Flash_ID_addr ...
- [加密]非对称加密STM32实现
转自:https://blog.csdn.net/kangerdong/article/details/82432701 把所有的准备工作都做完了以后,可以将加密算法移植到我们具体的项目中去了,在ST ...
- [stm32] NRF24L01+USART搞定有线和无线通信
前言 一般进行远程监控时,2.4G无线通信是充当远程数据传输的一种方法.这时就需要在现场部分具备无线数据发送装置,而在上位机部分由于一般只有串口,所以将采集到的数据送到电脑里又要在上位机端设计一个数据 ...
- stm32——NFC芯片--PN532的使用
stm32——NFC芯片--PN532的使用 一.NFC简介 NFC(Near Field Communication)近场通信,是一种短距高频的无线电技术,在13.56MHz频率运行于20厘米距离内 ...
- STM32全球唯一ID读取方法
产品唯一的身份标识非常适合:● 用来作为序列号(例如USB字符序列号或者其他的终端应用)● 用来作为密码,在编写闪存时,将此唯一标识与软件加解密算法结合使用,提高代码在闪存存储器内的安全性.● 用来激 ...
- 单片机上使用TEA加密通信(转)
源:单片机上使用TEA加密通信 本文博客链接:http://blog.csdn.net/jdh99,作者:jdh,转载请注明. 环境: 主机:WIN7 开发环境:MDK4.72 单片机:STM32 说 ...
随机推荐
- 尚未配置为Web项目.指定的本地IIS URL http://localhsst/..要打开项目,需要配置虚拟目录 。是否立即创建虚拟目录 解决
1.编辑.csproj文件 2.修改 UseIIS节点改为false,再次打开程序即可
- 笨方法学python--变量和命名
1 =(单等号)和==(双等号)的区别 =用来赋值, ==用来判断是否相等 2 x = 100 在操作符2侧加空格,易读 3 打印时,进行字符串拼接 print "there are&quo ...
- JS-如何把字符串转换成数组
var a = "1,22,33,44"; // 字符串 var b = a.split(","); // 将字符串按照","分割,存入数组 ...
- MySql-时间格式转换之转换为时分秒格式的日期
select date_format(create_datetime,'%Y-%m-%d %k:%i:%s') from busi_repairitem_category MySQL毫秒值和日期的指定 ...
- Android中实现滑动翻页—使用ViewFlipper(dp和px之间进行转换)
Android中实现滑动翻页—使用ViewFlipper(dp和px之间进行转换) Android中dp和px之间进行转换 在xml布局文件中,我们既可以设置px,也可以设置dp(或者dip).一般情 ...
- jquery 中 $('div','li')
要搞清楚$('div','li') 和 $('div , li') 和 $('div li') 区别$('div','li')是$(子,父),是从父节点里找子,而不是找li外面的div $('div ...
- Tomcat 虚拟目录映射
最近老是被一个旧Ant工程所困扰,代码版本都改好了测试也通过了,就是打不了war包,一看build.xml 我的天 各种逆天啊....头大.于是乎想起了最基础的tomcat虚拟目录虽是一个很基础的点, ...
- shortcut to open a linux terminal
1) alt+ f2 2) input "gnome-terminal" 3) press "enter"
- bash报错./mq.sh: line 15: warning: here-document at line 10 delimited by end-of-file (wanted `eof')
[root@localhost tmp]# ./mq.sh./mq.sh: line 15: warning: here-document at line 10 delimited by end-of ...
- 【项目笔记】拿宽高前measure(widthMeasureSpec, heightMeasureSpec)的使用技巧
我们知道获取宽高一般写法是: view.measure(0, 0); view.getMeasuredHeight(); 拿宽高前什么时候可以直接用measure(0, 0);而什么时候不能用meas ...