Browse Source

Linux 2.1.2 Open Source Gold Release

Security updates to Linux SDK and PSW

Signed-off-by: Li, Xun <xun.li@intel.com>
Li, Xun 6 years ago
parent
commit
bd59dc35dc
45 changed files with 741 additions and 381 deletions
  1. 0 8
      SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp
  2. 2 21
      SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp
  3. 1 11
      SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl
  4. 1 0
      common/inc/internal/se_atomic.h
  5. 1 1
      common/inc/internal/se_version.h
  6. 48 0
      common/inc/sgx_lfence.h
  7. 8 7
      common/inc/sgx_trts.h
  8. 4 4
      download_prebuilt.sh
  9. 1 0
      linux/installer/common/sdk/BOMs/sdk_base.txt
  10. 3 0
      psw/ae/aesm_service/source/aesm_wrapper/src/AESMQueueManager.cpp
  11. 3 9
      psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp
  12. 2 2
      psw/ae/aesm_service/source/upse/uecall_bridge.cpp
  13. 1 4
      psw/ae/common/inc/ICommunicationSocket.h
  14. 2 2
      psw/ae/common/inc/ITransporter.h
  15. 1 1
      psw/ae/common/inc/NonBlockingUnixCommunicationSocket.h
  16. 3 3
      psw/ae/common/inc/SocketTransporter.h
  17. 1 1
      psw/ae/common/inc/UnixCommunicationSocket.h
  18. 24 14
      psw/ae/common/src/NonBlockingUnixCommunicationSocket.cpp
  19. 8 3
      psw/ae/common/src/SocketTransporter.cpp
  20. BIN
      psw/ae/data/prebuilt/le_prod_css.bin
  21. 7 0
      psw/ae/pce/pce.cpp
  22. 1 1
      psw/ae/pse/pse_op/config.xml
  23. 37 2
      psw/ae/pse/pse_op/pse_op.cpp
  24. 7 0
      psw/ae/pse/pse_pr/X509Parser.cpp
  25. 58 0
      psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp
  26. 1 1
      psw/ae/pse/pse_pr/config.xml
  27. 4 2
      psw/ae/pse/pse_pr/include/t_long_term_pairing.h
  28. 6 28
      psw/ae/pse/pse_pr/pse_pr.cpp
  29. 4 2
      psw/ae/pse/pse_pr/pse_pr.edl
  30. 62 2
      psw/ae/pse/pse_pr/t_long_term_pairing.cpp
  31. 2 1
      psw/ae/pve/provision_enclave.cpp
  32. 10 1
      psw/ae/pve/provision_msg2.cpp
  33. 25 3
      psw/ae/qe/quoting_enclave.cpp
  34. 0 2
      sdk/edger8r/linux/Ast.ml
  35. 184 132
      sdk/edger8r/linux/CodeGen.ml
  36. 95 29
      sdk/edger8r/linux/Parser.mly
  37. 69 59
      sdk/sign_tool/SignTool/manage_metadata.cpp
  38. 33 15
      sdk/sign_tool/SignTool/sign_tool.cpp
  39. 2 2
      sdk/sign_tool/SignTool/util_st.h
  40. 2 1
      sdk/tkey_exchange/simple_vector.cpp
  41. 9 2
      sdk/tkey_exchange/tkey_exchange.cpp
  42. 2 1
      sdk/trts/init_enclave.cpp
  43. 2 1
      sdk/trts/trts.cpp
  44. 3 2
      sdk/trts/trts_ecall.cpp
  45. 2 1
      sdk/tseal/tSeal_internal.cpp

+ 0 - 8
SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp

@@ -104,14 +104,6 @@ void edger8r_pointer_attributes(void)
     for (int i = 0; i < 10; i++)
         assert(arr[i] == (9 - i));
     
-    memset(arr, 0x0, sizeof(arr));
-    ret = ecall_pointer_sizefunc(global_eid, (char *)arr);
-    if (ret != SGX_SUCCESS)
-        abort();
-
-    for (int i = 0; i < 10; i++)
-        assert(arr[i] == i);
-    
     return;
 }
 

+ 2 - 21
SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp

@@ -36,6 +36,7 @@
 #include <string.h>
 
 #include "sgx_trts.h"
+#include "sgx_lfence.h"
 #include "../Enclave.h"
 #include "Enclave_t.h"
 
@@ -70,7 +71,7 @@ size_t ecall_pointer_user_check(void *val, size_t sz)
         abort();
 
     /*fence after sgx_is_outside_enclave check*/
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     char tmp[100] = {0};
     size_t len = sz>100?100:sz;
@@ -198,23 +199,3 @@ void ecall_pointer_isptr_readonly(buffer_t buf, size_t len)
     strncpy((char*)buf, "0987654321", len);
 }
 
-/* get_buffer_len:
- *   get the length of input buffer 'buf'.
- */
-size_t get_buffer_len(const char* buf)
-{
-    (void)buf;
-    return 10*sizeof(int);
-}
-
-/* ecall_pointer_sizefunc:
- *   call get_buffer_len to determin the length of 'buf'.
- */
-void ecall_pointer_sizefunc(char *buf)
-{
-    int *tmp = (int*)buf;
-    for (int i = 0; i < 10; i++) {
-        assert(tmp[i] == 0);
-        tmp[i] = i;
-    }
-}

+ 1 - 11
SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl

@@ -38,7 +38,7 @@ enclave {
      * Following keywords/attributes are supported for pointers in Edger8r: 
      *      in, out, user_check, 
      *      string, wstring,
-     *      const, size, count, sizefunc, isptr, readonly
+     *      const, size, count, isptr, readonly
      */
 
     trusted {
@@ -122,16 +122,6 @@ enclave {
         
         public void ecall_pointer_isptr_readonly([in, isptr, readonly, size=len] buffer_t buf, size_t len);
         
-        /*
-         * [sizefunc]:
-         *      call a function to decide the size/length of the parameter; 
-         * Note:
-         *      User need to define and implement `get_buf_len' as:
-         *      size_t get_buf_len(const char* buf); 
-         */
-
-        public void ecall_pointer_sizefunc([sizefunc = get_buffer_len, in, out] char *buf);
-
     };
 
     /*

+ 1 - 0
common/inc/internal/se_atomic.h

@@ -34,6 +34,7 @@
 
 #include <stdint.h>
 
+
 inline uint32_t se_atomic_inc(volatile uint32_t *mem)
 {
     return __sync_add_and_fetch(mem, 1);

+ 1 - 1
common/inc/internal/se_version.h

@@ -28,6 +28,6 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  */
-#define STRFILEVER      "2.1.101.42529"
+#define STRFILEVER      "2.1.102.43402"
 #define COPYRIGHT      "Copyright (C) 2018 Intel Corporation"
 

+ 48 - 0
common/inc/sgx_lfence.h

@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011-2018 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 _SGX_LFENCE_H_
+#define _SGX_LFENCE_H_
+
+#define sgx_lfence  __builtin_ia32_lfence
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern void __builtin_ia32_lfence(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_SGX_LFENCE_H_ */
+

+ 8 - 7
common/inc/sgx_trts.h

@@ -63,6 +63,14 @@ int SGXAPI sgx_is_within_enclave(const void *addr, size_t size);
 int SGXAPI sgx_is_outside_enclave(const void *addr, size_t size);
 
 
+/* sgx_is_enclave_crashed()
+ * Return Value:
+ *      1 - the enclave state is crashed.
+ *      0 - the enclave state is not crashed.
+ */
+int SGXAPI sgx_is_enclave_crashed(void);
+
+
 /* sgx_read_rand()
  * Parameters:
  *      rand - the buffer to receive the random number
@@ -74,13 +82,6 @@ int SGXAPI sgx_is_outside_enclave(const void *addr, size_t size);
 */
 sgx_status_t SGXAPI sgx_read_rand(unsigned char *rand, size_t length_in_bytes);
 
-/* sgx_is_enclave_crashed()
- * Return Value:
- *      1 - The global enclave state is crashed.
- *      0 - The global enclave state is not crashed.
- */
-int SGXAPI sgx_is_enclave_crashed(void);
-
 #ifdef __cplusplus
 }
 #endif

+ 4 - 4
download_prebuilt.sh

@@ -33,13 +33,13 @@
 
 top_dir=`dirname $0`
 out_dir=$top_dir
-optlib_name=optimized_libs-2.1.1.tar
-ae_file_name=prebuilt-ae-2.1.1.tar
-server_url_path=https://download.01.org/intel-sgx/linux-2.1.1/
+optlib_name=optimized_libs-2.1.2.tar
+ae_file_name=prebuilt-ae-2.1.2.tar
+server_url_path=https://download.01.org/intel-sgx/linux-2.1.2/
 server_optlib_url=$server_url_path/$optlib_name
 server_ae_url=$server_url_path/$ae_file_name
 optlib_sha256=239cae39f87934d56c4eb919a4702c6ac82c19957b9a8d56c02b10eb4e27f573
-ae_sha256=f95589a69a8a8767815fe3bccf32bac5c9709022f9f32ae1a726b1da7955200b
+ae_sha256=55ebe53b724d66f045c4c05020610d0fc7771d5dc58aaff270ccaee82b5d0d65
 rm -rf $out_dir/$optlib_name
 wget $server_optlib_url -P $out_dir 
 if [ $? -ne 0 ]; then

+ 1 - 0
linux/installer/common/sdk/BOMs/sdk_base.txt

@@ -7,6 +7,7 @@ DeliveryName	InstallName	FileCheckSum	FileFeature	FileOwner
 <deliverydir>/common/inc/sgx_dh.h	<installdir>/package/include/./sgx_dh.h	0	main	STP
 <deliverydir>/common/inc/sgx_ecp_types.h	<installdir>/package/include/./sgx_ecp_types.h	0	main	STP
 <deliverydir>/common/inc/sgx_edger8r.h	<installdir>/package/include/./sgx_edger8r.h	0	main	STP
+<deliverydir>/common/inc/sgx_lfence.h	<installdir>/package/include/./sgx_lfence.h	0	main	STP
 <deliverydir>/common/inc/sgx_eid.h	<installdir>/package/include/./sgx_eid.h	0	main	STP
 <deliverydir>/common/inc/sgx_error.h	<installdir>/package/include/./sgx_error.h	0	main	STP
 <deliverydir>/common/inc/sgx.h	<installdir>/package/include/./sgx.h	0	main	STP

+ 3 - 0
psw/ae/aesm_service/source/aesm_wrapper/src/AESMQueueManager.cpp

@@ -79,6 +79,9 @@ void AESMQueueManager::enqueue(RequestData* requestData)
                 AESM_LOG_ERROR("Malformed request received (May be forged for attack)");
         }
 
+    }else {
+        delete requestData;
+        AESM_LOG_ERROR("Malformed request received (May be forged for attack)");
     }
 }
 

+ 3 - 9
psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp

@@ -116,15 +116,9 @@ void CAESMServer::doWork()
         std::list<ICommunicationSocket*>::const_iterator it = socketsWithData.begin();
 
         for (;it != socketsWithData.end(); ++it) {
-            try {
-                IAERequest  *request = m_transporter->receiveRequest(*it);  
-                RequestData *requestData = new RequestData(*it, request);   //deleted by the AESMWorkerThread after response is sent
-
-                m_queueManager->enqueue(requestData);
-
-            } catch (SockDisconnectedException& e) {
-                m_selector->removeSocket(*it);
-            }
+            IAERequest  *request = m_transporter->receiveRequest(*it);  
+            RequestData *requestData = new RequestData(*it, request);   //deleted by the AESMWorkerThread after response is sent
+            m_queueManager->enqueue(requestData);
         }
     }
 

+ 2 - 2
psw/ae/aesm_service/source/upse/uecall_bridge.cpp

@@ -295,7 +295,7 @@ ae_error_t tGenM7
         AESM_DBG_INFO("start gen M7 ...");
         // Call to get size required of output buffers
         seStatus = ecall_tGenM7(_enclaveID, &retval, pS1, 
-            (const EPID11_SIG_RL*)pSigRL, pOcspResp, nOcspResp, 
+            (const EPID11_SIG_RL*)pSigRL, sigRL.getSize(), pOcspResp, nOcspResp,
             pVCert, nVCert, (pairing_blob_t*)pPairingBlob,
             nS2, pS2, &nS2);
         BREAK_IF_TRUE( (SGX_ERROR_ENCLAVE_LOST == seStatus), retval, PSE_PR_ENCLAVE_LOST_ERROR);
@@ -346,7 +346,7 @@ ae_error_t tVerifyM8
 
         // Call to get size required of output buffers
         seStatus = ecall_tVerifyM8(_enclaveID, &retval, pS3, nS3,
-            (EPID11_PRIV_RL*)pPrivRL, pPairingBlob, &uNewPairing);
+       (const EPID11_PRIV_RL*)pPrivRL, privRL.getSize(), pPairingBlob, &uNewPairing);
         BREAK_IF_TRUE( (SGX_ERROR_ENCLAVE_LOST == seStatus), retval, PSE_PR_ENCLAVE_LOST_ERROR);
         BREAK_IF_TRUE( (SGX_SUCCESS != seStatus), retval, PSE_PR_ENCLAVE_BRIDGE_ERROR);
 

+ 1 - 4
psw/ae/common/inc/ICommunicationSocket.h

@@ -35,16 +35,13 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-class SockDisconnectedException : public std::exception {
-};
-
 class ICommunicationSocket{
     public:
         virtual ~ICommunicationSocket() {}
 
         //init returns true on successful connection
         virtual bool  init() =0;
-        virtual char* readRaw(ssize_t length) = 0; //throw(SockDisconnectedException) = 0;
+        virtual char* readRaw(ssize_t length) = 0;
         virtual ssize_t  writeRaw(const char* data, ssize_t length) = 0;
         virtual int   getSockDescriptor() = 0;
         virtual bool wasTimeoutDetected() = 0;

+ 2 - 2
psw/ae/common/inc/ITransporter.h

@@ -42,8 +42,8 @@ class ITransporter{
         virtual ~ITransporter() {};
 
         virtual uae_oal_status_t transact(IAERequest* request, IAEResponse* response, uint32_t timeout) = 0;
-        virtual IAERequest* receiveRequest(ICommunicationSocket* sock) = 0; //throw(SockDisconnectedException) = 0;
-        virtual uae_oal_status_t sendResponse(IAEResponse* response, ICommunicationSocket* sock) = 0;
+        virtual IAERequest* receiveRequest(ICommunicationSocket* sock) = 0;
+        virtual void sendResponse(IAEResponse* response, ICommunicationSocket* sock) = 0;
 
     protected:
 };

+ 1 - 1
psw/ae/common/inc/NonBlockingUnixCommunicationSocket.h

@@ -44,7 +44,7 @@ public:
     ~NonBlockingUnixCommunicationSocket();
 
     bool  init();
-    char* readRaw(ssize_t length); //throw(SockDisconnectedException) = 0;
+    char* readRaw(ssize_t length);
     ssize_t  writeRaw(const char* data, ssize_t length);
     int   getSockDescriptor();
     bool wasTimeoutDetected();

+ 3 - 3
psw/ae/common/inc/SocketTransporter.h

@@ -49,8 +49,8 @@ class SocketTransporter : public ITransporter{
 
         uae_oal_status_t transact(IAERequest* request, IAEResponse* response, uint32_t timeout = 0);
 
-        IAERequest* receiveRequest(ICommunicationSocket* sock);// throw(SockDisconnectedException);
-        uae_oal_status_t sendResponse(IAEResponse* response, ICommunicationSocket* sock);
+        IAERequest* receiveRequest(ICommunicationSocket* sock);
+        void sendResponse(IAEResponse* response, ICommunicationSocket* sock);
 
     protected:
         ISocketFactory*         mSocketFactory;
@@ -58,7 +58,7 @@ class SocketTransporter : public ITransporter{
 
     private:
         uae_oal_status_t sendMessage(AEMessage *message, ICommunicationSocket* sock);
-        AEMessage* receiveMessage(ICommunicationSocket* sock);// throw(SockDisconnectedException);
+        AEMessage* receiveMessage(ICommunicationSocket* sock);
         SocketTransporter& operator=(const SocketTransporter&);
         SocketTransporter(const SocketTransporter&);
 };

+ 1 - 1
psw/ae/common/inc/UnixCommunicationSocket.h

@@ -43,7 +43,7 @@ class UnixCommunicationSocket : public ICommunicationSocket{
 
         virtual bool init();
         virtual ssize_t writeRaw(const char* data, ssize_t length);
-        virtual char* readRaw(ssize_t length);// throw(SockDisconnectedException);
+        virtual char* readRaw(ssize_t length);
 
         void disconnect();
         virtual int getSockDescriptor();

+ 24 - 14
psw/ae/common/src/NonBlockingUnixCommunicationSocket.cpp

@@ -229,17 +229,22 @@ char* NonBlockingUnixCommunicationSocket::readRaw(ssize_t length)
         memset((char*)mEvents, 0, MAX_EVENTS * sizeof(struct epoll_event));
 
     }while (total_read < length);
-
-    event.data.fd = mSocket;
-    event.events = EPOLLET;
-    registerSocket = epoll_ctl (mEpoll, EPOLL_CTL_MOD, mSocket, &event);
-    if (registerSocket != 0)
+    if(mSocket!=-1)
     {
-        disconnect();
+        event.data.fd = mSocket;
+        event.events = EPOLLET;
+        registerSocket = epoll_ctl (mEpoll, EPOLL_CTL_MOD, mSocket, &event);
+        if (registerSocket != 0)
+        {
+            disconnect();
 
-        if (NULL != recBuf)
-            delete [] recBuf;
-        return NULL;
+            if (NULL != recBuf)
+                delete [] recBuf;
+            return NULL;
+        }
+    }else
+    {
+    // disconnected, recBuf is set NULL when disconnect() is called.
     }
 
     return recBuf;
@@ -407,11 +412,16 @@ ssize_t  NonBlockingUnixCommunicationSocket::writeRaw(const char* data, ssize_t
     }
     while(total_write < length);
 
-    event.data.fd = mSocket;
-    event.events = EPOLLET;
-    registerSocket = epoll_ctl (mEpoll, EPOLL_CTL_MOD, mSocket, &event);
-    if (registerSocket != 0)
-    {
+    if(mSocket!=-1){
+        event.data.fd = mSocket;
+        event.events = EPOLLET;
+        registerSocket = epoll_ctl (mEpoll, EPOLL_CTL_MOD, mSocket, &event);
+        if (registerSocket != 0)
+        {
+            return -1;
+        }
+    }else
+    {//disconneded due to error.
         return -1;
     }
 

+ 8 - 3
psw/ae/common/src/SocketTransporter.cpp

@@ -137,9 +137,14 @@ IAERequest* SocketTransporter::receiveRequest(ICommunicationSocket* sock) {
     return request;
 }
 
-uae_oal_status_t SocketTransporter::sendResponse(IAEResponse* response, ICommunicationSocket* sock) {
+void SocketTransporter::sendResponse(IAEResponse* response, ICommunicationSocket* sock) {
+    if (response == NULL)
+        return;
     AEMessage * message = response->serialize();
-    uae_oal_status_t retVal = sendMessage(message, sock);
+    if (sendMessage(message, sock) != UAE_OAL_SUCCESS)
+    {
+        //server can't do anything, ignore status
+    }
     delete message;
-    return retVal;
+    return;
 }

BIN
psw/ae/data/prebuilt/le_prod_css.bin


+ 7 - 0
psw/ae/pce/pce.cpp

@@ -33,6 +33,7 @@
 #include "pce_t.c"
 #include "aeerror.h"
 #include "sgx_utils.h"
+#include "sgx_lfence.h"
 #include "ipp_wrapper.h"
 #include "byte_order.h"
 #include "pve_qe_common.h"
@@ -92,6 +93,12 @@ uint32_t get_pc_info(const sgx_report_t* report,
         return AE_INVALID_PARAMETER;
     }
 
+	//
+	// if this mispredicts, we might go past end of 
+	// public_key below
+	//
+    sgx_lfence();
+
     *encrypted_ppid_out_size = RSA_MOD_SIZE;//output size is same as public key module size
     if (encrypted_ppid_buf_size < RSA_MOD_SIZE){
         return AE_INSUFFICIENT_DATA_IN_BUFFER;

+ 1 - 1
psw/ae/pse/pse_op/config.xml

@@ -3,7 +3,7 @@
     <ProvisionKey>0</ProvisionKey>
     <LaunchKey>0</LaunchKey>
     <ProdID>0x2</ProdID>
-    <ISVSVN>6</ISVSVN>
+    <ISVSVN>7</ISVSVN>
     <TCSNum>1</TCSNum>
     <TCSMinPool>0</TCSMinPool>
     <TCSPolicy>1</TCSPolicy>

+ 37 - 2
psw/ae/pse/pse_op/pse_op.cpp

@@ -45,6 +45,7 @@
 #include "dh.h"
 #include "pairing_blob.h"
 #include "monotonic_counter_database_sqlite_bin_hash_tree_utility.h"
+#include "sgx_lfence.h"
 
 #define BREAK_ON_MALLOC_FAIL(ptr,ret_val)           if (!(ptr)) {ret_val=PSE_OP_INTERNAL_ERROR;break;}
 
@@ -179,12 +180,25 @@ ae_error_t invoke_service_wrapper (
         return PSE_OP_PARAMETER_ERROR;
     }
 
-    if (req_msg_size < sizeof(pse_message_t)            // make sure the header is inside enclave
-        || pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t)   // check potential overflow
+	//
+	// make sure the header is inside enclave
+	//
+	if (req_msg_size < sizeof(pse_message_t))
+	{
+		return PSE_OP_PARAMETER_ERROR;
+	}
+
+	//
+	// if this mispredicts, we might overflow below
+	//
+	sgx_lfence();
+
+	if (pse_req_msg->payload_size > UINT32_MAX - sizeof(pse_message_t)   // check potential overflow
         || req_msg_size != sizeof(pse_message_t) + pse_req_msg->payload_size)
     {
         return PSE_OP_PARAMETER_ERROR;
     }
+
     if (resp_msg_size < sizeof(pse_message_t)           // make sure the header is inside enclave
         || pse_req_msg->exp_resp_size > UINT32_MAX - sizeof(pse_message_t)   // check potential overflow
         || resp_msg_size < sizeof(pse_message_t) + pse_req_msg->exp_resp_size)
@@ -192,6 +206,14 @@ ae_error_t invoke_service_wrapper (
         return PSE_OP_PARAMETER_ERROR;
     }
 
+	//
+	// put LFENCE here mostly for pse_req_msg->payload_size 
+	// check above. I don't think we use 
+	// pse_req_msg->exp_resp_size to calculate 
+	// any pointers.
+	//
+	sgx_lfence();
+
     pse_session_t* session = sid2session(pse_req_msg->session_id);
 
     // ephemeral session must have been established 
@@ -242,6 +264,11 @@ ae_error_t invoke_service_wrapper (
         int service_count = static_cast<int>(sizeof(service_handler) / sizeof(service_handler_t));
         for (i = 0; i < service_count; i++)
         {
+			//
+			// might mispredict the end of the loop
+			//
+			sgx_lfence();
+
             if (req_hdr->service_id == service_handler[i].service_id &&
                 req_hdr->service_cmd == service_handler[i].service_cmd)
             {
@@ -257,6 +284,14 @@ ae_error_t invoke_service_wrapper (
                     ae_ret = PSE_OP_INTERNAL_ERROR;
                     goto clean_up;
                 }
+
+				//
+				// in case payload_size, req_size comparisons
+				// mispredict
+				//
+				sgx_lfence();
+
+
                 // serve the request
                 op_ret = service_handler[i].srv_pfn(session->isv_attributes, req, resp);
                 if(op_ret != OP_SUCCESS)

+ 7 - 0
psw/ae/pse/pse_pr/X509Parser.cpp

@@ -31,6 +31,7 @@
 #include "X509Parser.h"
 #include <cstddef>
 #include "X509_Parser/X509_Interface.h"
+#include "sgx_lfence.h"
 #include <string.h>
 #include <stdlib.h>
 #include "byte_order.h"
@@ -90,6 +91,12 @@ UINT32 X509Parser::ParseGroupCertificate
                         ) {
                             break;
         }
+
+		//
+		// attacker can control pGroupCertVlr->VlrHeader.Length 
+		//
+		sgx_lfence();
+
         UINT32 X509GroupCertificateSize = static_cast<UINT32>(pGroupCertVlr->VlrHeader.Length -
             sizeof(pGroupCertVlr->VlrHeader) - pGroupCertVlr->VlrHeader.PaddedBytes);
 

+ 58 - 0
psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp

@@ -31,6 +31,7 @@
 
 
 #include "X509Cert.h"
+#include "sgx_lfence.h"
 #include <cstddef>
 #include <assert.h>
 
@@ -521,6 +522,12 @@ STATUS ParseCertificateChain(UINT8 *pCertChain,
 
     while(pCert < pCertChainEnd)
     {
+		//
+		// very, very doubtful we get here speculatively
+		// with NULL pCert, but between that and possibility
+		// of looping too many times, add lfence
+		//
+		sgx_lfence();
 
         /* certificate always starts with a sequence followed by length at offset 1. */
         CHECK_ID(*pCert, DER_ENCODING_SEQUENCE_ID);
@@ -1503,6 +1510,13 @@ static STATUS sessMgrParseDerCert
             return X509_INVALID_SIGNATURE;
         }
 
+		//
+		// if signature verifies, then length values in cert
+		// are ok wrt Spectre
+		//
+		sgx_lfence();
+
+
         /**** End Early Signature Verification *****/
 
         //  Next Field : Version (Optional field with explicit tagging)
@@ -2079,6 +2093,12 @@ static STATUS ParseInteger(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDataBuffer* Da
         return X509_STATUS_ENCODING_ERROR;
 
     // MSB must be zero for positive integer. Error if MSB is not zero and we expect positive
+
+	//
+	// current_ptr could be out of bounds (speculatively)
+	//
+	sgx_lfence();
+
     if(MustBePositive && (*current_ptr & 0x80))
         return X509_STATUS_ENCODING_ERROR;
 
@@ -2828,6 +2848,13 @@ static STATUS ParseOID(UINT8 **ppCurrent, UINT8 *pEnd, UINT32 *EnumVal, const UI
         /* We have a encoded list of hard coded OIDs that we support in an array. Just compare the OID with that array. */
         for(i = 0;i< Max_Entries; i++)
         {
+			//
+			// current_ptr could be out of bounds (speculatively)
+			// and looping one too many times (also speculatively)
+			// would be bad
+			//
+			sgx_lfence();
+
             if(memcmp(current_ptr, OidList, length) == 0){
                 /* We found a match. i is the algorithm number that  the caller is looking for */
                 *EnumVal= i;
@@ -2874,6 +2901,11 @@ static STATUS ParseSignatureValue(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 **pworkb
 
         /* Next Byte is the number of padded. Because this is a signature, we expect the resulting value to be a multiple of 8 bits meaning no padding will be necessery    */
 
+		//
+		// current_ptr could be out of bounds (speculatively)
+		//
+		sgx_lfence();
+
         if(*current_ptr != 0){
             Status = X509_STATUS_ENCODING_ERROR;
             break;
@@ -3387,15 +3419,30 @@ static STATUS ParseTime(UINT8 **ppCurrent, UINT8 *pEnd, SessMgrDateTime* DateTim
 */
 static STATUS DecodeLength(UINT8* Buffer, UINT8* BufferEnd, UINT32* Length, UINT8* EncodingBytes)
 {
+	//
+	// some spectre vulnerabilities in here
+	//
+	// stop speculation here to make sure Buffer[0] is in bounds
+	// before reading
+	//
+	sgx_lfence();
     if(Buffer[0] < 0x81){
         /* length is only one byte */
         *Length = Buffer[0];
         *EncodingBytes = 1;
     } else if ((Buffer[0] == 0x81) && (&Buffer[1] < BufferEnd)) {
+		//
+		// lfence for Buffer[1]
+		//
+		sgx_lfence();
         /* length is two bytes */
         *Length = Buffer[1];
         *EncodingBytes = 2;
     } else if ((Buffer[0] == 0x82) && (&Buffer[2] < BufferEnd)) {
+		//
+		// lfence for Buffer[2]
+		//
+		sgx_lfence();
         /* length is 3 bytes */
         *Length = (Buffer[1] << 8) + Buffer[2];
         *EncodingBytes = 3;
@@ -3411,6 +3458,11 @@ static STATUS DecodeLength(UINT8* Buffer, UINT8* BufferEnd, UINT32* Length, UINT
         if ((Buffer + tempLength) > BufferEnd) {
             return X509_STATUS_ENCODING_ERROR;
         }
+		//
+		// X.509 cert includes length fields that
+		// an attacker can control
+		//
+		sgx_lfence();
     }
     else {
         return X509_STATUS_ENCODING_ERROR;
@@ -3485,6 +3537,12 @@ static STATUS ParseIdAndLength(UINT8 **ppCurrent, UINT8 *pEnd, UINT8 ExpectedId,
     UINT8*  current_ptr = *ppCurrent;
     STATUS  Status;
 
+	//
+	// could be here speculatively and
+	// current_ptr be out of bounds
+	//
+	sgx_lfence();
+
     if(*current_ptr != ExpectedId){
         if(Optional)
             return X509_STATUS_NOT_FOUND;

+ 1 - 1
psw/ae/pse/pse_pr/config.xml

@@ -3,7 +3,7 @@
     <ProvisionKey>0</ProvisionKey>
     <LaunchKey>0</LaunchKey>
     <ProdID>0x2</ProdID>
-    <ISVSVN>6</ISVSVN>
+    <ISVSVN>7</ISVSVN>
     <TCSNum>1</TCSNum>
     <TCSMinPool>0</TCSMinPool>
     <TCSPolicy>1</TCSPolicy>

+ 4 - 2
psw/ae/pse/pse_pr/include/t_long_term_pairing.h

@@ -61,7 +61,8 @@ public:
     ae_error_t GenM7
     (
         /*in */ const SIGMA_S1_MESSAGE*      pS1,
-        /*in */ const EPID11_SIG_RL*         pSigRL, 
+        /*in */ const EPID11_SIG_RL*           pSigRL,
+        /*in */ uint32_t  nTotalLen_SigRL, 
         /*in */ const uint8_t*               pOcspResp, 
         /*in */ uint32_t  nLen_OcspResp, 
         /*in */ const uint8_t*               pVerifierCert,
@@ -76,7 +77,8 @@ public:
     (
         /*in */ const SIGMA_S3_MESSAGE*      pS3, 
         /*in */ uint32_t  nLen_S3,
-        /*in */ const EPID11_PRIV_RL*        pPrivRL,
+        /*in */ const EPID11_PRIV_RL*          pPrivRL,
+        /*in */ uint32_t  nTotalLen_PrivRL, 
         /*i/o*/ pairing_blob_t* pPairingBlob,
         /*out*/ bool*     pbNewPairing
     );

+ 6 - 28
psw/ae/pse/pse_pr/pse_pr.cpp

@@ -51,33 +51,6 @@
 
 static TEpidSigma11Verifier*  s_pVerifier = NULL;
 
-//length to copy into enclave
-size_t get_sigRL_size(const EPID11_SIG_RL* pSigRL)
-{
-    uint32_t nEntries = 0;
-    uint32_t nSize = 0;
-
-    if (TEpidSigma11Verifier::get_sigRL_info(pSigRL, nEntries, nSize))
-        return nSize;
-    else
-        //invalid sigRL
-        return sizeof(EPID11_SIG_RL);
-}
-
-//length to copy into enclave
-size_t get_privRL_size(const EPID11_PRIV_RL* pPrivRL)
-{
-    uint32_t nEntries = 0;
-    uint32_t nSize = 0;
-
-    if (TEpidSigma11Verifier::get_privRL_info(pPrivRL, nEntries, nSize))
-        return nSize;
-    else
-        //invalid privRL
-        return sizeof(EPID11_PRIV_RL);
-}
-
-
 ae_error_t ecall_tPrepareForCertificateProvisioning
 (
     /*in */ UINT64  nonce64,
@@ -103,6 +76,7 @@ ae_error_t ecall_tGenM7
 (
     /*in */ const SIGMA_S1_MESSAGE*      pS1,
     /*in */ const EPID11_SIG_RL*         pSigRL, 
+    /*in */ uint32_t  nTotalLen_SigRL,
     /*in */ const uint8_t*               pOcspResp, 
     /*in */ uint32_t  nLen_OcspResp,
     /*in */ const uint8_t*               pVerifierCert,
@@ -125,6 +99,7 @@ ae_error_t ecall_tGenM7
         status = s_pVerifier->GenM7(
             pS1, 
             pSigRL, 
+            nTotalLen_SigRL,
             pOcspResp, nLen_OcspResp, 
             pVerifierCert, nLen_VerifierCert,
             pPairingBlob,
@@ -145,6 +120,7 @@ ae_error_t ecall_tVerifyM8
     /*in */ const SIGMA_S3_MESSAGE*      pS3,
     /*in */ uint32_t  nLen_S3,
     /*in */ const EPID11_PRIV_RL*        pPrivRL,
+    /*in */ uint32_t  nTotalLen_PrivRL,
     /*out*/       pairing_blob_t* pPairingBlob,
     /*out*/ uint8_t*  puNewPairing
 )
@@ -157,7 +133,9 @@ ae_error_t ecall_tVerifyM8
 
         status = s_pVerifier->VerifyM8(
             pS3, nLen_S3, 
-            pPrivRL, pPairingBlob,
+            pPrivRL, 
+            nTotalLen_PrivRL,
+            pPairingBlob,
             (bool*)puNewPairing);
         BREAK_IF_FAILED(status);
 

+ 4 - 2
psw/ae/pse/pse_pr/pse_pr.edl

@@ -56,7 +56,8 @@ enclave
         public ae_error_t ecall_tGenM7
         (
             [in, count=1]                       const SIGMA_S1_MESSAGE*      pS1,
-            [in, sizefunc=get_sigRL_size]       const EPID11_SIG_RL*         pSigRL,
+            [in, size=nTotalLen_SigRL]          const EPID11_SIG_RL*           pSigRL,
+                                                uint32_t    nTotalLen_SigRL,
             [in, size=nTotalLen_OcspResp]       const uint8_t*               pOcspResp, 
                                                 uint32_t    nTotalLen_OcspResp,
             [in, size=nTotalLen_VerifierCert]   const uint8_t*               pVerifierCert,
@@ -71,7 +72,8 @@ enclave
         (
             [in, size=nTotalLen_S3]             const SIGMA_S3_MESSAGE*       pS3, 
                                                 uint32_t    nTotalLen_S3,
-            [in, sizefunc=get_privRL_size]      const EPID11_PRIV_RL*         pPrivRL,
+            [in, size=nTotalLen_PrivRL]         const EPID11_PRIV_RL*           pPrivRL,
+                                                uint32_t    nTotalLen_PrivRL,
             [in, out, count=1]                  pairing_blob_t*  pPairingBlob,
             [out, count=1]                      uint8_t*    bNewPairing
         );

+ 62 - 2
psw/ae/pse/pse_pr/t_long_term_pairing.cpp

@@ -34,6 +34,7 @@
 #include "sgx_trts.h"
 #include "sgx_utils.h"
 #include "sgx_tseal.h"
+#include "sgx_lfence.h"
 
 #include "t_long_term_pairing.h"
 #include "prepare_hash_sha256.h"
@@ -241,6 +242,7 @@ ae_error_t TEpidSigma11Verifier::GenM7
     (
     /*in */ const SIGMA_S1_MESSAGE*      pS1,
     /*in */ const EPID11_SIG_RL*         pSigRL,
+    /*in */ uint32_t  nTotalLen_SigRL, 
     /*in */ const UINT8*                 pOcspResp,
     /*in */ UINT32 nLen_OcspResp,
     /*in */ const UINT8*                 pVerifierCert,
@@ -262,6 +264,17 @@ ae_error_t TEpidSigma11Verifier::GenM7
 
     do
     {
+        if (pSigRL != NULL)
+        {
+            BREAK_IF_TRUE((nTotalLen_SigRL < sizeof(EPID11_SIG_RL)), status, PSE_PR_PARAMETER_ERROR);
+        }
+
+		//
+		// stop speculation in case undersized SigRL (where
+		// access of header would overflow)
+		//
+		sgx_lfence();
+
         ae_error_t tmp_status;
 
         // sigRL_size allows for the sigRL header, array of RL entries, and signature at the end
@@ -269,7 +282,13 @@ ae_error_t TEpidSigma11Verifier::GenM7
         uint32_t sigRL_size = 0;
         bResult = TEpidSigma11Verifier::get_sigRL_info(pSigRL, sigRL_entries, sigRL_size);
         BREAK_IF_FALSE((bResult), status, PSE_PR_BAD_POINTER_ERROR);
+        BREAK_IF_TRUE((nTotalLen_SigRL < sigRL_size), status, PSE_PR_PARAMETER_ERROR);
 
+	// sigRL_size is based on number of entries, which is basically
+	// an input to the enclave
+	//
+	sgx_lfence();
+	
         BREAK_IF_TRUE((STATE_GENM7 != m_nextState), status, PSE_PR_CALL_ORDER_ERROR);
 
 
@@ -515,6 +534,7 @@ ae_error_t TEpidSigma11Verifier::VerifyM8
     /*in */ const SIGMA_S3_MESSAGE*      pS3,
     /*in */ UINT32 nLen_S3,
     /*in */ const EPID11_PRIV_RL*        pPrivRL,
+    /*in */ uint32_t  nTotalLen_PrivRL, 
     /*in, out*/ pairing_blob_t* pPairingBlob,
     /*out*/ bool* pbNewPairing
     )
@@ -526,8 +546,8 @@ ae_error_t TEpidSigma11Verifier::VerifyM8
 
     //
     // This is misleading, PR_PSE_T isn't part of SIGMA, S3, it's part of our (sgx) m8.
-    // Also, min_s3 is a very low lower bound. m8 message (not s3) is hmac || taskinfo || g**a || group cert || epid sig || sig-rl || pr_pse.
-    // Group cert, EPID sig and SigRL are variable-length, but they have fixed length parts so lengths of the fixed
+    // Also, min_s3 is a very low lower bound. m8 message (not s3) is hmac || taskinfo || g**a || group cert || epid sig || pr_pse.
+    // Group cert and EPID sig are variable-length, but they have fixed length parts so lengths of the fixed
     // length parts could be included here.
     //
     const size_t min_s3 = sizeof(SIGMA_S3_MESSAGE) + sizeof(PR_PSE_T);
@@ -537,6 +557,17 @@ ae_error_t TEpidSigma11Verifier::VerifyM8
 
     do
     {
+        if (pPrivRL != NULL)
+        {
+            BREAK_IF_TRUE((nTotalLen_PrivRL < sizeof(EPID11_PRIV_RL)), status, PSE_PR_PARAMETER_ERROR);
+        }
+
+		//
+		// stop speculation in case undersized PrivRL (where
+		// access of header would overflow)
+		//
+		sgx_lfence();
+
         ae_error_t tmp_status;
 
         // privRL_size allows for the privRL header, array of RL entries, and signature at the end
@@ -544,6 +575,13 @@ ae_error_t TEpidSigma11Verifier::VerifyM8
         uint32_t privRL_size = 0;
         bResult = TEpidSigma11Verifier::get_privRL_info(pPrivRL, privRL_entries, privRL_size);
         BREAK_IF_FALSE((bResult), status, PSE_PR_BAD_POINTER_ERROR);
+        BREAK_IF_TRUE((nTotalLen_PrivRL < privRL_size), status, PSE_PR_PARAMETER_ERROR);
+
+		//
+	// privRL_size is based on number of entries, which is basically
+	// an input to the enclave
+	//
+	sgx_lfence();
 
         BREAK_IF_TRUE( (STATE_VERIFYM8 != m_nextState), status, PSE_PR_CALL_ORDER_ERROR);
 
@@ -552,6 +590,12 @@ ae_error_t TEpidSigma11Verifier::VerifyM8
         //*********************************************************************
         BREAK_IF_TRUE((NULL == pS3 || nLen_S3 < min_s3), status, PSE_PR_BAD_POINTER_ERROR);
 
+		//
+		// stop speculation so code below doesn't go past end of 
+		// undersized S3
+		//
+		sgx_lfence();
+
         // pPrivRL is allowed to be NULL and will be checked in ValidatePrivRL()
 
         BREAK_IF_TRUE((NULL == pPairingBlob), status, PSE_PR_BAD_POINTER_ERROR);
@@ -831,16 +875,32 @@ ae_error_t TEpidSigma11Verifier::ValidateS3DataBlock(const SIGMA_S3_MESSAGE* pS3
 
     pX = (X509_GROUP_CERTIFICATE_VLR *)(((uint8_t*)pS3) + data_offset);
 
+	//
+	// if above mispredicts and we end up here, then below
+	// can overflow
+	//
+	sgx_lfence();
+
     // Make sure epid signature VLR is within bounds of S3 message allocated in trusted memory
     if ((data_offset + sizeof(EPID_SIGNATURE_VLR) + pX->VlrHeader.Length) >= nLen_S3)
         return PSE_PR_S3_DATA_ERROR;
 
+	//
+	// attacker can control pX->VlrHeader.Length
+	//
+	sgx_lfence();
+
     pE = (EPID_SIGNATURE_VLR*)((UINT8*)(pX) + pX->VlrHeader.Length);
 
     // Make sure epid signature data is within bounds of S3 message allocated in trusted memory
     if ((data_offset + pX->VlrHeader.Length + pE->VlrHeader.Length) >= nLen_S3)
         return PSE_PR_S3_DATA_ERROR;
 
+	//
+	// attacker can control pE->VlrHeader.Length
+	//
+	sgx_lfence();
+
     *X509GroupCertVlr = pX;
     *EpidSigVlr = pE;
 

+ 2 - 1
psw/ae/pve/provision_enclave.cpp

@@ -45,6 +45,7 @@
 #include "provision_msg.h"
 #include "provision_enclave_t.c"
 #include "sgx_utils.h"
+#include "sgx_lfence.h"
 #include "aeerror.h"
 
 ae_error_t pve_error_2_ae_error(pve_status_t pve_error)
@@ -141,7 +142,7 @@ uint32_t proc_prov_msg2_data_wrapper(
     // for user_check SigRL input
     // based on sigrl_size input parameter
     //
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     if((sigrl==NULL&&sigrl_size!=0)||
         (sigrl!=NULL&&sigrl_size==0)){

+ 10 - 1
psw/ae/pve/provision_msg2.cpp

@@ -36,6 +36,7 @@
 #include "pve_qe_common.h"
 #include "pek_pub_key.h"
 #include "byte_order.h"
+#include "sgx_lfence.h"
 #include <string.h>
 #include <stdlib.h>
 
@@ -75,6 +76,13 @@ static pve_status_t prov_msg2_proc_sigrl_header(const external_memory_byte_t* em
         //sigrl with too small size, it should contains at least sigrl header and the ECDSA Signature
         return PVEC_SIGRL_INTEGRITY_CHECK_ERROR;//signature not checked so integrity error
     }
+
+	//
+	// if we mispredict above, we might overflow
+	// when we access SigRL header
+	//
+	sgx_lfence();
+
     pve_memcpy_in(&msg3_parm->sigrl_header, emp_sigrl, sigrl_header_size);//copy in sigrl header
     msg3_parm->emp_sigrl_sig_entries = emp_sigrl+sigrl_header_size;
     pve_status = verify_sigrl_cert_type_version(&msg3_parm->sigrl_header);
@@ -195,6 +203,7 @@ ret_point:
 //@return PVEC_SUCCESS on success and error code on failure
 //   PVEC_EPID_BLOB_ERROR is returned if msg2_blob_input.old_epid_data_blob is required but it is invalid and
 //   msg2_blob_input.previous_pi should be filled in by a Previous platform information from ProvMsg2
+
 pve_status_t proc_prov_msg2_data(const proc_prov_msg2_blob_input_t *msg2_blob_input,    //Input data of the ProvMsg2
                             uint8_t performance_rekey_used,             // if in performance rekey mode
                             const external_memory_byte_t *emp_sigrl,  //optional sigrl inside external memory
@@ -248,7 +257,7 @@ pve_status_t proc_prov_msg2_data(const proc_prov_msg2_blob_input_t *msg2_blob_in
             // for user_check SigRL input
             // based on n2 field in SigRL
             //
-            __builtin_ia32_lfence();
+            sgx_lfence();
 
             if( PVEC_SUCCESS!=ret )
                 goto ret_point;

+ 25 - 3
psw/ae/qe/quoting_enclave.cpp

@@ -42,6 +42,7 @@
 #include "sgx_quote.h"
 #include "aeerror.h"
 #include "sgx_tseal.h"
+#include "sgx_lfence.h"
 #include "epid_pve_type.h"
 #include "sgx_utils.h"
 #include "ipp_wrapper.h"
@@ -180,7 +181,8 @@ static ae_error_t verify_blob_internal(
         memset(&secret_epid_data.member_precomp_data, 0, sizeof(secret_epid_data.member_precomp_data));
         is_old_format = 1;
         //PrivKey of secret_epid_data are both in offset 0 so that we need not move it
-    }else{//SDK version format
+	}
+	else{//SDK version format
         memcpy(&plaintext_epid_data, &plaintext_old_format, sizeof(plaintext_epid_data));
     }
 
@@ -306,6 +308,12 @@ uint32_t verify_blob(
     if(SGX_TRUSTED_EPID_BLOB_SIZE_SDK != blob_size)
         return QE_PARAMETER_ERROR;
 
+	//
+	// if we mispredict here and blob_size is too
+	// small, we might overflow
+	//
+	sgx_lfence();
+
     if(!sgx_is_within_enclave(p_blob, blob_size))
         return QE_PARAMETER_ERROR;
 
@@ -927,10 +935,24 @@ uint32_t get_quote(
        || (!quote_size)
        || ((NULL != emp_sig_rl) && (sig_rl_size < sizeof(se_sig_rl_t)
                                                   + 2 * SE_ECDSA_SIGN_SIZE))
+
+		//
+		// this size check could mispredict and cause us to
+		// overflow, but we have an lfence below
+		// that's safe to use for this case
+		//
+
        || ((NULL == emp_sig_rl) && (sig_rl_size != 0)))
         return QE_PARAMETER_ERROR;
     if(SGX_TRUSTED_EPID_BLOB_SIZE_SDK != blob_size)
         return QE_PARAMETER_ERROR;
+
+	//
+	// this could mispredict and cause us to
+	// overflow, but we have an lfence below
+	// that's safe to use for this case
+	//
+
     if(SGX_LINKABLE_SIGNATURE != quote_type
        && SGX_UNLINKABLE_SIGNATURE != quote_type)
         return QE_PARAMETER_ERROR;
@@ -948,7 +970,7 @@ uint32_t get_quote(
     // for user_check SigRL input
     // based on quote_size input parameter
     //
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     if(!sgx_is_outside_enclave(emp_quote, quote_size))
         return QE_PARAMETER_ERROR;
@@ -1084,7 +1106,7 @@ uint32_t get_quote(
     // for user_check SigRL input
     // based on n2 field in SigRL
     //
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     /* Copy the data in the report into quote body. */
     memset(emp_quote, 0, quote_size);

+ 0 - 2
sdk/edger8r/linux/Ast.ml

@@ -64,13 +64,11 @@ type attr_value =
 
 type ptr_size = {
   ps_size     : attr_value option;
-  ps_sizefunc : string     option;
   ps_count    : attr_value option;
 }
 
 let empty_ptr_size = {
   ps_size     = None;
-  ps_sizefunc = None;
   ps_count    = None;
 }
 

+ 184 - 132
sdk/edger8r/linux/CodeGen.ml

@@ -287,13 +287,28 @@ let mk_member_decl (ty: Ast.atype) (declr: Ast.declarator) =
  * in the marshaling data structure to keep the pass-by-address scheme
  * as in the C programming language.
 *)
-let mk_ms_member_decl (pt: Ast.parameter_type) (declr: Ast.declarator) =
+let mk_ms_member_decl (pt: Ast.parameter_type) (declr: Ast.declarator) (isecall: bool) =
   let aty = Ast.get_param_atype pt in
   let tystr = Ast.get_tystr aty in
   let ptr = if is_foreign_array pt then "* " else "" in
   let field = mk_ms_member_name declr.Ast.identifier in
+  (* String attribute is available for in/inout both ecall and ocall.
+   * For ocall ,strlen is called in trusted proxy ocde, so no need to defense it.
+   *)
+  let need_str_len_var (pt: Ast.parameter_type) =
+    match pt with
+    Ast.PTVal _        -> false
+    | Ast.PTPtr(_, pa) ->
+    if pa.Ast.pa_isstr || pa.Ast.pa_iswstr then
+        match pa.Ast.pa_direction with
+        Ast.PtrInOut | Ast.PtrIn ->  if isecall then true else false
+        | _ -> false
+    else false
+  in
+  let str_len = if need_str_len_var pt then sprintf "\tsize_t %s_len;\n" field else ""
+  in
   let dmstr = get_array_dims declr.Ast.array_dims in
-    sprintf "\t%s%s %s%s;\n" tystr ptr field dmstr
+    sprintf "\t%s%s %s%s;\n%s" tystr ptr field dmstr str_len
 
 (* Generate data structure definition *)
 let gen_comp_def (st: Ast.composite_type) =
@@ -315,26 +330,26 @@ let get_param_tystr (pt: Ast.parameter_type) =
   Ast.get_tystr (Ast.get_param_atype pt)
 
 (* Generate marshaling structure definition *)
-let gen_marshal_struct (fd: Ast.func_decl) (errno: string) =
+let gen_marshal_struct (fd: Ast.func_decl) (errno: string) (isecall: bool) =
     let member_list_str = errno ^
     let new_param_list = List.map conv_array_to_ptr fd.Ast.plist in
     List.fold_left (fun acc (pt, declr) ->
-            acc ^ mk_ms_member_decl pt declr) "" new_param_list in
+            acc ^ mk_ms_member_decl pt declr isecall) "" new_param_list in
   let struct_name = mk_ms_struct_name fd.Ast.fname in
     match fd.Ast.rtype with
         (* A function w/o return value and parameters doesn't need
            a marshaling struct. *)
         Ast.Void -> if fd.Ast.plist = [] && errno = "" then ""
                     else mk_struct_decl member_list_str struct_name
-      | _ -> let rv_str = mk_ms_member_decl (Ast.PTVal fd.Ast.rtype) retval_declr
+      | _ -> let rv_str = mk_ms_member_decl (Ast.PTVal fd.Ast.rtype) retval_declr isecall
              in mk_struct_decl (rv_str ^ member_list_str) struct_name
 
 let gen_ecall_marshal_struct (tf: Ast.trusted_func) =
-    gen_marshal_struct tf.Ast.tf_fdecl ""
+    gen_marshal_struct tf.Ast.tf_fdecl "" true
 
 let gen_ocall_marshal_struct (uf: Ast.untrusted_func) =
     let errno_decl = if uf.Ast.uf_propagate_errno then "\tint ocall_errno;\n" else "" in
-    gen_marshal_struct uf.Ast.uf_fdecl errno_decl
+    gen_marshal_struct uf.Ast.uf_fdecl errno_decl false
 
 (* Check whether given parameter is `const' specified. *)
 let is_const_ptr (pt: Ast.parameter_type) =
@@ -576,42 +591,6 @@ let gen_theader_preemble (guard: string) (inclist: string) =
 #include \"sgx_edger8r.h\" /* for sgx_ocall etc. */\n\n" in
     grd_hdr ^ inc_exp ^ inclist ^ "\n" ^ common_macros
 
-
-(* Generate function prototype for functions used by `sizefunc' attribute. *)
-let gen_sizefunc_proto out_chan (ec: enclave_content) =
-  let tfunc_decls = tf_list_to_fd_list ec.tfunc_decls in
-  let ufunc_decls = uf_list_to_fd_list ec.ufunc_decls in
-
-  let dict = Hashtbl.create 4 in
-  let get_sizefunc_proto s =
-    let (pt, ns) = Hashtbl.find dict s in
-    let tmpdeclr = { Ast.identifier = "val"; Ast.array_dims = ns; } in
-      sprintf "size_t %s(const %s);\n" s (get_typed_declr_str pt tmpdeclr)
-  in
-
-  let add_item (fname: string) (ty: Ast.atype * int list) =
-    try
-      let v = Hashtbl.find dict fname
-      in
-        if v <> ty then
-          failwithf "`%s' requires different parameter types" fname
-    with Not_found -> Hashtbl.add dict fname ty
-  in
-  let fill_dict (pd: Ast.pdecl) =
-    let (pt, declr) = pd in
-      match pt with
-          Ast.PTVal _           -> ()
-        | Ast.PTPtr(aty, pattr) ->
-            match pattr.Ast.pa_size.Ast.ps_sizefunc with
-                Some s -> add_item s (aty, declr.Ast.array_dims)
-              | _ -> ()
-  in
-    List.iter (fun (fd: Ast.func_decl) ->
-                 List.iter fill_dict fd.Ast.plist) (tfunc_decls @ ufunc_decls);
-    Hashtbl.iter (fun x y ->
-                    output_string out_chan (get_sizefunc_proto x)) dict;
-    output_string out_chan "\n"
-
 (* Generate trusted header for enclave *)
 let gen_trusted_header (ec: enclave_content) =
   let header_fname = get_theader_name ec.file_shortnm in
@@ -626,7 +605,6 @@ let gen_trusted_header (ec: enclave_content) =
   let out_chan = open_out header_fname in
     output_string out_chan (guard_code ^ "\n");
     List.iter (fun s -> output_string out_chan (s ^ "\n")) comp_def_list;
-    gen_sizefunc_proto out_chan ec;
     List.iter (fun s -> output_string out_chan (s ^ ";\n")) func_proto_list;
     output_string out_chan "\n";
     List.iter (fun s -> output_string out_chan (s ^ ";\n")) func_tproxy_list;
@@ -636,11 +614,13 @@ let gen_trusted_header (ec: enclave_content) =
 (* It generates function invocation expression. *)
 let mk_parm_name_raw (pt: Ast.parameter_type) (declr: Ast.declarator) =
   let cast_expr =
+    let tystr = get_param_tystr pt in
     if Ast.is_array declr && List.length declr.Ast.array_dims > 1
     then
-      let tystr = get_param_tystr pt in
       let dims = get_array_dims (List.tl declr.Ast.array_dims) in
         sprintf "(%s (*)%s)"  tystr dims
+    else if is_const_ptr pt then
+        sprintf "(const %s)" tystr
     else ""
   in
     cast_expr ^ mk_parm_accessor declr.Ast.identifier
@@ -672,19 +652,14 @@ let mk_parm_name_ext (pt: Ast.parameter_type) (declr: Ast.declarator) =
 
 let gen_func_invoking (fd: Ast.func_decl)
                       (mk_parm_name: Ast.parameter_type -> Ast.declarator -> string) =
-  let gen_parm_str pt declr =
-    let parm_name = mk_parm_name pt declr in
-    let tystr = get_param_tystr pt in
-      if is_const_ptr pt then sprintf "(const %s)%s" tystr parm_name else parm_name
-  in
     match fd.Ast.plist with
       [] -> sprintf "%s();" fd.Ast.fname
     | (pt, (declr : Ast.declarator)) :: ps ->
         sprintf "%s(%s);"
           fd.Ast.fname
-          (let p0 = gen_parm_str pt declr in
+          (let p0 = mk_parm_name pt declr in
              List.fold_left (fun acc (pty, dlr) ->
-                               acc ^ ", " ^ gen_parm_str pty dlr) p0 ps)
+                               acc ^ ", " ^ mk_parm_name pty dlr) p0 ps)
 
 (* Generate untrusted bridge code for a given untrusted function. *)
 let gen_func_ubridge (file_shortnm: string) (ufunc: Ast.untrusted_func) =
@@ -725,6 +700,14 @@ let fill_ms_field (isptr: bool) (pd: Ast.pdecl) =
   let gen_setup_foreign_array aty =
     sprintf "%s%s%s = (%s *)&%s[0];"
       ms_struct_val accessor ms_member_name (Ast.get_tystr aty) param_name
+  in
+  let gen_setup_foreign_str aty =
+    sprintf "%s%s%s_len = %s ? strlen(%s) + 1 : 0;"
+      ms_struct_val accessor ms_member_name param_name param_name
+  in
+  let gen_setup_foreign_wstr aty =
+    sprintf "%s%s%s_len = %s ? (wcslen(%s) + 1) * sizeof(wchar_t) : 0;"
+      ms_struct_val accessor ms_member_name param_name param_name
   in
     if declr.Ast.array_dims = [] then
       match pt with
@@ -732,6 +715,10 @@ let fill_ms_field (isptr: bool) (pd: Ast.pdecl) =
         | Ast.PTPtr(aty, pattr) ->
             if pattr.Ast.pa_isary
             then gen_setup_foreign_array aty
+            else if pattr.Ast.pa_isstr
+            then assignment_str true aty ^ "\n\t" ^ gen_setup_foreign_str aty
+            else if pattr.Ast.pa_iswstr
+            then assignment_str true aty ^ "\n\t" ^ gen_setup_foreign_wstr aty
             else
               if pattr.Ast.pa_rdonly then assignment_str true aty
               else assignment_str false aty
@@ -785,7 +772,8 @@ let mk_check_ptr (name: string) (lenvar: string) =
 (* Pointer to marshaling structure should never be NULL. *)
 let mk_check_pms (fname: string) =
   let lenvar = sprintf "sizeof(%s)" (mk_ms_struct_name fname)
-  in sprintf "\t%s(%s, %s);\n" "CHECK_REF_POINTER" ms_ptr_name lenvar
+  in sprintf "\t%s(%s, %s);%s" "CHECK_REF_POINTER" ms_ptr_name lenvar
+        "\n\t//\n\t// fence after pointer checks\n\t//\n\tsgx_lfence();\n"
 
 (* Generate code to get the size of the pointer. *)
 let gen_ptr_size (ty: Ast.atype) (pattr: Ast.ptr_attr) (name: string) (get_parm: string -> string) =
@@ -802,37 +790,32 @@ let gen_ptr_size (ty: Ast.atype) (pattr: Ast.ptr_attr) (name: string) (get_parm:
         Ast.AString s -> sprintf "%s * %s" (get_parm s) size_str
       | Ast.ANumber n -> sprintf "%d * %s" n size_str in
 
-  let mk_len_sizefunc s = sprintf "((%s) ? %s(%s) : 0)" parm_name s parm_name in
-
-  (* Note, during the parsing stage, we already eliminated the case that
-   * user specified both 'size' and 'sizefunc' attribute.
-   *)
-  let do_attribute (pattr: Ast.ptr_attr) =
-    let do_ps_attribute (sattr: Ast.ptr_size) =
-      let size_str =
-        match sattr.Ast.ps_size with
+  let do_ps_attribute (sattr: Ast.ptr_size) =
+    let size_str =
+      match sattr.Ast.ps_size with
           Some a -> mk_len_size a
-        | None   ->
-          match sattr.Ast.ps_sizefunc with
-            None   -> sprintf "sizeof(*%s)" parm_name
-          | Some a -> mk_len_sizefunc a
+        | None   -> sprintf "sizeof(*%s)" parm_name
       in
-        match sattr.Ast.ps_count with
-          None   -> size_str
-        | Some a -> mk_len_count a size_str
+      match sattr.Ast.ps_count with
+        None   -> size_str
+      | Some a -> mk_len_count a size_str
     in
-      if pattr.Ast.pa_isstr then
-        sprintf "%s ? strlen(%s) + 1 : 0" parm_name parm_name
-      else if pattr.Ast.pa_iswstr then
-        sprintf "%s ? (wcslen(%s) + 1) * sizeof(wchar_t) : 0" parm_name parm_name
-      else
-        do_ps_attribute pattr.Ast.pa_size
-  in
     sprintf "size_t %s = %s;\n"
-      len_var
-      (if pattr.Ast.pa_isary
-       then sprintf "sizeof(%s)" (Ast.get_tystr ty)
-       else do_attribute pattr)
+          len_var
+          (if pattr.Ast.pa_isary then
+             sprintf "sizeof(%s)" (Ast.get_tystr ty)
+           else
+             (* genrerate ms_parm_len only for ecall with string/wstring in _t.c.*)
+             if (pattr.Ast.pa_isstr || pattr.Ast.pa_iswstr) && parm_name <> name then
+                 sprintf "%s_len " (mk_parm_accessor name)
+               else
+                 (* genrerate strlen(param)/wcslen(param) only for ocall with string/wstring in _t.c.*)
+                 if pattr.Ast.pa_isstr then
+                   sprintf "%s ? strlen(%s) + 1 : 0" parm_name parm_name
+                 else 
+                   if pattr.Ast.pa_iswstr then
+                     sprintf "%s ? (wcslen(%s) + 1) * sizeof(wchar_t) : 0" parm_name parm_name
+                   else do_ps_attribute pattr.Ast.pa_size)
 
 (* Find the data type of a parameter. *)
 let find_param_type (name: string) (plist: Ast.pdecl list) =
@@ -855,23 +838,18 @@ let gen_check_tbridge_length_overflow (plist: Ast.pdecl list) =
         Ast.AString s -> mk_tmp_var s
       | Ast.ANumber n -> sprintf "%d" n in
 
-    let mk_len_sizefunc s = sprintf "((%s) ? %s(%s) : 0)" tmp_ptr_name s tmp_ptr_name in
-
     let gen_check_overflow cnt size_str =
       let if_statement =
         match cnt with
             Ast.AString s -> sprintf "\tif (%s != 0 &&\n\t\t(size_t)%s > (SIZE_MAX / %s)) {\n" size_str (mk_tmp_var s) size_str
           | Ast.ANumber n -> sprintf "\tif (%s != 0 &&\n\t\t%d > (SIZE_MAX / %s)) {\n" size_str n size_str
       in
-        sprintf "%s\t\tstatus = SGX_ERROR_INVALID_PARAMETER;\n\t\tgoto err;\n\t}" if_statement
+        sprintf "%s\t\treturn SGX_ERROR_INVALID_PARAMETER;\n\t}" if_statement
     in
       let size_str =
         match attr.Ast.pa_size.Ast.ps_size with
           Some a -> mk_len_size a
-        | None   ->
-          match attr.Ast.pa_size.Ast.ps_sizefunc with
-            None   -> sprintf "sizeof(*%s)" tmp_ptr_name
-          | Some a -> mk_len_sizefunc a
+        | None   -> sprintf "sizeof(*%s)" tmp_ptr_name
       in
         match attr.Ast.pa_size.Ast.ps_count with
           None   -> ""
@@ -897,11 +875,16 @@ let gen_check_tbridge_ptr_parms (plist: Ast.pdecl list) =
   in
   let new_param_list = List.map conv_array_to_ptr plist
   in
+  let pointer_checkings =
     List.fold_left
       (fun acc (pty, declr) ->
          match pty with
              Ast.PTVal _         -> acc
            | Ast.PTPtr(ty, attr) -> acc ^ gen_check_ptr ty attr declr) "" new_param_list
+  in
+  if pointer_checkings = "" then ""
+  else pointer_checkings ^ "\n\t//\n\t// fence after pointer checks\n\t//\n\tsgx_lfence();\n"
+
 
 (* If a foreign type is a readonly pointer, we cast it to 'void*' for memcpy() and free() *)
 let mk_in_ptr_dst_name (rdonly: bool) (ptr_name: string) =
@@ -920,28 +903,24 @@ let gen_parm_ptr_direction_pre (plist: Ast.pdecl list) =
     let len_var     = mk_len_var name in
     let in_ptr_dst_name = mk_in_ptr_dst_name attr.Ast.pa_rdonly in_ptr_name in
     let tmp_ptr_name= mk_tmp_var name in
-
-    let mk_len_count v  =
-      match v with
-        None -> ""
-        |Some a ->
-          match a with
-            Ast.AString s -> sprintf "_tmp_%s * " s
-            | Ast.ANumber n -> sprintf "%d * " n
-    in
-    let check_sizefunc_with_cnt_ptr v fn =
-      sprintf "\t\t/* check whether the pointer is modified. */\n\
-\t\tif (%s%s(%s) != %s) {\n\
-\t\t\tstatus = SGX_ERROR_INVALID_PARAMETER;\n\
-\t\t\tgoto err;\n\
-\t\t}\n\n\
-\t\t//\n\t\t// fence after final sizefunc check\n\t\t//\n\t\t__builtin_ia32_lfence();\n\n" (mk_len_count v) fn in_ptr_name len_var
-    in
     let malloc_and_copy pre_indent =
       match attr.Ast.pa_direction with
           Ast.PtrIn | Ast.PtrInOut ->
+            let wstr_len_check =
+              if attr.Ast.pa_iswstr then
+                let wstr_len_check_template  = [
+                  sprintf "\n\t\tif (%s %% sizeof(wchar_t) != 0)" len_var;
+                  "\t\t{";
+                  "\t\t\tstatus = SGX_ERROR_UNEXPECTED;";
+                  "\t\t\tgoto err;";
+                  "\t\t}";
+                  ]
+                  in
+                  List.fold_left (fun acc s -> acc ^ s ^ "\n") "" wstr_len_check_template
+                else ""
+            in
             let code_template = [
-              sprintf "if (%s != NULL && %s != 0) {" tmp_ptr_name len_var;
+              sprintf "if (%s != NULL && %s != 0) {%s" tmp_ptr_name len_var wstr_len_check;
               sprintf "\t%s = (%s)malloc(%s);" in_ptr_name in_ptr_type len_var;
               sprintf "\tif (%s == NULL) {" in_ptr_name;
               "\t\tstatus = SGX_ERROR_OUT_OF_MEMORY;";
@@ -952,16 +931,30 @@ let gen_parm_ptr_direction_pre (plist: Ast.pdecl list) =
             in
             let s1 = List.fold_left (fun acc s -> acc ^ pre_indent ^ s ^ "\n") "" code_template in
             let s2 =
-              if attr.Ast.pa_isstr
-              then sprintf "%s\t\t%s[%s - 1] = '\\0';\n" s1 in_ptr_name len_var
-              else if attr.Ast.pa_iswstr
-              then sprintf "%s\t\t%s[(%s - sizeof(wchar_t))/sizeof(wchar_t)] = (wchar_t)0;\n" s1 in_ptr_name len_var
+              if attr.Ast.pa_isstr then
+                let code_template2  = [
+                  sprintf "\t%s[%s - 1] = '\\0';" in_ptr_name len_var;
+                  sprintf "\tif (%s != strlen(%s) + 1)" len_var in_ptr_name;
+                  "\t{";
+                  "\t\tstatus = SGX_ERROR_UNEXPECTED;";
+                  "\t\tgoto err;";
+                  "\t}";
+                  ]
+                in
+                s1 ^ List.fold_left (fun acc s -> acc ^ pre_indent ^ s ^ "\n") "" code_template2
+              else if attr.Ast.pa_iswstr then
+                let code_template3  = [
+                  sprintf "\t%s[(%s - sizeof(wchar_t))/sizeof(wchar_t)] = (wchar_t)0;" in_ptr_name len_var;
+                  sprintf "\tif ( %s / sizeof(wchar_t) != wcslen(%s) + 1)" len_var in_ptr_name;
+                  "\t{";
+                  "\t\tstatus = SGX_ERROR_UNEXPECTED;";
+                  "\t\tgoto err;";
+                  "\t}";
+                  ]
+                in
+                s1 ^ List.fold_left (fun acc s -> acc ^ pre_indent ^ s ^ "\n") "" code_template3
               else s1 in
-            let s3 =
-              match attr.Ast.pa_size.Ast.ps_sizefunc with
-                  None   -> s2
-                | Some s -> sprintf "%s\n%s\n" s2 (check_sizefunc_with_cnt_ptr attr.Ast.pa_size.Ast.ps_count s)
-            in sprintf "%s\t}\n" s3
+            sprintf "%s\t}\n" s2
         | Ast.PtrOut ->
             let code_template = [
               sprintf "if (%s != NULL && %s != 0) {" tmp_ptr_name len_var;
@@ -994,12 +987,37 @@ let gen_parm_ptr_direction_post (plist: Ast.pdecl list) =
       match attr.Ast.pa_direction with
           Ast.PtrIn -> sprintf "\tif (%s) free(%s);\n" in_ptr_name in_ptr_dst_name
         | Ast.PtrInOut | Ast.PtrOut ->
-            sprintf "\tif (%s) {\n\t\tmemcpy(%s, %s, %s);\n\t\tfree(%s);\n\t}\n"
-                    in_ptr_name
-                    (mk_tmp_var name)
-                    in_ptr_name
-                    len_var
-                    in_ptr_name
+          if attr.Ast.pa_isstr then
+                let code_template  = [
+                  sprintf "\tif (%s)" in_ptr_name;
+                  "\t{";
+                  sprintf "\t\t%s[%s - 1] = '\\0';" in_ptr_name len_var;
+                  sprintf "\t\t%s = strlen(%s) + 1;" len_var in_ptr_name;
+                  sprintf "\t\tmemcpy((void*)%s, %s, %s);" (mk_tmp_var name) in_ptr_name len_var;
+                  sprintf "\t\tfree(%s);" in_ptr_name;
+                  "\t}";
+                  ]
+                in
+                List.fold_left (fun acc s -> acc ^ s ^ "\n") "" code_template
+              else if attr.Ast.pa_iswstr then
+                let code_template  = [ 
+                  sprintf "\tif (%s)" in_ptr_name;
+                  "\t{";
+                  sprintf "\t\t%s[(%s - sizeof(wchar_t))/sizeof(wchar_t)] = (wchar_t)0;" in_ptr_name len_var;
+                  sprintf "\t\t%s = (wcslen(%s) + 1) * sizeof(wchar_t);" len_var in_ptr_name;
+                  sprintf "\t\tmemcpy((void*)%s, %s, %s);" (mk_tmp_var name) in_ptr_name len_var;
+                  sprintf "\t\tfree(%s);" in_ptr_name;
+                  "\t}";
+                  ]
+                in  
+                List.fold_left (fun acc s -> acc ^ s ^ "\n") "" code_template
+            else
+              sprintf "\tif (%s) {\n\t\tmemcpy(%s, %s, %s);\n\t\tfree(%s);\n\t}\n"
+                      in_ptr_name
+                      (mk_tmp_var name)
+                      in_ptr_name
+                      len_var
+                      in_ptr_name
         | _ -> ""
   in List.fold_left
        (fun acc (pty, declr) ->
@@ -1068,11 +1086,21 @@ let ptr_has_direction (pt: Ast.parameter_type) =
     | Ast.PTPtr(_, a) -> a.Ast.pa_direction <> Ast.PtrNoDirection
 
 let tbridge_mk_parm_name_ext (pt: Ast.parameter_type) (declr: Ast.declarator) =
+  let cast_expr =
+    let tystr = get_param_tystr pt in
+    if Ast.is_array declr && List.length declr.Ast.array_dims > 1
+    then
+      let dims = get_array_dims (List.tl declr.Ast.array_dims) in
+        sprintf "(%s (*)%s)" tystr dims
+    else if is_const_ptr pt then
+      sprintf "(const %s)" tystr
+    else ""
+  in
   if is_in_param_cache declr.Ast.identifier || (is_ptr pt && (not (is_foreign_array pt)))
   then
     if ptr_has_direction pt
-    then mk_in_var declr.Ast.identifier
-    else mk_tmp_var declr.Ast.identifier
+    then cast_expr ^ mk_in_var declr.Ast.identifier
+    else cast_expr ^ mk_tmp_var declr.Ast.identifier
   else mk_parm_name_ext pt declr
 
 let mk_parm_name_tbridge (pt: Ast.parameter_type) (declr: Ast.declarator) =
@@ -1149,14 +1177,13 @@ let gen_func_tbridge (fd: Ast.func_decl) (dummy_var: string) =
       in
         sprintf "%s%s%s\t%s\n\t%s\n%s" func_open local_vars dummy_var check_pms invoke_func func_close
     else
-      sprintf "%s%s\t%s\n%s\n%s%s\n%s\n%s\n\t%s\n%s\n%s\n%s"
+      sprintf "%s%s\t%s\n%s\n%s%s\n%s\n\t%s\n%s\n%s\n%s"
         func_open
         (mk_check_pms fd.Ast.fname)
         declare_ms_ptr
         local_vars
         (gen_check_tbridge_length_overflow fd.Ast.plist)
         (gen_check_tbridge_ptr_parms fd.Ast.plist)
-        "\n\t//\n\t// fence after pointer checks\n\t//\n\t__builtin_ia32_lfence();\n"
         (gen_parm_ptr_direction_pre fd.Ast.plist)
         (if fd.Ast.rtype <> Ast.Void then update_retval else invoke_func)
         (gen_err_mark fd.Ast.plist)
@@ -1171,12 +1198,8 @@ let tproxy_fill_ms_field (pd: Ast.pdecl) =
     match pt with
         Ast.PTVal _ -> fill_ms_field true pd
       | Ast.PTPtr(ty, attr) ->
-        let is_ary = (Ast.is_array declr || attr.Ast.pa_isary) in
-        let tystr = sprintf "%s%s" (get_param_tystr pt) (if is_ary then "*" else "") in
-          if is_ary && is_ptr_type ty then
-            sprintf "\n#pragma message(\"Pointer array `%s' in trusted proxy `\"\
-               __FUNCTION__ \"' is dangerous. No code generated.\")\n" name
-          else
+              let is_ary = (Ast.is_array declr || attr.Ast.pa_isary) in
+              let tystr = sprintf "%s%s" (get_param_tystr pt) (if is_ary then "*" else "") in
               if not attr.Ast.pa_chkptr (* [user_check] specified *)
               then sprintf "%s = SGX_CAST(%s, %s);" parm_accessor tystr name
               else
@@ -1301,7 +1324,35 @@ let gen_func_tproxy (ufunc: Ast.untrusted_func) (idx: int) =
       let name = declr.Ast.identifier in
         match attr.Ast.pa_direction with
             Ast.PtrInOut | Ast.PtrOut ->
-              sprintf "\tif (%s) memcpy((void*)%s, __tmp_%s, %s);\n" name name name (mk_len_var name)
+              if attr.Ast.pa_isstr then
+                let code_template  = [
+                  sprintf "\tif (%s)" name;
+                  "\t{";
+                  sprintf "\t\tsize_t __tmp%s;" (mk_len_var name);
+                  sprintf "\t\tmemcpy((void*)%s, __tmp_%s, %s);"  name name (mk_len_var name);
+                  sprintf "\t\t((char*)%s)[%s - 1] = '\\0';" name (mk_len_var name);
+                  sprintf "\t\t__tmp%s = strlen(%s) + 1;" (mk_len_var name) name;
+                  sprintf "\t\tmemset(%s +__tmp%s - 1, 0, %s -__tmp%s);" name (mk_len_var name) (mk_len_var name) (mk_len_var name);
+                  "\t}";
+                  ]
+                in
+                List.fold_left (fun acc s -> acc ^ s ^ "\n") "" code_template
+              else if attr.Ast.pa_iswstr then
+                let code_template  = [ 
+                  sprintf "\tif (%s)" name;
+                  "\t{";
+                  sprintf "\t\tsize_t __tmp%s;" (mk_len_var name);
+                  sprintf "\t\tmemcpy((void*)%s, __tmp_%s, %s);"  name name (mk_len_var name);
+                  sprintf "\t\t((wchar_t*)%s)[(%s - sizeof(wchar_t))/sizeof(wchar_t)] = (wchar_t)0;" name (mk_len_var name);
+                  sprintf "\t\t__tmp%s = (wcslen(%s) + 1) * sizeof(wchar_t);" (mk_len_var name) name;
+                  sprintf "\t\tmemset(((uint8_t*)%s) + __tmp%s - sizeof(wchar_t), 0, %s -__tmp%s);" name (mk_len_var name) (mk_len_var name) (mk_len_var name);
+                  "\t}";
+                  ]
+                in  
+                List.fold_left (fun acc s -> acc ^ s ^ "\n") "" code_template
+              else
+                sprintf "\tif (%s) memcpy((void*)%s, __tmp_%s, %s);\n" name name name (mk_len_var name)
+
           | _ -> ""
     in List.fold_left (fun acc (pty, declr) ->
              match pty with
@@ -1381,7 +1432,8 @@ let gen_untrusted_source (ec: enclave_content) =
 let gen_trusted_source (ec: enclave_content) =
   let code_fname = get_tsource_name ec.file_shortnm in
   let include_hd = "#include \"" ^ get_theader_short_name ec.file_shortnm ^ "\"\n\n\
-#include \"sgx_trts.h\" /* for sgx_ocalloc, sgx_is_outside_enclave */\n\n\
+#include \"sgx_trts.h\" /* for sgx_ocalloc, sgx_is_outside_enclave */\n\
+#include \"sgx_lfence.h\" /* for sgx_lfence */\n\n\
 #include <errno.h>\n\
 #include <string.h> /* for memcpy etc */\n\
 #include <stdlib.h> /* for malloc/free etc */\n\

+ 95 - 29
sdk/edger8r/linux/Parser.mly

@@ -47,9 +47,13 @@ let get_string_from_attr (v: Ast.attr_value) (err_func: int -> string) =
       Ast.AString s -> s
     | Ast.ANumber n -> err_func n
 
-(* Check whether 'size' or 'sizefunc' is specified. *)
+(* Check whether 'size' is specified. *)
 let has_size (sattr: Ast.ptr_size) =
-  sattr.Ast.ps_size <> None || sattr.Ast.ps_sizefunc <> None
+  sattr.Ast.ps_size <> None
+  
+(* Check whether 'count' is specified. *)
+let has_count (sattr: Ast.ptr_size) =
+  sattr.Ast.ps_count <> None
 
 (* Pointers can have the following attributes:
  *
@@ -59,9 +63,6 @@ let has_size (sattr: Ast.ptr_size) =
  * 'count'    - indicates how many of items is managed by the pointer
  *              e.g. count = 100, count = n ('n' is a parameter);
  *
- * 'sizefunc' - use a function to compute the size of the pointer.
- *              e.g. sizefunc = get_ptr_size
- *
  * 'string'   - indicate the pointer is managing a C string;
  * 'wstring'  - indicate the pointer is managing a wide char string.
  *
@@ -74,9 +75,9 @@ let has_size (sattr: Ast.ptr_size) =
  * 'in'       - the pointer is used as input
  * 'out'      - the pointer is used as output
  *
- * Note that 'size' and 'sizefunc' are mutual exclusive (but they can
- * be used together with 'count'.  'string' and 'wstring' indicates 'isptr',
- * and they cannot use with only an 'out' attribute.
+ * Note that 'size' can be used together with 'count'.
+ * 'string' and 'wstring' indicates 'isptr',
+ * and they cannot be used with only an 'out' attribute.
  *)
 let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
   let get_new_dir (cds: string) (cda: Ast.ptr_direction) (old: Ast.ptr_direction) =
@@ -85,19 +86,28 @@ let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
     else if old = cda           then failwithf "duplicated attribute: `%s'" cds
     else Ast.PtrInOut
   in
+  (* only one 'size' attribute allowed. *)
+  let get_new_size (new_value: Ast.attr_value) (old_ptr_size: Ast.ptr_size) =
+    if has_size old_ptr_size then
+     failwithf "duplicated attribute: `size'"
+    else new_value
+  in
+  (* only one 'count' attribute allowed. *)
+  let get_new_count (new_value: Ast.attr_value) (old_ptr_size: Ast.ptr_size) =
+    if has_count old_ptr_size then
+      failwithf "duplicated attribute: `count'"
+    else new_value
+  in
   let update_attr (key: string) (value: Ast.attr_value) (res: Ast.ptr_attr) =
     match key with
         "size"     ->
-        { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_size  = Some value }}
+        { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_size  = Some(get_new_size value res.Ast.pa_size)}}
       | "count"    ->
-        { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_count = Some value }}
+        { res with Ast.pa_size = { res.Ast.pa_size with Ast.ps_count = Some(get_new_count value res.Ast.pa_size)}}
       | "sizefunc" ->
-        let efn n = failwithf "invalid function name (%d) for `sizefunc'" n in
-        let funcname = get_string_from_attr value efn
-        in { res with Ast.pa_size =
-            { res.Ast.pa_size with Ast.ps_sizefunc = Some funcname }}
-      | "string"  -> { res with Ast.pa_isptr = true; Ast.pa_isstr = true; }
-      | "wstring" -> { res with Ast.pa_isptr = true; Ast.pa_iswstr = true; }
+        failwithf "The attribute 'sizefunc' is deprecated. Please use 'size' attribute instead."
+      | "string"  -> { res with Ast.pa_isstr = true; }
+      | "wstring" -> { res with Ast.pa_iswstr = true; }
       | "isptr"   -> { res with Ast.pa_isptr = true }
       | "isary"   -> { res with Ast.pa_isary = true }
 
@@ -124,16 +134,13 @@ let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
   in
   let check_invalid_ptr_size (pattr: Ast.ptr_attr) =
     let ps = pattr.Ast.pa_size in
-      if ps.Ast.ps_size <> None && ps.Ast.ps_sizefunc <> None
-      then failwith  "`size' and `sizefunc' cannot be used at the same time"
+      if ps <> Ast.empty_ptr_size && has_str_attr pattr
+      then failwith "size attributes are mutual exclusive with (w)string attribute"
       else
-        if ps <> Ast.empty_ptr_size && has_str_attr pattr
-        then failwith "size attributes are mutual exclusive with (w)string attribute"
-        else
-          if (ps <> Ast.empty_ptr_size || has_str_attr pattr) &&
-            pattr.Ast.pa_direction = Ast.PtrNoDirection
-          then failwith "size/string attributes must be used with pointer direction"
-          else pattr
+        if (ps <> Ast.empty_ptr_size || has_str_attr pattr) &&
+          pattr.Ast.pa_direction = Ast.PtrNoDirection
+        then failwith "size/string attributes must be used with pointer direction"
+        else pattr
   in
   let check_ptr_dir (pattr: Ast.ptr_attr) =
     if pattr.Ast.pa_direction <> Ast.PtrNoDirection && pattr.Ast.pa_chkptr = false
@@ -142,8 +149,8 @@ let get_ptr_attr (attr_list: (string * Ast.attr_value) list) =
       if pattr.Ast.pa_direction = Ast.PtrNoDirection && pattr.Ast.pa_chkptr
       then failwith "pointer/array should have direction attribute or `user_check'"
       else
-        if pattr.Ast.pa_direction = Ast.PtrOut && (has_str_attr pattr || pattr.Ast.pa_size.Ast.ps_sizefunc <> None)
-        then failwith "string/wstring/sizefunc should be used with an `in' attribute"
+        if pattr.Ast.pa_direction = Ast.PtrOut && has_str_attr pattr
+        then failwith "string/wstring should be used with an `in' attribute"
         else pattr
   in
   let check_invalid_ary_attr (pattr: Ast.ptr_attr) =
@@ -234,15 +241,51 @@ let check_ptr_attr (fd: Ast.func_decl) range =
     then failwithf "`%s': void pointer `%s' - buffer size unknown" fname identifier
     else ()
   in
+  let check_string_ptr_size (atype: Ast.atype) (pattr: Ast.ptr_attr) (identifier: string) =
+    if (pattr.Ast.pa_isstr)
+    then
+      match atype with
+      Ast.Ptr(Ast.Char(_)) -> ()
+      | _ -> failwithf "`%s': invalid 'string' attribute - `%s' is not char pointer." fname identifier
+    else
+      if (atype <> Ast.Ptr(Ast.WChar) &&  pattr.Ast.pa_iswstr)
+      then failwithf "`%s': invalid 'wstring' attribute - `%s' is not wchar_t pointer." fname identifier
+      else ()
+  in
+  let check_array_dims (atype: Ast.atype) (pattr: Ast.ptr_attr) (declr: Ast.declarator) =
+    if Ast.is_array declr then
+      if has_size pattr.Ast.pa_size then
+        failwithf "`%s': invalid 'size' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
+      else if has_count pattr.Ast.pa_size then
+        failwithf "`%s': invalid 'count' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
+      else if pattr.Ast.pa_isary then
+        failwithf "`%s': invalid 'isary' attribute - `%s' is explicitly declared array." fname declr.Ast.identifier
+    else ()
+  in
+  let check_pointer_array (atype: Ast.atype) (pattr: Ast.ptr_attr) (declr: Ast.declarator) = 
+    let is_ary = (Ast.is_array declr || pattr.Ast.pa_isary) in
+    let is_ptr  =
+      match atype with
+        Ast.Ptr _ -> true
+      | _         -> pattr.Ast.pa_isptr
+    in
+    if is_ary && is_ptr then
+      failwithf "`%s': Pointer array not allowed - `%s' is a pointer array." fname declr.Ast.identifier 
+    else ()
+  in
   let checker (pd: Ast.pdecl) =
     let pt, declr = pd in
     let identifier = declr.Ast.identifier in
       match pt with
           Ast.PTVal _ -> ()
         | Ast.PTPtr(atype, pattr) ->
-          if atype <> Ast.Ptr(Ast.Void) then check_const pattr identifier
-          else (* 'void' pointer, check there is a size or 'user_check' *)
+          if atype = Ast.Ptr(Ast.Void) then (* 'void' pointer, check there is a size or 'user_check' *)
             check_void_ptr_size pattr identifier
+          else
+            check_pointer_array atype pattr declr;
+            check_const pattr identifier;
+            check_string_ptr_size atype pattr identifier;
+            check_array_dims atype pattr declr
   in
     List.iter checker fd.Ast.plist
 %}
@@ -362,6 +405,29 @@ declarator: Tidentifier    { { Ast.identifier = $1; Ast.array_dims = []; } }
  * to tell whether the identifier is followed by array dimensions.
 */
 param_type: attr_block all_type {
+    let attr = get_ptr_attr $1 in
+    (*check the type is build in type or used defined type.*)
+    let rec is_foreign s =
+      match s with
+        Ast.Ptr(a) -> is_foreign a
+      | Ast.Foreign _ -> true
+      | _ -> false
+    in
+    let is_bare_foreign s =
+      match s with
+      | Ast.Foreign _ -> true
+      | _ -> false
+    in
+    (*'isptr', 'isary', only allowed for bare user defined type.*)
+    (*'readonly' only allowed for user defined type.*)
+    if attr.Ast.pa_isptr && not (is_bare_foreign $2) then
+      failwithf "'isptr', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
+    else if attr.Ast.pa_isary && not (is_bare_foreign $2) then
+      failwithf "'isary', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
+    else if attr.Ast.pa_rdonly && not (is_foreign $2) then
+      failwithf "'readonly', attributes are only for user defined type, not for `%s'." (Ast.get_tystr $2)
+    else if attr.Ast.pa_rdonly && not (attr.Ast.pa_isptr) then
+      failwithf "'readonly' attribute is only used with 'isptr' attribute."    else
     match $2 with
       Ast.Ptr _ -> fun x -> Ast.PTPtr($2, get_ptr_attr $1)
     | _         ->

+ 69 - 59
sdk/sign_tool/SignTool/manage_metadata.cpp

@@ -45,6 +45,7 @@
 #include "section.h"
 #include "se_page_attr.h"
 #include "elf_util.h"
+#include "crypto_wrapper.h"
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -990,20 +991,9 @@ bool update_metadata(const char *path, const metadata_t *metadata, uint64_t meta
 
 #define CONCAT(name, num) name##num
 #define A(num)     CONCAT(metadata, num)
-
-bool print_metadata(const char *path, const metadata_t *metadata)
+static void print_metadata_internal(std::ofstream &meta_ofs, const metadata_t *metadata)
 {
-    assert(path != NULL && metadata != NULL);
-
-    std::ofstream meta_ofs(path, std::ofstream::out | std::ofstream::trunc);
-    if (!meta_ofs.good())
-    {
-        se_trace(SE_TRACE_ERROR, OPEN_FILE_ERROR, path);
-        return false;
-    }
-    
-    meta_ofs << "The metadata information:" << std::endl
-	<< "=========================" << std::endl;
+    assert(metadata != NULL);
     PRINT_ELEMENT(meta_ofs, metadata, magic_num);
     PRINT_ELEMENT(meta_ofs, metadata, version);
     PRINT_ELEMENT(meta_ofs, metadata, size);
@@ -1042,54 +1032,74 @@ bool print_metadata(const char *path, const metadata_t *metadata)
     // css.buffer
     PRINT_ARRAY(meta_ofs, metadata, enclave_css.buffer.q1, SE_KEY_SIZE); 
     PRINT_ARRAY(meta_ofs, metadata, enclave_css.buffer.q2, SE_KEY_SIZE);
+}
 
-    metadata_t *metadata2 = GET_PTR(metadata_t, metadata, metadata->size);
-    if (metadata2->version == META_DATA_MAKE_VERSION(SGX_1_9_MAJOR_VERSION, SGX_1_9_MINOR_VERSION) &&
-        metadata2->magic_num == METADATA_MAGIC)
-    {
-        // Print the compatible metadata info
-        meta_ofs << std::endl << std::endl
-            << "The compatible metadata information: " << std::endl
-            << "====================================" << std::endl;
-        PRINT_ELEMENT(meta_ofs, metadata2, magic_num);
-        PRINT_ELEMENT(meta_ofs, metadata2, version);
-        PRINT_ELEMENT(meta_ofs, metadata2, size);
-        PRINT_ELEMENT(meta_ofs, metadata2, tcs_policy);
-        PRINT_ELEMENT(meta_ofs, metadata2, ssa_frame_size);
-        PRINT_ELEMENT(meta_ofs, metadata2, max_save_buffer_size);
-        PRINT_ELEMENT(meta_ofs, metadata2, desired_misc_select);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_size);
-        PRINT_ELEMENT(meta_ofs, metadata2, attributes.flags);
-        PRINT_ELEMENT(meta_ofs, metadata2, attributes.xfrm);
-    
-        // css.header
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.header.header, 12);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.header.type);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.header.module_vendor);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.header.date);
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.header.header2, 16);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.header.hw_version);
-    
-        // css.key
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.key.modulus, SE_KEY_SIZE);
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.key.exponent, SE_EXPONENT_SIZE);
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.key.signature, SE_KEY_SIZE);
-        
-        // css.body
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.misc_select);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.misc_mask);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.attributes.flags);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.attributes.xfrm);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.attribute_mask.flags);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.attribute_mask.xfrm);
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.body.enclave_hash.m, SGX_HASH_SIZE);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.isv_prod_id);
-        PRINT_ELEMENT(meta_ofs, metadata2, enclave_css.body.isv_svn);
-    
-        // css.buffer
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.buffer.q1, SE_KEY_SIZE); 
-        PRINT_ARRAY(meta_ofs, metadata2, enclave_css.buffer.q2, SE_KEY_SIZE);
+bool print_metadata(const char *path, const metadata_t *metadata)
+{
+    assert(path != NULL && metadata != NULL);
+
+    std::ofstream meta_ofs(path, std::ofstream::out | std::ofstream::trunc);
+    if (!meta_ofs.good())
+    {
+        se_trace(SE_TRACE_ERROR, OPEN_FILE_ERROR, path);
+        return false;
+     }
+
+    meta_ofs << "=============================" << std::endl
+        << "The metadata information:" << std::endl
+        << "=============================" << std::endl;
+    print_metadata_internal(meta_ofs, metadata);
+
+    // Print the compatible metadata info
+    size_t compat_meta_count = 0;
+    do {
+        metadata_t *compatible_metadata = GET_PTR(metadata_t, metadata, metadata->size);
+        if(compatible_metadata == NULL || (compatible_metadata->magic_num == METADATA_MAGIC && compatible_metadata->size == 0))
+        {
+            meta_ofs.close();
+            return false;
+        }
+        if(compatible_metadata->magic_num != METADATA_MAGIC)
+            break;
+
+        compat_meta_count++;
+
+        if(compat_meta_count == 1)
+        {
+            meta_ofs << std::endl << std::endl << std::endl
+                << "====================================" << std::endl
+                << "The compatible metadata information: " << std::endl
+                << "====================================" << std::endl;
+        }
+        meta_ofs << std::endl <<  "Compatible metadata number "
+            << compat_meta_count << ":" << std::endl
+            << "------------------------------" << std::endl;
+        print_metadata_internal(meta_ofs, compatible_metadata);
+
+        metadata = compatible_metadata;
+
+    }while(1);
+
+    typedef struct _mrsigner_t
+    {
+      uint8_t value[SGX_HASH_SIZE];
+    } mrsigner_t;
+    mrsigner_t ms;
+    memset(&ms, 0, sizeof(mrsigner_t));
+    mrsigner_t *mrsigner = &ms;
+    unsigned int signer_len = SGX_HASH_SIZE;
+
+    if(sgx_EVP_Digest(EVP_sha256(), metadata->enclave_css.key.modulus, SE_KEY_SIZE, ms.value, &signer_len) != SGX_SUCCESS)
+    {
+        se_trace(SE_TRACE_ERROR, "ERROR: failed to calculate the mrsigner.\n");
+        meta_ofs.close();
+        return false;
     }
+    meta_ofs << std::endl << std::endl
+        << "===================" << std::endl
+        << "The mrsigner value:" << std::endl
+        << "===================" << std::endl;
+    PRINT_ARRAY(meta_ofs, mrsigner, value, SGX_HASH_SIZE);    
 
     meta_ofs.close();
     return true;

+ 33 - 15
sdk/sign_tool/SignTool/sign_tool.cpp

@@ -85,7 +85,8 @@ typedef enum _file_path_t
     OUTPUT,
     SIG,
     UNSIGNED,
-    DUMPFILE
+    DUMPFILE,
+    CSSFILE
 } file_path_t;
 
 
@@ -564,7 +565,8 @@ static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char
         {"-out", NULL, PAR_REQUIRED},
         {"-sig", NULL, PAR_INVALID},
         {"-unsigned", NULL, PAR_INVALID},
-        {"-dumpfile", NULL, PAR_OPTIONAL}};
+        {"-dumpfile", NULL, PAR_OPTIONAL},
+        {"-cssfile", NULL, PAR_OPTIONAL}};
     param_struct_t params_gendata[] = {
         {"-enclave", NULL, PAR_REQUIRED},
         {"-config", NULL, PAR_OPTIONAL},
@@ -572,7 +574,8 @@ static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char
         {"-out", NULL, PAR_REQUIRED},
         {"-sig", NULL, PAR_INVALID},
         {"-unsigned", NULL, PAR_INVALID},
-        {"-dumpfile", NULL, PAR_INVALID}};
+        {"-dumpfile", NULL, PAR_INVALID},
+        {"-cssfile", NULL, PAR_INVALID}};
     param_struct_t params_catsig[] = {
         {"-enclave", NULL, PAR_REQUIRED},
         {"-config", NULL, PAR_OPTIONAL},
@@ -580,7 +583,8 @@ static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char
         {"-out", NULL, PAR_REQUIRED},
         {"-sig", NULL, PAR_REQUIRED},
         {"-unsigned", NULL, PAR_REQUIRED},
-        {"-dumpfile", NULL, PAR_OPTIONAL}};
+        {"-dumpfile", NULL, PAR_OPTIONAL},
+        {"-cssfile", NULL, PAR_OPTIONAL}};
     param_struct_t params_dump[] = {
         {"-enclave", NULL, PAR_REQUIRED},
         {"-config", NULL, PAR_INVALID},
@@ -588,7 +592,8 @@ static bool cmdline_parse(unsigned int argc, char *argv[], int *mode, const char
         {"-out", NULL, PAR_INVALID},
         {"-sig", NULL, PAR_INVALID},
         {"-unsigned", NULL, PAR_INVALID},
-        {"-dumpfile", NULL, PAR_REQUIRED}};
+        {"-dumpfile", NULL, PAR_REQUIRED},
+        {"-cssfile", NULL, PAR_OPTIONAL}};
 
 
     const char *mode_m[] ={"sign", "gendata","catsig", "dump"};
@@ -939,7 +944,7 @@ static bool generate_compatible_metadata(metadata_t *metadata)
     return ret;
 }
 
-static bool dump_enclave_metadata(const char *enclave_path, const char *dumpfile_path)
+static bool dump_enclave_metadata(const char *enclave_path, const char *dumpfile_path, const char *cssfile)
 {
     assert(enclave_path != NULL && dumpfile_path != NULL);
     
@@ -982,9 +987,17 @@ static bool dump_enclave_metadata(const char *enclave_path, const char *dumpfile
     if(print_metadata(dumpfile_path, metadata) == false)
     {
         close_handle(fh);
-        remove(dumpfile_path);
         return false;
     }
+    if(cssfile != NULL)
+    {
+        if (write_data_to_file(cssfile, std::ios::binary | std::ios::out,
+            (uint8_t *)&(metadata->enclave_css), sizeof(enclave_css_t)) == false)
+        {
+            close_handle(fh);
+            return false;
+        }
+    } 
 
     close_handle(fh);
     return true;
@@ -1045,17 +1058,14 @@ int main(int argc, char* argv[])
     else if(mode == DUMP)
     {
         // dump metadata info
-        if(dump_enclave_metadata(path[DLL], path[DUMPFILE]) == false)
+        if(dump_enclave_metadata(path[DLL], path[DUMPFILE], path[CSSFILE]) == false)
         {
             se_trace(SE_TRACE_ERROR, DUMP_METADATA_ERROR, path[DUMPFILE]);
             goto clear_return;
         }
-        else
-        {
-            se_trace(SE_TRACE_ERROR, SUCCESS_EXIT);
-            res = 0;
-            goto clear_return;
-        }
+        se_trace(SE_TRACE_ERROR, SUCCESS_EXIT);
+        res = 0;
+        goto clear_return;
     }
     
     //Other modes
@@ -1116,6 +1126,13 @@ int main(int argc, char* argv[])
             goto clear_return;
         }
     }
+    if (path[CSSFILE] != NULL)
+    {
+        if (write_data_to_file(path[CSSFILE], std::ios::binary | std::ios::out,
+            (uint8_t *)&(metadata->enclave_css), sizeof(enclave_css_t)) == false)
+            goto clear_return;
+    }
+
     se_trace(SE_TRACE_ERROR, SUCCESS_EXIT);
     res = 0;
 
@@ -1126,7 +1143,8 @@ clear_return:
         remove(path[OUTPUT]);
     if(res == -1 && path[DUMPFILE])
         remove(path[DUMPFILE]);
-    
+    if(res == -1 && path[CSSFILE])
+        remove(path[CSSFILE]);    
 #if OPENSSL_VERSION_NUMBER < 0x10100000L    
     EVP_cleanup();
     CRYPTO_cleanup_all_ex_data();

+ 2 - 2
sdk/sign_tool/SignTool/util_st.h

@@ -57,8 +57,9 @@
     "                       It is a required option for \"catsig\"\n"\
     "   -unsigned           Specify the enclave signing material generated by \"gendata\"\n" \
     "                       It is a required option for \"catsig\"\n" \
-    "   -dumpfile           Specify a file to dump metadata information\n" \
+    "   -dumpfile           Specify a file to dump metadata information (text format)\n" \
     "                       It is a required option for \"dump\"\n" \
+    "   -cssfile            Specify a file to dump the enclave SIGSTRUCT information (binary format)\n" \
     "   -ignore-rel-error   By default, sgx_sign provides an error for enclaves with\n" \
     "                       text relocations. You can ignore the error and continue signing\n" \
     "                       by providing this option. But it is recommended you eliminate the\n" \
@@ -108,7 +109,6 @@
 #define LACK_PUB_KEY_ERROR                  "Public key is required for the \"catsig\" command.\n"
 
 // error message for main()
-#define INIT_IPP_LIBRARY_ERROR              "Failed to initialize the IPP library.\n"
 #define ENCLAVE_ALREADY_SIGNED_ERROR        "The enclave has been signed already.\n"
 #define DUMP_METADATA_ERROR                 "Failed to dump metadata info to file \"%s\".\n."
 #define SUCCESS_EXIT                        "Succeed.\n"

+ 2 - 1
sdk/tkey_exchange/simple_vector.cpp

@@ -33,6 +33,7 @@
 #include <stddef.h>
 #include <stdlib.h>
 #include <string.h>
+#include "sgx_lfence.h"
 #include "simple_vector.h"
 
 //initial vector capacity when fisrt item is added to vector
@@ -103,7 +104,7 @@ errno_t vector_get(const simple_vector* v, uint32_t index, void** data)
         return 1;
         
     //fence after boundary check 
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     *data = v->data[index];
     return 0;

+ 9 - 2
sdk/tkey_exchange/tkey_exchange.cpp

@@ -33,6 +33,7 @@
 #include "sgx_tkey_exchange.h"
 #include "sgx_trts.h"
 #include "sgx_utils.h"
+#include "sgx_lfence.h"
 #include "ecp_interface.h"
 #include "util.h"
 #include "string.h"
@@ -395,8 +396,14 @@ extern "C" sgx_status_t sgx_ra_get_msg3_trusted(
 
     if (!sgx_is_outside_enclave(emp_msg3, msg3_size))
         return SGX_ERROR_INVALID_PARAMETER;
-    //fence after boundary check
-    __builtin_ia32_lfence();
+    //
+    // fence after boundary check 
+    // this also stops speculation in case of 
+    // branch associated 
+    // with sizeof(sgx_ra_msg3_t) + quote_size != msg3_size
+    // mispredicting
+    //
+    sgx_lfence();
 
     sgx_status_t se_ret = SGX_ERROR_UNEXPECTED;
 

+ 2 - 1
sdk/trts/init_enclave.cpp

@@ -42,6 +42,7 @@
 #include "util.h"
 #include "xsave.h"
 #include "sgx_trts.h"
+#include "sgx_lfence.h"
 #include "init_optimized_lib.h"
 #include "trts_internal.h"
 #include "linux/elf_parser.h"
@@ -95,7 +96,7 @@ extern "C" int init_enclave(void *enclave_base, void *ms)
     {
         return -1;
     }
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     const system_features_t sys_features = *info;
     g_sdk_version = sys_features.version;

+ 2 - 1
sdk/trts/trts.cpp

@@ -293,7 +293,7 @@ sgx_status_t sgx_read_rand(unsigned char *rand, size_t length_in_bytes)
 
 int sgx_is_enclave_crashed()
 {
-  return get_enclave_state() == ENCLAVE_CRASHED;
+    return get_enclave_state() == ENCLAVE_CRASHED;
 }
 
 extern uintptr_t __stack_chk_guard;
@@ -306,3 +306,4 @@ int check_static_stack_canary(void *tcs)
     }
     return 0;
 }
+

+ 3 - 2
sdk/trts/trts_ecall.cpp

@@ -37,6 +37,7 @@
 #include "util.h"
 #include "xsave.h"
 #include "sgx_trts.h"
+#include "sgx_lfence.h"
 #include "sgx_spinlock.h"
 #include "global_init.h"
 #include "trts_internal.h"
@@ -56,7 +57,7 @@ static sgx_status_t is_ecall_allowed(uint32_t ordinal)
     }
     thread_data_t *thread_data = get_thread_data();
 
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     if(thread_data->last_sp == thread_data->stack_base_addr)
     {
@@ -245,7 +246,7 @@ static sgx_status_t trts_ecall(uint32_t ordinal, void *ms)
     {
         ecall_func_t func = (ecall_func_t)addr;
 
-        __builtin_ia32_lfence();
+        sgx_lfence();
 
         status = func(ms);
     }

+ 2 - 1
sdk/tseal/tSeal_internal.cpp

@@ -33,6 +33,7 @@
 
 
 #include "sgx_tseal.h"
+#include "sgx_lfence.h"
 #include "tSeal_internal.h"
 #include "sgx_utils.h"
 #include <string.h>
@@ -144,7 +145,7 @@ sgx_status_t sgx_unseal_data_helper(const sgx_sealed_data_t *p_sealed_data, uint
     // know what crypto code does and if plain_text_offset-related 
     // checks mispredict the crypto code could operate on unintended data
     //
-    __builtin_ia32_lfence();
+    sgx_lfence();
 
     err = sgx_rijndael128GCM_decrypt(&seal_key, const_cast<uint8_t *>(p_sealed_data->aes_data.payload),
         decrypted_text_length, p_decrypted_text, &payload_iv[0], SGX_SEAL_IV_SIZE,