Rijndael key schedule procedure涉及RotWord
, SubWord
,和XOR
,这些都得到了支持
_mm_aeskeygenassist_si128 :
X3[31:0] ← SRC [127: 96];
X2[31:0] ← SRC [95: 64];
X1[31:0] ← SRC [63: 32];
X0[31:0] ← SRC [31: 0];
RCON[31:0] ← ZeroExtend(Imm8[7:0]);
DEST[31:0] ← SubWord(X1);
DEST[63:32 ] ← RotWord( SubWord(X1) ) XOR RCON;
DEST[95:64] ← SubWord(X3);
DEST[127:96] ← RotWord( SubWord(X3) ) XOR RCON;
DEST[VLMAX-1:128] (Unmodified)
但是,它不会返回完整的轮 key 。例如,而不是简单地执行
DEST[31:0] <- SubWord(X1)
,
我想我们应该实际执行
DEST[31:0]<-RotWord(SubWord(X3)) XOR RCON XOR X0
.
结果,_mm_aeskeygenassist_si128
之后,在轮 key 完全生成之前,我们开发者还要做一些额外的工作。
为什么上交所不提供完整的AES key 生成流程?
最佳答案
参见Key Expansion Using AESKEYGENASSIST (page 23)在英特尔的 AES-NI 白皮书中。他们指出该指令可以用作不同 key 大小的构建 block :128/192/256。它们仅显示了 128b 的示例,如您所描述的那样,在每个 aeskeygenassist
指令之后通过函数调用执行额外的工作。
AESKEYGENASSIST 已经进行了微编码(例如,Skylake 上为 13 uops,而 AESDEC
/AESENC
( http://agner.org/optimize/ ) 仅为 1 uops),因此具有不同的指令最后几个步骤对于不同的 key 大小是不同的,不会使其运行速度比当前实现的方式快得多。
Skylake 每 12 个周期有 1 个 aeskeygenassist
吞吐量,但 Nehalem 每 2 个周期有 1 个吞吐量,与 aesenc
相同。所以在 Nehalem,我猜他们确实主要在专用硬件中实现了它。这可能是解释的另一部分:在第一代实现中,更多的步骤将需要更多的硬件,或者对该指令进行微编码(Nehalem 中可能没有)以使用更多的微指令执行额外的步骤。/p>
英特尔显然并不认为按键设置对性能至关重要,因为正如我所说,他们在 Nehalem 之后降低了 aeskeygenassist
的性能。 (甚至 Sandybridge 也对其进行了微编码,每 8 个时钟吞吐量 1 个。)
针对不同的 key 大小使用不同的指令将需要更多的操作码。当时,英特尔尚未引入 VEX 前缀,因此在 AES 指令上花费更多的操作码空间会减少 future 扩展的空间。 (VEX 有大量可用的编码空间,仅使用几个多位代码来表示当前指令使用的现有强制前缀组合。)
关于assembly - 为什么SSE中的AES没有提供完整的功能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46512862/