/* Copyright (C) 2014 Stony Brook University This file is part of Graphene Library OS. Graphene Library OS is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Graphene Library OS is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef SGX_ARCH_H #define SGX_ARCH_H #include "pal_linux_defs.h" #ifndef __ASSEMBLER__ #include #include "assert.h" #pragma pack(push, 1) #define SE_KEY_SIZE 384 #define SE_EXPONENT_SIZE 4 #define SGX_HASH_SIZE 32 #define SGX_MAC_SIZE 16 typedef struct _sgx_measurement_t { uint8_t m[SGX_HASH_SIZE]; } sgx_measurement_t; typedef uint8_t sgx_mac_t[SGX_MAC_SIZE]; // This if for passing a mac to hex2str #define MACBUF_SIZE ((sizeof(sgx_mac_t) * 2) + 1) typedef struct _sgx_attributes_t { uint64_t flags; uint64_t xfrm; } sgx_attributes_t; #define SGX_CPUSVN_SIZE 16 #define SGX_CONFIGID_SIZE 64 #define SGX_KEYID_SIZE 32 #define SGX_REPORT_DATA_SIZE 64 typedef struct _sgx_cpu_svn_t { uint8_t svn[SGX_CPUSVN_SIZE]; } sgx_cpu_svn_t; typedef uint32_t sgx_misc_select_t; typedef uint16_t sgx_prod_id_t; typedef uint16_t sgx_isv_svn_t; typedef uint16_t sgx_config_svn_t; typedef uint8_t sgx_config_id_t[SGX_CONFIGID_SIZE]; #define SGX_ISVEXT_PROD_ID_SIZE 16 #define SGX_ISV_FAMILY_ID_SIZE 16 typedef uint8_t sgx_isvext_prod_id_t[SGX_ISVEXT_PROD_ID_SIZE]; typedef uint8_t sgx_isvfamily_id_t[SGX_ISV_FAMILY_ID_SIZE]; #define SGX_FLAGS_INITIALIZED 0x01ULL #define SGX_FLAGS_DEBUG 0x02ULL #define SGX_FLAGS_MODE64BIT 0x04ULL #define SGX_FLAGS_PROVISION_KEY 0x10ULL #define SGX_FLAGS_LICENSE_KEY 0x20ULL #define SGX_XFRM_LEGACY 0x03ULL #define SGX_XFRM_AVX 0x06ULL #define SGX_XFRM_MPX 0x18ULL #define SGX_XFRM_AVX512 0xe6ULL #define SGX_XFRM_RESERVED (~(SGX_XFRM_LEGACY | SGX_XFRM_AVX | SGX_XFRM_MPX | SGX_XFRM_AVX512)) #define SGX_MISCSELECT_EXINFO 0x01UL typedef struct { uint64_t size; uint64_t base; uint32_t ssa_frame_size; sgx_misc_select_t misc_select; uint8_t reserved1[24]; sgx_attributes_t attributes; sgx_measurement_t mr_enclave; uint8_t reserved2[32]; sgx_measurement_t mr_signer; uint8_t reserved3[32]; sgx_config_id_t config_id; sgx_prod_id_t isv_prod_id; sgx_isv_svn_t isv_svn; sgx_config_svn_t config_svn; uint8_t reserved4[3834]; } sgx_arch_secs_t; typedef struct { uint64_t reserved0; uint64_t flags; uint64_t ossa; uint32_t cssa; uint32_t nssa; uint64_t oentry; uint64_t reserved1; uint64_t ofs_base; uint64_t ogs_base; uint32_t ofs_limit; uint32_t ogs_limit; uint8_t reserved3[4024]; } sgx_arch_tcs_t; static_assert(sizeof(sgx_arch_tcs_t) == 4096, "incorrect struct size"); #define TCS_FLAGS_DBGOPTIN (01ULL) typedef struct { uint64_t rax; uint64_t rcx; uint64_t rdx; uint64_t rbx; uint64_t rsp; uint64_t rbp; uint64_t rsi; uint64_t rdi; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t rflags; uint64_t rip; uint64_t ursp; uint64_t urbp; uint32_t exitinfo; uint32_t reserved; uint64_t fsbase; uint64_t gsbase; } sgx_pal_gpr_t; typedef struct { uint64_t rax; uint64_t rcx; uint64_t rdx; uint64_t rbx; uint64_t rsp; uint64_t rbp; uint64_t rsi; uint64_t rdi; uint64_t r8; uint64_t r9; uint64_t r10; uint64_t r11; uint64_t r12; uint64_t r13; uint64_t r14; uint64_t r15; uint64_t rflags; uint64_t rip; } sgx_cpu_context_t; // Required by _restore_sgx_context, see enclave_entry.S. static_assert(offsetof(sgx_cpu_context_t, rip) - offsetof(sgx_cpu_context_t, rflags) == sizeof(((sgx_cpu_context_t){0}).rflags), "rip must be directly after rflags in sgx_cpu_context_t"); static_assert(offsetof(sgx_cpu_context_t, rip) - offsetof(sgx_cpu_context_t, r15) <= RED_ZONE_SIZE, "r15 needs to be within red zone distance from rip"); static_assert(offsetof(sgx_cpu_context_t, rip) - offsetof(sgx_cpu_context_t, rsp) <= RED_ZONE_SIZE, "rsp needs to be within red zone distance from rip"); typedef struct { uint32_t vector : 8; uint32_t exit_type : 3; uint32_t reserved : 20; uint32_t valid : 1; } sgx_arch_exit_info_t; #define SGX_EXCEPTION_HARDWARE 3UL #define SGX_EXCEPTION_SOFTWARE 6UL #define SGX_EXCEPTION_VECTOR_DE 0UL /* DIV and IDIV instructions */ #define SGX_EXCEPTION_VECTOR_DB 1UL /* For Intel use only */ #define SGX_EXCEPTION_VECTOR_BP 3UL /* INT 3 instruction */ #define SGX_EXCEPTION_VECTOR_BR 5UL /* BOUND instruction */ #define SGX_EXCEPTION_VECTOR_UD 6UL /* UD2 instruction or reserved opcodes */ #define SGX_EXCEPTION_VECTOR_MF 16UL /* x87 FPU floating-point or WAIT/FWAIT instruction */ #define SGX_EXCEPTION_VECTOR_AC 17UL /* Any data reference in memory */ #define SGX_EXCEPTION_VECTOR_XM 19UL /* Any SIMD floating-point exceptions */ typedef struct { uint64_t lin_addr; uint64_t src_pge; uint64_t sec_info; uint64_t secs; } sgx_arch_page_info_t; typedef struct { uint64_t flags; uint64_t reserved[7]; } sgx_arch_sec_info_t; #define SGX_SECINFO_FLAGS_R 0x001 #define SGX_SECINFO_FLAGS_W 0x002 #define SGX_SECINFO_FLAGS_X 0x004 #define SGX_SECINFO_FLAGS_SECS 0x000 #define SGX_SECINFO_FLAGS_TCS 0x100 #define SGX_SECINFO_FLAGS_REG 0x200 typedef struct _css_header_t { uint8_t header[12]; uint32_t type; uint32_t module_vendor; uint32_t date; uint8_t header2[16]; uint32_t hw_version; uint8_t reserved[84]; } css_header_t; static_assert(sizeof(css_header_t) == 128, "incorrect struct size"); typedef struct _css_key_t { uint8_t modulus[SE_KEY_SIZE]; uint8_t exponent[SE_EXPONENT_SIZE]; uint8_t signature[SE_KEY_SIZE]; } css_key_t; static_assert(sizeof(css_key_t) == 772, "incorrect struct size"); typedef struct _css_body_t { sgx_misc_select_t misc_select; sgx_misc_select_t misc_mask; uint8_t reserved[4]; sgx_isvfamily_id_t isv_family_id; sgx_attributes_t attributes; sgx_attributes_t attribute_mask; sgx_measurement_t enclave_hash; uint8_t reserved2[16]; sgx_isvext_prod_id_t isvext_prod_id; uint16_t isv_prod_id; uint16_t isv_svn; } css_body_t; static_assert(sizeof(css_body_t) == 128, "incorrect struct size"); typedef struct _css_buffer_t { uint8_t reserved[12]; uint8_t q1[SE_KEY_SIZE]; uint8_t q2[SE_KEY_SIZE]; } css_buffer_t; static_assert(sizeof(css_buffer_t) == 780, "incorrect struct size"); typedef struct _enclave_css_t { css_header_t header; css_key_t key; css_body_t body; css_buffer_t buffer; } sgx_arch_enclave_css_t; static_assert(sizeof(sgx_arch_enclave_css_t) == 1808, "incorrect struct size"); typedef struct _sgx_key_id_t { uint8_t id[SGX_KEYID_SIZE]; } sgx_key_id_t; typedef struct { uint32_t valid; uint32_t reserved1[11]; sgx_attributes_t attributes; sgx_measurement_t mr_enclave; uint8_t reserved2[32]; sgx_measurement_t mr_signer; uint8_t reserved3[32]; } launch_body_t; typedef struct { launch_body_t body; sgx_cpu_svn_t cpu_svn_le; sgx_prod_id_t isv_prod_id_le; sgx_isv_svn_t isv_svn_le; uint8_t reserved2[24]; sgx_misc_select_t masked_misc_select_le; sgx_attributes_t attributes_le; sgx_key_id_t key_id; sgx_mac_t mac; } sgx_arch_token_t; typedef struct _sgx_report_data_t { uint8_t d[SGX_REPORT_DATA_SIZE]; } sgx_report_data_t; #define __sgx_mem_aligned __attribute__((aligned(512))) typedef struct _report_body_t { sgx_cpu_svn_t cpu_svn; sgx_misc_select_t misc_select; uint8_t reserved1[28]; sgx_attributes_t attributes; sgx_measurement_t mr_enclave; uint8_t reserved2[32]; sgx_measurement_t mr_signer; uint8_t reserved3[96]; sgx_prod_id_t isv_prod_id; sgx_isv_svn_t isv_svn; uint8_t reserved4[60]; sgx_report_data_t report_data; } sgx_report_body_t; typedef struct _report_t { sgx_report_body_t body; sgx_key_id_t key_id; sgx_mac_t mac; } sgx_report_t; #define SGX_REPORT_SIGNED_SIZE 384 #define SGX_REPORT_ACTUAL_SIZE 432 typedef struct _target_info_t { sgx_measurement_t mr_enclave; sgx_attributes_t attributes; uint8_t reserved1[2]; sgx_config_svn_t config_svn; sgx_misc_select_t misc_select; uint8_t reserved2[8]; sgx_config_id_t config_id; uint8_t reserved3[384]; } sgx_target_info_t; static_assert(sizeof(sgx_target_info_t) == 512, "incorrect struct size"); typedef struct _key_request_t { uint16_t key_name; uint16_t key_policy; sgx_isv_svn_t isv_svn; uint16_t reserved1; sgx_cpu_svn_t cpu_svn; sgx_attributes_t attribute_mask; sgx_key_id_t key_id; sgx_misc_select_t misc_mask; sgx_config_svn_t config_svn; uint8_t reserved2[434]; // struct is 512-bytes in size, alignment is required for EGETKEY } sgx_key_request_t; static_assert(sizeof(sgx_key_request_t) == 512, "incorrect struct size"); #define SGX_TARGETINFO_FILLED_SIZE (sizeof(sgx_measurement_t) + sizeof(sgx_attributes_t)) typedef uint8_t sgx_key_128bit_t[16]; #define ENCLU ".byte 0x0f, 0x01, 0xd7" #else /* !__ASSEMBLER__ */ /* microcode to call ENCLU */ .macro ENCLU .byte 0x0f, 0x01, 0xd7 .endm #endif #define EENTER 2 #define ERESUME 3 #define EDBGRD 4 #define EDBGWR 5 #define EREPORT 0 #define EGETKEY 1 #define EEXIT 4 #define LAUNCH_KEY 0 #define PROVISION_KEY 1 #define PROVISION_SEAL_KEY 2 #define REPORT_KEY 3 #define SEAL_KEY 4 #define KEYPOLICY_MRENCLAVE 1 #define KEYPOLICY_MRSIGNER 2 #define XSAVE_SIZE 512 #define STACK_ALIGN 0xfffffffffffffff0 #define XSAVE_ALIGN 0xffffffffffffffc0 #define XSAVE_NON_FX_MASK 0xfffffffffffffffc #define RETURN_FROM_OCALL 0xffffffffffffffff #define RFLAGS_DF (1 << 10) #define RFLAGS_AC (1 << 18) #pragma pack(pop) #endif /* SGX_ARCH_H */