在TPM的应用中,审计就是记录主机和TPM之间命令和命令响应参数的过程。TPM宿主系统负责维护这些记录,它们可能被存储在内存或者硬盘中。后续一个审计者可以使用TPM来认证这个记录的完整性(没有被篡改)和真实性(记录的内容确实是TPM相关的传输记录)。
审计的基本原理与使用PCR认证类似。TPM会将命令和命令响应参数的哈希值扩展到审计摘要中。审计师可以请求一个签名过的审计摘要然后验证签名和证书链。然后审计师就可以遍历本地的审计记录来验证它的完整性。
审计总是会记录成功执行的命令和命令响应的参数。成功执行的命令的要求大大简化了审计的实现。(TPM1.2中没有这样的要求,这就导致了许多corner case,比如,命令的失败是因为审计的结果只有部分被更新,审计部分更新的原因又是另外一个命令没有执行成功等等类似的例子。)
这一章首先解释为什么需要审计,然后描述审计的类型,最后深入介绍审计机制的实现细节。
为什么审计师要认证一个TPM命令及命令响应参数的列表?这一小节将提供几个案例来说明,这些案例包含审计一个单独的命令和审计一系列连续的命令。
最简单的情况是,TPM可以审计一个命令。某种意义上说,这是会对PCR值签名的TPM 引用(Quote)的一般化操作。实际上,你可以使用审计来做Quote操作:启动一个审计记录,读取一组PCR的值,结束审计记录,然后请求一个签名的审计摘要。尽管对于PCR认证来说,使用TPM2_Quote更简单,但是这个命令不能用于引用NVPCR(参考11章,如何将NV当做PCR来用)。审计是引用NVPCR的唯一方式。
虽然已经有了获取PCR值的签名的解决方案(TPM_Quote命令),但是审计提供了一种略微复杂但是灵活得多的基本类似基本功能。
应用案例:我正在连接哪一个TPM?
审计师想要精确地知道TPM的属性:设备生产商,固件版本,等等。审计师可以启动一个审计记录,运行几个TPM2_GetCapability命令来读取感兴趣的实行,然后验证审计记录,从而确保这些命令响应都是合法的。
涉及到的TPM命令如下:
* TPM_StartAuthSession:启动一个用于审计的会话。
* TPM2_GetCapability:设定审计属性,然后读取设备厂商和估计版本信息,然后通过审计记录相应的结果。
* TPM2_GetSessionAuditDigest:获取一个针对审计记录哈希值的签名。审计师使用这个签名来验证包含TPM相关信息的记录没有被非法篡改。
应用案例:一个NV索引,NV计数器,或者NV位域索引的状态是什么?
标题中提到的这些NV索引可以用于通过实体的Policy撤销实体的使用。这样的Policy会使用TPM2_PolicyNV命令,参数可以是计数器或者位域索引。第14章介绍了Policy的相关应用。这里我们假设,命令调用者担心NV索引很可能没有被正确更新。比如说,调用者想要确保一个计数器确实被增加了或者位域的某一位被置位了。嗲用者就可以审计这个索引的读操作并获取一个经过签名的NV索引值摘要。在NV使用HMAC授权的情况下,命令响应的HMAC本身也提供了响应数据的完整性。但是,如果索引使用口令或者Policy来授权,或者调用者没有HMAC密钥的情况下,审计就可以提供调用者想要的完整性。
涉及到的TPM命令如下:
* TPM2_StartAuthSession:启动一个用于审计的会话。
* TPM2_NV_Read:设置会话的属性,然后读取用于Policy的NV索引。调用者保存审计的记录结果。
* TPM2_GetSessionAuditDigest:获得一个针对记录摘要的签名。调用者使用签名验证审计记录中包含的NV数据没有被修改过。
应用案例:NV索引用作PCR
在第11章中我们已经介绍过,一个混合的扩展NV索引可以用于实现超过平台指定数量的PCR。这些PCR不能通过TPM2_Quote命令被审计,但是一个签名过的审计可以提供与之等价的完整性。
涉及到的命令如下:
* TPM2_StartAuthSession:启动一个用于审计的会话。
* TPM2_NV_Read:设置会话属性,然后用作PCR的索引值。调用者保存审计的记录结果。
* TPM2_GetSessionAuditDigest:获取一个针对记录摘要的签名。调用者使用这个签名来验证审计记录中包含的NV PCR值没有被篡改过。
以下是用于审计的TPM命令的总结。参考TPM2.0规范的第3部分来了解完整的命令集和API详细信息:
- TPM2_StartAuthSession用于启动一个可以用于审计的会话。
- TPM2_GetSessionAuditDigest能够返回会话的审计记录的哈希值,还有一个可选的针对这个哈希值的签名。
- TPM2_GetCommandAuditDigest能够返回命令的审计记录的哈希值,还有一个可选的针对这个哈希值的签名。
- TPM2_SetCommandCodeAuditStatus决定了命令审计摘要中包含哪些命令。
TPM软件库支持两种类型的审计:命令审计和会话审计。
命令审计有两个重要的特点,这与TPM1.2的审计相同。
首先,命令审计是针对一个命令的操作。大多数的命令都包含这样一个属性,当设置这个属性时就表明TPM应该审计所有这个命令的实例。TPM有一个全局的,设备范围内的审计摘要,一个审计师可以请求针对这个摘要的签名。
其次,命令审计在PC客户端TPM规范中是可选的。在TPM1.2中,为了降低开发和测试开销,设备生产商通常会忽略可选的命令。因此,硬件TPM1.2都没有实现命令审计。软件也不能假设TPM2.0设备实现了命令审计。
应用案例:审计用作CA的TPM
一个TPM可以被用作一个证书授权机构(CA)。作为一个硬件安全模块,TPM对私钥的保护远远好于一个软件的保护方案。一个CA可能想要一个所有它签名过的证书的列表。通过设定TPM2_Sign命令的属性,审计师可以验证签名列表并及检测任何非法修改。
涉及的TPM命令如下:
* TPM2_SetCommandCodeAuditStatus:让TPM2_Sign被审计。
* TPM2_Sign:将TPM作为CA来对证书签名。调用者负责保存审计的记录结果。
* TPM2_GetCommandAuditDigest:获取一个针对审计摘要的签名,摘要包含证书的哈希。
会话审计是TPM2.0的新功能。这个功能在PC平台规范中是强制性的。因此,这个功能是广泛可用的。
就像名字显示的一样,会话审计提供真对一个会话的审计摘要。一个授权会话可以额外作为一个审计会话,只需要简单地配置会话的audit属性即可。这也就是说,一个会话在启动时并不是一个审计会话,而是在audit属性设置之后变成一个审计会话。对于那些不需要授权的命令,或者想要将审计和授权解耦开时,这个审计会话可以是一个功能单一的会话。
举例来说,TPM2_Create要求一个授权会话来授权父密钥的访问。这个会话可以同时被标记成一个审计会话。另外一种情况是,TPM2_Create命令包含第二个专门用于审计的会话。TPM2_GetCapability命令本身不需要授权,所以通常情况下这个命令在执行时没有会话参数。但是,可以提供一个独立的会话用户审计。
如果一个命令需要多个会话,那么只有其中一个被标记为审计会话。
本章的开始我们提到,命令和命令响应参数的哈希值将被记录到宿主系统上,并且审计师可以验证经过签名的记录。这一小节概括了相关的操作步骤:
- 审计师首先从命令执行时存储在宿主机上的审计记录中,提取出一组命令和命令响应参数。然后计算这些参数的哈希值。
- 幸运的是,命令参数和命令响应参数用于审计的哈希计算与用于授权的计算方式相同。首先将参数序列化成字节流,然后针对这个字节流做哈希。
- 对于一个命令来说,包含序列化后参数的哈希计算应该是直接了当的。一个TSS将会向用户暴露命令参数序列化的接口来助力命令参数授权操作。命令响应就有点棘手来,因为TSS默认会反序列化响应但是不会序列化它们。一种用于审计记录的方式审计记录包含序列化的命令响应和命令响应参数。审计师可以使用TSS来反序列化(序列化的)命令响应,然后和审计记录中的命令响应参数比较。如果TSS没有反序列化的接口,或者弱审计记录中没有序列化的命令响应,那么审计者别无选择,只能编写或者命令响应参数序列化函数或者从第三方获取这些函数。因为TPM本身是包含这些函数的,所以可以从将来可能出现的一个软件TPM的开源实现中找到相关的函数。
- 这一步之后,审计者应该已经获得了与命令和命令响应的参数在密钥学上对应的哈希值。
- 审计者执行与扩展等价的操作,将第1步中每个命令和命令响应参数的哈希值扩展到审计摘要中。
- 验证数字签名。审计者计算出的审计摘要通过TPM签名和一个公钥来验证。
- 审计者遍历证书链直到一个可信的根证书,从而建立公钥的可信链。
为了用于后续的审计,相关的公钥很有可能被缓存起来。
应用案例:使用TPM保护一个应用的审计记录
TPM的审计功能除了可以审计TPM函数外,还可以用于保护一个应用的审计记录。应用创建一个NV扩展索引来记录它的相关事件。每次应用记录一个事件时,它首先将事件扩展到NV索引中。之后,应用可以获得一个NV索引数据的签名,并且可以用这个签名验证事件记录没有被篡改。
涉及到的TPM命令如下:
* TPM2_NV_DefineSpace:创建一个混合扩展索引。
* TPM2_NV_Extend:扩展并记录应用事件。
当应用需要验证审计记录时:
* TPM2_StartAuthSession:启动一个审计会话。
* TPM2_NV_Read:读取事件的摘要。
* TPM2_GetSessionAuditDigest:获取NV数据的摘要。
如果TPM2_NV_Certify命令可用,它可以用于获取一个针对NV数据的签名,但是并不是所有的TPM上都支持这个命令。
我们可以通过TPM2_GetSessionAuditDigest命令获取会话的审计摘要。在一个典型应用案例中,需要提供一个签名密钥然后就会返回签名值。
上述提到的数字签名不仅仅包含审计摘要。就像其他的认证函数一样,TPM会将审计摘要打包到一个包含其他信息的数据结构中。TPM规范的第2部分描述了这个数据结构,其中TPMs_ATTEST包含了一个TPMU_ATTEST联合体,这个联合体又是一个TPMS_SESSION_AUDIT_INFO结构体。
第12章有介绍TPMS_ATTEST,它包括TPM_GENERATED,符合要求的签名密钥名称,以及“额外的数据”,时间,固件信息。它们的安全属性都是相同的(安全属性是啥子个意思?)。
TPMS_SESSION_AUDIT_INFO包含期望的会话审计摘要。它同时还包含一个指示“排他性”的会话标志。具体参考下一小节。
排他性(或者叫做独占性)的审计可以允许审计者在验证一系列审计记录中连续的一系列命令,这些命令中间没有没有被插入其他命令。一个调用者在一次命令调用中只能定义一个会话为排他性会话。这是通过设置审计会话中的auditExclusive属性来实现的。假设之前没有排他性会话,然后一个会话变成排他性会话,那么这个属性会在命令响应中回显。
一旦一个会话变成排他性会话,它就可以用于后续的几个命令执行。但是,中间过程中任何一个不使用这个排他性审计会话的命令都将导致这个会话不再是排他性会话。 这就是说,一个排他性会话并不会阻塞另外一个命令,而是会记录这个被插入的命令。
当审计摘要被返回以后,这个数据结构中就包含一个标志位,exclusiveSession,如果没有被插入的命令这个标志就为真。
应用案例:确保PCR在一些列命令中间没有被修改
一个用户想要在一个特定可信的状态时运行一系列命令。PCR的值表征了平台的可信状态。因此用户想要确保再此期间PCR的值没有变化。用户会在排他性的会话中执行这一系列的命令。如果一个调用者想要在插入的命令之后继续使用排他性会话执行计划中的命令,TPM会报错,因为会话本身的属性和命令的会话属性已经不匹配了。
涉及到的TPM命令如下:
* TPM2_StartAuthSession:启动一个会话用于排他性审计。
* 执行命令序列,序列不能被PCR扩展操作命令打断。并设置会话属性中的audit和auditExclusive位。
* 如果中间出现一个非法插入的命令,命令会返回TPM_RC_EXCLUSIVE。
TPM的审计就是记录命令和命令响应参数的过程。TPM记录这些参数并使用与PCR类似的操作扩展审计记录,宿主系统会保存这些参数。之后,TPM可以返回一个签名过的审计记录摘要。接受者可以验证签名,这样一来也就验证了审计记录的完整性。
TPM提供两种审计类型。命令审计会记录一组指定命令的执行实例,但是不关心命令使用的会话。会话审计则记录所有使用这个会话的命令,不管具体的命令是什么。一个排他性审计会话允许命令响应接收者检测,会话有没有被不使用审计的命令打断过。因为有这样的命令插入后,后续的命令会返回错误代码,所以排他审计会话可以保证一系列计划的命令中没有被插入其他命令(表达有些别扭,参考上面的例子吧)。