Rijndael key schedule procedure涉及RotWordSubWordXOR,它们都受。
_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 。

SSE为什么不提供完整的AES key 生成过程?

最佳答案

请参阅英特尔AES-NI白皮书中的Key Expansion Using AESKEYGENASSIST (page 23)。他们指出,该指令可用作不同 key 大小的构造块:128/192/256。它们仅显示了128b的示例,在您描述的每个aeskeygenassist指令之后对函数调用进行了额外的工作。

AESKEYGENASSIST已经进行了微编码(例如,Skylake上为13 uo,而AESDEC/AESENC(http://agner.org/optimize/)仅为1 uops),因此使用不同的指令对不同的 key 大小执行不同的最后几步操作不会使它运行得更快当前实现的方式。

Skylake每12个周期aeskeygenassist有1个吞吐量,但是Nehalem每2个周期1个,与aesenc相同。因此,在Nehalem中,我想他们确实确实在专用硬件中实现了它。这可能是解释的另一部分:在第一代实现中,更多的步骤会占用更多的硬件,或者使该指令经过微编码(这可能不在Nehalem中),以便用更多的指令来执行额外的步骤。

英特尔显然并不认为 key 设置对性能至关重要,因为正如我所说,在Nehalem之后,它们降低了aeskeygenassist的性能。 (甚至Sandybridge也对它进行了微编码,每8个时钟吞吐量中有1个。)

针对不同的 key 大小使用不同的指令将需要更多的操作码。那时,英特尔尚未引入VEX前缀,因此在AES指令上花费更多的操作码空间将减少将来扩展的空间。 (VEX具有大量可用的编码空间,仅对当前指令使用的现有强制性前缀组合使用几个多位代码。)

关于assembly - 为什么SSE中的AES无法提供全部功能?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46512862/

10-11 18:56