🌈个人主页: aileen_0v0
🔥热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|mysql|
💫个人格言:“没有罗马,那就自己创造罗马~”
本文转自 周贺贺,baron,代码改变世界ctw,arm精选, armv8/armv9,trustzone/tee,secureboot,资深安全架构专家,11年手机安全/soc底层安全开发经验。擅长trustzone/tee安全产品的设计和开发。文章有感而发。

1、背景:
随着时代的发展、科技的进步,安全需求的趋势也越来越明显,arm也一直在调整和更新其新架构,很多都是和安全相关的。 如下列出了一些和安全相关的架构
trustzone做为arm安全架构的一部分,从 2008 年 12月 arm 公司第一次 release trustzone 技术白皮书。() 2013 年 apple 推出了第一款搭载指纹解锁的 iphone:iphone 5s,用以保证指纹信息安全的 secure enclave 技术据分析深度定制了 arm trustzone 架构,印象中这大概是 trustzone 技术第一次走进大众视线。到如今 trustzone 技术已经成为移动安全领域的重要基础技术,你也许不了解它的技术原理,但它一直默默为你守护你的指纹信息,账户密码等各种敏感数据。 如下也列出了一张在trustzone架构下的一张指纹的框图,这也是这些年(2015-至今)比较流行的一张软件框图。 |
1.1、arm trustzone的安全扩展简介
从上文我们已经知道, arm trustzone不具体指一个硬件,也不是一个软件,而是一个技术架构,在支持arm trustzone的soc中,需按照arm trustzone技术对各个子模块进行设计。如下便展示了一个soc的trustzone架构下的设计框图 |
其中:
- (1)、amba-axi总线的扩展, 增加了标志secure读和写地址线:awprot[1]和arprot[1]
- (2)、processor的扩展(或者说master的扩展),在arm core内部增加了scr.ns比特位,这样arm core发起的操作就可以被标记“是以secure身份发起的访问,还是以non-secure身份发起的访问”
- (3)、tzpc扩展,在axi-to-apb端增加了tzpc,用于配置apb controller的权限(或者叫secure controller),例如将efuse(otp fuse)配置成安全属性后,那么processor以non-secure发起的访问将会被拒绝,非法的访问将会返回给axi总线一个错误。
- (4)、tzasc扩展,在ddrc(dmc)之上增加一个memory filter,现在一般都是使用tzc400,或由soc厂商自己设计一个这样的ip,或叫mpu,或集成在dmc内部,它的作用一般就是配置ddr的权限。 如果配置了ddr中某块region为安全属性,那么processor以non-secure发起的访问将会被拒绝。
- (5)、mmu/cache对安全扩展的支持 在软件架构的设计中,就分为: non-secure el0&1 transslation regime 和 secure el0&1 transslation regime,即normal world和secure world侧使用不同的transslation regime,其实就是使用不同的ttbrx_eln寄存器,使用不同得页表。 注意:在armv7上,ttbrx_el0、ttbrx_el1是banked by security state,也就是说在安全世界和非安全世界各有一组这样的寄存器,所以在linux和tee中可以各自维护一张自己的内存页表. 在armv8/armv9上,ttbrx_el0、ttbrx_el1不再是banked了,但是world switch时会在atf中switch cpu context, 所以从hypervisror或os的视角来看,依然还是两套不同的ttbrx_eln寄存器,linux和tee各有各的页表。 而在tlb中,又为每一个entry增加了non-secure属性位,即标记当前翻译出的物理地址是secure还是non-secure; cache的扩展:在cache的entry中的tag中,有一个non-secure identifier标记为,表示当前缓存数据的物理地址是属于non-secure还是secure。
- (6)、gic对安全扩展的支持,在gicv2、gicv3的版本中,都增加了对安全扩展的支持. 以gicv3为例,将中断划分成了group0、secure group1和non-secure group1. 在软件的配置下,group0和secure group1的中断将不会target到ree(linux)中处理
1.2、arm trustzone的安全扩展详细解剖
1.3、 amba-axi对trustzone的支持
arprot[2:0]和awprot[2:0] 分别是读通道和写通道中的关于权限的信号,例如他们中的bit[1]则分别表示正是进行secure身份的读或secure身份的写操作。
1.4processor的scr.ns比特位
scr_el3.ns
表示当前processor的安全状态,ns=1表示是non-secure的,ns=0表示是secure的
2.tzc400和tzpc简介
tzc400接在core和(dmc)ddr之间,相当于一个memory filter。 tzc400一般可以配置8个region(算上特殊region0, 也可以说9个),然后可以对每一个region配置权限。例如讲一块region配置成secure rw的,那么当有non-secure的master来访问这块内存时,将会被tzc挡住。
2.1 mmu对trustzone的支持
首页,在软件架构的设计中,就分为: non-secure el0&1 transslation regime 和 secure el0&1 transslation regime,即normal world和secure world侧使用不同的transslation regime;
其实就是使用不同的ttbrx_eln寄存器,使用不同得页表 其次,在mmu使用的页表中,也有ns比特位。
non-secure transslation regime 只能翻译ns=1的页表项,secure transslation regime 可以翻译ns=1和ns=0的页表项。
即secure的页表可以映射non-secure或secure的内存,而non-secure的页表只能去映射non-secure的内存,否则在转换时会发生错误 在page descriptor中(页表entry中),有ns比特位(bit[5]),表示当前的映射的内存属于安全内存还是非安全内存:
2.2 cache对trustzone的支持
如下所示,以为cortex-a78为例,l1 data cache tag中 ,有一个ns比特位(bit[33]),表示当前缓存的cacheline是secure的还是non-secure的
2.3 tlb对trustzone的支持
如下所示,以为cortex-a78为例,l1 data tlb entry中 ,有一个ns比特位(bit[35]),表示当前缓存的entry是secure的还是non-secure的
2.4 gicv的安全中断
在gicv2/gicv3中,支持了安全中断,配置有如下: (1)、group分组(gicd_igrouprn) – gicv2 ◾group0:安全中断,由nfiq驱动 ◾group1:非安全中断,由nirq驱动
(2)、group分组(gicd_igrouprn)– gicv3 ◾group0:安全中断 ◾non-secure group1:非安全中断 ◾secure group1:安全中断
3.arm trustzone技术对软件带来的变化
arm trustzone技术对软件框架带来了变化
3.1、el3 is aarch64:
3.2、el3 is aarch32:
aarch32和aarch64 secure monitor的理解:
- 如果secureos和monitor都是64位,secureos跑在el1, monitor跑在el3;- 如果secureos和monitor都是32位,secureos和monitor都跑在el3(secureos在svc模式、monitor在svc模式),它俩共用页表;- 如果monitor是64位,secureos是32位,那么secureos跑在svc模式(el1),monitor跑在el3,他俩不共用页表
3.3、armv7:
思考:通过mmu/tlb/cache对安全内存攻击的可能性
在安全架构的设计时,我们在core和ddr之间增加了一个tzc做为memory filter,数据流为:core ---> tzc---->ddr
, 这种架构下,core以非安全身份发起的对安全内存的读写,将会被tzc挡住。
但是这都是在理想的情况下,事实上core发起对内存的读写,未必经过tzc未必到ddr,有可能到cache阶段就完成了,即数据流变成了core ---> mmu(tlb+addtress translation)---->cache
,那么这种情况下,没有tzc的事了,你也许会说mmu/cache中都有ns比特,但是你真的理解这里ns比特的用法吗? 如果core以非安全身份对安全内存发起的读写时,我强制将mmu页表中的安全属性标记位强制改成ns=0
,会如何呢?

事实上我们只要理清原理、理清数据流 ,就不会问上面那么s13的问题了。 下面来开始剖析:
假设一个安全core 读取了一个安全物理内存0x2000_0000数据(虚拟地址可能是0x_xxxx_xxxx),那么将产生一下行为:
- 在读写之前,势必做好了mmu map,如物理地址0x2000_0000 map成了0x_xxxx_xxxx地址, 此时page descriptor中的atrribute中的
ns=0
- tlb缓存该翻译,即tlb的entry中包含:0x2000_0000
、0x_xxxx_xxxx
、ns=0
- 安全内存0x2000_0000数据将会被缓存到cache中,entry中的tag包含0x2000_0000
、ns=0
同时,我有一个非安全core 发起读写虚拟地址0x_yyyy_yyyy,我自行修改该页表,让0x_yyyy_yyyy强制映射到安全物理内存0x2000_0000,此时有两种配置: (1)、0x_yyyy_yyyy
—0x2000_0000
,ns=0
(2)、0x_yyyy_yyyy
—0x2000_0000
,ns=1
我们分别看下这两种配置,是否能读到安全内存: 针对(1),非安全的core发起访问,发现tlb中的条目是0x_yyyy_yyyy
—0x2000_0000
,ns=0
,自然不会被命中,然后使用address translation转换,mmu发现非安全的core要来访问安全属性ns=0
将会被直接拒绝掉。 针对(2),非安全的core发起访问,由于ns=1
,tlb可能会被命中,即能翻译出0x2000_0000
物理地址来,即使没有被命中,在经过address translation转换,由于ns=1
,此时也是可以正确转换出正确的0x2000_0000
物理地址。 然后接着会去cache中查询这个地址,但是此时cache的entry中的ns=0
,所以cache不会被命中,接下来就要走tzc流程了,很显然,你一个非安全的core想访问安全的内存,tzc将会挡住你。
综上所述:安全就是安全,不要再想漏洞了。 |
推荐
- armv8/armv9架构从入门到精通 --博客专栏
- 《armv8/armv9架构从入门到精通 第二期》 --大课程
- 8天入门arm架构 --入门课程
发表评论