架构
KPIO 的架构跟Opal 的架构不同。在原本的Opal的架构下,自加密引擎的密钥是在存储设备种生成并保存的,这些密钥的保护范围是LBA (range start & range length)
但是在KPIO的架构下,KPIO 允许用户为存储设备注入加密密钥,并且为对应的IO CMD 绑定注入的加密密钥,下图展示了KPIO 架构下为注入密钥并绑定IO CMD 的过程

图例解析
- host的KPIO 管理应用从 Key Management Service(密钥管理服务)获取eMEK
- host 向存储设备注入密钥MEK,并为这把密钥绑定对应的ID 和 槽
- 存储设备验证密钥,验证通过后将密钥绑定到对应的槽中
- 绑定完密钥后,通知host 已ready
- 这时host 的I/O 读写命令已经可以指定对应的加密密钥MEK 和 key id了
- 存储设备用host 指定的密钥,来加密/解密这一笔rw CMD 的数据
KPIO架构中还规定(只列spec 中比较重要的):
1.host 注入的密钥仍有与lba 相关联的功能
2.host 注入的密钥会在存储设备的断电会丢失
3.也需要支持KEK
4.支持对KEK 进行锁定,在reset 事件下重置锁定
5.支持MEK 的注入(上述提到的密钥注入功能)
6.MEK 可擦除
Key Generation(密钥生成)

对应密钥生成,KPIO spec 其实没有特别多的规定,因为KMS (key management service)可以不存在存储设备内部,因此,图三只是简单的表达了密钥生成的过程,实际过程中需要具体问题具体分析,spec 的重点也不在这里。
KEK Provisioning Model(KEK 提供模型)
这一部分同上,模型提供的具体细则在KPIO spec 规定之外,但是至少遵循下面两个传输规则的一个
- Static Pre-Shared Plaintext Key Encryption Keys
- PKI-based Key Encryption Keys Transport (这个需要device 支持X.509 证书)

Kek 明文传输step 解析
1.host向KMS 发送获取Kek的req
2.KMS 回复结果给host
3.host 通过KMIP 协议的import 操作将注入kek的req发给device
4.device 保存kek和相关的数据结构
5.返回import的结果
备注:
1.如果device 支持两种kek 传输方式的一种,那么device 就要支持KEK 注入功能
2.如果采用明文传输的方式。spec 强烈建议device 在安全可信的环境下进行,如果不处于安全可信的环境,那么最好是使用安全协议比如:SPDM 的Secure Session 进行传输
Updating KEK Using a Previously Provisioned KEK
前提条件:至少支持一种keywrap 算法(比如AES_256_keywrarp)

- host 发送req 给KMS 获取新的KEK
- KMS 检索新的KEK,并用老的KEK加密新的KEK
- KMS 返回结果
- host 向device 发送import 操作的请求,从而提供新的KEK 给host
- device 搜索旧的KEK并且用旧的KEK 来解密新的KEK
- device 用新的KEK 替换旧的KEK
- device 将KEK import的结果返回给主机
MEK Injection
同理,需要支持至少一种keywrap算法
支持KPIO的device 不能将注入的MEK 存到非易失性存储介质中,且power cycle 后,所有注入的MEK都要被清除
TCG reset不应该导致从易失性存储介质把注入的MEK给清除

- host 发req给KMS 获取MEK
- KMS 检索MEK和KEK并用KEK来加密MEK
- KMS将加密后的MEK和相关信息返回给host
- host向device 发送Import 操作的请求,从而提供MEK给device
- device 通过host 提供的信息(比如MEK's KMIP KeyUID)来搜索KEK
- device 用搜索到的KEK 来解密host 传过来加密的MEK
- 将解密的MEK inject到device的key cache 里,并与key tag 和 NSID 关联起来
- device 回复结果
Key Selection Theory of Operation
支持KPIO的设备应该支持multi NS 跟支持独立的MEK。并且需要注意的是key tag再NS 内部是唯一的

架构解析中规定了read & write CMD 在KPIO 下的行为
Write CMD
前提条件:host已经进行过MEK inject的操作,并且有使用MEK的需求
- host选择NS 并岱山给特定的KeyUID和Key。这个例子中是NS1,KeyUID_1
- host 查找NSID 和KeyUID 关联的Key tag。这个例子中是KeyTag_1
- host 将带有前面两个step参数的write CMD 传给device
- device 查找对应的key。在这个例子是Key_1
- device 用Key_1 来加密这笔write CMD 传输的data
- 可选,如果device 支持 Incorrect Key Dectection, device 还可以写入一些metadata跟着加密数据一起发送到非易失性存储介质中,当处理read CMD的时候可以用这些metadata来帮device识别目前是否有用不正确的密钥。注意,在这种情况下,device不能确定错误的密钥是原本写操作造成的还是读操作造成的,仅仅是与读数据相比,写入的时候用了不同的密钥
- device 将加密后的数据存到非易失性存储介质中
Read CMD
- host选择NS 并岱山给特定的KeyUID和Key。这个例子中是NS1,KeyUID_1
- host 查找NSID 和KeyUID 关联的Key tag。这个例子中是KeyTag_1
- host 将带有前面两个step参数的readCMD 传给device
- device 查找对应的key。在这个例子是Key_1
- device 用Key_1 来解密这笔read CMD 想要读的data
- 可选,如果device 支持 Incorrect Key Dectection, device 还可以写入一些metadata 帮助device在read期间判断对之前相同的lba range 写入的密钥是否不同。这个操作需要metadata的信息,在这个例子中是Key_1和KeyUID_1。如果device检测到了不正确的密钥,则应该返回error,这个行为基于设计这个功能的厂商实现
- device 将解密后的数据返回给host