STM32L5是一颗主打低功耗和安全应用的MCU,它的安全特性,从各个方面都比以往的STM32系列有了进一步提高。
- 它支持安全启动,这是信任链的可靠锚点:bootlock可以保证启动的唯一入口,HDP可以将用户闪存的一部分隐藏起来,通常是复位后运行的安全启动代码,使得其对后面的用户应用程序不可见。
- 为了支持CM33内核里的trustzone安全扩展,L5上的外设模块、存储模块都做了升级来配合trustzone机制
- 为了实现对软件和数据的保护,L5新增了配合trustzone的安全调试功能,可以限制用户仅能调试非安全世界代码,而无法调试安全世界的代码。另外,L5还有一个OTFDEC模块,可以对存储在芯片外Ocot-SPI flash上的密文数据或者密文代码,on the fly地解密执行和解密读取,从而解放了片上闪存空间对用户代码的限制,同时还能保证用户代码的机密性。
- 对密码学操作的硬件加速,L5继WB系列后,也新增了PKA模块,对公钥加解密操作的硬件支持
- 在防纂改检测方面,L5在以往历代STM32上,首度把静态保护升级到动态保护,符合更高要求的安全应用需求。
- STM32L5还是首个全部产品线都支持SFI的STM32系列,天生就是为安全应用而打造。基于L5的TZ硬件基础,ARM的TFM已经得到L5的支持,并经过了PSA level2认证。
可以看到,对TrustZone的支持,只是L5安全特性的一部分。本期内容我们先把片上系统如何配合trustzone讲清楚,后面还会围绕着L5的其他安全特性,全部一一展开讨论。
安全属性配置
当CPU的取指或者数据访问,经过SAU和IDAU审查,以及MPU的审查通过后,携带着HNONSEC信号来到AHB总线上,这个transac
tion的属性可能是安全的,或者是非安全的。右图中,蓝色的部分是AHB矩阵,是AHB 5总线矩阵,是可以传递transaction的安全属性信号的。那么作为总线连接的另外一端,AHB从设备是如何识别和应答transaction的安全属性呢?
STM32L5上的外设有两种,一种是TZ aware外设。表格里列出了STM32L5上所有的TZ aware外设。顾名思义,这些外设本身,是认识trustzone信号的。用户可以配置这些模块自己的寄存器,来让它知道自己哪些部门是可以被非安全状态的CPU访问,哪些是只能被安全状态的CPU访问。
另外一种外设,本身的寄存器没有和TZ,security相关的寄存器可以设置,它们全靠自己的话,是完全不知道啥安全访问,非安全访问的,但是在它们的前面,首先面对AHB5总线传来的带安全属性的transaction的,有一个叫做PPC的硬件,全名Peripheral protection controller,它是属于TZSC模块的一部分。TZSC,全称trust zone security controller。是STM2L5为了配合CM33内核的TZ安全扩展,新加的一个帮助片上众多非TZ aware的外设,识别secure访问和非secure访问的硬件模块。
如果拿右边的芯片“系统架构” 简图和以前的STM32比较,会发现,除了最上面的flash memory,从SRAM1开始,到AHB1、AHB2外设、到外部存储区,它们和AHB5总线矩阵的AHB slave端口,不是直接连接。原因很简单,就是刚才说的,这些外设 不能识别 HNONSEC信号,因此前面有一个额外的东西,参考手册上叫它‘’secure gate‘’,来做识别,阻拦或者放行寻址到后面SRAM1、SRAM2、AHB上外设的transaction。而最上面的Flash,为什么可以直接连到AHB slave端口呢?因为左边的表格告诉我们,flash memory是TZ aware的外设呀。
右边的芯片“系统架构” 简图和以前的STM32比较,还有一个地方不同:左上角,内核出来两条bus:C-bus和S-bus,都是可以取指取数据;仅仅是target的目标区域不同。
C就是target到code region的,S是target到除了code的其它region的。
ST在芯片实现时,在C-bus上接了一个Icache,再分出来了Fast-bus和Slow-bus,接到AHB总线矩阵上。扩展了target的区域,不仅是Code region,而是所有内部、外部存储区都可以访问。
GTZC,global trustzone controller,全局TZ控制器。它是STM32L5把内核TZ安全概念扩展到整个片上系统的关键,我们一定要弄清楚它的工作原理。我觉得看图说话比较好,框图里能包含很多信息,我截了参考手册里GTZC这个外设章节里的系统框图来说明它的结构和功能。
从图中可以看到,GTZC有三个子模块组成。第一个M
PCBB,我用绿色标注。MPC就是memory protection unit的简称。BB是block base的。因此MPCBB保护的对象,是我们STM32L5片上系统里的internal SRAM区域。为什么是BBx,因为我们有SRAM1和SRAM2,因此有两组寄存器来控制。SRMA上的安全区域,以256字节为单位来划分block。
再来看第二个子模块,TZSC,我用紫红色标注。TZSC出去的有4条线,一条深绿色的,三条紫红色的。我们先来看深绿色线条的走向,它连到了MPCWMx,又见到了熟悉的MPC字样,知道它也是保护的存储区域,是外部存储区,即FSMC和Octo-SPI所连的外部flash区域。但是这里是WM结尾,不是BB结尾。WM是watermark的意思,这是一种粗粒度的设置。不能像BB那样,每个block单独设置安全还是不安全。WM只能在原本安全的底色上,划出两道线,来指定非安全区域的范围。
TZSC出去的其他几条紫红色线条,分别连到了AHB/APB bridge、AHB master和AHB slave,去控制直接连接在AHB总线上的主设备、从设备;以及间接连接在AHB总线上的APB从设备。
因此一眼可以看出,TZSC这个子模块,从secure gate这个功能角度,控制的设备最多。各种外设,以及外部存储器。
紫色的TZIC,是第三个子模块,全称是TZ illegal access concentrator。它监控并搜集所有系统上安全角度的非法访问,以触发GTZC这条用户中断。
这张图从另外一个角度展示了GTZC的三个子模块及其对应的功能。同时也能体现STM32L5里TZ aware的IP的位置。
TZ Aware的外设,【】比如flash memory, GPIO , RTC,它们无需GTZC站在前面,帮它们审查过来的transaction的安全属性,但是对它们的安全方面非法操作,也会产生IA事件,即illegal access event。
非TZ aware,又可以被配置成secure的外设,即这里被TZSC子模块里的PPC保护的Securable IP,【】比如UART
flash已经是TZ aware的外设了,剩下的存储器件,还有internal Flash,【】受MPCBB模块保护,提供精细粒度的Block base方式配置。片外flash则是受MPCWM保护,提供粗粒度的WM方式配置。
我们后两节课,讲解具体实例demo和hands-on环节的时候,会用到UART、SRAM、Flash、GPIO。因此,接下来,我们对这四个外设的TZ相关安全特性,做一个简要介绍。
片上Flash memory是TZ aware的外设,因此它有相关的寄存器来配置自己的访问安全属性。除此之外,它甚至还有选项字节的配置,可以使得预定义的安全属性在上电即生效。Flash通过选项字节,提供water mark方式的配置,可以标出哪一段区域是安全的。还可以同时标出哪一段区域是用户程序不可见的隐藏区域。对于一个virgin的STM32L5芯片,使能了TZ安全扩展后,SECWM这个选项字节的默认状态是全片都是安全的,如图所示。
用户配置SECWM,指定出安全和不安全的区域,以及HDP用户不可见区。这个配置apply到系统后,下次上电就生效。上电后,用户还可以通过寄存器SECBB来以page为粒度,精细地对安全区域和非安全区域再做调整,如图所示。然后按照两种设置叠加,取安全等级高的原则,最后得到用户flash的安全配置,如最右边的图示。
Flash的各个page被最终配置好安全属性后,在安全扇区的操作,和非安全扇区的操作,就依据两套不同的控制寄存器和状态位来完成了。非安全区域上的flash操作,产生的中断连到Flash这条NVIC线上;安全区域上的flash操作,对应中断连到Flash_S这条NVIC中断线上。
这就是一个典型的TZ aware IP,无需GTZC的帮助,自己可以配置自己哪些部分是安全transaction可以访问,哪些部分只能非安全transaction访问。
SRAM自己没有配置自己哪些部分是安全区域,哪些部分是非安全区域的能力,因此它需要GTZC的帮助。具体依赖的就是GTZC中刚才介绍的第一个子模块,MPCBB。从左边这个“STM32L5系统架构简图”可以看到,MPCBB是站在SRAM和AHB总线矩阵之间的那个“门卫”。
片上flash,一直是按照flash page组织的,L5上是2K一个page,或者4K一个page,取决于当前flash是双bank还是单bank模式。
SRAM现在为了设置安全部分区域,也特意逻辑上划分出256字节为单位的一个个block。通过MPCBB寄存器组,可以对这些SRAM上的block做独立的安全属性配置。
寄存器复位值,每个位域都是1,表示对应的block是安全的。
SRAM就是一个典型的securable的外设,通过GTZC的MPCBB子模块来配置其区域的安全性。
另外应该可以提到的应该是SRAM的访问控制属性,S的区域可以被什么样的transaction访问,NS的区域可以被什么样的transaction访问,以及可以通过寄存器设置允许S transaction访问NS的SRAM区域
GPIO和Flash memory一样,是TZ aware的外设,因此它自己有寄存器来配置自己的TZ安全性。
复位后,所有GPIO的引脚都是安全的,可通过寄存器SECCFGR(secure configure register)对每个引脚的安全性单独配置。
当这些引脚不是单纯地做GPIO使用,而是通过Alternate Function多路选择器和某个外设复用时,GPIO引脚的安全性要和这个外设的安全性匹配。
比如,GPIO引脚PG.7和PG.8,担任UART模块的收、发功能时,PG.7、PG.8的安全性要和UART配置的一样,否则不能正常工作。
同样的,如果这些引脚和模拟外设,类似ADC、比较器模块相连,双方的安全配置也要保持一致。
所有GPIO引脚,复位后默认都是安全的;而所有除了GPIO的外设模块,复位后默认都是不安全的,如果我们忘了去做对应配置,基本上用到外部I/O引脚的外设模块都不会正常工作。这点请大家尤其注意一下。
GPIO和flash memory一样,有自己的寄存器来配置自己模块里哪些是安全的哪些是不安全的,因此也是属于TZ aware IP
UART和SRAM一样,不是TZ aware的IP,需要通过GTZC这个大管家帮自己设置TZ安全属性。而和SRAM不同之处在于,第一,SRAM是通过GTZC的第一个子模块MPCBB来配置的,UART是通过GTZC的第二个子模块TZSC来配置的;第二,SRAM内部可以有些区域是安全的,有些区域是非安全的,所谓“BB”, block based,而UART要么all in, 要么all out,它的安全属性是贯穿在整个UART模块上,不会是某些部分,比如发送逻辑安全的,接收逻辑处于非安全配置中。通过GTZC_TZSC_SecureConfigureRegister也可以看出来,每个uart,都是整体配置成安全或者非安全。
上一期,我们了解了从内核视角看出去的4G地址空间的安全性。这一期,地址空间上实现的具体物理设备的安全性配置情况我们也看到了。
现在,小结一下,系统复位后,各自的安全配置情况:
- 复位后,内核从SAU、IDAU看出来的视角,整个4G空间地址都是安全的;因此内核本身也处于安全状态。
- 内核之外呢,片上flash,选项字节初始设置,全部flash扇区都是安全的,即使flash的block base配置寄存器复位状态把所有flash空间配置成非安全,二者综合作用下,flash全部空间也是安全的。如果用户修改了选项字节配置,之后的每次系统复位后的状态,还是取决于选项字节的配置。
- 片上SRAM,由于都是受寄存器控制,复位状态,全部SRAM都是安全的。
- 片外存储区,即FSMC和Octo-SPI连接的外部flash,寄存器复位状态下,这些存储区也都是安全的。
- GPIO,全部引脚是安全的;
- 其他外设,无论是TZ aware的外设,还是Securable的外设,都是非安全的。
- 中断方面,所有的中断,都是target到安全状态,即发生对应中断时,硬件都是去VTOR_S这个向量表的对应entry取中断响应函数的执行地址。
资源访问规则
从CPU看出来的S/NS属性有了,实际的物理模块单元的S/NS属性也有了,现在来看整个链路上的访问规则。
CPU对片上资源,无论是memory还是外设的访问,需要通过两级检查:分别是从内核看出去的视角,是否允许发出这样的访问;再是具体资源自身的安全配置,是否可以接受这样的访问。
第一级检查,发生在内核内部,由SAU、IDAU从安全/非安全的角度去检查,此次访问是否允许放行。然后在安全MPU或者非安全MPU那里检查,此次访问是否符合目标地址所在区域的访问权限,更多是从可执行否,是否要求CPU的特权级别这些方面去考量。
第二级检查,发生在被寻址的具体物理模块上,可以是flash控制器,它和其他TZ aware的外设一样,知道自身的安全性;也可以是非TZ aware的外设,它们在GTZC的帮助下,判断此次address到自己的访问是否合法。
接下来,我们用三张图解来更加形象地阐明以上描述的访问规则。为了集中体现TrustZone相关的访问规则,后面的图里,暂时隐掉MPU的检查。
首先来看CPU的取指行为。标题上是“存储区上的”取指,好像有点多余,指令当然是放在存储区里。这是为了和下一页的“存储区上的”取数据相对应。
第一级检查,由SAU/IDAU执行:对于取指令的访问,SAU/IDAU都会放行,放行的transaction的安全属性,仅取决于目标指令地址所在的区域,从SAU/IDAU看来的安全性。
第二级检查,发生在STM32L5的片上flash,片上SRAM,片外flash上。如果目标地址实际的安全性,和transaction携带的安全属性匹配,取指访问可以进行下去,memory返回对应的值;如果不匹配,取指指令什么都读不到,执行不成功。
CPU对存储区上的数据访问,和取指有点不一样。在第一级检查的时候,就有被block的可能:当CPU当前处于非安全状态,要企图访问安全世界的数据,注意是“数据”,不是“指令”,该访问企图,SAU/IDAU不会放行。另外,从图示里的第一级检查来看,即使CPU当前处于安全状态,如果它企图访问的数据在非安全世界,SAU/IDAU会放行此次访问transaction,但是会标识上非安全transaction的属性。只有CPU本身就处于安全状态,要访问的数据也是处于SAU/IDAU看来的安全世界,出去的transaction才是安全的。CPU本身处于非安全状态,要访问的数据也在非安全世界,顺其自然地,出去的transaction就是非安全的。
经过了第一级检查并放行的transaction来到STM32L5的片上存储区,物理存储设备是否接受过来的访问transaction呢?只有存储区自身的安全属性和过来的transaction的安全属性一致,访问才能成功。但是在SRAM上有一个例外, MPCBB寄存器中的位域SRWILADIS置位时,允许破个例,即安全的读写transaction,可以访问SRAM的非安全区域。
CPU对外设的访问,也是属于数据读、写访问,因此在第一级检查时,和第二张图示一样,存在着transaction被block的可能。
不同的是,在第二级检查时,无论是由TZ aware的外设自己来检查,还是非TZ aware的外设通过GTZC模块来帮助检查,规则稍微和STM32L5的存储区检查不一样。只要transaction是安全的,它寻址的外设无论是处于安全还是非安全模式,都可以被访问。如果transaction是非安全的,那么还是只有非安全的外设才能响应此次访问。
本期小结
这一期,我们介绍了STM32L5如何配合内核的trustzone机制,配合携带“安全” 和“非安全” 标志的transaction,通过自身寄存器或者GTZC模块配置外设,存储器的安全性。
现在,大家应该理解STM32L5是如何把“隔离”的概念和措施,从内核延伸出来,部署到全片系统了