EGETKEY — Retrieves a Cryptographic Key

Opcode/Instruction Op/En 64/32 bit Mode Support CPUID Feature Flag Description
EAX = 01H ENCLU[EGETKEY] IR V/V SGX1 This leaf function retrieves a cryptographic key.

Instruction Operand Encoding

Op/En EAX RBX RCX
IR EGETKEY (In) Address to a KEYREQUEST (In) Address of the OUTPUTDATA (In)

Description

The ENCLU[EGETKEY] instruction returns a 128-bit secret key from the processor specific key hierarchy. The register RBX contains the effective address of a KEYREQUEST structure, which the instruction interprets to determine the key being requested. The Requesting Keys section below provides a description of the keys that can be requested. The RCX register contains the effective address where the key will be returned. Both the addresses in RBX & RCX should be locations inside the enclave.

EGETKEY derives keys using a processor unique value to create a specific key based on a number of possible inputs. This instruction leaf can only be executed inside an enclave.

EEGETKEY Memory Parameter Semantics

KEYREQUEST OUTPUTDATA
Enclave read access Enclave write access

After validating the operands, the instruction determines which key is to be produced and performs the following actions:

The instruction fails with #GP(0) if the operands are not properly aligned. Successful completion of the instruction will clear RFLAGS.{ZF, CF, AF, OF, SF, PF}. The instruction returns an error code if the user tries to request a key based on an invalid CPUSVN or ISVSVN (when the user request is accepted, see the table below), requests a key for which it has not been granted the attribute to request, or requests a key that is not supported by the hardware. These checks may be performed in any order. Thus, an indication by error number of one cause (for example, invalid attribute) does not imply that there are not also other errors. Different processors may thus give different error numbers for the same Enclave. The correctness of software should not rely on the order resulting from the checks documented in this section. In such cases the ZF flag is set and the corresponding error bit (SGX_INVALID_SVN, SGX_INVALID_ATTRIBUTE, SGX_INVALID_KEYNAME) is set in RAX and the data at the address specified by RCX is unmodified.

Requesting Keys

The KEYREQUEST structure (see Section 37.17.1) identifies the key to be provided. The Keyrequest.KeyName field identifies which type of key is requested.

Deriving Keys

Key derivation is based on a combination of the enclave specific values (see Table 40-64) and a processor key. Depending on the key being requested a field may either be included by definition or the value may be included from the KeyRequest. A “yes” in Table 40-64 indicates the value for the field is included from its default location, identified in the source row, and a “request” indicates the values for the field is included from its corresponding KeyRequest field.

Key Name Attributes Owner Epoch CPU SVN ISV SVN ISV PRODID ISVEXT PRODID ISVFAM ILYID MRENCLAVE MRSIGNER CONFIG ID CONFIGS VN RAND
Source Key Dependent Constant Y← SECS.ATTRIBUTES and SECS.MISCSELECT; CR_SGX OWNER EPOCH Y← CPUSVN Register; R← Req.ISV SVN; SECS. ISVID SECS.IS VEXTPR ODID SECS.IS VFAMIL YID SECS. MRENCLAVE SECS. MRSIGNER SECS.CO NFIGID SECS.CO NFIGSVN Req. KEYID
R←AttribMask & SECS.ATTRIBUTES and SECS.MISCSELECT; R← Req.CPU SVN;
EINITTOKEN Yes Request Yes Request Request Yes No No No Yes No No Request
Report Yes Yes Yes Yes No No No No Yes No Yes Yes Request
Seal Yes Request Yes Request Request Request Request Request Request Request Request Request Request
Provisioning Yes Request No Request Request Yes No No No Yes No No Yes
Provisioning Seal Yes Request No Request Request Request Request Request No Yes Request Request Yes
Table 40-64. Key Derivation

Keys that permit the specification of a CPU or ISV's code's, or enclave configuration's SVNs have additional requirements. The caller may not request a key for an SVN beyond the current CPU, ISV or enclave configuration's SVN, respectively.

Several keys are access controlled. Access to the Provisioning Key and Provisioning Seal key requires the enclave's ATTRIBUTES.PROVISIONKEY be set. The EINITTOKEN Key requires ATTRIBUTES.EINITTOKEN_KEY be set and SECS.MRSIGNER equal IA32_SGXLEPUBKEYHASH.

Some keys are derived based on a hardcode PKCS padding constant (352 byte string):

HARDCODED_PKCS1_5_PADDING[15:0] ← 0100H;

HARDCODED_PKCS1_5_PADDING[2655:16]←SignExtend330Byte(-1); // 330 bytes of 0FFH

HARDCODED_PKCS1_5_PADDING[2815:2656] ← 2004000501020403650148866009060D30313000H;

The error codes are:

Error Code (see Table 40-4) Value Description
No Error 0 EGETKEY successful.
SGX_INVALID_ATTRIBUTE The KEYREQUEST contains a KEYNAME for which the enclave is not authorized.
SGX_INVALID_CPUSVN If KEYREQUEST.CPUSVN is an unsupported platforms CPUSVN value.
SGX_INVALID_ISVSVN If KEYREQUEST software SVN (ISVSVN or CONFIGSVN) is greater than the enclave's corresponding SVN.
SGX_INVALID_KEYNAME If KEYREQUEST.KEYNAME is an unsupported value.
Table 40-65. EGETKEY Return Value in RAX

Concurrency Restrictions

Leaf Parameter Base Concurrency Restrictions
Access On Conflict SGX_CONFLICT VM Exit Qualification
EGETKEY KEYREQUEST [DS:RBX] Concurrent
OUTPUTDATA [DS:RCX] Concurrent
Table 40-66. Base Concurrency Restrictions of EGETKEY
Leaf Parameter Additional Concurrency Restrictions
vs. EACCEPT, EACCEPTCOPY, EMODPE, EMODPR, EMODT vs. EADD, EEXTEND, EINIT vs. ETRACK, ETRACKC
Access On Conflict Access On Conflict Access On Conflict
EGETKEY KEYREQUEST [DS:RBX] Concurrent Concurrent Concurrent
OUTPUTDATA [DS:RCX] Concurrent Concurrent Concurrent
Table 40-67. Additional Concurrency Restrictions of EGETKEY

Operation

Temp Variables in EGETKEY Operational Flow

Name Type Size (Bits) Description
TMP_CURRENTSECS Address of the SECS for the currently executing enclave.
TMP_KEYDEPENDENCIES Temp space for key derivation.
TMP_ATTRIBUTES 128 Temp Space for the calculation of the sealable Attributes.
TMP_ISVEXTPRODID 16 bytes Temp Space for ISVEXTPRODID.
TMP_ISVPRODID 2 bytes Temp Space for ISVPRODID.
TMP_ISVFAMILYID 16 bytes Temp Space for ISVFAMILYID.
TMP_CONFIGID 64 bytes Temp Space for CONFIGID.
TMP_CONFIGSVN 2 bytes Temp Space for CONFIGSVN.
TMP_OUTPUTKEY 128 Temp Space for the calculation of the key.

(* Make sure KEYREQUEST is properly aligned and inside the current enclave *)

IF ( (DS:RBX is not 512Byte aligned) or (DS:RBX is within CR_ELRANGE) )

THEN #GP(0); FI;

(* Make sure DS:RBX is an EPC address and the EPC page is valid *)

IF ( (DS:RBX does not resolve to an EPC address) or (EPCM(DS:RBX).VALID = 0) )

THEN #PF(DS:RBX); FI;

IF (EPCM(DS:RBX).BLOCKED = 1)

THEN #PF(DS:RBX); FI;

(* Check page parameters for correctness *)

IF ( (EPCM(DS:RBX).PT ≠ PT_REG) or (EPCM(DS:RBX).ENCLAVESECS ≠ CR_ACTIVE_SECS) or (EPCM(DS:RBX).PENDING = 1) or

(EPCM(DS:RBX).MODIFIED = 1) or (EPCM(DS:RBX).ENCLAVEADDRESS ≠ (DS:RBX & ~0FFFH) ) or (EPCM(DS:RBX).R = 0) )

THEN #PF(DS:RBX);

FI;

(* Make sure OUTPUTDATA is properly aligned and inside the current enclave *)

IF ( (DS:RCX is not 16Byte aligned) or (DS:RCX is not within CR_ELRANGE) )

THEN #GP(0); FI;

(* Make sure DS:RCX is an EPC address and the EPC page is valid *)

IF ( (DS:RCX does not resolve to an EPC address) or (EPCM(DS:RCX).VALID = 0) )

THEN #PF(DS:RCX); FI;

IF (EPCM(DS:RCX).BLOCKED = 1)

THEN #PF(DS:RCX); FI;

(* Check page parameters for correctness *)

IF ( (EPCM(DS:RCX).PT ≠ PT_REG) or (EPCM(DS:RCX).ENCLAVESECS ≠ CR_ACTIVE_SECS) or (EPCM(DS:RCX).PENDING = 1) or

(EPCM(DS:RCX).MODIFIED = 1) or (EPCM(DS:RCX).ENCLAVEADDRESS ≠ (DS:RCX & ~0FFFH) ) or (EPCM(DS:RCX).W = 0) )

THEN #PF(DS:RCX);

FI;

(* Verify RESERVED spaces in KEYREQUEST are valid *)

IF ( (DS:RBX).RESERVED ≠ 0) or (DS:RBX.KEYPOLICY.RESERVED ≠ 0) )

THEN #GP(0); FI;

TMP_CURRENTSECS ← CR_ACTIVE_SECS;

(* Verify that CONFIGSVN & New Policy bits are not used if KSS is not enabled *)

IF ((TMP_CURRENTSECS.ATTRIBUTES.KSS == 0) AND ((DS:RBX.KEYPOLICY & 0x003C ≠ 0) OR (DS:RBX.CONFIGSVN > 0)))

THEN #GP(0); FI;

(* Determine which enclave attributes that must be included in the key. Attributes that must always be include INIT & DEBUG *)

REQUIRED_SEALING_MASK[127:0]←00000000 00000000 00000000 00000003H;

TMP_ATTRIBUTES←(DS:RBX.ATTRIBUTEMASK | REQUIRED_SEALING_MASK) & TMP_CURRENTSECS.ATTRIBUTES;

(* Compute MISCSELECT fields to be included *)

TMP_MISCSELECT←DS:RBX.MISCMASK & TMP_CURRENTSECS.MISCSELECT

CASE (DS:RBX.KEYNAME)

SEAL_KEY:

IF (DS:RBX.CPUSVN is beyond current CPU configuration)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_CPUSVN;

GOTO EXIT;

FI;

IF (DS:RBX.ISVSVN > TMP_CURRENTSECS.ISVSVN)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ISVSVN;

GOTO EXIT;

FI;

IF (DS:RBX.CONFIGSVN > TMP_CURRENTSECS.CONFIGSVN)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ISVSVN;

GOTO EXIT;

FI;

(*Include enclave identity?*)

TMP_MRENCLAVE ← 0;

IF (DS:RBX.KEYPOLICY.MRENCLAVE = 1)

THEN TMP_MRENCLAVE←TMP_CURRENTSECS.MRENCLAVE;

FI;

(*Include enclave author?*)

TMP_MRSIGNER ← 0;

IF (DS:RBX.KEYPOLICY.MRSIGNER = 1)

THEN TMP_MRSIGNER←TMP_CURRENTSECS.MRSIGNER;

FI;

(* Include enclave product family ID? *)

TMP_ISVFAMILYID ← 0;

IF (DS:RBX.KEYPOLICY.ISVFAMILYID = 1)

THEN TMP_ISVFAMILYID←TMP_CURRENTSECS.ISVFAMILYID;

FI;

(* Include enclave product ID? *)

TMP_ISVPRODID ← 0;

IF (DS:RBX.KEYPOLICY.NOISVPRODID = 0)

TMP_ISVPRODID ←TMP_CURRENTSECS.ISVPRODID;

FI;

(* Include enclave Config ID? *)

TMP_CONFIGID ← 0;

TMP_CONFIGSVN ← 0;

IF (DS:RBX.KEYPOLICY.CONFIGID = 1)

TMP_CONFIGID ← TMP_CURRENTSECS.CONFIGID;

TMP_CONFIGSVN ← DS:RBX.CONFIGSVN;

FI;

(* Include enclave extended product ID? *)

TMP_ISVEXTPRODID ← 0;

IF (DS:RBX.KEYPOLICY.ISVEXTPRODID = 1 )

TMP_ISVEXTPRODID ← TMP_CURRENTSECS.ISVEXTPRODID;

FI;

//Determine values key is based on

TMP_KEYDEPENDENCIES.KEYNAME ← SEAL_KEY;

TMP_KEYDEPENDENCIES.ISVFAMILYID ← TMP_ISVFAMILYID;

TMP_KEYDEPENDENCIES.ISVEXTPRODID ← TMP_ISVEXTPRODID;

TMP_KEYDEPENDENCIES.ISVPRODID ← TMP_ISVPRODID;

TMP_KEYDEPENDENCIES.ISVSVN ← DS:RBX.ISVSVN;

TMP_KEYDEPENDENCIES.SGXOWNEREPOCH ← CR_SGXOWNEREPOCH;

TMP_KEYDEPENDENCIES.ATTRIBUTES ← TMP_ATTRIBUTES;

TMP_KEYDEPENDENCIES.ATTRIBUTESMASK ← DS:RBX.ATTRIBUTEMASK;

TMP_KEYDEPENDENCIES.MRENCLAVE ← TMP_MRENCLAVE;

TMP_KEYDEPENDENCIES.MRSIGNER ← TMP_MRSIGNER;

TMP_KEYDEPENDENCIES.KEYID ← DS:RBX.KEYID;

TMP_KEYDEPENDENCIES.SEAL_KEY_FUSES ← CR_SEAL_FUSES;

TMP_KEYDEPENDENCIES.CPUSVN ← DS:RBX.CPUSVN;

TMP_KEYDEPENDENCIES.PADDING ← TMP_CURRENTSECS.PADDING;

TMP_KEYDEPENDENCIES.MISCSELECT ← TMP_MISCSELECT;

TMP_KEYDEPENDENCIES.MISCMASK ← ~DS:RBX.MISCMASK;

TMP_KEYDEPENDENCIES.KEYPOLICY ← DS:RBX.KEYPOLICY;

TMP_KEYDEPENDENCIES.CONFIGID ← TMP_CONFIGID;

TMP_KEYDEPENDENCIES.CONFIGSVN ← TMP_CONFIGSVN;

BREAK;

REPORT_KEY:

//Determine values key is based on

TMP_KEYDEPENDENCIES.KEYNAME ← REPORT_KEY;

TMP_KEYDEPENDENCIES.ISVFAMILYID ← 0;

TMP_KEYDEPENDENCIES.ISVEXTPRODID ← 0;

TMP_KEYDEPENDENCIES.ISVPRODID ← 0;

TMP_KEYDEPENDENCIES.ISVSVN ← 0;

TMP_KEYDEPENDENCIES.SGXOWNEREPOCH ← CR_SGXOWNEREPOCH;

TMP_KEYDEPENDENCIES.ATTRIBUTES ← TMP_CURRENTSECS.ATTRIBUTES;

TMP_KEYDEPENDENCIES.ATTRIBUTESMASK ← 0;

TMP_KEYDEPENDENCIES.MRENCLAVE ← TMP_CURRENTSECS.MRENCLAVE;

TMP_KEYDEPENDENCIES.MRSIGNER ← 0;

TMP_KEYDEPENDENCIES.KEYID ← DS:RBX.KEYID;

TMP_KEYDEPENDENCIES.SEAL_KEY_FUSES ← CR_SEAL_FUSES;

TMP_KEYDEPENDENCIES.CPUSVN ← CR_CPUSVN;

TMP_KEYDEPENDENCIES.PADDING ← HARDCODED_PKCS1_5_PADDING;

TMP_KEYDEPENDENCIES.MISCSELECT ← TMP_CURRENTSECS.MISCSELECT;

TMP_KEYDEPENDENCIES.MISCMASK ← 0;

TMP_KEYDEPENDENCIES.KEYPOLICY ← 0;

TMP_KEYDEPENDENCIES.CONFIGID ← TMP_CURRENTSECS.CONFIGID;

TMP_KEYDEPENDENCIES.CONFIGSVN ← TMP_CURRENTSECS.CONFIGSVN;

BREAK;

EINITTOKEN_KEY:

(* Check ENCLAVE has LAUNCH capability *)

IF (TMP_CURRENTSECS.ATTRIBUTES.LAUNCHKEY = 0)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ATTRIBUTE;

GOTO EXIT;

FI;

IF (DS:RBX.CPUSVN is beyond current CPU configuration)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_CPUSVN;

GOTO EXIT;

FI;

IF (DS:RBX.ISVSVN > TMP_CURRENTSECS.ISVSVN)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ISVSVN;

GOTO EXIT;

FI;

(* Determine values key is based on *)

TMP_KEYDEPENDENCIES.KEYNAME ← EINITTOKEN_KEY;

TMP_KEYDEPENDENCIES.ISVFAMILYID ← 0;

TMP_KEYDEPENDENCIES.ISVEXTPRODID ← 0;

TMP_KEYDEPENDENCIES.ISVPRODID ← TMP_CURRENTSECS.ISVPRODID

TMP_KEYDEPENDENCIES.ISVSVN ← DS:RBX.ISVSVN;

TMP_KEYDEPENDENCIES.SGXOWNEREPOCH ← CR_SGXOWNEREPOCH;

TMP_KEYDEPENDENCIES.ATTRIBUTES ← TMP_ATTRIBUTES;

TMP_KEYDEPENDENCIES.ATTRIBUTESMASK ← 0;

TMP_KEYDEPENDENCIES.MRENCLAVE ← 0;

TMP_KEYDEPENDENCIES.MRSIGNER ← TMP_CURRENTSECS.MRSIGNER;

TMP_KEYDEPENDENCIES.KEYID ← DS:RBX.KEYID;

TMP_KEYDEPENDENCIES.SEAL_KEY_FUSES ← CR_SEAL_FUSES;

TMP_KEYDEPENDENCIES.CPUSVN ← DS:RBX.CPUSVN;

TMP_KEYDEPENDENCIES.PADDING ← TMP_CURRENTSECS.PADDING;

TMP_KEYDEPENDENCIES.MISCSELECT ← TMP_MISCSELECT;

TMP_KEYDEPENDENCIES.MISCMASK ← 0;

TMP_KEYDEPENDENCIES.KEYPOLICY ← 0;

TMP_KEYDEPENDENCIES.CONFIGID ← 0;

TMP_KEYDEPENDENCIES.CONFIGSVN ← 0;

BREAK;

PROVISION_KEY:

(* Check ENCLAVE has PROVISIONING capability *)

IF (TMP_CURRENTSECS.ATTRIBUTES.PROVISIONKEY = 0)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ATTRIBUTE;

GOTO EXIT;

FI;

IF (DS:RBX.CPUSVN is beyond current CPU configuration)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_CPUSVN;

GOTO EXIT;

FI;

IF (DS:RBX.ISVSVN > TMP_CURRENTSECS.ISVSVN)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ISVSVN;

GOTO EXIT;

FI;

(* Determine values key is based on *)

TMP_KEYDEPENDENCIES.KEYNAME ← PROVISION_KEY;

TMP_KEYDEPENDENCIES.ISVFAMILYID ← 0;

TMP_KEYDEPENDENCIES.ISVEXTPRODID ← 0;

TMP_KEYDEPENDENCIES.ISVPRODID ← TMP_CURRENTSECS.ISVPRODID;

TMP_KEYDEPENDENCIES.ISVSVN ← DS:RBX.ISVSVN;

TMP_KEYDEPENDENCIES.SGXOWNEREPOCH ← 0;

TMP_KEYDEPENDENCIES.ATTRIBUTES ← TMP_ATTRIBUTES;

TMP_KEYDEPENDENCIES.ATTRIBUTESMASK ← DS:RBX.ATTRIBUTEMASK;

TMP_KEYDEPENDENCIES.MRENCLAVE ← 0;

TMP_KEYDEPENDENCIES.MRSIGNER ← TMP_CURRENTSECS.MRSIGNER;

TMP_KEYDEPENDENCIES.KEYID ← 0;

TMP_KEYDEPENDENCIES.SEAL_KEY_FUSES ← 0;

TMP_KEYDEPENDENCIES.CPUSVN ← DS:RBX.CPUSVN;

TMP_KEYDEPENDENCIES.PADDING ← TMP_CURRENTSECS.PADDING;

TMP_KEYDEPENDENCIES.MISCSELECT ← TMP_MISCSELECT;

TMP_KEYDEPENDENCIES.MISCMASK ← ~DS:RBX.MISCMASK;

TMP_KEYDEPENDENCIES.KEYPOLICY ← 0;

TMP_KEYDEPENDENCIES.CONFIGID ← 0;

BREAK;

PROVISION_SEAL_KEY:

(* Check ENCLAVE has PROVISIONING capability *)

IF (TMP_CURRENTSECS.ATTRIBUTES.PROVISIONKEY = 0)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ATTRIBUTE;

GOTO EXIT;

FI;

IF (DS:RBX.CPUSVN is beyond current CPU configuration)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_CPUSVN;

GOTO EXIT;

FI;

IF (DS:RBX.ISVSVN > TMP_CURRENTSECS.ISVSVN)

THEN

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_ISVSVN;

GOTO EXIT;

FI;

(* Include enclave product family ID? *)

TMP_ISVFAMILYID ← 0;

IF (DS:RBX.KEYPOLICY.ISVFAMILYID = 1)

THEN TMP_ISVFAMILYID←TMP_CURRENTSECS.ISVFAMILYID;

FI;

(* Include enclave product ID? *)

TMP_ISVPRODID ← 0;

IF (DS:RBX.KEYPOLICY.NOISVPRODID = 0)

TMP_ISVPRODID ←TMP_CURRENTSECS.ISVPRODID;

FI;

(* Include enclave Config ID? *)

TMP_CONFIGID ← 0;

TMP_CONFIGSVN ← 0;

IF (DS:RBX.KEYPOLICY.CONFIGID = 1)

TMP_CONFIGID ← TMP_CURRENTSECS.CONFIGID;

TMP_CONFIGSVN ← DS:RBX.CONFIGSVN;

FI;

(* Include enclave extended product ID? *)

TMP_ISVEXTPRODID ← 0;

IF (DS:RBX.KEYPOLICY.ISVEXTPRODID = 1)

TMP_ISVEXTPRODID ← TMP_CURRENTSECS.ISVEXTPRODID;

FI;

(* Determine values key is based on *)

TMP_KEYDEPENDENCIES.KEYNAME ← PROVISION_SEAL_KEY;

TMP_KEYDEPENDENCIES.ISVFAMILYID ← TMP_ISVFAMILYID;

TMP_KEYDEPENDENCIES.ISVEXTPRODID ← TMP_ISVEXTPRODID;

TMP_KEYDEPENDENCIES.ISVPRODID ← TMP_ISVPRODID;

TMP_KEYDEPENDENCIES.ISVSVN ← DS:RBX.ISVSVN;

TMP_KEYDEPENDENCIES.SGXOWNEREPOCH ← 0;

TMP_KEYDEPENDENCIES.ATTRIBUTES ← TMP_ATTRIBUTES;

TMP_KEYDEPENDENCIES.ATTRIBUTESMASK ← DS:RBX.ATTRIBUTEMASK;

TMP_KEYDEPENDENCIES.MRENCLAVE ← 0;

TMP_KEYDEPENDENCIES.MRSIGNER ← TMP_CURRENTSECS.MRSIGNER;

TMP_KEYDEPENDENCIES.KEYID ← 0;

TMP_KEYDEPENDENCIES.SEAL_KEY_FUSES ← CR_SEAL_FUSES;

TMP_KEYDEPENDENCIES.CPUSVN ← DS:RBX.CPUSVN;

TMP_KEYDEPENDENCIES.PADDING ← TMP_CURRENTSECS.PADDING;

TMP_KEYDEPENDENCIES.MISCSELECT ← TMP_MISCSELECT;

TMP_KEYDEPENDENCIES.MISCMASK ← ~DS:RBX.MISCMASK;

TMP_KEYDEPENDENCIES.KEYPOLICY ← DS:RBX.KEYPOLICY;

TMP_KEYDEPENDENCIES.CONFIGID ← TMP_CONFIGID;

TMP_KEYDEPENDENCIES.CONFIGSVN ← TMP_CONFIGSVN;

BREAK;

DEFAULT:

(* The value of KEYNAME is invalid *)

RFLAGS.ZF ← 1;

RAX ← SGX_INVALID_KEYNAME;

GOTO EXIT:

ESAC;

(* Calculate the final derived key and output to the address in RCX *)

TMP_OUTPUTKEY ← derivekey(TMP_KEYDEPENDENCIES);

DS:RCX[15:0] ← TMP_OUTPUTKEY;

RAX←0;

RFLAGS.ZF ← 0;

EXIT:

RFLAGS.CF ← 0;

RFLAGS.PF ← 0;

RFLAGS.AF ← 0;

RFLAGS.OF ← 0;

RFLAGS.SF ← 0;

Flags Affected

ZF is cleared if successful, otherwise ZF is set. CF, PF, AF, OF, SF are cleared.

Protected Mode Exceptions

#GP(0) If executed outside an enclave.
If a memory operand effective address is outside the current enclave.
If an effective address is not properly aligned.
If an effective address is outside the DS segment limit.
If KEYREQUEST format is invalid.
#PF(error code) If a page fault occurs in accessing memory.

64-Bit Mode Exceptions

#GP(0) If executed outside an enclave.
If a memory operand effective address is outside the current enclave.
If an effective address is not properly aligned.
If an effective address is not canonical.
If KEYREQUEST format is invalid.
#PF(error code) If a page fault occurs in accessing memory operands.