【精品博文】使用J-Flash实现Kinetis唯一ID绑定加密
关于Kinetis加密类的文章,我之前在我的博客里写过不少,也得到了很多博友的支持和欢迎。所谓道高一尺魔高一丈,“魔道之争”(比较形象哈,呵呵)在我们嵌入式开发领域也是愈演愈烈,同时也是在我们李总理大力倡导的”全民创新“大浪潮下(咳咳,说的有点大,但的确是实情,呵呵),大家在嵌入式产品开发选型之初已经开始逐渐理性,从早期的唯成本论到现在除了能满足产品基本要求之外也开始考虑芯片的可靠和安全性,可以看出大家对产品知识产权保护方面越来越重视,毕竟以我大华强北为标志的芯片破解行业生态链如今已经达到非常恐怖的程度,作为产品开发者来说,绝对的安全我们谁也不敢指望,但是谁不希望自己的产品能多上一层保护伞呢,哈哈。正所谓破解行业的一句老话“没有破解不了的芯片,只是时间和成本问题”,如果破解一款产品的成本超出或者接近破解后所能获取的利润,那破解也就没有意义了,所以我们就可以称这款产品就是相对安全的。
回到芯片本身上来,芯片级的加密无非可以分成两类,一种是半导体原厂在芯片加密方面所做的硬件相关的加密措施,另一种则是用户端需要做的软件相关的加密措施(当然软件加密需要依托一些芯片端的硬件特性,比如芯片出厂的唯一ID,或者外加独立加密芯片,后者我这里就不提了,本文主要讲前者即唯一ID绑定)。我之前的文章都是讲的第一种加密方式,本篇文章则换换思路简单写个软件加密的方法,而主角则还是我大飞思卡尔(New NXP)的Kinetis系列,其中Kinetis K系列M4内核的芯片内部有128bit唯一ID号可以供软件加密使用(ID号编码则是随机算法,避免了同一批次可能会出现有规律的序号问题)。有这128bit ID号作为钥匙,实际上用户可操作的灵活性还是比较高的,通常来讲为了最好的安全性,用户可以自己编写个上位机或者脚本,在批量烧写每片芯片之后读出芯片ID号然后做复杂的软件算法处理最后生成秘钥再将该秘钥写回芯片Flash的某个地址当中,在用户的应用程序中则定期读取该地址的秘钥进行校验以确保安全性。本文则利用现成的J-Flash完成类似的软件加密功能,但是由于J-Flash的功能有限,所以这种软件加密是一个简化版的加密方式,仅供学习和参考啦,下面开始吧,呵呵:
硬件平台: FRDM-K64(飞思卡尔Kinetis MK64FN1MVLQ12,M4内核)
软件工具:Segger J-Flash v5.0
1. 打开Jlink自带的J-Flash烧写工具,并选择新建一个project,并在J-Flash菜单栏中选择Options->ProjectSettings,配置好TargetInterface为SWD方式,CPU选择device->MK64FN1M0xxx12,如下图所示:
2. 把要烧写的用户代码image文件拖到J-Flash窗口(bin或者Hex都可以,我这里选S19文件也算是为了致敬曾经的巨头Motorola吧,呵呵),点击“Target->Connect”即可与目标芯片连接成功,如下图。此时实际上正常的烧写程序就可以通过“Target->Auto”来完成了。然并卵….我们的目标肯定不只限于简单烧写个程序,俺们是要高大上的加密的有木有,下面继续;
3. 书接上回,呵呵,在我们进入正题之前,有些准备工作需要提前做好。第一个是需要在K64的数据手册中找到唯一ID所在的地址(K64的唯一ID号为128位),我们这里只是简单演示,所以只取128位唯一ID号的低32位即SIM_UIDL寄存器如下图1所示,其地址为0x40048060,第二我们需要先查看下当前板子上K64芯片的ID号是多少以验证我们最后通过J-flash写进去的对不对,通过IAR在线调试查看该寄存器可以看到我板子上K64的唯一ID号为0x9018000B如下图2所示,Ok,准备工作完毕,进入重点内容,keep moving, go;
4. 我们选择J-Flash菜单栏“Target->ProjectSettings->CPU”,找到最下面的辅助功能“Init Steps”和“Exit Steps”,即J-Flash贴心的为我们预留了点击Auto之后正式烧写之前(Init Steps)以及烧写之后启动用户程序之前(Exit Steps)这两个时间段可人为添加指令,为我们接下来的加密措施提供了可操作性(我只能心里一遍一遍的默念,Segger你真NB),这里我们通过在Init Steps中添加指令来完成软件唯一ID绑定加密,具体添加指令如下图所示(点击左下角的“Add”添加),第一个Reset是默认的指令我们不需要改动,第二步“Read 32bit”指令即从Value0参数指定的地址中读取32bit数据到缓存,第三部“Var XOR”指令即用Value1的参数与上一步的缓存数据进行异或操作并覆盖原来的缓存,最后一步(咳咳,看来比装大象到冰箱费了一步的劲儿,呵呵)把缓存里面的结果数据写到Value0参数所指定的地址中(这个地址理论上是可以任意指定,但为了防止被后面用户程序所覆盖建议这个地址尽量选择芯片Flash的靠后面的区域),然后点击Ok保存配置;
5. 全部配置完毕之后,点击菜单栏“Target->Auto”自动完成擦写和InitStep的动作,为了验证是否写入正确,可以继续点击”Target->Read back->Entire Chip“可以完整的把芯片中的代码读回来,在读回来的文件中找到我们在上一步填入的写入地址0x0000F000,查看该地址的内容如下图,最后用第三步得到的未加密的数据与第四步的加密逻辑进行一下简单的逻辑运算,最后算出来可以得出我们读回来的数据的确是加密后的数据了,怎么样,是不是挺方便挺NB的(这里只添加了一步与逻辑运算加密,实际上可以添加其他逻辑操作,但是局限的是也只有逻辑操作了,这种加密略简单略简陋了些),这样我们需要在程序中以固定周期去读取本芯片的唯一ID号然后在到J-Flash里配置的最后加密数据写入的地址进行数据比对,如果是正确则可以正常执行,如果错误则认为是被破解了,拒绝执行即可。
呼。。。总算是完结了,这篇文章断断续续的间隔了好几天才完成,写起来的确比较麻烦些,索性最后交差了,呵呵。不过就像我上面提到的,使用J-Flash的这种加密方式由于只限于对唯一ID号进行逻辑上的与或非操作,所以的确是比较简单的所谓加密了,仅限于玩玩和参考学习了,如果真正的想做好绑定ID号进行复杂加密算法的方式还是推荐自己做个上位机去做好了,J-Flash比较是比较限定死了,但是也足以说明Segger的NB之处了,呵呵。好了,就到这里,真是写虚了,累了歇会儿,未完待续!