TPM使用非易失性内存来存储两种类型的数据:
- TPM架构定义的数据结构。
- 用户或者平台相关的规范定义的非结构性数据。
TPM非易失性内存的一个应用是用于存储架构或者TPM软件规范定义的数据。这些数据包括授权值,种子,凭据以及TPM从不会暴露在安全边界之外的私有数据。除此之外,这些数据还包括计数器,时钟,以及其他用户可以读取的数据。非易失性内存也可以用于存储被配置成持续性的数据结构,比如秘钥。
本小节我们将介绍NV内存的另外一个使用案例:作为平台或者用户自定义的内存空间。因为是用户为每一个区域分配一个索引并使用这个索引来访问数据,所以有时候这又被称为用户自定义索引。
TPM1.2中包含可以存储自定义数据的用户索引。索引的大小和属性由用户来决定。用户可以不受限制地向索引的内存区域写数据。TPM为这些索引提供授权机制,可以提供基于HMAC,PCR,locality,和物理存在(physical presence)的访问控制;另外TPM提供索引的读写锁定机制。
TPM2.0在以下几个方面TPM1.2NV相关的特性:
- 一个索引有一个状态叫做“未初始化的,没有被写过”。在第一次写操作之前的读操作都将失败。更进一步,索引不能被用于policy。这样可以向这个索引的使用者保证这个索引的值一定是被具有授权权限的一方初始化过的,而不是简单默认值或者未初始化值。
- 与其他受保护的实体一样,TPM2.0的索引可以有授权值或者policy。
- 另外一个policy可以包含一个NV索引的值。这个policy可以对索引或者索引的一部分设定一个操作:比如跟policy数据对比。操作包括相等,不相等,有符号比较,无符号比较,以及检查某一位置位或者清零。
NV索引的另外一个新特性是数据类型。TPM2.0在1.2版本的非结构化数据(现在叫做普通数据)的基础上增加了另外三种类型,所以一共有四种类型:
- 普通。
- 计数器。
- 位域。
- 扩展(请脑补PCR的扩展操作)。
一个普通的NV索引和TPM1.2的索引类似。它用于存储任意长度的非结构化数据。与计数器,位域,以及扩展索引不同的是,普通NV索引对所写入的数据类型没有限制。
应用案例:存储一个秘密信息
假设一个平台包含一个必须在早期系统启动阶段可用的20字节长的秘密信息。这个信息可以被存储在一个NV索引中。索引的属性被设置为TPMA_NV_PPREAD,这表示读取这个索引需要平台授权。在系统启动早期运行的平台软件知道平台的授权信息,所以这些软件可以读取这个秘密信息。这同时也确保一旦启动软件完成启动任务之后这个秘密信息再也不会被读取。因为系统启动之后的其他软件并不知道平台授权信息,也就不能读取秘密信息了。
上述案例中TPM相关的命令如下:
* TPM2_NV_DefineSpace:创建一个普通的索引,NV内存大小为20字节,并且需要平台授权读写。
* TPM2_NV_Read:使用平台授权信息读取信息。
应用案例:存储一个证书
一个平台OEM厂商会创建一个证书,这个证书会声明平台有一个固定的背书密钥,并且平台具备一定程度的安全保证。OEM会在平台生成阶段将证书存储在NV中。其中,这个NV区域的读操作是不受限制的。但是写操作需要OEM的policy,它用于OEM安全地更新证书。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:创建一个普通NV索引,大小与证书大小相等,写操作需要平台授权,读操作授权是一个空口令。
* TPM2_NV_Write:使用平台授权(policy)。
* TPM2_NV_Read:使用空口令授权。
应用案例:存储一个通用的口令
一个用户使用同一个policy创建了一组密钥,当提供一个NV索引的授权口令时可以使用这些密钥。这样用户可以通过提供一个正确的口令来授权所有密钥的访问。同时用户只需要对NV区域做一次写操作就可以修改所有相关密钥的口令。
涉及的TPM命令如下:
1. TPM2_NV_DefineSpace:普通索引,大小为0,因为这个应用案例中并不会实际使用NV内存,设置NV索引的授权值为一个通用口令,也就是用于修改密钥授权值得policy口令。
2. 创建一个通用policy:执行TPM2_PolicySecret,并用NV索引的名称作为参数。
3. TPM2_Create:使用这个通用的policy创建多个密钥。userWithAuth属性为清除状态,这样就强制使用policy来授权密钥使用。
4. TPM2_NV_ChangeAuth:使用当前NV索引的口令来一次性修改所有密钥的授权值。
应用案例:存储一个密钥树根节点的公钥
IT管理员可以将一个公钥的哈希值存储在NV中,这个NV可以被写锁定,从而防止其他用户修改。这个哈希值用于验证另外一个公钥,这“另外一个公钥”又进一步用于验证一些签名确实来自于这个IT组织。所以,这个NV中存储的是一个证书链中根证书的公钥的哈希值。
涉及的TPM命令如下:
1. IT组织创建一个签名密钥,并对它的公钥做哈希。
2. 创建一个读操作的policy:TPM2_PolicyCommandCode指定TPM2_NV_READ命令。这个policy允许任何人读取NV索引的信息,并且不用提供任何授权信息。
3. TPM2_NV_DefineSpace:同样也是一个普通的索引,大小为哈希的大小,授权值为IT管理员的口令,口令用于写授权,读操作使用上述的policy。
4. TPM_NV_Write:使用IT管理员的授权口令授权NV写操作,将公钥的哈希值写入NV。
如下是验证签名时的操作:
1. TPM2_NV_Read命令读取公钥的哈希值。
2. 验证根证书中公钥的哈希值(在一个应用中,被验证的实体中会包含一个完整的证书链)。
3. 使用公钥来验证签名。
应用案例:存储一个HMAC密钥
在Linux系统的完整性测量架构(Integrity Measurement Architecture)的扩展验证模块(Extended Verification Module)中存储了一个HMAC密钥,这个密钥在启动早期就释放给内核,然后内核使用它验证文件的扩展属性。主要目的是看这些文件是否允许被内核加载或者使用。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:普通NV索引,大小等于HMAC密钥的大小,IT管理员口令用于写操作,读操作仍然使用上一个案例中使用的任何人可以不用授权就读的policy。
* TPM2_NV_Write:使用IT管理员口令授权NV写操作,将HMAC密钥存储到NV中。
* TPM2_NV_Read:读取HMAC密钥。
NV计数值是一个只能增加的64位数值。在对一个NV计数值执行增加命令之前,这个计数值会被初始化为这个TPM上曾经出现过的最大NV计数值。这个值既包括当前存在的计数值也包括过去曾经定义的但是现在已经删除的计数值。这样一来一个计数值就永远不会被回滚,即使是被删除后重新创建也不行。
TPM1.2用户可能会熟悉单向计数器。现在介绍的计数器与之相同,但是现在用户可以定义任意数量的计数器,数量仅受TPM存储资源的限制。
应用案例:撤销一个密钥的访问权限
有时候一个密钥的所有者可能会想撤销密钥的访问权限。密钥在创建时使用policy作为授权方式,policy可以被设定为当一个NV计数器的值与当前值相同时(NV没有增加时)可以访问密钥。这样一来,只要增加NV计数器的值就可撤销密钥的访问权限。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:计数器索引,口令设置为密钥所有者的口令,并且口令用于写授权。读操作授权为Policy,policy执行TPM2_PolicyCommandCode并选择TPM2_PolicyNV命令。这个policy可以让任何人读取计数器的值。
* TPM2_Create:创建一个密钥,密钥属性userWityAuth设置为0,这就说明必须使用policy授权密钥访问。policy创建使用TPM2_PolicyNV,参数为当前NV的值。
* TPM2_NV_Increment:撤销密钥的使用(译注:这个密钥撤销后,应该可以继续用这个NV做类似的事情)。
一个NV位域包含64位,默认情况下全部初始化为0,但是也可以选择设置为1。位域的某一位只能被写1而不能清0。
应用案例:撤销某用户使用一个多用户密钥
假设有一个密钥有多达64个使用用户,密钥的所有者想要撤销某一个用户对密钥的使用权限。创建密钥时使用一个由64个部分(64个policy摘要组成的list作为PolicyOR的输入)使用PolicyOR操作后的结果。每一部分都包含对应用户的授权信息(比如指纹或者智能卡签名信息)和NV位域中某一位。当设置NV位域的某一位之后就可以撤销对应用户对这个密钥的使用权限,因为他再也得不到正确的policy了。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:位域索引,口令为密钥拥有者的口令,口令同样用于写授权。读操作授权为Policy,policy执行TPM2_PolicyCommandCode并选择TPM2_PolicyNV命令。这个policy可以让任何人读取计数器的值。
* TPM2_Create:创建一个密钥,密钥属性userWityAuth设置为0,这就说明必须使用policy授权密钥访问。policy创建使用TPM2_PolicyNV,参数为TPM_EO_BITCLEAR。
* TPM2_NV_SetBits:设置给某一个用户分配的NV索引位,这样就撤销了这个用户的使用权限。(译注:撤销之后,似乎这个位就没什么用了?)
扩展索引在创建的时候需要选定一个哈希算法,算法在索引的整个生命周期内都是固定的。索引对应NV区域的大小与哈希算法相对应。NV区域会被初始化位全0。写这个NV区域是一个扩展操作,这与PCR的操作类似。
扩展索引最可能的应用案例就是与混合索引结合来创建灵活的PCR,后面的“混合索引”将会介绍。另外一个应用案例就是安全审计记录,因为扩展的操作可以创建一个不可逆转的密码学历史信息。
一个证书授权中心想要记录每一次它的密钥用于签名证书的使用情况。授权中心必须有办法检测到存储在硬盘上的记录的修改。它可以创建一个NV扩展索引,授权机构拥有基于policy的排他性写权限。
每次CA签名一个新的证书时,它会记录证书并将证书的摘要扩展到NV索引中。为了验证最终的记录结果,CA会遍历证书并用扩展操作重新创建记录,然后与NV索引中的值比较。为了增加额外的安全性,CA还可以获得一个针对NV索引值的签名。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:扩展索引,只能CA写的policy,以及任何人都可以读的policy。CA签名一个证书时,会将证书记录在审计账本(可以理解为一个存储区域)中,并对证书做哈希。
* TPM2_NV_Extend:将摘要增加到NV审计账本中,也就是扩展到NV索引对应的区域中。如果证书足够小,可以直接用证书做扩展操作。但是,在TPM之外做哈希,然后只对摘要做扩展应该会更快。
TPM2.0在NV方面的另外一个新特性就是混合索引。如果没有混合属性,NV索引的元数据(索引的handle,大小,属性,policy和口令)都是非易失性的;而混合索引时在易失性的内存中创建的。除了混合计数器(后面会介绍),索引的数据只有在关闭TPM时才会被写到NV区域中。前面介绍的四种索引类型(普通,计数器,位域,或者扩展)都可以成为混合索引。
当应用需要频繁对NV区域做写操作时,使用混合索引时比较合理的。因为NV技术经常会遭受被用坏的情况,TPM可能为了保护NV而拒绝频繁的写操作。易失性内存就没有这样的问题,所以混合索引的写操作可以根据具体需求来定,而不用担心受限制。
如果TPM关闭之前混合索引被删除,那混合索引的数据有可能只存在于易失性内存中。所以一个应用可以在一个上电周期内创建索引,写数据,使用数据,然后删除索引,并且不占用NV空间。
应用案例:额外的PCR
PC客户端平台的TPM厂商通常会提供24个PCR,混合索引的最简单的使用场景就是用户增加PCR的数量。因为对于TPM内置的PCR来说,PCR的索引在上电周期之间是保持不变的,但是PCR的值在重新上电后会被清零。这看起来和普通的易失性内存并没有本质区别,也就意味着PCR并不是一种稀有的资源(相对来说?)(按照TCG工作组的行话说“沙滩前沿属性”,来一波浪,什么沙滩屋,什么贝壳啦,什么“一箭钟情”啦,全都game over,哈哈哈哈哈)。
涉及的TPM命令如下:
* TPM2_NV_DefineSpace:混合索引,空口令,任何人可以读写。
* TPM2_NV_Extend:等同于TPM2_PCR_Extend.
应用案例:不同属性的PCR
一个应用可能想要使用一个PCR,但是标准的PCR都是由平台设置的固定属性的。比如说,操作系统可能想限制某一个PCR的访问,应用可能想限制PCR的授权,应用可能想用与当前PCR不同的哈希算法,或者应用想要限制只能通过扩展的locality来更新PCR。
应用可以使用自己想要的属性创建一个混合扩展索引,然后把它当作PCR来使用,应用程序结束的时候可以直接删除这个索引。需要强调的是,因为索引是混合索引,所以扩展操作并不会占用NV内存,这避免了性能和NV内存写坏的问题。、
涉及的TPM命令:
* TPM2_NV_DefineSpace:混合扩展索引,应用程序自己选择的哈希算法,使用应用程序相关的policy,可以增加更多的限制。
* TPM2_NV_Extend:应用程序按需操作。
* TPM2_NV_UndefineSpace:应用程序结束时执行。
这些PCR可以由读操作授权:授权可以是与平台不同的读写policy。这些PCR还可以用在虚拟TPM中,用于记录VM助手的状态。(参考TPM虚拟化相关的规范)
应用案例:虚拟化
一个VMM可以为每一个VM创建一个混合扩展索引。当VMM创建VM时就使用这样的索引当作VM中vTPM的PCR。当VMM启动VM时,VMM使用内部功能读取和测量VM的启动代码,然后将测量值扩展到VM相应的PCR中。
这个案例仅仅涉及到一个命令:
* TPM2_NV_DefineSpace:用于创建混合扩展索引,作为VM中vTPM的PCR。
混合的普通,扩展,以及位域索引只有在TPM正常下电时会将数据写入NV内存。然而混合计数器索引因为它不能回滚和不能丢失写操作的特性而变得很复杂。这些特性要求即使是在非正常下电的情况下,存储在易失性内存中的数据也要写入到NV存储中。
为了实现上述的目标,易失性内存中的计数值在每增加一定的次数后就会写入NV区域。这样一来,混合计数器的值可能不仅仅存在于易失性内存中,即使是在正常下电之前被删除也是如此。如果一个应用想要避免向NV写入数据,或者想了解NV写入的时间,它可以通过capability命令读取写入的时间间隔。
混合计数器另外一个复杂的地方是TPM启动。如果最近一次的计数值因为突发情况没有来得及写入NV,计数器的值会在没有写入NV的情况下更新成它能达到的最大值。这就意味着,它可能错过一些计数操作,但是永远不会回滚和错过一次计数值的实际增长。(TPM用什么来检测这种突发情况)
前面几个小结我们讨论了NV的主要属性:NV可能是普通,计数器,位域或者扩展的索引,并且NV也可以是一个混合的索引。一个NV索引还有一个独特的控制功能,这个控制与其他TPM对象如密钥的控制不同。或许最有意思的是NV索引有独立的读写控制。具体来说,每一个索引的读写控制都可以被独立配置,控制可以是索引的policy,口令授权,或者是所有者的口令和授权。
TPM还支持一组读写锁定机制。一个索引可以永久地写锁定。它也可以被读或者写锁定,直到TPM重启。一个索引可以作为一组索引中的一员被一次性地锁定(全局锁定),同样是直到TPM重启后才能解锁。
另外,许多TPM实体都收到字典攻击保护机制的保护。授权尝试失败达到一定次数之后,TPM就会拒绝执行授权,知道经过一定的时间之后才会解锁授权。一个NV索引也可以收到这样的保护,但是通过配置索引的属性取消这种保护。如果授权口令强度很高的话去掉这个保护也是可行的。
每一个NV索引在创建的时候都有一个隐含的属性:未被写过。在TPM1.2中,一个索引被创建时数据被初始化为全0。但从读取的数值来看并不能区分全零数据和未被写过的数据。在TPM2.0中,没有写过数据是一个独立的状态。一个policy可以制定索引必须或者必须没有被写过。
应用案例:只能写一次的NV索引
NV索引的创建者可能会要求索引只能被写一次,或许在(TPM)初始配置的时候。一旦被写入后,任何知道正确口令的人都可以读取。
为了实现这个功能,可以创建一个ORpolicy,这个policy是两部分执行OR操作的结果。第一部分保证只有在NV没有被写过时才能执行NV Write命令。第二部分则用于允许在提供口令的情况下执行读操作。
下面是具体的操作步骤:
1. 创建包含两个项目的policy:
* TPM2_PolicyCommandCode(TPM2_NV_Write)以及TPM2_PolicyNvWritten(writtenSet clear)。
* TPM2_PolicyCommandCode(TPM2_NV_Read)以及TPM2_PolicyPassword。
2. TPM2_NV_DefineSpace,创建一个普通的索引,以及读写policy。
当用户创建一个NV索引时,会为索引分配一个索引值。在TPM1.2中,这个值中的某些位有特殊的性质,比如说D位用于锁定。在TPM2.0软件规范中,NV索引值除了有一个整体上的范围之外没有对具体的位域定义特殊含义。TPM不会通过索引值来定义索引的属性。但是,一些平台相关的规范或者全局的TCG注册处可以制定特殊的索引值。
举例来说,TCG注册处会为TPM厂商(0-0x3fffff),平台厂商,以及背书和平台证书分配handle。它还会位平台相关的规范保留handle范围,比方说PC客户端,服务器,移动,和嵌入式平台。所有这些范围都是根据惯例来分配的,TPM不能以任何形式强制它们。
使用案例:标准证书
我们期望TCG基础设施工作组将会定义存储背书密钥证书的标准NV索引。在TPM1.2中有两个这样的证书相关的索引,一个用户TPM厂商,另外一个用于平台OEM。TPM2.0则更灵活,它支持不同的密钥算法甚至时不同的证书创建模板。
尽管前面介绍的NV索引值都是根据惯例来分配的,TCG工作组也可以分配一些具有隐含的硬件属性的NV索引值。举例来说,TPM可能包含用于通用IO的特殊的硬件封装引脚,这在软件和平台规范中又叫做GPIO引脚。平台规范来决定这些GPIO引脚的属性,包括以下内容:
- 引脚的数量。
- 给引脚分配一个NV索引值。
- 引脚是强制性的还是可选的。
- 引脚是固定的输入或者输出,又或者是可编程配置的。
- 引脚的输出是易变的或者持续性的。
- 引脚的索引值是TPM厂商在生产阶段通过固件设定的,还是终端用户必须通过TPM_NV_DefineSpace命令来设定。
虽然NV数据代表了硬件引脚,但是NV的元数据与其他的索引相同。这就是说GPIO拥有完全的NV索引控制机制,包括授权值或者policy,读写控制,以及锁定特性。
TPM实体的名称决定了实体的唯一性,并且用于授权。对于NV索引来说,它的名称就是它公共区域的哈希,公共区域包含索引值(handle),属性(包含是否已经被写过),policy和大小。
TPM2_PolicyNV允许一个NV索引用于Policy。policy可以基于一组针对这个索引的逻辑或者算术运算构建。如果Policy仅仅是基于NV索引的值,安全性会有所降低:一个攻击者可能会删除这个索引然后用具有不同访问权限的索引来代替。基于这个原因,TPM2_PolicyNV使用索引的名称。
现在我们介绍一个对我们理解有帮助的例子,假设你创建了一个NV位域索引用于密钥撤销。密钥的policy包含TPM2_PolicyNV操作,只有当NV的第0位是清除状态时才会满足policy。NV索引的policy指定只有另外一个私钥的所有者可以写这个索引(TPM2_PolicySigned)。为了撤销这个密钥,另外一个私钥的所有者需要签名一个随机值来满足NV索引的policy,然后将第0位设置为1(TPM2_NV_SetBits)。
现在假设一个攻击者试图恢复密钥的访问权限。首先,攻击者不能清除NV索引的第0位,因为NV索引本身的特性决定了这些比特位只能被设置不能被清零。因此,攻击尝试一些更有希望的方法:他们可以删除这个索引然后重新创建一个名称与之前相同的索引。这个操作会因为TPM2_PolicySigned命令不能作用于一个没有被写过的NV索引而失败。反过来,攻击者也不能写NV索引,因为他们不能满足NV索引的policy。
攻击者的最后一招如下。他们删除这个索引然后重新创建索引,这一次索引使用他们可以满足的policy。然后他们可以写这个NV索引让第0位为0(译者理解:这里有一个隐含的重要信息:攻击者在重新创建时设置0位的初始值位0,似乎有点绕。回忆以下NV位域部分,创建的时候可以选择比特位是1),这样一来攻击这就可以通过TPM2_PolicyNV来满足密钥的policy。因为此时第0位的值为0,看起来policy确实可以满足。但是,因为攻击者在重新创建索引h后对索引写操作本身就导致索引的名称变化(请继续看后面的介绍,然后反过来再全局理解一下)。因为TPM2_PolicyNV命令会使用索引的名称,所以攻击永远不可能满足密钥的policy。
总结一下,“删除和重新创建索引”的攻击方法不可行是因为以下两个TPM的特性:
- 如果NV索引没有被写过就不能用于policy。
- NV索引本身的policy使用整个名称,而不仅仅是索引的handle。
应用案例:只能写一次,永远可以读的NV索引
用户想要创建一个只能写一次而且可以被任何人读的NV索引。一个典型的例子就是用证书给TPM做初始配置。
索引的policy由两个部分执行PolicyOR操作后构成。第一部分只有在NV没有被写过并且所有者提供正确的口令后才满足,并且它只允许NV写命令。第二部分只要在NV被写过之后就可以满足,当然只能使用NV读命令。
另外一个微妙的地方是,当索引被写过之后它的名称也发生变化了,这是因为索引的公共部分包含了written整个属性。
应用案例:保护一个Policy的秘密信息
一个policy的秘密信息允许将一组对象的授权信息绑定到一个秘密信息。比如说,一组密钥可以拥有相同的policy,只要知道一个NV索引的授权口令就可以满足这些密钥的policy。这个policy会使用NV索引被写过之后的名称。
注意:TPM2_PolicySecret命令用于将policy与NV索引的口令绑定。而TPM2_PolicyNV将Policy与NV索引指向的数据绑定。
如果NV被写过之后名称没有发生变化,一个攻击者就可以删除索引然后创建一个新的名称相同的索引,但是使用攻击者自己的秘密信息。这样就能获取密钥的访问权限。这种攻击不能成功是因为攻击者的索引没有被写过,而一旦写过之后名称又会发生变化,进而就不能满足密钥的policy。
上述描述的一个假设就是NV索引的policy要能过阻止攻击者写索引。比如就像我们在前面的例子种提到的,NV的写policy要求一个公钥认证(TPM2_PolicySigned)。
注意:假设写入NV索引种的数据对授权没有影响,仅仅是影响到NV所有者能不能写索引。那这个密钥就是与NV的口令绑定,而不是与NV种的数据绑定。
签名的例子展现了NV一个有趣的属性。你可以创建一个别人没法复制的NV索引。索引的名称包含了是否被写过这个属性,设定NV相关的policy时只有你可以写这个索引,因为写操作附带着名称的变化,这也就是说只有你能创建索引的名称。这就保证了policy只能跟你创建的索引关联,而不是与攻击者创建的索引。
更进一步说,相同NV索引及其名称可以在多个TPM上创建。
应用案例:复制一组密钥
在之前的应用案例种,一组密钥的授权与NV索引的口令绑定。一个用户可以将一组密钥复制到另外的TPM种。然后用户可以在这个TPM种创建相同的NV索引及其名称,这样一来密钥的policy在新的TPM上就可以被满足。
TPM的微妙之处是用户并不能真正地改变一个TPM对象的口令。TPM2_ObjectChangeAuth命令可以使用新的口令创建一个TPM对象,但是原有的对象仍然存在。用户可以删除所有的对象副本,但是TPM并不会强制这样做。
但是NV索引并不会有这些奇怪的性质。索引仅仅存在于TPM中,它们的上下文不能被保存或者是以任何形式存储到TPM之外。因此,TPM2_NV_ChangeAuth真得会改变NV对象的口令。
TPM API定义了一组针对NV的命令。TPM2_NV_DefineSpace用户创建NV索引。命令调用者指定NV元数据,这些元数据包括普通索引的大小,policy,属性,以及口令。我们之前也解释过,新创建的索引是没有被初始化过的,或者说是没有被写过的。因此,一个新创建的索引并没有数据。
NV写操作相关的命令如下:
- TPM2_NV_Write用于写一个普通的NV索引。索引的属性决定是否可以写NV索引的部分内存空间。
- TPM2_NV_Increment用于增加一个NV计数器索引的值。根据NV索引属性和计数器当前的值,这个操作可能会产生一个向非易失性内存写数据的操作。
- TPM2_NV_Extend用于将任意数据(并不一定是哈希值)扩展到NV扩展索引中。
- TPM2_NV_SetBits用户设置NV位域索引的值。它会将命令输入值与当前值做OR操作。输入全0是合法并且有用的。它可以让索引变成被写过的同时被初始化为0。
TPM2_NV_Read可以读取任意的NV索引对应的数据。一个读操作要求这个索引已经至少被写过一次。TPM2_NV_ReadPublic可以读取一个索引的公共数据。这个命令与会话审计特性结合之后,用户就可以获得一个NV索引公共区域的哈希值,从而证明它的属性。
还有一些专门用于锁定索引的命令。索引的属性决定了它是否可以被锁定:
- TPM2_NV_WriteLock可以用于锁定一个索引,索引可以到TPM下次重启后结束或者永久性的。
- TPM2_NV_GlobalWriteLock可以锁定一组索引,同样是可以到TPM下次重启后结束或者永久锁定。
- TPM2_NV_ReadLock用于锁定索引的读操作,锁定之后索引只能在TPM重启之后才能被读取。
TPM2_NV_ChangeAuth用户改变索引的口令。TPM2_NV_Certify可以为索引的数据创建一个签名。这个命令在PC客户端规范中是可选的。但是通过在审计会话中读取索引可以得到一个经过签名的审计摘要,这与TPM2_NV_Certify的结果类似。
TPM2.0有四种类型的NV索引:普通(非结构化的数据),位域,计数器,和扩展数据索引。一个索引可以通过标准的TPM口令或者policy控制机制被读写。混合索引通常情况下只存在于易失性内存中,但是正常的TPM关闭可以将其中的数据存储到非易失性内存中。这个特点可以避免产生性能和NV空间被写坏的问题。当一个索引被创建后,它具有一个没有被写过的状态。如果没有被写过,NV数据就不能被读取或者用于policy中,“未被写过”这个状态可以被用于一个policy中。
NV最基本的应用包括给TPM设备初始配置证书或者公钥。高级一点的应用是将NV授权信息应用于一个policy中,然后让多个TPM实体共享这个policy。一个使用位域索引或者计数器索引的policy可以被用于撤销密钥访问权限。一个扩展的索引提供与PCR相同的特性,它可以支持不同的算法,支持授权,并且具有相同的生命周期特性。
NV索引有独立的几组命令和属性用于控制授权,读写锁定,以及字典攻击保护。