第十一章 安全
开始本章之前,需要对加密技术有所了解。
在数据传输中,有两点需要注意,一个是数据的保密性。如果发送方A以明文方式发送消息给接收方B,则容易被第三方C截获并分析出其中的内容。为了提高数据的安全性,需要对消息加密。
第二点是数据的完整性。发送方A将消息加密发送给接收方B,但是如果这个过程中有第三方C截获并且加以篡改(比如更改其中的一些bit或是更改密文块的顺序,此时C无需解密数据),然后再发送B,在B端是无法感知数据已经被破坏。这就需要有机制保证数据的完整性,即在传输过程中没有被破坏。单纯的数据校验不能保证完整性,这是因为C可以根据修改后的数据重新生成校验。
综上,安全的数据传输方式是A将数据加密,并且给加密后的数据打上一个特有的标签(tag),然后将密文和标签一起发送给B;B接收到数据后,先要检查标签,看看数据是否被修改过,确认数据的完整性后再将数据解密。
常见的加密可以分为两类,即对称加密和非对称加密。
对称加密,也称单密钥加密,同一个密钥既可以用作加密也可以用作解密。因此对称加密的安全性不仅取决于加密算法本身,也和密钥管理相关。采用对称加密,收发双方需要在通信前协商一个密钥,并且双方负责该密钥的安全性。 非对称加密算法使用两把完全不同但又是完全匹配的一对钥匙,公钥(public key)和私钥(private key)。加密明文时采用公钥加密,解密密文时使用私钥才能完成,而且发送方(加密者)知道接收方的公钥,只有接收方(解密者)才是唯一知道自己私钥的人。采用不对称加密,收发双方在通信之前,接收方必须将自己早已随机生成的公钥送给发送方,而自己保留私钥,留待解密用。
CXL采用的是AES-GCM加密方式。
AES属于对称加密。加密技术包括两个元素:算法和密钥。以下图为例,发送方将明文P(plain text)和密钥K(key)通过加密函数,生成密文C(cipher text);接收方在接收到密文C后,与密钥K通过解密函数,恢复明文P。
再来看加密模式,因为每次只能加密一组数据,而实际的明文可能很长,会分为很多组,此时就需要对这些分组进行迭代,已完成整个明文的加密。迭代的方法就是加密模式。
说完AES,再来看看什么是MACs(Message Authentication Codes,消息认证码)。消息认证码是一种允许对接收到的消息进行身份验证的信息,确保消息来自声称的发送者,而不是伪装成他们的第三方,同时确保消息没有以某种方式修改,以提供数据完整性。
消息认证码的输入为任意长度的消息和一个发送者与接收者之间共享的密钥,它可以输出固定长度的数据,这个数据称为MAC 值。用于生成消息认证码的密钥与用于验证消息认证码的密钥相同。从这个意义上讲,它类似于对称加密系统,并且密钥必须由所有通信方事先商定或以某种安全方式共享。
回过头来看AES-GCM,GCM是认证加密模式中的一种,其中G指的是GMAC,即利用伽罗华域(Galois Field,GF,有限域)乘法运算来计算消息的MAC值;C指的是CTR。
11.1 CXL IDE
CXL完整性和数据加密(Integrity and Data Encryption,IDE)定义了为传输CXL链路的数据提供机密性、完整性和重播保护的机制。加密方案与当前行业最佳实践保持一致。它支持各种使用模型,同时提供广泛的互操作性。CXL IDE可用于在由多个组件组成的可信执行环境(TEE)中保护流量,然而,这种组合的框架不在本规范的范围内。
11.1.1 范围
本章重点介绍通过链路传输的CXL.cache和CXL.mem流量传输,以及对控制CXL.io流量的PCIe基本规范的更新/限制。
CXL.io IDE的定义基于PCIe的IDE规范 CXL.cachemem IDE可以使用基于CXL.io的机制进行发现(discovery)、协商(negotiation)、设备证明(device attestation)和密钥协商(key negotiation)。
11.1.2 CXL.io IDE
所有协议级别的重试flit都经过加密并受到完整性保护。 链路层控制flit和flit CRC没有加密,也没有完整性保护。 LCRC应该在加密flit上计算。 任何完整性检查失败的数据流都应被放弃。 必须支持多数据头功能。这允许将多个(最多4个)数据头打包到一个slot中,然后紧接着是所有数据的16个slot。 采用256-bit密钥的AES-GCM加解密 必须支持在不丢失任何数据的情况下进行密钥刷新 密钥刷新预计不经常发生。延迟/带宽受到影响是可以接受的,但不能有任何数据丢失。 支持加密PCRC机制。加密PCRC集成到标准MAC检查机制中,不消耗额外链路带宽,不增加显著额外延迟。PCRC对于CXL.cachemem IDE是强制性的,并且在默认情况下是启用的
11.1.4 CXL.cache/CXL.mem IDE架构
IDE应当以flit为单位,使用AES-GCM模式。AES-GCM采用三个输入,分别为附加身份验证数据(Additional Authentication data,AAD,在AES-GCM规范中指定为A)、明文(P)和初始化矢量(IV)。在CXL.cachemem协议中,32-bit的数据包头作为slot 0的一部分,映射到A——它没有加密,但受到完整性保护。Slot 0/1/2/3的映射到P,P经过加密并受到完整性保护。CXL.cachemem协议也支持仅有数据(data-only)的flit,在这种情况下,flit中的所有4个slot映射到P。 LCRC不加密且不受到完整性保护。在flit被加密之后,对其计算CRC IDE flit也遵守用于检测和纠正错误的链路层机制。 AES-GCM可以应用于多flit聚合,这些flit组成一个MAC_Epoch。可以聚合的flit数目取决于Aggregation Flit Count。如果启用PCRC,则32-bit的PCRC值应这些聚合的flit的末尾,以产生受完整性保护的最终P值。然而,PCRC的32-bit并不在链路上传输的。下图显示了在5个flit聚合MAC的情况下,flit内容到A和P的映射。图中深灰色部分是flit header,映射到A;浅灰色部分是数据,映射到P。
MAC是96-bit,MAC必须在H6类型的slot 0报头中传输。MAC本身既没有加密,也没有完整性保护。下图显示了在5个flit聚合MAC的情况下,flit内容到A和P的映射,其中一个flit携带MAC。图中橙色部分是MAC。
下图给出了5个flit组成MAC Epoch示例的更详细视图。顶部显示的Flit 0是在该MAC Epoch中要发送的第一个flit。该图描绘了仅受完整性保护的标题字段,以及加密和受完整性防护的文本内容。Flit 0明文0字节0是明文的第一个字节。Flit 1明文0字节0应紧跟在Flit 0明文0字节11之后。
上面示例中,flit包头字节映射到AAD如下图。在上图中,只有Flit 0,2,3有flit包头。
CXL.cachemem IDE流的初始化涉及多个步骤。第一步是建立包含两个端口的组件的标识和认证,这两个端口充当CXL.cachemem IDE流的端点。第二步是建立IDE流的密钥。在某些情况下,这两个步骤可以合并。第三,配置IDE。最后,开始IDE流传输。
CXL.cachemem IDE可以利用CXL.io IDE机制进行设备认证和密钥交换。CXL.cachemem IDE的IV(初始化矢量)构造应遵循CXL.io PCIe规范。根据AES-GCM规范,使用确定性结构的96-bit IV。
[95:92]位包含子流标识符,1000b,[91:64]位均为0。相同的子流编码用于发送和接收的flit,但端口在发送和接收流期间使用的密钥必须不同。 [63:0]位包含一个单调递增的计数器。在建立IDE流时,每个子流的调用字段最初设置为值0000_0001h,并且每次使用IV时都会递增。
11.1.7 CXL.cache/CXL.mem IDE模式
CXL.cachemem IDE支持两种操作模式。
Containment模式:此模式下,只有在完整性检查通过后,数据才会发布以供进一步处理。此模式会影响延迟和带宽。延迟影响是由于在接收并检查完完整性值前,需要缓冲多个flit。带宽影响是由于完整性值被频繁发送。如果支持并启用了containment模式,则设备(和主机)将使用Aggregation Flit Counter为5。因为此模式需要缓冲接收到的flit,所以AFC数量不会太大。 Skid模式:滑动模式允许释放数据进行进一步处理,而无需等待完整性值的接收和检查。这样可以减少完整性值的传输频率。滑动模式允许接近零的延迟开销和非常低的带宽开销。在此模式下,被恶意修改的数据可能会被软件所接受和处理,但当接收并检查完整性值后才会检测到此类攻击。因此,当使用此模式时,软件和应用程序堆栈必须能够在狭窄的时间窗口内容忍攻击,否则结果是未定义的。如果支持并启用了skid模式,则设备(和主机)将使用Aggregation Flit Counter为128。
11.1.7.1 完整性模式的发现和设置
每个端口应通过CXL IDE的capability寄存器枚举其支持的模式和其它能力。所有符合本规范的设备应支持containment模式。
11.1.7.2 操作模式的协商和设置
在启用CXL.cachemem IDE之前,在CXL IDE的capability寄存器中配置操作模式和时序参数。
11.1.8 MAC聚合规则
MAC_Epoch:一组连续的flit用于flit聚合。给定的MAC报头应包含恰好一个MAC_Epoch的标签。在发送之前,发送方应在一个MAC_Epoch(最多N个flit)中积累flit上的完整性值。 在所有情况下,发送方必须按照与MAC Epochs相同的顺序发送MAC。 下图显示了在存在背靠背协议流量的情况下,一个MAC_Epoch的MAC生成和传输示例。要发送或接收的最早的flit显示在图的顶部。因此,属于MAC_EPOCH 1的flit 0到N-1(以黄色显示)按该顺序发送。MAC是在flit 0到N-1上计算的。
发送方应尽早发送包含该完整性值的MAC报头。本规范允许在当前MAC_Epoch的最后一个flit的传输和该MAC_EpochMAC报头的实际传输之间传输属于下一个MAC_Epoch的协议flit。这可以避免由于MAC计算延迟而导致的带宽浪费。建议发送方在MAC计算完成后立即在第一个可用的Slot 0报头上发送MAC报头。在所有情况下,允许在发送先前MAC_Epoch MAC之前发送当前MAC_Epoch的最多5个协议flit。上图右侧就是发送了5个当前属于MAC_Epoch flit的情况。 接收方可以期望在先前MAC_Epoch的最后一个flit之后的从第一到第六个协议flit中的任一个flit接收到先前MAC_Epoch的MAC。还是对应上面的最多5个flit。
在containment模式中,接收方必须不释放(即给后续的功能模块)给定MAC_Epoch的flit,直到已经接收到包含这些flit的完整性值的MAC报头并且完整性检查已经通过。由于在接收先前MAC_Epoch的MAC报头之前,接收器可以接收属于当前MAC_Epoch的5个协议flit,因此接收方应缓冲当前MAC_Epoch的flit,以确保没有数据丢失。 在skid模式中,一旦接收到flit,接收器就可以解密并释放flit。MAC值应根据需要进行累积,并在MAC_Epoch中的MAC报头到达时进行完整性检查。
11.1.9提前终止MAC
对于在链路在发送Aggregation Flit Count数量后变为空闲的情况下,则不得使用如上定义的截断MAC flit。MAC标头必须是下一个MAC Epoch的一部分。允许使用截断的MAC Flit提前终止此新的MAC Epoch,见下图。规范在这里说的很拗口,直白一点就是,仅当MAC_Epoch中的flit数少于Aggregation Flit Counter的数目时才可以使用截断的MAC flit。
在提前MAC终止和传输截断MAC之后,发射机必须发送至少TruncationDelay数量的IDE空闲flit,然后才能传输任何协议flit。TruncationDelay计算公式如下:
TruncationDelay = Min(Remaining Flits, Tx Min Truncation Transmit Delay)
Remaining Flits= Aggregation Flit Count - Number of protocol flits received in
current MAC Epoch
11.1.10 Handshake to Trigger the Use of Keys
11.1.11 错误处理
CXL IDE不会影响或是要求对链路CRC错误处理和链路retry流程进行任何更改。
有关CXL.cachemem错误的详细信息记录在CXL IDE的Error Status寄存器中。当检测到CXL.cachemem IDE错误时,也会设置Uncorrectable Error Status寄存器中的相应位,并使用标准的CXL.cachemem协议错误信号机制发出错误信号。
在检测到完整性失败时:
在错误报告寄存器中记录完整性检查失败,并使用标准CXL.cachemem协议错误信号机制发出错误信号。 丢弃任何缓冲的协议flit,并丢弃所有后续的数据流,直到链路重置。 设备应防止密钥或用户数据泄露。设备可能需要实现清除数据/状态的机制,或者具有访问控制以防止机密泄露。
以下情况必须视为完整性失败:
当链路不处于安全模式时接收到MAC包头 未收到预期的MAC包头 接收到未预期的截断MAC Flit 在截断MAC flit之后,协议flit的接收时间早于预期 密钥切换后,协议flit的接收时间早于预期
11.1.12 交换机支持
支持CXL.cachemem IDE的CXL交换机必须支持用于CXL.io的Link Stream IDE。
总结:本章内容为CXL数据加解密。CXL采用AES-GCM模式进行数据加解密,CXL.io的IDE基本与PCIe的IDE一致,因此本章主要是对CXL.cachemem IDE进行约束。
后面的章节我目前不太感兴趣,就不深究了。CXL协议一刷到此结束,很多细节还没有搞清楚,留待以后再说。总的说来,想要深入了解CXL,必须先要了解PCIe。不多说了,看PCIe规范去了。