LOADIWKEY

Load Internal Wrapping Key With Key Locker

stableVMJITAOTinstruction

Encodings

OpcodeInstructionOp/En64-bitCompat/LegacyDescription
F3 0F 38 DC 11:rrr:bbbLOADIWKEY xmm1, xmm2, <EAX>, <XMM0>AValidValidLoad internal wrapping key from xmm1, xmm2, and ER XMM0.

Operand encoding

Each mode is a value of the Op/En column above. It says which field of the encoded instruction carries each operand, in the order they are written, and whether the instruction reads it, writes it or both.

A

  1. modrm.reg lecturaModRM byte, reg field (bits 5-3)
  2. modrm.rm lecturaModRM byte, r/m field (bits 2-0); with the SIB byte and the displacement when the mod field asks for them
  3. EAX lectura
  4. XMM0 lectura

Measured cost

Loading measurements from arch-data...

Flags named

Description

The LOADIWKEY1 instruction writes the Key Locker internal wrapping key, which is called IWKey. This IWKey is used by the ENCODEKEY instructions to wrap keys into handles. Conversely, the AESENC/DECKL instructions use IWKey to unwrap those keys from the handles and help verify the handle integrity. For security reasons, no instruction is designed to allow software to directly read the IWKey value.

IWKey includes two cryptographic keys as well as metadata. The two cryptographic keys are loaded from register sources so that LOADIWKEY can be executed without the keys ever being in memory.

The key input operands are:

The implicit operand EAX specifies the KeySource and whether backing up the key is permitted:

storage.

A KeySource of 0 indicates that the key input operands described above should be directly stored as the internal wrapping keys. LOADIWKEY with a KeySource of 1 will have random numbers from the on-chip random number generator XORed with the source registers (including XMM0) so that the software that executes the LOADIWKEY does not know the actual IWKey encryption and integrity keys. Software can choose to put additional random data into the source registers so that other sources of random data are combined with the hardware random number generator supplied value. Software should always check ZF after executing LOADIWKEY with KeySource of 1 as this operation may fail due to it being unable to get sufficient full-entropy data from the on-chip random number generator. Both KeySource of 0 and 1 specify that IWKey be used with the AES-GCM-SIV algorithm. CPUID.19H:ECX[1] enumerates support for KeySource of 1. All other KeySource encodings are reserved.

  1. Further details on Key Locker and usage of this instruction can be found here: https://software.intel.com/content/www/us/en/develop/download/intel-key-locker-specification.html.

Operation

LOADIWKEY

IF CPL > 0              // LOADKWKEY only allowed at ring 0 (supervisor mode)

     THEN #GP (0); FI;

IF EAX[4:1] > 1         // Reserved KeySource encoding used

     THEN #GP (0); FI;

IF EAX[31:5] != 0       // Reserved bit in EAX is set

     THEN #GP (0); FI;

IF EAX[0] AND (CPUID.19H:ECX[0] == 0) // NoBackup is not supported on this part

     THEN #GP (0); FI;

IF (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0) // KeySource of 1 is not supported on this part

     THEN #GP (0); FI;

IF (EAX[4:1] == 0) // KeySource of 0

     THEN

     IWKey.Encryption Key[127:0] := SRC2[127:0]:

     IWKey.Encryption Key[255:128] := SRC1[127:0];

     IWKey.IntegrityKey[127:0] := XMM0[127:0];

     IWKey.NoBackup = EAX [0];

     IWKey.KeySource = EAX [4:1];

     RFLAGS.ZF := 0;

     ELSE               // KeySource of 1. See RDSEED definition for details of randomness

     IF HW_NRND_GEN.ready == 1                         // Full-entropy random data from RDSEED hardware block was received

            THEN

                   IWKey.Encryption Key[127:0] := SRC2[127:0] XOR HW_NRND_GEN.data[127:0];

                   IWKey.Encryption Key[255:128] := SRC1[127:0] XOR HW_NRND_GEN.data[255:128];

                   IWKey.IntegrityKey[127:0] := XMM0[127:0] XOR HW_NRND_GEN.data[383:256];

                   IWKey.NoBackup = EAX [0];

                   IWKey.KeySource = EAX [4:1];

                   RFLAGS.ZF := 0;

            ELSE        // Random data was not returned from RDSEED hardware block. IWKey was not loaded

                   RFLAGS.ZF := 1;

     FI;

FI;

RFLAGS.OF, SF, AF, PF, CF := 0;

Flags affected

ZF is set to 0 if the operation succeeded and set to 1 if the operation failed due to full-entropy random data not being received from RDSEED. The other arithmetic flags (OF, SF, AF, PF, CF) are cleared to 0.

Intel C/C++ compiler intrinsics

LOADIWKEY void _mm_loadiwkey(unsigned int ctl, __m128i intkey, __m128i enkey_lo, __m128i enkey_hi);

Exceptions

Real address mode
#GPIf CPL > 0. (Does not apply in real-address mode.) If EAX[4:1] > 1. If EAX[31:5] != 0. If (EAX[0] == 1) AND (CPUID.19H:ECX[0] == 0). If (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0).
#UDIf the LOCK prefix is used. If CPUID.07H.00H:ECX.KEY_LOCKER[23] = 0. If CR4.KL = 0. If CR0.EM = 1. If CR4.OSFXSR = 0.
#NMIf CR0.TS = 1.
Protected mode
#GPIf CPL > 0. (Does not apply in real-address mode.) If EAX[4:1] > 1. If EAX[31:5] != 0. If (EAX[0] == 1) AND (CPUID.19H:ECX[0] == 0). If (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0).
#UDIf the LOCK prefix is used. If CPUID.07H.00H:ECX.KEY_LOCKER[23] = 0. If CR4.KL = 0. If CR0.EM = 1. If CR4.OSFXSR = 0.
#NMIf CR0.TS = 1.
Virtual-8086 mode
#GPIf CPL > 0. (Does not apply in real-address mode.) If EAX[4:1] > 1. If EAX[31:5] != 0. If (EAX[0] == 1) AND (CPUID.19H:ECX[0] == 0). If (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0).
#UDIf the LOCK prefix is used. If CPUID.07H.00H:ECX.KEY_LOCKER[23] = 0. If CR4.KL = 0. If CR0.EM = 1. If CR4.OSFXSR = 0.
#NMIf CR0.TS = 1.
Compatibility mode
#GPIf CPL > 0. (Does not apply in real-address mode.) If EAX[4:1] > 1. If EAX[31:5] != 0. If (EAX[0] == 1) AND (CPUID.19H:ECX[0] == 0). If (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0).
#UDIf the LOCK prefix is used. If CPUID.07H.00H:ECX.KEY_LOCKER[23] = 0. If CR4.KL = 0. If CR0.EM = 1. If CR4.OSFXSR = 0.
#NMIf CR0.TS = 1.
64-bit mode
#GPIf CPL > 0. (Does not apply in real-address mode.) If EAX[4:1] > 1. If EAX[31:5] != 0. If (EAX[0] == 1) AND (CPUID.19H:ECX[0] == 0). If (EAX[4:1] == 1) AND (CPUID.19H:ECX[1] == 0).
#UDIf the LOCK prefix is used. If CPUID.07H.00H:ECX.KEY_LOCKER[23] = 0. If CR4.KL = 0. If CR0.EM = 1. If CR4.OSFXSR = 0.
#NMIf CR0.TS = 1.

Sources