随着汽车上通信系统越来越复杂,云端、远程通信的场景越来越多,信息安全变得越来越重要,在通信领域常用的AES、SHA、RSA等加密算法被越来越多地应用到汽车电子系统中。通常这类加解密算法都需要大量的数学运算,需要消耗相当多的CPU时间,但同时汽车应用场景对ECU有比较高的实时性要求,为了节省主CPU的资源,专用于执行加解密算法的硬件HSM模块应运而生。
广义上的HSM(Hardware Security Module),是MCU上专门用于实现加解密算法的外设模块,它一般会有一个独立的CPU,专门用来进行加解密运算,还有一些针对特定算法的硬件加速器(如AES-128、SHA-256等)。有了HSM模块,程序中就可以把加解密运算交给HSM来执行,同时主CPU就可以去做其他工作,一段时间后来查询结果,或等待HSM计算完成后通过中断等方式通知主CPU计算结果即可。HSM通常还拥有单独的存储区,包括RAM和NVM(Flash存储器),HSM的存储区在正常运行状态下应只允许HSM读写,主CPU不能读写。这样就可以把算法秘钥等重要数据存储在HSM存储区,与主CPU进行隔离,进一步加强安全性。此外HSM模块还会集成(或者共存)真随机数生成器等加密算法常用外设。
常用的加密方法,比较耳熟能详的是摘要算法(哈希算法,HASH)、对称加密、非对称加密等。
假设有发送方向接收方发送消息。如果没有任何加密算法,接收方发送的是一条明文消息:我是小灰
。
如果中间人截获到消息,即使中间人无法篡改消息,也可以窥探到消息的内容,从而暴露了通信双方的私密。
因此,我们不再直接传送明文,而改用对称加密的方式传输密文,画风就变成了下面这样:
具体工作的步骤如下:
123456
,加密明文我是小灰
,加密结果为TNYRvx+SNjZwEK+ZXFEcDw==
。TNYRvx+SNjZwEK+ZXFEcDw==
传输给接收方。TNYRvx+SNjZwEK+ZXFEcDw==
,利用密钥123456
还原为明文我是小灰
。(使用相同密钥的对称加密方法)YTM32的HCU(Hardware Cryptography Unit)是HSM的一种典型实现,使用硬件计算引擎,可以实现对用户数据的加解密计算,其中包括AES
、SM4
、SHA
等算法,并配合真随机数发生器TRNG
和HCU_NVR
存储区,完成了对加解密系统的硬件支持。如图x所示。
从HCU外设的系统框图中可以看到,HCU的核心是一个复用成多种模式的计算引擎,用户可以通过FIFO向计算引擎送数参与计算,并在计算结束后,通过FIFO读出计算结果。HCU的用户操作接口(寄存器)并不复杂,主要的配置选项都在选择计算引擎的工作模式上(HCU_CR
寄存器),DMA和中断,以及标志位的设置,都是面向FIFO的常规功能。
需要特别关注的是,HCU外设模块从Flash(EFM模块)存储器中导入Key到HCU_KEY
寄存器的机制,以及众多面向具体加解密算法,需要通过专用的寄存器传入专用的参数,例如通过HCU_MSGINFO
寄存器和HCU_MSGADL
寄存器指定输入数据(“消息”,Message)的长度,通过HCU_ASECV
寄存器为计算ASE-CTR
算法时传入Counter参数,通过HCU_ASEIV
寄存器为计算ASE-CBC
算法时传入Initial Vector
参数,通过HCU_ASEMAC
寄存器为计算ASE-CMAC
算法时传入或传出MAC
值。
使用HCU计算引擎的流程大体相似:先准备密钥Key、配置引擎,到准备数据、执行计算,最后等待计算完成读取计算结果。这里以AES-ECB为例,具体说明使用HCU计算引擎的操作过程:
HCU_KEY
寄存器中写数。HCU_CR[ENGSEL]=1, HCU_CR[ALGSEL]=0
,指定即将以AES-ECB模式进行计算。HCU_CR[KEYLEN]
,例如,可指定长度为128。HCU_IFDAT
寄存器中写数。HCU_MSGADL[MSGLEN]
寄存器中写数。AES-CBC
计算,需要在这个阶段写入HCU_IV
寄存器。AES-CTR
计算,需要在这个阶段写入HCU_CTR
寄存器。HCU_CR[ENC]
寄存器。HCU_GO[GO]=1
。HCU_SR[OD]=1
。HCU_OFDAT
寄存器中读数。其他计算模式的过程大体相同,在软件应用上,可以直接调用SDK软件包中的API,或者阅读参考手册对照具体的操作。
一般应用中,AES / SHA计算引擎处理一个消息块的长度小于 32768 / 65536 字节,对应在HCU外设的寄存器字段HCU_CR[MSGLEN]
中配置。但当用户需要处理(加密或解密)长度大于 32768 / 65536 字节的消息块,就需要使用处理多块消息的机制:需要指定寄存器HCU_CR[MSGB]
和HCU_CR[MSGE]
,表示即将要进行处理的数据块是开始块(Begin Message)、中间块(Middle Message)或是结束块(End Message),并且需要配置HCU_CR[CS]=1
指定即将处理完成数据块后,需要为下次计算保留种子(在AES-CBC
和AES-CTR
两种计算模式下,除了Key之外,还需要配合IV
和CTR
值才能启动数据块的计算)。
大部分计算过程,都是对于一段不长的数据进行计算,经过一次计算就可以得到最终的结果。
但对于AES-CBC
和AES-CTR
这两种计算过程,可能会计算一组比较长的数据。在开始计算数据前,还需要预先设定IV
寄存器(Initial Vector)和CTR
寄存器参与计算。当设置HCU_CR[CS]=1
,处理完数据块后,产生的IV和CTR值将被载入到硬件的HCU_IV
寄存器和HCU_CTR
寄存器,供下一个数据块的处理过程使用,并以此类推。
通过HCU_MSGINFO
和HCU_MSGADL
分别指定完整数据块的长度和每次参与计算的数据子块的长度。设置HCU_CR[CS]=1
,启用保存计算上下文。设置[HCU_CR[MSGB]:HCU_CR[MSGE]]
的值为0b10
、0b00
、0b01
,指定即将处理最开始的子数据块、若干个中间子数据块和最后一个字数据块。
HCU_MSGINFO
寄存器,设定真个长消息的数据长度(如果是AES-CCM
,则不包含额外的数据长度)。HCU_CR[CS]=1
,启用保存计算上下文。HCU_CR[MSGB]=1, HCU_CR[MSGE]=0
,指定即将处理长消息的第一个子数据块。HCU_MSGADL[MSGLEN]
,指定即将处理的一个子数据块的长度。HCU_GO[GO]=1
,启动计算引擎。等待计算完成。HCU_SR[OD]=1
。HCU_CR[MSGB]=0, HCU_CR[MSGE]=0
,指定即将处理长消息的中间子数据块。HCU_CR[MSGB]=0, HCU_CR[MSGE]=1
,指定即将处理长消息的中间子数据块。注意:
根据手册中存储空间(Memory Map)和EFM模块(Embedded Flash Module)章节中的介绍,YTM32微控制器片内的Flash中,还划分了一块区域HCU_NVR
,专门用于存放同HCU相关的密钥数据。如图x所示。
HCU_NVR中可以存放32组 AES-256的Key。用户可通过配置EFM_CTRL[AES_KEY_SEL]
寄存器,指定AES-256的Key序号,然后在EFM_CMD寄存器中写入Load AES Key
命令,如图x所示,就可以将对应的Key从Flash中的HCU_NVR载入到HCU_KEY寄存器中,参与AES算法的计算。这就是使用硬件密钥的方法。
当然,在调试阶段,或者需要使用灵活密钥的情况下,用户软件也可以不使用预先存放在硬件Flash中的密钥,而直接向HCU_KEY
寄存器中写入Key值参与计算。
出于安全的考虑,用户软件(通过CPU)不能直接读取HCU_NVR
存储区和HCU_KEY
寄存器中的数据。用户可以通过写Flash的方式(带有KEY)向HCU_NVR
中写数,但除了最初写数的人,别人是无法再读出正确的数。
Input FIFO入口寄存器的位宽是32b,但手册上明确说明,要求每次向FIFO中写数必须为128b,这也就意味着对Input FIFO的操作,每次都要加倍再加倍,连续4次写入才算完成一次操作。
Input FIFO可以通过Watermark触发中断,但Watermark的值是以字(1 Word)为单位的,这也就意味着Watermark的实际设定值必须是4的倍数(4个Word对应128b)。
至于Input FIFO Watermark的中断,这里有一个逻辑。在Operation Done事件到来之前,Input FIFO Watermark的事件都是按需触发的,即只要当前FIFO中的数据量(Word数量)小于Watermark的设定值,就可以触发对应的中断。但若Operation Done事件到来,此时Input FIFO的检测逻辑就停了,哪怕Input FIFO中的数据已经耗尽,库存低于Watermark值,(刚消耗掉最后一组128b数据后),也不会再产生Input FIFO Watermark的中断。因此在YTMicro SDK的样例代码中,停用Input FIFO Watermark中断的操作并不是等着一个空的Input FIFO触发,而是同Operation Done事件放在一起停用的。
void HCU_IRQHandler(void)
{
/* Operate done handler */
if ((HCU_GetStatusFlag(OPERATION_DONE_FLAG)) && (HCU_GetIntMode(OPERATION_DONE_FLAG)))
{
/* clear flags. */
HCU_ClearStatusFlag(OPERATION_DONE_FLAG); /* Clear operate done flag */
/* disable interrupts. */
HCU_SetIntMode(OPERATION_DONE_FLAG, false);
HCU_SetIntMode(INPUT_FIFO_WATERMARK_FLAG, false); /* Disable input watermark interrupt */
...
}
YTMicro SDK中,提供了HCU外设模块的驱动程序,以及一个基本的样例工程hcu_ecb
。
从笔者的经验看来,目前设计这个样例工程更多是为验证HCU驱动代码,并简单演示HCU模块的应用流程。从用户角度看,如果需要更充分有效地利用好HCU外设,原厂的开发团队应该在后续会设计和发布专门的功能安全软件组件,将这些硬件细节隐藏在将来会逐渐统一的通用HSM软件接口之下(例如集成到AutoSAR软件体系中),因为HSM的开发者大多是算法专家,相对于某个具体的外设模块的实现,他们更多关注的是软件的应用场景,以及实际计算的速率。
所以,这里还是期待原厂的软件开发团队继续为开发者带来一些惊喜。
HCU模块在YTM的M系列中都有集成,但每个子系列中的HCU功能略有不同,如表x所示。
以 YTM32B1ME0 为例,在系统时钟为 120MHz PLL 下,测量各个算法处理 1KB 明文与 4KB 明文所需的时间。如下表所示。
本文简要介绍了密码学在汽车电子系统中的应用场景,详细介绍了YTM32信息安全子系统中的核心模块HCU外设模块,以及基本用法,在文末汇总了HCU在YTM32微控制器中的分布情况,以及执行速度的参考指标。
本文尚未深入探究HCU以及信息安全的应用,期待后续HSM技术的应用规范逐渐形成标准,开发团队可依据规范开发和发布专用信息安全软件包。