大白话漫谈「嵌入式安全」
ID:技术让梦想更伟大
作者: GorgonMeducer
在一个PPT满天飞的世界里,有些现象还是蛮有趣的。比如也许你的女朋友没有听说过什么叫做嵌入式系统,但她一定知道什么是物联网;就算她并不知道“互联网无隐私”,也一定知道“物联网最关键的是安全”——正所谓故事听得多了,爱因斯坦的司机都可以讲相对论了。那么问题来了:
作为专业人士的你,物联网的安全是什么,你能说的清楚么?
好了,好了,别装逼了,知道你啥都不懂,如果不服,请掠过这篇文章。下面,我们首先从几个常见的误区开始,慢慢为你展开:
误区一:安全和安全
英文里面有两个词语都可以对应中文的“安全”,分别是Security和Safety。首先,我要明确的强调一下:
Security 和 Safety 不是同义词,他们在很多领域有着完全不同的定义。
别说普通人了,很多工程专家也未必能讲得清楚他们的区别——原因很简单,不同的工业标准对 Security 和 Safety(其实主要是Safety)有着完全不同的定义——手中捧着的教科书不同,你自然不能责怪工程师们对安全做出不同的理解。
这是不是说,离开具体的领域,Security 和 Safety 对我们普通人来说就是一个糊涂账了呢?也不是。脱离具体领域的教条,Security 和 Safety 有一些精神值得我们去领会下:
Security 基本上等效于 “信息安全”,Safety 基本上等效于 “功能/设施安全”
Security 主要讨论的是 如何保证信息不被别人窃取。
生活中的 Security 就是如何防隔壁老王。
Safety 主要讨论的是 在极端的情况下 如何保证 设备或者设施 不会出乱子、不会造成损伤或者损害;甚至仍然能提供最低限度的功能。举几个例子:
有人触电时,家里自动断路器会切断电源(过流保护)
温度过低时,为了保护锂电池的寿命,某些负责任的电子设备会禁止你充电或者放电。比如,某phone冬天冷了没法充电,要被子里捂热了才行(低温保护)
某些工业级芯片,如果系统电压过低,会自动将复位信号拉低以防止系统跑飞(BOD)
Security 防止不怀好意的人为攻击;Safety 防止极端环境变量导致的损害
有时候,Safety和Security 是同时需要满足的,以汽车为例,传统的汽车强调Safety——如何避免交通事故,如何减小人员伤亡,所谓的Security估计也就和车钥匙有关,顶多防止二手车商改里程表;到了“PPT”时代,汽车已然能够上网,如果不重视 Security,那么一旦黑客控制了汽车,交通事故,人员伤亡都很难避免——Safety也无从谈起。
有时候,在 Safety 面前,Security 是可以有所妥协的。
这就好比,你已经被匪徒绑在老虎凳上了,还有什么保险柜密码不可以说的?
在一个嵌入式系统中(或者说在物联网系统中)Security 和 Safety 分别是什么呢?他们之间的关系是怎样的呢?
在嵌入式系统中,Security 涉及面那可不是今天这篇文章可以说的完的。
通信有通信的信息安全,也就是大家熟悉的 1)各种通信内容的加密解密、以及2)通信双方的握手和鉴权(类似,证明你妈是你妈,你是你妈的孩子)。
软件有软件的信息安全,比如,你写的代码如何保证不被别人读取出去;你通讯用的密钥如何安全的保存,你与人合作写的库如何保证不被别人未经授权的使用等等。
系统有系统的安全,比如,如何保证FLASH的内容不被别人直接开盖读取出去,如何保证某个硬件IP的算法逻辑(时序)被黑客获取,如何保证不同的任务之间相互无法未经授权的读取彼此的内容等等。
Safety 在单纯的嵌入式系统中,可以被理解为 基础设施功能安全。什么意思呢?就是,对于极端的温度、电压、电流、充满噪音的时钟,系统都不应该跑飞,甚至还要提供一个最小限度的功能。
Security 无论如何本质上说都只是一个功能逻辑。功能逻辑作用的正常发挥建立在硬件能够正常工作的基础之上。黑客的思路往往是,既然一个正常工作的 Security 逻辑我不好攻破,那我们就攻击实现 Security 逻辑的硬件基础设施——如果基础设施的Safety不够强壮,容易受到破坏,俗语说,皮之不存毛将焉附,构建在其之上的 Security 也就无法正常工作,从而暴露出更多可攻击的机会。正因为如此,我们说:
嵌入式系统中,Security 是构建在 Safety 基础之上的。离开基础设施的Safety,Security 就是纸老虎——就是因为这个原因,我们容易看到,很多攻击 Security 的方法,实际上是首先攻击 Safety。讨论Security的很多文章也在所难免地会讨论很多Safety的内容。这就容易让读者产生错觉,仿佛Safety 和 Security 在嵌入式系统中是一回事。现在你知道了,其实并不是这样,这就好比“釜底抽薪并不说明柴火和“煮东西” 是一回事”。
攻击复位电路,曾经让某知名厂商的Cortex-M3单片机的破解“立等可取”——这是典型的通过攻击硬件基础设施来攻击上层Security的案例。其实,你是否知道,软件也有基础设施,攻击软件基础设施也是黑客的常见手法。
栈是C语言的基础设施,无论是函数调用,参数传递,还是局部变量分配都离不开栈,因此就有各类针对栈的攻击,比如经典的stack smash,code injection等等;与之类似,堆、C标准库也都是软件的基础设施。
原理上,很多Security的攻防其实都是针对软硬件基础设施的攻防展开的——釜底抽薪,简单有效——然而,这只是 Security 冰山一角。
那么,嵌入式信息安全的本质是什么呢?
嵌入式信息安全(Security)的本质是隔离(Isolation)
值得强调的是,这里的隔离并不区分软件(Software Security)、硬件(Hardware Security)和团队相关的各类流程(Team / Design Flow Security)。换句话说,用“隔离(Isolation)”的方式去实现“信息安全(Security)”,在嵌入式系统中无论放到任何语境都是成立的——或者说是放之四海而皆准的公理。
提到隔离,我们立即就面临以下几个问题:
把谁从谁那里隔离开来?(防谁)
要隔离的东西是什么?(保护什么)
用什么办法进行隔离?(怎么隔离)
别小看这三个问题,他们可是信息安全系统设计的关键。正确回答了这三个问题,是防止博士卖驴下笔千言离题万里的最有效方法。
“等下,等下……”,有人坐不住了:“隔离什么的我不管,信息安全不应该是加密解密,握手鉴权这一类的东西么?”
“对啊,对啊,什么DES,3DES,什么AES128已经不安全应该用AES256之类的话题么?”又有人附和道:“MD5啊,RSA啊之类的算法和 Isolation 有什么关系呢?难道是把所有内容都加密了来实现隔离么?”
所以说,你们有些同志,图样图森破,就知道些个加密解密的算法,以为所谓的信息安全就是加个密,保护个密钥,让人看不懂就行了。这都是非常片面的。打个比方,加解密算法、密钥管理、鉴权之类的东西相对信息安全就是砖头和房子的关系——造房子要有需求(房屋的用途是什么,给谁住,有什么需求,预算是多少?设计寿命是多少?房屋所在地又怎样的自然和地质灾害?需要抗击到什么成都?)、目标规划(多少预算,多久造出来,找谁来造,如何施工?如何验收?验收标准是什么)、还要有理论指导——最终通过工程实践,使用各类建筑材料造出符合要求的房子来。你看看,要不是你们打岔,浪费这么多口舌,结果什么有用的东西都没有说。要完整的搞清楚这里面的关系,我会在随后的文章中详细介绍,这里我们先从更本质的东西开始理解信息安全。
防谁和保护什么
这两个问题通常是一起考虑的,具体讲究太多,三言两语讲不完,我就讲个大家身边的故事:
小李是个硬件工程师,自学软件开发小有所成,经常接一些私活赚点烧烤钱。这次,他从相熟的私人小老板那里接了一个开发的活,具体什么硬件,什么功能并不重要,但值得说明的是,小李很自豪里面的一个软件算法,这个算法可以极大的提高产品的参数,用较小的硬件成本实现那些“昂贵高级”货才能做到的参数。为了保护这个算法,小李又额外花了大量心思对产品进行了加密,什么“对固件升级的通信尽心加密啦”,“用状态机混淆算法逻辑啦”,什么“固件完整性检测啦”,“多重密钥保护啦”……总之,网上能找到的算法他都用了,虽然花了不少时间,私人小老板一分钱也不多给,但是他还是很满意的。
然而……产品推出不到两周,市场上就出现了一模一样的克隆产品。对方通过暴力开盖的方法复制出来固件,然后用同样的固件进行了批量的生产。小老板很不满,找到了小李,责问他是不是嫌钱给的不够,又把设计卖给了别人。小李很委屈,他一再强调,自己已经对产品做了加密,别人绝对没法获得自己的算法——听到这里,小老板冷冷一笑,“没人感兴趣你的算法,人家感兴趣的只是如何克隆整个产品,然后量产就行了!——你浪费那么多时间精力,却没有对关键的UID做绑定,真不知道怎么说你才好。”
真是老话说得好:长得再屌,一砖撂倒。加密再好,克隆拉倒。
这个故事告诉我们,很多时候,如果你实现的隔离手段本质上只是关起门来防贼,但如果别人连你房子一起挖走了……所以,针对不同的攻击手段,要设计不同的隔离方式,不能只想到空间上的隔离,时间上的隔离也不能放过。
怎么隔离
有位电影里的长者说过,你看那世间纷争,不过“名、利”二字,看透了……看透了就会明白,两手抓两手都要硬才是真正的人生赢家。有位象牙塔里的长者说过,你看那时间纷繁,不过“时、空”二字,看透了——就会明白,做信息安全,时间隔离(Temporal Isolation)和空间隔离(Spatial Isolation)两手抓两手都要硬!
空间隔离
空间隔离好理解,比如一个32bit的4G地址空间,你通过硬件把它分成一小段一小段的(大小任意),然后每一段都可以拥有不同的访问权限(No-Access / Read-Only / Full Access)。这就是空间隔离。但时间隔离怎么理解呢?难道是一对穿越时空的恋人,都到达过同一个空间,却一直错过?你真这么理解,其实也不错,不过你确信你是程序猿,而不是程序媛?要想正确的理解这个问题,我们首先从两类不同资源的空间隔离谈起。
非共享资源的隔离
非共享资源,是指在多任务系统中,由某一个任务“独享”的资源。对于这类资源,非常简单,在任务切换时将当前任务的资源配置写入到专用的存储器隔离外设(例如Cortex-M中的Memory Protection Unit,简称MPU)就可以了。这样,每个任务都可以将自己独享的资源与其它任务隔离开。
共享资源的隔离
共享资源,顾名思义,就是在多个任务间共享的资源,比如,共享的各类外设(UART,SPI之类)。对共享资源来说,要想实现隔离,单纯从静态空间角度出发是做不到的,因为隔离本质上就是一种“排他”——我的东西别人都不准用——那么又如何做到多任务之间进行“共享”呢?很自然的,“分时复用”的概念就被引入进来。简单说就是在时间轴上,把时间像地址空间那样分段,然后把不同的段落划分给不同的任务,这样,对每个任务来说,在自己的时间片内,这个资源就是独享的。
分时复用的概念并不是什么新鲜玩意,那么它跟隔离有什么关系呢?严格来说,一毛钱关系都没有。单纯的分时复用并没有起到任何隔离的作用——在分时复用的情况下,所谓的隔离,应该体现在,前后彼此相邻的两个任务在切换资源使用权后,后来者应该无法获取前者的残留信息——否则就是任务的信息泄露了。要实现这个功能,我们需要引入现场的概念:
当一个任务获得资源的使用权时,要回复自己的现场,以继续之前的工作
当一个任务被迫要放弃使用权时,不光要保护自己的现场,以便下次能继续,还要毁掉现在的现场,以防止泄露信息给资源的其它使用者
这一过程并不难理解,但值得强调的是,对共享资源来说,每个任务都有了一个针对该资源的“现场”。现场保存在哪里?还不是属于任务的某段存储器里?所以说,容易推导出:
共享资源的隔离,就是每个任务对资源专属现场(context)的空间隔离。
更进一步的,上述这种给每个任务都配备一个“现场”,从而将一个公共资源在多个任务之间共享的方式叫“虚拟化(Virtualisation)”——也就是
用一个物理的资源,用分时复用的方式给每个任务都虚拟一个资源出来。
而
虚拟化,就是实现“时间隔离”的核心方式。
好吧,饶了半天,终于绕回来了。我们来简单总结下:
非共享的资源——我们使用存储器管理外设,简单的用空间隔离就行了
共享资源——我们使用虚拟化技术,通过空间隔离“现场”的方式,实现资源在时间上的隔离(防止信息在任务切换时发生泄露)
说了这么多,我们来解释一个有趣的事情:
流水线(pipeline)其实是一个共享资源——多个任务共享同一个流水线,通过分时复用的方式来执行任务代码。针对流水线的“现场”,我们习惯上叫任务上下文。从这个意义上说,OS不过是对流水线进行了虚拟化,使得每个任务执行时都能暂时的独占流水线。那么问题来了,你注意到没有,如果说前后台系统是简单的多任务,那么普通MCU在进行中断处理时,虽然有出入栈操作,但并没有“抹掉”前一个任务留下的“现场残骸”!——也就是说,任务信息在中断处理的过程中是会泄露的!!在原理上,普通MCU就是无法可靠实现“时间隔离”!
ARMv8-M TrustZone架构做了一件什么事情呢?就是,当程序在Secure模式下运行,突然来了Non-Secure的中断,除了普通现场保护,硬件还会帮你把Secure运行的现象抹掉!——也就是在架构上彻底通过硬件的方法实现了可靠的“时间隔离”,这是老的ARMv7-M和ARMv-6M架构无法通过硬件做到的——这就是为啥从原理上ARMv8-M的TrustZone比老的架构更安全。
—————以上正文结束—————
长按前往图中包含的公众号关注
嵌入式编程专辑 Linux 学习专辑 C/C++编程专辑 关注微信公众号『技术让梦想更伟大』,后台回复“m”查看更多内容,回复“加群”加入技术交流群。 长按前往图中包含的公众号关注