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. |
Op/En | EAX | RBX | RCX |
IR | EGETKEY (In) | Address to a KEYREQUEST (In) | Address of the OUTPUTDATA (In) |
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.
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 |
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. |
Leaf | Parameter | Base Concurrency Restrictions | ||
---|---|---|---|---|
Access | On Conflict | SGX_CONFLICT VM Exit Qualification | ||
EGETKEY | KEYREQUEST [DS:RBX] | Concurrent | ||
OUTPUTDATA [DS:RCX] | Concurrent |
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 |
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;
ZF is cleared if successful, otherwise ZF is set. CF, PF, AF, OF, SF are cleared.
#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. |
#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. |