DSP

[转]DCSM模块使用说明

2019-07-13 15:56发布

一、功能描述: CSM加密是C2000系列芯片最基础的加密方式,也是在前代产品(如F2803x/F2806x)中广泛采用的加密方式。在最新的28004x、2837x等芯片中增加了双码安全模块(DCSM),该功能支持将芯片中的memory划为两个独立区域,并设置各自独立的的128位CSM密码。该功能可以阻止未授权人员访问加密内容,进而有效防止您的代码被重复或逆向编译;与此同时,需要维护与升级的代码可以存储于另一个独立区域内,并授权给相关人员使用。合理运用此功能,可以进一步地提高产品的安全性以及易用性。   二、功能使用: 2.1 芯片存储的分区设置 下面以Control Suite中TMS320F28377S的 blinky_with_DCSM工程为例,讲解DCSM模块的用法: 首先必须明确,虽然DCSM模块中设计了相关机制允许用户反复设置和使用该功能,但对于DCSM模块的不当操作仍然可能锁死芯片,因此建议您在工程开发的末尾阶段再进行DCSM模块的相关设置和操作。 为了充分发挥双码安全模块的作用,需要根据工程需要对MCU中的资源进行分区配置。通过配置GRABRAMx/GRABSECTx寄存器,按需求将RAM/FLASH分别划入不同的Zone中,从而实现用两套独立密码对不同区域分别进行安全管理。   图1 GRABRAMx/GRABSECTx寄存器设置 以工程blinky_with_DCSM为例,假如我们想要将FLASH A 分配至Zone1进行保护,FLASH B分配至Zone2进行保护。参考手册中关于Zx_GRABSECTR Register及Zx_GRABSECTR Register,需要对DCSM_Zx_ZoneSelectBlock.asm进行如下修改。将Zone 1GRABSECT中FLASH A对应的[1:0]位改为01或10;将Zone 2 GRABSECT中FLASH B对应的[3:2]位改为01或10;特别需要注意的是,由于.asm中一个section是按位写入的,因此在对.asm文件进行修改时,必须以section为单位进行修改,即便有reserve的部分也需要将注释删掉进行编译,否则写入时只会按位写入已编译的内容,发生错位,难以修改。
  •       .sect "dcsm_zsel_z1"
  •      .long 0xFFFFFFFF      ;Z1-EXEONLYRAM
  •      .long 0xFFFFFFFF      ;Z1-EXEONLYSECT
  •      .long 0xFFFFFFFF      ;Z1-GRABRAM
  •      .long 0xFFFFFFFE      ;Z1-GRABSECT

 
  •       .sect "dcsm_zsel_z2"  
  •      .long 0xFFFFFFFF      ;Z2-EXEONLYRAM
  •      .long 0xFFFFFFFF      ;Z2-EXEONLYSECT
  •      .long 0xFFFFFFFF      ;Z2-GRABRAM
  •      .long 0XFFFFFFF7      ;Z2-GRABSECT

  2.2分区的基本设置 在完成了对要保护存储的分区之后,我们需要了解如何给两个区域设置不同的密码。 对于两个保护Zone,每个都有一个专属的OTP Block,以对各Zone进行安全设置,具体包含的资源及作用如下: Zx-LINKPOINTER1-3 配置Zx OTP中Zone Select Block的位置 Zx-PSWDLOCK 用于使能Password Lock Zx-CRCLOCK 用于使能Safe CRC ZoneSelectBlock(0x20-0x1F0) Zone Select Block 预留位置 Zx-EXEONLYRAM 用于使能RAM的Execute-only 保护 Zx-EXEONLYSECT 用于使能FLASH的Execute-only 保护 Zx-GRABRAM 用于配置RAM的所在分区 Zx-GRABSECT 用于配置FLASH的所在分区 Zx-CSMPASSWORD 用于配置分区的CSM密码
  为了能够让用户多次使用该功能、设置不同的密码,如图2,28004x系列MCU在USERS OTP中设置了多个存储密码及相关信息的位置(ZoneSelect Block),用户可以通过LINKPOINTER自由选择当前使用哪一个Zone Select Block。 LINKPOINTER与Zone Select Block 对应关系如图3所示。作为一种校验措施三个LINKERPOINTER的值设为相同,若LINKERPOINTER1/2/3值不相同,则LINKPOINTER的值将被置为全1,系统将默认选择Zone-Select Block 1(0x20)。此外,由于Zx-LINKERPOINTER位于OTP区域,因此该寄存器的各位只能由1写成0,而不能逆向操作。因此,只有Zx-LINKPOINTER的值从“全F”写起,并在每次重新设置时按照下表顺序逐位写0,才能够充分利用到OTP中的所有Zone-Select Block。   图2 Zonex OTP Flash 图3 Zx-LINKPOINTER与Zone Select Block对应关系 以工程blinky_with_DCSM为例,假如是第一次使用DCSM功能,为了充分利用所有Blocks,选取Zone_Select Block0作为当前使用的Block,在DCSM_Zx_ZoneSelectBlock.asm中保证Z1-LINKPOINTER值为全F,此时选取的Zone_Select Block起始地址为0x70820。
  •   .sect "dcsm_otp_z1_linkpointer"
  • .long 0x1FFFFFFF     ;Z1-LINKPOINTER1
  • .long 0xFFFFFFFF     ;Reserved
  • .long 0x1FFFFFFF     ;Z1-LINKPOINTER2
  • .long 0xFFFFFFFF     ;Reserved
  • .long 0x1FFFFFFF     ;Z1-LINKPOINTER3
  • .long 0xFFFFFFFF     ;Reserved
  类似地,如果后续工程需要对密码以及分区情况进行修改,我们可以启用Zone_Select Block1,将LINKERPOINTER的最后一位写0,对应的修改如下:
  •   .sect "dcsm_otp_z1_linkpointer"
  • .long 0x1FFFFFFE     ;Z1-LINKPOINTER1
  • .long 0xFFFFFFFF     ;Reserved
  • .long 0x1FFFFFFE     ;Z1-LINKPOINTER2
  • .long 0xFFFFFFFF     ;Reserved
  • .long 0x1FFFFFFE     ;Z1-LINKPOINTER3
  • .long 0xFFFFFFFF     ;Reserved

  此时需要注意还需要将CMD文件中对应Zone Select Block地址的内容进行修改,保证写入的Flash地址与当前的Zone Select Block正确对应。
  • /* DCSM Z1 Zone Select Contents (!!Movable!!) */  
  • /* Z1 OTP.  Z1 password locations / Flash and RAM partitioning */  
  • DCSM_ZSEL_Z1_P0         : origin = 0x78030, length = 0x000010

  最后在SECTIONS中将要写入区域对应处的type=DSECT 删除,否则FLASH写入不会进行。
  • SECTIONS
  • {
  •    b0_dcsm_otp_z1_linkpointer   : > B0_DCSM_OTP_Z1_LINKPOINTER   PAGE = 0, type = DSECT
  • /* Delete type=DSECT when writing in OTP */    

  特别需要注意的是:由于以上涉及到的寄存器都位于OTP(One-Time Programmable)FLASH中,不能进行反复更改,因此建议在开发后期代码以及内存分配确定之后,再进行相关的设置。   2.3 加密功能及其使用 在完成了对MCU中memory的分区以及Zone Select Block位置的设置后,下面来看DCSM所支持的几种加密模功能: 1)CSM密码加密与解密: CSM加密是DCSM加密的基础,在完成对MCU 存储的分区之后,需要为分区设置各自的密码才能使能加密功能。密码寄存器Zx-CSMPSWD0/1/2/3位于各自的OTP的Zone Select Block中,具体位置由该区域的LINKPOINTER决定。对于2837x系列,当Zx-CSMPSWD0/1/2/3的值为默认值1,该区域处于解锁状态。当寄存器值为全0,该区域会被锁死,因此用户不应当使用全0密码。 以工程blinky_with_DCSM为例,要设置Zone1的密码,我们需要在DCSM_Zx_ZoneSelectBlock.asm中将Zx-CSMPSWDx寄存器改为想要设置的密码:
  • .sect "dcsm_zsel_z1"  
  •       .long 0xFFFFFFFF      ;Z1-EXEONLYRAM
  •       .long 0xFFFFFFFF      ;Z1-EXEONLYSECT
  •       .long 0xFFFFFFFF      ;Z1-GRABRAM
  •       .long 0xFFFFFFBF      ;Z1-GRABSECT
  •       .long 0x11223344      ;Z1-CSMPSWD0 (LSW of 128-bit password)
  •       .long 0x11223344      ;Z1-CSMPSWD1
  •       .long 0x55667788      ;Z1-CSMPSWD2
  •       .long 0x55667788      ;Z1-CSMPSWD3 (MSW of 128-bit password)

  同样需要在CMD中对相应的dcsm_zsel_zx 的sections 进行修改,删除type=DSECT,对FLASH的操作才能够进行。这样就完成了Zonex 密码的设置工作。
  •      b0_dcsm_zsel_z1      : > B0_DCSM_ZSEL_Z1_P0            PAGE = 0
  进行加密后,通过仿真器读取Zone 1 OTP Flash结果如下: 图3 加密后的OTP区域 可以看到此时Zone 1 OTP Flash中除了 CSMPSWDx寄存器中的密码,其它部分均进行了加密操作。之所以采用这样的设计,是为了在开发初期开发者可以利用这一特性随时查看CSM,避免因为密码遗忘或者写入操作造成芯片被锁死。对于密码区域的加密需要通过Password Lock 功能进行,将在后文进行进一步描述。 此时,如果试图通过仿真器读取加密区域Flash B,可以看到Flash区域也进行了加密(返回全0): 图3 未加密的Flash(左)与加密后的Flash(右) 要对CSM进行解密,需要经过Password match flow(PMF)流程,程序将从两个Zone读取CSM PWL并与写入CSMKEYx寄存器的密码进行比对,若密码完全一致,则为该区域解密,否则解密失败。 图4 Password Match Flow 流程图 解密操作可以通过几种方法进行,首先可以在debug界面单击tools -> on chip flash -> 在对应位置处输入密码,点击Unlock: 图5在On chip flash中进行密码匹配 也可以在.gel文件中找到写入csmkey寄存器的代码段,并自行修改密码:
  • *(unsigned long *)0x5F010 = 0x11223344;  // Virtual password
  • *(unsigned long *)0x5F012 = 0x55667788;
  • *(unsigned long *)0x5F014 = 0x11223344;
  • *(unsigned long *)0x5F016 = 0x55667788;

  另外,也可以通过在芯片内部执行一段解密程序完成解密操作,具体代码可参照.gel文件。 以blinky_with_DCSM为例,如果把代码段写入FLASH A,并将FLASH A划入Zone1设置密码保护。在正确输入密码时,烧录操作可以正常进行。 而在不输入正确密码时,会出现解锁失败的提示,烧录也会报错。 图6 未解锁状态下进行烧录报错 NOTE:特别需要注意的是,在使用280049系列芯片时,与传统C2000系列芯片不同,其ZxOTP_CSMPSWD1寄存中写入的默认密码不是全“1”。由于OTP寄存器的特殊性,只能在默认设置的基础上将1改成0,否则可能发生FLASH写入错误。 图8 28004x CSMPWSD1默认密码表(部分) 2)仿真代码保密逻辑 Emulation Code Security Logic(ECSL) 在CSM的基础上,芯片利用CSM密码的后64位设计了仿真加密逻辑。如果试图在加密代码中Halt就会触发该保护,断开仿真连接。用户需要在CSMKEY(0/1)中写入正确的64位密码才能启用仿真,但此时并不会解锁CSM保护,对CSMKEY(0/1)的写入方法可以参考上一条。 图8 在加密代码中Halt触发仿真保护 特别注意,在debug一个加密MCU时,仿真器需要一些时间控制CPU,但此时CPU可能已经运行并触发ECSL保护导致断连。要解决此问题,请使用Wait Boot Mode boot选项,在此模式中,CPU会运行在一个循环中而不进入应用程序,从而避免触发保护。具体设置方法请参考技术手册Boot Rom部分,Launchpad可以通过拨动相应的开关进入此模式。   3)CPU加密逻辑 CPU Secure Logic(CPUSL) CPU加密逻辑可以防止未授权者通过Watch Window读取CPU寄存器,在程序指针指向保护区域时,所有对于CPU寄存器的访问都被禁止(程序指针除外)。在此情况下,最好不要对CPU寄存器进行写入。另外,如果CSM被解锁,此外,CPUSL也将被关闭。 图8 加密代码运行过程中CPU Registers不可见 4)仅执行保护 Execute-Only Protection 对于存储关键数据的RAM或FLASH,TI提供了Execute-Only Protection。当该逻辑启用,任何对该区域数据的读取都将被禁止。例如如果试图使用另一个加密区域中的代码对Execute-Only Protection加密区域中的代码进行复制、读取等操作都将被禁止。通过写入EXEONLYSECT以及EXEONLYRAM寄存器对应位的值,可以启用该功能。 5)密码锁 Password Lock 如前文所述,若只采用CSM加密,可以通过Memory Browser发现此时对应CSM密码的位置并没有进行加密。在开发完成后,开发者需要通过Password Lock功能对此区域进行加密,以防他人读取密码并进行解密。启用该保护的方法是向对应区域的PSWDLOCK寄存器0:3位写入0xF以外的值。 图9 未开启Password Lock时的ZSB0寄存器值 以blinky_with_DCSM为例,要设置Zonex的密码,需要在DCSM_Zx_ZoneSelectBlock.asm中将Zx-PSWDLOCK[3:0]该为非全1,并在CMD中删去相应部分的.DSECT:
  • .sect "dcsm_otp_z1_pswdlock"  
  • .long 0xFFFFFFFE     ;Z1-PSWDLOCK
  • .long 0xFFFFFFFF     ;Reserved
  图10开启Password Lock时的ZSB0寄存器值 至此,我们就完成了DCSM中各种安全功能的介绍和设置,特别注意,由于PSWDLOCK等寄存器并不位于Zone Select Block当中,因此只能进行一次写入,不能进行更改,因此应该在程序开发后期再加此类保护。   三、小结 DCSM加密相较于传统的CSM加密具有更完善的保密措施和更灵活的使用方法。双密码的引入允许用户用不同密码管理不同部分的代码,为产品的代码安全以及后期的升级维护都带来了极大的便利。本实例以2837x系列芯片为对象,描述了DCSM模块常见的使用方法。28004x系列芯片仅在DCSM OTP区域的数量和使用方法上与2837x略有不用,也可参照此说明进行相应操作。 另外部分C2000芯片也可以使用Unique ID作为种子进行进一步的加密,具体方法不在此展开。 转自:http://bbs.21ic.com/icview-2575368-1-1.html?fromuser=