I have an implementation of AES which can cache at most a 256-bit value between encryptions. Currently, the master key is cached and the key schedule is re-computed for each and every block. Is there any intermediate ≤ 256-bit value which can be derived from the master key which I can cache and use to compute each round key faster than re-running the entire key schedule?

The implementation is in x86 assembly in 64-bit mode and uses the AES-NI extensions. This means I have the AESKEYGENASSIST instruction, which performs the following in 10-12 cycles:

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[MAXVL-1:128] (Unmodified)
  • $\begingroup$ If the CPU registers are used correctly, you do not need to cache anything in memory, as the registers store all the round keys required $\endgroup$ – Richie Frame May 12 '18 at 2:33
  • $\begingroup$ @RichieFrame It's not stored in memory anyway. However, because of interrupts and preemption, I'm currently only using privileged and optional registers (e.g. debug registers, various MSRs, etc). In order to store them all in, say, XMM registers, I would have to block access to XMM in userspace (and giving up SSE is not something I'm willing to do). I've thought of using x87 floating point registers and simply trapping them in userspace, but that'd require I emulate them in userspace which I don't want to do. $\endgroup$ – forest May 12 '18 at 2:43
  • $\begingroup$ Can't save and restore on context switch when they're in use? Specifically: on transition from one context to another using them, save and restore; on transition from a context using them to a context not using them, leave in place but make them trap; on trap, save and zero; on transition from one context not using them to another, do nothing. $\endgroup$ – Squeamish Ossifrage May 12 '18 at 13:07
  • $\begingroup$ @SqueamishOssifrage Nope. I'm implementing heavily-modified version of TRESOR (modified to support kvm and memory encryption, among other things) for a client, but I need to reduce the performance hit. $\endgroup$ – forest May 12 '18 at 21:58
  • $\begingroup$ Is that AES-128 or some other key size? For AES-128 the key is 128-bit, the first subkey is the key, and the next subkey is most naturally expressed as a function of the previous subkey. Things are more complex for AES-192 and AES-256. Also, independently: does the implementation use AESENC? $\endgroup$ – fgrieu Jun 16 '18 at 6:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.