前言¶
与本文档相对应的产品版本如下。
本文档(本指南)主要适用于以下工程师:
技术支持工程师
软件开发工程师
在本文中可能出现下列标志,它们所代表的含义如下。
概述¶
SSxxxx SoC提供丰富的安全特性,包括一系列硬件、固件和软件,以支持客户构建安全可信的设备。主要的安全特性如下:
One Time Programmable(OTP),用于存储包括设备安全启动验签的RSA 公钥哈希、多组对称根密钥、SoC安全相关的各种控制信息,以及用户自定义数据等。
芯片支持基于OTP对称根密钥的三级密钥派生。支持对烧录到OTP的根密钥的加扰保护;密钥派生过程中所有的明文密钥软件不可见。
硬件真随机数。
非对称密码算法RSA模块。
支持多种通用Hash算法和对称密码算法的SPACC模块。
基于硬件可信根的安全启动:支持安全镜像逐级校验;支持镜像加密可选择;支持TEE/REE信任链分离;安全启动镜像和非安全启动镜像格式统一,即安全启动没有使能的情况下,非加密的安全启动镜像也可以正常启动。
支持ARM TrustZone,支持安全、非安全内存地址隔离。客户可构建TEE安全方案。
支持安全JTAG。
OTP¶
简介¶
OTP是一种非易失性存储器,其主要特性是对应存储空间的内容由0写为1之后,或者写入后锁定,就不能再次更改。SSxxxx OTP 包含如下几大区域:
存放SoC各种密钥的区域:包括存放安全启动的根公钥哈希值(受限可读),存放保护多个对称密码算法根密钥。密钥区域一旦发起写入操作,自行锁定不可再更改。
芯片可存放各组根公钥哈希值,用于安全启动校验。包括:芯片厂商根公钥哈希(已预置),OEM根公钥哈希和第三方双签名根公钥哈希。客户可根据产品实际需要,选择合适的根公钥(通过OTP选择)。
加解密根密钥:芯片预留4个OEM可烧写的对称密码根密钥OTP空间,oem_root_symc_key0~ oem_root_symc_key3,OEM可以利用这里面的一个或者多个根密钥,分别派生出不同的密钥保护密钥和工作密钥。这些密钥区域可以通过对应的OTP烧写接口烧写,一旦写入,硬件自行锁定,不可更改。写入的内容也不能通过软件方式或JTAG接口读取得到。
芯片预置一个芯片厂商TEE对称密码算法加解密的根密钥,用户可根据实际需要选择使用(通过OTP选择)。
SoC重要特性/功能开关控制区域(含单bit控制区域和多bit控制区域):SoC大多数重要的特性,都可以通过OTP来控制,以提高产品应用的灵活性。比如:安全启动使能,安全启动镜像是否加密,安全启动是否启动冗余备份,是否使能TEE,JTAG工作模式选择等等。特性/功能开关控制区域,在烧写好目标值之后,都可以选择将其锁定,避免后续非法篡改。
强烈建议客户在最终产品发布前,将所有的特性/功能开关位对应的值设置好,并且强制锁定!即使默认值满足要求,也要求锁定。
用户自定义区域:芯片集成了约25Kbit的用户自定义OTP区域,用以存放用户数据。
用户自定义区域还包含了一个128bit的版本控制区域:版本控制区域用于存放重要版本标识,防止版本回滚攻击。即防止攻击者利用有安全漏洞的老的合法镜像重新升级,实现重放攻击。版本控制区域不能锁定,每一个控制位都只能由0写到1,一旦写入1后,便不可再更改(one way 模式)。
在SSxxxx SDK包中,提供了OTP相关的读写接口。详细请参考本文“SSxxxx OTP字段定义 ”以及文档《OTP API 参考》。
须知:
所有的OTP控制位,无论默认值是否满足实际应用,请全部重新烧写锁定,保证设备安全。
SSxxxx OTP字段定义¶
OTP位域属性说明¶
LOCK属性说明¶
Oneway属性:具有此属性的位域未烧写为1的bit都可以在下一次继续烧写,直到所有bit都烧为1;lock使能位不会锁定此属性的位域;
lockable属性:lockable属性的相关位域在锁定前与oneway属性一致,烧写对应的lock位后,即使没烧写过的bit也不能再次烧写;建议lockable属性的位域,烧写值后对对应的位域进行锁定,防止被修改。
wrlock属性:只要执行过写操作,相应的位域即锁定,不能再做更改。
Load shadow属性说明¶
芯片上电硬复位后OTP的值会自动加载到对应的寄存器(shadow寄存器);每次烧写OTP后,必须重新上下电才能从shadow寄存器读到刷新后的值;
OTP位域无对应的shadow寄存器。
密钥区域¶
密钥区域可以通过下面OTP API接口访问:
td_s32 ot_mpi_otp_burn_product_pv(const ot_otp_burn_pv_item *pv, td_u32 num); td_s32 ot_mpi_otp_read_product_pv(ot_otp_burn_pv_item *pv, td_u32 num);
详细请参考《OTP API参考》
密钥区域的内容不可读取,因此ot_mpi_otp_read_product_pv接口只是返回对应区域的锁定状态(已经锁定的区域,不可再写),无法获取该区域的内容。
单比特控制区域¶
单比特控制的区域可以通过下面OTP API接口访问:
td_s32 ot_mpi_otp_burn_product_pv(const ot_otp_burn_pv_item *pv, td_u32 num); td_s32 ot_mpi_otp_read_product_pv(ot_otp_burn_pv_item *pv, td_u32 num);
详细请参考《OTP API参考》
单比特控制的区域,OTP对应的值,会在其对应的shadow寄存器中体现出来。通过ot_mpi_otp_read_product_pv接口只能返回该控制位的锁定状态(已经锁定的位置,不可再写),不能直接获得该控制位的值。
多比特控制区域¶
多比特控制区域可通过如下OTP API访问:
td_s32 ot_mpi_otp_burn_product_pv(const ot_otp_burn_pv_item *pv, td_u32 num); td_s32 ot_mpi_otp_read_product_pv(ot_otp_burn_pv_item *pv, td_u32 num)
多比特控制区域可读可写。其中oneway属性的区域,不可锁定,通过API获得的锁定状态无意义。
用户自定义区域¶
|
用户自定义区域可通过如下OTP API访问:
td_s32 ot_mpi_otp_set_user_data(const td_char *field_name, td_u32 offset, const td_u8 *value, td_u32 value_len); td_s32 ot_mpi_otp_get_user_data(const td_char *field_name, td_u32 offset, td_u8 *value, td_u32 value_len); td_s32 ot_mpi_otp_set_user_data_lock(const td_char *field_name, td_u32 offset, td_u32 value_len); td_s32 ot_mpi_otp_get_user_data_lock(const td_char *field_name, td_u32 offset, td_u32 value_len, ot_otp_lock_status *lock);
用户自定义区域可写可读,其中oneway属性的区域,不可锁定,通过API获得的锁定状态无意义。
须知: 配置JTAG安全模式时,请注意以下事项:
jtag_prt_mode字段为oneway属性(为0的bit可以烧写为1,直到所有bit都为1),其他字段位只要写过一次即锁定;
jtag_prt_mode可以向更高密级配置:JTAG OPEN →JTAG PASSWORD → JTAG CLOSE。
shadow寄存器¶
shadow寄存器概览如表1所示。
表 1 shadow寄存器概览(基址是0x1012_0000)
OTP_USER_ONEWAY0¶
OTP_USER_ONEWAY0为OTP用户接口寄存器20。
Offset Address: 0x2050 Total Reset Value: 0x0000_0000
OTP_USER_ONEWAY1¶
OTP_USER_ONEWAY1为OTP用户接口寄存器21。
Offset Address: 0x2054 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE0¶
OTP_USER_LOCKABLE0为OTP用户接口寄存器22。
Offset Address: 0x2058 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE1¶
OTP_USER_LOCKABLE1为OTP用户接口寄存器23。
Offset Address: 0x205C Total Reset Value: 0x0000_0000
|
bit[8]: deob_key_sel 根密钥加扰静态值选择,固定写0; |
OTP_USER_LOCKABLE2¶
OTP_USER_LOCKABLE2为OTP用户接口寄存器24。
Offset Address: 0x2060 Total Reset Value: 0x0000_0000
|
bit[8]: deob_key_sel 根密钥加扰静态值选择,固定写0; |
OTP_USER_LOCKABLE3¶
OTP_USER_LOCKABLE3为OTP用户接口寄存器25。
Offset Address: 0x2064 Total Reset Value: 0x0000_0000
|
bit[8]: deob_key_sel 根密钥加扰静态值选择,固定写0; |
OTP_USER_LOCKABLE4¶
OTP_USER_LOCKABLE4为OTP用户接口寄存器26。
Offset Address: 0x2068 Total Reset Value: 0x0000_0000
|
bit[8]: deob_key_sel 根密钥加扰静态值选择,固定写0; |
OTP_USER_LOCKABLE5¶
OTP_USER_LOCKABLE5为OTP用户接口寄存器27。
Offset Address: 0x206C Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE6¶
OTP_USER_LOCKABLE6为OTP用户接口寄存器28。
Offset Address: 0x2070 Total Reset Value: 0x0000_0056
OTP_USER_LOCKABLE8¶
OTP_USER_LOCKABLE8为OTP用户接口寄存器30。
Offset Address: 0x2078 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE9¶
OTP_USER_LOCKABLE9为OTP用户接口寄存器31。
Offset Address: 0x207C Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE10¶
OTP_USER_LOCKABLE10为OTP用户接口寄存器32。
Offset Address: 0x2080 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE11¶
OTP_USER_LOCKABLE11为OTP用户接口寄存器33。
Offset Address: 0x2084 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE13¶
OTP_USER_LOCKABLE13为OTP用户接口寄存器35。
Offset Address: 0x208c Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE14¶
OTP_USER_LOCKABLE14为OTP用户接口寄存器36。
Offset Address: 0x2090 Total Reset Value: 0x0000_0000
OTP_USER_LOCKABLE15¶
OTP_USER_LOCKABLE15为OTP用户接口寄存器37。
Offset Address: 0x2094 Total Reset Value: 0x0000_0000
客户细分市场标识(ID):便于客户对不同细分市场的差异化控制。ID内容由客户自己管理,需保证客户镜像中MSID的值和OTP烧制的值一致。 |
OTP_USER_LOCKABLE16¶
OTP_USER_LOCKABLE16为OTP用户接口寄存器38。
Offset Address: 0x2098 Total Reset Value: 0x0000_0000
第三方细分市场标识(ID):便于其对不同细分市场的差异化控制。ID内容由第三方管理,需保证镜像中对应MSID的值和OTP烧写的值一致。 |
OTP_USER_LOCKABLE17¶
OTP_USER_LOCKABLE17为OTP用户接口寄存器39。
Offset Address: 0x209c Total Reset Value: 0x0000_0000
TEE侧镜像细分市场标识(ID):便于其对不同细分市场的差异化控制。ID内容由TEE owner自己管理,需保证镜像中对应MSID的值和OTP烧写的值一致。 |
硬件真随机数¶
TRNG¶
TRNG模块能够生成真随机数。产生的真随机数符合FIPS140-1的随机测试标准。
TRNG具体应用方法,请参考文档《CIPHER API 参考》
密钥管理¶
密钥管理分为三级,分别为RKP、一级KLAD、二级KLAD,增强了密钥安全强度。密钥经三级密钥管理后,生成明文的工作密钥,并送给加解密引擎(SPACC),实现对最终的数据加解密运算。明文的工作密钥不会出现在内存中,确保不会被泄露。
RKP¶
RKP模块从OTP中获取对称根密钥,根据OTP配置判断是否解混淆对称根密钥,根据用户输入的派生材料派生ROOT KEY,并将ROOT KEY传递给一级KLAD。ROOT KEY存储在硬件中,不会泄露。RKP的具体规格:
支持AES 128 ECB算法。
支持从OTP中获取对称根密钥。
支持对称根密钥解混淆。
支持派生232个密钥。
一级KLAD¶
一级KLAD从RKP模块中获取ROOT KEY,并将受保护的一级密钥解密,传递给二级KLAD。解密后的一级密钥存储在硬件中,不会泄露。一级KLAD的具体规格:
支持AES 128 ECB算法。
支持受保护的一级密钥长度为128bits。
二级KLAD¶
二级KLAD从一级KLAD获取解密后的密钥,并将受保护的二级密钥解密(明文的工作密钥),传递给加解密引擎(SPACC)。明文的工作密钥存储在硬件中,不会泄露。二级KLAD的具体规格:
支持AES 128 ECB算法。
支持受保护的二级密钥长度为128/256bits。
为详细了解密钥管理中RKP、一级KLAD、二级KLAD与OTP、SPACC之间的关系,请参考图1。
SPACC具体应用方法,请参考文档《CIPHER API 参考》
硬件非对称密码算法¶
RSA¶
RSA是一种非对称密码算法,通过模幂计算实现加解密,常用于对数据进行数字签名和签名验证。SSXXXX RSA模块支持RSA2048/3072/4096,算法实现符合PKCS#1 V1.5/2.1标准。具体规格:
支持2048bit、3072bit和4096bit的密钥位宽。
2048密钥位宽公钥加解密性能最低为10 bps。
支持RSA内部密钥RAM、报文RAM和结果RAM清零。
RSA具体应用方法,请参考文档《CIPHER API 参考》。
Hash算法和对称密码算法AES¶
SPACC¶
SSxxxx SPACC模块实现了对称密码算法AES和HASH算法。
AES算法的实现符合FIPS 197 标准;AES 的工作模式符合NIST special800-38a 标准。
SHA算法实现符合FIPS180-2标准,HMAC_SHA算法实现符合RFC2104标准。
具体规格:
支持AES ECB/CBC/OFB/CFB/CTR/CCM/GCM。
支持AES128、AES192和AES256。
支持SHA256、HMAC-SHA256、SHA384、HMAC-SHA384、SHA512、HMAC-SHA512。
支持15个DMA通道。
支持CPU配置输入数据和DMA方式读取输入数据。
多块加密通道支持字节地址。
AES算法支持基于硬件根密钥派生工作密钥进行加解密(如图1)
安全启动¶
SSxxxx 支持基于芯片硬件可信根的安全启动。芯片OTP中可存储一个RSA2048(或者RSA4096)public key的hash256值,作为安全启动签名校验的起点。安全启动的信任传递为:
硬件可信根(OTP hash值)验证Flash中的RSA public key,这部分由BootRom完成;
RSA public key 验证U-boot;
U-boot再验证启动后续的镜像(uImage、rootfs,和其它分区)。
强烈建议在产品开发中使用安全启动。安全启动需要通过OTP中的secure_boot_en 控制位来使能。在使能安全启动之前,版本提供的未加密的安全启动镜像(特指安全U-boot),可以正常启动。
SSxxxx 安全启动方案支持镜像加密功能。安全启动的根密钥来自于OTP中的AES key0(软件不可读),由根密钥派生出实际的镜像解密密钥。
OTP中的可信根,以及数据加解密根密钥AES key0 完全由客户自行管理并烧录。
安全启动更详细的信息,请参考文档《SSxxxVxxx 安全启动使用指南》。
支持安全、非安全内存地址隔离¶
TZASC¶
SSxxxx 提供TZASC模块,支持对内存地址空间进行隔离控制,使CPU和其他SoC组件在处于安全模式和非安全模式等不同特权模式下,对内存的访问权限进行硬件级别的控制。这是实现基于ARM TrustZone 下的TEE、REE隔离的基础。
TZASC全称是TrustZone Address Space Controller,它是Advanced Microcontroller Bus Architecture(AMBA)兼容的SoC外围组件,可对接AMBA AXI和AMBA APB接口。
SSxxxx的 TZASC模块提供了16个可配置的区域(region0~region15)。其中region0固定使能,无法配置访问属性,大小覆盖除了region1~region15区域以外的所有内存区域。任何组件(无论是安全还是非安全)都无法访问region0覆盖的内存。
其余内存区域的访问属性,可以根据需要,选择下面四个属性单元的组合:
安全可读属性
安全可写属性
非安全可读属性
非安全可写属性
TZASC模块的bypass属性控制着模块是否使能:
默认bypass属性使能,TZASC模块处于失能状态,内存访问不受限制;
设置bypass属性失能,TZASC模块将会使能,各内存区域的访问属性生效。
TZASC控制的参考代码,请参考发布包GSL源代码根目录下drivers/tzasc/tzasc.c,该代码在boot/checkup.c中调用。
须知:
bypass属性失能后,在系统复位前无法再次使能。
TZASC的配置,建议客户在系统启动之后,只做一次配置,不要多次动态调整,以避免处理不当导致其他异常。
安全Debug¶
JTAG¶
SSxxxx 的JTAG调试接口可以通过OTP进行打开模式、密码模式、永久关闭模式的切换,默认为打开模式。OTP烧写的具体操作方法,请参照本文“SSxxxx OTP字段定义”和文档《OTP API 参考》。
通过JTAG调试接口对SoC进行调试,需要配套的调试板和PC对应的软件工具。
JTAG的安全由OTP中如下四个控制属性控制:
jtag_ca_en:
不使能,则JTAG永远打开,JTAG调试无需任何权鉴;
使能,JTAG安全由jtag_prt_mode控制。
jtag_prt_mode:在jtag_ca_en为1(使能)的情况下有效。jtag_prt_mode由2bit控制不同工作模式。
直通模式,即无需任何权鉴即可联通;
密码模式,需要输入用户名和密码(参见jtag_pw_id和jtag_pw字段);
其它模式,jtag关闭,即不可用。
详细配置,请参考本文“SSxxxx OTP字段定义”。
jtag_pw_id:JTAG的用户名。如有需要,需在设备出厂前烧录;可以通过PC端调试工具读取。
jtag_pw:JTAG用户密码。如有需要,需在设备出厂前烧录。该字段不可读取。
密码模式下,如果调试者输入的用户名、密码和OTP中的jtag_pw_id、jtag_pw一致,则可以打开JTAG,否则不能接通JTAG。芯片重启后需要重新输入密码。
JTAG的权限由DBC模块控制,密钥模式下要打开JTAG,需要配置DBC寄存器。
通过SOC JTAG读写DBC寄存器的方法:
读 chipid
chipid为64bit,储存在2个寄存器中,需要读2次完全获取。
配置chipid[31:0]的寄存器地址0x13000到JTAG_ADDR;配置0x01到JTAG_ENABLE开始读操作:
读JTAG_STATUS直到req_cnt以及ack_cnt计数都已经加1。
读JTAG_RDATA获得chipid[31:0]。
配置0x0到JTAG_ENABLE清除读使能。
chipid[63:32]同样的操作,仅需修改ADDR为0x13004.
输入密钥
jtag密钥128bit,需要写4次寄存器输入。
配置COM_PSWD_0的寄存器地址0x13010到JTAG_ADDR;配置密钥的低32bit数据到JTAG_WDATA,配置0x1到JTAG_WRITE和JTAG_ENABLE开始写操作:
读JTAG_STATUS 直到req_cnt以及ack_cnt计数都已经加1。
配置0x0到JTAG_WRITE和JTAG_ENABLE清除写使能。
其余96bit同样的操作输入,对应密钥寄存器地址为0x130014~0x13001c.
表 1 SOC_JTAG接口命令
说明:
SOC JTAG支持一次配置1个命令,也支持一次配置2个命令。soc_jtag_op有128bit,当前为了提升指令效率,reserved的高20bit未使用,其他108bit根据数据和使能拆分为2个指令;
当SOC JTAG一次配置1个命令时,支持通过JTAG_ENABLE_0或者JTAG_ENABLE_1发起;
当SOC JTAG一次配置2个命令时,逻辑优先执行JTAG_ENABLE_0,再执行JTAG_ENABLE_1命令;
JTAG_REQ_CNT是SOC JTAG命令请求次数统计,JTAG_ACK_CNT是逻辑命令完成次数统计;
无论是否启用安全JTAG功能,建议客户根据实际情况烧写锁定JTAG状态。





