启动在这里被定义为每次系统启动时需要做的软件操作。系统启动可以是冷启动,或者是PC相关的从睡眠中唤醒,或者从休眠中重新启动。TPM内部有几种易失性的状态,包括PCR值,已加载的会话和密钥,使能配置,授权和Policy信息,混合NV索引,以及时钟状态。根据TPM电源周期类型的不同,这些易失性状态可能必须被保留或者重新初始化。TPM提供了两个命令,它们可以有各种组合,这允许外部软件来处理TPM电源周期相关的要求。
与上述的情况相反,初始配置是极少发生的事情。它很可能在整个平台声明周期中只发生一次。一个TPM厂商,平台厂商,IT部门,或者终端用户会生成密钥以及其他秘密信息,注入证书,以及使能或者关闭特定的TPM功能。配置的另外一面就是取消配置:在将平台用作他用,变卖,或者丢弃之前需要保证TPM相关的秘密信息都被擦除了。
这一章首先讨论启动,之后是TPM相关的各方可能会做的初始配置。配置方包括TPM厂商,平台厂商(也叫做OEM),以及终端用户(个人或者IT部门)。
TPM的启动和关闭都由底层软件来管理。在一个PC平台上,底层软件是指BIOS(UEFI)和操作系统。管理的主要目的是相关的状态需要按照要求被复位或者恢复,从而使得应用不用关心这些事件的发生。举例来说,一个应用不希望已经加载过的密钥或者会话突然消失了。这个应用可能不能重新加载密钥,并且它也不希望因为会话突然消失而重新运行一个Policy检查。在启动软件和操作系统的支持下,TPM可以让电源周期对应用软件透明,具体的做法就是在掉电时将易失性状态保存到非易失性内存中,重新上电后将这些状态恢复。
TPM规范定义了三种启动事件:TPM复位,TPM恢复,以及TPM重启。这些信号在平台复位时的TPM Init信号之后发生。在一个典型的硬件TPM实现中,初始化就是释放TPM的复位引脚,这很可能是在一个电源周期之后。这时候,我们假设TPM的易失性状态都会丢失,只有之前保存的非易失性状态仍存在于TPM中。
TPM复位通常在平台上电后的启动阶段或者不断电重启时发生。TPM会收到一个启动命令,这个命令用于复位TPM的易失性状态。在这种情况下,复位可以理解为将一些状态设置为指定的初始化值或者为nonce分配新的随机值。TPM复位将会建立一个新的可信平台状态。所有需要的软件都会被测量并扩展到一组复位PCR中。所有的TPM资源都会被复位到默认的初始配置状态。
TPM恢复通常平台由挂起状态恢复的时候发生,有时候挂起又叫做睡眠或者低功耗状态。因为平台是在继续执行而不是重新启动,所以是所有的状态,包括PCR值,都会被恢复。TPM恢复会将TPM的状体恢复到TPM因系统睡眠或者重启而掉电前的状态,因为从系统复位或者掉电的时刻起,它的可信状态就没有变化了。
TPM重启通常在平台由休眠状态被唤醒的时候发生。系统休眠时会在TPM断电之前向TPM发送命令来保存状态,大部分的状态都会在TPM启动的时候恢复。例外是PCR的值,PCR在TPM启动时只做了初始化,而不是状态恢复。这个操作就允许平台在启动(由休眠状态恢复)时向PCR扩展新的测量值,而不是将操作系统和应用使用的TPM状态重新恢复到PCR中。TPM重启在PCR操作上是比较特殊的,在这个过程中平台是在重新建立可信状态(会创建新的测量值),而不是恢复相关的可信状态(在这个上下文环境中可以说这些状态就是操作系统和应用程序使用的PCR值)。
TPM提供两个命令来支持上述的启动事件:TPM2_Shutdown和TPM2_Startup命令。关机命令通常是由操作系统在复位或者断电前执行的。TPM2_Shutdown有两个选项:CLEAR和STATE。TPM2_Startup命令通常是在用于系统初始化的固件(比如PC上的BIOS(UEFI))在做RTM(Root of Trust for Measurement)时执行的。TPM2_Startup同样也有两个选项:CLEAR和STATE。
以下是两个命令配合使用的情况:
- TPM复位(重新启动):TPM2_Shutdown(CLEAR)或者没有TPM2_Shutdown命令,然后执行TPM2_Startup(CLEAR)。
- TPM重启(休眠唤醒):TPM2_Shutdown(STATE),然后执行TPM2_Startup(CLEAR)。
- TPM恢复(挂起,睡眠):TPM2_Shutdown(STATE),然后执行TPM2_Startup(STATE)。
以下是命令行为的简要描述。这些命令的行为包含很多与时钟,时间,计数器,会话上下文,混合NV索引相关的细节。这些概念已经在本书的其他章节介绍过了:
- TPM2_Shutdown(CLEAR)是平台在关机或者重启时顺序性的关机行为。TPM会将一些易失性的值保存到非易失性内存中:时钟和有顺序属性的NV索引通常会在易失性内存中有一个副本。
- TPM2_Shutdown(STATE)通常是由于系统需要休眠或者挂起而执行的关机操作。TPM会保存之前记录的会话上下文,平台规范强制要求保存的PCR值,一些特定的NV索引标志位,以及审计相关的状态。
- TPM2_Startup(CLEAR)会初始化TPM易失性状态,包括PCR和NV易失性状态;它还会使能三个组织架构;以及清除平台授权和Policy。
- TPM2_Startup(STATE)仅在使用TPM2_Shutdown(STATE)命令关机之后才可以使用。此时PCR会被恢复,或者按照平台相关的规范初始化(0-15保存,16-23初始化)。
举例来说,PCR在上述三种电源周期中的详细行为和原理概括如下:
- 在系统重启时,也就是TPM复位,所有的PCR都必须被初始化。TPM2_Startup(CLEAR)命令总是会初始化PCR的值,不考虑关机的类型。
- 当系统由休眠状态被唤醒时,也就是TPM重启,平台会重新运行BIOS代码并做测量,所以PCR值也必须被初始化。此时使用TPM2_Startup(CLEAR)来初始化PCR,尽管在系统休眠的时候PCR的状态通过TPM2_Shutdown(STATE)被保存了。
- 在系统由睡眠状态被唤醒时,也就是TPM恢复,PCR的值可能在断电时丢失(基本确认会丢失啊,作者是什么意思呢?)。但是因为系统在这种情况下恢复时并不会重新运行BIOS,启动,或者OS初始化代码。所以PCR的值必须被恢复。TPM2_Shutdown(STATE)命令会在系统睡眠之前保存易失性的PCR值。TPM2_Startup(STATE)命令则会恢复这些值。
TPM有几个参数必须在每次启动的时候被初始化。在TPM1.2中,只有一个组织架构和一个所有者授权,并且授权是持续性的。这个组织架构有一个禁用和关闭标志。在第9章我们已经介绍过了,TPM2.0有三个组织架构,每一个都有一个授权秘密信息,一个policy,以及一个启用标志。
TPM2.0拥有一个平台组织架构,这个组织架构包含一个易失性的授权值和Policy,它们会在TPM复位和TPM重启的时候被复位。正常情况下,系统启动早期阶段的软件会设置这些值。我们不希望平台OEM提供操作系统或者应用可以使用的接口来禁用平台组织架构,因为OEM有可能在运行时服务中使用平台组织架构。
平台Policy看起来很直接。如果不设置它,它就是空的:一个永远不能满足的Policy。如果平台OEM有一个用于平台组织架构控制的Policy,那这个平台的启动软件会使用TPM2_SetPrimaryPolicy命令来设置这个Policy。这个Policy不包含任何秘密信息,但是在运行启动软件时,Policy的值必须被合理地保护以防止被修改。如果OEM没有这样的Policy,它就将平台组织架构的Policy保留为空,因此Policy也就不能被满足。
平台授权(HMAC共享秘密类型的授权)的工作方式则不同。TPM架构希望平台能够通过TPM2_HierarchyChangeAuth将平台授权值设置成一个强度很高的秘密信息。又或者是,如果OEM不需要平台授权,那OEM可以将授权值设置成一个随机数并通过删除这个随机值的方式将它忘记。此时,平台组织架构仍然是有效的,但是它不能通过一个口令或者HMAC值来授权。
TPM规范的设计者起初想让平台授权值变成一个持续性的值,这样就与TPM1.2的所有者授权类似。但是这种实现方式产生两个问题:怎样使平台软件在两次启动之间记住共享的秘密信息,以及平台怎么保证它使用了一个足够强度的秘密信息?解决办法就是使用一个易失性的值:在启动时设置一个很大的随机数。这个随机数甚至可以通过TPM的随机数发生器产生。这样一来,平台软件就不用在两次启动之间记住这个值了。它存储在平台的易失性内存中,只能被平台软件访问。
我们期望平台授权值可能不会立即被设置。因为平台软件是相信它自己的,它可以保持这个值为空,或者是一个非常容易被记住的值,之后在平台软件退出并跳转到option ROM或者其他不可信的软件时再设置它,这样就可以防止其他软件攻击平台组织架构。
其他的组织架构是持续性的,并在启动时不用被初始化。这包括所有者授权值和Policy(存储组织架构),背书组织架构授权值和Policy,以及锁定授权值和Policy。
存储和背书组织架构的启用(使能)在TPM复位和TPM重启时会被设置。平台可以记住所有者和隐私管理员的请求状态,并且可以在需要的时候禁用它们。
处理配置包含所有的出现频次很少的TPM设置。在一个典型的TPM生命周期中,这些动作可能仅需要执行一次。
这本书将初始配置分成以下三个部分:TPM厂商,平台厂商(OEM),以及终端用户。尽管这是一种典型的分割方式,但是TPM并没有强制这样做,并且企业可能因为自己的可信模型而偏离上述的模式。比如说,一个大型企业可能会进一步将终端用户的初始配置分割成IT部门和使用者。一个安全性较高的应用案例可能会将TPM厂商提供的背书主密钥或者证书替换成它自己的。
在TPM1.2中,一些特定的配置步骤只能被实施一次。比方说,尽管TPM1.2中有可撤销的背书密钥这样的概念,它可以被删除并重新生成,但是这个功能是可选的,并且在商业硬件TPM中并没有实现这个功能。
在TPM2.0的架构中,没有声明周期内只能设置一次的值。但是,一个平台相关的规范可能让TPM2_ChangeEPS变成可选选项,并且TPM厂商可能不实现这个命令。在这种情况下,尽管使用一个已知模板创建的背书密钥(参考第15章)可以被清除出TPM,但是它却不能被永久地销毁。不过,TPM2.0还可以配置额外的背书密钥。
TPM厂商是唯一有资格认证它的硬件是真实的机构。一旦TPM进入供应链,大部分的采购商都不足以专业到可以分辨伪造TPM和真实TPM。
当TPM第一次上电时,它会在背书组织架构中生成一个原始种子(厂商可以在TPM之外创建一个原始种子,然后通过生产阶段的特殊处理将种子注入到TPM中。这个操作可以潜在地节省TPM的生产时间,因为这样一来,主密钥也可以在外部生成。)然后TPM厂商会使用TPM2_CreatePrimary一次或多次来生成背书主密钥——也就是背书组织架构的根节点(第10章解释了创建主密钥的通用过程,第15章则涉及了更多相关细节)。这个命令会返回主密钥的公钥,厂商会使用这个公钥生成一个证书。
证书,通常是以X.509格式存在,用于证明相关公钥属于一个真实的TPM厂商。证书中通常包含设备厂商的身份信息(ID)。设备厂商的主密钥和证书存储在TPM中与安全性无关。这仅仅是实际应用的结果。
主密钥是由主种子(原始种子)和命令调用者提供的密钥模板生成的。密钥模板包含密钥算法和大小,以及可能的熵值。如果种子不变,相同的模板总是会生成相同的密钥。这样一来TPM厂商就不用交付持续性内存中包含密钥的TPM设备了。用户在任何时候都可以重新生成密钥。这就避免了TPM厂商为了提供基于多种密钥模板的密钥或者提供不常用的密钥而占用宝贵的NV内存。
为什么TPM要使用种子呢?TPM1.2会直接生成背书密钥,但是它只有一种算法(RSA)和一种密钥大小(2048比特)。TPM2.0则支持许多算法和密钥大小。如果继续使用TPM1.2的密钥生成模式,每个密钥都必须存储在TPM中,并且占用宝贵的NV内存。而TPM2.0的设计仅仅需要一个持续性的种子即可。由这个种子派生的密钥可以在需要的时候生成(不需要的时候丢弃,所以不占用额外的NV资源)。
交付一个带有主背书密钥的TPM的优势在于性能。为什么在厂商已经创建主密钥的情况下,用户还要重新生成密钥呢?
实际上,TCG平台工作组被期望基于预期的应用需要指定一个或者多个标准模板。TPM厂商将会生成多个密钥,但是在交付时仅仅给TPM配置一种算法和长度最常用的密钥。
TPM在交付时是否包含证书也是基于和以上类似的实际应用考虑而定。尽管用户可以向TPM厂商请求其公钥对应的证书,但是直接从TPM的NV存储中直接读取无疑是更方便的方式。况且有时候平台并不能与公共网络连接,这样就使得获取证书更加不方便。在实际应用中,我们希望TPM厂商能够配置一个对应一个或者多个主密钥的证书。证书一般情况下都是存储在TPM的NV区域中。
有些情况下用户不完全相信TPM厂商的生产流程(译者的疑问:如果你不相信厂商的生产流程,又凭什么相信TPM厂商在设计上就没给你加后门呢?)。还有一些应用场景要求终端用户比如说政府机构,阻断与机构所用机器相关供应链的任何联系。它们想要祛除任何能够辅助跟踪的密钥。那这个用户可以使用TPM2_ChangeEPS命令来修改背书主种子;然后自己生成新的不同的种子;最后生成自己的证书。用户还可以修改包含TPM厂商知道的随机数的密钥模板,这样一来,就可以在不废止现有主密钥证书的情况下生成厂商不知道的主密钥。
总结一下,TPM2.0与TPM1.2在上述的场景中有如下四种不同:
- 只要主种子不变并且知道密钥模板,主背书密钥可以被无限次的重新创建。
- 因为主背书密钥可以被重新创建,所以它们不用存储在TPM的持续性内存中。
- 因为TPM2.0支持多种密钥算法和额外的模板熵值,因此可以有不止一个主背书密钥。
- 如果TPM设备支持修改EPS,背书密钥可以被删除,从而废除它的证书。
平台OEM的配置主要基于以下两种考虑:
- 真实性
- 控制 与TPM厂商类似,一个平台厂商的证书(通常是X.509格式)会用于断言这个硬件是货真价实的。它会断言TPM是与OEM的平台绑定在一起的。它还进一步证明平台的TPM相关软件是符合TCG推荐标准的。对于一个PC客户端来说,这些相关软件包括CRTM,CRTM主要用于测量软件并将测量值扩展到PCR中。
尽管攻击者可能会从物理上将TPM设备从OEM平台上移除,并使用伪造设备替代,但是TCG的技术明确说明不能阻挡这样的物理攻击。更进一步讲,这种攻击方式一次只能攻击一个平台。从另一角度来说,如果一次攻击能够让攻击者提取出主密钥种子的话,这将导致攻击者可能生产无数的伪造设备。
平台证书通常针对由TPM厂商在TPM生产阶段产生的背书主密钥。在断言它的平台式真实的之前,OEM会想要验证TPM是真实的。它会读取TPM的证书并验证证书;还可能更进一步地读取公钥,并验证公钥与私钥匹配,或者至少证明密钥对儿是存在的。
与TPM厂商背书密钥证书一样,交付TPM时将平台证书存储在TPM中也跟安全性无关。基于实践应用的考虑,OEM可能会将证书保存在TPM持续性内存中,这与TPM厂商的证书对应。
TPM2.0具备一个平台组织架构。平台OEM可能会使用平台Policy配置这个组织架构。之前已经解释过,TPM会将这个Policy初始化为空:也就是一个永远不能满足的Policy。OEM必须在TPM启动时使用TPM2_SetPrimaryPolicy命令来配置它。
那问题是,平台Policy的值是从哪里来的呢?我们期望的是,这个值会被嵌入到平台的早期启动软件中,并且使用与保护CRTM一样的OEM机制来保护这个软件。因此,这个值是在平台生产阶段被配置到平台的CRTM中,而不是直接配置到TPM设备中。然后在TPM启动的时候会被注入到TPM中。
终端用户在这里是一个泛指。对于家庭电脑来说,终端用户通常指得就是电脑形式上的使用者。对于一个企业集中管理的平台来说,终端用户可能是平台实际的使用者或者技术支持人员。
终端用户必须配置背书和存储组织架构。有一种情况是,企业的IT部门可能会配置背书组织架构以及字典攻击复位授权,然后让实际使用这个平台的个人配置存储组织架构。
第一个要考虑的是,是否需要通过TPM2_HierarchyControl命令禁用这个组织架构(TPM启动时总是会启用)。禁用组织架构的方法是平台相关的。我们期望方法是一个BIOS配置界面选项,通过这个选项可以在后面的启动过程中禁用或者继续保持使能这个组织架构。(我们希望TPM能够提供足够多的应用场景,以至于你从来不想禁用TPM的某个功能。)
接下来,终端用户必须配置背书和存储组织架构,以及字典攻击保护的Policy和授权值。所有者授权值的初始值是空(不需要授权值),这个Policy一样(没有Policy)。TPM2_HierarchyChangeAuth和TPM2_SetPrimaryPolicy命令能够修改这些值,这些值会一直存在直到被清除。背书组织架构授权和Policy也是通过同样的命令来修改的。所有者授权和背书授权应该被设置成具有很高的熵值,因为它们不受字典攻击的保护。
字典攻击的逻辑同时有Policy和授权值。一个组织可能会配置所有的Policy和授权值,但是也可以选择不同的逻辑和授权值。设置字典攻击复位的Policy是非常重要的。一旦触发,字典攻击口令只能使用一次,如果错误则必须等待很长时间。但是即使是口令被锁定的情况下,也可以使用Policy来复位字典攻击复位计数器。
背书主秘钥种子是在TPM厂商生产TPM设备时生成的。终端用户通常不会修改这个值。
存储主秘钥种子也是在TPM厂商生产TPM设备时生成的。终端用户可以使用这个已经存在的种子,也可以重新生成一个。生成一个新的种子将会废止除背书组织架构主秘钥之外的所有存储和背书组织架构的对象。因此,背书主秘钥证书此时仍然有效。
取消配置主要是将TPM的秘密信息去除的过程,虽然用户也可能想把公共的但是唯一的数据去除。一个用户通常在公司内部转让平台,变卖设备,或者将系统报废时做取消配置的操作。
什么样的信息是不能被别人接触到的呢?由平台厂商控制的平台组织架构。背书组织架构通常在整个TPM生命周期内是固定不变的。因此修改这个组织架构的种子就会废止背书组织架构的主秘钥,进而让它们的证书失效。
一个平台OEM厂商可能会试图用NV空间存储用户的配置。举例来说,考虑一下BIOS的配置信息存储方式。这样的NV索引可以拥有一个允许终端用户作写操作的Policy,并且Policy允许任何人(尤其是BIOS)读它。如果有些秘密信息是远程或者隐私相关的,那就不鼓励这样设置,因为终端用户取消配置时很容易忽略。
取消配置会使用TPM2_Clear命令。需要注意的是这个命令的授权值不是你可能认为的TPM_RH_OWNER(控制存储组织架构的角色)。相反,这个授权角色是TPM_RH_LOCKOUT(控制字典攻击复位的授权)或者TPM_RH_PLATFORM(平台授权)。
锁定复位授权可能是一个合理的选择。而且很可能用户知道这个授权值。 TPM很可能使用这个授权值而不是所有者授权值的原因是,在一些情况下,所有者授权值可能被更广泛的知晓。因为取消配置有很大的影响,所以最好将它的授权分配给一个有更多限制的角色。
使用平台授权又显得有点敷衍,像恶作剧,因为它只有在系统早期启动阶段才可用,而不是在OS阶段。这就引出两个问题。第一,大多数不熟悉专业操作的用户在BIOS显示阶段做不了任何事情。第二,BIOS显示阶段不允许远程取消配置,但是远程取消配置又是云计算类型数据中心必需的,这就矛盾了。解决这种困境的方法是使用平台Policy,又或者是一个简单的平台HMAC或者口令授权。举例来说,假设平台所有者希望允许一个用户使用所有者授权执行TPM2_Clear命令。可以设置如下包含AND操作的policy:“command code == TPM2_Clear AND Policy Secret's handle == TPM_RH_OWNER”。这个Policy就可以通过所有者授权使用,并且可以在OS层应用这个授权。
那TPM2_Clear命令到底做了什么呢?非常多。首先,shProof和ehProof会被改变。这些证据是以保存上下文的HAMC秘钥的形式存在的。一旦这些证明值变化了,那存储和背书组织架构下被保存的上下文就不能被加载到TPM中了。接下来,任何驻留在存储和平台组织架构下的对象都会被清除出TPM。存储主秘钥种子也会被修改;这就阻止主存储秘钥被重新生成,这样以来,任何在这些秘钥下创建的对象再也不能被加载了。最后,所有者创建的所有NV索引也都会被删除。在NV这方面,TPM2.0相对TPM1.2有一些改进,在TPM1.2中只能单独删除NV。
TPM2_Clear同时还会为下一个TPM的拥有者做准备。它会复位授权值。锁定授权值也会被清除(长度为0的口令),并且Policy也被清除。所有者和背书的授权和Policy也都会被复位。存储和背书组织架构被配置成启用状态;这也是与 TPM1.2不同的地方,在TPM1.2中,所有者清除TPM后在配置新用户之前必须重启。
字典攻击逻辑中的授权尝试失败计数器也会被复位。时钟也会被复位,这样新的所有者就可以按照自己的意愿来精确的设定。用于记录启动次数的复位计数器和重启计数器都都将被复位。
一共有三种启动的情况,它们可以粗略地和PC的冷启动,由睡眠中恢复,以及休眠之后的唤醒。TPM提供了启动命令来复位或者恢复适合上述情况的TPM状态值。
为了不用在启动时以明文的方式在TPM之外保存授权秘密信息,并在启动时访问它们,TPM会复位一些特定的值并期望它们在启动时被重新配置。在最终用户可以访问之前,TPM可能会被配置一些秘钥和证书。这包括TPM厂商配置的背书主秘钥和对应的证书,以及由平台厂商配置的平台主秘钥和对应的证书。终端用户的配置步骤包括初始化存储组织架构和设置背书以及存储组织架构授权值或者Policy。
最后,通过TPM2_Clear命令取消TPM配置包括,删除秘密信息和NV索引,复位授权值和Policy,以及为准备新的所有者复位其他的一些值。