引言
ARM芯片作为嵌入式系统的主流芯片,已经广泛应用于手机、路由器及其他工业和民用电子设备[1]。在ARM处理器得到越来越多的应用的同时,如何防止黑客拷贝ARM内部程序、窃取核心代码,防止开发人员花费大量金钱和时间研发出的产品被非法人员一夜之间仿冒的事情发生,已成为亟待解决的问题。
保护嵌入式产品内部程序不被窃取的方法,总体上有软件加密和硬件加密两大类。软件加密主要有加密锁定位、加密字节、伪指令等方法。事实上,由于存储器中程序总体是反汇编可读的,攻击者借助专用设备,便可以而破解芯片内程序,得到程序源代码[2]。甚至不需要得到源码,只需要得到存储器上的二进制文件,将其复制到同型号设备中,就可以得到同样功能的设备。硬件加密方法,往往采用专用的加密卡或加密芯片的方式,通过相应的传输协议及硬件电路完成加密[3]。但是,硬件加密方案会增加设备制造的复杂度和设备成本。
本文以ARM CortexM3芯片为例,设计并实现了一种基于分散加载的ARM芯片加密方案,此方案将经过加密的程序烧写到存储器上,从而完全打乱程序在存储器上的正常顺序,使其反汇编完全不可读。以ARM芯片内全球唯一的序列号为密钥,确保被整片复制的程序无法正确运行在其他设备上。此方案充分利用了ARM芯片的特点,为嵌入式产品开发工程师提供了一种保护知识成果的方案。
1 分散加载技术介绍
1.1 分散加载的基本原理
在嵌入式系统中,其存储系统常常由FLASH、ROM、RAM等存储器组成,它们被定位于不同的物理地址范围。为了让软件更好地访问和利用这些存储器并让系统高效的运行,ARM链接器提供了分散加载机制。在链接时可以根据分散加载文件中指定的存储器分配方案,将可执行镜像文件分为指定的分区并定位于指定的存储器物理地址。当嵌入式系统在重新上电或复位时,首先对处理器内部寄存器执行初始化,然后执行ROM存储器的自举代码,根据链接时的存储器分配方案,将相应代码和数据从加载地址复制到运行地址。这样,定位于RAM存储器中的代码和数据就在RAM中执行,而不再从ROM存储器中执行[4]。利用分散加载的特性,可以在加载域指定的ROM中存储经过加密的二进制程序,而在对应的运行域RAM中将其还原,RAM的掉电易失性使源程序不被暴露。
1.2 存储器规划
ARM CortexM3芯片有32 KB本地静态RAM和512 KB片内FLASH[5],其地址映射如图1所示。
图1 ARM CortexM3存储器映射
由于ARM芯片程序中有大量的公共库程序和简单的流程控制程序,所以不需要加密全部程序,只要加密核心代码即可。本文把ARM程序抽象成三大部分:预处理部分、核心程序部分、其他程序部分。预处理部分最先执行,负责与上位机软件交互、解密加载域并写入对应运行域中。核心程序是芯片代码中需要加密部分,其加载域上存储其密文。其他程序为芯片代码中的公共库程序或简单流程程序,其加载域上直接存储其明文。本文对存储器的规划如表1所列,值得注意的是核心程序的运行域在RAM上。根据分散加载文件的编写规则和表1,编写相应分散加载文件后,使用集成开发环境编译并下载程序,预处理程序、核心程序、其他程序将会被烧写到相应加载域,并且得到三个与之对应的二进制文件。
表1 CortexM3存储器规划
2 加密方案具体实现
软件加密的目的就是要千方百计造成机器码的错误反汇编或反汇编后的程序不可读,所以可以考虑把程序加密后再烧写到FLASH中,达到完全打乱FLASH程序顺序的作用。这样,不法分子从FLASH中提取的程序,反汇编的结果将是完全不可分析的。被加密的程序运行前,将其解密后到复制到分散加载文件指定的位于RAM的运行域,由于RAM的掉电丢失性,正确的二进制程序将被隐藏。到此为止,已经能够阻止不法分子通过反汇编得到程序的源代码。然而,仍然没有防止仿制者通过非法手段整片复制芯片程序到同型号的其他芯片,从而快速生产出同类电子产品。通过对ARM芯片的分析发现,在所有ARM芯片内部寄存器中,都有一组128位全球唯一芯片序列号[5]。并且此序列号只能被读取,不能被修改,可以以此序列号作为加密算法的密钥,这样,由于所有ARM设备的密钥都不同,不法人员通过简单拷贝芯片程序给其他同类型芯片,会因为密钥不匹配,得不到正确的运行域程序,使整片复制芯片程序的窃取方法失败。
本文的加密方案总体思想如图2所示。首先以分散加载方式规划存储器,正常加载程序。然后将核心程序以ARM序列号为密钥,加密后烧写到分散加载文件指定的加载域上,以密文形式覆盖原有明文。最后,在预处理程序中提取设备序列号,以此为密钥进行解密,将得到的结果复制到分散加载文件指定的运行域中。
图2 加密方案
2.1 加密算法选择
在数据加密认证的过程中,选择合适的加密算法是研发工程师首先要考虑的事情。选择加密算法时要结合自身需求,从算法执行速度、安全性、资源占用性等方面进行综合考虑。对称加密算法是常用于嵌入式设备加密的主要方法,其中广范应用的对称加密算法有AES算法和DES算法。DES算法有不能对抗差分和线性密码分析、对系统资源要求高等缺点[6]。2000年,美国国家标准局正式宣布AES算法为新的高级加密标准。AES优点如下:运算速度快,对内存要求低,高安全性等。由于AES算法可以提供128位密钥,所以128位ARM芯片全球唯一序列号不做任何处理便可作为AES算法密钥,本文选用AES算法作为核心程序加密算法。
2.2 核心程序加密实现过程
根据表1的分散加载方案下载程序到存储器芯片中后,包括核心程序在内的所有程序在FLASH上都以明文存储。要使核心程序不被窃取,必须对其加密处理,以密文覆盖原有明文。在实现时,要设计一个简单的上位机软件,其与芯片中预处理程序配合完成芯片加密工作。上位机可以用MFC或C#开发,笔者以MFC方式实现的上位机软件界面,如图3所示。
图3 上位机软件界面
上位机可以采用无线、串口、USB接口等任何方式与ARM微处理器进行通信。上位机首先判断是否与ARM设备连接,笔者采用的方法是上位机向微处理器发送CONNECT宏命令,如果从ARM设备收到同样的CONNECT宏命令,则可以判断ARM设备与上位机成功连接。之后,上位机自动发送GET_SERIAL_NUMBER宏命令让微处理器调用内置函数读取芯片全球唯一序列号,并将此序列号发送给上位机。选择核心程序对应的二进制文件进行加密处理,上位机会调用AES算法,以芯片全球唯一序列号为密钥产生经过加密的核心程序文件。选择产生的加密核心程序文件,将分散加载文件中核心程序的加载地址和运行地址分别填入上位机软件相应控件。最后,上位机会把经过加密的核心程序文件发送至ARM设备中。芯片中预处理程序接收到加密核心程序后,以在应用编程(IAP)方式将经过加密的核心程序覆盖未加密核心程序的加载域。除此之外,发送加密核心程序的同时,烧写地址(ROM_CORE_ADDR)、执行地址(RAM_RUN_ADDR)以及核心程序代码大小(CORE_SIZE)三个参数被一起发送给ARM设备,预处理程序解密时要使用以上三个参数。核心程序加密流程如图4所示,执行每一步的结果都会在上位机上得到显示。
图4 核心程序加密流程
2.3 运行时解密的实现过程
为使此加密方案通用性更强,将与上位机通信的程序和解密程序全部放到预处理程序部分,只要在ARM程序的起始部分添加预处理程序,所有ARM系列微处理器都可以应用此加密方案。预处理程序执行时,首先检测ARM设备是否与上位机相连,如果相连,执行与上位机交互相关程序,如上文提到的接收核心程序密文,以IAP方式覆盖核心程序加载域明文、ARM序列号发送等。如果ARM设备没有与上位机连接,进行运行域解密工作,首先调用ARM芯片提供的API提取内部全球唯一序列号(SERIAL_NUMBER),然后以此为密钥,对核心程序加载域(ROM_CORE_ADDR)上的程序执行AES解密,最后将结果复制到核心程序运行域(RAM_RUN_ADDR)。关键程序描述如下:
uint8_t ciphertext [16], plaintext[16];// CORE_SIZE单位为字节,以此确定要解密的次数
unsigned int decrypt_times = CoreSize / 16, i = 0;
while (i < decrypt_times) {//把加载域上的密文复制到ciphertext中
memcpy(ciphertext, (uint8_t *)( ROM_CORE_ADDR + i * 16), 16); //SERIAL_NUMBER为密钥,将ciphertext解密后复制到plaintext中
aes_decrypt(ciphertext, plaintext, SERIAL_NUMBER); //把解密后明文复制到RAM运行域
memcpy((uint8_t *)(RAM_RUN_ADDR + i * 16), plaintext, 16);
}
采用迭代的方法,每次从核心代码加载域提取128位,将其解密后复制到核心代码运行域,迭代的次数由核心程序代码大小决定。无论要解密的核心程序有多大,此方案只需32字节的额外存储空间。另外,应用ARM处理器特有的32位指令集,可以大幅加快AES解密算法的执行速度。将解密后的核心程序复制到相应运行域后,就可以跳转出预处理程序,执行正常的功能程序。运行时解密过程如图5所示。
图5 运行时解密过程
3 安全性分析
对嵌入式软件而言,没有办法做到绝对的保密,只能采取合适的加密技术尽量提高解密成本,只要能使剽窃者望而却步,就是成功的加密方法[7]。本文提出的基于分散加载的ARM芯片软件加密方法大大增加了剽窃者破解系统的难度和成本,会使剽窃者感到得不偿失而放弃解密,从而有效地保护开发者的劳动成果。
本文提出的加密方案较高安全性主要体现在:芯片内部序列号的全球唯一性,以及以此序列号为密钥,应用高强度加密算法进行加密后存储器核心程序反汇编完全不可读。首先,即使黑客通过非法手段将整个芯片程序复制到另一个同型号的芯片中,由于两个芯片内的全球唯一序列号不同,运行过程中解密得到的程序完全不可运行。其次,即使黑客通过专业手段,从芯片中得到了程序的二进制文件,由于存储器上核心代码已经经过了AES加密,此文件经过反汇编是完全不可读的。
结语
本文提出的基于分散加载的ARM芯片软件加密方案安全易用,克服了其他软件加密方法不能同时防止代码拷贝和代码窃取的不足,避免了外扩硬件加密芯片和加密电路给系统带来的高成本和复杂性。笔者已经将该方案应用于自身开发的产品中,运行效果良好。本文提出加密方案,可以应用于ARM系列所有芯片,在不影响芯片内部程序整体功能的情况下,为从事嵌入式产品开发的技术人员提供了一种保护知识成果的有效途径。