PCONFIG — Platform Configuration

Opcode/Instruction Op/En 64/32 bit Mode Support CPUID Feature Flag Description
NP 0F 01 C5 PCONFIG A V/V PCONFIG This instruction is used to execute functions for configuring platform features.

Instruction Operand Encoding

Op/En Tuple Operand 1 Operand 2 Operand 3 Operand 4
A N/A N/A N/A N/A N/A

Description

PCONFIG allows software to configure certain platform features. PCONFIG supports multiple leaf functions, with a leaf function identified by the value in EAX. The registers RBX, RCX, and RDX may provide input or output information for certain leaves. All leaves write status information to EAX but do not modify RBX, RCX, or RDX unless they are being used as leaf-specific output.

Each PCONFIG leaf function applies to a specific hardware block called a PCONFIG target, and each PCONFIG target is associated with a numerical target identifier. Supported target identifiers are enumerated, along with other PCONFIG capabilities, in the sub-leaves of the PCONFIG-information leaf of CPUID (EAX = 1BH). An attempt to execute an undefined leaf function, or a leaf function that applies to an unsupported target identifier, results in a general-protection exception (#GP). (In the future, the PCONFIG-information leaf of CPUID may enumerate PCONFIG capabilities in addition to the supported target identifiers.)

Addresses and operands are 32 bits outside 64-bit mode and are 64 bits in 64-bit mode. The value of CS.D does not affect operand size or address size.

Table 4-15 shows the leaf encodings for PCONFIG, and Table 4-16 shows the leaf register usage for PCONFIG.

Leaf Encoding Description
MKTME_KEY_PROGRAM 00000000H This leaf is used to program the key and encryption mode associated with a KeyID.
RESERVED 00000001H - FFFFFFFFH Reserved for future use (#GP(0) if used).
Table 4-15. PCONFIG Leaf Encodings
Leaf RBX RCX RDX
MKTME_KEY_PROGRAM Input only. Input only. Input only.
RESERVED Reserved for future use. Reserved for future use. Reserved for future use.
Table 4-16. PCONFIG Leaf Register Usage

The MKTME_KEY_PROGRAM leaf of PCONFIG pertains to the MKTME1 target, which has target identifier 1. It is used by software to manage the key associated with a KeyID. The leaf function is invoked by setting the leaf value of 0 in EAX and the address of MKTME_KEY_PROGRAM_STRUCT in RBX. Successful execution of the leaf clears RAX (set to zero) and ZF, CF, PF, AF, OF, and SF are cleared. In case of failure, the failure reason is indicated in RAX with ZF set to 1 and CF, PF, AF, OF, and SF are cleared. The MKTME_KEY_PROGRAM leaf uses the MKTME_KEY_PROGRAM_STRUCT in memory shown in Table 4-17.

1. Further details on MKTME usage can be found here:

https://software.intel.com/sites/default/files/managed/a5/16/Multi-Key-Total-Memory-Encryption-Spec.pdf

Field Offset (bytes) Size (bytes) Comments
KEYID 0 2 Key Identifier.
KEYID_CTRL 2 4 KeyID control: • Bits [7:0]: COMMAND. • Bits [23:8]: ENC_ALG. • Bits [31:24]: Reserved, must be zero.
RESERVED 6 58 Reserved, must be zero.
KEY_FIELD_1 64 64 Software supplied KeyID data key or entropy for KeyID data key.
KEY_FIELD_2 128 64 Software supplied KeyID tweak key or entropy for KeyID tweak key.
Table 4-17. MKTME_KEY_PROGRAM_STRUCT Format

A description of each of the fields in MKTME_KEY_PROGRAM_STRUCT is provided below:

  • KEYID: Key Identifier being programmed to the MKTME engine.
  • KEYID_CTRL: The KEYID_CTRL field carries two sub-fields used by software to control the behavior of a KeyID: Command and KeyID encryption algorithm.

The command used controls the encryption mode for a KeyID. Table 4-18 provides a summary of the commands supported.

Command Encoding Description
KEYID_SET_KEY_DIRECT 0 Software uses this mode to directly program a key for use with KeyID.
KEYID_SET_KEY_RANDOM 1 CPU generates and assigns an ephemeral key for use with a KeyID. Each time the instruction is executed, the CPU generates a new key using a hardware random number generator and the keys are discarded on reset.
KEYID_CLEAR_KEY 2 Clear the (software programmed) key associated with the KeyID. On execution of this command, the KeyID gets TME behavior (encrypt with platform TME key or bypass TME encryption).
KEYID_NO_ENCRYPT 3 Do not encrypt memory when this KeyID is in use.
Table 4-18. Supported Key Programming Commands

The encryption algorithm field (ENC_ALG) allows software to select one of the activated encryption algorithms for the KeyID. The BIOS can activate a set of algorithms to allow for use when programming keys using the IA32_TME_ACTIVATE MSR (does not apply to KeyID 0 which uses the TME policy when TME encryption is not bypassed). The processor checks to ensure that the algorithm selected by software is one of the algorithms that has been activated by the BIOS.

  • KEY_FIELD_1: This field carries the software supplied data key to be used for the KeyID if the direct key programming option is used (KEYID_SET_KEY_DIRECT). When the random key programming option is used (KEYID_SET_KEY_RANDOM), this field carries the software supplied entropy to be mixed in the CPU generated random data key. It is software's responsibility to ensure that the key supplied for the direct programming option or the entropy supplied for the random programming option does not result in weak keys. There are no explicit checks in the instruction to detect or prevent weak keys. When AES XTS-128 is used, the upper 48B are treated as reserved and must be zeroed out by software before executing the instruction.
  • KEY_FIELD_2: This field carries the software supplied tweak key to be used for the KeyID if the direct key programming option is used (KEYID_SET_KEY_DIRECT). When the random key programming option is used (KEYID_SET_KEY_RANDOM), this field carries the software supplied entropy to be mixed in the CPU generated random tweak key. It is software's responsibility to ensure that the key supplied for the direct programming option or the entropy supplied for the random programming option does not result in weak keys. There are no explicit checks in the instruction to detect or prevent weak keys. When AES XTS-128 is used, the upper 48B are treated as reserved and must be zeroed out by software before executing the instruction.

All KeyIDs default to TME behavior (encrypt with TME key or bypass encryption) on MKTME activation. Software can at any point decide to change the key for a KeyID using the PCONFIG instruction. Change of

keys for a KeyID does NOT change the state of the TLB caches or memory pipeline. It is software's responsibility to take appropriate actions to ensure correct behavior.

Table 4-19 shows the return values associated with the MKTME_KEY_PROGRAM leaf of PCONFIG. On instruction execution, RAX is populated with the return value.

Return Value Encoding Description
PROG_SUCCESS 0 KeyID was successfully programmed.
INVALID_PROG_CMD 1 Invalid KeyID programming command.
ENTROPY_ERROR 2 Insufficient entropy.
INVALID_KEYID 3 KeyID not valid.
INVALID_ENC_ALG 4 Invalid encryption algorithm chosen (not supported).
DEVICE_BUSY 5 Failure to access key table.
Table 4-19. Supported Key Error Codes

PCONFIG Concurrency

In a scenario where the MKTME_KEY_PROGRAM leaf of PCONFIG is executed concurrently on multiple logical processors, only one logical processor will succeed in updating the key table. PCONFIG execution will return with an error code (DEVICE_BUSY) on other logical processors and software must retry. In cases where the instruction execution fails with a DEVICE_BUSY error code, the key table is not updated, thereby ensuring that either the key table is updated in its entirety with the information for a KeyID, or it is not updated at all. In order to accomplish this, the MKTME_KEY_PROGRAM leaf of PCONFIG maintains a writer lock for updating the key table. This lock is referred to as the Key table lock and denoted in the instruction flows as KEY_TABLE_LOCK. The lock can either be unlocked, when no logical processor is holding the lock (also the initial state of the lock) or be in an exclusive state where a logical processor is trying to update the key table. There can be only one logical processor holding the lock in exclusive state. The lock, being exclusive, can only be acquired when the lock is in unlocked state.

PCONFIG uses the following syntax to acquire KEY_TABLE_LOCK in exclusive mode and release the lock:

  • KEY_TABLE_LOCK.ACQUIRE(WRITE)
  • KEY_TABLE_LOCK.RELEASE()

Operation

Variable Name Type Size (Bytes) Description
TMP_KEY_PROGRAM_STRUCT MKTME_KEY_PROGRAM_STRUCT 192 Structure holding the key programming structure.
TMP_RND_DATA_KEY UINT128 16 Random data key generated for random key programming option.
TMP_RND_TWEAK_KEY UINT128 16 Random tweak key generated for random key programming option.
Table 4-20. PCONFIG Operation Variables

(* #UD if PCONFIG is not enumerated or CPL>0 *)

IF (CPUID.7.0:EDX[18] == 0 OR CPL > 0) #UD;

(* #GP(0) for an unsupported leaf *)

IF (EAX != 0) #GP(0)

(* KEY_PROGRAM leaf flow *)

IF (EAX == 0)

{

(* #GP(0) if TME_ACTIVATE MSR is not locked or does not enable hardware encryption or multiple keys are not enabled *)

IF (IA32_TME_ACTIVATE.LOCK != 1 OR IA32_TME_ACTIVATE.ENABLE != 1 OR IA32_TME_ACTIVATE.MK_TME_KEYID_BITS == 0) #GP(0)

(* Check MKTME_KEY_PROGRAM_STRUCT is 256B aligned *)

IF (DS:RBX is not 256B aligned) #GP(0);

(* Check that MKTME_KEY_PROGRAM_STRUCT is read accessible *)

<<DS: RBX should be read accessible>>

(* Copy MKTME_KEY_PROGRAM_STRUCT to a temporary variable *)

TMP_KEY_PROGRAM_STRUCT = DS:RBX.*;

(* RSVD field check *)

IF (TMP_KEY_PROGRAM_STRUCT.RSVD != 0) #GP(0);

IF (TMP_KEY_PROGRAM_STRUCT.KEYID_CTRL.RSVD !=0) #GP(0);

IF (TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_1.BYTES[63:16] != 0) #GP(0);

IF (TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_2.BYTES[63:16] != 0) #GP(0);

(* Check for a valid command *)

IF (TMP_KEY_PROGRAM_STRUCT. KEYID_CTRL.COMMAND is not a valid command)

{

RFLAGS.ZF = 1;

RAX = INVALID_PROG_CMD;

goto EXIT;

}

(* Check that the KEYID being operated upon is a valid KEYID *)

IF (TMP_KEY_PROGRAM_STRUCT.KEYID >

2^IA32_TME_ACTIVATE.MK_TME_KEYID_BITS - 1

OR TMP_KEY_PROGRAM_STRUCT.KEYID >

IA32_TME_CAPABILITY.MK_TME_MAX_KEYS

OR TMP_KEY_PROGRAM_STRUCT.KEYID == 0)

{

RFLAGS.ZF = 1;

RAX = INVALID_KEYID;

goto EXIT;

}

(* Check that only one algorithm is requested for the KeyID and it is one of the activated algorithms *)

IF (NUM_BITS(TMP_KEY_PROGRAM_STRUCT.KEYID_CTRL.ENC_ALG) != 1 ||

(TMP_KEY_PROGRAM_STRUCT.KEYID_CTRL.ENC_ALG &

IA32_TME_ACTIVATE. MK_TME_CRYPTO_ALGS == 0))

{

RFLAGS.ZF = 1;

RAX = INVALID_ENC_ALG;

goto EXIT;

}

(* Try to acquire exclusive lock *)

IF (NOT KEY_TABLE_LOCK.ACQUIRE(WRITE))

{

//PCONFIG failure

RFLAGS.ZF = 1;

RAX = DEVICE_BUSY;

goto EXIT;

}

(* Lock is acquired and key table will be updated as per the command

Before this point no changes to the key table are made *)

switch(TMP_KEY_PROGRAM_STRUCT.KEYID_CTRL.COMMAND)

{

case KEYID_SET_KEY_DIRECT:

<<Write

DATA_KEY=TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_1,

TWEAK_KEY=TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_2,

ENCRYPTION_MODE=ENCRYPT_WITH_KEYID_KEY,

to MKTME Key table at index TMP_KEY_PROGRAM_STRUCT.KEYID

>>

break;

case KEYID_SET_KEY_RANDOM:

TMP_RND_DATA_KEY = <<Generate a random key using hardware RNG>>

IF (NOT ENOUGH ENTROPY)

{

RFLAGS.ZF = 1;

RAX = ENTROPY_ERROR;

goto EXIT;

}

TMP_RND_TWEAK_KEY = <<Generate a random key using hardware RNG>>

IF (NOT ENOUGH ENTROPY)

{

RFLAGS.ZF = 1;

RAX = ENTROPY_ERROR;

goto EXIT;

}

(* Mix user supplied entropy to the data key and tweak key *)

TMP_RND_DATA_KEY = TMP_RND_KEY XOR

TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_1.BYTES[15:0];

TMP_RND_TWEAK_KEY = TMP_RND_TWEAK_KEY XOR

TMP_KEY_PROGRAM_STRUCT.KEY_FIELD_2.BYTES[15:0];

<<Write

DATA_KEY=TMP_RND_DATA_KEY,

TWEAK_KEY=TMP_RND_TWEAK_KEY,

ENCRYPTION_MODE=ENCRYPT_WITH_KEYID_KEY,

to MKTME_KEY_TABLE at index TMP_KEY_PROGRAM_STRUCT.KEYID

>>

break;

case KEYID_CLEAR_KEY:

<<Write

DATA_KEY='0,

TWEAK_KEY='0,

ENCRYPTION_MODE = ENCRYPT_WITH_TME_KEY_OR_BYPASS,

to MKTME_KEY_TABLE at index TMP_KEY_PROGRAM_STRUCT.KEYID

>>

break;

case KD_NO_ENCRYPT:

<<Write

ENCRYPTION_MODE=NO_ENCRYPTION,

to MKTME_KEY_TABLE at index TMP_KEY_PROGRAM_STRUCT.KEYID

>>

break;

}

RAX = 0;

RFLAGS.ZF = 0;

//Release Lock

KEY_TABLE_LOCK(RELEASE);

EXIT:

RFLAGS.CF=0;

RFLAGS.PF=0;

RFLAGS.AF=0;

RFLAGS.OF=0;

RFLAGS.SF=0;

}

end_of_flow

Protected Mode Exceptions

#GP(0) If input value in EAX encodes an unsupported leaf.
If IA32_TME_ACTIVATE MSR is not locked.
If hardware encryption and MKTME capability are not enabled in IA32_TME_ACTIVATE MSR.
If the memory operand is not 256B aligned.
If any of the reserved bits in MKTME_KEY_PROGRAM_STRUCT are set.
If a memory operand effective address is outside the DS segment limit.
#PF(fault-code) If a page fault occurs in accessing memory operands.
#UD If any of the LOCK/REP/OSIZE/VEX prefixes are used.
If current privilege level is not 0.
If CPUID.7.0:EDX[bit 18] = 0

Real-Address Mode Exceptions

#GP If input value in EAX encodes an unsupported leaf.
If IA32_TME_ACTIVATE MSR is not locked.
If hardware encryption and MKTME capability are not enabled in IA32_TME_ACTIVATE MSR.
If a memory operand is not 256B aligned.
If any of the reserved bits in MKTME_KEY_PROGRAM_STRUCT are set.
#UD If any of the LOCK/REP/OSIZE/VEX prefixes are used.
If current privilege level is not 0.
If CPUID.7.0:EDX.PCONFIG[bit 18] = 0

Virtual-8086 Mode Exceptions

#UD PCONFIG instruction is not recognized in virtual-8086 mode.

Compatibility Mode Exceptions

Same exceptions as in protected mode.

64-Bit Mode Exceptions

#GP(0) If input value in EAX encodes an unsupported leaf.
If IA32_TME_ACTIVATE MSR is not locked.
If hardware encryption and MKTME capability are not enabled in IA32_TME_ACTIVATE MSR.
If a memory operand is not 256B aligned.
If any of the reserved bits in MKTME_KEY_PROGRAM_STRUCT are set.
If a memory operand is non-canonical form.
#PF(fault-code) If a page fault occurs in accessing memory operands.
#UD If any of the LOCK/REP/OSIZE/VEX prefixes are used.
If the current privilege level is not 0.
If CPUID.7.0:EDX.PCONFIG[bit 18] = 0.