diff --git a/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp b/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp index 7c62baf0..f2e18ef2 100644 --- a/SampleCode/SampleEnclave/App/Edger8rSyntax/Pointers.cpp +++ b/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; } diff --git a/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp b/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp index 0b09eaa9..6c35a193 100644 --- a/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp +++ b/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.cpp @@ -36,6 +36,7 @@ #include #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; - } -} diff --git a/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl b/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl index 72ba96d1..bc7c928f 100644 --- a/SampleCode/SampleEnclave/Enclave/Edger8rSyntax/Pointers.edl +++ b/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); - }; /* diff --git a/common/inc/internal/se_atomic.h b/common/inc/internal/se_atomic.h index f4e1e6b8..13ca1d22 100644 --- a/common/inc/internal/se_atomic.h +++ b/common/inc/internal/se_atomic.h @@ -34,6 +34,7 @@ #include + inline uint32_t se_atomic_inc(volatile uint32_t *mem) { return __sync_add_and_fetch(mem, 1); diff --git a/common/inc/internal/se_version.h b/common/inc/internal/se_version.h index e09e94a4..a457b4ff 100644 --- a/common/inc/internal/se_version.h +++ b/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" diff --git a/common/inc/sgx_lfence.h b/common/inc/sgx_lfence.h new file mode 100644 index 00000000..1909e636 --- /dev/null +++ b/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_ */ + diff --git a/common/inc/sgx_trts.h b/common/inc/sgx_trts.h index 774efded..a7e757b9 100644 --- a/common/inc/sgx_trts.h +++ b/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 diff --git a/download_prebuilt.sh b/download_prebuilt.sh index 7b869cde..e8084078 100755 --- a/download_prebuilt.sh +++ b/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 diff --git a/linux/installer/common/sdk/BOMs/sdk_base.txt b/linux/installer/common/sdk/BOMs/sdk_base.txt index 15e2be74..a8e7c53d 100644 --- a/linux/installer/common/sdk/BOMs/sdk_base.txt +++ b/linux/installer/common/sdk/BOMs/sdk_base.txt @@ -7,6 +7,7 @@ DeliveryName InstallName FileCheckSum FileFeature FileOwner /common/inc/sgx_dh.h /package/include/./sgx_dh.h 0 main STP /common/inc/sgx_ecp_types.h /package/include/./sgx_ecp_types.h 0 main STP /common/inc/sgx_edger8r.h /package/include/./sgx_edger8r.h 0 main STP +/common/inc/sgx_lfence.h /package/include/./sgx_lfence.h 0 main STP /common/inc/sgx_eid.h /package/include/./sgx_eid.h 0 main STP /common/inc/sgx_error.h /package/include/./sgx_error.h 0 main STP /common/inc/sgx.h /package/include/./sgx.h 0 main STP diff --git a/psw/ae/aesm_service/source/aesm_wrapper/src/AESMQueueManager.cpp b/psw/ae/aesm_service/source/aesm_wrapper/src/AESMQueueManager.cpp index e8bee11d..e6f663da 100644 --- a/psw/ae/aesm_service/source/aesm_wrapper/src/AESMQueueManager.cpp +++ b/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)"); } } diff --git a/psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp b/psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp index 46dc10a1..e0c0e0ac 100644 --- a/psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp +++ b/psw/ae/aesm_service/source/aesm_wrapper/src/CAESMServer.cpp @@ -116,15 +116,9 @@ void CAESMServer::doWork() std::list::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); } } diff --git a/psw/ae/aesm_service/source/upse/uecall_bridge.cpp b/psw/ae/aesm_service/source/upse/uecall_bridge.cpp index cb7e01e9..fb71e053 100644 --- a/psw/ae/aesm_service/source/upse/uecall_bridge.cpp +++ b/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); diff --git a/psw/ae/common/inc/ICommunicationSocket.h b/psw/ae/common/inc/ICommunicationSocket.h index 140275e1..1815c494 100644 --- a/psw/ae/common/inc/ICommunicationSocket.h +++ b/psw/ae/common/inc/ICommunicationSocket.h @@ -35,16 +35,13 @@ #include #include -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; diff --git a/psw/ae/common/inc/ITransporter.h b/psw/ae/common/inc/ITransporter.h index 5c8d62d7..efd271fa 100644 --- a/psw/ae/common/inc/ITransporter.h +++ b/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: }; diff --git a/psw/ae/common/inc/NonBlockingUnixCommunicationSocket.h b/psw/ae/common/inc/NonBlockingUnixCommunicationSocket.h index 97834e3c..59555afa 100644 --- a/psw/ae/common/inc/NonBlockingUnixCommunicationSocket.h +++ b/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(); diff --git a/psw/ae/common/inc/SocketTransporter.h b/psw/ae/common/inc/SocketTransporter.h index a0a2df67..978b1e22 100644 --- a/psw/ae/common/inc/SocketTransporter.h +++ b/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&); }; diff --git a/psw/ae/common/inc/UnixCommunicationSocket.h b/psw/ae/common/inc/UnixCommunicationSocket.h index ae4296c4..247ef54b 100644 --- a/psw/ae/common/inc/UnixCommunicationSocket.h +++ b/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(); diff --git a/psw/ae/common/src/NonBlockingUnixCommunicationSocket.cpp b/psw/ae/common/src/NonBlockingUnixCommunicationSocket.cpp index d9679989..82581865 100644 --- a/psw/ae/common/src/NonBlockingUnixCommunicationSocket.cpp +++ b/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; } diff --git a/psw/ae/common/src/SocketTransporter.cpp b/psw/ae/common/src/SocketTransporter.cpp index c4c5a592..2fc1ceeb 100644 --- a/psw/ae/common/src/SocketTransporter.cpp +++ b/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; } diff --git a/psw/ae/data/prebuilt/le_prod_css.bin b/psw/ae/data/prebuilt/le_prod_css.bin index eb58216f..5b48e103 100644 Binary files a/psw/ae/data/prebuilt/le_prod_css.bin and b/psw/ae/data/prebuilt/le_prod_css.bin differ diff --git a/psw/ae/pce/pce.cpp b/psw/ae/pce/pce.cpp index a8a5de51..51301cf3 100644 --- a/psw/ae/pce/pce.cpp +++ b/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; diff --git a/psw/ae/pse/pse_op/config.xml b/psw/ae/pse/pse_op/config.xml index f014763f..16969592 100644 --- a/psw/ae/pse/pse_op/config.xml +++ b/psw/ae/pse/pse_op/config.xml @@ -3,7 +3,7 @@ 0 0 0x2 - 6 + 7 1 0 1 diff --git a/psw/ae/pse/pse_op/pse_op.cpp b/psw/ae/pse/pse_op/pse_op.cpp index 638b2107..9f3f5a9c 100644 --- a/psw/ae/pse/pse_op/pse_op.cpp +++ b/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(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) diff --git a/psw/ae/pse/pse_pr/X509Parser.cpp b/psw/ae/pse/pse_pr/X509Parser.cpp index 23934eb5..96919f0a 100644 --- a/psw/ae/pse/pse_pr/X509Parser.cpp +++ b/psw/ae/pse/pse_pr/X509Parser.cpp @@ -31,6 +31,7 @@ #include "X509Parser.h" #include #include "X509_Parser/X509_Interface.h" +#include "sgx_lfence.h" #include #include #include "byte_order.h" @@ -90,6 +91,12 @@ UINT32 X509Parser::ParseGroupCertificate ) { break; } + + // + // attacker can control pGroupCertVlr->VlrHeader.Length + // + sgx_lfence(); + UINT32 X509GroupCertificateSize = static_cast(pGroupCertVlr->VlrHeader.Length - sizeof(pGroupCertVlr->VlrHeader) - pGroupCertVlr->VlrHeader.PaddedBytes); diff --git a/psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp b/psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp index 9f3e2ae8..f9fe4671 100644 --- a/psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp +++ b/psw/ae/pse/pse_pr/X509_Parser/X509_Parser.cpp @@ -31,6 +31,7 @@ #include "X509Cert.h" +#include "sgx_lfence.h" #include #include @@ -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; diff --git a/psw/ae/pse/pse_pr/config.xml b/psw/ae/pse/pse_pr/config.xml index d830ba42..2de9d6e3 100644 --- a/psw/ae/pse/pse_pr/config.xml +++ b/psw/ae/pse/pse_pr/config.xml @@ -3,7 +3,7 @@ 0 0 0x2 - 6 + 7 1 0 1 diff --git a/psw/ae/pse/pse_pr/include/t_long_term_pairing.h b/psw/ae/pse/pse_pr/include/t_long_term_pairing.h index aaff02af..b3fcd47e 100644 --- a/psw/ae/pse/pse_pr/include/t_long_term_pairing.h +++ b/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 ); diff --git a/psw/ae/pse/pse_pr/pse_pr.cpp b/psw/ae/pse/pse_pr/pse_pr.cpp index 25066459..d33f9241 100644 --- a/psw/ae/pse/pse_pr/pse_pr.cpp +++ b/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); diff --git a/psw/ae/pse/pse_pr/pse_pr.edl b/psw/ae/pse/pse_pr/pse_pr.edl index 89607c4a..1e121905 100644 --- a/psw/ae/pse/pse_pr/pse_pr.edl +++ b/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 ); diff --git a/psw/ae/pse/pse_pr/t_long_term_pairing.cpp b/psw/ae/pse/pse_pr/t_long_term_pairing.cpp index b11dd1bf..61d8aa44 100644 --- a/psw/ae/pse/pse_pr/t_long_term_pairing.cpp +++ b/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; diff --git a/psw/ae/pve/provision_enclave.cpp b/psw/ae/pve/provision_enclave.cpp index b970e776..66b569c5 100644 --- a/psw/ae/pve/provision_enclave.cpp +++ b/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)){ diff --git a/psw/ae/pve/provision_msg2.cpp b/psw/ae/pve/provision_msg2.cpp index 4fa3b0b2..563d570a 100644 --- a/psw/ae/pve/provision_msg2.cpp +++ b/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 #include @@ -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; diff --git a/psw/ae/qe/quoting_enclave.cpp b/psw/ae/qe/quoting_enclave.cpp index 8b187cea..f6cdf793 100644 --- a/psw/ae/qe/quoting_enclave.cpp +++ b/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); diff --git a/sdk/edger8r/linux/Ast.ml b/sdk/edger8r/linux/Ast.ml index 704079fb..7f288e6b 100644 --- a/sdk/edger8r/linux/Ast.ml +++ b/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; } diff --git a/sdk/edger8r/linux/CodeGen.ml b/sdk/edger8r/linux/CodeGen.ml index 71461763..8424327a 100644 --- a/sdk/edger8r/linux/CodeGen.ml +++ b/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 \n\ #include /* for memcpy etc */\n\ #include /* for malloc/free etc */\n\ diff --git a/sdk/edger8r/linux/Parser.mly b/sdk/edger8r/linux/Parser.mly index b826515f..3c28a689 100644 --- a/sdk/edger8r/linux/Parser.mly +++ b/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) | _ -> diff --git a/sdk/sign_tool/SignTool/manage_metadata.cpp b/sdk/sign_tool/SignTool/manage_metadata.cpp index 33e8455d..3d840861 100644 --- a/sdk/sign_tool/SignTool/manage_metadata.cpp +++ b/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 #include @@ -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) +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()) { - // 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); + 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; diff --git a/sdk/sign_tool/SignTool/sign_tool.cpp b/sdk/sign_tool/SignTool/sign_tool.cpp index 45584797..94494d8d 100644 --- a/sdk/sign_tool/SignTool/sign_tool.cpp +++ b/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(); diff --git a/sdk/sign_tool/SignTool/util_st.h b/sdk/sign_tool/SignTool/util_st.h index 6b5824bc..ef1a038b 100644 --- a/sdk/sign_tool/SignTool/util_st.h +++ b/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" diff --git a/sdk/tkey_exchange/simple_vector.cpp b/sdk/tkey_exchange/simple_vector.cpp index 46a1995a..7b5372a6 100644 --- a/sdk/tkey_exchange/simple_vector.cpp +++ b/sdk/tkey_exchange/simple_vector.cpp @@ -33,6 +33,7 @@ #include #include #include +#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; diff --git a/sdk/tkey_exchange/tkey_exchange.cpp b/sdk/tkey_exchange/tkey_exchange.cpp index 87118245..10a72879 100644 --- a/sdk/tkey_exchange/tkey_exchange.cpp +++ b/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; diff --git a/sdk/trts/init_enclave.cpp b/sdk/trts/init_enclave.cpp index 6d39fdbc..247b5b46 100644 --- a/sdk/trts/init_enclave.cpp +++ b/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; diff --git a/sdk/trts/trts.cpp b/sdk/trts/trts.cpp index d49717c7..a79b16cf 100644 --- a/sdk/trts/trts.cpp +++ b/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; } + diff --git a/sdk/trts/trts_ecall.cpp b/sdk/trts/trts_ecall.cpp index a4579e0a..fbe10143 100644 --- a/sdk/trts/trts_ecall.cpp +++ b/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); } diff --git a/sdk/tseal/tSeal_internal.cpp b/sdk/tseal/tSeal_internal.cpp index 59a341ed..c43a032d 100644 --- a/sdk/tseal/tSeal_internal.cpp +++ b/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 @@ -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(p_sealed_data->aes_data.payload), decrypted_text_length, p_decrypted_text, &payload_iv[0], SGX_SEAL_IV_SIZE,