diff --git a/.gitmodules b/.gitmodules
index 3703d34a4..a4e439761 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -17,3 +17,7 @@
path = external/protobuf/protobuf_code
url = https://github.com/protocolbuffers/protobuf.git
branch = 3.14.x
+[submodule "external/sgx-emm/emm_src"]
+ path = external/sgx-emm/emm_src
+ url = https://github.com/intel/sgx-emm
+ branch = dev
diff --git a/SampleCode/SampleEnclave/Enclave/Enclave.config.xml b/SampleCode/SampleEnclave/Enclave/Enclave.config.xml
index e94c9bc50..83ec0679f 100644
--- a/SampleCode/SampleEnclave/Enclave/Enclave.config.xml
+++ b/SampleCode/SampleEnclave/Enclave/Enclave.config.xml
@@ -1,12 +1,23 @@
0
0
- 0x40000
- 0x100000
- 10
+ 1
+ 5
1
+ 13
+
+
+
+ 0x4000
+ 0x2000
+ 0x5000
+ 0x50000
+
0
- 0
+ 1
0xFFFFFFFF
diff --git a/SampleCode/SampleEnclave/Enclave/config.01.xml b/SampleCode/SampleEnclave/Enclave/config.01.xml
index ca652963f..2e1354499 100644
--- a/SampleCode/SampleEnclave/Enclave/config.01.xml
+++ b/SampleCode/SampleEnclave/Enclave/config.01.xml
@@ -23,6 +23,6 @@
0
- 0
+ 1
0xFFFFFFFF
diff --git a/SampleCode/SampleEnclave/Enclave/config.02.xml b/SampleCode/SampleEnclave/Enclave/config.02.xml
index 126eac07b..59b267388 100644
--- a/SampleCode/SampleEnclave/Enclave/config.02.xml
+++ b/SampleCode/SampleEnclave/Enclave/config.02.xml
@@ -20,6 +20,6 @@
1
0
- 0
+ 1
0xFFFFFFFF
diff --git a/SampleCode/SampleEnclave/Enclave/config.03.xml b/SampleCode/SampleEnclave/Enclave/config.03.xml
index ef642799b..3ccf61abc 100644
--- a/SampleCode/SampleEnclave/Enclave/config.03.xml
+++ b/SampleCode/SampleEnclave/Enclave/config.03.xml
@@ -22,6 +22,6 @@
0
- 0
+ 1
0xFFFFFFFF
diff --git a/SampleCode/SampleEnclave/Enclave/config.04.xml b/SampleCode/SampleEnclave/Enclave/config.04.xml
index a72d611b5..028445402 100644
--- a/SampleCode/SampleEnclave/Enclave/config.04.xml
+++ b/SampleCode/SampleEnclave/Enclave/config.04.xml
@@ -18,6 +18,6 @@
0
- 0
+ 1
0xFFFFFFFF
diff --git a/common/inc/internal/arch.h b/common/inc/internal/arch.h
index 54f31ded6..8cfa683e6 100644
--- a/common/inc/internal/arch.h
+++ b/common/inc/internal/arch.h
@@ -124,6 +124,8 @@ typedef struct _exit_info_t
#define SE_VECTOR_BP 3
#define SE_VECTOR_BR 5
#define SE_VECTOR_UD 6
+#define SE_VECTOR_GP 13
+#define SE_VECTOR_PF 14
#define SE_VECTOR_MF 16
#define SE_VECTOR_AC 17
#define SE_VECTOR_XM 19
@@ -156,6 +158,15 @@ typedef struct _ssa_gpr_t
uint64_t gs; /* (176) GS register */
} ssa_gpr_t;
+typedef struct _misc_exinfo
+{
+ uint64_t maddr; // address for #PF, #GP.
+ uint32_t errcd;
+ uint32_t reserved;
+} misc_exinfo_t;
+
+#define MISC_BYTE_SIZE sizeof(misc_exinfo_t)
+
typedef uint64_t si_flags_t;
#define SI_FLAG_NONE 0x0
diff --git a/common/inc/internal/bit_array.h b/common/inc/internal/bit_array.h
new file mode 120000
index 000000000..8b14d3a15
--- /dev/null
+++ b/common/inc/internal/bit_array.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/bit_array.h
\ No newline at end of file
diff --git a/common/inc/internal/bit_array_imp.h b/common/inc/internal/bit_array_imp.h
new file mode 120000
index 000000000..c30a510f2
--- /dev/null
+++ b/common/inc/internal/bit_array_imp.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/bit_array_imp.h
\ No newline at end of file
diff --git a/common/inc/internal/ema.h b/common/inc/internal/ema.h
new file mode 120000
index 000000000..1cd936219
--- /dev/null
+++ b/common/inc/internal/ema.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/ema.h
\ No newline at end of file
diff --git a/common/inc/internal/ema_imp.h b/common/inc/internal/ema_imp.h
new file mode 120000
index 000000000..41b8b3d22
--- /dev/null
+++ b/common/inc/internal/ema_imp.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/ema_imp.h
\ No newline at end of file
diff --git a/common/inc/internal/emm_private.h b/common/inc/internal/emm_private.h
new file mode 120000
index 000000000..cf6d63de1
--- /dev/null
+++ b/common/inc/internal/emm_private.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/emm_private.h
\ No newline at end of file
diff --git a/common/inc/internal/enclave_creator.h b/common/inc/internal/enclave_creator.h
index 4b5328055..8fde80547 100644
--- a/common/inc/internal/enclave_creator.h
+++ b/common/inc/internal/enclave_creator.h
@@ -81,10 +81,10 @@ class EnclaveCreator : private Uncopyable
virtual uint32_t handle_page_fault(uint64_t pf_address) { UNUSED(pf_address); return (uint32_t)SGX_ERROR_UNEXPECTED; }
#endif
virtual int emodpr(uint64_t addr, uint64_t size, uint64_t flag) = 0;
+ virtual int alloc(uint64_t addr, uint64_t size, int flag) = 0;
virtual int mktcs(uint64_t tcs_addr) = 0;
virtual int trim_range(uint64_t fromaddr, uint64_t toaddr) = 0;
virtual int trim_accept(uint64_t addr) = 0;
- virtual int remove_range(uint64_t fromaddr, uint64_t numpages) = 0;
// destructor
virtual ~EnclaveCreator() {};
diff --git a/common/inc/internal/inst.h b/common/inc/internal/inst.h
index 4f2b35756..aa22de72f 100644
--- a/common/inc/internal/inst.h
+++ b/common/inc/internal/inst.h
@@ -46,7 +46,9 @@ typedef enum {
SE_ERESUME,
SE_EEXIT,
SE_EACCEPT,
- SE_EVERIFYREPORT2 = 0x8,
+ SE_EMODPE,
+ SE_EACCEPTCOPY,
+ SE_EVERIFYREPORT2,
SE_LAST_RING3,
SE_ECREATE = 0x0,
diff --git a/common/inc/internal/linux/linux-regs.h b/common/inc/internal/linux/linux-regs.h
index 48a206d3b..8741edc2e 100644
--- a/common/inc/internal/linux/linux-regs.h
+++ b/common/inc/internal/linux/linux-regs.h
@@ -88,6 +88,7 @@
#define SE_EEXIT 4
#define SE_EACCEPT 5
#define SE_EMODPE 6
+#define SE_EACCEPTCOPY 7
#define SE_EVERIFYREPORT2 8
diff --git a/common/inc/internal/metadata.h b/common/inc/internal/metadata.h
index ec121a730..dac267a81 100644
--- a/common/inc/internal/metadata.h
+++ b/common/inc/internal/metadata.h
@@ -37,10 +37,10 @@
#pragma pack(1)
/* version of metadata */
-#define MAJOR_VERSION 2 //MAJOR_VERSION should not larger than 0ffffffff
-#define MINOR_VERSION 4 //MINOR_VERSION should not larger than 0ffffffff
+#define MAJOR_VERSION 3 //MAJOR_VERSION should not larger than 0ffffffff
+#define MINOR_VERSION 0 //MINOR_VERSION should not larger than 0ffffffff
-#define SGX_2_ELRANGE_MAJOR_VERSION 12
+#define SGX_2_ELRANGE_MAJOR_VERSION 13
#define SGX_1_ELRANGE_MAJOR_VERSION 11
#define SGX_MAJOR_VERSION_GAP 10
@@ -84,6 +84,7 @@
#define HEAP_SIZE_MAX 0x1000000 /* 16 MB */
#define RSRV_SIZE_MIN 0x0000000 /* 0 KB */
#define RSRV_SIZE_MAX 0x0000000 /* 0 KB */
+#define USER_REGION_SIZE 0x0000000 /* 0 KB */
#define DEFAULT_MISC_SELECT 0
#define DEFAULT_MISC_MASK 0xFFFFFFFF
#define ISVFAMILYID_MAX 0xFFFFFFFFFFFFFFFFULL
@@ -128,6 +129,7 @@ typedef enum
#define LAYOUT_ID_RSRV_MIN (20)
#define LAYOUT_ID_RSRV_INIT (21)
#define LAYOUT_ID_RSRV_MAX (22)
+#define LAYOUT_ID_USER_REGION (23)
extern const char * layout_id_str[];
diff --git a/common/inc/internal/rts.h b/common/inc/internal/rts.h
index e94ad56be..612cd8454 100644
--- a/common/inc/internal/rts.h
+++ b/common/inc/internal/rts.h
@@ -65,7 +65,8 @@ typedef enum
SDK_VERSION_2_0,
SDK_VERSION_2_1,
SDK_VERSION_2_2,
- SDK_VERSION_2_3
+ SDK_VERSION_2_3,
+ SDK_VERSION_3_0,
} sdk_version_t;
typedef struct _system_features
@@ -95,6 +96,8 @@ typedef struct _system_features
#define BUILTIN_OCALL_2 -3
#define BUILTIN_OCALL_3 -4
#define BUILTIN_OCALL_4 -5
+#define BUILTIN_OCALL_5 -6
+#define BUILTIN_OCALL_6 -7
typedef enum
{
@@ -102,10 +105,12 @@ typedef enum
EDMM_TRIM_COMMIT = BUILTIN_OCALL_2,
EDMM_MODPR = BUILTIN_OCALL_3,
EDMM_MPROTECT = BUILTIN_OCALL_4,
+ EDMM_ALLOC = BUILTIN_OCALL_5,
+ EDMM_MODIFY = BUILTIN_OCALL_6,
}edmm_ocall_t;
-#define is_builtin_ocall(ocall_val) (((int)ocall_val >= BUILTIN_OCALL_4) && ((int)ocall_val <= BUILTIN_OCALL_1))
+#define is_builtin_ocall(ocall_val) (((int)ocall_val >= BUILTIN_OCALL_6) && ((int)ocall_val <= BUILTIN_OCALL_1))
#pragma pack(pop)
diff --git a/common/inc/internal/rts_cmd.h b/common/inc/internal/rts_cmd.h
index 725e34dc6..d0fabdfd6 100644
--- a/common/inc/internal/rts_cmd.h
+++ b/common/inc/internal/rts_cmd.h
@@ -40,6 +40,8 @@
#define ECMD_ECALL_PTHREAD (-6)
+#define ECMD_INTERRUPT (-32)
+
/* Reserved for 3rd party usage */
#define RESERVED_FOR_3RD_PARTY_START -100
#define RESERVED_FOR_3RD_PARTY_END -1000
diff --git a/common/inc/internal/se_event.h b/common/inc/internal/se_event.h
index 99fb4de8a..b4e6bd81a 100644
--- a/common/inc/internal/se_event.h
+++ b/common/inc/internal/se_event.h
@@ -34,6 +34,8 @@
# include
# include
+# include
+# include
# include
typedef void * se_handle_t;
@@ -53,6 +55,7 @@ se_handle_t SGXAPI se_event_init(void);
void SGXAPI se_event_destroy(se_handle_t);
int SGXAPI se_event_wait(se_handle_t);
+int SGXAPI se_event_timeout_wait(se_handle_t, int, const struct timespec *, int, int *);
int SGXAPI se_event_wait_timeout(se_handle_t se_event, uint64_t timeout);
int SGXAPI se_event_wake(se_handle_t);
diff --git a/common/inc/internal/sethread_spinlock.h b/common/inc/internal/sethread_spinlock.h
new file mode 100644
index 000000000..2c7a1863a
--- /dev/null
+++ b/common/inc/internal/sethread_spinlock.h
@@ -0,0 +1,59 @@
+
+/*
+ * Copyright (C) 2022 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _SE_THREAD_SPINLOCK_H_
+#define _SE_THREAD_SPINLOCK_H_
+#include "sgx_thread.h"
+/** a recursive spin lock */
+typedef struct _sgx_thread_spinlock_t
+{
+ size_t m_refcount; /* number of recursive calls */
+ volatile uint32_t m_lock; /* use sgx_spinlock_t */
+ sgx_thread_t m_owner;
+} sgx_thread_spinlock_t;
+
+#define SGX_THREAD_RECURSIVE_SPINLOCK_INITIALIZER \
+ {0, 0, SGX_THREAD_T_NULL}
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int sgx_thread_spin_init(sgx_thread_spinlock_t *mutex);
+int sgx_thread_spin_destroy(sgx_thread_spinlock_t *mutex);
+
+int sgx_thread_spin_trylock(sgx_thread_spinlock_t *mutex);
+int sgx_thread_spin_unlock(sgx_thread_spinlock_t *mutex);
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/common/inc/internal/sgx_mm_rt_abstraction.h b/common/inc/internal/sgx_mm_rt_abstraction.h
new file mode 120000
index 000000000..c396ee7b4
--- /dev/null
+++ b/common/inc/internal/sgx_mm_rt_abstraction.h
@@ -0,0 +1 @@
+../../../external/sgx-emm/emm_src/include/sgx_mm_rt_abstraction.h
\ No newline at end of file
diff --git a/common/inc/internal/trts_inst.h b/common/inc/internal/trts_inst.h
index 354148dcc..ffb7f80a2 100644
--- a/common/inc/internal/trts_inst.h
+++ b/common/inc/internal/trts_inst.h
@@ -74,17 +74,13 @@ struct ms_tcs
extern "C" {
#endif
-int sgx_accept_forward(si_flags_t sfl, size_t lo, size_t hi);
int do_ereport(const sgx_target_info_t *target_info, const sgx_report_data_t *report_data, sgx_report_t *report);
int do_everifyreport2(const sgx_report2_mac_struct_t *report2_mac_struct);
int do_egetkey(const sgx_key_request_t *key_request, sgx_key_128bit_t *key);
uint32_t do_rdrand(uint32_t *rand);
int do_eaccept(const sec_info_t *, size_t);
+int do_eacceptcopy(const sec_info_t *, size_t, size_t);
int do_emodpe(const sec_info_t*, size_t);
-int apply_EPC_pages(void *start_address, size_t page_number);
-int apply_pages_within_exception(void *start_address, size_t page_count);
-int trim_EPC_pages(void *start_address, size_t page_number);
-sgx_status_t SGXAPI trts_mprotect(size_t start, size_t size, uint64_t perms);
sgx_status_t do_add_thread(void *ms);
int is_dynamic_thread(void *tcs);
int is_dynamic_thread_exist(void);
diff --git a/common/inc/sgx_attributes.h b/common/inc/sgx_attributes.h
index 4f5e18008..955e69595 100644
--- a/common/inc/sgx_attributes.h
+++ b/common/inc/sgx_attributes.h
@@ -49,7 +49,7 @@
#define SGX_XFRM_MPX 0x0000000000000018ULL /* MPX XFRM - not supported */
#define SGX_XFRM_PKRU 0x0000000000000200ULL /* PKRU state */
-#define SGX_XFRM_RESERVED (~(SGX_XFRM_LEGACY | SGX_XFRM_AVX | SGX_XFRM_AVX512 | SGX_XFRM_PKRU))
+#define SGX_XFRM_RESERVED (~(SGX_XFRM_LEGACY | SGX_XFRM_AVX | SGX_XFRM_AVX512 | SGX_XFRM_MPX | SGX_XFRM_PKRU))
typedef struct _attributes_t
{
diff --git a/common/inc/sgx_interrupt.h b/common/inc/sgx_interrupt.h
new file mode 100644
index 000000000..e2ca93269
--- /dev/null
+++ b/common/inc/sgx_interrupt.h
@@ -0,0 +1,65 @@
+#ifndef _SGX_INTERRUPT_H_
+#define _SGX_INTERRUPT_H_
+
+// An interrupt mechanism for dynamically-loaded workloads in enclaves.
+//
+// Workloads in an enclave can be classified into two categories: statically-loaded and
+// dynamically-loaded workloads. Statically-loaded workloads are application code that
+// are built into the enclave; that is, they are part of the enclave since enclave initialization.
+// Dynamically-loaded workloads, as the name suggests, are application code loaded after
+// the enclave gets running.
+//
+// One typical example of dynamically-loaded workloads is user programs loaded by a SGX
+// LibOS. The user programs could be arbitrary code. As a result, once the user program
+// gets executed, the LibOS may never have the opportunity to take control of the CPU.
+// Without the ability to regain the control, it is impossible for the LibOS to implement
+// features like interruptible signal handler or preemptive in-enclave thread scheduling.
+//
+// To address the issue above, we implement the signal-based interrupt mechanism for
+// dynamically-loaded workloads. With the provided APIs, the users can now interrupt the
+// dynamically-loaded workloads executed in a SGX thread by simply sending a real-time
+// POSIX signal (whosenumber is 64, the max value of signal numbers on Linux) to the SGX
+// thread. The signal will be captured and (if the timing is good) a pre-registered
+// interrupt handler will get executed inside the enclave.
+//
+// Note that the interrupt mechanism only performs the signal-to-interrupt conversion
+// described above is in a best-effort manner. That is, sending a signal may not
+// result in the interrupt handler getting called. For example, if the target SGX thread is
+// executing some code outside the enclave, then the signal received will be simply
+// ignored, thus not triggering the interrupt handler to be executed. So the users of
+// the interrupt mechanism should find other means to determine if an interrupt has been
+// delivered, and if not, whether and when to resend the interrupt (via POSIX signal).
+
+#include "sgx_error.h"
+#include "sgx_trts_exception.h"
+
+// A data structure that represents an interrupt
+typedef struct _sgx_interrupt_info_t {
+ sgx_cpu_context_t cpu_context;
+} sgx_interrupt_info_t;
+
+// A handler function that processes an interrupt
+typedef void (*sgx_interrupt_handler_t)(sgx_interrupt_info_t*);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Initialize the interrupt mechanism for SGX threads.
+sgx_status_t SGXAPI sgx_interrupt_init(sgx_interrupt_handler_t handler);
+
+// Make the current thread interruptible when executing in the given code region.
+//
+// By default, a SGX thread is not interruptible. It is the responsibility of the
+// caller of this API to ensure that the given code region is ok to be interrupted,
+// e.g., not causing deadlocks.
+sgx_status_t SGXAPI sgx_interrupt_enable(size_t code_addr, size_t code_size);
+
+// Make the current thread uninterruptible.
+sgx_status_t SGXAPI sgx_interrupt_disable(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SGX_INTERRUPT_H_ */
diff --git a/common/inc/sgx_mm.h b/common/inc/sgx_mm.h
new file mode 120000
index 000000000..ec4db6615
--- /dev/null
+++ b/common/inc/sgx_mm.h
@@ -0,0 +1 @@
+../../external/sgx-emm/emm_src/include/sgx_mm.h
\ No newline at end of file
diff --git a/common/inc/sgx_mm_primitives.h b/common/inc/sgx_mm_primitives.h
new file mode 120000
index 000000000..88d2c9b61
--- /dev/null
+++ b/common/inc/sgx_mm_primitives.h
@@ -0,0 +1 @@
+../../external/sgx-emm/emm_src/include/sgx_mm_primitives.h
\ No newline at end of file
diff --git a/common/inc/sgx_mm_rt_abstraction.h b/common/inc/sgx_mm_rt_abstraction.h
new file mode 120000
index 000000000..8ffd119d4
--- /dev/null
+++ b/common/inc/sgx_mm_rt_abstraction.h
@@ -0,0 +1 @@
+../../external/sgx-emm/emm_src/include/sgx_mm_rt_abstraction.h
\ No newline at end of file
diff --git a/common/inc/sgx_occlum_utils.edl b/common/inc/sgx_occlum_utils.edl
new file mode 100644
index 000000000..5996b5621
--- /dev/null
+++ b/common/inc/sgx_occlum_utils.edl
@@ -0,0 +1,6 @@
+enclave {
+ untrusted {
+ /* Go outside and wait on my untrusted event with timeout */
+ [cdecl] int sgx_thread_wait_untrusted_event_timeout_ocall([user_check] const void *self, int clockbit, [in] const struct sgx_edl_timespec* ts, int absolute_time, [out] int* err);
+ };
+};
diff --git a/common/inc/sgx_random_buffers.h b/common/inc/sgx_random_buffers.h
index 721de3d7f..0a78bae11 100644
--- a/common/inc/sgx_random_buffers.h
+++ b/common/inc/sgx_random_buffers.h
@@ -164,7 +164,12 @@ struct alignas(A)randomly_placed_buffer
// used for objects without a constructor.
T *randomize_object(std::size_t count = 1)
{
- return (T*)(reset(count).__bigger_ + ((rdrand() % M) & ~(A - 1)));
+#if defined(MAXIMAL_CALLSTACK)
+ unsigned rand_size = M - 1;
+#else
+ unsigned rand_size = rdrand() % M;
+#endif
+ return (T*)(reset(count).__bigger_ + ((rand_size) & ~(A - 1)));
}
// instantiate_object() invokes T's constructor on the object returned by
diff --git a/common/inc/sgx_tprotected_fs.edl b/common/inc/sgx_tprotected_fs.edl
index b6f0b8c3f..5cd025da7 100644
--- a/common/inc/sgx_tprotected_fs.edl
+++ b/common/inc/sgx_tprotected_fs.edl
@@ -14,7 +14,6 @@
* * Neither the name of Intel Corporation nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
- *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
diff --git a/common/inc/sgx_tprotected_fs.h b/common/inc/sgx_tprotected_fs.h
index dbd5abf91..acb6dbe32 100644
--- a/common/inc/sgx_tprotected_fs.h
+++ b/common/inc/sgx_tprotected_fs.h
@@ -45,6 +45,7 @@
#include "sgx_defs.h"
#include "sgx_key.h"
+#include "sgx_tcrypto.h"
#define SGX_FILE void
@@ -94,6 +95,43 @@ SGX_FILE* SGXAPI sgx_fopen(const char* filename, const char* mode, const sgx_key
SGX_FILE* SGXAPI sgx_fopen_auto_key(const char* filename, const char* mode);
+/* sgx_fopen_integrity_only
+* Purpose: open existing protected file (created with previous call to sgx_fopen_integrity_only) or create a new one (see c++ fopen documentation for more details).
+* This API skips encryption and only performs MAC calculation/validation, thus protecting the file's integrity, not confidentiality.
+*
+* Parameters:
+* filename - [IN] the name of the file to open/create.
+* mode - [IN] open mode. only supports 'r' or 'w' or 'a' (one and only one of them must be present), and optionally 'b' and/or '+'.
+*
+* Return value:
+* SGX_FILE* - pointer to the newly created file handle, NULL if an error occurred - check errno for the error code.
+*/
+SGX_FILE* SGXAPI sgx_fopen_integrity_only(const char* filename, const char* mode);
+
+
+/* sgx_fopen_ex
+ * Purpose: Expert version of sgx_fopen/sgx_fopen_auto_key which is used if you want to control the internal `cache size`.
+ * The specified `cache size` must be page (4KB by default) aligned.
+ * Note that `sgx_fexport_auto_key` and `sgx_fimport_auto_key` don't support configuring `cache_size` right now
+ *
+ * Parameters:
+ * filename - [IN] the name of the file to open/create.
+ * mode - [IN] open mode. only supports 'r' or 'w' or 'a' (one and only one of them must be present), and optionally 'b' and/or '+'.
+ * key - [IN] encryption key that will be used for the file encryption.
+ * If it's NULL, we will swtich back to `sgx_fopen_auto_key and use enclave's seal key to protect the file
+ * NOTE - the key is actually used as a KDK (key derivation key) and only for the meta-data node, and not used directly for the encryption of any part of the file
+ * this is important in order to prevent hitting the key wear-out problem, and some other issues with GCM encryptions using the same key
+ * cache_size - [IN] Internal cache size in byte, which used to cache R/W data in enclave before flush to actual file
+ * It must larger than default cache size (192KB), and must be page (4KB by default) aligned
+ * a) Please make sure enclave heap is enough for the `cache`, e.g. Configure enough heap in enclave config file
+ * b) All the data in cache may lost after exeception, please try to call `sgx_fflush` explicitly to avoid data loss
+ *
+ * Return value:
+ * SGX_FILE* - pointer to the newly created file handle, NULL if an error occurred - check errno for the error code.
+*/
+SGX_FILE* SGXAPI sgx_fopen_ex(const char* filename, const char* mode, const sgx_key_128bit_t *key, const uint64_t cache_size);
+
+
/* sgx_fwrite
* Purpose: write data to a file (see c++ fwrite documentation for more details).
*
@@ -101,7 +139,7 @@ SGX_FILE* SGXAPI sgx_fopen_auto_key(const char* filename, const char* mode);
* ptr - [IN] pointer to the input data buffer
* size - [IN] size of data block
* count - [IN] count of data blocks to write
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* size_t - number of 'size' blocks written to the file, 0 in case of an error - check sgx_ferror for error code
@@ -116,7 +154,7 @@ size_t SGXAPI sgx_fwrite(const void* ptr, size_t size, size_t count, SGX_FILE* s
* ptr - [OUT] pointer to the output data buffer
* size - [IN] size of data block
* count - [IN] count of data blocks to write
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* size_t - number of 'size' blocks read from the file, 0 in case of an error - check sgx_ferror for error code
@@ -128,7 +166,7 @@ size_t SGXAPI sgx_fread(void* ptr, size_t size, size_t count, SGX_FILE* stream);
* Purpose: get the current value of the position indicator of the file (see c++ ftell documentation for more details).
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int64_t - the current value of the position indicator, -1 on error - check errno for the error code
@@ -140,7 +178,7 @@ int64_t SGXAPI sgx_ftell(SGX_FILE* stream);
* Purpose: set the current value of the position indicator of the file (see c++ fseek documentation for more details).
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
* offset - [IN] the new required value, relative to the origin parameter
* origin - [IN] the origin from which to calculate the offset (SEEK_SET, SEEK_CUR or SEEK_END)
*
@@ -154,7 +192,7 @@ int32_t SGXAPI sgx_fseek(SGX_FILE* stream, int64_t offset, int origin);
* Purpose: force actual write of all the cached data to the disk (see c++ fflush documentation for more details).
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int32_t - result, 0 on success, 1 in case of an error - check sgx_ferror for error code
@@ -166,7 +204,7 @@ int32_t SGXAPI sgx_fflush(SGX_FILE* stream);
* Purpose: get the latest operation error code (see c++ ferror documentation for more details).
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int32_t - the error code, 0 means no error, anything else is the latest operation error code
@@ -178,7 +216,7 @@ int32_t SGXAPI sgx_ferror(SGX_FILE* stream);
* Purpose: did the file's position indicator hit the end of the file in a previous read operation (see c++ feof documentation for more details).
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int32_t - 1 - end of file was reached, 0 - end of file wasn't reached
@@ -191,7 +229,7 @@ int32_t SGXAPI sgx_feof(SGX_FILE* stream);
* call sgx_ferror or sgx_feof after a call to this function to learn if it was successful or not
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* none
@@ -204,7 +242,7 @@ void SGXAPI sgx_clearerr(SGX_FILE* stream);
* after a call to this function, the handle is invalid even if an error is returned
*
* Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
+ * stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int32_t - result, 0 - file was closed successfully, 1 - there were errors during the operation
@@ -261,7 +299,7 @@ int32_t SGXAPI sgx_fimport_auto_key(const char* filename, const sgx_key_128bit_t
* if a user wishes to remove all secrets from memory, he should close the file handle with sgx_fclose
*
* Parameters:
-* stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key
+* stream - [IN] the file handle (opened with sgx_fopen*)
*
* Return value:
* int32_t - result, 0 - success, 1 - there was an error, check errno for the error code
@@ -269,6 +307,19 @@ int32_t SGXAPI sgx_fimport_auto_key(const char* filename, const sgx_key_128bit_t
int32_t SGXAPI sgx_fclear_cache(SGX_FILE* stream);
+/* sgx_fget_mac
+* Purpose: get the MAC of the file. To ensure the MAC reflects all the content in the file,
+* sgx_fflush will be called automatically before getting the MAC. It is the caller's responsibility of not doing any writes before
+* this function returns the MAC.
+*
+* Parameters:
+* stream - [IN] the file handle (opened with sgx_fopen*)
+*
+* Return value:
+* int32_t - result, 0 - success, 1 - there was an error, check errno for the error code
+*/
+int32_t SGXAPI sgx_fget_mac(SGX_FILE* stream, sgx_aes_gcm_128bit_tag_t* mac);
+
#ifdef __cplusplus
}
#endif
diff --git a/common/inc/sgx_trts_exception.h b/common/inc/sgx_trts_exception.h
index 3e04c3255..83cdd5cb4 100644
--- a/common/inc/sgx_trts_exception.h
+++ b/common/inc/sgx_trts_exception.h
@@ -54,6 +54,7 @@ typedef enum _sgx_exception_vector_t
SGX_EXCEPTION_VECTOR_BP = 3, /* INT 3 instruction */
SGX_EXCEPTION_VECTOR_BR = 5, /* BOUND instruction */
SGX_EXCEPTION_VECTOR_UD = 6, /* UD2 instruction or reserved opcode */
+ SGX_EXCEPTION_VECTOR_PF = 14, /* page fault */
SGX_EXCEPTION_VECTOR_MF = 16, /* x87 FPU floating-point or WAIT/FWAIT instruction */
SGX_EXCEPTION_VECTOR_AC = 17, /* Any data reference in memory */
SGX_EXCEPTION_VECTOR_XM = 19, /* SSE/SSE2/SSE3 floating-point instruction */
@@ -103,11 +104,19 @@ typedef struct _cpu_context_t
} sgx_cpu_context_t;
#endif
+typedef struct _exinfo_t
+{
+ uint64_t faulting_address;
+ uint32_t error_code;
+ uint32_t reserved;
+}sgx_misc_exinfo_t;
+
typedef struct _exception_info_t
{
sgx_cpu_context_t cpu_context;
sgx_exception_vector_t exception_vector;
sgx_exception_type_t exception_type;
+ sgx_misc_exinfo_t exinfo;
} sgx_exception_info_t;
typedef int (*sgx_exception_handler_t)(sgx_exception_info_t *info);
diff --git a/common/inc/sgx_tstdc.edl b/common/inc/sgx_tstdc.edl
index 7e5769132..0ec65f723 100644
--- a/common/inc/sgx_tstdc.edl
+++ b/common/inc/sgx_tstdc.edl
@@ -30,9 +30,15 @@
*/
enclave {
+ /* Define libc's timespec_t for EDL */
+ struct sgx_edl_timespec {
+ int64_t sec;
+ int64_t nsec;
+ };
+
untrusted {
[cdecl] void sgx_oc_cpuidex([out] int cpuinfo[4], int leaf, int subleaf);
-
+
/* Go outside and wait on my untrusted event */
[cdecl] int sgx_thread_wait_untrusted_event_ocall([user_check] const void *self);
diff --git a/common/se_wrapper/Makefile b/common/se_wrapper/Makefile
index d741a7b9c..92ff48abc 100644
--- a/common/se_wrapper/Makefile
+++ b/common/se_wrapper/Makefile
@@ -43,7 +43,8 @@ OBJS := se_memory.o \
se_event.o \
se_rwlock.o \
se_time.o \
- se_map.o
+ se_map.o \
+ se_event_timeout_wait.o
LIBWRAPPER := libwrapper.a
diff --git a/common/se_wrapper_psw/Makefile b/common/se_wrapper_psw/Makefile
index e776c2b25..92ff48abc 100644
--- a/common/se_wrapper_psw/Makefile
+++ b/common/se_wrapper_psw/Makefile
@@ -34,7 +34,7 @@ include ../../buildenv.mk
CFLAGS += -Werror -D_GNU_SOURCE -fPIC
CFLAGS += $(ADDED_INC)
-CPPFLAGS := -I$(SGX_HEADER_DIR) \
+CPPFLAGS := -I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal
OBJS := se_memory.o \
@@ -43,7 +43,8 @@ OBJS := se_memory.o \
se_event.o \
se_rwlock.o \
se_time.o \
- se_map.o
+ se_map.o \
+ se_event_timeout_wait.o
LIBWRAPPER := libwrapper.a
diff --git a/common/src/se_event_timeout_wait.c b/common/src/se_event_timeout_wait.c
new file mode 100644
index 000000000..6ab337479
--- /dev/null
+++ b/common/src/se_event_timeout_wait.c
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011-2020 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include "se_event.h"
+
+#include
+#include
+
+int se_event_timeout_wait(se_handle_t se_event, int clockbit, const struct timespec *ts, int absolute_time, int *err)
+{
+ int ret = 0;
+
+ if (se_event == NULL || err == NULL)
+ return SE_MUTEX_INVALID;
+
+ if (__sync_fetch_and_add((int*)se_event, -1) == 0) {
+ // From futex man page:
+ // For FUTEX_WAIT, timeout is interpreted as a relative value. This differs from other futex operations, where
+ // timeout is interpreted as an absolute value. To obtain the equivalent of FUTEX_WAIT with an absolute timeout,
+ // employ FUTEX_WAIT_BITSET with val3 specified as FUTEX_BITSET_MATCH_ANY.
+ if (absolute_time == 1) {
+ ret = (int)syscall(__NR_futex, se_event, FUTEX_WAIT_BITSET | clockbit, -1, ts, NULL, FUTEX_BITSET_MATCH_ANY);
+ } else {
+ // FUTEX_WAIT can't work with FUTEX_CLOCK_REALTIME in Linux. Thus, ignore the clockbit.
+ // Reference: https://github.com/torvalds/linux/commit/4fbf5d6837bf81fd7a27d771358f4ee6c4f243f8
+ ret = (int)syscall(__NR_futex, se_event, FUTEX_WAIT, -1, ts, NULL, 0);
+ }
+ __sync_val_compare_and_swap((int*)se_event, -1, 0);
+ }
+ *err = ret < 0 ? errno : 0;
+
+ return SE_MUTEX_SUCCESS;
+}
diff --git a/compile_and_install.sh b/compile_and_install.sh
new file mode 100755
index 000000000..d48319d92
--- /dev/null
+++ b/compile_and_install.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -e
+
+pushd `dirname $0` > /dev/null
+SCRIPT_PATH=`pwd`
+popd > /dev/null
+
+# Uninstall old sdk
+sudo /opt/intel/sgxsdk/uninstall.sh || true
+
+# Compile SDK and install
+make USE_OPT_LIBS=3 sdk_no_mitigation
+make sdk_install_pkg_no_mitigation
+sudo mkdir -p /opt/intel
+cd /opt/intel
+yes yes | sudo ${SCRIPT_PATH}/linux/installer/bin/sgx_linux_x64_sdk_*.bin
+source /opt/intel/sgxsdk/environment
+
+cd ${SCRIPT_PATH}
+make -C psw/urts/linux
+cd build/linux
+ln -sf libsgx_enclave_common.so libsgx_enclave_common.so.1
+export LD_LIBRARY_PATH=${SCRIPT_PATH}/build/linux/
+
+cd ${SCRIPT_PATH}/external/sgx-emm/api_tests/
+make clean
+make
+./test_mm_api
+
diff --git a/external/sgx-emm/Makefile b/external/sgx-emm/Makefile
new file mode 100644
index 000000000..43c82abec
--- /dev/null
+++ b/external/sgx-emm/Makefile
@@ -0,0 +1,66 @@
+# Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+include ../../buildenv.mk
+
+HAVE_PRIMITIVES ?= 1
+
+CPPFLAGS += -Iemm_src/include \
+ -I$(COMMON_DIR)/inc/tlibc \
+ -Wno-missing-braces -Wno-unused-parameter
+
+C_Files := $(wildcard emm_src/*.c)
+OBJS := $(C_Files:.c=.o)
+OBJS := $(sort $(OBJS))
+
+ifneq ($(HAVE_PRIMITIVES), 1)
+ASM_OBJ := emm_src/sgx_primitives.o
+endif
+
+LIB_NAME := libsgx_mm.a
+
+.PHONY: all
+all: $(LIB_NAME) | $(BUILD_DIR)
+ $(CP) $(LIB_NAME) $|
+
+$(LIB_NAME): $(OBJS) $(ASM_OBJ)
+ $(AR) rcs $@ $^
+
+$(ASM_OBJ): %.o: %.S
+ $(CC) $(COMMON_FLAGS) $(ENCLAVE_CFLAGS) $(CPPFLAGS) -c $< -o $@
+
+$(OBJS): %.o: %.c
+ $(CC) -c $(COMMON_FLAGS) $(ENCLAVE_CFLAGS) $(CPPFLAGS) $< -o $@
+
+$(BUILD_DIR):
+ @$(MKDIR) $@
+
+.PHONY: clean
+clean:
+ @$(RM) $(LIB_NAME) $(ASM_OBJ) $(OBJS) $(BUILD_DIR)/$(LIB_NAME) *.bak *~
+
diff --git a/external/sgx-emm/api_tests/App/App.cpp b/external/sgx-emm/api_tests/App/App.cpp
new file mode 100644
index 000000000..91d16b503
--- /dev/null
+++ b/external/sgx-emm/api_tests/App/App.cpp
@@ -0,0 +1,420 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+
+#include
+#include
+#include
+
+#include
+#include
+#include
+
+# include
+# include
+# define MAX_PATH FILENAME_MAX
+
+#include "sgx_urts.h"
+#include "App.h"
+#include "Enclave_u.h"
+#include "../tcs.h"
+using namespace std;
+
+/* Global EID shared by multiple threads */
+sgx_enclave_id_t global_eid = 0;
+
+typedef struct _sgx_errlist_t {
+ sgx_status_t err;
+ const char *msg;
+ const char *sug; /* Suggestion */
+} sgx_errlist_t;
+
+/* Error code returned by sgx_create_enclave */
+static sgx_errlist_t sgx_errlist[] = {
+ {
+ SGX_ERROR_UNEXPECTED,
+ "Unexpected error occurred.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_PARAMETER,
+ "Invalid parameter.",
+ NULL
+ },
+ {
+ SGX_ERROR_OUT_OF_MEMORY,
+ "Out of memory.",
+ NULL
+ },
+ {
+ SGX_ERROR_ENCLAVE_LOST,
+ "Power transition occurred.",
+ "Please refer to the sample \"PowerTransition\" for details."
+ },
+ {
+ SGX_ERROR_INVALID_ENCLAVE,
+ "Invalid enclave image.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_ENCLAVE_ID,
+ "Invalid enclave identification.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_SIGNATURE,
+ "Invalid enclave signature.",
+ NULL
+ },
+ {
+ SGX_ERROR_OUT_OF_EPC,
+ "Out of EPC memory.",
+ NULL
+ },
+ {
+ SGX_ERROR_NO_DEVICE,
+ "Invalid SGX device.",
+ "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards."
+ },
+ {
+ SGX_ERROR_MEMORY_MAP_CONFLICT,
+ "Memory map conflicted.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_METADATA,
+ "Invalid enclave metadata.",
+ NULL
+ },
+ {
+ SGX_ERROR_DEVICE_BUSY,
+ "SGX device was busy.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_VERSION,
+ "Enclave version was invalid.",
+ NULL
+ },
+ {
+ SGX_ERROR_INVALID_ATTRIBUTE,
+ "Enclave was not authorized.",
+ NULL
+ },
+ {
+ SGX_ERROR_ENCLAVE_FILE_ACCESS,
+ "Can't open enclave file.",
+ NULL
+ },
+};
+
+/* Check error conditions for loading enclave */
+void print_error_message(sgx_status_t ret)
+{
+ size_t idx = 0;
+ size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0];
+
+ for (idx = 0; idx < ttl; idx++) {
+ if(ret == sgx_errlist[idx].err) {
+ if(NULL != sgx_errlist[idx].sug)
+ printf("Info: %s\n", sgx_errlist[idx].sug);
+ printf("Error: %s\n", sgx_errlist[idx].msg);
+ break;
+ }
+ }
+
+ if (idx == ttl)
+ printf("Error code is 0x%X. Please refer to the \"Intel SGX SDK Developer Reference\" for more details.\n", ret);
+}
+
+/* Initialize the enclave:
+ * Call sgx_create_enclave to initialize an enclave instance
+ */
+int initialize_enclave(void)
+{
+ sgx_status_t ret = SGX_ERROR_UNEXPECTED;
+
+ /* Call sgx_create_enclave to initialize an enclave instance */
+ /* Debug Support: set 2nd parameter to 1 */
+ ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, NULL, NULL, &global_eid, NULL);
+ if (ret != SGX_SUCCESS) {
+ print_error_message(ret);
+ return -1;
+ }
+
+ return 0;
+}
+
+/* OCall functions */
+void ocall_print_string(const char *str)
+{
+ /* Proxy/Bridge will check the length and null-terminate
+ * the input string to prevent buffer overflow.
+ */
+ printf("%s", str);
+}
+
+int test_tcs();
+
+static atomic counter_failures;
+
+#include //rand
+void driver(int sid)
+{
+ sgx_status_t ret = SGX_ERROR_UNEXPECTED;
+ int retval = 0;
+ do{
+ usleep(rand()%11);
+ ret = ecall_test_sgx_mm(global_eid, &retval, sid);
+ if (ret == SGX_SUCCESS){
+ printf("test_sgx_mm returned %d\n", retval);
+ counter_failures += retval;
+ }else if (ret == SGX_ERROR_OUT_OF_TCS){
+ printf("!!! enclave out of TCS, retrying...\n");
+ continue;
+ }else
+ {
+ printf("ret = %d\n", ret);
+ abort();
+ }
+ //test_tcs does its own retry
+ counter_failures += test_tcs();
+ return;
+ }while(true);
+}
+
+
+int test_unsafe()
+{
+ sgx_status_t ret = SGX_ERROR_UNEXPECTED;
+ int retval = 0;
+ ret = ecall_test_sgx_mm_unsafe(global_eid, &retval);
+ if (ret == SGX_SUCCESS){
+ if(retval)
+ printf("!!! test_sgx_mm_unsafe returned %d\n", retval);
+ else
+ printf("*** unsafe tests passed\n");
+ return retval;
+ }else
+ abort();
+}
+
+
+typedef struct ms_ecall_check_context_t {
+ int ms_retval;
+ size_t ms_tcs;
+} ms_ecall_check_context_t;
+
+extern "C" {
+#include "sgx.h"
+}
+vdso_sgx_enter_enclave_t vdso_sgx_enter_enclave;
+
+#define EENTER 2
+
+int ecall_check_context_manual(int* retval, size_t tcs)
+{
+ ms_ecall_check_context_t ms;
+ ms.ms_tcs = tcs;
+ ms.ms_retval= -1;
+ struct sgx_enclave_run run;
+ memset(&run, 0, sizeof(run));
+ run.tcs = (__u64)tcs;
+/********
+ !NOTE: hardcoded ecall number. Needs update if edl changes
+*******/
+ int ret = vdso_sgx_enter_enclave((unsigned long)3, (unsigned long)(&ms), 0, EENTER,
+ 0, 0, &run);
+ if (ret == 0) *retval = ms.ms_retval;
+ return ret;
+}
+#include
+#include
+void* get_vdso_sym(const char* vdso_func_name)
+{
+ char* dynstr = 0;
+ void *ret = NULL;
+
+ uint8_t* vdso_addr = (uint8_t*)getauxval(AT_SYSINFO_EHDR);
+ Elf64_Ehdr* elf_header = (Elf64_Ehdr*)vdso_addr;
+ Elf64_Shdr* section_header = (Elf64_Shdr*)(vdso_addr + elf_header->e_shoff);
+
+ for (int i = 0; i < elf_header->e_shnum; i++) {
+ auto& s = section_header[i];
+ auto& ss_ = section_header[elf_header->e_shstrndx];
+ auto name = (char*)(vdso_addr + ss_.sh_offset + s.sh_name);
+ if (strcmp(name, ".dynstr") == 0) {
+ dynstr = (char*)(vdso_addr + s.sh_offset);
+ break;
+ }
+ }
+
+ for (int i = 0; i < elf_header->e_shnum; i++) {
+ auto& s = section_header[i];
+ auto& ss_ = section_header[elf_header->e_shstrndx];
+ auto name = (char*)(vdso_addr + ss_.sh_offset + s.sh_name);
+ if (strcmp(name, ".dynsym") == 0) {
+ for (unsigned int si = 0; si < (s.sh_size/s.sh_entsize); si++) {
+ auto &sym = ((Elf64_Sym*)(vdso_addr + s.sh_offset))[si];
+ auto vdname = dynstr + sym.st_name;
+ if (strcmp(vdname, vdso_func_name) == 0) {
+ ret = (vdso_addr + sym.st_value);
+ break;
+ }
+ }
+ if (ret) break;
+ }
+ }
+ return ret;
+}
+
+#define fastcall __attribute__((regparm(3),noinline,visibility("default")))
+//this function is used to notify GDB scripts
+//GDB is supposed to have a breakpoint on urts_add_tcs to receive debug interupt
+//once the breakpoint has been hit, GDB extracts the address of tcs and sets DBGOPTIN for the tcs
+extern "C" void fastcall urts_add_tcs(tcs_t * const tcs)
+{
+ (void)(tcs);
+}
+
+int test_tcs()
+{
+ if(vdso_sgx_enter_enclave == NULL)
+ return 0; //skip this test
+ sgx_status_t ret = SGX_ERROR_UNEXPECTED;
+ size_t tcs = 0;
+
+ do {
+ usleep(rand()%11);
+ ret = ecall_alloc_context(global_eid, &tcs);
+ if (ret == SGX_SUCCESS){
+ if (tcs > 1) {
+ printf("*** test_alloc_context returned 0X%LX\n", tcs);
+ break;
+ } else {
+ printf("!!! alloc context failed\n");
+ return 1;
+ }
+ }else if (ret == SGX_ERROR_OUT_OF_TCS){
+ continue;
+ }else
+ abort();
+ } while (true);
+
+ urts_add_tcs((tcs_t*)tcs);//turn on sgx-gdb
+ int retval = 0;
+ int r = ecall_check_context_manual(&retval, tcs);
+
+ if (r == 0){
+ if (retval) {
+ printf("!!! check tcs returned %d\n", retval);
+ return 1;
+ }
+ else
+ printf("*** check tcs passed\n");
+ }else
+ abort();
+
+ do {
+ usleep(rand()%11);
+ ret = ecall_dealloc_context(global_eid, &retval, tcs);
+ if (ret == SGX_SUCCESS) {
+ if(retval) {
+ printf("!!! test_deaalloc_context returned %d\n", retval);
+ return 1;
+ }
+ else{
+ printf("*** dealloc context pass\n");
+ return 0;
+ }
+ } else if (ret == SGX_ERROR_OUT_OF_TCS){
+ continue;
+ }else
+ abort();
+ } while (true);
+ return 0;
+}
+
+/* ecall_thread_functions:
+ * Invokes thread functions including mutex, condition variable, etc.
+ */
+int test_sgx_mm_functions(int num_threads)
+{
+ vector threads;
+ for (int i=0; i< num_threads; i++)
+ threads.push_back(new thread(driver, i));
+
+ for (int i=0; i< num_threads; i++)
+ {
+ threads[i]->join();
+ delete threads[i];
+ }
+
+ if(counter_failures)
+ {
+ printf("!!! Fail in %d threads\n", static_cast(counter_failures));
+ }else
+ printf("*** All threads ran successfully.\n");
+ return counter_failures;
+}
+
+
+
+/* Application entry */
+int SGX_CDECL main(int argc, char *argv[])
+{
+ (void)(argc);
+ (void)(argv);
+
+
+ vdso_sgx_enter_enclave = (vdso_sgx_enter_enclave_t)get_vdso_sym("__vdso_sgx_enter_enclave");
+ /* Initialize the enclave */
+ if(initialize_enclave() < 0){
+ printf("Failed initialize enclave.\n");
+ return -1;
+ }
+ //srand (time(NULL));
+ srand ((3141596/1618)*271828);
+ int ret = 0;
+
+ //17 threads for 100 iterations passed when this is checked in
+ ret += test_sgx_mm_functions(2); // FIXME: 247 freeze on NUC.
+ ret += test_unsafe();
+
+ sgx_destroy_enclave(global_eid);
+ if (!ret)
+ printf("*** All tests pass.\n");
+ else
+ printf("!!! %d test(s) failed.\n", ret);
+
+ return ret;
+}
+
diff --git a/sdk/trts/trts_emodpr.cpp b/external/sgx-emm/api_tests/App/App.h
similarity index 58%
rename from sdk/trts/trts_emodpr.cpp
rename to external/sgx-emm/api_tests/App/App.h
index 79d85ebd8..ec2de43c8 100644
--- a/sdk/trts/trts_emodpr.cpp
+++ b/external/sgx-emm/api_tests/App/App.h
@@ -30,50 +30,45 @@
*/
-#include "trts_emodpr.h"
+#ifndef _APP_H_
+#define _APP_H_
-#include "sgx_trts.h" // for sgx_ocalloc, sgx_is_outside_enclave
-#include "arch.h"
-#include "sgx_edger8r.h" // for sgx_ocall etc.
-#include "internal/rts.h"
+#include
+#include
+#include
+#include
-/* sgx_ocfree() just restores the original outside stack pointer. */
-#define OCALLOC(val, type, len) do { \
- void* __tmp = sgx_ocalloc(len); \
- if (__tmp == NULL) { \
- sgx_ocfree(); \
- return SGX_ERROR_UNEXPECTED;\
- } \
- (val) = (type)__tmp; \
-} while (0)
+#include "sgx_error.h" /* sgx_status_t */
+#include "sgx_eid.h" /* sgx_enclave_id_t */
-typedef struct ms_change_permissions_ocall_t {
- size_t ms_addr;
- size_t ms_size;
- uint64_t ms_epcm_perms;
-} ms_change_permissions_ocall_t;
-
-sgx_status_t SGXAPI change_permissions_ocall(size_t addr, size_t size, uint64_t epcm_perms, const int proc)
-{
-#ifdef SE_SIM
- (void)addr;
- (void)size;
- (void)epcm_perms;
- (void)proc;
- return SGX_SUCCESS;
-#else
- sgx_status_t status = SGX_SUCCESS;
+#ifndef TRUE
+# define TRUE 1
+#endif
- ms_change_permissions_ocall_t* ms;
- OCALLOC(ms, ms_change_permissions_ocall_t*, sizeof(*ms));
+#ifndef FALSE
+# define FALSE 0
+#endif
- ms->ms_addr = addr;
- ms->ms_size = size;
- ms->ms_epcm_perms = epcm_perms;
- status = sgx_ocall(proc, ms);
+# define TOKEN_FILENAME "enclave.token"
+# define ENCLAVE_FILENAME "enclave.signed.so"
+extern sgx_enclave_id_t global_eid; /* global enclave id */
- sgx_ocfree();
- return status;
+#if defined(__cplusplus)
+extern "C" {
#endif
+
+void edger8r_array_attributes(void);
+void edger8r_type_attributes(void);
+void edger8r_pointer_attributes(void);
+void edger8r_function_attributes(void);
+
+void ecall_libc_functions(void);
+void ecall_libcxx_functions(void);
+void ecall_thread_functions(void);
+
+#if defined(__cplusplus)
}
+#endif
+
+#endif /* !_APP_H_ */
diff --git a/external/sgx-emm/api_tests/App/sgx.h b/external/sgx-emm/api_tests/App/sgx.h
new file mode 100644
index 000000000..b2fbcee9d
--- /dev/null
+++ b/external/sgx-emm/api_tests/App/sgx.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright(c) 2016-20 Intel Corporation.
+ */
+#ifndef _UAPI_ASM_X86_SGX_H
+#define _UAPI_ASM_X86_SGX_H
+
+#include
+#include
+
+/**
+ * enum sgx_page_flags - page control flags
+ * %SGX_PAGE_MEASURE: Measure the page contents with a sequence of
+ * ENCLS[EEXTEND] operations.
+ */
+enum sgx_page_flags {
+ SGX_PAGE_MEASURE = 0x01,
+};
+
+#define SGX_MAGIC 0xA4
+
+#define SGX_IOC_ENCLAVE_CREATE \
+ _IOW(SGX_MAGIC, 0x00, struct sgx_enclave_create)
+#define SGX_IOC_ENCLAVE_ADD_PAGES \
+ _IOWR(SGX_MAGIC, 0x01, struct sgx_enclave_add_pages)
+#define SGX_IOC_ENCLAVE_INIT \
+ _IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init)
+#define SGX_IOC_ENCLAVE_PROVISION \
+ _IOW(SGX_MAGIC, 0x03, struct sgx_enclave_provision)
+#define SGX_IOC_PAGE_MODP \
+ _IOWR(SGX_MAGIC, 0x04, struct sgx_page_modp)
+#define SGX_IOC_PAGE_MODT \
+ _IOWR(SGX_MAGIC, 0x05, struct sgx_page_modt)
+#define SGX_IOC_PAGE_REMOVE \
+ _IOWR(SGX_MAGIC, 0x06, struct sgx_page_remove)
+
+/**
+ * struct sgx_enclave_create - parameter structure for the
+ * %SGX_IOC_ENCLAVE_CREATE ioctl
+ * @src: address for the SECS page data
+ */
+struct sgx_enclave_create {
+ __u64 src;
+};
+
+/**
+ * struct sgx_enclave_add_pages - parameter structure for the
+ * %SGX_IOC_ENCLAVE_ADD_PAGE ioctl
+ * @src: start address for the page data
+ * @offset: starting page offset
+ * @length: length of the data (multiple of the page size)
+ * @secinfo: address for the SECINFO data
+ * @flags: page control flags
+ * @count: number of bytes added (multiple of the page size)
+ */
+struct sgx_enclave_add_pages {
+ __u64 src;
+ __u64 offset;
+ __u64 length;
+ __u64 secinfo;
+ __u64 flags;
+ __u64 count;
+};
+
+/**
+ * struct sgx_enclave_init - parameter structure for the
+ * %SGX_IOC_ENCLAVE_INIT ioctl
+ * @sigstruct: address for the SIGSTRUCT data
+ */
+struct sgx_enclave_init {
+ __u64 sigstruct;
+};
+
+/**
+ * struct sgx_enclave_provision - parameter structure for the
+ * %SGX_IOC_ENCLAVE_PROVISION ioctl
+ * @fd: file handle of /dev/sgx_provision
+ */
+struct sgx_enclave_provision {
+ __u64 fd;
+};
+
+/**
+ * struct sgx_page_modp - parameter structure for the %SGX_IOC_PAGE_MODP ioctl
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @prot: new protection bits of pages in range described by @offset
+ * and @length
+ * @result: SGX result code of ENCLS[EMODPR] function
+ * @count: bytes successfully changed (multiple of page size)
+ */
+struct sgx_page_modp {
+ __u64 offset;
+ __u64 length;
+ __u64 prot;
+ __u64 result;
+ __u64 count;
+};
+
+/**
+ * struct sgx_page_modt - parameter structure for the %SGX_IOC_PAGE_MODT ioctl
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @type: new type of pages in range described by @offset and @length
+ * @result: SGX result code of ENCLS[EMODT] function
+ * @count: bytes successfully changed (multiple of page size)
+ */
+struct sgx_page_modt {
+ __u64 offset;
+ __u64 length;
+ __u64 type;
+ __u64 result;
+ __u64 count;
+};
+
+/**
+ * struct sgx_page_remove - parameters for the %SGX_IOC_PAGE_REMOVE ioctl
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @count: bytes successfully changed (multiple of page size)
+ *
+ * Regular (PT_REG) or TCS (PT_TCS) can be removed from an initialized
+ * enclave if the system supports SGX2. First, the %SGX_IOC_PAGE_MODT ioctl
+ * should be used to change the page type to PT_TRIM. After that succeeds
+ * ENCLU[EACCEPT] should be run from within the enclave and then can this
+ * ioctl be used to complete the page removal.
+ */
+struct sgx_page_remove {
+ __u64 offset;
+ __u64 length;
+ __u64 count;
+};
+
+struct sgx_enclave_run;
+
+/**
+ * typedef sgx_enclave_user_handler_t - Exit handler function accepted by
+ * __vdso_sgx_enter_enclave()
+ * @run: The run instance given by the caller
+ *
+ * The register parameters contain the snapshot of their values at enclave
+ * exit. An invalid ENCLU function number will cause -EINVAL to be returned
+ * to the caller.
+ *
+ * Return:
+ * - <= 0: The given value is returned back to the caller.
+ * - > 0: ENCLU function to invoke, either EENTER or ERESUME.
+ */
+typedef int (*sgx_enclave_user_handler_t)(long rdi, long rsi, long rdx,
+ long rsp, long r8, long r9,
+ struct sgx_enclave_run *run);
+
+/**
+ * struct sgx_enclave_run - the execution context of __vdso_sgx_enter_enclave()
+ * @tcs: TCS used to enter the enclave
+ * @function: The last seen ENCLU function (EENTER, ERESUME or EEXIT)
+ * @exception_vector: The interrupt vector of the exception
+ * @exception_error_code: The exception error code pulled out of the stack
+ * @exception_addr: The address that triggered the exception
+ * @user_handler: User provided callback run on exception
+ * @user_data: Data passed to the user handler
+ * @reserved Reserved for future extensions
+ *
+ * If @user_handler is provided, the handler will be invoked on all return paths
+ * of the normal flow. The user handler may transfer control, e.g. via a
+ * longjmp() call or a C++ exception, without returning to
+ * __vdso_sgx_enter_enclave().
+ */
+struct sgx_enclave_run {
+ __u64 tcs;
+ __u32 function;
+ __u16 exception_vector;
+ __u16 exception_error_code;
+ __u64 exception_addr;
+ __u64 user_handler;
+ __u64 user_data;
+ __u8 reserved[216];
+};
+
+/**
+ * typedef vdso_sgx_enter_enclave_t - Prototype for __vdso_sgx_enter_enclave(),
+ * a vDSO function to enter an SGX enclave.
+ * @rdi: Pass-through value for RDI
+ * @rsi: Pass-through value for RSI
+ * @rdx: Pass-through value for RDX
+ * @function: ENCLU function, must be EENTER or ERESUME
+ * @r8: Pass-through value for R8
+ * @r9: Pass-through value for R9
+ * @run: struct sgx_enclave_run, must be non-NULL
+ *
+ * NOTE: __vdso_sgx_enter_enclave() does not ensure full compliance with the
+ * x86-64 ABI, e.g. doesn't handle XSAVE state. Except for non-volatile
+ * general purpose registers, EFLAGS.DF, and RSP alignment, preserving/setting
+ * state in accordance with the x86-64 ABI is the responsibility of the enclave
+ * and its runtime, i.e. __vdso_sgx_enter_enclave() cannot be called from C
+ * code without careful consideration by both the enclave and its runtime.
+ *
+ * All general purpose registers except RAX, RBX and RCX are passed as-is to the
+ * enclave. RAX, RBX and RCX are consumed by EENTER and ERESUME and are loaded
+ * with @function, asynchronous exit pointer, and @run.tcs respectively.
+ *
+ * RBP and the stack are used to anchor __vdso_sgx_enter_enclave() to the
+ * pre-enclave state, e.g. to retrieve @run.exception and @run.user_handler
+ * after an enclave exit. All other registers are available for use by the
+ * enclave and its runtime, e.g. an enclave can push additional data onto the
+ * stack (and modify RSP) to pass information to the optional user handler (see
+ * below).
+ *
+ * Most exceptions reported on ENCLU, including those that occur within the
+ * enclave, are fixed up and reported synchronously instead of being delivered
+ * via a standard signal. Debug Exceptions (#DB) and Breakpoints (#BP) are
+ * never fixed up and are always delivered via standard signals. On synchronously
+ * reported exceptions, -EFAULT is returned and details about the exception are
+ * recorded in @run.exception, the optional sgx_enclave_exception struct.
+ *
+ * Return:
+ * - 0: ENCLU function was successfully executed.
+ * - -EINVAL: Invalid ENCL number (neither EENTER nor ERESUME).
+ */
+typedef int (*vdso_sgx_enter_enclave_t)(unsigned long rdi, unsigned long rsi,
+ unsigned long rdx, unsigned int function,
+ unsigned long r8, unsigned long r9,
+ struct sgx_enclave_run *run);
+
+#endif /* _UAPI_ASM_X86_SGX_H */
diff --git a/external/sgx-emm/api_tests/Enclave/Enclave.cpp b/external/sgx-emm/api_tests/Enclave/Enclave.cpp
new file mode 100644
index 000000000..c7d809bc0
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/Enclave.cpp
@@ -0,0 +1,884 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "Enclave.h"
+#include "Enclave_t.h" /* print_string */
+#include
+#include /* vsnprintf */
+#include
+#include
+#include "../../emm_src/include/sgx_mm.h"
+#define SGX_PAGE_SIZE 4096
+#include "sgx_thread.h"
+#include
+#include "sgx_trts.h"
+#include "../tcs.h"
+using namespace std;
+/*
+ * printf:
+ * Invokes OCALL to display the enclave buffer to the terminal.
+ */
+int printf(const char* fmt, ...)
+{
+ char buf[4096*2] = { '\0' };
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, BUFSIZ, fmt, ap);
+ va_end(ap);
+ ocall_print_string(buf);
+ return (int)strnlen(buf, BUFSIZ - 1) + 1;
+}
+
+#define LOG(fmt, ...) do { \
+ printf("[%s %s:%d] " fmt, __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+}while(0)
+
+
+#define EXPECT_EQ(a, b) \
+ do { \
+ if ((a) != (b)){ \
+ LOG( #a " expected:" #b " got: %lu\n", (uint64_t)(a)); \
+ return 1; \
+ }\
+ } while(0);
+
+#define EXPECT_NEQ(a, b) \
+ do { \
+ if ((a) == (b)) {\
+ LOG( #a " not expected: " #b "\n" ); \
+ return 1; \
+ }\
+ } while(0);
+
+const size_t ALLOC_SIZE = 0x2000;
+vector allocated_blocks;
+sgx_thread_mutex_t mutex = SGX_THREAD_MUTEX_INITIALIZER;
+
+int test_sgx_mm_alloc_dealloc()
+{
+ int ret = sgx_mm_dealloc(0, ALLOC_SIZE);
+ EXPECT_EQ(ret, EINVAL);
+ // we should be able to alloc, commit, uncommit
+ // in multiple threads without interference
+ void* addr = 0;
+ ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW, NULL, NULL, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ return 0;
+}
+
+int test_sgx_mm_alloc_commit_uncommit()
+{
+ int ret = sgx_mm_dealloc(0, ALLOC_SIZE);
+ EXPECT_EQ(ret, EINVAL);
+ // we should be able to alloc, commit, uncommit
+ // in multiple threads without interference
+ void* addr = 0;
+ ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW, NULL, NULL, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+
+ ret = sgx_mm_commit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ void* addr1 = NULL;
+ ret = sgx_mm_alloc(addr, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW | SGX_EMA_FIXED, NULL, NULL, &addr1);
+
+ EXPECT_EQ(ret, EEXIST);
+ EXPECT_EQ(addr1, NULL);
+ ret = sgx_mm_uncommit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+ ret = sgx_mm_uncommit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0); //we do nothing if it's already uncommitted
+
+ ret = sgx_mm_commit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ //no longer use these areas, ready to be
+ // released by any thread
+ sgx_thread_mutex_lock(&mutex);
+ allocated_blocks.push_back(addr);
+ sgx_thread_mutex_unlock(&mutex);
+ return 0;
+}
+/*
+ * Only release areas previously stored
+ * by other threads as ready to be released
+ */
+int test_sgx_mm_dealloc()
+{
+ int res = 0;
+ sgx_thread_mutex_lock(&mutex);
+ auto it = allocated_blocks.begin();
+ while ( it!=allocated_blocks.end()){
+ int ret = sgx_mm_dealloc(*it, ALLOC_SIZE);
+ if(ret){
+ res ++;
+ LOG("!!! failed dealloc, errno = %d\n", ret);
+ it++;
+ }else
+ it = allocated_blocks.erase(it);
+ }
+ sgx_thread_mutex_unlock(&mutex);
+ return res;
+}
+
+int test_sgx_mm_alloc_dealloc_unsafe1()
+{
+// allocation, deallocation
+ int ret = sgx_mm_dealloc(0, ALLOC_SIZE);
+ EXPECT_EQ(ret, EINVAL);
+
+ void* addr = 0;
+ ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW, NULL, NULL, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+
+ ret = sgx_mm_commit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ void* addr1 = NULL;
+ ret = sgx_mm_alloc(addr, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW|SGX_EMA_FIXED, NULL, NULL, &addr1);
+
+ EXPECT_EQ(ret, EEXIST);
+ EXPECT_EQ(addr1, NULL);
+
+ ret = sgx_mm_uncommit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ ret = sgx_mm_uncommit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0); //we do nothing if it's already uncommitted
+
+ ret = sgx_mm_commit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, EINVAL);
+
+ ret = sgx_mm_uncommit(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, EINVAL); // error if it's already deallocated
+
+ void* addr2 = NULL;
+ ret = sgx_mm_alloc(addr, ALLOC_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND|SGX_EMA_FIXED, NULL, NULL, &addr2);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_EQ(addr2, addr);//mm should realloc to the given addr
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ ret = sgx_mm_alloc(addr, ALLOC_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND|SGX_EMA_FIXED, NULL, NULL, &addr2);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_EQ(addr, addr2);
+
+ ret = sgx_mm_alloc(addr, ALLOC_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND, NULL, NULL, &addr2);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, addr2);
+
+ uint8_t *data= (uint8_t*)addr2;
+ data[0]=0xFF;
+ data[ALLOC_SIZE-1]=0xFF;
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ ret = sgx_mm_dealloc(addr2, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+
+ return 0;
+}
+
+#include
+typedef struct _pfdata
+{
+ sgx_pfinfo pf;
+ union {
+ int access; // access that triggers PF, R/W/X
+ int magic;
+ };
+ void* addr_expected;
+ jmp_buf jbuf; // used for jmp_handler only
+} pf_data_t;
+
+int jmp_handler(const sgx_pfinfo *pfinfo, void *private_data)
+{
+ pf_data_t* pd = (pf_data_t *) private_data;
+ memcpy(private_data, pfinfo, sizeof(*pfinfo));
+ void* addr = (void*) pd->pf.maddr;
+ if (pd->pf.pfec.rw == 0
+ && addr == pd->addr_expected)
+ {
+ int ret = sgx_mm_commit(addr, SGX_PAGE_SIZE);
+ if (ret) abort();
+ memset(addr, pd->magic, SGX_PAGE_SIZE);
+ longjmp(pd->jbuf, 1);
+ abort(); //won't reach here
+ }
+ return SGX_MM_EXCEPTION_CONTINUE_SEARCH;
+}
+
+int test_sgx_mm_alloc_jmp()
+{
+
+ void* addr = 0;
+ pf_data_t pd;
+ memset((void*) &pd, 0, sizeof(pd));
+ int ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND, &jmp_handler, &pd, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+ const int MAGIC = 0x55UL;
+
+ uint8_t* data = (uint8_t*)addr;
+ pd.magic = MAGIC;
+ pd.addr_expected = addr;
+ if (0 == setjmp(pd.jbuf)) {
+ uint8_t d0 = 0;
+ d0 = data[0];
+ EXPECT_NEQ (d0, 0); //should not come here
+ }else {
+ uint8_t d0 = data[0];
+
+ EXPECT_EQ (d0, MAGIC);
+ EXPECT_EQ (pd.pf.pfec.rw, 0); //Read caused PF
+ EXPECT_EQ (pd.pf.pfec.sgx, 1); // sgx bit set
+ }
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+ return 0;
+}
+
+int permissions_handler(const sgx_pfinfo *pfinfo, void *private_data)
+{
+ pf_data_t* pd = (pf_data_t *) private_data;
+ memcpy(private_data, pfinfo, sizeof(*pfinfo));
+ void* addr = (void*) pd->pf.maddr;
+ if(pd->pf.pfec.rw == 1 && pd->access == SGX_EMA_PROT_WRITE){
+ sgx_mm_modify_permissions(addr, SGX_PAGE_SIZE, SGX_EMA_PROT_WRITE | SGX_EMA_PROT_READ);
+ }else if (pd->pf.pfec.rw == 0 && (pd->access & SGX_EMA_PROT_READ )){//R or RX
+ sgx_mm_modify_permissions(addr, SGX_PAGE_SIZE, pd->access);
+ }else
+ abort();
+ return SGX_MM_EXCEPTION_CONTINUE_EXECUTION;
+}
+
+int commit_data_handler(const sgx_pfinfo *pfinfo, void *private_data)
+{
+ pf_data_t* pd = (pf_data_t *) private_data;
+ memcpy(private_data, pfinfo, sizeof(*pfinfo));
+ void* addr = (void*) pd->pf.maddr;
+
+ if (pd->access == SGX_EMA_PROT_WRITE
+ && pd->pf.pfec.rw == 1
+ && addr == pd->addr_expected)
+ {
+ int ret = sgx_mm_modify_permissions(addr, SGX_PAGE_SIZE, SGX_EMA_PROT_WRITE | SGX_EMA_PROT_READ);
+ if(ret) abort();
+ return SGX_MM_EXCEPTION_CONTINUE_EXECUTION;
+ }
+
+ if (addr == pd->addr_expected)
+ {
+ void* data = 0;
+ int ret = sgx_mm_alloc(NULL, SGX_PAGE_SIZE, SGX_EMA_COMMIT_NOW,
+ NULL, NULL, &data);
+ if(ret) abort();
+ assert(data!=0);
+ memset(data, pd->magic, SGX_PAGE_SIZE);
+ ret = sgx_mm_commit_data(addr, SGX_PAGE_SIZE, (uint8_t*)data,
+ SGX_EMA_PROT_READ);
+ if(ret) abort();
+ ret = sgx_mm_dealloc((void*)data, SGX_PAGE_SIZE);
+ if(ret) abort();
+ return SGX_MM_EXCEPTION_CONTINUE_EXECUTION;
+ }else
+ return SGX_MM_EXCEPTION_CONTINUE_SEARCH;
+}
+
+static const int MAX_NESTED_HANDLER = 10;
+int nested_handler(const sgx_pfinfo *pfinfo, void *private_data)
+{
+ pf_data_t* orig_pd = (pf_data_t *) private_data;
+ memcpy(private_data, pfinfo, sizeof(*pfinfo));
+ void* addr = (void*) orig_pd->pf.maddr;
+
+ if (addr == orig_pd->addr_expected)
+ {
+ void* data = 0;
+ if (orig_pd->magic == MAX_NESTED_HANDLER)
+ {
+ int ret = sgx_mm_alloc(NULL, SGX_PAGE_SIZE, SGX_EMA_COMMIT_NOW,
+ NULL, NULL, &data);
+ if (ret) abort();
+ assert(data!=0);
+ memset(data, orig_pd->magic, SGX_PAGE_SIZE);
+ ret = sgx_mm_commit_data(addr, SGX_PAGE_SIZE, (uint8_t*)data,
+ SGX_EMA_PROT_READ);
+ if (ret) abort();
+ } else
+ {
+ pf_data_t nested_pd;
+ memset((void*) &nested_pd, 0, sizeof(nested_pd));
+ int ret = sgx_mm_alloc(NULL, SGX_PAGE_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND,
+ &nested_handler,
+ &nested_pd, &data);
+
+ if (ret) abort();
+ assert(data != 0);
+ nested_pd.addr_expected = data;
+ nested_pd.magic = orig_pd->magic + 1;
+ ret = sgx_mm_commit_data(addr, SGX_PAGE_SIZE, (uint8_t*)data,
+ SGX_EMA_PROT_READ);
+ if (ret) abort();
+ if (nested_pd.pf.pfec.errcd == 0) abort(); //READ suceess with PF
+ if (nested_pd.pf.pfec.rw != 0) abort(); //READ indicated in PFEC
+ }
+ int ret = sgx_mm_dealloc((void*)data, SGX_PAGE_SIZE);
+ if (ret) abort();
+ return SGX_MM_EXCEPTION_CONTINUE_EXECUTION;
+ }else
+ return SGX_MM_EXCEPTION_CONTINUE_SEARCH;
+}
+
+int test_sgx_mm_permissions()
+{
+
+ void* addr = 0;
+ pf_data_t pd;
+ memset((void*) &pd, 0, sizeof(pd));
+ int ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW, &permissions_handler, &pd, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+
+ uint8_t* data = (uint8_t*)addr;
+ uint8_t d0 = data[0];
+ EXPECT_EQ(d0, 0);
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //Read suceess without PF
+ data[0] = 0xFF;
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //WRITE suceess without PF
+
+ // permissions reduction
+ ret = sgx_mm_modify_permissions(addr, ALLOC_SIZE/2, SGX_EMA_PROT_READ);
+ EXPECT_EQ(ret, 0);
+
+ pd.access = SGX_EMA_PROT_READ;
+ d0 = data[0];
+ EXPECT_EQ(d0, 0xFF);
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //Read suceess without PF
+
+ pd.access = SGX_EMA_PROT_WRITE;
+ data[ALLOC_SIZE-1] = 0xFF;
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //WRITE suceess without PF
+
+ pd.access = SGX_EMA_PROT_WRITE;
+ data[0] = 0xFF;
+ EXPECT_NEQ (pd.pf.pfec.errcd, 0); //WRITE suceess with PF
+ EXPECT_EQ (pd.pf.pfec.rw, 1); //WRITE indicated in PFEC
+
+ // permissions reduction
+ ret = sgx_mm_modify_permissions(addr + ALLOC_SIZE/2, ALLOC_SIZE/2, SGX_EMA_PROT_NONE);
+ EXPECT_EQ(ret, 0);
+
+ //no longer used, ready to be released by any thread
+ //we could dealloc here but to make it more interesting...
+ sgx_thread_mutex_lock(&mutex);
+ allocated_blocks.push_back(addr);
+ sgx_thread_mutex_unlock(&mutex);
+
+ return 0;
+}
+
+int test_sgx_mm_permissions_dealloc()
+{
+ void* addr = 0;
+ pf_data_t pd;
+ memset((void*) &pd, 0, sizeof(pd));
+ int ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_NOW, &permissions_handler, &pd, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+
+ uint8_t* data = (uint8_t*)addr;
+ uint8_t d0 = data[0];
+ EXPECT_EQ(d0, 0);
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //Read suceess without PF
+ data[0] = 0xFF;
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //WRITE suceess without PF
+
+ // permissions reduction
+ ret = sgx_mm_modify_permissions(addr, ALLOC_SIZE/2, SGX_EMA_PROT_READ);
+ EXPECT_EQ(ret, 0);
+
+ pd.access = SGX_EMA_PROT_READ;
+ d0 = data[0];
+ EXPECT_EQ(d0, 0xFF);
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //Read suceess without PF
+
+ pd.access = SGX_EMA_PROT_WRITE;
+ data[ALLOC_SIZE-1] = 0xFF;
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); //WRITE suceess without PF
+
+ pd.access = SGX_EMA_PROT_WRITE;
+ data[0] = 0xFF;
+ EXPECT_NEQ (pd.pf.pfec.errcd, 0); //WRITE suceess with PF
+ EXPECT_EQ (pd.pf.pfec.rw, 1); //WRITE indicated in PFEC
+
+ memset((void*) &pd, 0, sizeof(pd));
+ pd.access = SGX_EMA_PROT_READ|SGX_EMA_PROT_EXEC;
+
+
+ ret = sgx_mm_dealloc(addr, ALLOC_SIZE);
+ EXPECT_EQ(ret, 0);
+ EXPECT_EQ (pd.pf.pfec.errcd, 0); // no PF
+
+ return 0;
+}
+
+int test_sgx_mm_commit_data()
+{
+ void* addr = 0;
+ const int MAGIC = 0x55UL;
+ pf_data_t pd;
+ memset((void*) &pd, 0, sizeof(pd));
+ int ret = sgx_mm_alloc(NULL, ALLOC_SIZE,
+ SGX_EMA_COMMIT_ON_DEMAND,
+ &commit_data_handler,
+ &pd, &addr);
+
+ EXPECT_EQ(ret, 0);
+ EXPECT_NEQ(addr, NULL);
+
+ pd.addr_expected = addr;
+ pd.magic = MAGIC;
+
+ uint8_t* data = (uint8_t*)addr;
+ for (int i =0; ioentry = (size_t)(&enclave_entry) - enclave_base;
+ tcs->cssa = 0;
+ tcs->nssa = 2;
+ tcs->ofs_limit = tcs->ogs_limit = (uint32_t)-1;
+ tcs->ossa = (size_t) ssa - enclave_base;
+ tcs->ofs_base = (size_t)tls - enclave_base;
+ tcs->ogs_base = (size_t)tls - enclave_base;
+
+ ret =sgx_mm_modify_type(ptcs, SGX_PAGE_SIZE, SGX_EMA_PAGE_TYPE_TCS);
+
+ EXPECT_EQ(ret, 0);
+ return (size_t) ptcs;
+}
+
+int ecall_check_context(size_t tcs)
+{
+ return 0;
+}
+
+int ecall_dealloc_context(size_t tcs)
+{
+ size_t base = tcs - 37*SGX_PAGE_SIZE;
+ size_t size = (16 * 3 + 5 + 1 + 2 + 1) * SGX_PAGE_SIZE;
+
+ int ret = sgx_mm_dealloc ((void*)base, size);
+
+ EXPECT_EQ(ret, 0);
+
+ return 0;
+}
diff --git a/external/sgx-emm/api_tests/Enclave/Enclave.edl b/external/sgx-emm/api_tests/Enclave/Enclave.edl
new file mode 100644
index 000000000..be3fc5775
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/Enclave.edl
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+enclave {
+ from "sgx_tstdc.edl" import sgx_thread_wait_untrusted_event_ocall, sgx_thread_set_untrusted_event_ocall;
+ trusted {
+ public int ecall_test_sgx_mm(int seq_id);
+ public int ecall_test_sgx_mm_unsafe(void);
+ public size_t ecall_alloc_context(void);
+ public int ecall_check_context(size_t tcs);
+ public int ecall_dealloc_context(size_t tcs);
+ };
+ untrusted {
+ void ocall_print_string([in, string] const char *str);
+ };
+
+};
diff --git a/external/sgx-emm/api_tests/Enclave/Enclave.h b/external/sgx-emm/api_tests/Enclave/Enclave.h
new file mode 100644
index 000000000..f6bb82b59
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/Enclave.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef _ENCLAVE_H_
+#define _ENCLAVE_H_
+
+#include
+#include
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+int printf(const char* fmt, ...);
+
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* !_ENCLAVE_H_ */
diff --git a/external/sgx-emm/api_tests/Enclave/Enclave.lds b/external/sgx-emm/api_tests/Enclave/Enclave.lds
new file mode 100644
index 000000000..0d5614f55
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/Enclave.lds
@@ -0,0 +1,11 @@
+enclave.so
+{
+ global:
+ g_global_data_sim;
+ g_global_data;
+ enclave_entry;
+ g_peak_heap_used;
+ g_peak_rsrv_mem_committed;
+ local:
+ *;
+};
diff --git a/external/sgx-emm/api_tests/Enclave/Enclave_private_test.pem b/external/sgx-emm/api_tests/Enclave/Enclave_private_test.pem
new file mode 100644
index 000000000..529d07be3
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/Enclave_private_test.pem
@@ -0,0 +1,39 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIIG4gIBAAKCAYEAroOogvsj/fZDZY8XFdkl6dJmky0lRvnWMmpeH41Bla6U1qLZ
+AmZuyIF+mQC/cgojIsrBMzBxb1kKqzATF4+XwPwgKz7fmiddmHyYz2WDJfAjIveJ
+ZjdMjM4+EytGlkkJ52T8V8ds0/L2qKexJ+NBLxkeQLfV8n1mIk7zX7jguwbCG1Pr
+nEMdJ3Sew20vnje+RsngAzdPChoJpVsWi/K7cettX/tbnre1DL02GXc5qJoQYk7b
+3zkmhz31TgFrd9VVtmUGyFXAysuSAb3EN+5VnHGr0xKkeg8utErea2FNtNIgua8H
+ONfm9Eiyaav1SVKzPHlyqLtcdxH3I8Wg7yqMsaprZ1n5A1v/levxnL8+It02KseD
+5HqV4rf/cImSlCt3lpRg8U5E1pyFQ2IVEC/XTDMiI3c+AR+w2jSRB3Bwn9zJtFlW
+KHG3m1xGI4ck+Lci1JvWWLXQagQSPtZTsubxTQNx1gsgZhgv1JHVZMdbVlAbbRMC
+1nSuJNl7KPAS/VfzAgEDAoIBgHRXxaynbVP5gkO0ug6Qw/E27wzIw4SmjsxG6Wpe
+K7kfDeRskKxESdsA/xCrKkwGwhcx1iIgS5+Qscd1Yg+1D9X9asd/P7waPmWoZd+Z
+AhlKwhdPsO7PiF3e1AzHhGQwsUTt/Y/aSI1MpHBvy2/s1h9mFCslOUxTmWw0oj/Q
+ldIEgWeNR72CE2+jFIJIyml6ftnb6qzPiga8Bm48ubKh0kvySOqnkmnPzgh+JBD6
+JnBmtZbfPT97bwTT+N6rnPqOOApvfHPf15kWI8yDbprG1l4OCUaIUH1AszxLd826
+5IPM+8gINLRDP1MA6azECPjTyHXhtnSIBZCyWSVkc05vYmNXYUNiXWMajcxW9M02
+wKzFELO8NCEAkaTPxwo4SCyIjUxiK1LbQ9h8PSy4c1+gGP4LAMR8xqP4QKg6zdu9
+osUGG/xRe/uufgTBFkcjqBHtK5L5VI0jeNIUAgW/6iNbYXjBMJ0GfauLs+g1VsOm
+WfdgXzsb9DYdMa0OXXHypmV4GwKBwQDUwQj8RKJ6c8cT4vcWCoJvJF00+RFL+P3i
+Gx2DLERxRrDa8AVGfqaCjsR+3vLgG8V/py+z+dxZYSqeB80Qeo6PDITcRKoeAYh9
+xlT3LJOS+k1cJcEmlbbO2IjLkTmzSwa80fWexKu8/Xv6vv15gpqYl1ngYoqJM3pd
+vzmTIOi7MKSZ0WmEQavrZj8zK4endE3v0eAEeQ55j1GImbypSf7Idh7wOXtjZ7WD
+Dg6yWDrri+AP/L3gClMj8wsAxMV4ZR8CgcEA0fzDHkFa6raVOxWnObmRoDhAtE0a
+cjUj976NM5yyfdf2MrKy4/RhdTiPZ6b08/lBC/+xRfV3xKVGzacm6QjqjZrUpgHC
+0LKiZaMtccCJjLtPwQd0jGQEnKfMFaPsnhOc5y8qVkCzVOSthY5qhz0XNotHHFmJ
+gffVgB0iqrMTvSL7IA2yqqpOqNRlhaYhNl8TiFP3gIeMtVa9rZy31JPgT2uJ+kfo
+gV7sdTPEjPWZd7OshGxWpT6QfVDj/T9T7L6tAoHBAI3WBf2DFvxNL2KXT2QHAZ9t
+k3imC4f7U+wSE6zILaDZyzygA4RUbwG0gv8/TJVn2P/Eynf76DuWHGlaiLWnCbSz
+Az2DHBQBBaku409zDQym3j1ugMRjzzSQWzJg0SIyBH3hTmnYcn3+Uqcp/lEBvGW6
+O+rsXFt3pukqJmIV8HzLGGaLm62BHUeZf3dyWm+i3p/hQAL7Xvu04QW70xuGqdr5
+afV7p5eaeQIJXyGQJ0eylV/90+qxjMKiB1XYg6WYvwKBwQCL/ddpgOdHJGN8uRom
+e7Zq0Csi3hGheMKlKbN3vcxT5U7MdyHtTZZOJbTvxKNNUNYH/8uD+PqDGNneb29G
+BfGzvI3EASyLIcGZF3OhKwZd0jUrWk2y7Vhob91jwp2+t73vdMbkKyI4mHOuXvGv
+fg95si9oO7EBT+Oqvhccd2J+F1IVXncccYnF4u5ZGWt5lLewN/pVr7MjjykeaHqN
+t+rfnQam2psA6fL4zS2zTmZPzR2tnY8Y1GBTi0Ko1OKd1HMCgcAb5cB/7/AQlhP9
+yQa04PLH9ygQkKKptZp7dy5WcWRx0K/hAHRoi2aw1wZqfm7VBNu2SLcs90kCCCxp
+6C5sfJi6b8NpNbIPC+sc9wsFr7pGo9SFzQ78UlcWYK2Gu2FxlMjonhka5hvo4zvg
+WxlpXKEkaFt3gLd92m/dMqBrHfafH7VwOJY2zT3WIpjwuk0ZzmRg5p0pG/svVQEH
+NZmwRwlopysbR69B/n1nefJ84UO50fLh5s5Zr3gBRwbWNZyzhXk=
+-----END RSA PRIVATE KEY-----
diff --git a/external/sgx-emm/api_tests/Enclave/config.xml b/external/sgx-emm/api_tests/Enclave/config.xml
new file mode 100644
index 000000000..f96ddcd47
--- /dev/null
+++ b/external/sgx-emm/api_tests/Enclave/config.xml
@@ -0,0 +1,21 @@
+
+ 0
+ 0
+ 248
+ 3
+ 1
+ 248
+
+ 0x10000
+ 0x2000
+ 0xF0000000
+ 0x9000
+ 0x08000
+ 0x90000000
+
+ 0
+ 1
+ 0xFFFFFFFF
+
diff --git a/external/sgx-emm/api_tests/Makefile b/external/sgx-emm/api_tests/Makefile
new file mode 100644
index 000000000..4f49bc834
--- /dev/null
+++ b/external/sgx-emm/api_tests/Makefile
@@ -0,0 +1,265 @@
+#
+# Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+######## SGX SDK Settings ########
+
+SGX_SDK ?= /opt/intel/sgxsdk
+SGX_MODE ?= HW
+SGX_ARCH ?= x64
+SGX_DEBUG ?= 1
+
+include $(SGX_SDK)/buildenv.mk
+
+ifeq ($(shell getconf LONG_BIT), 32)
+ SGX_ARCH := x86
+else ifeq ($(findstring -m32, $(CXXFLAGS)), -m32)
+ SGX_ARCH := x86
+endif
+
+ifeq ($(SGX_ARCH), x86)
+ SGX_COMMON_FLAGS := -m32
+ SGX_LIBRARY_PATH := $(SGX_SDK)/lib
+ SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x86/sgx_sign
+ SGX_EDGER8R := $(SGX_SDK)/bin/x86/sgx_edger8r
+else
+ SGX_COMMON_FLAGS := -m64
+ SGX_LIBRARY_PATH := $(SGX_SDK)/lib64
+ SGX_ENCLAVE_SIGNER := $(SGX_SDK)/bin/x64/sgx_sign
+ SGX_EDGER8R := $(SGX_SDK)/bin/x64/sgx_edger8r
+endif
+
+ifeq ($(SGX_DEBUG), 1)
+ifeq ($(SGX_PRERELEASE), 1)
+$(error Cannot set SGX_DEBUG and SGX_PRERELEASE at the same time!!)
+endif
+endif
+
+ifeq ($(SGX_DEBUG), 1)
+ SGX_COMMON_FLAGS += -O0 -g
+else
+ SGX_COMMON_FLAGS += -O2
+endif
+
+SGX_COMMON_FLAGS += -Wall -Wextra -Winit-self -Wpointer-arith -Wreturn-type \
+ -Waddress -Wsequence-point -Wformat-security \
+ -Wmissing-include-dirs -Wfloat-equal -Wundef -Wshadow \
+ -Wcast-align -Wcast-qual -Wconversion -Wredundant-decls
+SGX_COMMON_CFLAGS := $(SGX_COMMON_FLAGS) -Wjump-misses-init -Wstrict-prototypes -Wunsuffixed-float-constants
+SGX_COMMON_CXXFLAGS := $(SGX_COMMON_FLAGS) -Wnon-virtual-dtor -std=c++11
+
+######## App Settings ########
+
+ifneq ($(SGX_MODE), HW)
+ Urts_Library_Name := sgx_urts_sim
+else
+ Urts_Library_Name := sgx_urts
+endif
+
+App_Cpp_Files := App/App.cpp
+App_Include_Paths := -IApp -I$(SGX_SDK)/include
+
+App_C_Flags := -fPIC -Wno-attributes $(App_Include_Paths)
+
+# Three configuration modes - Debug, prerelease, release
+# Debug - Macro DEBUG enabled.
+# Prerelease - Macro NDEBUG and EDEBUG enabled.
+# Release - Macro NDEBUG enabled.
+ifeq ($(SGX_DEBUG), 1)
+ App_C_Flags += -DDEBUG -UNDEBUG -UEDEBUG
+else ifeq ($(SGX_PRERELEASE), 1)
+ App_C_Flags += -DNDEBUG -DEDEBUG -UDEBUG
+else
+ App_C_Flags += -DNDEBUG -UEDEBUG -UDEBUG
+endif
+
+App_Cpp_Flags := $(App_C_Flags)
+App_Link_Flags := -L$(SGX_LIBRARY_PATH) -l$(Urts_Library_Name) -lpthread
+
+App_Cpp_Objects := $(App_Cpp_Files:.cpp=.o)
+
+App_Name := test_mm_api
+
+######## Enclave Settings ########
+
+ifneq ($(SGX_MODE), HW)
+ Trts_Library_Name := sgx_trts_sim
+ Service_Library_Name := sgx_tservice_sim
+else
+ Trts_Library_Name := sgx_trts
+ Service_Library_Name := sgx_tservice
+endif
+Crypto_Library_Name := sgx_tcrypto
+
+Enclave_Cpp_Files := Enclave/Enclave.cpp
+Enclave_Include_Paths := -IEnclave -I$(SGX_SDK)/include -I$(SGX_SDK)/include/tlibc -I$(SGX_SDK)/include/libcxx
+
+Enclave_C_Flags := $(Enclave_Include_Paths) -nostdinc -fvisibility=hidden -fpie -ffunction-sections -fdata-sections $(MITIGATION_CFLAGS)
+CC_BELOW_4_9 := $(shell expr "`$(CC) -dumpversion`" \< "4.9")
+ifeq ($(CC_BELOW_4_9), 1)
+ Enclave_C_Flags += -fstack-protector
+else
+ Enclave_C_Flags += -fstack-protector-strong
+endif
+
+Enclave_Cpp_Flags := $(Enclave_C_Flags) -nostdinc++
+
+# Enable the security flags
+Enclave_Security_Link_Flags := -Wl,-z,relro,-z,now,-z,noexecstack
+
+# To generate a proper enclave, it is recommended to follow below guideline to link the trusted libraries:
+# 1. Link sgx_trts with the `--whole-archive' and `--no-whole-archive' options,
+# so that the whole content of trts is included in the enclave.
+# 2. For other libraries, you just need to pull the required symbols.
+# Use `--start-group' and `--end-group' to link these libraries.
+# Do NOT move the libraries linked with `--start-group' and `--end-group' within `--whole-archive' and `--no-whole-archive' options.
+# Otherwise, you may get some undesirable errors.
+Enclave_Link_Flags := $(MITIGATION_LDFLAGS) $(Enclave_Security_Link_Flags) \
+ -Wl,--no-undefined -nostdlib -nodefaultlibs -nostartfiles -L$(SGX_TRUSTED_LIBRARY_PATH) \
+ -Wl,--whole-archive -l$(Trts_Library_Name) -Wl,--no-whole-archive \
+ -Wl,--start-group -lsgx_tstdc -lsgx_tcxx -l$(Crypto_Library_Name) -l$(Service_Library_Name) -Wl,--end-group \
+ -Wl,-Bstatic -Wl,-Bsymbolic -Wl,--no-undefined \
+ -Wl,-pie,-eenclave_entry -Wl,--export-dynamic \
+ -Wl,--defsym,__ImageBase=0 -Wl,--gc-sections \
+ -Wl,--version-script=Enclave/Enclave.lds
+
+Enclave_Cpp_Objects := $(sort $(Enclave_Cpp_Files:.cpp=.o))
+
+Enclave_Name := enclave.so
+Signed_Enclave_Name := enclave.signed.so
+Enclave_Config_File := Enclave/config.xml
+
+ifeq ($(SGX_MODE), HW)
+ifeq ($(SGX_DEBUG), 1)
+ Build_Mode = HW_DEBUG
+else ifeq ($(SGX_PRERELEASE), 1)
+ Build_Mode = HW_PRERELEASE
+else
+ Build_Mode = HW_RELEASE
+endif
+else
+ifeq ($(SGX_DEBUG), 1)
+ Build_Mode = SIM_DEBUG
+else ifeq ($(SGX_PRERELEASE), 1)
+ Build_Mode = SIM_PRERELEASE
+else
+ Build_Mode = SIM_RELEASE
+endif
+endif
+
+
+.PHONY: all target run
+all: .config_$(Build_Mode)_$(SGX_ARCH)
+ @$(MAKE) target
+
+ifeq ($(Build_Mode), HW_RELEASE)
+target: $(App_Name) $(Enclave_Name)
+ @echo "The project has been built in release hardware mode."
+ @echo "Please sign the $(Enclave_Name) first with your signing key before you run the $(App_Name) to launch and access the enclave."
+ @echo "To sign the enclave use the command:"
+ @echo " $(SGX_ENCLAVE_SIGNER) sign -key -enclave $(Enclave_Name) -out <$(Signed_Enclave_Name)> -config $(Enclave_Config_File)"
+ @echo "You can also sign the enclave using an external signing tool."
+ @echo "To build the project in simulation mode set SGX_MODE=SIM. To build the project in prerelease mode set SGX_PRERELEASE=1 and SGX_MODE=HW."
+
+
+else
+target: $(App_Name) $(Signed_Enclave_Name)
+ifeq ($(Build_Mode), HW_DEBUG)
+ @echo "The project has been built in debug hardware mode."
+else ifeq ($(Build_Mode), SIM_DEBUG)
+ @echo "The project has been built in debug simulation mode."
+else ifeq ($(Build_Mode), HW_PRERELEASE)
+ @echo "The project has been built in pre-release hardware mode."
+else ifeq ($(Build_Mode), SIM_PRERELEASE)
+ @echo "The project has been built in pre-release simulation mode."
+else
+ @echo "The project has been built in release simulation mode."
+endif
+
+endif
+
+run: all
+ifneq ($(Build_Mode), HW_RELEASE)
+ @$(CURDIR)/$(App_Name)
+ @echo "RUN => $(App_Name) [$(SGX_MODE)|$(SGX_ARCH), OK]"
+endif
+
+.config_$(Build_Mode)_$(SGX_ARCH):
+ @rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*
+ @touch .config_$(Build_Mode)_$(SGX_ARCH)
+
+######## App Objects ########
+
+App/Enclave_u.h: $(SGX_EDGER8R) Enclave/Enclave.edl
+ @cd App && $(SGX_EDGER8R) --untrusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
+ @echo "GEN => $@"
+
+App/Enclave_u.c: App/Enclave_u.h
+
+App/Enclave_u.o: App/Enclave_u.c
+ @$(CC) $(SGX_COMMON_CFLAGS) $(App_C_Flags) -c $< -o $@
+ @echo "CC <= $<"
+
+App/%.o: App/%.cpp App/Enclave_u.h
+ @$(CXX) $(SGX_COMMON_CXXFLAGS) $(App_Cpp_Flags) -c $< -o $@
+ @echo "CXX <= $<"
+
+$(App_Name): App/Enclave_u.o $(App_Cpp_Objects)
+ @$(CXX) $^ -o $@ $(App_Link_Flags)
+ @echo "LINK => $@"
+
+######## Enclave Objects ########
+
+Enclave/Enclave_t.h: $(SGX_EDGER8R) Enclave/Enclave.edl
+ @cd Enclave && $(SGX_EDGER8R) --trusted ../Enclave/Enclave.edl --search-path ../Enclave --search-path $(SGX_SDK)/include
+ @echo "GEN => $@"
+
+Enclave/Enclave_t.c: Enclave/Enclave_t.h
+
+Enclave/Enclave_t.o: Enclave/Enclave_t.c
+ @$(CC) $(SGX_COMMON_CFLAGS) $(Enclave_C_Flags) -c $< -o $@
+ @echo "CC <= $<"
+
+Enclave/%.o: Enclave/%.cpp Enclave/Enclave_t.h
+ @$(CXX) $(SGX_COMMON_CXXFLAGS) $(Enclave_Cpp_Flags) -c $< -o $@
+ @echo "CXX <= $<"
+
+$(Enclave_Name): Enclave/Enclave_t.o $(Enclave_Cpp_Objects)
+ @$(CXX) $^ -o $@ $(Enclave_Link_Flags)
+ @echo "LINK => $@"
+
+$(Signed_Enclave_Name): $(Enclave_Name)
+ @$(SGX_ENCLAVE_SIGNER) sign -key Enclave/Enclave_private_test.pem -enclave $(Enclave_Name) -out $@ -config $(Enclave_Config_File)
+ @echo "SIGN => $@"
+
+.PHONY: clean
+
+clean:
+ @rm -f .config_* $(App_Name) $(Enclave_Name) $(Signed_Enclave_Name) $(App_Cpp_Objects) App/Enclave_u.* $(Enclave_Cpp_Objects) Enclave/Enclave_t.*
diff --git a/external/sgx-emm/api_tests/tcs.h b/external/sgx-emm/api_tests/tcs.h
new file mode 100644
index 000000000..a6012e3a2
--- /dev/null
+++ b/external/sgx-emm/api_tests/tcs.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef TCS_H_
+#define TCS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct _tcs_t
+{
+ uint64_t reserved0; /* (0) */
+ uint64_t flags; /* (8)bit 0: DBGOPTION */
+ uint64_t ossa; /* (16)State Save Area */
+ uint32_t cssa; /* (24)Current SSA slot */
+ uint32_t nssa; /* (28)Number of SSA slots */
+ uint64_t oentry; /* (32)Offset in enclave to which control is transferred on EENTER if enclave INACTIVE state */
+ uint64_t reserved1; /* (40) */
+ uint64_t ofs_base; /* (48)When added to the base address of the enclave, produces the base address FS segment inside the enclave */
+ uint64_t ogs_base; /* (56)When added to the base address of the enclave, produces the base address GS segment inside the enclave */
+ uint32_t ofs_limit; /* (64)Size to become the new FS limit in 32-bit mode */
+ uint32_t ogs_limit; /* (68)Size to become the new GS limit in 32-bit mode */
+#define TCS_RESERVED_LENGTH 4024
+ uint8_t reserved[TCS_RESERVED_LENGTH]; /* (72) */
+}tcs_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/external/sgx-emm/api_tests/test_loop.sh b/external/sgx-emm/api_tests/test_loop.sh
new file mode 100755
index 000000000..ea5d95d45
--- /dev/null
+++ b/external/sgx-emm/api_tests/test_loop.sh
@@ -0,0 +1,17 @@
+let fail=0
+for ((i=1;i<=$1;i++));do
+ ./test_mm_api
+ if [ $? -eq 0 ]
+ then
+ echo "pass for iteration $i"
+ else
+ echo "fail for iteration $i"
+ let fail=fail+1
+ fi
+done
+if [ $fail -eq 0 ]
+then
+ echo "passed $1 iterations"
+ else
+ echo "$fail out of $1 iterations failed"
+fi
diff --git a/external/sgx-emm/emm_src b/external/sgx-emm/emm_src
new file mode 160000
index 000000000..5497098a7
--- /dev/null
+++ b/external/sgx-emm/emm_src
@@ -0,0 +1 @@
+Subproject commit 5497098a71cd6e791fcbde6f524b334f7b45b80f
diff --git a/external/sgx-emm/ut/Makefile b/external/sgx-emm/ut/Makefile
new file mode 100644
index 000000000..34a7fa2e8
--- /dev/null
+++ b/external/sgx-emm/ut/Makefile
@@ -0,0 +1,55 @@
+#
+# Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Intel Corporation nor the names of its
+# contributors may be used to endorse or promote products derived
+# from this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+#
+
+include ../../../buildenv.mk
+
+CPPFLAGS += -I$(COMMON_DIR)/inc \
+ -I$(COMMON_DIR)/inc/internal \
+ -DTEST=1 -g
+
+.PHONY: all clean
+
+all: test_bit_array test_ema test_public test_emm
+
+test_bit_array: test_bit_array.c ../emm_src/bit_array.c
+ @$(CC) $(CPPFLAGS) $^ -o $@
+
+test_ema: test_ema.c stub.c ../ema.c ../bit_array.c
+ @$(CC) $(CPPFLAGS) $^ -o $@
+
+test_public: test_public.c stub.c ../sgx_mm.c ../ema.c ../bit_array.c
+ @$(CC) $(CPPFLAGS) $^ -o $@
+
+test_emm: test_emm.c stub.c ../emm_private.c ../sgx_mm.c ../ema.c ../bit_array.c
+ @$(CC) $(CPPFLAGS) $^ -o $@
+
+clean:
+ @$(RM) test_bit_array test_ema test_public test_emm
diff --git a/sdk/trts/trts_trim.cpp b/external/sgx-emm/ut/stub.c
similarity index 56%
rename from sdk/trts/trts_trim.cpp
rename to external/sgx-emm/ut/stub.c
index de447033a..8fe080d52 100644
--- a/sdk/trts/trts_trim.cpp
+++ b/external/sgx-emm/ut/stub.c
@@ -29,58 +29,80 @@
*
*/
+#include "../sgx_mm_primitives.h"
+#include "../sgx_mm_rt_abstraction.h"
-#include "trts_trim.h"
-#include "sgx_trts.h" // for sgx_ocalloc, sgx_is_outside_enclave
-#include "internal/rts.h"
+struct _sgx_mm_mutex {
+ void *impl;
+} g_mm_lock;
-/* sgx_ocfree() just restores the original outside stack pointer. */
-#define OCALLOC(val, type, len) do { \
- void* __tmp = sgx_ocalloc(len); \
- if (__tmp == NULL) { \
- sgx_ocfree(); \
- return SGX_ERROR_UNEXPECTED;\
- } \
- (val) = (type)__tmp; \
-} while (0)
-
-typedef struct ms_trim_range_ocall_t {
- size_t ms_fromaddr;
- size_t ms_toaddr;
-} ms_trim_range_ocall_t;
-
-typedef struct ms_trim_range_commit_ocall_t {
- size_t ms_addr;
-} ms_trim_range_commit_ocall_t;
+int do_eaccept(const sec_info_t* si, size_t addr)
+{
+ return 0;
+}
-sgx_status_t SGXAPI trim_range_ocall(size_t fromaddr, size_t toaddr)
+int do_eacceptcopy(const sec_info_t* si, size_t addr, size_t src)
{
- sgx_status_t status = SGX_SUCCESS;
+ return 0;
+}
- ms_trim_range_ocall_t* ms;
- OCALLOC(ms, ms_trim_range_ocall_t*, sizeof(*ms));
+int do_emodpe(const sec_info_t* si, size_t addr)
+{
+ return 0;
+}
- ms->ms_fromaddr = fromaddr;
- ms->ms_toaddr = toaddr;
- status = sgx_ocall(EDMM_TRIM, ms);
+int sgx_mm_alloc_ocall(size_t addr, size_t length, int props, int flags)
+{
+ return 0;
+}
+int sgx_mm_modify_ocall(size_t addr, size_t length, int flags_from, int flags_to)
+{
+ return 0;
+}
- sgx_ocfree();
- return status;
+size_t get_rts_base()
+{
+ return 0;
}
-sgx_status_t SGXAPI trim_range_commit_ocall(size_t addr)
+size_t get_rts_end()
{
- sgx_status_t status = SGX_SUCCESS;
+ return 0x7FFFFF000000;
+}
- ms_trim_range_commit_ocall_t* ms;
- OCALLOC(ms, ms_trim_range_commit_ocall_t*, sizeof(*ms));
+size_t get_user_base()
+{
+ return 0x7FFFFF000000;
+}
- ms->ms_addr = addr;
- status = sgx_ocall(EDMM_TRIM_COMMIT, ms);
+size_t get_user_end()
+{
+ return 0x7FFFFFFFFFFF;
+}
+bool sgx_mm_is_within_enclave(const void *ptr, size_t size){
+ return true;
+}
- sgx_ocfree();
- return status;
+sgx_mm_mutex* sgx_mm_mutex_create(void)
+{
+ return &g_mm_lock;
+}
+int sgx_mm_mutex_lock(sgx_mm_mutex *mutex)
+{
+ return 0;
+}
+int sgx_mm_mutex_unlock(sgx_mm_mutex *mutex)
+{
+ return 0;
}
+int sgx_mm_mutex_destroy(sgx_mm_mutex *mutex)
+{
+ return 0;
+}
+bool sgx_mm_register_pfhandler(sgx_mm_pfhandler_t pfhandler)
+{
+ return true;
+}
diff --git a/external/sgx-emm/ut/test_bit_array.c b/external/sgx-emm/ut/test_bit_array.c
new file mode 100644
index 000000000..c329fcb88
--- /dev/null
+++ b/external/sgx-emm/ut/test_bit_array.c
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include "bit_array.h"
+
+int main()
+{
+ bit_array *ba = bit_array_new_set(31);
+
+ assert(bit_array_size(ba) == 31);
+
+ assert(bit_array_any(ba) == true);
+ assert(bit_array_none(ba) == false);
+
+ assert(bit_array_test(ba, 0) == true);
+ assert(bit_array_test(ba, 15) == true);
+ assert(bit_array_test(ba, 18) == true);
+ assert(bit_array_test(ba, 24) == true);
+ assert(bit_array_test(ba, 30) == true);
+
+ assert(bit_array_test_range(ba, 17, 10) == true);
+ assert(bit_array_all(ba) == true);
+
+ bit_array_reset_range(ba, 17, 10);
+ assert(bit_array_test_range(ba, 17, 10) == false);
+ assert(bit_array_test(ba, 17) == false);
+ assert(bit_array_test(ba, 18) == false);
+ assert(bit_array_test(ba, 24) == false);
+ assert(bit_array_test(ba, 26) == false);
+ assert(bit_array_test(ba, 27) == true);
+
+ bit_array_flip(ba, 30);
+ assert(bit_array_test(ba, 30) == false);
+
+ bit_array *lo = NULL, *hi = NULL;
+ int ret = bit_array_split(ba, 0, &lo, &hi);
+ assert(ret == 0);
+ assert(lo == NULL);
+ assert(hi == ba);
+
+ ret = bit_array_split(ba, 31, &lo, &hi);
+ assert(ret == 0);
+ assert(lo == ba);
+ assert(hi == NULL);
+
+ ret = bit_array_split(ba, 17, &lo, &hi);
+ assert(lo == ba);
+ assert(ret == 0);
+ bit_array_delete(lo);
+
+ bit_array *new_ba = NULL, *new_hi = NULL;
+ ret = bit_array_split(hi, 10, &new_ba, &new_hi);
+ assert(ret == 0);
+ assert(new_ba == hi);
+ assert(bit_array_size(new_ba) == 10);
+ assert(bit_array_none(new_ba) == true);
+ assert(bit_array_size(new_hi) == 4);
+ assert(bit_array_all(new_hi) == false);
+ assert(bit_array_test(new_hi, 3) == false);
+
+ bit_array_delete(new_ba);
+ bit_array_delete(new_hi);
+ return 0;
+}
diff --git a/external/sgx-emm/ut/test_ema.c b/external/sgx-emm/ut/test_ema.c
new file mode 100644
index 000000000..7ceb61408
--- /dev/null
+++ b/external/sgx-emm/ut/test_ema.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include
+#include
+#include "ema.h"
+
+extern ema_root_t g_user_ema_root;
+extern ema_root_t g_rts_ema_root;
+struct ema_root_ {
+ ema_t *guard;
+};
+
+int main()
+{
+ //make sure rts is inited.
+ ema_t *node0 = ema_new(0, 0xFFF00000,
+ SGX_EMA_COMMIT_NOW,
+ SGX_EMA_PROT_READ_WRITE | SGX_EMA_PAGE_TYPE_REG,
+ NULL, NULL, g_rts_ema_root.guard);
+
+ assert(node0);
+ // find_build/insert node
+ size_t addr = 0;
+ ema_t *next_ema = NULL;
+ bool ret = find_free_region(&g_user_ema_root,
+ 0x2000, SGX_PAGE_SIZE, &addr, &next_ema);
+
+ assert(ret == true);
+ assert(addr == 0xFFF00000);
+ assert(next_ema == g_user_ema_root.guard);
+
+ node0 = ema_new(0xFFF00000, 0x2000,
+ SGX_EMA_COMMIT_ON_DEMAND,
+ SGX_EMA_PROT_READ_WRITE | SGX_EMA_PAGE_TYPE_REG,
+ NULL, NULL, next_ema);
+
+
+ // find at/build/push_back node
+
+ ret = find_free_region_at(&g_user_ema_root, 0xFFF03000,
+ 0x1000,
+ &next_ema);
+
+ assert(ret == true);
+ assert(next_ema == g_user_ema_root.guard);
+
+ ema_t *node1 = ema_new(0xFFF03000, 0x1000,
+ SGX_EMA_COMMIT_NOW,
+ SGX_EMA_PROT_READ_WRITE | SGX_EMA_PAGE_TYPE_REG,
+ NULL, NULL, g_user_ema_root.guard);
+
+
+ // negative case for find_at
+ ret = find_free_region_at(&g_user_ema_root,
+ 0xFFF02000, 0x3000, &next_ema);
+
+ assert(ret == false);
+ assert(next_ema == NULL);
+
+
+ // find_at/build/insert node
+ ret = find_free_region_at(&g_user_ema_root,
+ 0xFFF06000, 0x3000, &next_ema);
+
+ assert(ret == true);
+ assert(next_ema == g_user_ema_root.guard);
+
+ ema_t *node2 = ema_new(0xFFF06000, 0x3000,
+ SGX_EMA_COMMIT_ON_DEMAND,
+ SGX_EMA_PROT_READ_WRITE | SGX_EMA_PAGE_TYPE_REG,
+ NULL, NULL, next_ema);
+
+ // dump current nodes on the root
+ dump_ema_root(&g_user_ema_root);
+
+ ema_t *first = NULL, *last = NULL;
+
+ // search_ema_range #1
+ int r = search_ema_range(&g_user_ema_root,
+ 0xFFF00000, 0xFFF06000,
+ &first, &last);
+ assert(r == 0);
+ assert(first == node0);
+ assert(last == node2);
+
+
+ // search_ema_range #2
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFF02000, 0xFFF06000,
+ &first, &last);
+ assert(r == 0);
+ assert(first == node1);
+ assert(last == node2);
+
+
+ // search_ema_range #3
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFF02000, 0xFFF09000,
+ &first, &last);
+ assert(r == 0);
+ assert(first == node1);
+ assert(last == g_user_ema_root.guard);
+
+ // search_ema_range #4
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFF01000, 0xFFF05000,
+ &first, &last);
+ assert(r == 0);
+ assert(first == node0);
+ assert(last == node2);
+
+ // negative case, middle address region
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFF04000, 0xFFF05000,
+ &first, &last);
+ assert(r == -1);
+ assert(first == NULL);
+ assert(last == NULL);
+
+ // negative case, front address region
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFE00000, 0xFFF00000,
+ &first, &last);
+ assert(r == -1);
+ assert(first == NULL);
+ assert(last == NULL);
+
+ // negative case, rear address region
+ r = search_ema_range(&g_user_ema_root,
+ 0xFFF0A000, 0xFFF0B000,
+ &first, &last);
+ assert(r == -1);
+ assert(first == NULL);
+ assert(last == NULL);
+
+
+ // ema split: split point is out of range
+ ema_t *tmp_node = NULL;
+ r = ema_split(node0, 0xFFE00000, true, &tmp_node);
+ assert(tmp_node == NULL);
+
+ // ema split: split point is out of range
+ tmp_node = NULL;
+ r = ema_split(node0, 0xFFF02000, false, &tmp_node);
+ assert(tmp_node == NULL);
+
+ // ema split: split point is within range
+ size_t node0_base = ema_base(node0);
+ tmp_node = NULL;
+ ema_split(node0, 0xFFF01000, true, &tmp_node);
+ assert(ema_next(tmp_node) == node0);
+ assert(ema_base(tmp_node) == node0_base);
+ assert(ema_size(tmp_node) == 0x1000);
+
+ tmp_node = NULL;
+ r = ema_split_ex(node2, 0xFFF07000, 0xFFF08000, &tmp_node);
+ assert(ema_base(tmp_node) == 0xFFF07000);
+ assert(ema_size(tmp_node) == 0x1000);
+ dump_ema_root(&g_user_ema_root);
+ destroy_ema_root(&g_user_ema_root);
+
+ return 0;
+}
diff --git a/external/sgx-emm/ut/test_emm.c b/external/sgx-emm/ut/test_emm.c
new file mode 100644
index 000000000..a82330d81
--- /dev/null
+++ b/external/sgx-emm/ut/test_emm.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "emm_private.h"
+#include "sgx_mm.h"
+
+int main()
+{
+ int ret = -1;
+ void* addr;
+ ret = mm_alloc((void *)0xFFFF0000, 0x10000,
+ SGX_EMA_COMMIT_NOW | SGX_EMA_GROWSUP,
+ NULL, NULL, &addr);
+
+ return ret;
+}
diff --git a/external/sgx-emm/ut/test_public.c b/external/sgx-emm/ut/test_public.c
new file mode 100644
index 000000000..64d15c243
--- /dev/null
+++ b/external/sgx-emm/ut/test_public.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "sgx_mm.h"
+
+int main()
+{
+ int ret = -1;
+
+ ret = sgx_mm_alloc((void *)0xFFFF0000, 0x10000,
+ SGX_EMA_COMMIT_NOW | SGX_EMA_GROWSUP,
+ NULL, NULL, NULL);
+
+ return ret;
+}
diff --git a/linux/installer/common/sdk/BOMs/sdk_base.txt b/linux/installer/common/sdk/BOMs/sdk_base.txt
index c9e5f348e..2b4309cd6 100644
--- a/linux/installer/common/sdk/BOMs/sdk_base.txt
+++ b/linux/installer/common/sdk/BOMs/sdk_base.txt
@@ -26,6 +26,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner
/common/inc/sgx_trts.h /package/include/./sgx_trts.h 0 main STP
/common/inc/sgx_tseal.h /package/include/./sgx_tseal.h 0 main STP
/common/inc/sgx_tstdc.edl /package/include/./sgx_tstdc.edl 0 main STP
+/common/inc/sgx_occlum_utils.edl /package/include/./sgx_occlum_utils.edl 0 main Occlum
/common/inc/sgx_uae_service.h /package/include/./sgx_uae_service.h 0 main STP
/common/inc/sgx_uae_epid.h /package/include/./sgx_uae_epid.h 0 main STP
/common/inc/sgx_uae_launch.h /package/include/./sgx_uae_launch.h 0 main STP
diff --git a/linux/installer/common/sdk/BOMs/sdk_x64.txt b/linux/installer/common/sdk/BOMs/sdk_x64.txt
index d96b24c0b..ca62ff7df 100644
--- a/linux/installer/common/sdk/BOMs/sdk_x64.txt
+++ b/linux/installer/common/sdk/BOMs/sdk_x64.txt
@@ -34,6 +34,9 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner
/build/linux/libsgx_pclsim.a /package/lib64/libsgx_pclsim.a 0 main STP
/build/linux/libsgx_urts_deploy.so /package/lib64/libsgx_urts.so 0 main STP
/build/linux/libsgx_urts_sim.so /package/lib64/libsgx_urts_sim.so 0 main STP
+/build/linux/libsgx_urts.a /package/lib64/libsgx_urts.a 0 main STP
+/build/linux/libsgx_urts_sim.a /package/lib64/libsgx_urts_sim.a 0 main STP
+/build/linux/libsgx_urts_sim_with_se_event.a /package/lib64/libsgx_urts_sim_with_se_event.a 0 main STP
/build/linux/libc++_Changes_SGX.txt /package/lib64/libc++_Changes_SGX.txt 0 main STP
/build/linux/sgx_config_cpusvn /package/bin/x64/sgx_config_cpusvn 0 main STP
/build/linux/sgx_edger8r /package/bin/x64/sgx_edger8r 0 main STP
diff --git a/linux/installer/common/sgx-aesm-service/Makefile b/linux/installer/common/sgx-aesm-service/Makefile
index 71face180..c86ca03fb 100644
--- a/linux/installer/common/sgx-aesm-service/Makefile
+++ b/linux/installer/common/sgx-aesm-service/Makefile
@@ -42,14 +42,10 @@ AESMD_CONF_DEL=$(if $(wildcard /run/systemd/system/.*),aesmd.conf,$(if $(wildcar
AESMD_CONF_PATH=$(if $(wildcard /run/systemd/system/.*),$(if $(wildcard /lib/systemd/system/.*),/lib/systemd/system,/usr/lib/systemd/system),$(if $(wildcard /etc/init/.*),/etc/init/))
ifeq ($(AESMD_CONF_NAME),)
-ifneq ($(shell awk -F/ '$$2 == "docker"' /proc/self/cgroup),)
AESMD_CONF_NAME=aesmd.service
AESMD_CONF_DEL=aesmd.conf
AESMD_CONF_PATH=/lib/systemd/system
$(warning "You may need to start aesmd manually after it's installed!")
-else
-$(error "Unsupported platform - neither systemctl nor initctl is found!")
-endif
endif
QE_VER=1.0.0
diff --git a/psw/enclave_common/Makefile b/psw/enclave_common/Makefile
index 6627e99c5..583536796 100644
--- a/psw/enclave_common/Makefile
+++ b/psw/enclave_common/Makefile
@@ -44,9 +44,10 @@ CXXFLAGS += $(ADDED_INC)
CFLAGS += -fPIC -Werror -g
CFLAGS += $(ADDED_INC)
-INC += -I$(SGX_HEADER_DIR) \
+INC += -I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal \
-I$(COMMON_DIR)/inc/internal/linux \
+ -I$(LINUX_EXTERNAL_DIR)/sgx-emm/emm_src/include \
-I$(LINUX_PSW_DIR)/urts/ \
-I$(LINUX_PSW_DIR)/urts/linux \
-I$(LINUX_PSW_DIR)/enclave_common
@@ -92,7 +93,7 @@ ifndef DEBUG
$(OBJCOPY) --add-gnu-debuglink=$(LIBSGX_ENCLAVE_COMMON_DEBUG) $(LIBSGX_ENCLAVE_COMMON)
endif
-$(OBJ): %.o: %.cpp
+$(OBJ): %.o: %.cpp sgx_mm_ocalls.cpp
$(CXX) -c $(CXXFLAGS) $(INC) $< -o $@
$(LIBWRAPPER):
diff --git a/psw/enclave_common/sgx_enclave_common.cpp b/psw/enclave_common/sgx_enclave_common.cpp
index 95e7eb4f6..f3dace1fd 100644
--- a/psw/enclave_common/sgx_enclave_common.cpp
+++ b/psw/enclave_common/sgx_enclave_common.cpp
@@ -47,12 +47,12 @@
#include
#include "se_memcpy.h"
#include "se_lock.hpp"
+#include "sgx_mm.h"
//ubuntu 18.04 use glibc 2.27, doesn't support MAP_FIXED_NOREPLACE
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0x100000
#endif
-
#define POINTER_TO_U64(A) ((__u64)((uintptr_t)(A)))
#define SGX_LAUNCH_SO "libsgx_launch.so.1"
@@ -1066,7 +1066,6 @@ extern "C" size_t COMM_API enclave_load_data(
}
-
/* enclave_initialize()
* Parameters:
* base_address [in] - The enclave base address as returned from the enclave_create API.
@@ -1312,4 +1311,9 @@ extern "C" bool COMM_API enclave_set_information(
return false;
}
-
+uint32_t COMM_API enclave_get_features()
+{
+ //!TODO
+ return 0;
+}
+#include "sgx_mm_ocalls.cpp"
diff --git a/psw/enclave_common/sgx_enclave_common.h b/psw/enclave_common/sgx_enclave_common.h
index cdedbed98..32f4ef21d 100644
--- a/psw/enclave_common/sgx_enclave_common.h
+++ b/psw/enclave_common/sgx_enclave_common.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ * Copyright (C) 2011-2022 Intel Corporation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -35,11 +35,23 @@
#include
#include
#include
+#ifdef _MSC_VER
+#include
+#endif
#ifdef __cplusplus
extern "C" {
#endif
+#ifdef _MSC_VER
+/* The following macros are MSVC only */
+#define COMM_API cdecl
+#define COMM_IN _In_
+#define COMM_IN_OPT _In_opt_
+#define COMM_OUT _Out_
+#define COMM_OUT_OPT _Out_opt_
+#define COMM_IN_OUT _Inout_
+#else
/* The following macros are for GCC only */
#define COMM_API
#define COMM_IN
@@ -47,9 +59,12 @@ extern "C" {
#define COMM_OUT
#define COMM_OUT_OPT
#define COMM_IN_OUT
+#endif
#ifndef ENCLAVE_TYPE_SGX
#define ENCLAVE_TYPE_SGX 0x00000001 /* An enclave for the Intel Software Guard Extensions (SGX) architecture version 1. */
+#endif
+#ifndef ENCLAVE_TYPE_SGX2
#define ENCLAVE_TYPE_SGX2 0x00000002 /* An enclave for the Intel Software Guard Extensions (SGX) architecture version 2. */
#endif
#define ENCLAVE_TYPE_SGX1 ENCLAVE_TYPE_SGX
@@ -86,9 +101,29 @@ typedef enum {
ENCLAVE_PAGE_WRITE = 1 << 1, /* Enables write access to the committed region of pages. */
ENCLAVE_PAGE_EXECUTE = 1 << 2, /* Enables execute access to the committed region of pages. */
ENCLAVE_PAGE_THREAD_CONTROL = 1 << 8, /* The page contains a thread control structure. */
+ ENCLAVE_PAGE_REG = 2 << 8, /* The page contains a PT_REG page. */
+ ENCLAVE_PAGE_TRIM = 4 << 8, /* The page is trimmed(PT_TRIM). This is for pages which will be trimmed (removed) from the enclave. */
+ ENCLAVE_PAGE_SS_FIRST = 5 << 8, /* The page contains the first page of a Shadow Stack (future). */
+ ENCLAVE_PAGE_SS_REST = 6 << 8, /* The page contains a non-first page of a Shadow Stack (future). */
ENCLAVE_PAGE_UNVALIDATED = 1 << 12, /* The page contents that you supply are excluded from measurement and content validation. */
} enclave_page_properties_t;
+/*
+ * Hints to OS on how application may use the pages allocated with enclave_alloc.
+ */
+typedef enum {
+ ENCLAVE_EMA_NONE = 0, /* No suggestions provided. */
+ ENCLAVE_EMA_RESERVE = 1, /* Suggest that the kernel should reserve the memory range and not immediately EAUG pages. */
+ ENCLAVE_EMA_COMMIT_NOW = 2, /* Gives a hint that the kernel should EAUG pages immediately. */
+ ENCLAVE_EMA_COMMIT_ON_DEMAND = 4, /* Gives a hint that the kernel can EAUG pages later. */
+ ENCLAVE_EMA_GROWSDOWN = 16, /* Gives a hint to the kernel that the application will access pages above the
+ last accessed page. The kernel may want to EAUG pages from higher to lower addresses
+ with no gaps in addresses above the last committed page. */
+ ENCLAVE_EMA_GROWSUP = 32, /* Gives a hint to the kernel that the application will access pages below the
+ last accessed page. The kernel may want to EAUG pages from lower to higher addresses
+ with no gaps in addresses below the last committed page. */
+} enclave_alloc_flags_t;
+
typedef enum {
ENCLAVE_LAUNCH_TOKEN = 0x1
} enclave_info_type_t;
@@ -100,12 +135,12 @@ typedef enum {
#define ENCLAVE_CREATE_EX_EL_RANGE (1 << ENCLAVE_CREATE_EX_EL_RANGE_BIT_IDX) // Reserve Bit 0 for the el_range config
//update the following when adding new extended feature
-#define _ENCLAVE_CREATE_LAST_EX_FEATURE_IDX_ ENCLAVE_CREATE_EX_EL_RANGE_BIT_IDX
+#define _ENCLAVE_CREATE_LAST_EX_FEATURE_IDX_ ENCLAVE_CREATE_EX_EL_RANGE_BIT_IDX
#define _ENCLAVE_CREATE_EX_FEATURES_MASK_ (((uint32_t)-1) >> (ENCLAVE_CREATE_MAX_EX_FEATURES_COUNT - 1 - _ENCLAVE_CREATE_LAST_EX_FEATURE_IDX_))
-typedef struct enclave_elrange{
+typedef struct enclave_elrange {
uint64_t enclave_image_address;
uint64_t elrange_start_address;
uint64_t elrange_size;
@@ -148,7 +183,7 @@ void* COMM_API enclave_create_ex(
COMM_IN const uint32_t ex_features,
COMM_IN const void* ex_features_p[32],
COMM_OUT_OPT uint32_t* enclave_error);
-
+
/* enclave_create()
* Parameters:
@@ -175,7 +210,7 @@ void* COMM_API enclave_create(
/* enclave_load_data()
* Parameters:
* target_address [in] - The address in the enclave where you want to load the data.
- * target_size [in] - The size of the range that you want to load in the enclave, in bytes.
+ * target_size [in] - The size of the range that you want to load in the enclave, in bytes.
* source_buffer [in, optional] - An optional pointer to the data you want to load into the enclave.
* data_properties [in] - The properties of the pages you want to add to the enclave.
* enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
@@ -193,7 +228,7 @@ size_t COMM_API enclave_load_data(
/* enclave_initialize()
* Parameters:
* base_address [in] - The enclave base address as returned from the enclave_create API.
- * info [in] - A pointer to the architecture-specific information to use to initialize the enclave.
+ * info [in] - A pointer to the architecture-specific information to use to initialize the enclave.
* info_size [in] - The length of the structure that the info parameter points to, in bytes.
* enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
* Return Value:
@@ -224,7 +259,7 @@ bool COMM_API enclave_delete(
* info_type[in] - Identifies the type of information requested. initialized.
* output_info[out] - Pointer to information returned by the API
* output_info_size[in, out] - Size of the output_info buffer, in bytes. If the API succeeds, then this will return the number of bytes returned in output_info. If the API fails with, ENCLAVE_INVALID_SIZE, then this will return the required size
- * enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
+ * enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
*/
bool COMM_API enclave_get_information(
COMM_IN void* base_address,
@@ -239,7 +274,7 @@ bool COMM_API enclave_get_information(
* info_type[in] - Identifies the type of information requested. not been initialized.
* input_info[in] - Pointer to information provided to the API
* input_info_size[in] - Size of the information, in bytes, provided in input_info from the API.
- * enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
+ * enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
*/
bool COMM_API enclave_set_information(
COMM_IN void* base_address,
@@ -247,6 +282,116 @@ bool COMM_API enclave_set_information(
COMM_IN void* input_info,
COMM_IN size_t input_info_size,
COMM_OUT_OPT uint32_t* enclave_error);
+
+/* enclave_get_features()
+ * Parameters:
+ * None
+ * Return Value:
+ * Returns flags indicating enclave features which are supported on the platform.
+ */
+uint32_t COMM_API enclave_get_features();
+
+/* enclave_alloc()
+ * Call OS to reserve region for EAUG, immediately or on-demand.
+ *
+ * Parameters
+ * targt_addr [in] - Desired page aligned start address.
+ * target_size [in] - Size of the region in bytes of multiples of page size.
+ * data_properties [in] - Page types to be allocated, must be one of these:
+ * - ENCLAVE_PAGE_REG: regular page type. This is the default if not specified.
+ * - ENCLAVE_PAGE_SS_FIRST: the first page in shadow stack.
+ * - ENCLAVE_PAGE_SS_REST: the rest page in shadow stack.
+ * alloc_flags [in] - A bitwise OR of flags describing committing mode, committing
+ * order, address preference, page type. The untrusted side. Implementation
+ * should always invoke mmap syscall with MAP_SHARED|MAP_FIXED_NOREPLACE, and
+ * translate following additional bits to proper parameters invoking mmap or
+ * other SGX specific syscall(s) provided by the kernel. The alloc_flags param
+ * of this interface should include exactly one of following for committing mode:
+ * - ENCLAVE_EMA_COMMIT_NOW: reserves memory range with ENCLAVE_PAGE_READ|SGX_EMA_PROT_WRITE, if supported,
+ * kernel is given a hint to EAUG EPC pages for the area as soon as possible.
+ * - ENCLAVE_EMA_COMMIT_ON_DEMAND: reserves memory range, EPC pages can be EAUGed upon #PF.
+ * ORed with zero or one of the committing order flags:
+ * - ENCLAVE_EMA_GROWSDOWN: if supported, a hint given for the kernel to EAUG pages from higher
+ * to lower addresses, no gaps in addresses above the last committed.
+ * - ENCLAVE_EMA_GROWSUP: if supported, a hint given for the kernel to EAUG pages from lower
+ * to higher addresses, no gaps in addresses below the last committed.
+ * enclave_error [out, optional] - An optional pointer to a variable that receives an enclave error code.
+ *
+ * Return Values:
+ * ENCLAVE_ERROR_SUCCESS(0): The operation was successful.
+ * ENCLAVE_NOT_SUPPORTED: Enavle feature is not supported by the system
+ * ENCLAVE_LOST: May be returned if the enclave has been removed or if it has not been initialized (via EINIT)
+ * ENCLAVE_INVALID_ADDRESS: The start address does not point to an enclave.
+ * ENCLAVE_INVALID_PARAMETER: An invalid combination of flags was provided.
+ * ENCLAVE_OUT_OF_MEMORY: No EPC left (some OSes like Linux), or system is out of memory for internal allocation by OS or this function.
+ * ENCLAVE_DEVICE_NO_MEMORY: NO EPC left (some OSes like Windows)
+ * ENCLAVE_INVALID_ADDRESS: Address does not point to an enclave or valid memory within the enclave
+ * ENCLAVE_NOT_INITIALIZED: May be returned if the enclave has not been initialized (via EINIT).
+ * Some configurations may give ENCLAVE_LOST if the enclave has not been initialized.
+ * ENCLAVE_UNEXPECTED: Unexpected error.
+ */
+
+uint32_t COMM_API enclave_alloc (
+ COMM_IN void* target_addr,
+ COMM_IN size_t target_size,
+ COMM_IN uint32_t data_properties,
+ COMM_IN uint32_t alloc_flags,
+ COMM_OUT_OPT uint32_t* enclave_error
+);
+
+/* enclave_modify()
+ * Call OS to change permissions, type, or notify EACCEPT done after TRIM.
+ *
+ * Parameters:
+ * target_addr [in] - Start address of the memory to change protections.
+ * target_size [in] - Length of the area. This must be a multiple of the page size.
+ * from_data_properties [in] - The original EPCM flags of the EPC pages to be modified.
+ * Must be bitwise OR of following:
+ * ENCLAVE_PAGE_READ
+ * ENCLAVE_PAGE_WRITE
+ * ENCLAVE_PAGE_EXEC
+ * ENCLAVE_PAGE_REG: regular page, changeable to TRIM or TCS
+ * ENCLAVE_PAGE_TRIM: signal to the kernel EACCEPT is done for TRIM pages.
+ * to_data_properties [in] - The target EPCM flags. This must be bitwise OR of following:
+ * ENCLAVE_PAGE_READ
+ * ENCLAVE_PAGE_WRITE
+ * ENCLAVE_PAGE_EXEC
+ * ENCLAVE_PAGE_TRIM: change the page type to PT_TRIM. Note the address
+ * range for trimmed pages may still be reserved by enclave with
+ * proper permissions.
+ * ENCLAVE_PAGE_TCS: change the page type to PT_TCS
+ *
+ * Return Values:
+ * ENCLAVE_ERROR_SUCCESS(0): The operation was successful.
+ * ENCLAVE_NOT_SUPPORTED: Enclave feature is not supported by the system
+ * ENCLAVE_LOST: May be returned if the enclave has been removed or if it has not been initialized (via EINIT)
+ * ENCLAVE_INVALID_PARAMETER: An invalid combination of flags was provided.
+ * ENCLAVE_OUT_OF_MEMORY: No EPC left (some OSes like Linux), or system is out of memory for internal allocation by OS or this function.
+ * ENCLAVE_DEVICE_NO_MEMORY: NO EPC left (some OSes like Windows)
+ * ENCLAVE_INVALID_ADDRESS: Address does not point to an enclave or valid memory within the enclave
+ * ENCLAVE_NOT_INITIALIZED: May be returned if the enclave has not been initialized (via EINIT).
+ * Some configurations may give ENCLAVE_LOST if the enclave has not been initialized.
+ * ENCLAVE_UNEXPECTED: Unexpected error.
+ */
+
+uint32_t COMM_API enclave_modify (
+ COMM_IN void* target_addr,
+ COMM_IN size_t target_size,
+ COMM_IN uint32_t from_data_properties,
+ COMM_IN uint32_t to_data_properties,
+ COMM_OUT_OPT uint32_t* enclave_error
+);
+
+/**
+ * The enclave features flags describe additional enclave features
+ * which are supported by the platform. A value of 0 indicates not features are supported.
+ */
+typedef enum {
+ ENCLAVE_FEATURE_NONE = 0,
+ ENCLAVE_FEATURE_SGX1 = 0x00000001, /* The platform (HW and OS) supports SGX1 */
+ ENCLAVE_FEATURE_SGX2 = 0x00000002, /* The platform (HW and OS) supports SGX2 */
+}enclave_features_t;
+
#ifdef __cplusplus
}
#endif
diff --git a/psw/enclave_common/sgx_enclave_common.lds b/psw/enclave_common/sgx_enclave_common.lds
index d76001f15..8621fdf50 100644
--- a/psw/enclave_common/sgx_enclave_common.lds
+++ b/psw/enclave_common/sgx_enclave_common.lds
@@ -7,6 +7,8 @@ global:
enclave_get_information;
enclave_set_information;
enclave_create_ex;
+ enclave_alloc;
+ enclave_modify;
local:
*;
};
diff --git a/psw/enclave_common/sgx_mm_ocalls.cpp b/psw/enclave_common/sgx_mm_ocalls.cpp
new file mode 100644
index 000000000..7f29d51e3
--- /dev/null
+++ b/psw/enclave_common/sgx_mm_ocalls.cpp
@@ -0,0 +1,460 @@
+
+////////////////////////////////////////////////////////////
+// OCall impl. These will be part of sgx_enclave_common.cpp
+////////////////////////////////////////////////////////////
+#include
+using namespace std;
+#define PROT_MASK (PROT_READ|PROT_WRITE|PROT_EXEC)
+
+uint32_t COMM_API enclave_alloc(
+ COMM_IN void* target_addr,
+ COMM_IN size_t target_size,
+ COMM_IN uint32_t data_properties,
+ COMM_IN uint32_t alloc_flags,
+ COMM_OUT_OPT uint32_t* enclave_error)
+{
+ int ret = ENCLAVE_UNEXPECTED;
+ SE_TRACE(SE_TRACE_DEBUG,
+ "enclave_alloc for %p ( %llX ) with alloc flags = 0x%lX\n",
+ target_addr, target_size, alloc_flags);
+
+ if (s_driver_type == SGX_DRIVER_DCAP)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ if (s_driver_type == SGX_DRIVER_OUT_OF_TREE)
+ {
+ ret = mprotect(target_addr, target_size, PROT_WRITE | PROT_READ);
+ if ((ret != 0) && (enclave_error != NULL))
+ {
+ *enclave_error = ENCLAVE_UNEXPECTED;
+ }
+ return ret;
+ }
+ int enclave_fd = get_file_handle_from_address(target_addr);
+ if (enclave_fd == -1)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_ADDRESS;
+ return ENCLAVE_INVALID_ADDRESS;
+ }
+ int map_flags = MAP_SHARED | MAP_FIXED;
+ //COMMIT_NOW not supported by kernel yet
+ if (alloc_flags & ENCLAVE_EMA_COMMIT_NOW)
+ {
+ }
+ //CET pages not supported by kernel yet
+ int type = data_properties;
+ if((type == ENCLAVE_PAGE_SS_FIRST) | (type == ENCLAVE_PAGE_SS_REST))
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_NOT_SUPPORTED;
+ return ENCLAVE_NOT_SUPPORTED;
+ }
+ if((type == ENCLAVE_PAGE_SS_FIRST) && target_size > SE_PAGE_SIZE)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ void *out = mmap(target_addr, target_size, PROT_WRITE | PROT_READ, map_flags, enclave_fd, 0);
+ if (out == MAP_FAILED)
+ {
+ ret = errno;
+ SE_TRACE(SE_TRACE_WARNING, "mmap failed, error = %d\n", ret);
+ ret = error_driver2api(-1, ret);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ }
+ else
+ {
+ ret = 0;
+ }
+ return ret;
+}
+
+uint64_t get_offset_for_address(uint64_t target_address)
+{
+ uint64_t enclave_base_addr = (uint64_t)get_enclave_base_address_from_address((void *)target_address);
+ assert(enclave_base_addr != 0);
+ assert(target_address >= enclave_base_addr);
+ return (uint64_t)target_address - (uint64_t)enclave_base_addr;
+}
+
+static int emodt(int fd, void *addr, size_t length, uint64_t type)
+{
+ struct sgx_enclave_modify_types ioc;
+ if (length == 0)
+ return EINVAL;
+
+ SE_TRACE(SE_TRACE_DEBUG,
+ "MODT for %p ( %llX ), type: 0x%llX\n",
+ addr, length, type);
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.page_type = type;
+ ioc.offset = get_offset_for_address((uint64_t)addr);
+ ioc.length = length;
+ do
+ {
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_MODIFY_TYPES, &ioc);
+
+ if (ret && ioc.count == 0 && errno != EBUSY && errno != EAGAIN)
+ { //total failure
+ int err = errno;
+ SE_TRACE(SE_TRACE_WARNING,
+ "MODT failed, error = %d for %p ( %llX ), type: 0x%llX\n",
+ err, addr, length, type);
+ return err;
+ }
+ //for recoverable partial errors
+ length -= ioc.count;
+ ioc.offset += ioc.count;
+ ioc.result = 0;
+ ioc.count = 0;
+ } while (length != 0);
+
+ return 0;
+}
+
+static int trim(int fd, void *addr, size_t length)
+{
+ return emodt(fd, addr, length, (SGX_EMA_PAGE_TYPE_TRIM >> SGX_EMA_PAGE_TYPE_SHIFT));
+}
+static int mktcs(int fd, void *addr, size_t length)
+{
+
+ return emodt(fd, addr, length, (SGX_EMA_PAGE_TYPE_TCS >> SGX_EMA_PAGE_TYPE_SHIFT));
+}
+static int trim_accept(int fd, void *addr, size_t length)
+{
+ struct sgx_enclave_remove_pages ioc;
+ memset(&ioc, 0, sizeof(ioc));
+
+ SE_TRACE(SE_TRACE_DEBUG,
+ "REMOVE for 0x%llX ( %llX )\n",
+ addr, length);
+ ioc.offset = get_offset_for_address((uint64_t)addr);
+ ioc.length = length;
+ int ret = 0;
+ do {
+ ret = ioctl(fd, SGX_IOC_ENCLAVE_REMOVE_PAGES, &ioc);
+ if(ret && ioc.count == 0 && errno != EBUSY && errno != EAGAIN )
+ { //total failure
+ int err = errno;
+ SE_TRACE(SE_TRACE_WARNING,
+ "REMOVE failed, error = %d for 0x%llX ( %llX )\n",
+ err, addr, length);
+ return err;
+ }
+ ioc.length -= ioc.count;
+ ioc.offset += ioc.count;
+ ioc.count = 0;
+ } while (ioc.length != 0);
+
+ return 0;
+}
+static int emodpr(int fd, void *addr, size_t length, uint64_t prot)
+{
+ struct sgx_enclave_restrict_permissions ioc;
+ if (length == 0)
+ return EINVAL;
+
+ SE_TRACE(SE_TRACE_DEBUG,
+ "MODP for 0x%llX ( %llX ), prot: 0x%llX\n",
+ addr, length, prot);
+ memset(&ioc, 0, sizeof(ioc));
+
+ ioc.permissions = prot;
+ ioc.offset = get_offset_for_address((uint64_t)addr);
+ ioc.length = length;
+
+ do
+ {
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc);
+ //TODO: use error code
+ if (ret && ioc.count == 0 && errno != EBUSY && errno!=EAGAIN )
+ { //total failure
+ int err = errno;
+ SE_TRACE(SE_TRACE_WARNING,
+ "MODP failed, error = %d for 0x%llX ( %llX ), prot: 0x%llX\n",
+ err, addr, length, prot);
+ return err;
+ }
+ ioc.length -= ioc.count;
+ ioc.offset += ioc.count;
+ ioc.result = 0;
+ ioc.count = 0;
+ } while (ioc.length != 0);
+
+ return 0;
+}
+
+// legacy support for EDMM
+
+static int trim_accept_legacy(int fd, void *addr, size_t len)
+{
+ sgx_range params;
+ memset(¶ms, 0, sizeof(sgx_range));
+ params.start_addr = (unsigned long)addr;
+ params.nr_pages = (unsigned int)(len / SE_PAGE_SIZE);
+
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_NOTIFY_ACCEPT, ¶ms);
+
+ if (ret)
+ {
+ return errno;
+ }
+
+ return SGX_SUCCESS;
+}
+
+static int trim_legacy(int fd, void *fromaddr, uint64_t len)
+{
+ sgx_range params;
+ memset(¶ms, 0, sizeof(sgx_range));
+ params.start_addr = (unsigned long)fromaddr;
+ params.nr_pages = (unsigned int)((len) / SE_PAGE_SIZE);
+
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_TRIM, ¶ms);
+ if (ret)
+ {
+ return errno;
+ }
+
+ return SGX_SUCCESS;
+}
+
+static int mktcs_legacy(int fd, void *tcs_addr, size_t len)
+{
+ if (len != SE_PAGE_SIZE)
+ return EINVAL;
+ sgx_range params;
+ memset(¶ms, 0, sizeof(sgx_range));
+ params.start_addr = (unsigned long)tcs_addr;
+ params.nr_pages = 1;
+
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_MKTCS, ¶ms);
+ if (ret)
+ {
+ return errno;
+ }
+ return SGX_SUCCESS;
+}
+
+static int emodpr_legacy(int fd, void *addr, uint64_t size, uint64_t flag)
+{
+ sgx_modification_param params;
+ memset(¶ms, 0, sizeof(sgx_modification_param));
+ params.range.start_addr = (unsigned long)addr;
+ params.range.nr_pages = (unsigned int)(size / SE_PAGE_SIZE);
+ params.flags = (unsigned long)flag;
+
+ int ret = ioctl(fd, SGX_IOC_ENCLAVE_EMODPR, ¶ms);
+ if (ret)
+ {
+ return errno;
+ }
+
+ return SGX_SUCCESS;
+}
+
+uint32_t COMM_API enclave_modify(
+ COMM_IN void* target_addr,
+ COMM_IN size_t target_size,
+ COMM_IN uint32_t from_data_properties,
+ COMM_IN uint32_t to_data_properties,
+ COMM_OUT_OPT uint32_t* enclave_error)
+{
+ int ret = ENCLAVE_UNEXPECTED;
+ SE_TRACE(SE_TRACE_DEBUG,
+ "enclave_modify for %p ( %llX ) from 0x%lX to %lX\n",
+ target_addr, target_size, from_data_properties, to_data_properties);
+ if (s_driver_type == SGX_DRIVER_DCAP)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_NOT_SUPPORTED;
+ return ENCLAVE_NOT_SUPPORTED;
+ }
+ uint64_t enclave_base = (uint64_t)get_enclave_base_address_from_address(target_addr);
+ if (enclave_base == 0)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_ADDRESS;
+ return ENCLAVE_INVALID_ADDRESS;
+ }
+ if (target_size % SE_PAGE_SIZE != 0)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ function _trim = trim;
+ function _trim_accept = trim_accept;
+ function _mktcs = mktcs;
+ function _emodpr = emodpr;
+ int fd = get_file_handle_from_address(target_addr);
+ if (s_driver_type == SGX_DRIVER_OUT_OF_TREE)
+ {
+ _trim = trim_legacy;
+ _trim_accept = trim_accept_legacy;
+ _mktcs = mktcs_legacy;
+ _emodpr = emodpr_legacy;
+ fd = s_hdevice;
+ }
+ if(fd == -1)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_ADDRESS;
+ return ENCLAVE_INVALID_ADDRESS;
+ }
+
+ int type_to = (to_data_properties & SGX_EMA_PAGE_TYPE_MASK);
+ int type_from = (from_data_properties & SGX_EMA_PAGE_TYPE_MASK);
+ if (type_from == SGX_EMA_PAGE_TYPE_TRIM && type_to != SGX_EMA_PAGE_TYPE_TRIM)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ int prot_to = (to_data_properties & PROT_MASK);
+ int prot_from = (from_data_properties & PROT_MASK);
+ if ((prot_to != prot_from) && (type_to != type_from))
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+
+ if ((type_from & type_to & SGX_EMA_PAGE_TYPE_TRIM))
+ {
+ //user space can only do EACCEPT for PT_TRIM type
+ ret = _trim_accept(fd, target_addr, target_size);
+ if (ret)
+ {
+ ret = error_driver2api(-1, ret);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ if (prot_to == PROT_NONE)
+ {
+ //EACCEPT done and notified.
+ //if user wants to remove permissions,
+ //only mprotect is needed
+ ret = mprotect(target_addr, target_size, prot_to);
+ if (ret == -1)
+ {
+ ret = error_driver2api(ret, errno);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ }
+ return ret;
+ }
+
+ if (type_to == SGX_EMA_PAGE_TYPE_TRIM)
+ {
+ assert(type_from != SGX_EMA_PAGE_TYPE_TRIM);
+ if (prot_to != prot_from)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ ret = _trim(fd, target_addr, target_size);
+ if (ret)
+ {
+ ret = error_driver2api(-1, ret);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ return 0;
+ }
+
+ if (type_to == SGX_EMA_PAGE_TYPE_TCS)
+ {
+ if (type_from != SGX_EMA_PAGE_TYPE_REG)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ if ((prot_from != (SGX_EMA_PROT_READ_WRITE)) && prot_to != prot_from)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ ret = _mktcs(fd, target_addr, target_size);
+ if (ret)
+ {
+ ret = error_driver2api(-1, ret);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ return 0;
+ }
+
+ if (type_to != type_from)
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ // type_to == type_from
+ // this is for emodpr to epcm.NONE, enclave EACCEPT with pte.R
+ // separate mprotect is needed to change pte.R to pte.NONE
+ if (prot_to == prot_from && prot_to == PROT_NONE)
+ {
+ ret = mprotect(target_addr, target_size, prot_to);
+ if (ret == -1)
+ {
+ ret = error_driver2api(ret, errno);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ }
+
+ if (prot_to == prot_from)
+ {
+ return 0; //nothing to be done.
+ }
+ // Permissions changes. Only do emodpr for PT_REG pages
+ if ((type_from & type_to & SGX_EMA_PAGE_TYPE_MASK) == SGX_EMA_PAGE_TYPE_REG)
+ {
+ ret = _emodpr(fd, target_addr, target_size, prot_to);
+ if (ret)
+ {
+ ret = error_driver2api(-1, ret);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ }
+ else
+ {
+ if (enclave_error != NULL)
+ *enclave_error = ENCLAVE_INVALID_PARAMETER;
+ return ENCLAVE_INVALID_PARAMETER;
+ }
+ //EACCEPT needs at least pte.R, PROT_NONE case done above.
+ if (prot_to != PROT_NONE)
+ {
+ ret = mprotect((void *)target_addr, target_size, prot_to);
+ if (ret == -1)
+ {
+ ret = error_driver2api(ret, errno);
+ if (enclave_error != NULL)
+ *enclave_error = ret;
+ return ret;
+ }
+ }
+ return ret;
+}
diff --git a/psw/uae_service/linux/Makefile b/psw/uae_service/linux/Makefile
index c797b00a9..523c2b03f 100644
--- a/psw/uae_service/linux/Makefile
+++ b/psw/uae_service/linux/Makefile
@@ -52,8 +52,7 @@ INCLUDE += -I$(COMMON_DIR) \
INCLUDE += -I$(LINUX_PSW_DIR)/ae/common \
-I$(LINUX_PSW_DIR)/ae/inc \
- -I$(LINUX_PSW_DIR)/ae/inc/internal \
- -I$(SGX_HEADER_DIR)
+ -I$(LINUX_PSW_DIR)/ae/inc/internal
INCLUDE += -I$(LINUX_EXTERNAL_DIR)/epid-sdk \
-I$(IPC_COMMON_INC_DIR) \
diff --git a/psw/urts/create_param.h b/psw/urts/create_param.h
index 6300d7dad..235427e66 100644
--- a/psw/urts/create_param.h
+++ b/psw/urts/create_param.h
@@ -51,6 +51,8 @@ typedef struct _create_param_t
uint64_t rsrv_init_size;
uint64_t rsrv_offset;
uint64_t rsrv_executable;
+ uint64_t user_region_offset;
+ uint64_t user_region_size;
uint64_t first_ssa_gpr;
uint64_t td_addr;
uint64_t tls_addr;
diff --git a/psw/urts/enclave.cpp b/psw/urts/enclave.cpp
index b7fdc2afb..8ef2e53d5 100644
--- a/psw/urts/enclave.cpp
+++ b/psw/urts/enclave.cpp
@@ -40,6 +40,7 @@
#include "se_memory.h"
#include "urts_trim.h"
#include "urts_emodpr.h"
+#include "urts_emm.h"
#include "rts_cmd.h"
#include
#include "rts.h"
@@ -352,7 +353,7 @@ sgx_status_t CEnclave::ecall(const int proc, const void *ocall_table, void *ms,
se_event_wake(m_new_thread_event);
pthread_join(m_pthread_tid, NULL);
}
- ocall_table = m_ocall_table;
+ /*ocall_table = m_ocall_table;
std::vector threads = m_thread_pool->get_thread_list();
for (unsigned idx = 0; idx < threads.size(); ++idx)
@@ -370,6 +371,7 @@ sgx_status_t CEnclave::ecall(const int proc, const void *ocall_table, void *ms,
// Change TCS permission to Read only to let driver not handle the
// #PF caused by TCS trim. It gives urts a chance to catch the exception
// and exit the ecall with an error code.
+ //!TODO do we really need this?
if(0 != mprotect((void *)start, TCS_SIZE, SI_FLAG_R))
{
se_rdunlock(&m_rwlock);
@@ -381,7 +383,7 @@ sgx_status_t CEnclave::ecall(const int proc, const void *ocall_table, void *ms,
return (sgx_status_t)ret;
}
}
- }
+ }*/
}
ret = do_ecall(proc, m_ocall_table, ms, trust_thread);
@@ -420,6 +422,10 @@ int CEnclave::ocall(const unsigned int proc, const sgx_ocall_table_t *ocall_tabl
error = ocall_emodpr(ms);
else if ((int)proc == EDMM_MPROTECT)
error = ocall_mprotect(ms);
+ else if ((int)proc == EDMM_ALLOC)
+ error = ocall_emm_alloc(ms);
+ else if ((int)proc == EDMM_MODIFY)
+ error = ocall_emm_modify(ms);
}
else
{
diff --git a/psw/urts/enclave_creator_hw.h b/psw/urts/enclave_creator_hw.h
index 15d02e200..6cfe8b4a7 100644
--- a/psw/urts/enclave_creator_hw.h
+++ b/psw/urts/enclave_creator_hw.h
@@ -61,10 +61,10 @@ class EnclaveCreatorHW : public EnclaveCreator
int get_misc_attr(sgx_misc_attribute_t *sgx_misc_attr, metadata_t *metadata, SGXLaunchToken * const lc, uint32_t flag);
bool get_plat_cap(sgx_misc_attribute_t *se_attr);
int emodpr(uint64_t addr, uint64_t size, uint64_t flag);
+ int alloc(uint64_t addr, uint64_t size, int flag);
int mktcs(uint64_t tcs_addr);
int trim_range(uint64_t fromaddr, uint64_t toaddr);
int trim_accept(uint64_t addr);
- int remove_range(uint64_t fromaddr, uint64_t numpages);
private:
virtual bool open_device();
virtual void close_device();
diff --git a/psw/urts/enclave_creator_hw_com.cpp b/psw/urts/enclave_creator_hw_com.cpp
index 534f7233b..9bfe23d0c 100644
--- a/psw/urts/enclave_creator_hw_com.cpp
+++ b/psw/urts/enclave_creator_hw_com.cpp
@@ -65,7 +65,7 @@ int EnclaveCreatorHW::initialize(sgx_enclave_id_t enclave_id)
init_cpuinfo((uint32_t *)info.cpuinfo_table);
info.system_feature_set[0] |= (1ULL << SYS_FEATURE_EXTEND);
info.size = sizeof(system_features_t);
- info.version = (sdk_version_t)MIN((uint32_t)SDK_VERSION_2_3, enclave->get_enclave_version());
+ info.version = (sdk_version_t)MIN((uint32_t)SDK_VERSION_3_0, enclave->get_enclave_version());
info.sealed_key = enclave->get_sealed_key();
info.cpu_core_num = (uint32_t)sysconf(_SC_NPROCESSORS_ONLN);
if (is_EDMM_supported(enclave_id))
diff --git a/psw/urts/enclave_mutex.cpp b/psw/urts/enclave_mutex.cpp
index 49abe95b9..6588d61a6 100644
--- a/psw/urts/enclave_mutex.cpp
+++ b/psw/urts/enclave_mutex.cpp
@@ -52,6 +52,21 @@ extern "C" int sgx_thread_wait_untrusted_event_ocall(const void *self)
return SGX_SUCCESS;
}
+extern "C" int sgx_thread_wait_untrusted_event_timeout_ocall(const void *self, int clockbit, const struct timespec *ts, int absolute_time, int *err)
+{
+ if (self == NULL)
+ return SGX_ERROR_INVALID_PARAMETER;
+
+ se_handle_t hevent = CEnclavePool::instance()->get_event(self);
+ if (hevent == NULL)
+ return SE_ERROR_MUTEX_GET_EVENT;
+
+ if (SE_MUTEX_SUCCESS != se_event_timeout_wait(hevent, clockbit, ts, absolute_time, err))
+ return SE_ERROR_MUTEX_WAIT_EVENT;
+
+ return SGX_SUCCESS;
+}
+
/* set untrusted event */
extern "C" int sgx_thread_set_untrusted_event_ocall(const void *waiter)
{
diff --git a/psw/urts/linux/Makefile b/psw/urts/linux/Makefile
index 529d7c2bc..689fd4585 100644
--- a/psw/urts/linux/Makefile
+++ b/psw/urts/linux/Makefile
@@ -44,13 +44,14 @@ CFLAGS += $(ADDED_INC)
VTUNE_DIR = $(LINUX_EXTERNAL_DIR)/vtune/linux
-INC += -I$(SGX_HEADER_DIR) \
+INC += -I$(COMMON_DIR)/inc \
-I$(COMMON_DIR)/inc/internal \
-I$(COMMON_DIR)/inc/internal/linux \
-I$(LINUX_PSW_DIR)/enclave_common \
-I$(LINUX_PSW_DIR)/urts/ \
-I$(LINUX_PSW_DIR)/urts/linux \
-I$(LINUX_PSW_DIR)/urts/parser \
+ -I$(LINUX_EXTERNAL_DIR)/sgx-emm/emm_src/include \
-I$(VTUNE_DIR)/include \
-I$(VTUNE_DIR)/sdk/src/ittnotify
@@ -96,6 +97,7 @@ OBJ2 := urts.o \
get_thread_id.o \
prd_css_util.o \
urts_emodpr.o \
+ urts_emm.o \
urts_trim.o \
edmm_utility.o
@@ -120,11 +122,13 @@ LIBSGX_ENCLAVE_COMMON := libsgx_enclave_common.a
LIBURTS := libsgx_urts.so
LIBURTS_INTERNAL := liburts_internal.so
LIBURTS_DEBUG := libsgx_urts.so.debug
+LIBURTS_STATIC := libsgx_urts.a
.PHONY: all
-all: $(LIBURTS) $(LIBURTS_INTERNAL) $(LIBURTS_DEBUG) | $(BUILD_DIR)
+all: $(LIBURTS) $(LIBURTS_STATIC) $(LIBURTS_INTERNAL) $(LIBURTS_DEBUG) | $(BUILD_DIR)
@$(CP) $(LIBURTS) $|
+ @$(CP) $(LIBURTS_STATIC) $|
@$(CP) $(LIBURTS_INTERNAL) $|
ifndef DEBUG
@$(CP) $(LIBURTS_DEBUG) $|
@@ -142,6 +146,15 @@ $(LIBURTS_INTERNAL): $(INTERNAL_OBJ) $(LIBWRAPPER) $(LIBSGX_ENCLAVE_COMMON) ittn
$(LIBURTS): $(URTS_OBJ) $(LIBWRAPPER) $(LIBSGX_ENCLAVE_COMMON) ittnotify
$(CXX) $(CXXFLAGS) -shared -Wl,-soname=$@ $(LIB) -o $@ $(URTS_OBJ) $(LDFLAGS)
+$(LIBURTS_STATIC): $(LIBURTS)
+ @$(MKDIR) $(BUILD_DIR)/.sgx_static_urts
+ @$(RM) -f $(BUILD_DIR)/.sgx_static_urts/*
+ cd $(BUILD_DIR)/.sgx_static_urts && \
+ $(AR) x $(COMMON_DIR)/se_wrapper/libwrapper.a && \
+ $(AR) x $(VTUNE_DIR)/sdk/src/ittnotify/libittnotify.a && \
+ $(RM) -f se_event.o
+ $(AR) rsD $@ $(URTS_OBJ) $(BUILD_DIR)/.sgx_static_urts/*.o
+
$(LIBURTS_DEBUG): $(LIBURTS)
ifndef DEBUG
$(CP) $(LIBURTS) $(LIBURTS).orig
@@ -171,7 +184,7 @@ $(BUILD_DIR):
.PHONY: clean
clean::
- @$(RM) *.o $(LIBURTS) $(LIBURTS_INTERNAL) $(LIBURTS_DEBUG)
+ @$(RM) *.o $(LIBURTS) $(LIBURTS_INTERNAL) $(LIBURTS_DEBUG) $(LIBURTS_STATIC)
@$(RM) $(BUILD_DIR)/$(LIBURTS) $(BUILD_DIR)/$(LIBURTS_INTERNAL)
@$(RM) $(LIBURTS).orig $(BUILD_DIR)/$(LIBURTS_DEBUG)
$(MAKE) -C $(COMMON_DIR)/se_wrapper_psw/ clean
diff --git a/psw/urts/linux/edmm_utility.cpp b/psw/urts/linux/edmm_utility.cpp
index 69e701a6b..a7e9f73ce 100644
--- a/psw/urts/linux/edmm_utility.cpp
+++ b/psw/urts/linux/edmm_utility.cpp
@@ -41,7 +41,7 @@
#include
#include
#include
-
+#include
#define SGX_URTS_CMD "for f in $(find /usr/$(basename $(gcc -print-multi-os-directory)) -name 'libsgx_urts.so' 2> /dev/null); do strings $f|grep 'SGX_URTS_VERSION_2'; done"
#define SGX_CPUID 0x12
@@ -236,8 +236,17 @@ extern "C" bool is_cpu_support_edmm()
*/
extern "C" bool is_driver_support_edmm(int hdevice)
{
- if (-1 == hdevice)
- return false;
+ if (-1 == hdevice){
+ if(!open_se_device(SGX_DRIVER_IN_KERNEL, &hdevice))
+ return false;
+ struct sgx_enclave_restrict_permissions ioc;
+ memset(&ioc, 0, sizeof(ioc));
+
+ int ret = ioctl(hdevice, SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS, &ioc);
+ bool supported = ret != -1 || (errno != ENOTTY);
+ close_se_device(&hdevice);
+ return supported;
+ }
sgx_modification_param param;
param.flags = 0;
diff --git a/psw/urts/linux/enclave_creator_hw.cpp b/psw/urts/linux/enclave_creator_hw.cpp
index d956e8181..425a7d890 100644
--- a/psw/urts/linux/enclave_creator_hw.cpp
+++ b/psw/urts/linux/enclave_creator_hw.cpp
@@ -49,7 +49,7 @@
#include
#include
#include
-
+#include "sgx_mm.h"
#define POINTER_TO_U64(A) ((__u64)((uintptr_t)(A)))
static EnclaveCreatorHW g_enclave_creator_hw;
@@ -306,103 +306,76 @@ void EnclaveCreatorHW::close_device()
m_hdevice = -1;
}
-int EnclaveCreatorHW::emodpr(uint64_t addr, uint64_t size, uint64_t flag)
+int EnclaveCreatorHW::alloc(uint64_t addr, uint64_t size, int flag)
{
- sgx_modification_param params;
- memset(¶ms, 0 ,sizeof(sgx_modification_param));
- params.range.start_addr = (unsigned long)addr;
- params.range.nr_pages = (unsigned int)(size/SE_PAGE_SIZE);
- params.flags = (unsigned long)flag;
-
- int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_EMODPR, ¶ms);
+ int ret = enclave_alloc((void *)addr, size, flag, SGX_EMA_COMMIT_ON_DEMAND, NULL);
if (ret)
{
- SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_EMODPR failed %d\n", errno);
- return error_driver2urts(ret, errno);
+ SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_alloc failed %d\n", ret);
+ return error_api2urts(ret);
}
return SGX_SUCCESS;
}
-
-int EnclaveCreatorHW::mktcs(uint64_t tcs_addr)
+
+int EnclaveCreatorHW::emodpr(uint64_t addr, uint64_t size, uint64_t flag)
{
- sgx_range params;
- memset(¶ms, 0 ,sizeof(sgx_range));
- params.start_addr = (unsigned long)tcs_addr;
- params.nr_pages = 1;
- int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_MKTCS, ¶ms);
+ int ret = enclave_modify((void *)addr, size, PROT_READ|PROT_WRITE|PROT_EXEC|SGX_EMA_PAGE_TYPE_REG,
+ (int) (flag|SGX_EMA_PAGE_TYPE_REG), NULL);
if (ret)
{
- SE_TRACE(SE_TRACE_ERROR, "MODIFY_TYPE failed %d\n", errno);
- return error_driver2urts(ret, errno);
+ SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_EMODPR failed %d\n", ret);
+ return error_api2urts(ret);
}
return SGX_SUCCESS;
}
-int EnclaveCreatorHW::trim_range(uint64_t fromaddr, uint64_t toaddr)
+int EnclaveCreatorHW::mktcs(uint64_t tcs_addr)
{
- sgx_range params;
- memset(¶ms, 0 ,sizeof(sgx_range));
- params.start_addr = (unsigned long)fromaddr;
- params.nr_pages = (unsigned int)((toaddr - fromaddr)/SE_PAGE_SIZE);
-
- int ret= ioctl(m_hdevice, SGX_IOC_ENCLAVE_TRIM, ¶ms);
+ int ret = enclave_modify((void *)tcs_addr, SE_PAGE_SIZE, PROT_READ|PROT_WRITE|SGX_EMA_PAGE_TYPE_REG, PROT_READ|PROT_WRITE|SGX_EMA_PAGE_TYPE_TCS, NULL);
if (ret)
{
- SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_TRIM failed %d\n", errno);
- return error_driver2urts(ret, errno);
+ SE_TRACE(SE_TRACE_ERROR, "MODIFY_TYPE failed %d\n", ret);
+ return error_api2urts(ret);
}
return SGX_SUCCESS;
-
}
-int EnclaveCreatorHW::trim_accept(uint64_t addr)
+int EnclaveCreatorHW::trim_range(uint64_t fromaddr, uint64_t toaddr)
{
- sgx_range params;
- memset(¶ms, 0 ,sizeof(sgx_range));
- params.start_addr = (unsigned long)addr;
- params.nr_pages = 1;
-
- int ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_NOTIFY_ACCEPT, ¶ms);
-
+ int ret= enclave_modify( (void *)fromaddr, toaddr - fromaddr, PROT_READ|PROT_WRITE, PROT_READ|PROT_WRITE|SGX_EMA_PAGE_TYPE_TRIM, NULL);
if (ret)
{
- SE_TRACE(SE_TRACE_ERROR, "TRIM_RANGE_COMMIT failed %d\n", errno);
- return error_driver2urts(ret, errno);
+ SE_TRACE(SE_TRACE_ERROR, "SGX_IOC_ENCLAVE_TRIM failed %d\n", ret);
+ return error_api2urts(ret);
}
return SGX_SUCCESS;
+
}
-int EnclaveCreatorHW::remove_range(uint64_t fromaddr, uint64_t numpages)
+int EnclaveCreatorHW::trim_accept(uint64_t addr)
{
- int ret = -1;
- uint64_t i;
- unsigned long start;
+ int ret = enclave_modify((void *)addr, SE_PAGE_SIZE, SGX_EMA_PAGE_TYPE_TRIM|PROT_READ|PROT_WRITE
+ , SGX_EMA_PAGE_TYPE_TRIM|PROT_READ|PROT_WRITE, NULL);
- for (i = 0; i < numpages; i++)
+ if (ret)
{
- start = (unsigned long)fromaddr + (unsigned long)(i << SE_PAGE_SHIFT);
- ret = ioctl(m_hdevice, SGX_IOC_ENCLAVE_PAGE_REMOVE, &start);
- if (ret)
- {
- SE_TRACE(SE_TRACE_ERROR, "PAGE_REMOVE failed %d\n", errno);
- return error_driver2urts(ret, errno);
- }
+ SE_TRACE(SE_TRACE_ERROR, "TRIM_RANGE_COMMIT failed %d\n", ret);
+ return error_api2urts(ret);
}
return SGX_SUCCESS;
}
-
//EDMM is supported if and only if all of the following requirements are met:
//1. We operate in HW mode
//2. CPU has EDMM support
//3. Driver has EDMM support
-//4. Both the uRTS version and enclave (metadata) version are higher than 1.5
+//4. SDK version >= 3.0
bool EnclaveCreatorHW::is_EDMM_supported(sgx_enclave_id_t enclave_id)
{
bool supported = false, driver_supported = false, cpu_edmm = false;
@@ -415,7 +388,7 @@ bool EnclaveCreatorHW::is_EDMM_supported(sgx_enclave_id_t enclave_id)
driver_supported = is_driver_compatible();
//return value of get_enclave_version() considers the version of uRTS and enclave metadata
- supported = use_se_hw() && cpu_edmm && driver_supported && (enclave->get_enclave_version() >= SDK_VERSION_2_0);
+ supported = use_se_hw() && cpu_edmm && driver_supported && (enclave->get_enclave_version() >= SDK_VERSION_3_0);
return supported;
}
diff --git a/psw/urts/linux/isgx_user.h b/psw/urts/linux/isgx_user.h
index 3c4dfdd00..177b50276 100644
--- a/psw/urts/linux/isgx_user.h
+++ b/psw/urts/linux/isgx_user.h
@@ -4,7 +4,7 @@
*
* GPL LICENSE SUMMARY
*
- * Copyright(c) 2016 Intel Corporation.
+ * Copyright(c) 2016-2022 Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of version 2 of the GNU General Public License as
@@ -21,7 +21,7 @@
*
* BSD LICENSE
*
- * Copyright(c) 2016 Intel Corporation.
+ * Copyright(c) 2016-2022 Intel Corporation.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -55,6 +55,7 @@
* Suresh Siddha
* Serge Ayoun
* Shay Katz-zamir
+ * Haitao Huang
*/
#ifndef _UAPI_ASM_X86_SGX_H
@@ -108,16 +109,28 @@ enum sgx_page_flags {
_IOW(SGX_MAGIC, 0x02, struct sgx_enclave_init)
#define SGX_IOC_ENCLAVE_SET_ATTRIBUTE \
_IOW(SGX_MAGIC, 0x03, struct sgx_enclave_set_attribute)
+#define SGX_IOC_VEPC_REMOVE_ALL \
+ _IO(SGX_MAGIC, 0x04)
+#define SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS \
+ _IOWR(SGX_MAGIC, 0x05, struct sgx_enclave_restrict_permissions)
+#define SGX_IOC_ENCLAVE_MODIFY_TYPES \
+ _IOWR(SGX_MAGIC, 0x06, struct sgx_enclave_modify_types)
+#define SGX_IOC_ENCLAVE_REMOVE_PAGES \
+ _IOWR(SGX_MAGIC, 0x07, struct sgx_enclave_remove_pages)
+
+
+/* Legacy OOT driver support for EDMM */
#define SGX_IOC_ENCLAVE_EMODPR \
_IOW(SGX_MAGIC, 0x09, struct sgx_modification_param)
#define SGX_IOC_ENCLAVE_MKTCS \
_IOW(SGX_MAGIC, 0x0a, struct sgx_range)
#define SGX_IOC_ENCLAVE_TRIM \
_IOW(SGX_MAGIC, 0x0b, struct sgx_range)
+
+//Legacy implementation to ensure EPC pages removed no later by this ioctl
+
#define SGX_IOC_ENCLAVE_NOTIFY_ACCEPT \
_IOW(SGX_MAGIC, 0x0c, struct sgx_range)
-#define SGX_IOC_ENCLAVE_PAGE_REMOVE \
- _IOW(SGX_MAGIC, 0x0d, unsigned long)
//Note: SGX_IOC_ENCLAVE_CREATE is the same for in-kernel except that it returns a file handle for in-kernel
#define SGX_IOC_ENCLAVE_ADD_PAGES_IN_KERNEL \
@@ -267,7 +280,7 @@ struct sgx_enclave_destroy {
/*
- * SGX2.0 definitions
+ * SGX2.0 definitions for Legacy OOT driver
*/
#define SGX_GROW_UP_FLAG 1
@@ -284,6 +297,61 @@ struct sgx_modification_param {
};
+/**
+ * struct sgx_enclave_restrict_permissions - parameters for ioctl
+ * %SGX_IOC_ENCLAVE_RESTRICT_PERMISSIONS
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @permissions:new permission bits for pages in range described by @offset
+ * and @length
+ * @result: (output) SGX result code of ENCLS[EMODPR] function
+ * @count: (output) bytes successfully changed (multiple of page size)
+ */
+struct sgx_enclave_restrict_permissions {
+ __u64 offset;
+ __u64 length;
+ __u64 permissions;
+ __u64 result;
+ __u64 count;
+};
+
+/**
+ * struct sgx_enclave_modify_type - parameters for %SGX_IOC_ENCLAVE_MODIFY_TYPES
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @page_type: new type for pages in range described by @offset and @length
+ * @result: (output) SGX result code of ENCLS[EMODT] function
+ * @count: (output) bytes successfully changed (multiple of page size)
+ */
+struct sgx_enclave_modify_types {
+ __u64 offset;
+ __u64 length;
+ __u64 page_type;
+ __u64 result;
+ __u64 count;
+};
+
+/**
+ * struct sgx_enclave_remove_pages - %SGX_IOC_ENCLAVE_REMOVE_PAGES parameters
+ * @offset: starting page offset (page aligned relative to enclave base
+ * address defined in SECS)
+ * @length: length of memory (multiple of the page size)
+ * @count: (output) bytes successfully changed (multiple of page size)
+ *
+ * Regular (PT_REG) or TCS (PT_TCS) can be removed from an initialized
+ * enclave if the system supports SGX2. First, the %SGX_IOC_ENCLAVE_MODIFY_TYPE
+ * ioctl() should be used to change the page type to PT_TRIM. After that
+ * succeeds ENCLU[EACCEPT] should be run from within the enclave and then
+ * %SGX_IOC_ENCLAVE_REMOVE_PAGES can be used to complete the page removal.
+ */
+struct sgx_enclave_remove_pages {
+ __u64 offset;
+ __u64 length;
+ __u64 count;
+};
+
struct sgx_enclave_run;
@@ -363,7 +431,7 @@ struct sgx_enclave_run {
* Most exceptions reported on ENCLU, including those that occur within the
* enclave, are fixed up and reported synchronously instead of being delivered
* via a standard signal. Debug Exceptions (#DB) and Breakpoints (#BP) are
- * never fixed up and are always delivered via standard signals. On synchrously
+ * never fixed up and are always delivered via standard signals. On synchronously
* reported exceptions, -EFAULT is returned and details about the exception are
* recorded in @run.exception, the optional sgx_enclave_exception struct.
*
diff --git a/psw/urts/linux/sig_handler.cpp b/psw/urts/linux/sig_handler.cpp
index b84d0a227..e99ea2d4b 100644
--- a/psw/urts/linux/sig_handler.cpp
+++ b/psw/urts/linux/sig_handler.cpp
@@ -86,6 +86,12 @@ typedef struct _ecall_param_t
#define ECALL_PARAM (reinterpret_cast(context->uc_mcontext.gregs[REG_EBP] + 2 * 4))
#endif
+// Real-time signal 64 is used to trigger an interrupt to an enclave thread
+#define SIGRT_INTERRUPT (64)
+
+/* Known from the kernel driver. Relative to %rbp. */
+#define SGX_ENCLAVE_OFFSET_OF_RUN 16
+
extern "C" void *get_aep();
extern "C" void *get_eenterp();
extern "C" void *get_eretp();
@@ -95,15 +101,18 @@ extern "C" int vdso_sgx_enter_enclave_wrapper(unsigned long rdi, unsigned long r
unsigned long rdx, unsigned int function,
unsigned long r8, unsigned long r9,
struct sgx_enclave_run *run);
-
+static size_t g_sgx_enter_enclave_symbol_start = 0;
+static size_t g_sgx_enter_enclave_symbol_end = 0;
void reg_sig_handler();
int do_ecall(const int fn, const void *ocall_table, const void *ms, CTrustThread *trust_thread);
+// TODO: For simulation mode, the signal should be handled in the old way.
void sig_handler(int signum, siginfo_t* siginfo, void *priv)
{
+ UNUSED(siginfo);
SE_TRACE(SE_TRACE_DEBUG, "signal handler is triggered\n");
ucontext_t* context = reinterpret_cast(priv);
unsigned int *xip = reinterpret_cast(context->uc_mcontext.gregs[REG_XIP]);
@@ -112,14 +121,14 @@ void sig_handler(int signum, siginfo_t* siginfo, void *priv)
/* `xbx' is only used in assertions. */
size_t xbx = context->uc_mcontext.gregs[REG_XBX];
#endif
- ecall_param_t *param = ECALL_PARAM;
//the case of exception on ERESUME or within enclave.
//We can't distinguish ERESUME exception from exception within enclave. We assume it is the exception within enclave.
//If it is ERESUME exception, it will raise another exception in ecall and ecall will return error.
- if(xip == get_aep()
- && SE_ERESUME == xax)
- {
+ //Here we can't get an accurate address for AEP. We just use the symbol's range of __vdso_sgx_enter_enclave.
+ if(g_sgx_enter_enclave_symbol_start <= (size_t)xip
+ && (size_t)xip <= g_sgx_enter_enclave_symbol_end
+ && SE_ERESUME == xax) {
#ifndef SE_SIM
assert(ENCLU == (*xip & 0xffffff));
#endif
@@ -127,84 +136,54 @@ void sig_handler(int signum, siginfo_t* siginfo, void *priv)
SE_TRACE(SE_TRACE_NOTICE, "exception on ERESUME\n");
//The ecall looks recursively, but it will not cause infinite call.
//If exception is raised in trts again and again, the SSA will overflow, and finally it is EENTER exception.
- assert(reinterpret_cast(xbx) == param->tcs);
- CEnclave *enclave = param->trust_thread->get_enclave();
- unsigned int ret = enclave->ecall(ECMD_EXCEPT, param->ocall_table, NULL);
- if(SGX_SUCCESS == ret)
+ int ecmd;
+ if (signum != SIGRT_INTERRUPT) {
+ ecmd = ECMD_EXCEPT;
+ } else {
+ ecmd = ECMD_INTERRUPT;
+ }
+ // This handler is only used to handle interrupt signal.
+ assert(ecmd == ECMD_INTERRUPT);
+
+ size_t rbp = context->uc_mcontext.gregs[REG_RBP];
+ size_t* run_context_addr = reinterpret_cast(rbp + SGX_ENCLAVE_OFFSET_OF_RUN);
+ struct sgx_enclave_run* run = reinterpret_cast (*run_context_addr);
+ SE_TRACE(SE_TRACE_DEBUG, "in sig_handler, run_addr = 0x%lx\n", run);
+
+#ifndef NDEBUG
+ tcs_t *tcs = reinterpret_cast(xbx);
+ assert(reinterpret_cast(run->tcs) == tcs);
+#endif
+
+ __u64 *user_data = (__u64*)run->user_data;
+ CTrustThread* trust_thread = reinterpret_cast(user_data[1]);
+ if (trust_thread == NULL)
{
- //ERESUME execute
+ run->user_data = SGX_ERROR_UNEXPECTED;
return;
}
- //If the exception is caused by enclave lost or internal stack overrun, then return the error code to ecall caller elegantly.
- else if(SGX_ERROR_ENCLAVE_LOST == ret || SGX_ERROR_STACK_OVERRUN == ret)
+
+ void *ocall_table = reinterpret_cast(user_data[0]);
+ unsigned int ret = do_ecall(ecmd, ocall_table, NULL, trust_thread);
+ if(SGX_SUCCESS == ret)
{
- //enter_enlcave function will return with ret which is from tRTS;
- context->uc_mcontext.gregs[REG_XIP] = reinterpret_cast(get_eretp());
- context->uc_mcontext.gregs[REG_XSI] = ret;
+ //ERESUME execute
+ SE_TRACE(SE_TRACE_DEBUG, "SIGRT_INTERRUPT handle successful\n");
return;
}
- //If we can't fix the exception within enclave, then give the handle to other signal hanlder.
- //Call the previous signal handler. The default signal handler should terminate the application.
-
- enclave->rdunlock();
- CEnclavePool::instance()->unref_enclave(enclave);
}
- //the case of exception on EENTER instruction.
- else if(xip == get_eenterp()
- && SE_EENTER == xax)
+ else if (signum == SIGRT_INTERRUPT)
{
- assert(reinterpret_cast(xbx) == param->tcs);
- assert(ENCLU == (*xip & 0xffffff));
- SE_TRACE(SE_TRACE_NOTICE, "exception on EENTER\n");
- //enter_enlcave function will return with SE_ERROR_ENCLAVE_LOST
- context->uc_mcontext.gregs[REG_XIP] = reinterpret_cast(get_eretp());
- context->uc_mcontext.gregs[REG_XSI] = SGX_ERROR_ENCLAVE_LOST;
+ // If not interrupting the enclave, just ignore the signal
return;
- }
-
- SE_TRACE(SE_TRACE_DEBUG, "NOT enclave signal\n");
- //it is not SE exception. if the old signal handler is default signal handler, we reset signal handler.
- //raise the signal again, and the default signal handler will be called.
- if(SIG_DFL == g_old_sigact[signum].sa_handler)
- {
- signal(signum, SIG_DFL);
- raise(signum);
- }
- //if there is old signal handler, we need transfer the signal to the old signal handler;
- else
- {
- if(!(g_old_sigact[signum].sa_flags & SA_NODEFER))
- sigaddset(&g_old_sigact[signum].sa_mask, signum);
-
- sigset_t cur_set;
- pthread_sigmask(SIG_SETMASK, &g_old_sigact[signum].sa_mask, &cur_set);
-
- if(g_old_sigact[signum].sa_flags & SA_SIGINFO)
- {
- g_old_sigact[signum].sa_sigaction(signum, siginfo, priv);
- }
- else
- {
- g_old_sigact[signum].sa_handler(signum);
- }
-
- pthread_sigmask(SIG_SETMASK, &cur_set, NULL);
-
- //If the g_old_sigact set SA_RESETHAND, it will break the chain which means
- //g_old_sigact->next_old_sigact will not be called. Our signal handler does not
- //responsable for that. We just follow what os do on SA_RESETHAND.
- if(g_old_sigact[signum].sa_flags & SA_RESETHAND)
- g_old_sigact[signum].sa_handler = SIG_DFL;
+ } else {
+ SE_TRACE(SE_TRACE_DEBUG, "Unexpected error occured\n");
+ abort();
}
}
void reg_sig_handler()
{
- if(vdso_sgx_enter_enclave != NULL)
- {
- SE_TRACE(SE_TRACE_DEBUG, "vdso_sgx_enter_enclave exists, we won't use signal handler here\n");
- return;
- }
int ret = 0;
struct sigaction sig_act;
SE_TRACE(SE_TRACE_DEBUG, "signal handler is registered\n");
@@ -226,16 +205,13 @@ void reg_sig_handler()
sigdelset(&sig_act.sa_mask, SIGBUS);
sigdelset(&sig_act.sa_mask, SIGTRAP);
}
+ // The signal for interrupt should only interrupt the normal execution of
+ // the enclave, not interrupt the enclave's handling of exceptions or
+ // interrupts
+ sigaddset(&sig_act.sa_mask, SIGRT_INTERRUPT);
- ret = sigaction(SIGSEGV, &sig_act, &g_old_sigact[SIGSEGV]);
- if (0 != ret) abort();
- ret = sigaction(SIGFPE, &sig_act, &g_old_sigact[SIGFPE]);
- if (0 != ret) abort();
- ret = sigaction(SIGILL, &sig_act, &g_old_sigact[SIGILL]);
- if (0 != ret) abort();
- ret = sigaction(SIGBUS, &sig_act, &g_old_sigact[SIGBUS]);
- if (0 != ret) abort();
- ret = sigaction(SIGTRAP, &sig_act, &g_old_sigact[SIGTRAP]);
+ sig_act.sa_flags = SA_SIGINFO ; // Remove SA_RESTART and SA_NODEFER
+ ret = sigaction(SIGRT_INTERRUPT, &sig_act, &g_old_sigact[SIGRT_INTERRUPT]);
if (0 != ret) abort();
}
@@ -246,7 +222,7 @@ extern "C" int enter_enclave(const tcs_t *tcs, const long fn, const void *ocall_
extern "C" int stack_sticker(unsigned int proc, sgx_ocall_table_t *ocall_table, void *ms, CTrustThread *trust_thread, tcs_t *tcs);
-void* get_vdso_sym(const char* vdso_func_name)
+void* get_vdso_sym(const char* vdso_func_name, size_t *size)
{
void *ret = NULL;
@@ -282,6 +258,9 @@ void* get_vdso_sym(const char* vdso_func_name)
auto vdname = dynstr + sym.st_name;
if (strcmp(vdname, vdso_func_name) == 0) {
ret = (vdso_address + sym.st_value);
+ if (size != NULL) {
+ *size = sym.st_size;
+ }
break;
}
}
@@ -292,7 +271,6 @@ void* get_vdso_sym(const char* vdso_func_name)
return ret;
}
-
static int sgx_urts_vdso_handler(long rdi, long rsi, long rdx, long ursp, long r8, long r9,
struct sgx_enclave_run *run)
{
@@ -304,14 +282,14 @@ static int sgx_urts_vdso_handler(long rdi, long rsi, long rdx, long ursp, long r
{
//need to handle exception here
__u64 *user_data = (__u64*)run->user_data;
- void *ocall_table = reinterpret_cast(user_data[0]);
CTrustThread* trust_thread = reinterpret_cast(user_data[1]);
- if(ocall_table == NULL || trust_thread == NULL)
+ if (trust_thread == NULL)
{
run->user_data = SGX_ERROR_UNEXPECTED;
return 0;
}
+ void *ocall_table = reinterpret_cast(user_data[0]);
unsigned int ret = do_ecall(ECMD_EXCEPT, ocall_table, NULL, trust_thread);
if(SGX_SUCCESS == ret)
{
@@ -337,14 +315,14 @@ static int sgx_urts_vdso_handler(long rdi, long rsi, long rdx, long ursp, long r
else
{
__u64 *user_data = (__u64*)run->user_data;
- sgx_ocall_table_t *ocall_table = reinterpret_cast(user_data[0]);
CTrustThread* trust_thread = reinterpret_cast(user_data[1]);
- if(ocall_table == NULL || trust_thread == NULL)
+ if (trust_thread == NULL)
{
run->user_data = SGX_ERROR_UNEXPECTED;
return 0;
}
+ sgx_ocall_table_t *ocall_table = reinterpret_cast(user_data[0]);
auto status = stack_sticker((unsigned int )rdi, ocall_table, (void *)rsi,
trust_thread, trust_thread->get_tcs());
if(status == (int)SE_ERROR_READ_LOCK_FAIL)
@@ -379,7 +357,13 @@ static void __attribute__((constructor)) vdso_detector(void)
#else
if(vdso_sgx_enter_enclave == NULL)
{
- vdso_sgx_enter_enclave = (vdso_sgx_enter_enclave_t)get_vdso_sym("__vdso_sgx_enter_enclave");
+ size_t size = 0;
+ void* start_addr = get_vdso_sym("__vdso_sgx_enter_enclave", &size);
+ g_sgx_enter_enclave_symbol_start = (size_t)start_addr;
+ g_sgx_enter_enclave_symbol_end = g_sgx_enter_enclave_symbol_start + size;
+ SE_TRACE(SE_TRACE_DEBUG, "get_vdso_range = [%x, %x]\n", g_sgx_enter_enclave_symbol_start, g_sgx_enter_enclave_symbol_end);
+
+ vdso_sgx_enter_enclave = (vdso_sgx_enter_enclave_t)g_sgx_enter_enclave_symbol_start;
}
#endif
}
diff --git a/psw/urts/linux/urts.lds b/psw/urts/linux/urts.lds
index 44897f21e..fcee9c930 100644
--- a/psw/urts/linux/urts.lds
+++ b/psw/urts/linux/urts.lds
@@ -6,6 +6,7 @@
sgx_ecall;
sgx_ecall_switchless;
sgx_thread_wait_untrusted_event_ocall;
+ sgx_thread_wait_untrusted_event_timeout_ocall;
sgx_thread_set_untrusted_event_ocall;
sgx_thread_setwait_untrusted_events_ocall;
sgx_thread_set_multiple_untrusted_events_ocall;
diff --git a/psw/urts/linux/urts_emm.cpp b/psw/urts/linux/urts_emm.cpp
new file mode 100644
index 000000000..94f124abb
--- /dev/null
+++ b/psw/urts/linux/urts_emm.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2011-2021 Intel Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Intel Corporation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include "urts_emm.h"
+#include "sgx_enclave_common.h"
+
+#ifdef SE_SIM
+#include
+#define PROT_MASK (PROT_READ | PROT_WRITE | PROT_EXEC)
+#endif
+
+typedef struct ms_alloc_ocall_t {
+ int32_t retval;
+ size_t addr;
+ size_t size;
+ uint32_t page_properties;
+ uint32_t alloc_flags;
+} ms_emm_alloc_ocall_t;
+
+extern "C" sgx_status_t SGX_CDECL ocall_emm_alloc(void* pms)
+{
+
+ ms_emm_alloc_ocall_t* ms = SGX_CAST(ms_emm_alloc_ocall_t*, pms);
+#ifdef SE_SIM
+ ms->retval = mprotect((void*)ms->addr, ms->size, ms->page_properties|PROT_MASK);
+#else
+ ms->retval = enclave_alloc((void *)ms->addr, ms->size,ms->page_properties, ms->alloc_flags, NULL);
+#endif
+ return SGX_SUCCESS;
+}
+
+typedef struct ms_modify_ocall_t {
+ int32_t retval;
+ size_t addr;
+ size_t size;
+ uint32_t flags_from;
+ uint32_t flags_to;
+} ms_emm_modify_ocall_t;
+
+
+extern "C" sgx_status_t SGX_CDECL ocall_emm_modify(void* pms)
+{
+ ms_emm_modify_ocall_t* ms = SGX_CAST(ms_emm_modify_ocall_t*, pms);
+
+#ifdef SE_SIM
+ ms->retval = mprotect((void*)ms->addr, ms->size, ms->flags_to|PROT_MASK);
+#else
+ ms->retval = enclave_modify((void *)ms->addr, ms->size, ms->flags_from, ms->flags_to, NULL);
+#endif
+ return SGX_SUCCESS;
+}
diff --git a/sdk/trts/trts_trim.h b/psw/urts/linux/urts_emm.h
similarity index 87%
rename from sdk/trts/trts_trim.h
rename to psw/urts/linux/urts_emm.h
index 8adc959f0..747094456 100644
--- a/sdk/trts/trts_trim.h
+++ b/psw/urts/linux/urts_emm.h
@@ -29,17 +29,14 @@
*
*/
-
-#ifndef TRIM_RANGE_T_H__
-#define TRIM_RANGE_T_H__
+#ifndef _URTS_EMM_H_
+#define _URTS_EMM_H_
#include
#include
#include
-#include "sgx_edger8r.h" // for sgx_ocall etc.
-
+#include "sgx_urts.h"
-#include // for size_t
#define SGX_CAST(type, item) ((type)(item))
@@ -47,11 +44,15 @@
extern "C" {
#endif
-sgx_status_t SGXAPI trim_range_ocall(size_t fromaddr, size_t toaddr);
-sgx_status_t SGXAPI trim_range_commit_ocall(size_t addr);
+
+
+sgx_status_t SGX_CDECL ocall_emm_alloc(void* pms);
+sgx_status_t SGX_CDECL ocall_emm_modify(void *pms);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
+
diff --git a/psw/urts/linux/urts_internal.lds b/psw/urts/linux/urts_internal.lds
index b2a0f716b..f91338a8b 100644
--- a/psw/urts/linux/urts_internal.lds
+++ b/psw/urts/linux/urts_internal.lds
@@ -6,6 +6,7 @@
sgx_ecall;
sgx_ecall_switchless;
sgx_thread_wait_untrusted_event_ocall;
+ sgx_thread_wait_untrusted_event_timeout_ocall;
sgx_thread_set_untrusted_event_ocall;
sgx_thread_setwait_untrusted_events_ocall;
sgx_thread_set_multiple_untrusted_events_ocall;
diff --git a/psw/urts/loader.cpp b/psw/urts/loader.cpp
index 546dd78e2..b80c7fa60 100644
--- a/psw/urts/loader.cpp
+++ b/psw/urts/loader.cpp
@@ -952,6 +952,7 @@ int CLoader::set_memory_protection()
return SGX_ERROR_UNEXPECTED;
}
+#if 0
if ((META_DATA_MAKE_VERSION(MAJOR_VERSION,MINOR_VERSION) <= m_metadata->version) &&
get_enclave_creator()->is_EDMM_supported(get_enclave_id()))
{
@@ -980,6 +981,7 @@ int CLoader::set_memory_protection()
}
}
}
+#endif
//set memory protection for context
ret = set_context_protection(GET_PTR(layout_t, m_metadata, m_metadata->dirs[DIR_LAYOUT].offset),
@@ -989,7 +991,6 @@ int CLoader::set_memory_protection()
{
return ret;
}
-
return SGX_SUCCESS;
}
@@ -1028,13 +1029,25 @@ int CLoader::set_context_protection(layout_t *layout_start, layout_t *layout_end
}
#endif
}
-
- ret = mprotect(GET_PTR(void, m_start_addr, layout->entry.rva + delta),
+#ifdef SE_SIM
+ ret = mprotect(GET_PTR(void, m_start_addr, layout->entry.rva + delta),
(size_t)layout->entry.page_count << SE_PAGE_SHIFT,
prot);
- if(ret != 0)
+#else
+ if((layout->entry.attributes&PAGE_ATTR_EADD))
+ ret = mprotect(GET_PTR(void, m_start_addr, layout->entry.rva + delta),
+ (size_t)layout->entry.page_count << SE_PAGE_SHIFT,
+ prot);
+ else//dynamic allocated regions
+ if(prot!=PROT_NONE)
+ ret = get_enclave_creator()->alloc((uint64_t) GET_PTR(void, m_start_addr, layout->entry.rva + delta),
+ (size_t)layout->entry.page_count << SE_PAGE_SHIFT,
+ prot);
+ else ret = 0;
+#endif
+ if(ret != 0)
{
- SE_TRACE(SE_TRACE_WARNING, "mprotect(rva=%" PRIu64 ", len=%" PRIu64 ", flags=%d) failed\n",
+ SE_TRACE(SE_TRACE_WARNING, "mprotect/alloc(rva=%" PRIu64 ", len=%" PRIu64 ", flags=%d) failed\n",
(uint64_t)m_start_addr + layout->entry.rva + delta,
(uint64_t)layout->entry.page_count << SE_PAGE_SHIFT,
prot);
diff --git a/psw/urts/tcs.cpp b/psw/urts/tcs.cpp
index fb4827622..46079ee19 100644
--- a/psw/urts/tcs.cpp
+++ b/psw/urts/tcs.cpp
@@ -433,7 +433,7 @@ CTrustThread * CTrustThreadPool::acquire_thread(int ecall_cmd)
}
if(is_special_ecall != true &&
- need_to_new_thread() == true)
+ need_to_new_thread() == true && NULL != m_utility_thread)
{
m_utility_thread->get_enclave()->fill_tcs_mini_pool_fn();
}
diff --git a/psw/urts/urts_com.h b/psw/urts/urts_com.h
index 40a1e0e4b..67ad10603 100644
--- a/psw/urts/urts_com.h
+++ b/psw/urts/urts_com.h
@@ -155,6 +155,11 @@ static bool check_metadata_version(uint64_t urts_version, uint64_t metadata_vers
return false;
}
+ if (MAJOR_VERSION_OF_METADATA(metadata_version)%SGX_MAJOR_VERSION_GAP == 2)
+ {
+ return false;
+ }
+
return true;
}
@@ -284,12 +289,7 @@ static int __create_enclave(BinParser &parser,
if (MAJOR_VERSION_OF_METADATA(metadata->version) % SGX_MAJOR_VERSION_GAP == MAJOR_VERSION_OF_METADATA(urts_version)% SGX_MAJOR_VERSION_GAP &&
MINOR_VERSION_OF_METADATA(metadata->version) >= MINOR_VERSION_OF_METADATA(urts_version))
{
- enclave_version = SDK_VERSION_2_3;
- }
- else if (MAJOR_VERSION_OF_METADATA(metadata->version) % SGX_MAJOR_VERSION_GAP == MAJOR_VERSION_OF_METADATA(urts_version)% SGX_MAJOR_VERSION_GAP &&
- MINOR_VERSION_OF_METADATA(metadata->version) < MINOR_VERSION_OF_METADATA(urts_version))
- {
- enclave_version = SDK_VERSION_2_0;
+ enclave_version = SDK_VERSION_3_0;
}
// initialize the enclave object
@@ -408,7 +408,8 @@ static int __create_enclave(BinParser &parser,
if (get_enclave_creator()->is_EDMM_supported(loader.get_enclave_id()))
{
- layout_t *layout_start = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset);
+ //!FIXME use version of enclave to determine action here
+ /*layout_t *layout_start = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset);
layout_t *layout_end = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset + metadata->dirs[DIR_LAYOUT].size);
if (SGX_SUCCESS != (ret = loader.post_init_action(layout_start, layout_end, 0)))
{
@@ -417,7 +418,7 @@ static int __create_enclave(BinParser &parser,
generate_enclave_debug_event(URTS_EXCEPTION_PREREMOVEENCLAVE, debug_info);
CEnclavePool::instance()->remove_enclave(loader.get_enclave_id(), status);
goto fail;
- }
+ }*/
}
//call trts to do some initialization
@@ -431,7 +432,8 @@ static int __create_enclave(BinParser &parser,
if (get_enclave_creator()->is_EDMM_supported(loader.get_enclave_id()))
{
-
+ //!FIXME use version of enclave to determine action here
+ /*
layout_t *layout_start = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset);
layout_t *layout_end = GET_PTR(layout_t, metadata, metadata->dirs[DIR_LAYOUT].offset + metadata->dirs[DIR_LAYOUT].size);
if (SGX_SUCCESS != (ret = loader.post_init_action_commit(layout_start, layout_end, 0)))
@@ -441,7 +443,7 @@ static int __create_enclave(BinParser &parser,
generate_enclave_debug_event(URTS_EXCEPTION_PREREMOVEENCLAVE, debug_info);
CEnclavePool::instance()->remove_enclave(loader.get_enclave_id(), status);
goto fail;
- }
+ }*/
}
if(SGX_SUCCESS != (ret = loader.set_memory_protection()))
diff --git a/sdk/Makefile b/sdk/Makefile
index 4c95dd3d7..fd3e90667 100644
--- a/sdk/Makefile
+++ b/sdk/Makefile
@@ -48,6 +48,7 @@ opt_check_failed:
.PHONY: all
all: $(CHECK_OPT)
$(MAKE) components
+ $(MAKE) -C ../psw/urts/linux
ifneq ($(MITIGATION-CVE-2020-0551),)
$(RM) -r $(BUILD_DIR)$(MITIGATION-CVE-2020-0551)
mv $(BUILD_DIR) $(BUILD_DIR)$(MITIGATION-CVE-2020-0551)
diff --git a/sdk/Makefile.source b/sdk/Makefile.source
index 6ebb8fb33..6aeac2972 100644
--- a/sdk/Makefile.source
+++ b/sdk/Makefile.source
@@ -66,7 +66,7 @@ LIBTCXX := $(BUILD_DIR)/libsgx_tcxx.a
LIBTSE := $(BUILD_DIR)/libsgx_tservice.a
.PHONY: components
-components: tstdc tcxx tservice trts tcrypto tkey_exchange ukey_exchange tprotected_fs uprotected_fs ptrace sample_crypto libcapable simulation signtool edger8r tcmalloc sgx_pcl sgx_encrypt sgx_tswitchless sgx_uswitchless pthread openmp protobuf ttls utls
+components: tstdc tcxx tservice trts tcrypto tkey_exchange ukey_exchange tprotected_fs uprotected_fs ptrace sample_crypto libcapable simulation signtool edger8r tcmalloc sgx_pcl sgx_encrypt sgx_tswitchless sgx_uswitchless pthread openmp protobuf ttls utls sgx_mm
# ---------------------------------------------------
# tstdc
@@ -176,6 +176,10 @@ ec_dh_lib:
# ---------------------------------------------------
# Other trusted libraries
# ---------------------------------------------------
+.PHONY: sgx_mm
+sgx_mm:
+ $(MAKE) -C $(LINUX_EXTERNAL_DIR)/sgx-emm/
+
.PHONY: trts
trts:
$(MAKE) -C trts/
@@ -291,6 +295,7 @@ clean:
$(MAKE) -C tlibcxx/ clean
$(MAKE) -C tseal/linux/ clean
$(MAKE) -C selib/linux/ clean
+ $(MAKE) -C $(LINUX_EXTERNAL_DIR)/sgx-emm/ clean
$(MAKE) -C trts/ clean
$(MAKE) -C tsetjmp/ clean
$(MAKE) -C tsafecrt/ clean
diff --git a/sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py b/sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
index be120d16c..aeca1f950 100755
--- a/sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
+++ b/sdk/debugger_interface/linux/gdb-sgx-plugin/gdb_sgx_plugin.py
@@ -56,6 +56,7 @@
ENCLAVE_INFO_SIZE = 8 * 7 + 2 * 4
INFO_FMT = 'QQQIIQQQQ'
ENCLAVES_ADDR = {}
+OCCLUM_GDB = 0
# The following definitions should strictly align with the struct of
# tcs_t
@@ -173,6 +174,8 @@ def init_enclave_debug(self):
gdb.execute(gdb_cmd, False, True)
global ENCLAVES_ADDR
ENCLAVES_ADDR[self.start_addr] = gdb_cmd.split()[2]
+ if OCCLUM_GDB == 1:
+ GetOcclumElfBreakpoint()
return 0
def get_peak_heap_used(self):
@@ -523,7 +526,7 @@ def is_bp_in_urts():
try:
ip = gdb.parse_and_eval("$pc")
solib_name = gdb.solib_name(int(str(ip).split()[0], 16))
- if(solib_name.find("libsgx_urts.so") == -1 and solib_name.find("libsgx_urts_sim.so") == -1 and solib_name.find("libsgx_aesm_service.so") == -1):
+ if(solib_name.find("libocclum-pal.so") == -1 and solib_name.find("libsgx_urts.so") == -1 and solib_name.find("libsgx_urts_sim.so") == -1 and solib_name.find("libsgx_aesm_service.so") == -1):
return False
else:
return True
@@ -686,6 +689,64 @@ def stop(self):
gdb.execute(gdb_cmd, False, True)
return False
+class GetLdLoadLibraryReturnBreakpoint(gdb.FinishBreakpoint):
+ def __init__(self):
+ gdb.FinishBreakpoint.__init__ (self, gdb.newest_frame(), internal=1)
+ self.silent = True
+
+ def stop(self):
+ dso_addr_ = gdb.parse_and_eval("$rax")
+ dso_addr = ctypes.c_uint64(dso_addr_).value
+ string = read_from_memory(dso_addr, 16)
+ elf_start_addr, elf_name_addr = struct.unpack('QQ', string)
+ # Assume the file name length is less than 512
+ string = read_from_memory(elf_name_addr, 512)
+ elf_name = "image"
+ for i in range(512):
+ if string[i] != struct.pack("B", 0):
+ elf_name += string[i].decode('ascii')
+ else:
+ break
+ gdb_cmd = load_symbol_cmd.GetLoadSymbolCommand(elf_name, str(elf_start_addr))
+ if gdb_cmd == -1:
+ return 0
+ gdb.execute(gdb_cmd, False, True)
+ return False
+
+class GetLdLoadLibraryBreakpoint(gdb.Breakpoint):
+ def __init__(self):
+ # for Musl
+ gdb.Breakpoint.__init__ (self, spec="load_library", internal=1)
+ # for Glibc
+ gdb.Breakpoint.__init__ (self, spec="_dl_map_object", internal=1)
+
+ def stop(self):
+ GetLdLoadLibraryReturnBreakpoint()
+ return False
+
+class GetOcclumElfBreakpoint(gdb.Breakpoint):
+ def __init__(self):
+ gdb.Breakpoint.__init__ (self, spec="occlum_gdb_hook_load_elf", internal=1)
+
+ def stop(self):
+ addr_ = gdb.parse_and_eval("$rdi")
+ addr = ctypes.c_uint64(addr_).value
+ file_name_ = gdb.parse_and_eval("$rsi")
+ file_name = ctypes.c_uint64(file_name_).value
+ file_name_len_ = gdb.parse_and_eval("$rdx")
+ file_name_len = ctypes.c_uint64(file_name_len_).value
+ file_string = read_from_memory(file_name, file_name_len)
+ file_path = "image" + \
+ struct.unpack('{length}s'.format(length=file_name_len), \
+ file_string[0:file_name_len])[0].decode("ascii")
+ gdb_cmd = load_symbol_cmd.GetLoadSymbolCommand(file_path, str(addr))
+ if gdb_cmd == -1:
+ return 0
+ print (gdb_cmd)
+ gdb.execute(gdb_cmd, False, True)
+ GetLdLoadLibraryBreakpoint()
+ return False
+
def sgx_debugger_init():
print ("detect urts is loaded, initializing")
global SIZE
@@ -697,6 +758,9 @@ def sgx_debugger_init():
if bp.location == "sgx_debug_load_state_add_element":
inited = 1
break
+ if os.getenv("OCCLUM_GDB") == "1":
+ global OCCLUM_GDB
+ OCCLUM_GDB = 1
if inited == 0:
detach_enclaves()
gdb.execute("source gdb_sgx_cmd", False, True)
@@ -716,7 +780,7 @@ def exit_handler(event):
def newobj_handler(event):
solib_name = os.path.basename(event.new_objfile.filename)
- if solib_name == 'libsgx_urts.so' or solib_name == 'libsgx_urts_sim.so' or solib_name == 'libsgx_aesm_service.so':
+ if solib_name.find("libocclum-pal.so") != -1 or solib_name == 'libsgx_urts.so' or solib_name == 'libsgx_urts_sim.so' or solib_name == 'libsgx_aesm_service.so':
sgx_debugger_init()
return
diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_crypto.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_crypto.cpp
index ffef99314..02b155f76 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/file_crypto.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/file_crypto.cpp
@@ -56,6 +56,11 @@ typedef struct {
bool protected_fs_file::generate_secure_blob(sgx_aes_gcm_128bit_key_t* key, const char* label, uint64_t physical_node_number, sgx_aes_gcm_128bit_tag_t* output)
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
kdf_input_t buf = {0, "", 0, "", 0};
uint32_t len = (uint32_t)strnlen(label, MAX_LABEL_LEN + 1);
@@ -67,19 +72,19 @@ bool protected_fs_file::generate_secure_blob(sgx_aes_gcm_128bit_key_t* key, cons
// index
// SP800-108:
- // i - A counter, a binary string of length r that is an input to each iteration of a PRF in counter mode [...].
+ // i ? A counter, a binary string of length r that is an input to each iteration of a PRF in counter mode [...].
buf.index = 0x01;
// label
// SP800-108:
- // Label - A string that identifies the purpose for the derived keying material, which is encoded as a binary string.
+ // Label ? A string that identifies the purpose for the derived keying material, which is encoded as a binary string.
// The encoding method for the Label is defined in a larger context, for example, in the protocol that uses a KDF.
strncpy(buf.label, label, len);
// context and nonce
- // SP800-108:
- // Context - A binary string containing the information related to the derived keying material.
- // It may include identities of parties who are deriving and / or using the derived keying material and,
+ // SP800-108:
+ // Context ? A binary string containing the information related to the derived keying material.
+ // It may include identities of parties who are deriving and / or using the derived keying material and,
// optionally, a nonce known by the parties who derive the keys.
buf.node_number = physical_node_number;
@@ -108,24 +113,29 @@ bool protected_fs_file::generate_secure_blob(sgx_aes_gcm_128bit_key_t* key, cons
bool protected_fs_file::generate_secure_blob_from_user_kdk(bool restore)
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
kdf_input_t buf = {0, "", 0, "", 0};
sgx_status_t status = SGX_SUCCESS;
// index
// SP800-108:
- // i - A counter, a binary string of length r that is an input to each iteration of a PRF in counter mode [...].
+ // i ? A counter, a binary string of length r that is an input to each iteration of a PRF in counter mode [...].
buf.index = 0x01;
// label
// SP800-108:
- // Label - A string that identifies the purpose for the derived keying material, which is encoded as a binary string.
+ // Label ? A string that identifies the purpose for the derived keying material, which is encoded as a binary string.
// The encoding method for the Label is defined in a larger context, for example, in the protocol that uses a KDF.
strncpy(buf.label, METADATA_KEY_NAME, strlen(METADATA_KEY_NAME));
// context and nonce
- // SP800-108:
- // Context - A binary string containing the information related to the derived keying material.
- // It may include identities of parties who are deriving and / or using the derived keying material and,
+ // SP800-108:
+ // Context ? A binary string containing the information related to the derived keying material.
+ // It may include identities of parties who are deriving and / or using the derived keying material and,
// optionally, a nonce known by the parties who derive the keys.
buf.node_number = 0;
@@ -143,7 +153,7 @@ bool protected_fs_file::generate_secure_blob_from_user_kdk(bool restore)
{
memcpy(&buf.nonce32, &file_meta_data.plain_part.meta_data_key_id, sizeof(sgx_key_id_t));
}
-
+
// length of output (128 bits)
buf.output_len = 0x80;
@@ -168,8 +178,13 @@ bool protected_fs_file::generate_secure_blob_from_user_kdk(bool restore)
bool protected_fs_file::init_session_master_key()
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
sgx_aes_gcm_128bit_key_t empty_key = {0};
-
+
if (generate_secure_blob(&empty_key, MASTER_KEY_NAME, 0, (sgx_aes_gcm_128bit_tag_t*)&session_master_key) == false)
return false;
@@ -181,6 +196,11 @@ bool protected_fs_file::init_session_master_key()
bool protected_fs_file::derive_random_node_key(uint64_t physical_node_number)
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
if (master_key_count++ > MAX_MASTER_KEY_USAGES)
{
if (init_session_master_key() == false)
@@ -196,15 +216,20 @@ bool protected_fs_file::derive_random_node_key(uint64_t physical_node_number)
bool protected_fs_file::generate_random_meta_data_key()
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
if (use_user_kdk_key == 1)
{
return generate_secure_blob_from_user_kdk(false);
}
- // derive a random key from the enclave sealing key
+ // derive a random key from the enclave sealing key
sgx_key_request_t key_request;
- memset(&key_request, 0, sizeof(sgx_key_request_t));
-
+ memset(&key_request, 0, sizeof(sgx_key_request_t));
+
key_request.key_name = SGX_KEYSELECT_SEAL;
key_request.key_policy = SGX_KEYPOLICY_MRSIGNER;
@@ -215,14 +240,14 @@ bool protected_fs_file::generate_random_meta_data_key()
key_request.attribute_mask.xfrm = 0x0;
key_request.misc_mask = TSEAL_DEFAULT_MISCMASK;
-
+
sgx_status_t status = sgx_read_rand((unsigned char*)&key_request.key_id, sizeof(sgx_key_id_t));
if (status != SGX_SUCCESS)
{
last_error = status;
return false;
}
-
+
status = sgx_get_key(&key_request, &cur_key);
if (status != SGX_SUCCESS)
{
@@ -241,8 +266,13 @@ bool protected_fs_file::generate_random_meta_data_key()
bool protected_fs_file::restore_current_meta_data_key(const sgx_aes_gcm_128bit_key_t* import_key)
{
+ if (integrity_only)
+ {
+ return true;
+ }
+
if (import_key != NULL)
- {
+ {
memcpy(&cur_key, import_key, sizeof(sgx_aes_gcm_128bit_key_t));
return true;
}
@@ -283,5 +313,3 @@ bool protected_fs_file::restore_current_meta_data_key(const sgx_aes_gcm_128bit_k
return true;
}
-
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp
index cbfbbc8d7..969e5e47b 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/file_flush.cpp
@@ -37,7 +37,7 @@
#include
-bool protected_fs_file::flush(/*bool mc*/)
+bool protected_fs_file::flush()
{
bool result = false;
@@ -55,8 +55,8 @@ bool protected_fs_file::flush(/*bool mc*/)
sgx_thread_mutex_unlock(&mutex);
return false;
}
-
- result = internal_flush(/*mc,*/ true);
+
+ result = internal_flush(true);
if (result == false)
{
assert(file_status != SGX_FILE_STATUS_OK);
@@ -70,18 +70,11 @@ bool protected_fs_file::flush(/*bool mc*/)
}
-bool protected_fs_file::internal_flush(/*bool mc,*/ bool flush_to_disk)
+bool protected_fs_file::internal_flush(bool flush_to_disk)
{
if (need_writing == false) // no changes at all
return true;
-/*
- if (mc == true && encrypted_part_plain.mc_value > (UINT_MAX-2))
- {
- last_error = SGX_ERROR_FILE_MONOTONIC_COUNTER_AT_MAX;
- return false;
- }
-*/
if (encrypted_part_plain.size > MD_USER_DATA_SIZE && root_mht.need_writing == true) // otherwise it's just one write - the meta-data node
{
if (_RECOVERY_HOOK_(0) || write_recovery_file() != true)
@@ -104,44 +97,17 @@ bool protected_fs_file::internal_flush(/*bool mc,*/ bool flush_to_disk)
}
}
-/*
- sgx_status_t status;
-
- if (mc == true)
- {
- // increase monotonic counter local value - only if everything is ok, we will increase the real counter
- if (encrypted_part_plain.mc_value == 0)
- {
- // no monotonic counter so far, need to create a new one
- status = sgx_create_monotonic_counter(&encrypted_part_plain.mc_uuid, &encrypted_part_plain.mc_value);
- if (status != SGX_SUCCESS)
- {
- clear_update_flag();
- file_status = SGX_FILE_STATUS_FLUSH_ERROR;
- last_error = status;
- return false;
- }
- }
- encrypted_part_plain.mc_value++;
- }
-*/
if (_RECOVERY_HOOK_(3) || update_meta_data_node() != true)
{
clear_update_flag();
- /*
- if (mc == true)
- encrypted_part_plain.mc_value--; // don't have to do this as the file cannot be fixed, but doing it anyway to prevent future errors
- */
+
file_status = SGX_FILE_STATUS_CRYPTO_ERROR; // this is something that shouldn't happen, can't fix this...
return false;
}
if (_RECOVERY_HOOK_(4) || write_all_changes_to_disk(flush_to_disk) != true)
{
- //if (mc == false)
- file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; // special case, need only to repeat write_all_changes_to_disk in order to repair it
- //else
- //file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED_NEED_MC; // special case, need to repeat write_all_changes_to_disk AND increase the monotonic counter in order to repair it
+ file_status = SGX_FILE_STATUS_WRITE_TO_DISK_FAILED; // special case, need only to repeat write_all_changes_to_disk in order to repair it
return false;
}
@@ -156,20 +122,7 @@ bool protected_fs_file::internal_flush(/*bool mc,*/ bool flush_to_disk)
erase_recovery_file();
}
*/
-/*
- if (mc == true)
- {
- uint32_t mc_value;
- status = sgx_increment_monotonic_counter(&encrypted_part_plain.mc_uuid, &mc_value);
- if (status != SGX_SUCCESS)
- {
- file_status = SGX_FILE_STATUS_MC_NOT_INCREMENTED; // special case - need only to increase the MC in order to repair it
- last_error = status;
- return false;
- }
- assert(mc_value == encrypted_part_plain.mc_value);
- }
-*/
+
return true;
}
@@ -259,7 +212,7 @@ bool protected_fs_file::set_update_flag(bool flush_to_disk)
file_meta_data.plain_part.update_flag = 0; // turn it off in memory. at the end of the flush, when we'll write the meta-data to disk, this flag will also be cleared there.
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -327,8 +280,16 @@ bool protected_fs_file::update_all_data_and_mht_nodes()
gcm_crypto_data_t* gcm_crypto_data = &data_node->parent->plain.data_nodes_crypto[data_node->data_node_number % ATTACHED_DATA_NODES_COUNT];
// encrypt the data, this also saves the gmac of the operation in the mht crypto node
- status = sgx_rijndael128GCM_encrypt(&cur_key, data_node->plain.data, NODE_SIZE, data_node->encrypted.cipher,
- empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ if(!integrity_only) {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, data_node->plain.data, NODE_SIZE, data_node->encrypted.cipher,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ }
+ // calculate the MAC only
+ else {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE, data_node->plain.data, NODE_SIZE, &gcm_crypto_data->gmac);
+ memcpy(data_node->encrypted.cipher, data_node->plain.data, NODE_SIZE);
+ }
if (status != SGX_SUCCESS)
{
last_error = status;
@@ -380,9 +341,15 @@ bool protected_fs_file::update_all_data_and_mht_nodes()
mht_list.clear();
return false;
}
-
- status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, file_mht_node->encrypted.cipher,
- empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ if(!integrity_only) {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, file_mht_node->encrypted.cipher,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, NULL ,0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE, (const uint8_t*)&file_mht_node->plain, NODE_SIZE, &gcm_crypto_data->gmac);
+ memcpy(file_mht_node->encrypted.cipher, (const uint8_t*)&file_mht_node->plain, NODE_SIZE);
+ }
if (status != SGX_SUCCESS)
{
mht_list.clear();
@@ -399,8 +366,15 @@ bool protected_fs_file::update_all_data_and_mht_nodes()
if (derive_random_node_key(root_mht.physical_node_number) == false)
return false;
- status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&root_mht.plain, NODE_SIZE, root_mht.encrypted.cipher,
- empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac);
+ if(!integrity_only) {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, (const uint8_t*)&root_mht.plain, NODE_SIZE, root_mht.encrypted.cipher,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_encrypt(&cur_key, NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE, (const uint8_t*)&root_mht.plain, NODE_SIZE, &encrypted_part_plain.mht_gmac);
+ memcpy(root_mht.encrypted.cipher, (const uint8_t*)&root_mht.plain, NODE_SIZE);
+ }
if (status != SGX_SUCCESS)
{
last_error = status;
@@ -416,20 +390,31 @@ bool protected_fs_file::update_all_data_and_mht_nodes()
bool protected_fs_file::update_meta_data_node()
{
sgx_status_t status;
-
+
// randomize a new key, saves the key _id_ in the meta data plain part
if (generate_random_meta_data_key() != true)
{
// last error already set
return false;
}
-
- // encrypt meta data encrypted part, also updates the gmac in the meta data plain part
- status = sgx_rijndael128GCM_encrypt(&cur_key,
- (const uint8_t*)&encrypted_part_plain, sizeof(meta_data_encrypted_t), (uint8_t*)&file_meta_data.encrypted_part,
- empty_iv, SGX_AESGCM_IV_SIZE,
- NULL, 0,
- &file_meta_data.plain_part.meta_data_gmac);
+
+ if (!integrity_only) {
+ // encrypt meta data encrypted part, also updates the gmac in the meta data plain part
+ status = sgx_rijndael128GCM_encrypt(&cur_key,
+ (const uint8_t*)&encrypted_part_plain, sizeof(meta_data_encrypted_t), (uint8_t*)&file_meta_data.encrypted_part,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ NULL, 0,
+ &file_meta_data.plain_part.meta_data_gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_encrypt(&cur_key,
+ NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ (const uint8_t*)&encrypted_part_plain, sizeof(meta_data_encrypted_t),
+ &file_meta_data.plain_part.meta_data_gmac);
+ memcpy((uint8_t*)&file_meta_data.encrypted_part, (const uint8_t*)&encrypted_part_plain, sizeof(meta_data_encrypted_t));
+ }
+
if (status != SGX_SUCCESS)
{
last_error = status;
@@ -482,7 +467,7 @@ bool protected_fs_file::write_all_changes_to_disk(bool flush_to_disk)
status = u_sgxprotectedfs_fwrite_node(&result32, file, node_number, data_to_write, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -504,7 +489,7 @@ bool protected_fs_file::write_all_changes_to_disk(bool flush_to_disk)
status = u_sgxprotectedfs_fwrite_node(&result32, file, 1, (uint8_t*)&root_mht.encrypted, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -515,7 +500,7 @@ bool protected_fs_file::write_all_changes_to_disk(bool flush_to_disk)
status = u_sgxprotectedfs_fwrite_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -545,5 +530,3 @@ void protected_fs_file::erase_recovery_file()
status = u_sgxprotectedfs_remove(&result32, recovery_filename);
(void)status; // don't care if it succeeded or failed...just remove the warning
}
-
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp
index a68e3639d..64c0cffd0 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/file_init.cpp
@@ -67,15 +67,15 @@ bool protected_fs_file::cleanup_filename(const char* src, char* dest)
}
-protected_fs_file::protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key)
+protected_fs_file::protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key, bool _integrity_only, const uint64_t cache_page)
{
sgx_status_t status = SGX_SUCCESS;
uint8_t result = 0;
int32_t result32 = 0;
-
- init_fields();
- if (filename == NULL || mode == NULL ||
+ init_fields(cache_page);
+
+ if (filename == NULL || mode == NULL ||
strnlen(filename, 1) == 0 || strnlen(mode, 1) == 0)
{
last_error = EINVAL;
@@ -108,7 +108,7 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
return;
}
- if (init_session_master_key() == false)
+ if (init_session_master_key() == false)
// last_error already set
return;
@@ -116,16 +116,16 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
{
// for new file, this value will later be saved in the meta data plain part (init_new_file)
// for existing file, we will later compare this value with the value from the file (init_existing_file)
- use_user_kdk_key = 1;
+ use_user_kdk_key = 1;
memcpy(user_kdk_key, kdk_key, sizeof(sgx_aes_gcm_128bit_key_t));
}
-
+
// get the clean file name (original name might be clean or with relative path or with absolute path...)
char clean_filename[FILENAME_MAX_LEN];
if (cleanup_filename(filename, clean_filename) == false)
// last_error already set
return;
-
+
if (import_key != NULL)
{// verify the key is not empty - note from SAFE review
sgx_aes_gcm_128bit_key_t empty_aes_key = {0};
@@ -183,6 +183,8 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
return;
}
+ integrity_only = _integrity_only;
+
// now open the file
read_only = (open_mode.read == 1 && open_mode.update == 0); // read only files can be opened simultaneously by many enclaves
@@ -206,7 +208,7 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
last_error = SGX_ERROR_FILE_NOT_SGX_FILE;
break;
}
-
+
strncpy(recovery_filename, filename, FULLNAME_MAX_LEN - 1); // copy full file name
recovery_filename[FULLNAME_MAX_LEN - 1] = '\0'; // just to be safe
size_t full_name_len = strnlen(recovery_filename, RECOVERY_FILE_MAX_LEN);
@@ -222,7 +224,7 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
if (init_existing_file(filename, clean_filename, import_key) == false)
break;
-
+
if (open_mode.append == 1 && open_mode.update == 0)
offset = encrypted_part_plain.size;
}
@@ -247,11 +249,12 @@ protected_fs_file::protected_fs_file(const char* filename, const char* mode, con
}
-void protected_fs_file::init_fields()
+void protected_fs_file::init_fields(const uint64_t cache_page)
{
meta_data_node_number = 0;
memset(&file_meta_data, 0, sizeof(meta_data_node_t));
memset(&encrypted_part_plain, 0, sizeof(meta_data_encrypted_t));
+ memset(&cur_key, 0, sizeof(sgx_aes_gcm_128bit_key_t));
memset(&empty_iv, 0, sizeof(sgx_iv_t));
@@ -261,25 +264,29 @@ void protected_fs_file::init_fields()
root_mht.mht_node_number = 0;
root_mht.new_node = true;
root_mht.need_writing = false;
-
+
offset = 0;
file = NULL;
end_of_file = false;
+ integrity_only = false;
need_writing = false;
read_only = 0;
file_status = SGX_FILE_STATUS_NOT_INITIALIZED;
last_error = SGX_SUCCESS;
- real_file_size = 0;
+ real_file_size = 0;
open_mode.raw = 0;
use_user_kdk_key = 0;
master_key_count = 0;
+ max_cache_page = 0;
recovery_filename[0] = '\0';
-
- memset(&mutex, 0, sizeof(sgx_thread_mutex_t));
- // set hash size to fit MAX_PAGES_IN_CACHE
- cache.rehash(MAX_PAGES_IN_CACHE);
+ max_cache_page = cache_page;
+
+ // set hash size
+ cache.rehash(max_cache_page);
+
+ memset(&mutex, 0, sizeof(sgx_thread_mutex_t));
}
@@ -343,7 +350,7 @@ bool protected_fs_file::file_recovery(const char* filename)
status = u_sgxprotectedfs_fclose(&result32, file);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EINVAL;
return false;
}
@@ -361,7 +368,7 @@ bool protected_fs_file::file_recovery(const char* filename)
status = u_sgxprotectedfs_exclusive_file_open(&file, filename, read_only, &new_file_size, &result32);
if (status != SGX_SUCCESS || file == NULL)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != 0) ? result32 : EACCES;
return false;
}
@@ -376,7 +383,7 @@ bool protected_fs_file::file_recovery(const char* filename)
status = u_sgxprotectedfs_fread_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -394,7 +401,7 @@ bool protected_fs_file::init_existing_file(const char* filename, const char* cle
status = u_sgxprotectedfs_fread_node(&result32, file, 0, (uint8_t*)&file_meta_data, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
@@ -439,15 +446,31 @@ bool protected_fs_file::init_existing_file(const char* filename, const char* cle
return false;
}
+ if (file_meta_data.plain_part.integrity_only != integrity_only)
+ {
+ last_error = EINVAL;
+ return false;
+ }
+
if (restore_current_meta_data_key(import_key) == false)
return false;
- // decrypt the encrypted part of the meta-data
- status = sgx_rijndael128GCM_decrypt(&cur_key,
- (const uint8_t*)file_meta_data.encrypted_part, sizeof(meta_data_encrypted_blob_t), (uint8_t*)&encrypted_part_plain,
- empty_iv, SGX_AESGCM_IV_SIZE,
- NULL, 0,
- &file_meta_data.plain_part.meta_data_gmac);
+ if(!integrity_only) {
+ // decrypt the encrypted part of the meta-data
+ status = sgx_rijndael128GCM_decrypt(&cur_key,
+ (const uint8_t*)file_meta_data.encrypted_part, sizeof(meta_data_encrypted_blob_t), (uint8_t*)&encrypted_part_plain,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ NULL, 0,
+ &file_meta_data.plain_part.meta_data_gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_decrypt(&cur_key,
+ NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ (const uint8_t*)file_meta_data.encrypted_part, sizeof(meta_data_encrypted_blob_t),
+ &file_meta_data.plain_part.meta_data_gmac);
+ memcpy((uint8_t*)&encrypted_part_plain, (const uint8_t*)file_meta_data.encrypted_part, sizeof(meta_data_encrypted_blob_t));
+ }
if (status != SGX_SUCCESS)
{
last_error = status;
@@ -460,66 +483,30 @@ bool protected_fs_file::init_existing_file(const char* filename, const char* cle
return false;
}
-/*
- sgx_mc_uuid_t empty_mc_uuid = {0};
-
- // check if the file contains an active monotonic counter
- if (consttime_memequal(&empty_mc_uuid, &encrypted_part_plain.mc_uuid, sizeof(sgx_mc_uuid_t)) == 0)
- {
- uint32_t mc_value = 0;
-
- status = sgx_read_monotonic_counter(&encrypted_part_plain.mc_uuid, &mc_value);
- if (status != SGX_SUCCESS)
- {
- last_error = status;
- return false;
- }
-
- if (encrypted_part_plain.mc_value < mc_value)
- {
- last_error = SGX_ERROR_FILE_MONOTONIC_COUNTER_IS_BIGGER;
- return false;
- }
-
- if (encrypted_part_plain.mc_value == mc_value + 1) // can happen if AESM failed - file value stayed one higher
- {
- sgx_status_t status = sgx_increment_monotonic_counter(&encrypted_part_plain.mc_uuid, &mc_value);
- if (status != SGX_SUCCESS)
- {
- file_status = SGX_FILE_STATUS_MC_NOT_INCREMENTED;
- last_error = status;
- return false;
- }
- }
-
- if (encrypted_part_plain.mc_value != mc_value)
- {
- file_status = SGX_FILE_STATUS_CORRUPTED;
- last_error = SGX_ERROR_UNEXPECTED;
- return false;
- }
- }
- else
- {
- assert(encrypted_part_plain.mc_value == 0);
- encrypted_part_plain.mc_value = 0; // do this anyway for release...
- }
-*/
if (encrypted_part_plain.size > MD_USER_DATA_SIZE)
{
// read the root node of the mht
status = u_sgxprotectedfs_fread_node(&result32, file, 1, root_mht.encrypted.cipher, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return false;
}
- // this also verifies the root mht gmac against the gmac in the meta-data encrypted part
- status = sgx_rijndael128GCM_decrypt(&encrypted_part_plain.mht_key,
- root_mht.encrypted.cipher, NODE_SIZE, (uint8_t*)&root_mht.plain,
- empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac);
+ if(!integrity_only){
+ // this also verifies the root mht gmac against the gmac in the meta-data encrypted part
+ status = sgx_rijndael128GCM_decrypt(&encrypted_part_plain.mht_key,
+ root_mht.encrypted.cipher, NODE_SIZE, (uint8_t*)&root_mht.plain,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &encrypted_part_plain.mht_gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_decrypt(&encrypted_part_plain.mht_key,
+ NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE, root_mht.encrypted.cipher, NODE_SIZE, &encrypted_part_plain.mht_gmac);
+ memcpy((uint8_t*)&root_mht.plain, root_mht.encrypted.cipher, NODE_SIZE);
+ }
+
if (status != SGX_SUCCESS)
{
last_error = status;
@@ -540,9 +527,10 @@ bool protected_fs_file::init_new_file(const char* clean_filename)
file_meta_data.plain_part.minor_version = SGX_FILE_MINOR_VERSION;
file_meta_data.plain_part.use_user_kdk_key = use_user_kdk_key;
+ file_meta_data.plain_part.integrity_only = integrity_only;
strncpy(encrypted_part_plain.clean_filename, clean_filename, FILENAME_MAX_LEN);
-
+
need_writing = true;
return true;
@@ -552,7 +540,7 @@ bool protected_fs_file::init_new_file(const char* clean_filename)
protected_fs_file::~protected_fs_file()
{
void* data;
-
+
while ((data = cache.get_last()) != NULL)
{
if (((file_data_node_t*)data)->type == FILE_DATA_NODE_TYPE) // type is in the same offset in both node types, need to scrub the plaintext
@@ -573,7 +561,7 @@ protected_fs_file::~protected_fs_file()
// scrub the last encryption key and the session key
memset_s(&cur_key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t));
memset_s(&session_master_key, sizeof(sgx_aes_gcm_128bit_key_t), 0, sizeof(sgx_aes_gcm_128bit_key_t));
-
+
// scrub first 3KB of user data and the gmac_key
memset_s(&encrypted_part_plain, sizeof(meta_data_encrypted_t), 0, sizeof(meta_data_encrypted_t));
@@ -616,7 +604,7 @@ bool protected_fs_file::pre_close(sgx_key_128bit_t* key, bool import)
status = u_sgxprotectedfs_fclose(&result32, file);
if (status != SGX_SUCCESS || result32 != 0)
{
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : SGX_ERROR_FILE_CLOSE_FAILED;
retval = false;
}
@@ -624,7 +612,7 @@ bool protected_fs_file::pre_close(sgx_key_128bit_t* key, bool import)
file = NULL;
}
- if (file_status == SGX_FILE_STATUS_OK &&
+ if (file_status == SGX_FILE_STATUS_OK &&
last_error == SGX_SUCCESS) // else...maybe something bad happened and the recovery file will be needed
erase_recovery_file();
@@ -649,4 +637,3 @@ bool protected_fs_file::pre_close(sgx_key_128bit_t* key, bool import)
return retval;
}
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp
index ea708687d..a5ccc657d 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/file_other.cpp
@@ -45,105 +45,9 @@ int32_t protected_fs_file::remove(const char* filename)
sgx_status_t status;
int32_t result32 = 0;
-/*
- void* file = NULL;
- int64_t real_file_size = 0;
-
- if (filename == NULL)
- return 1;
-
- meta_data_node_t* file_meta_data = NULL;
- meta_data_encrypted_t* encrypted_part_plain = NULL;
-
- // if we have a problem in any of the stages, we simply jump to the end and try to remove the file...
- do {
- status = u_sgxprotectedfs_check_if_file_exists(&result, filename);
- if (status != SGX_SUCCESS)
- break;
-
- if (result == 0)
- {
- errno = EINVAL;
- return 1; // no such file, or file locked so we can't delete it anyways
- }
-
- try {
- file_meta_data = new meta_data_node_t;
- encrypted_part_plain = new meta_data_encrypted_t;
- }
- catch (std::bad_alloc e) {
- break;
- }
-
- status = u_sgxprotectedfs_exclusive_file_open(&file, filename, 1, &real_file_size, &result32);
- if (status != SGX_SUCCESS || file == NULL)
- break;
-
- if (real_file_size == 0 || real_file_size % NODE_SIZE != 0)
- break; // empty file or not an SGX protected FS file
-
- // might be an SGX protected FS file
- status = u_sgxprotectedfs_fread_node(&result32, file, 0, (uint8_t*)file_meta_data, NODE_SIZE);
- if (status != SGX_SUCCESS || result32 != 0)
- break;
-
- if (file_meta_data->plain_part.major_version != SGX_FILE_MAJOR_VERSION)
- break;
-
- sgx_aes_gcm_128bit_key_t zero_key_id = {0};
- sgx_aes_gcm_128bit_key_t key = {0};
- if (consttime_memequal(&file_meta_data->plain_part.key_id, &zero_key_id, sizeof(sgx_aes_gcm_128bit_key_t)) == 1)
- break; // shared file - no monotonic counter
-
- sgx_key_request_t key_request = {0};
- key_request.key_name = SGX_KEYSELECT_SEAL;
- key_request.key_policy = SGX_KEYPOLICY_MRENCLAVE;
- memcpy(&key_request.key_id, &file_meta_data->plain_part.key_id, sizeof(sgx_key_id_t));
-
- status = sgx_get_key(&key_request, &key);
- if (status != SGX_SUCCESS)
- break;
-
- status = sgx_rijndael128GCM_decrypt(&key,
- file_meta_data->encrypted_part, sizeof(meta_data_encrypted_blob_t),
- (uint8_t*)encrypted_part_plain,
- file_meta_data->plain_part.meta_data_iv, SGX_AESGCM_IV_SIZE,
- NULL, 0,
- &file_meta_data->plain_part.meta_data_gmac);
- if (status != SGX_SUCCESS)
- break;
-
- sgx_mc_uuid_t empty_mc_uuid = {0};
- if (consttime_memequal(&empty_mc_uuid, &encrypted_part_plain->mc_uuid, sizeof(sgx_mc_uuid_t)) == 0)
- {
- status = sgx_destroy_monotonic_counter(&encrypted_part_plain->mc_uuid);
- if (status != SGX_SUCCESS)
- break;
-
- // monotonic counter was deleted, mission accomplished!!
- }
- }
- while (0);
-
- // cleanup
- if (file_meta_data != NULL)
- delete file_meta_data;
-
- if (encrypted_part_plain != NULL)
- {
- // scrub the encrypted part
- memset_s(encrypted_part_plain, sizeof(meta_data_encrypted_t), 0, sizeof(meta_data_encrypted_t));
- delete encrypted_part_plain;
- }
-
- if (file != NULL)
- u_sgxprotectedfs_fclose(&result32, file);
-
-*/
-
// do the actual file removal
status = u_sgxprotectedfs_remove(&result32, filename);
- if (status != SGX_SUCCESS)
+ if (status != SGX_SUCCESS)
{
errno = status;
return 1;
@@ -197,13 +101,6 @@ int protected_fs_file::seek(int64_t new_offset, int origin)
return -1;
}
- //if (open_mode.binary == 0 && origin != SEEK_SET && new_offset != 0)
- //{
- // last_error = EINVAL;
- // sgx_thread_mutex_unlock(&mutex);
- // return -1;
- //}
-
int result = -1;
switch (origin)
@@ -232,7 +129,7 @@ int protected_fs_file::seek(int64_t new_offset, int origin)
}
break;
- default:
+ default:
break;
}
@@ -299,33 +196,6 @@ void protected_fs_file::clear_error()
}
}
-/*
- if (file_status == SGX_FILE_STATUS_WRITE_TO_DISK_FAILED_NEED_MC)
- {
- if (write_all_changes_to_disk(true) == true)
- {
- need_writing = false;
- file_status = SGX_FILE_STATUS_MC_NOT_INCREMENTED; // fall through...next 'if' should take care of this one
- }
- }
-
- if ((file_status == SGX_FILE_STATUS_MC_NOT_INCREMENTED) &&
- (encrypted_part_plain.mc_value <= (UINT_MAX-2)))
- {
- uint32_t mc_value;
- sgx_status_t status = sgx_increment_monotonic_counter(&encrypted_part_plain.mc_uuid, &mc_value);
- if (status == SGX_SUCCESS)
- {
- assert(mc_value == encrypted_part_plain.mc_value);
- file_status = SGX_FILE_STATUS_OK;
- }
- else
- {
- last_error = status;
- }
- }
-*/
-
if (file_status == SGX_FILE_STATUS_OK)
{
last_error = SGX_SUCCESS;
@@ -364,13 +234,13 @@ int32_t protected_fs_file::clear_cache()
assert(data != NULL);
assert(((file_data_node_t*)data)->need_writing == false); // need_writing is in the same offset in both node types
- // for production -
+ // for production -
if (data == NULL || ((file_data_node_t*)data)->need_writing == true)
{
sgx_thread_mutex_unlock(&mutex);
return 1;
}
-
+
cache.remove_last();
// before deleting the memory, need to scrub the plain secrets
@@ -393,3 +263,7 @@ int32_t protected_fs_file::clear_cache()
return 0;
}
+int32_t protected_fs_file::get_root_mac(sgx_aes_gcm_128bit_tag_t* mac) {
+ memcpy(mac, file_meta_data.plain_part.meta_data_gmac, sizeof(*mac));
+ return 0;
+}
diff --git a/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp b/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp
index 8d0c5f18c..410476c57 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/file_read_write.cpp
@@ -110,7 +110,7 @@ size_t protected_fs_file::write(const void* ptr, size_t size, size_t count)
data_to_write += empty_place_left_in_md;
data_left_to_write -= empty_place_left_in_md;
}
-
+
if (offset > encrypted_part_plain.size)
encrypted_part_plain.size = offset; // file grew, update the new file size
@@ -126,7 +126,7 @@ size_t protected_fs_file::write(const void* ptr, size_t size, size_t count)
size_t offset_in_node = (size_t)((offset - MD_USER_DATA_SIZE) % NODE_SIZE);
size_t empty_place_left_in_node = NODE_SIZE - offset_in_node;
-
+
if (data_left_to_write <= empty_place_left_in_node)
{ // this will be the last write
memcpy(&file_data_node->plain.data[offset_in_node], data_to_write, data_left_to_write);
@@ -272,7 +272,7 @@ size_t protected_fs_file::read(void* ptr, size_t size, size_t count)
size_t offset_in_node = (offset - MD_USER_DATA_SIZE) % NODE_SIZE;
size_t data_left_in_node = NODE_SIZE - offset_in_node;
-
+
if (data_left_to_read <= data_left_in_node)
{
memcpy(out_buffer, &file_data_node->plain.data[offset_in_node], data_left_to_read);
@@ -304,15 +304,15 @@ size_t protected_fs_file::read(void* ptr, size_t size, size_t count)
}
-// this is a very 'specific' function, tied to the architecture of the file layout, returning the node numbers according to the offset in the file
-void get_node_numbers(uint64_t offset, uint64_t* mht_node_number, uint64_t* data_node_number,
+// this is a very 'specific' function, tied to the architecture of the file layout, returning the node numbers according to the offset in the file
+void get_node_numbers(uint64_t offset, uint64_t* mht_node_number, uint64_t* data_node_number,
uint64_t* physical_mht_node_number, uint64_t* physical_data_node_number)
{
// node 0 - meta data node
// node 1 - mht
// nodes 2-97 - data (ATTACHED_DATA_NODES_COUNT == 96)
// node 98 - mht
- // node 99-195 - data
+ // node 99-194 - data
// etc.
uint64_t _mht_node_number;
uint64_t _data_node_number;
@@ -348,7 +348,7 @@ file_data_node_t* protected_fs_file::get_data_node()
return NULL;
}
- if ((offset - MD_USER_DATA_SIZE) % NODE_SIZE == 0 &&
+ if ((offset - MD_USER_DATA_SIZE) % NODE_SIZE == 0 &&
offset == encrypted_part_plain.size)
{// new node
file_data_node = append_data_node();
@@ -370,11 +370,11 @@ file_data_node_t* protected_fs_file::get_data_node()
}
// even if we didn't get the required data_node, we might have read other nodes in the process
- while (cache.size() > MAX_PAGES_IN_CACHE)
+ while (cache.size() > max_cache_page)
{
void* data = cache.get_last();
assert(data != NULL);
- // for production -
+ // for production -
if (data == NULL)
{
last_error = SGX_ERROR_UNEXPECTED;
@@ -409,7 +409,7 @@ file_data_node_t* protected_fs_file::get_data_node()
}
}
}
-
+
return file_data_node;
}
@@ -461,7 +461,7 @@ file_data_node_t* protected_fs_file::read_data_node()
file_data_node_t* file_data_node = (file_data_node_t*)cache.get(physical_node_number);
if (file_data_node != NULL)
return file_data_node;
-
+
// need to read the data node from the disk
file_mht_node = get_mht_node();
@@ -481,20 +481,32 @@ file_data_node_t* protected_fs_file::read_data_node()
file_data_node->data_node_number = data_node_number;
file_data_node->physical_node_number = physical_node_number;
file_data_node->parent = file_mht_node;
-
+
status = u_sgxprotectedfs_fread_node(&result32, file, file_data_node->physical_node_number, file_data_node->encrypted.cipher, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
delete file_data_node;
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return NULL;
}
gcm_crypto_data_t* gcm_crypto_data = &file_data_node->parent->plain.data_nodes_crypto[file_data_node->data_node_number % ATTACHED_DATA_NODES_COUNT];
- // this function decrypt the data _and_ checks the integrity of the data against the gmac
- status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_data_node->encrypted.cipher, NODE_SIZE, file_data_node->plain.data, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ if(!integrity_only) {
+ // this function decrypt the data _and_ checks the integrity of the data against the gmac
+ status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key,
+ file_data_node->encrypted.cipher,
+ NODE_SIZE, file_data_node->plain.data,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key,
+ NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ file_data_node->encrypted.cipher, NODE_SIZE, &gcm_crypto_data->gmac);
+ memcpy(file_data_node->plain.data, file_data_node->encrypted.cipher, NODE_SIZE);
+ }
if (status != SGX_SUCCESS)
{
delete file_data_node;
@@ -505,7 +517,7 @@ file_data_node_t* protected_fs_file::read_data_node()
}
return NULL;
}
-
+
if (cache.add(file_data_node->physical_node_number, file_data_node) == false)
{
memset_s(&file_data_node->plain, sizeof(data_node_t), 0, sizeof(data_node_t)); // scrub the plaintext data
@@ -536,7 +548,7 @@ file_mht_node_t* protected_fs_file::get_mht_node()
return &root_mht;
// file is constructed from 128*4KB = 512KB per MHT node.
- if ((offset - MD_USER_DATA_SIZE) % (ATTACHED_DATA_NODES_COUNT * NODE_SIZE) == 0 &&
+ if ((offset - MD_USER_DATA_SIZE) % (ATTACHED_DATA_NODES_COUNT * NODE_SIZE) == 0 &&
offset == encrypted_part_plain.size)
{
file_mht_node = append_mht_node(mht_node_number);
@@ -582,7 +594,7 @@ file_mht_node_t* protected_fs_file::append_mht_node(uint64_t mht_node_number)
last_error = ENOMEM;
return NULL;
}
-
+
return new_file_mht_node;
}
@@ -619,20 +631,32 @@ file_mht_node_t* protected_fs_file::read_mht_node(uint64_t mht_node_number)
file_mht_node->mht_node_number = mht_node_number;
file_mht_node->physical_node_number = physical_node_number;
file_mht_node->parent = parent_file_mht_node;
-
+
status = u_sgxprotectedfs_fread_node(&result32, file, file_mht_node->physical_node_number, file_mht_node->encrypted.cipher, NODE_SIZE);
if (status != SGX_SUCCESS || result32 != 0)
{
delete file_mht_node;
- last_error = (status != SGX_SUCCESS) ? status :
+ last_error = (status != SGX_SUCCESS) ? status :
(result32 != -1) ? result32 : EIO;
return NULL;
}
-
+
gcm_crypto_data_t* gcm_crypto_data = &file_mht_node->parent->plain.mht_nodes_crypto[(file_mht_node->mht_node_number - 1) % CHILD_MHT_NODES_COUNT];
- // this function decrypt the data _and_ checks the integrity of the data against the gmac
- status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key, file_mht_node->encrypted.cipher, NODE_SIZE, (uint8_t*)&file_mht_node->plain, empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ if(!integrity_only){
+ // this function decrypt the data _and_ checks the integrity of the data against the gmac
+ status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key,
+ file_mht_node->encrypted.cipher,
+ NODE_SIZE, (uint8_t*)&file_mht_node->plain,
+ empty_iv, SGX_AESGCM_IV_SIZE, NULL, 0, &gcm_crypto_data->gmac);
+ }
+ else {
+ status = sgx_rijndael128GCM_decrypt(&gcm_crypto_data->key,
+ NULL, 0, NULL,
+ empty_iv, SGX_AESGCM_IV_SIZE,
+ file_mht_node->encrypted.cipher, NODE_SIZE, &gcm_crypto_data->gmac);
+ memcpy((uint8_t*)&file_mht_node->plain, file_mht_node->encrypted.cipher, NODE_SIZE);
+ }
if (status != SGX_SUCCESS)
{
delete file_mht_node;
@@ -654,4 +678,3 @@ file_mht_node_t* protected_fs_file::read_mht_node(uint64_t mht_node_number)
return file_mht_node;
}
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp
index 5b7918beb..bacc28526 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.cpp
@@ -61,7 +61,7 @@ lru_cache::~lru_cache()
}
-void lru_cache::rehash(uint32_t size_)
+void lru_cache::rehash(uint64_t size_)
{
map.rehash(size_);
}
@@ -272,4 +272,3 @@ void lru_cache::remove_last()
map.erase(key);
delete map_node;
}
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.h b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.h
index f024f7e25..64b43eb83 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/lru_cache.h
+++ b/sdk/protected_fs/sgx_tprotected_fs/lru_cache.h
@@ -83,7 +83,7 @@ class lru_cache
lru_cache();
~lru_cache();
- void rehash(uint32_t size_);
+ void rehash(uint64_t size_);
bool add(uint64_t key, void* p);
void* get(uint64_t key);
diff --git a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h
index f02b208f1..66fef67e8 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h
+++ b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_file.h
@@ -52,12 +52,15 @@ typedef enum
SGX_FILE_STATUS_CRYPTO_ERROR,
SGX_FILE_STATUS_CORRUPTED,
SGX_FILE_STATUS_MEMORY_CORRUPTED,
- //SGX_FILE_STATUS_WRITE_TO_DISK_FAILED_NEED_MC,
- //SGX_FILE_STATUS_MC_NOT_INCREMENTED,
SGX_FILE_STATUS_CLOSED,
} protected_fs_status_e;
+#ifndef SE_PAGE_SIZE
+#define SE_PAGE_SIZE 0x1000
+#endif
+
#define MAX_PAGES_IN_CACHE 48
+#define DEFAULT_CACHE_SIZE (MAX_PAGES_IN_CACHE * SE_PAGE_SIZE)
COMPILE_TIME_ASSERT(filename_length, FILENAME_MAX_LEN == FILENAME_MAX);
@@ -143,22 +146,23 @@ class protected_fs_file
};
meta_data_encrypted_t encrypted_part_plain; // encrypted part of meta data node, decrypted
-
+
file_mht_node_t root_mht; // the root of the mht is always needed (for files bigger than 3KB)
FILE* file; // OS's FILE pointer
-
+
open_mode_t open_mode;
uint8_t read_only;
int64_t offset; // current file position (user's view)
bool end_of_file; // flag
+ uint64_t max_cache_page;
int64_t real_file_size;
-
+ bool integrity_only; // If true, no encryption, only MAC. Default: false.
bool need_writing; // flag
uint32_t last_error; // last operation error
protected_fs_status_e file_status;
-
+
sgx_thread_mutex_t mutex;
uint8_t use_user_kdk_key;
@@ -167,7 +171,7 @@ class protected_fs_file
sgx_aes_gcm_128bit_key_t cur_key;
sgx_aes_gcm_128bit_key_t session_master_key;
uint32_t master_key_count;
-
+
char recovery_filename[RECOVERY_FILE_MAX_LEN]; // might include full path to the file
lru_cache cache;
@@ -176,21 +180,21 @@ class protected_fs_file
sgx_iv_t empty_iv;
sgx_report_t report;
- void init_fields();
+ void init_fields(const uint64_t cache_page);
bool cleanup_filename(const char* src, char* dest);
bool parse_mode(const char* mode);
bool file_recovery(const char* filename);
bool init_existing_file(const char* filename, const char* clean_filename, const sgx_aes_gcm_128bit_key_t* import_key);
bool init_new_file(const char* clean_filename);
-
+
bool generate_secure_blob(sgx_aes_gcm_128bit_key_t* key, const char* label, uint64_t physical_node_number, sgx_aes_gcm_128bit_tag_t* output);
bool generate_secure_blob_from_user_kdk(bool restore);
bool init_session_master_key();
bool derive_random_node_key(uint64_t physical_node_number);
bool generate_random_meta_data_key();
bool restore_current_meta_data_key(const sgx_aes_gcm_128bit_key_t* import_key);
-
-
+
+
file_data_node_t* get_data_node();
file_data_node_t* read_data_node();
file_data_node_t* append_data_node();
@@ -204,10 +208,10 @@ class protected_fs_file
bool update_meta_data_node();
bool write_all_changes_to_disk(bool flush_to_disk);
void erase_recovery_file();
- bool internal_flush(/*bool mc,*/ bool flush_to_disk);
+ bool internal_flush(bool flush_to_disk);
public:
- protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key);
+ protected_fs_file(const char* filename, const char* mode, const sgx_aes_gcm_128bit_key_t* import_key, const sgx_aes_gcm_128bit_key_t* kdk_key, bool integrity_only, const uint64_t cache_page);
~protected_fs_file();
size_t write(const void* ptr, size_t size, size_t count);
@@ -218,8 +222,9 @@ class protected_fs_file
uint32_t get_error();
void clear_error();
int32_t clear_cache();
- bool flush(/*bool mc*/);
+ bool flush();
bool pre_close(sgx_key_128bit_t* key, bool import);
+ int32_t get_root_mac(sgx_aes_gcm_128bit_tag_t* root_mac);
static int32_t remove(const char* filename);
};
diff --git a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h
index e360cca7d..8541ed474 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h
+++ b/sdk/protected_fs/sgx_tprotected_fs/protected_fs_nodes.h
@@ -66,8 +66,9 @@ typedef struct _meta_data_plain
sgx_attributes_t attribute_mask;
sgx_aes_gcm_128bit_tag_t meta_data_gmac;
-
+
uint8_t update_flag;
+ uint8_t integrity_only;
} meta_data_plain_t;
// these are all defined as relative to node size, so we can decrease node size in tests and have deeper tree
@@ -83,7 +84,7 @@ typedef struct _meta_data_encrypted
{
char clean_filename[FILENAME_MAX_LEN];
int64_t size;
-
+
sgx_mc_uuid_t mc_uuid; // not used
uint32_t mc_value; // not used
@@ -153,4 +154,3 @@ typedef struct _recovery_node
#pragma pack(pop)
#endif // _PROTECTED_FS_NODES_H_
-
diff --git a/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp b/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp
index fe8634acc..2cf3681b1 100644
--- a/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp
+++ b/sdk/protected_fs/sgx_tprotected_fs/sgx_tprotected_fs.cpp
@@ -35,19 +35,22 @@
#include
-
-static SGX_FILE* sgx_fopen_internal(const char* filename, const char* mode, const sgx_key_128bit_t *auto_key, const sgx_key_128bit_t *kdk_key)
+static SGX_FILE* sgx_fopen_internal(const char* filename, const char* mode, const sgx_key_128bit_t *auto_key, const sgx_key_128bit_t *kdk_key, bool integrity_only, const uint64_t cache_size)
{
protected_fs_file* file = NULL;
+ uint64_t cache_page = 0;
- if (filename == NULL || mode == NULL)
+ if (filename == NULL || mode == NULL ||
+ cache_size < DEFAULT_CACHE_SIZE || cache_size % SE_PAGE_SIZE != 0)
{
errno = EINVAL;
return NULL;
}
+ cache_page = cache_size / SE_PAGE_SIZE;
+
try {
- file = new protected_fs_file(filename, mode, auto_key, kdk_key);
+ file = new protected_fs_file(filename, mode, auto_key, kdk_key, integrity_only, cache_page);
}
catch (std::bad_alloc& e) {
(void)e; // remove warning
@@ -68,13 +71,23 @@ static SGX_FILE* sgx_fopen_internal(const char* filename, const char* mode, cons
SGX_FILE* sgx_fopen_auto_key(const char* filename, const char* mode)
{
- return sgx_fopen_internal(filename, mode, NULL, NULL);
+ return sgx_fopen_internal(filename, mode, NULL, NULL, false, DEFAULT_CACHE_SIZE);
}
+SGX_FILE* sgx_fopen_integrity_only(const char* filename, const char* mode)
+{
+ sgx_key_128bit_t empty_key = {0};
+ return sgx_fopen_internal(filename, mode, NULL, &empty_key, true, DEFAULT_CACHE_SIZE);
+}
SGX_FILE* sgx_fopen(const char* filename, const char* mode, const sgx_key_128bit_t *key)
{
- return sgx_fopen_internal(filename, mode, NULL, key);
+ return sgx_fopen_internal(filename, mode, NULL, key, false, DEFAULT_CACHE_SIZE);
+}
+
+SGX_FILE* SGXAPI sgx_fopen_ex(const char* filename, const char* mode, const sgx_key_128bit_t *key, const uint64_t cache_size)
+{
+ return sgx_fopen_internal(filename, mode, NULL, key, false, cache_size);
}
@@ -133,30 +146,6 @@ int32_t sgx_fflush(SGX_FILE* stream)
}
-/* sgx_fflush_and_increment_mc
- * Purpose: force actual write of all the cached data to the disk (see c++ fflush documentation for more details).
- * in addition, in the first time this function is called, it adds a monotonic counter to the file
- * in subsequent calls, the monotonic counter is incremented by one every time this function is called
- * the monotonic counter is a limited resource, please read the SGX documentation for more details
- *
- * Parameters:
- * stream - [IN] the file handle (opened with sgx_fopen or sgx_fopen_auto_key)
- *
- * Return value:
- * int32_t - result, 0 on success, 1 in case of an error - check sgx_ferror for error code
- *
-int32_t sgx_fflush_and_increment_mc(SGX_FILE* stream)
-{
- if (stream == NULL)
- return 1;
-
- protected_fs_file* file = (protected_fs_file*)stream;
-
- return file->flush(true) == true ? 0 : 1;
-}
-*/
-
-
int32_t sgx_ferror(SGX_FILE* stream)
{
if (stream == NULL)
@@ -172,7 +161,7 @@ int32_t sgx_feof(SGX_FILE* stream)
{
if (stream == NULL)
return -1;
-
+
protected_fs_file* file = (protected_fs_file*)stream;
return ((file->get_eof() == true) ? 1 : 0);
@@ -222,7 +211,7 @@ int32_t sgx_remove(const char* filename)
int32_t sgx_fexport_auto_key(const char* filename, sgx_key_128bit_t *key)
{
- SGX_FILE* stream = sgx_fopen_internal(filename, "r", NULL, NULL);
+ SGX_FILE* stream = sgx_fopen_internal(filename, "r", NULL, NULL, false, DEFAULT_CACHE_SIZE);
if (stream == NULL)
return 1;
@@ -232,7 +221,7 @@ int32_t sgx_fexport_auto_key(const char* filename, sgx_key_128bit_t *key)
int32_t sgx_fimport_auto_key(const char* filename, const sgx_key_128bit_t *key)
{
- SGX_FILE* stream = sgx_fopen_internal(filename, "r+", key, NULL);
+ SGX_FILE* stream = sgx_fopen_internal(filename, "r+", key, NULL, false, DEFAULT_CACHE_SIZE);
if (stream == NULL)
return 1;
@@ -251,4 +240,14 @@ int32_t sgx_fclear_cache(SGX_FILE* stream)
}
+int32_t SGXAPI sgx_fget_mac(SGX_FILE* stream, sgx_aes_gcm_128bit_tag_t* mac)
+{
+ if (stream == NULL)
+ return 1;
+
+ protected_fs_file* file = (protected_fs_file*)stream;
+ if (file->flush() == false)
+ return 1;
+ return file->get_root_mac(mac);
+}
diff --git a/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp b/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp
index d38cb46a7..7e451cc27 100644
--- a/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp
+++ b/sdk/protected_fs/sgx_uprotected_fs/sgx_uprotected_fs.cpp
@@ -58,7 +58,7 @@ void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_on
int fd = -1;
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;
struct stat stat_st;
-
+
memset(&stat_st, 0, sizeof(struct stat));
if (filename == NULL || strnlen(filename, 1) == 0)
@@ -99,7 +99,7 @@ void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_on
assert(result == 0);
return NULL;
}
-
+
// convert the file handle to standard 'C' API file pointer
f = fdopen(fd, read_only ? "rb" : "r+b");
if (f == NULL)
@@ -122,7 +122,7 @@ void* u_sgxprotectedfs_exclusive_file_open(const char* filename, uint8_t read_on
uint8_t u_sgxprotectedfs_check_if_file_exists(const char* filename)
{
struct stat stat_st;
-
+
memset(&stat_st, 0, sizeof(struct stat));
if (filename == NULL || strnlen(filename, 1) == 0)
@@ -130,8 +130,8 @@ uint8_t u_sgxprotectedfs_check_if_file_exists(const char* filename)
DEBUG_PRINT("filename is NULL or empty\n");
return 1;
}
-
- return (stat(filename, &stat_st) == 0);
+
+ return (stat(filename, &stat_st) == 0);
}
@@ -247,7 +247,7 @@ int32_t u_sgxprotectedfs_fclose(void* f)
DEBUG_PRINT("fileno returned -1\n");
else
flock(fd, LOCK_UN);
-
+
if ((result = fclose(file)) != 0)
{
if (errno != 0)
@@ -274,13 +274,13 @@ uint8_t u_sgxprotectedfs_fflush(void* f)
DEBUG_PRINT("file is NULL\n");
return 1;
}
-
+
if ((result = fflush(file)) != 0)
{
DEBUG_PRINT("fflush returned %d\n", result);
return 1;
}
-
+
return 0;
}
@@ -302,7 +302,7 @@ int32_t u_sgxprotectedfs_remove(const char* filename)
return errno;
return -1;
}
-
+
return 0;
}
@@ -317,7 +317,7 @@ void* u_sgxprotectedfs_recovery_file_open(const char* filename)
DEBUG_PRINT("recovery filename is NULL or empty\n");
return NULL;
}
-
+
for (int i = 0; i < MAX_FOPEN_RETRIES; i++)
{
f = fopen(filename, "wb");
@@ -330,7 +330,7 @@ void* u_sgxprotectedfs_recovery_file_open(const char* filename)
DEBUG_PRINT("fopen (%s) returned NULL\n", filename);
return NULL;
}
-
+
return f;
}
@@ -344,7 +344,7 @@ uint8_t u_sgxprotectedfs_fwrite_recovery_node(void* f, uint8_t* data, uint32_t d
DEBUG_PRINT("file is NULL\n");
return 1;
}
-
+
// recovery nodes are written sequentially
size_t count = fwrite(data, 1, data_length, file);
if (count != data_length)
@@ -371,7 +371,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
uint8_t* recovery_node = NULL;
uint32_t i = 0;
- do
+ do
{
if (filename == NULL || strnlen(filename, 1) == 0)
{
@@ -384,7 +384,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
DEBUG_PRINT("recovery filename is NULL or empty\n");
return (int32_t)NULL;
}
-
+
recovery_file = fopen(recovery_filename, "rb");
if (recovery_file == NULL)
{
@@ -402,7 +402,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
}
file_size = ftello(recovery_file);
-
+
if ((result = fseeko(recovery_file, 0, SEEK_SET)) != 0)
{
DEBUG_PRINT("fseeko returned %d\n", result);
@@ -445,7 +445,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
err = ferror(recovery_file);
if (err != 0)
ret = err;
- else if (errno != 0)
+ else if (errno != 0)
ret = errno;
break;
}
@@ -466,7 +466,7 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
err = ferror(source_file);
if (err != 0)
ret = err;
- else if (errno != 0)
+ else if (errno != 0)
ret = errno;
break;
}
@@ -503,6 +503,6 @@ int32_t u_sgxprotectedfs_do_file_recovery(const char* filename, const char* reco
if (ret == 0)
remove(recovery_filename);
-
+
return ret;
}
diff --git a/sdk/sign_tool/SignTool/enclave_creator_sign.cpp b/sdk/sign_tool/SignTool/enclave_creator_sign.cpp
index b1585a4b6..9d5896e78 100644
--- a/sdk/sign_tool/SignTool/enclave_creator_sign.cpp
+++ b/sdk/sign_tool/SignTool/enclave_creator_sign.cpp
@@ -305,6 +305,15 @@ int EnclaveCreatorST::get_enclave_info(uint8_t *hash, int size, uint64_t *quota)
return SGX_SUCCESS;
}
+int EnclaveCreatorST::alloc(uint64_t addr, uint64_t size, int flag)
+{
+ UNUSED(addr);
+ UNUSED(size);
+ UNUSED(flag);
+
+ return SGX_SUCCESS;
+}
+
int EnclaveCreatorST::emodpr(uint64_t addr, uint64_t size, uint64_t flag)
{
UNUSED(addr);
@@ -337,14 +346,6 @@ int EnclaveCreatorST::trim_accept(uint64_t addr)
return SGX_SUCCESS;
}
-int EnclaveCreatorST::remove_range(uint64_t fromaddr, uint64_t numpages)
-{
- UNUSED(fromaddr);
- UNUSED(numpages);
-
- return SGX_SUCCESS;
-}
-
static EnclaveCreatorST g_enclave_creator_st;
EnclaveCreator* g_enclave_creator = &g_enclave_creator_st;
diff --git a/sdk/sign_tool/SignTool/enclave_creator_sign.h b/sdk/sign_tool/SignTool/enclave_creator_sign.h
index dd23c83ef..4703d8fc8 100644
--- a/sdk/sign_tool/SignTool/enclave_creator_sign.h
+++ b/sdk/sign_tool/SignTool/enclave_creator_sign.h
@@ -56,12 +56,11 @@ class EnclaveCreatorST : public EnclaveCreator
bool is_EDMM_supported(sgx_enclave_id_t enclave_id);
bool is_driver_compatible();
int get_enclave_info(uint8_t *hash, int size, uint64_t *quota);
+ int alloc(uint64_t addr, uint64_t size, int flag);
int emodpr(uint64_t addr, uint64_t size, uint64_t flag);
int mktcs(uint64_t tcs_addr);
int trim_range(uint64_t fromaddr, uint64_t toaddr);
int trim_accept(uint64_t addr);
- int remove_range(uint64_t fromaddr, uint64_t numpages);
-
private:
uint8_t m_enclave_hash[SGX_HASH_SIZE];
EVP_MD_CTX *m_ctx;
diff --git a/sdk/sign_tool/SignTool/manage_metadata.cpp b/sdk/sign_tool/SignTool/manage_metadata.cpp
index e75a18fe2..e97d16c08 100644
--- a/sdk/sign_tool/SignTool/manage_metadata.cpp
+++ b/sdk/sign_tool/SignTool/manage_metadata.cpp
@@ -48,6 +48,8 @@
#include "crypto_wrapper.h"
#include "global_data.h"
#include "se_version.h"
+#include "ema_imp.h"
+#include "bit_array_imp.h"
#include
#include
@@ -401,7 +403,8 @@ bool CMetadata::modify_metadata(const xml_parameter_t *parameter)
//set bits that have been set '1' and need to be checked
m_metadata->attributes.xfrm |= (m_metadata->enclave_css.body.attributes.xfrm & m_metadata->enclave_css.body.attribute_mask.xfrm);
- return true;
+ bool ret = check_config();
+ return ret;
}
bool CMetadata::check_xml_parameter(const xml_parameter_t *parameter)
@@ -489,6 +492,12 @@ bool CMetadata::check_xml_parameter(const xml_parameter_t *parameter)
}
}
+ if ((parameter[USERREGIONSIZE].value % ALIGN_SIZE))
+ {
+ se_trace(SE_TRACE_ERROR, SET_USER_REGION_SIZE_ALIGN_ERROR);
+ return false;
+ }
+
// LE setting: HW != 0, Licensekey = 1
// Other enclave setting: HW = 0, Licensekey = 0
if((parameter[HW].value == 0 && parameter[LAUNCHKEY].value != 0) ||
@@ -547,6 +556,7 @@ bool CMetadata::check_xml_parameter(const xml_parameter_t *parameter)
m_create_param.rsrv_min_size = parameter[RSRVMINSIZE].value;
m_create_param.rsrv_max_size = parameter[RSRVMAXSIZE].value;
m_create_param.rsrv_executable = parameter[RSRVEXECUTABLE].flag ? parameter[RSRVEXECUTABLE].value : 0;
+ m_create_param.user_region_size = parameter[USERREGIONSIZE].value;
m_create_param.stack_max_size = parameter[STACKMAXSIZE].value;
m_create_param.stack_min_size = parameter[STACKMINSIZE].value;
m_create_param.tcs_num = (uint32_t)parameter[TCSNUM].value;
@@ -558,10 +568,152 @@ bool CMetadata::check_xml_parameter(const xml_parameter_t *parameter)
SE_TRACE_DEBUG("RSRV_MIN_SIZE = 0x%016llX\n", m_create_param.rsrv_min_size);
SE_TRACE_DEBUG("RSRV_INIT_SIZE = 0x%016llX\n", m_create_param.rsrv_init_size);
SE_TRACE_DEBUG("RSRV_MAX_SIZE = 0x%016llX\n", m_create_param.rsrv_max_size);
+ SE_TRACE_DEBUG("USER_REGION_SIZE = 0x%016llX\n", m_create_param.user_region_size);
return true;
}
+uint64_t CMetadata::calculate_rts_bk_overhead()
+{
+ uint64_t ema_overhead = sizeof(struct ema_t_);
+ uint64_t bit_array_overhead = sizeof(struct bit_array_);
+
+ // MIN heap
+ uint32_t page_count = (uint32_t)(m_create_param.heap_min_size >> SE_PAGE_SHIFT);
+ uint64_t heap_node_overhead = ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+
+ if(m_create_param.heap_init_size > m_create_param.heap_min_size)
+ {
+ // INIT heap
+ page_count = (uint32_t)((m_create_param.heap_init_size - m_create_param.heap_min_size) >> SE_PAGE_SHIFT);
+ heap_node_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ }
+
+ if(m_create_param.heap_max_size > m_create_param.heap_init_size)
+ {
+ page_count = (uint32_t)((m_create_param.heap_max_size - m_create_param.heap_init_size) >> SE_PAGE_SHIFT);
+ heap_node_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ }
+
+ page_count = (uint32_t)(m_create_param.rsrv_min_size >> SE_PAGE_SHIFT);
+ uint64_t rsrv_node_overhead = ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+
+ if(m_create_param.rsrv_init_size > m_create_param.rsrv_min_size)
+ {
+ // INIT RSRV
+ page_count = (uint32_t)((m_create_param.rsrv_init_size - m_create_param.rsrv_min_size) >> SE_PAGE_SHIFT);
+ rsrv_node_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ }
+
+ if(m_create_param.rsrv_max_size > m_create_param.rsrv_init_size)
+ {
+ page_count = (uint32_t)((m_create_param.rsrv_max_size - m_create_param.rsrv_init_size) >> SE_PAGE_SHIFT);
+ rsrv_node_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ }
+ // guard page | stack | guard page | TCS | SSA | guard page | TLS
+
+ // guard page
+ uint64_t non_removed_ctx_overhead = ema_overhead;
+ uint64_t removed_ctx_overhead = ema_overhead;
+
+ // stack
+ page_count = (uint32_t)(m_create_param.stack_min_size >> SE_PAGE_SHIFT);
+ non_removed_ctx_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ removed_ctx_overhead += ema_overhead;
+
+ if(m_create_param.stack_max_size > m_create_param.stack_min_size)
+ {
+ page_count = (uint32_t)((m_create_param.stack_max_size - m_create_param.stack_min_size) >> SE_PAGE_SHIFT);
+ non_removed_ctx_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ removed_ctx_overhead += ema_overhead;
+ }
+
+ // guard page
+ non_removed_ctx_overhead += ema_overhead;
+ removed_ctx_overhead += ema_overhead;
+
+ // tcs
+ page_count = TCS_SIZE >> SE_PAGE_SHIFT;
+ non_removed_ctx_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ removed_ctx_overhead += ema_overhead;
+
+ // ssa
+ page_count = SSA_FRAME_SIZE * SSA_NUM;
+ non_removed_ctx_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ removed_ctx_overhead += ema_overhead;
+
+ // guard page
+ non_removed_ctx_overhead += ema_overhead;
+ removed_ctx_overhead += ema_overhead;
+
+ // td
+ page_count = 1;
+ const Section *section = m_parser->get_tls_section();
+ if(section)
+ {
+ page_count += (uint32_t)(ROUND_TO_PAGE(section->virtual_size()) >> SE_PAGE_SHIFT);
+ }
+ non_removed_ctx_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(page_count, 8) >> 3);
+ removed_ctx_overhead += ema_overhead;
+
+ uint32_t tcs_min_pool = 0; /* Number of static threads (EADD) */
+ uint32_t tcs_eremove = 0;
+ if(m_create_param.tcs_min_pool > m_create_param.tcs_num - 1)
+ {
+ tcs_min_pool = m_create_param.tcs_num - 1;
+ tcs_eremove = 0;
+ }
+ else
+ {
+ tcs_min_pool = m_create_param.tcs_min_pool;
+ tcs_eremove = m_create_param.tcs_num -1 - m_create_param.tcs_min_pool;
+ }
+
+ // static thread contexts
+ uint64_t total_non_removed_ctx_overhead = non_removed_ctx_overhead;
+ if (tcs_min_pool > 0)
+ {
+ total_non_removed_ctx_overhead += non_removed_ctx_overhead;
+
+ if (tcs_min_pool > 1)
+ {
+ total_non_removed_ctx_overhead += non_removed_ctx_overhead * (tcs_min_pool - 1);
+ }
+ }
+
+ // eremoved thread contexts
+ uint64_t total_removed_ctx_overhead = removed_ctx_overhead;
+ if (tcs_eremove > 0)
+ {
+ total_removed_ctx_overhead += removed_ctx_overhead;
+
+ if (tcs_eremove > 1)
+ {
+ total_removed_ctx_overhead += removed_ctx_overhead * (tcs_eremove - 1);
+ }
+ }
+
+ // dynamic thread contexts
+ if (m_create_param.tcs_max_num > tcs_min_pool + 1)
+ {
+ total_non_removed_ctx_overhead += non_removed_ctx_overhead * (m_create_param.tcs_max_num - tcs_min_pool);
+ }
+
+ // PT_LOAD segments
+ uint64_t total_sections_overhead = 0;
+ std::vector sections = m_parser->get_sections();
+ for (auto s : sections) {
+ uint32_t p_count = (uint32_t)(ROUND_TO_PAGE(s->virtual_size()) >> SE_PAGE_SHIFT);
+ total_sections_overhead += ema_overhead + bit_array_overhead + (ROUND_TO(p_count, 8) >> 3);
+ }
+
+ return heap_node_overhead +
+ rsrv_node_overhead +
+ total_non_removed_ctx_overhead +
+ total_removed_ctx_overhead +
+ total_sections_overhead;
+}
+
void *CMetadata::alloc_buffer_from_metadata(uint32_t size)
{
void *addr = GET_PTR(void, m_metadata, m_metadata->size);
@@ -998,6 +1150,27 @@ bool CMetadata::build_layout_table()
}
}
+ // USER_REGION
+ uint8_t meta_versions = get_meta_versions();
+ // SGX2 metadata required
+ if ((meta_versions & 2u) == 2u)
+ {
+ uint64_t rts_bk_overhead = calculate_rts_bk_overhead() + 0x20000;
+ uint64_t user_region_size = ROUND_TO_PAGE(rts_bk_overhead);
+ se_trace(SE_TRACE_ERROR, "RTS bookkeeping overhead: 0x%016llX\n", user_region_size);
+
+ if (m_create_param.user_region_size > 0)
+ {
+ user_region_size += m_create_param.user_region_size;
+ }
+ memset(&layout, 0, sizeof(layout));
+ layout.entry.id = LAYOUT_ID_USER_REGION;
+ layout.entry.page_count = (uint32_t)(user_region_size >> SE_PAGE_SHIFT);
+ layout.entry.attributes = PAGE_ATTR_POST_ADD;
+ layout.entry.si_flags = SI_FLAGS_RW;
+ m_layouts.push_back(layout);
+ }
+
// update layout entries
if(false == update_layout_entries())
{
@@ -1219,6 +1392,16 @@ bool CMetadata::build_gd_template(uint8_t *data, uint32_t *data_size)
m_create_param.rsrv_offset = (size_t)layout_rsrv->rva;
}
+ layout_entry_t * layout_user = get_entry_by_id(LAYOUT_ID_USER_REGION, false);
+ if (NULL == layout_user)
+ {
+ m_create_param.user_region_offset = (size_t)0;
+ }
+ else
+ {
+ m_create_param.user_region_offset = (size_t)layout_user->rva;
+ }
+
size_t tmp_tls_addr = (size_t)(get_entry_by_id(LAYOUT_ID_TD)->rva - get_entry_by_id(LAYOUT_ID_TCS)->rva);
m_create_param.td_addr = tmp_tls_addr + (size_t)((get_entry_by_id(LAYOUT_ID_TD)->page_count - 1) << SE_PAGE_SHIFT);
@@ -1327,6 +1510,117 @@ uint64_t CMetadata::calculate_enclave_size(uint64_t size)
return round_size;
}
+bool CMetadata::rts_dynamic()
+{
+ bool no_dynamic_heap =
+ ((m_create_param.heap_init_size == m_create_param.heap_min_size) &&
+ (m_create_param.heap_init_size == m_create_param.heap_max_size));
+
+ bool no_dynamic_stack =
+ (m_create_param.stack_max_size == m_create_param.stack_min_size);
+
+ bool no_dynamic_rsrv =
+ ((m_create_param.rsrv_init_size == m_create_param.rsrv_min_size) &&
+ (m_create_param.rsrv_init_size == m_create_param.rsrv_max_size));
+
+
+ uint32_t tcs_min_pool = 0;
+ if(m_create_param.tcs_min_pool > m_create_param.tcs_num - 1)
+ {
+ tcs_min_pool = m_create_param.tcs_num - 1;
+ }
+ else
+ {
+ tcs_min_pool = m_create_param.tcs_min_pool;
+ }
+
+ bool no_dynamic_thread = (m_create_param.tcs_max_num == tcs_min_pool + 1);
+
+ bool no_rts_dynamic = (no_dynamic_heap && no_dynamic_stack &&
+ no_dynamic_rsrv && no_dynamic_thread);
+
+ return !no_rts_dynamic;
+}
+
+bool CMetadata::user_dynamic()
+{
+ return (m_create_param.user_region_size > 0);
+}
+
+sgx_misc_select_t CMetadata::get_config_misc_select()
+{
+ return m_metadata->enclave_css.body.misc_select;
+}
+
+sgx_misc_select_t CMetadata::get_config_misc_mask()
+{
+ return m_metadata->enclave_css.body.misc_mask;
+}
+
+bool CMetadata::check_config()
+{
+ uint32_t misc_select_0 = (uint32_t)get_config_misc_select() & 1u;
+ uint32_t misc_mask_0 = (uint32_t)get_config_misc_mask() & 1u;
+
+ bool has_rts_dynamic = rts_dynamic();
+ bool has_user_dynamic = user_dynamic();
+
+ // user region configured, either mask or select, or both are zero
+ if (has_user_dynamic)
+ {
+ if ((misc_mask_0 && misc_select_0) == 0)
+ {
+ m_meta_verions = 0;
+ se_trace(SE_TRACE_ERROR, "\033[0;31mERROR: Enclave configuration 'UserRegionSize' requires MiscSelect[0] and MiscMask[0] set to 1.\n\033[0m");
+ return false;
+ }
+ else
+ {
+ // SGX2 metadata only
+ m_meta_verions = 1u << 1;
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'UserRegionSize' requires the enclave to be run on SGX2 platform.\n\033[0m");
+ return true;
+ }
+ }
+
+ if (has_rts_dynamic)
+ {
+ if (misc_select_0 == 0)
+ {
+ // SGX1 metadata only
+ m_meta_verions = 1u;
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will prevent enclave from using dynamic features. To use the dynamic features on SGX2 platform, suggest to set MiscSelectMask[0]=0 and MiscSelect[0]=1.\n\033[0m");
+ return true;
+ }
+
+ if (misc_mask_0 == 1)
+ {
+ // SGX2 metadata only
+ m_meta_verions = 1u << 1;
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will prevent enclave from running on SGX1 platform. To make it run on SGX1 platform, suggest to set MiscSelectMask[0]=0 and MiscSelect[0]=1.\n\033[0m");
+ return true;
+ }
+
+ // SGX1 and SGX2 metadata
+ m_meta_verions = (1u << 1) | 1u;
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will work on SGX1 and SGX2 platforms with respective metadata.\n\033[0m");
+ return true;
+ }
+
+ // SGX1 metadata only
+ m_meta_verions = 1u;
+ if (misc_select_0 == 1)
+ {
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: Enclave configuration 'MiscSelect' and 'MiscSelectMask' will prevent enclave from running on SGX1 platform.\n\033[0m");
+ return true;
+ }
+ else
+ {
+ se_trace(SE_TRACE_ERROR, "\033[0;32mINFO: SGX1 only enclave, which will run on all platforms.\n\033[0m");
+ return true;
+ }
+}
+
bool update_metadata(const char *path, const metadata_t *metadata, uint64_t meta_offset)
{
assert(path != NULL && metadata != NULL);
diff --git a/sdk/sign_tool/SignTool/manage_metadata.h b/sdk/sign_tool/SignTool/manage_metadata.h
index 856e6abc8..df5bb4a02 100644
--- a/sdk/sign_tool/SignTool/manage_metadata.h
+++ b/sdk/sign_tool/SignTool/manage_metadata.h
@@ -83,7 +83,8 @@ typedef enum _para_type_t
ENCLAVEIMAGEADDRESS,
ELRANGESTARTADDRESS,
ELRANGESIZE,
- PKRU
+ PKRU,
+ USERREGIONSIZE
} para_type_t;
typedef struct _xml_parameter_t
@@ -106,6 +107,11 @@ class CMetadata: private Uncopyable
CMetadata(metadata_t *metadata, BinParser *parser);
~CMetadata();
bool build_metadata(const xml_parameter_t *parameter);
+ bool rts_dynamic();
+ bool user_dynamic();
+ sgx_misc_select_t get_config_misc_select();
+ sgx_misc_select_t get_config_misc_mask();
+ uint8_t get_meta_versions() { return m_meta_verions; }
private:
bool get_time(uint32_t *date);
bool modify_metadata(const xml_parameter_t *parameter);
@@ -128,6 +134,9 @@ class CMetadata: private Uncopyable
void* get_rawdata_by_rva(uint64_t rva);
bool vaildate_elrange_config();
bool build_elrange_config_entry();
+ uint64_t calculate_rts_bk_overhead();
+ bool check_config();
+ uint8_t m_meta_verions;
metadata_t *m_metadata;
BinParser *m_parser;
diff --git a/sdk/sign_tool/SignTool/sign_tool.cpp b/sdk/sign_tool/SignTool/sign_tool.cpp
index ea9f5317f..a6710ec1e 100644
--- a/sdk/sign_tool/SignTool/sign_tool.cpp
+++ b/sdk/sign_tool/SignTool/sign_tool.cpp
@@ -141,9 +141,9 @@ static bool get_enclave_info(BinParser *parser, bin_fmt_t *bf, uint64_t * meta_o
// measure_enclave():
// 1. Get the enclave hash by loading enclave
// 2. Get the enclave info - metadata offset and enclave file format
-static bool measure_enclave(uint8_t *hash, const char *dllpath, const xml_parameter_t *parameter, uint32_t option_flag_bits, metadata_t *metadata, uint64_t *meta_offset)
+static bool measure_enclave(uint8_t *hash, const char *dllpath, const xml_parameter_t *parameter, uint32_t option_flag_bits, metadata_t *metadata, uint64_t *meta_offset, uint8_t *meta_versions)
{
- assert(hash && dllpath && metadata && meta_offset);
+ assert(hash && dllpath && metadata && meta_offset && meta_versions);
bool res = false;
off_t file_size = 0;
uint64_t quota = 0;
@@ -189,6 +189,9 @@ static bool measure_enclave(uint8_t *hash, const char *dllpath, const xml_parame
return false;
}
+ // get the versions of metadata we need to output
+ *meta_versions = meta.get_meta_versions();
+
// Collect enclave info
if(get_enclave_info(parser.get(), &bin_fmt, meta_offset, false, ENABLE_RESIGN(option_flag_bits)) == false)
{
@@ -1066,29 +1069,67 @@ static bool append_compatible_metadata(metadata_t *compat_metadata, metadata_t *
return true;
}
-static bool generate_compatible_metadata(metadata_t *metadata, const xml_parameter_t *parameter)
+static bool handle_compatible_metadata(metadata_t *compat_metadata, metadata_t *metadata, bool append)
+{
+ if (append) {
+ se_trace(SE_TRACE_ERROR, "%s: Append metadata version 0x%lx\n", __FUNCTION__, compat_metadata->version);
+ return append_compatible_metadata(compat_metadata, metadata);
+ } else {
+ // overwrite
+ memset(metadata, 0, METADATA_SIZE);
+ if(memcpy_s(metadata, METADATA_SIZE, compat_metadata, compat_metadata->size))
+ return false;
+ se_trace(SE_TRACE_ERROR, "%s: Overwrite with metadata version 0x%lx\n", __FUNCTION__, metadata->version);
+ return true;
+ }
+}
+
+static bool generate_compatible_metadata(metadata_t *metadata, const xml_parameter_t *parameter, uint8_t meta_versions)
{
+ if(meta_versions == 0)
+ {
+ se_trace(SE_TRACE_ERROR, "metadata version is invalid");
+ return false;
+ }
+
+ bool meta_sgx1_only = ((meta_versions & 3u) == 1u);
+ bool meta_sgx2_only = ((meta_versions & 3u) == 2u);
+ bool append = (meta_sgx1_only ? false : true);
+
+ if (meta_sgx2_only) {
+ se_trace(SE_TRACE_ERROR, "%s: Only requires SGX2 metadata\n", __FUNCTION__);
+ return true;
+ }
+
metadata_t *metadata2 = (metadata_t *)malloc(metadata->size);
if(!metadata2)
{
se_trace(SE_TRACE_ERROR, NO_MEMORY_ERROR);
return false;
}
-
SE_TRACE_DEBUG("\n");
-
- // append 2_0 metadata
- memcpy_s(metadata2, metadata->size, metadata, metadata->size);
- //if elrange is set, we can remove this metadata
- if(parameter[ELRANGESIZE].value == 0)
- {
- metadata2->version = META_DATA_MAKE_VERSION(SGX_2_0_MAJOR_VERSION,SGX_2_0_MINOR_VERSION);
- if (!append_compatible_metadata(metadata2, metadata))
+
+ if (memcpy_s(metadata2, metadata->size, metadata, metadata->size)) {
+ se_trace(SE_TRACE_ERROR, "%s: Error memcpy_s failed\n", __FUNCTION__);
+ free(metadata2);
+ return false;
+ }
+
+#if 0
+ if (!meta_sgx1_only) {
+ // append 2_0 metadata
+ // if elrange is set, we can remove this metadata
+ if(parameter[ELRANGESIZE].value == 0)
{
- free(metadata2);
- return false;
+ metadata2->version = META_DATA_MAKE_VERSION(SGX_2_0_MAJOR_VERSION,SGX_2_0_MINOR_VERSION);
+ if (!append_compatible_metadata(metadata2, metadata))
+ {
+ free(metadata2);
+ return false;
+ }
}
}
+#endif
// append 1_9 metadata
if(parameter[ELRANGESIZE].value != 0)
@@ -1157,7 +1198,7 @@ static bool generate_compatible_metadata(metadata_t *metadata, const xml_paramet
{
se_trace(SE_TRACE_DEBUG, "%s: Utility thread TD is the last layout\n", __FUNCTION__);
metadata_cleanup(metadata2, 0);
- ret = append_compatible_metadata(metadata2, metadata);
+ ret = handle_compatible_metadata(metadata2, metadata, append);
free(metadata2);
return ret;
}
@@ -1176,7 +1217,7 @@ static bool generate_compatible_metadata(metadata_t *metadata, const xml_paramet
max_rsrv_entry->entry.si_flags = SI_FLAG_NONE;
max_rsrv_entry->entry.attributes &= (uint16_t)(~PAGE_ATTR_POST_ADD);
}
- ret = append_compatible_metadata(metadata2, metadata);
+ ret = handle_compatible_metadata(metadata2, metadata, append);
free(metadata2);
return ret;
}
@@ -1204,7 +1245,7 @@ static bool generate_compatible_metadata(metadata_t *metadata, const xml_paramet
if (false == ret)
goto end;
}
- ret = append_compatible_metadata(metadata2, metadata);
+ ret = handle_compatible_metadata(metadata2, metadata, append);
if (false == ret)
goto end;
ret = dump_metadata_layout(metadata);
@@ -1306,7 +1347,8 @@ int main(int argc, char* argv[])
{"EnclaveImageAddress", 0xFFFFFFFFFFFFFFFF, 0x1000, 0, 0},
{"ELRangeStartAddress", 0xFFFFFFFFFFFFFFFF, 0, 0, 0},
{"ELRangeSize", 0xFFFFFFFFFFFFFFFF, 0x1000, 0, 0},
- {"PKRU", FEATURE_LOADER_SELECTS, FEATURE_MUST_BE_DISABLED, FEATURE_MUST_BE_DISABLED, 0}};
+ {"PKRU", FEATURE_LOADER_SELECTS, FEATURE_MUST_BE_DISABLED, FEATURE_MUST_BE_DISABLED, 0},
+ {"UserRegionSize", ENCLAVE_MAX_SIZE_64/2, 0, USER_REGION_SIZE, 0}};
const char *path[8] = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
uint8_t enclave_hash[SGX_HASH_SIZE] = {0};
uint8_t metadata_raw[METADATA_SIZE];
@@ -1318,7 +1360,7 @@ int main(int argc, char* argv[])
uint32_t option_flag_bits = 0;
RSA *rsa = NULL;
memset(&metadata_raw, 0, sizeof(metadata_raw));
-
+ uint8_t meta_versions = 0;
#if OPENSSL_VERSION_NUMBER < 0x10100000L
OpenSSL_add_all_algorithms();
@@ -1369,7 +1411,7 @@ int main(int argc, char* argv[])
goto clear_return;
}
- if(measure_enclave(enclave_hash, path[OUTPUT], parameter, option_flag_bits, metadata, &meta_offset) == false)
+ if(measure_enclave(enclave_hash, path[OUTPUT], parameter, option_flag_bits, metadata, &meta_offset, &meta_versions) == false)
{
se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
goto clear_return;
@@ -1388,7 +1430,7 @@ int main(int argc, char* argv[])
se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
goto clear_return;
}
- if(false == generate_compatible_metadata(metadata, parameter))
+ if(false == generate_compatible_metadata(metadata, parameter, meta_versions))
{
se_trace(SE_TRACE_ERROR, OVERALL_ERROR);
goto clear_return;
diff --git a/sdk/sign_tool/SignTool/util_st.h b/sdk/sign_tool/SignTool/util_st.h
index 8dbe1db28..98b5c1f41 100644
--- a/sdk/sign_tool/SignTool/util_st.h
+++ b/sdk/sign_tool/SignTool/util_st.h
@@ -140,6 +140,7 @@
#define SET_RSRV_SIZE_INIT_MIN_ERROR "Reserved memory size setting is not correct: min value should not be larger than init value.\n"
#define SET_RSRV_SIZE_MAX_MIN_ERROR "Reserved memory size setting is not correct: max value should not be smaller than min value.\n"
#define SET_RSRV_EXECUTABLE_ERROR "Reserved memory executable setting is not correct: the executable value should be set to 1 or 0.\n"
+#define SET_USER_REGION_SIZE_ALIGN_ERROR "User region size setting is not correct: size is not page aligned.\n"
#define SET_HW_LE_ERROR "Conflicting setting between the 'HW' and 'LaunchKey'.\n"
#define SET_TCS_MAX_NUM_ERROR "Maximum number of TCS is not correct.\n"
#define SET_TCS_MIN_POOL_ERROR "Minimum number of TCS Pool is not correct.\n"
diff --git a/sdk/simulation/tinst/t_instructions.cpp b/sdk/simulation/tinst/t_instructions.cpp
index 85846a128..ede1e389b 100644
--- a/sdk/simulation/tinst/t_instructions.cpp
+++ b/sdk/simulation/tinst/t_instructions.cpp
@@ -281,6 +281,28 @@ static void _EREPORT(const sgx_target_info_t* ti, const sgx_report_data_t* rd, s
}
////////////////////////////////////////////////////////////////////////
+#define ARCH_SET_GS 0x1001
+#define ARCH_SET_FS 0x1002
+
+
+static void arch_prctl(int code, unsigned long addr) __attribute__((section(".nipx")));
+static void arch_prctl(int code, unsigned long addr)
+{
+ int ret;
+
+ __asm__("mov %1, %%edi\n\t"
+ "movq %2, %%rsi\n\t"
+ "mov $0x9e,%%eax\n\t"
+ "syscall\n\t"
+ "mov %%eax, %0\n\t"
+ :"=a"(ret)
+ :"r"(code), "r"(addr)
+ :"r11", "rcx");
+ if(ret != 0) {
+ // This should never happen.
+ abort();
+ }
+}
static void
_EEXIT(uintptr_t dest, uintptr_t xcx, uintptr_t xdx, uintptr_t xsi, uintptr_t xdi) __attribute__((section(".nipx")));
@@ -301,16 +323,11 @@ _EEXIT(uintptr_t dest, uintptr_t xcx, uintptr_t xdx, uintptr_t xsi, uintptr_t xd
tcs_t *tcs = GET_TCS_PTR(xdx);
GP_ON(tcs == NULL);
- // restore the used _tls_array
- GP_ON(td_mngr_restore_td(tcs) == false);
-
- // check thread is in use or not
tcs_sim_t *tcs_sim = reinterpret_cast(tcs->reserved);
+ // Update the tcs status
size_t tcs_target_state = TCS_STATE_INACTIVE;
- size_t tcs_current_state = TCS_STATE_INACTIVE;
- __atomic_exchange(&tcs_sim->tcs_state, &tcs_target_state, &tcs_current_state, __ATOMIC_RELAXED);
- GP_ON(tcs_current_state!= TCS_STATE_ACTIVE);
+ __atomic_store(&tcs_sim->tcs_state, &tcs_target_state, __ATOMIC_RELAXED);
regs.xax = 0;
regs.xbx = dest;
@@ -318,6 +335,10 @@ _EEXIT(uintptr_t dest, uintptr_t xcx, uintptr_t xdx, uintptr_t xsi, uintptr_t xd
regs.xsi = xsi;
regs.xdi = xdi;
+ //restore the FS, GS base address
+ arch_prctl(ARCH_SET_FS, tcs_sim->saved_fs_base);
+ arch_prctl(ARCH_SET_GS, tcs_sim->saved_gs_base);
+
load_regs(®s);
// jump back to the instruction after the call to _SE3
diff --git a/sdk/simulation/trtssim/linux/Makefile b/sdk/simulation/trtssim/linux/Makefile
index 7a0a9bf52..cb32c4da6 100644
--- a/sdk/simulation/trtssim/linux/Makefile
+++ b/sdk/simulation/trtssim/linux/Makefile
@@ -62,14 +62,20 @@ TRTS1_OBJS := init_enclave.o \
trts.o \
trts_ecall.o \
trts_ocall.o \
+ ema_init.o \
trts_util.o \
trts_veh.o \
trts_xsave.o \
init_optimized_lib.o \
- trts_emodpr.o \
- trts_add_trim.o
+ trts_interrupt.o \
+ trts_version.o \
+ trts_add_trim.o \
+
TRTS2_OBJS := trts_nsp.o
-TRTS_OBJS := $(TRTS1_OBJS) $(TRTS2_OBJS)
+TRTS3_OBJS := ema_rt.o
+
+TRTS_OBJS := $(TRTS1_OBJS) $(TRTS2_OBJS) $(TRTS3_OBJS)
+
TINST_OBJS := t_instructions.o \
deriv.o
@@ -92,6 +98,9 @@ TLDR_OBJS := $(TLDR_ASM_OBJS) $(TLDR_C_OBJS)
LIBTRTS := libsgx_trts_sim.a
+LIBSGX_MM_PATH = $(LINUX_EXTERNAL_DIR)/sgx-emm
+LIBSGX_MM = libsgx_mm.a
+
vpath %.cpp $(TRTS_DIR):$(TINST_DIR)
vpath %.S $(LOWLIB_DIR):$(TLDR_DIR):$(XSAVE_DIR)
vpath %.c $(TLS_DIR):$(TLDR_DIR)
@@ -101,8 +110,15 @@ vpath %.c $(TLS_DIR):$(TLDR_DIR)
all: $(LIBTRTS) | $(BUILD_DIR)
$(CP) $< $|
-$(LIBTRTS): $(TRTS_OBJS) $(TINST_OBJS) $(LOWLIB_OBJS) $(TLS_OBJS) $(TLDR_OBJS)
+$(LIBTRTS): $(TRTS_OBJS) $(TINST_OBJS) $(LOWLIB_OBJS) $(TLS_OBJS) $(TLDR_OBJS) $(LIBSGX_MM)
$(AR) rcsD $@ $(TRTS_OBJS) $(TINST_OBJS) $(LOWLIB_OBJS) $(TLS_OBJS) $(TLDR_OBJS)
+ $(MKDIR) $(BUILD_DIR)/.libsgx_mm
+ $(RM) $(BUILD_DIR)/.libsgx_mm/* && cd $(BUILD_DIR)/.libsgx_mm && $(AR) x $(LIBSGX_MM_PATH)/libsgx_mm.a
+ $(AR) rsD $@ $(BUILD_DIR)/.libsgx_mm/*.o
+ @$(RM) -rf $(BUILD_DIR)/.libsgx_mm
+
+$(LIBSGX_MM):
+ $(MAKE) -C $(LIBSGX_MM_PATH)
# ------------------------------------------------------------
$(TRTS1_OBJS): CPPFLAGS += -I$(COMMON_DIR)/inc/tlibc \
@@ -110,6 +126,9 @@ $(TRTS1_OBJS): CPPFLAGS += -I$(COMMON_DIR)/inc/tlibc \
$(TRTS2_OBJS): %.o:%.cpp
$(CXX) -c $(filter-out -fstack-protector-strong, $(CXXFLAGS)) -I$(SIM_DIR)/tinst/ $(CPPFLAGS) $< -o $@
+$(TRTS3_OBJS): %.o:../%.c
+ $(CC) -c $(TCFLAGS) $(CFLAGS) -I$(COMMON_DIR)/inc -I$(COMMON_DIR)/inc/internal -I$(COMMON_DIR)/inc/internal/linux -I$(COMMON_DIR)/inc/tlibc -I$(SIM_DIR)/tinst/ -fPIC $< -o $@
+
# Explicitly disable optimization for tRTS simulation library,
# since the '_SE3' function has assumptions on stack layout.
diff --git a/sdk/simulation/uinst/td_mngr.h b/sdk/simulation/uinst/td_mngr.h
index 47e082edd..7001ad397 100644
--- a/sdk/simulation/uinst/td_mngr.h
+++ b/sdk/simulation/uinst/td_mngr.h
@@ -43,6 +43,8 @@ typedef struct _tcs_sim_t
size_t tcs_state;
uintptr_t saved_dtv;
uintptr_t saved_fs_gs_0;
+ uintptr_t saved_fs_base;
+ uintptr_t saved_gs_base;
uint64_t tcs_offset_update_flag;
} tcs_sim_t;
diff --git a/sdk/simulation/uinst/u_instructions.cpp b/sdk/simulation/uinst/u_instructions.cpp
index 3532a5dbe..8ea8a2336 100644
--- a/sdk/simulation/uinst/u_instructions.cpp
+++ b/sdk/simulation/uinst/u_instructions.cpp
@@ -37,6 +37,8 @@
#include
#include
#include
+#include
+#include
#include
#include "arch.h"
@@ -59,7 +61,7 @@ static uintptr_t _EINIT(secs_t* secs, enclave_css_t* css, token_t* launch);
static uintptr_t _ECREATE (page_info_t* pi);
static uintptr_t _EADD (page_info_t* pi, void* epc_lin_addr);
static uintptr_t _EREMOVE(const void* epc_lin_addr);
-extern "C" void* get_td_addr(void);
+extern "C" int arch_prctl(int code, unsigned long addr);
extern "C" bool get_elrange_start_address(void* base_address, uint64_t &elrange_start_address);
@@ -103,7 +105,6 @@ void call_old_handler(int signum, void* siginfo, void *priv)
sigset_t cur_set;
pthread_sigmask(SIG_SETMASK, &g_old_sigact[signum].sa_mask, &cur_set);
-
if(g_old_sigact[signum].sa_flags & SA_SIGINFO)
{
@@ -120,13 +121,14 @@ void call_old_handler(int signum, void* siginfo, void *priv)
g_old_sigact[signum].sa_handler = SIG_DFL;
}
}
-
+#define SIGRT_INTERRUPT (64)
void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv) __attribute__((optimize(0))) __attribute__((optimize("no-stack-protector")));
void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv)
{
- GP_ON(signum != SIGFPE && signum != SIGSEGV);
+ GP_ON(signum != SIGFPE && signum != SIGSEGV && signum != SIGRT_INTERRUPT);
- thread_data_t *thread_data = (thread_data_t*)get_td_addr();
+ thread_data_t *thread_data = 0;
+ arch_prctl(ARCH_GET_GS, (unsigned long)&thread_data);
if (thread_data != NULL && (uintptr_t)thread_data == (uintptr_t)thread_data->self_addr)
{
// first SSA can be used to get tcs, even cssa > 0.
@@ -137,13 +139,27 @@ void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv)
{
tcs_sim_t *tcs_sim = reinterpret_cast(tcs->reserved);
- size_t tcs_current_state = TCS_STATE_ACTIVE;
- __atomic_load(&tcs_sim->tcs_state, &tcs_current_state, __ATOMIC_RELAXED);
+ size_t tcs_target_state = TCS_STATE_INACTIVE;
+ size_t tcs_current_state = TCS_STATE_INACTIVE;
+ __atomic_exchange(&tcs_sim->tcs_state, &tcs_target_state, &tcs_current_state, __ATOMIC_RELAXED);
if (tcs_current_state == TCS_STATE_ACTIVE)
{
- size_t tcs_target_state = TCS_STATE_INACTIVE;
- __atomic_store(&tcs_sim->tcs_state, &tcs_target_state, __ATOMIC_RELAXED);
+ // save FS, GS base address
+ bool user_interrupt = false;
+ uint64_t tmp_fs_base = 0, tmp_gs_base = 0;
+ arch_prctl(ARCH_GET_FS, (unsigned long)&tmp_fs_base);
+ arch_prctl(ARCH_GET_GS, (unsigned long)&tmp_gs_base);
+
+ // Workaround for Occlum. Occlum only handle user application exception
+ // the fs_base is used by application which is not same as the gs_base used by Occlum
+ if (tmp_fs_base == tmp_gs_base) {
+ return;
+ }
+
+ // restore FS, GS base address
+ arch_prctl(ARCH_SET_FS, tcs_sim->saved_fs_base);
+ arch_prctl(ARCH_SET_GS, tcs_sim->saved_gs_base);
CEnclaveMngr *mngr = CEnclaveMngr::get_instance();
assert(mngr != NULL);
@@ -154,8 +170,11 @@ void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv)
ucontext_t* context = reinterpret_cast(priv);
size_t xip = context->uc_mcontext.gregs[REG_RIP];
secs_t *secs = ce->get_secs();
- if (secs && (xip >= (size_t)secs->base) && (xip < (size_t)secs->base + secs->size))
- {
+
+ //Workaround for Occlum. Occlum only handle user application exception
+ if (secs && (xip >= (size_t)tcs) && (xip < (size_t)secs->base + secs->size))
+ {
+ user_interrupt = true;
GP_ON(tcs->cssa >= tcs->nssa);
p_ssa_gpr = (ssa_gpr_t*)((size_t)p_ssa_gpr + tcs->cssa * secs->ssa_frame_size * SE_PAGE_SIZE);
p_ssa_gpr->REG(ax) = context->uc_mcontext.gregs[REG_RAX];
@@ -175,7 +194,9 @@ void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv)
p_ssa_gpr->r13 = context->uc_mcontext.gregs[REG_R13];
p_ssa_gpr->r14 = context->uc_mcontext.gregs[REG_R14];
p_ssa_gpr->r15 = context->uc_mcontext.gregs[REG_R15];
- p_ssa_gpr->rflags = context->uc_flags;
+ p_ssa_gpr->rflags = context->uc_mcontext.gregs[REG_EFL];
+ p_ssa_gpr->fs = tmp_fs_base;
+ p_ssa_gpr->gs = tmp_gs_base;
context->uc_mcontext.gregs[REG_RAX] = SE_ERESUME;
context->uc_mcontext.gregs[REG_RBX] = (size_t)tcs;
@@ -203,21 +224,34 @@ void sig_handler_sim(int signum, siginfo_t *siginfo, void *priv)
p_ssa_gpr->exit_info.vector = 0; //#DE
}
else
- {
+ {
p_ssa_gpr->exit_info.valid = 0;
}
tcs->cssa +=1;
}
- }
- }
+ }
+
+ if (user_interrupt == false) {
+ // restore FS, GS base address
+ arch_prctl(ARCH_SET_FS, tmp_fs_base);
+ arch_prctl(ARCH_SET_GS, tmp_gs_base);
+ }
+ }
}
}
call_old_handler(signum, siginfo, priv);
}
#define SIG_STACK_SIZE (4096*10)
+#include
+std::atomic sig_handler_registed (false);
void reg_sig_handler_sim()
{
+ if (sig_handler_registed)
+ return;
+
+ SE_TRACE(SE_TRACE_DEBUG, "signal hander for simulation registed\n");
+
int ret = 0;
struct sigaction sig_act;
stack_t ss;
@@ -240,10 +274,19 @@ void reg_sig_handler_sim()
sigdelset(&sig_act.sa_mask, SIGSEGV);
sigdelset(&sig_act.sa_mask, SIGFPE);
}
+
+ sigdelset(&sig_act.sa_mask, SIGRT_INTERRUPT);
+
ret = sigaction(SIGSEGV, &sig_act, &g_old_sigact[SIGSEGV]);
if (0 != ret) abort();
ret = sigaction(SIGFPE, &sig_act, &g_old_sigact[SIGFPE]);
if (0 != ret) abort();
+
+ ret = sigaction(SIGRT_INTERRUPT, &sig_act, &g_old_sigact[SIGRT_INTERRUPT]);
+ if (0 != ret)
+ abort();
+
+ sig_handler_registed = true;
}
uintptr_t _EINIT(secs_t* secs, enclave_css_t *css, token_t *launch)
@@ -276,6 +319,8 @@ uintptr_t _EINIT(secs_t* secs, enclave_css_t *css, token_t *launch)
return SGX_ERROR_INVALID_ATTRIBUTE;
}
+ reg_sig_handler_sim();
+
mcp_same_size(&this_secs->mr_enclave, &css->body.enclave_hash, sizeof(sgx_measurement_t));
this_secs->isv_prod_id = css->body.isv_prod_id;
this_secs->isv_svn = css->body.isv_svn;
@@ -338,16 +383,13 @@ uintptr_t _ECREATE(page_info_t* pi)
// `ce' is not checked against NULL, since it is not
// allocated with new(std::no_throw).
- addr = mmap(secs->base, (size_t)secs->size, PROT_READ | PROT_WRITE, mmap_flag, -1, 0);
+ addr = mmap(secs->base, (size_t)secs->size, SGX_PROT_NONE, mmap_flag, -1, 0);
if(MAP_FAILED == addr)
{
delete ce;
return 0;
}
- // Mark all the memory inaccessible.
- se_virtual_protect(addr, (size_t)secs->size, SGX_PROT_NONE);
-
//set image_offset
if(image_offset != 0)
{
@@ -471,8 +513,9 @@ void _SE3(uintptr_t xax, uintptr_t xbx,
xip = reinterpret_cast(enclave_base_addr);
GP_ON_EENTER(xip == 0);
- //set the _tls_array to point to the self_addr of TLS section inside the enclave
- GP_ON_EENTER(td_mngr_set_td(enclave_base_addr, tcs) == false);
+ // save FS, GS base address
+ arch_prctl(ARCH_GET_FS, (unsigned long)&tcs_sim->saved_fs_base);
+ arch_prctl(ARCH_GET_GS, (unsigned long)&tcs_sim->saved_gs_base);
// Destination depends on STATE
xip += (uintptr_t)tcs->oentry;
@@ -496,6 +539,10 @@ void _SE3(uintptr_t xax, uintptr_t xbx,
regs.xsp = p_ssa_gpr->REG(sp_u);
regs.xip = xip;
+ // adjust the FS, GS base address
+ arch_prctl(ARCH_SET_FS, (unsigned long)enclave_base_addr + tcs->ofs_base);
+ arch_prctl(ARCH_SET_GS, (unsigned long)enclave_base_addr + tcs->ogs_base);
+
load_regs(®s);
// Returning from this function enters the enclave
@@ -523,8 +570,7 @@ void _SE3(uintptr_t xax, uintptr_t xbx,
__atomic_exchange(&tcs_sim->tcs_state, &tcs_target_state, &tcs_current_state, __ATOMIC_RELAXED);
GP_ON_EENTER(tcs_current_state != TCS_STATE_INACTIVE);
-
- tcs->cssa -=1;
+ tcs->cssa -=1;
secs = ce->get_secs();
enclave_base_addr = secs->base;
@@ -545,6 +591,10 @@ void _SE3(uintptr_t xax, uintptr_t xbx,
regs.xbp = p_ssa_gpr->REG(bp);
regs.xip = p_ssa_gpr->REG(ip);
+ // adjust the FS, GS base address
+ arch_prctl(ARCH_SET_FS, p_ssa_gpr->fs);
+ arch_prctl(ARCH_SET_GS, p_ssa_gpr->gs);
+
load_regs(®s);
return;
diff --git a/sdk/simulation/urtssim/enclave_creator_sim.cpp b/sdk/simulation/urtssim/enclave_creator_sim.cpp
index f1da35951..233f63a9f 100644
--- a/sdk/simulation/urtssim/enclave_creator_sim.cpp
+++ b/sdk/simulation/urtssim/enclave_creator_sim.cpp
@@ -46,7 +46,7 @@
#include
#include "sgx_enclave_common.h"
#include