图略
所有PSA设备必须支持一个安全启动(引导)流,以确保只有授权的软件才能加载到设备上。上面的图概述了一个通用的安全启动流,仅作为定义安全需求的一种参考。
一般情况下,建议将启动过程分割成小块,简单和可验证放入Boot ROM,所有复杂步骤可以放在一个可更新的boot镜像中,这本质上是将启动过程的所有复杂步骤移动到PSA RoT (SPM)的启动阶段,仅将boot ROM用作引导验证链的信任根(可信根的可信根,链的首端)。
实际实现可能使用更复杂的模型,例如,一些解决方案可能会支持带有附加步骤的引导链,例如,初始启动映像加载可信根代码和初始应用程序的引导程序(入口主程序), 然后应用程序次分别引导NS端内核和应用程序映像(次要应用程序映像)。或者某个实现可能支持将主系统映像拆分为多个子映像,以允许增量更新,而不是更新整个映像。或者使用不同的签名实体支持更复杂的供应链模型。
任何此类变体仍然必须满足本文档中定义的通用安全属性:
- 设备在复位后必须始终从Boot ROM引导
Boot ROM构成系统上PSA不可变根的一部分。作为不可变的,它不能改变,因此必须是最小的、可认证的和通用的。
Boot ROM在运行引导到主引导代码之前测量(度量)并验证主引导映像。
- 主映像包含主引导代码
主引导代码负责大部分引导过程,启动设备的主软件,包括信任组件的根,主引导映像可能是可更新的。
在执行引导前,主引导代码必须具备测量RoT组件和设备的主要应用程序的能力,
- 一般在PSA系统上,主引导代码将执行在SPM(安全分区Secure Partition Manager)上,然后再在系统上为其他代码创建(并强制执行)相应的隔离环境。
- 一些设备可能包括加载用户应用程序的额外启动步骤:可下载的应用程序、内核文件系统和其他后期阶段的镜像和组件
应该验证执行链中任意点上的任何加载组件,并且不能破坏设备的安全引导链。
-
- 镜像签名和认证(强制要求)
所有装载在PSA设备上的镜像必须使用非对称密钥(RSA或ECC)进行签名,并且必须在镜像安装到设备之前进行验证确保无误。
镜像一旦安装在设备上,就可以选择用本地哈希锁定,以避免每次启动时都要使用非对称验证(混合验证方式)。
规则 |
描述 | 备注 |
装载在PSA设备上的所有镜像必须使用非对称密钥(RSA或ECC)进行签名。 | 设备必须能够确保只安装和加载经过授权的软件。 | 对于PSA兼容性设备,我们认为对称加密的验证方式是不充分的 |
镜像签名至少包括以下几部分: 镜像大小 镜像的所有内容(代码和数据) 关键参数,如位置和启动地址,适用范围等 镜像清单,包括组件版本,软件尺寸等 |
|
|
每个软件组件必须指定一个软件版本。 软件版本必须包括至少下列组件,或全部(发布版本或镜像版本),或单独的(组件版本):
| 启动过程和认证验证程序都需要能够识别设备中当前加载的软件版本。 版本号应该是唯一能标识相关组件更新的信息,版本号较高说明更新较新。
| 这部分要包含在初始认证中,在反回滚操作中可以作为重要依据 |
如果未指定个别组件版本,则为了认证和反回滚的目的,应将其报告为具有与整体依据镜像版本号相同的版本 |
| 在启动状态中获取 |
在设备上安装镜像之前,必须执行完全非对称验证。 |
| 例如,在固件更新期间。 |
在加载镜像执行之前,应该执行完全非对称验证。 |
| 例如,在固件启动期间。 |
安装时镜像可能被哈希(或对称)锁住 | 允许设备仅在安装映像时执行完全非对称验证(比如固件更新)并在加载执行时(例如,在引导时)执行更简单的局部对称验证,以提高性能。 |
|
任何本地锁必须是完整的和防重放攻击的。 | 不能使用本地哈希锁定机制来绕过安全的引导链 | |
Boot ROM必须与不可变的根验证密钥关联 | Boot ROM必须能够根据不可变根验证它加载的任何映像。 | 根验证密钥可以是Boot ROM的一部分,也可以单独存储在受保护的存储区 |
不可变根验证密钥不应用于直接对镜像进行签名和验证。 | 不可变根验证密钥是一项重要的资产,应该仅用于对委托的验证密钥进行签名,以最小化根验证密钥的签名事件。 | 看验证和供应链章节和【TBFU】 |
-
- 组件测量(强制要求)
不管以何种方式打包,软件组件必须在加载执行时进行测量,以便进行认证
规则 |
描述 | 备注 |
以下组件在加载执行时必须单独测量:
| 验证实体必须能够确定设备完成完全安全的配置。 | 如果其中一个组件被加载为多个子组件,那么每个子组件必须单独测量。 |
如果上面列出的任何一个组件被更新为多个单独的子组件,那么每个子组件都必须单独测量。 | 一些设备架构支持细粒度更新,以最小化更新的大小。 |
|
组件的度量必须至少以哈希形式计算:
|
| 重要的参数,例如位置和启动地址都包含在签名验证中,不需要单独测量。 |
-
- 系统复位(强制要求)
在本文档中,术语“系统复位”用于描述完整的系统复位,包括任何可信的子系统都要复位。系统复位后,系统和任何可信子系统应处于新的状态。不应该保留或使用重置之前的任何运行时状态。
规则 |
描述 | 备注 |
PSA系统的复位应包括任何可信子系统的复位 | 系统必须以新的状态启动,包括所有可信的子系统都应该是新的 |
|
必须在每次引导时重新评估和验证引导状态。 | 系统的启动链和可靠性必须在每次重置后重新建立。 |
|
系统只能在系统重置后从Boot ROM启动。 |
|
|
Boot ROM和重置后的入口点必须是不可变的,并且不能在生产设备上以任何方式更新或修改。 |
|
术语“系统休眠”用于描述系统重置事件,该事件可以保留足够的状态,以便在重置之前从已知点重新启动执行。
系统休眠是一个可选的功能。如果支持,休眠通常需要在关闭系统之前将运行时状态保存到掉电不丢失存储设备中。在系统重置时,启动代码能够检测并恢复先前保存的状态,这是系统启动过程的一部分。
从安全的角度来看,支持系统休眠的符合psa的设备应该确保任何保存和恢复的休眠状态都得到了适当的保护:
- 保护运行时机密数据和存储状态中包含的机密数据的隐私
- 保证存储数据完整性
- 防重放保护,以保证数据未必修改
规则 |
描述 | 备注 |
必须保护休眠状态,包括隐私、完整性和重放保护。 | 不能提取、修改或替换休眠状态(值),包括运行时密钥和数据。 | 根据设备架构的不同,可以通过使用片上存储资源或通过密码保护来满足这一要求。看存储章节。 |
已休眠然后恢复的系统和一个从未休眠的系统一定不能有差别 | 不能使用休眠函数来影响或修改系统的运行时状态或数据。 | 从安全的角度来看是无法区分的。比如,由于休眠的原因,使得网络连接断开。 |
休眠处理代码必须经由PSA可信根验证可信 | 休眠系统的行为必须作为设备上最受信任的代码的一部分来处理 | 通用电源管理代码,包括决定是否休眠,可能在PSA可信根可信边界外。实际的休眠代码必须在PSA可信根边界之中,
|
术语系统挂起用来描述任何低功耗状态,在这种状态下,系统没有被重置或进行用电循环,但是大多数资源已经挂起。任何需要系统复位或完全断电的电源管理状态都必须视为系统休眠。
系统挂起是一个可选特性,如果支持,则挂起通常涉及到确保当前执行状态有序挂起的挂起代码,然后电源管理硬件停止并关闭系统资源,只维护很小的内部电源管理状态,并保持DDR刷新以维护系统的运行时状态。
在恢复时,电源管理硬件恢复系统资源,挂起代码确保有序地恢复挂起执行状态。
规则 |
描述 | 备注 |
应尽可能地保护挂起状态,包括机密性、完整性和重放保护。 | 挂起状态包含运行时状态和内存中的数据 | 通常,在安全性和挂起的恢复时间性能之间需要进行权衡,预期的挂起和恢复时间比较短。 根据认证配置文件和硬件功能,挂起的性能可能在物理角度难以实现,也可能出现执行状态的部分关键部分被覆盖的情况 |
已挂起然后恢复的系统和一个从未挂起的系统一定不能有差别 | 不能使用挂起函数来影响或修改系统的运行时状态或数据。 | 从安全的角度来看是无法区分的。比如,由于挂起的原因,使得网络连接断开。 |
挂起处理代码必须经由PSA可信根验证可信 | 挂起行为必须作为设备上最受信任的代码的一部分来处理 | 通用电源管理代码,包括决定是否挂起,可能在PSA可信根可信边界外。实际的休眠代码必须在PSA可信根边界之中, |
-
- 反回滚(强制要求)
反回滚机制确保设备只接受较新版本的软件,目的是为了防止加载包含已知错误或漏洞的较早版本软件的操作。PSA允许以下两种方法中的一种在符合PSA的设备上支持反回滚保护:
- 本地更新与复位功能
在这种模型中,当设备成功引导了一个新版本的软件时,Boot ROM会自动更新一个反回滚计数器。这里成功的定义,唯一一条就是镜像通过了认证。
然而,一些代码实现可能在下一次重启时可以检测到(通过BootROM)设备是否被重启过,例如,
检测看门狗是否出了故障,或者使用更复杂的检查点方案。这时反回滚计数器可能暂时不更新直到
确保一次启动完成。
在后一种情况下,在引导代码更新了反回滚计数器之前,如果检测到引导错误,则引导代码可能会
退回到以前最后一个已知的好版本。
如果反回滚进程本身出现错误,例如反回滚计数器不同步,导致设备无法启动,则可能需要支持反
回滚计数器的重置机制。例如,工厂重置操作也可以重置反回滚计数器,或者设备管理的协议中可
能包含了一个重置反回滚计数器的指令。在后一种情况下,由BootROM强制执行用来支持源验证
和此类消息的重放保护,显然是必要的。
- 更新指令
另一种方法是boot R不自动更新它的反回滚计数器,只有在它从设备管理服务接收到安全消息时
才进行更新。
这需要设备管理协议中的安全消息传递特性,至少支持源验证和合理的重放保护。
它还需要一个安全的消息传递功能,向设备发出信号,告诉设备哪几个软件版本可以被加载(基本
上是比设备上的反回滚计数器的当前版本更新的任何版本)。
使用哪种方法取决于操作需求。
第一个选项可能在设备级别上更健壮,但可能使管理回滚场景变得更困难,如果新部署的映像存在服务级别问题—但它可能还是会正确引导,但是它的某些功能确实被破坏了,服务提供商决定回滚。
此外,如果使用了重置报文用于重置计数器,那么如果没有适当和有效的消息重放保护方案,则该消息本身可能存在安全风险。
第二个选项在服务级别上可能更健壮,因为服务提供者在其网络中推出新软件版本后,将决定何时调用反回滚。但它也有可能使设备能够更长时间地回滚到以前的软件版本。它需要一个安全的消息传递功能,确保更新计数器的消息只能来自可信的来源,但是,通过阻止消息更新反回滚计数器,仍然可能(取决于协议实现)受到拒绝服务攻击,从而使设备暴露于回滚攻击。
无论哪种方式,这两种类型的语义都需要以下通用特性:
- 一个由引导代码专门管理的反回滚计数器——只有与反回滚计数器相同或比它更近的版本的映像才可以加载到设备上
- 反回滚计数器可以在新映像成功引导后由引导代码自动更新,也可以根据设备管理服务的命令进行更新
- 反回滚计数器可以重置,可以在工厂重置时自动重置,也可以通过设备管理服务的命令重置
- 如果使用来自远程服务的命令控制反回滚(重置或更新),则必须通过源验证和重放保护来保护该命令
规则 |
描述 | 备注 |
系统必须只加载、安装和组件当前安装版本相同或更高版本的更新。 不能安装任何组件的旧版本。 | 生产设备必须支持反回滚。 | 通常反回滚计数器需要存放在安全的存储中。 |
反回滚功能必须只能由Boot ROM执行 | 设备状态,包括它的启动状态,必须是可测试的,并且在运行时不能改变。 所有固件更新必须重新启动设备才能生效。 |
|
反回滚机制只能直接被boot ROM访问。 | 设备上的任何其他代码都不能直接修改设备的反回滚状态。 | 根据认证配置文件的不同,可以通过隔离或可锁定寄存器或类似的方式满足此要求。 |
反回滚机制可以在工厂重置指令后重置。 | 如果反回滚机制不同步,则允许设备被恢复。 |
|
设备可以支持一种通过远程消息传递控制反回滚保护的机制——重置消息或更新消息 | 远程设备管理消息传递。 | 例如,在某些设备管理协议中也可以使用这种远程机制来支持目标更新。这些附加功能超出了本文档的范围,但通常具有类似的安全性要求。 |
任何远程设备管理机制必须至少通过以下方式进行保护: 使用至少与用于镜像签名相同的密码属性,对指令发出者进行身份验证 重放保护,确保任何发出的命令实例,只能由设备执行一次
| 破坏消息传输协议不能比破坏安全启动机制本身更容易(使得破坏协议成为安全的一个短板) 不能对设备使用以前发布的这些命令的版本。 |
|
不能使用任何远程管理功能强制设置设备上的反回滚计数器的值,超出当前加载到设备上的所有镜像的最高版本。 | 不能强制设备进入无法引导的状态。 |
|
加载SPM(安全分区)之前的引导阶段——boot ROM和main boot——应该通过时间(时差性)隔离来隔离:
- 每个阶段的代码应该执行它的任务,完成后,终止并将执行移交给下一个阶段
- 每个阶段的代码应该在引导状态中记录,以便将结果和数据从一个阶段转移到下一个阶段
- 一个阶段的私有数据不应该被后面的阶段直接访问(或访问)
注意,在这个上下文中,时间隔离与启动任务的执行有关。在受限的设备上重复使用通用的引导代
码功能,例如,密码库,可以减少整体的代码占用。任何此类重用都不能改变或影响系统的启动状态,并且不能暴露任何私有的引导代码机密信息或数据。
规则 |
描述 | 备注 |
在一个启动阶段执行的代码必须完全退出,然后才能移交给下一个阶段。 | 每个启动阶段(安全分区管理之前的操作)必须完全控制自己的环境和执行上下文 |
|
一个引导阶段的数据和结果可能会作为下一个引导阶段的引导状态。 |
|
|
引导状态值应该存放在片上 RAM上。 | 引导状态值可能包含根密钥 | 使用外部DDR来保存启动状态可能会将根密钥暴露给探测设备,可能遭受其他外部攻击。 |
一个引导阶段的代码不应该直接访问前一个引导阶段的密钥和私有数据。 | 必须遵守时间边界的限制。 | 退出特定的启动阶段时,硬件应该将某些存储位置禁用直到系统完全复位。 也可以通过软件约定或隔离来实施,具体取决于认证配置文件 |
-
-
- 初始启动状态(Initial boot state)
-
初始启动状态是在提交到主启动(main boot)之前,Boot ROM留下的隐私信息和数据。
规则 |
描述 | 备注 |
通过boot ROM,至少为每个验证过的软件组件提供如下信息:
manifest)
| 获取由boot ROM确定的引导状态。 |
|
初始参数应该从屏蔽区域复制到初始启动状态(initial boot state)。 | 只有boot ROM应该直接访问屏蔽区域的根参数。 |
|
初始启动状态应该只能被主启动(main boot)直接访问。 | 软件的后期阶段不应该使用初始参数。 | 这可以通过main boot在退出时擦除初始启动状态的全部或部分数据来实现。 |
通过bootROM的控制,初始启动状态只能设置一次不能被修改 | 确保主启动(main boot)组件可以信任初始启动状态(initial boot state)。 | 根据认证配置文件的不同,这个需求可以通过物理隔离和软件实现来满足。在具有更严格的认证配置文件的设备上,可能需要可锁定的寄存器(只能通过boot ROM写入))。 |
-
-
- 主启动(引导)状态(Main boot state)
-
主启动状态值是主引导代码留下的数据和私密信息。
规则 |
描述 | 备注 |
主引导状态值必须包含由bootROM获取到的所有组件信息。 | 保留通过bootROM测量(度量)的所有组件的测量值。 |
|
对于每个由主引导代码验证的附加软件组件,必须获取以下组件信息:
manifest)
| 通过主引导代码,为所有的附加组件都提供测量值。 |
|
启动种子 启动状态必须包含在每个启动事件中唯一生成的启动种子 | 启动种子可能被以后的服务使用,例如,允许验证实体确保在同一启动会话中生成不同认证端点的认证。 它必须足够大,使得全局碰撞在统计上不可能发生。 | 这里的唯一是指统计学上的唯一。建议使用256位的大小。 如果引导过程耗费足够的资源,则可以通过随机生成来满足此属性,或者通过从单调启动计数器生成散列来生成种子。 |
主引导状态必须包含所有 PSA可信根参数。 | 必须确保所有的可信根参数都可获取 | 要么从初始启动状态的初始参数填充,要么从初始参数派生,例如HUK(硬件唯一标识hardware unique identifier)。 |
主引导状态只能被PSA可信根服务访问。 | 只有PSA可信根能够直接访问PSA RoT参数。 | 对于等级1的隔离系统,这一要求只能通过软件约定来满足。 对于等级2或更高隔离级别的系统,必须通过硬件隔离机制强制执行此要求。 |
主引导代码设置一次后,不应修改主引导状态。 | 确保启动状态可以被PSA RoT信任 | 根据认证配置文件的不同,这个需求可以通过物理隔离或软件约定来满足。 在具有更严格的认证配置文件的设备上,可能需要可锁定的寄存器(只能由main boot和对应的锁来写入)。 |
-
-
- 可信子系统测量(Measured trusted subsystems)
-
可信子系统的任何可更新组件都必须在引导时进行测量和验证,并包含在引导状态中。
规则 |
描述 | 备注 |
每个可信子系统的任何可更新部分都应该由一个签名清单描述。 | 与验证过的软件组件有相同的模型。 | 可更新的部件包括,例如,软件,固件,硬件。 影响可信子系统功能的任何可更新组件。 |
每个可信子系统的每个可更新组件必须在引导时由Boot ROM分别测量和验证。 | 必须验证可信子系统的状态和属性。 |
|
通过boot ROM,至少为每个验证过的软件组件提供如下信息: Signer ID (from manifest) Software version (from manifest) 实际的测量值——由Boot ROM真是测量出来的 | 与验证过的软件组件有相同的模型。 |
|
图略
图略