| // Copyright (c) 2017 Baidu, Inc. 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 Baidu, Inc., 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. |
| |
| //! # Trusted Runtime System |
| //! |
| //! The Intel(R) SGX trusted runtime system (tRTS) is a key component of the Intel(R) Software Guard Extensions SDK. |
| //! It provides the enclave entry point logic as well as other functions to be used by enclave developers. |
| //! |
| //! **Intel(R) Software Guard Extensions Helper Functions** |
| //! |
| //! **CustomExceptionHandling** |
| //! |
| //! # Intel(R) Software Guard Extensions Helper Functions |
| //! |
| //! The tRTS provides the helper functions for you to determine whether a given address is within or outside |
| //! enclave memory. |
| //! |
| //! The tRTS provides a wrapper to the RDRAND instruction to generate a true random number from hardware. |
| //! enclave developers should use the rsgx_read_rand function to get true random numbers. |
| //! |
| //! # CustomExceptionHandling |
| //! |
| //! The Intel(R) Software Guard Extensions SDK provides an API to allow you to register functions, or exception handlers, |
| //! to handle a limited set of hardware exceptions. When one of the enclave supported hardware exceptions occurs within |
| //! the enclave, the registered exception handlers will be called in a specific order until an exception handler reports |
| //! that it has handled the exception. For example, issuing a CPUID instruction inside an Enclave will result in a #UD fault |
| //! (Invalid Opcode Exception). ISV enclave code can call rsgx_register_exception_handler to register a function of type |
| //! sgx_exception_handler_t to respond to this exception. To check a list of enclave supported exceptions, see Intel(R) |
| //! Software Guard Extensions Programming Reference. |
| //! |
| //! **Note** |
| //! |
| //! Custom exception handling is only supported in HW mode. Although the exception handlers can be registered in simulation mode, |
| //! the exceptions cannot be caught and handled within the enclave. |
| //! |
| //! **Note** |
| //! |
| //! OCALLs are not allowed in the exception handler. |
| //! |
| //! **Note** |
| //! |
| //! Custom exception handing only saves general purpose registers in sgx_ exception_info_t. You should be careful when touching |
| //! other registers in the exception handlers. |
| //! |
| //! **Note** |
| //! |
| //! If the exception handlers can not handle the exceptions, abort() is called. |
| //! abort() makes the enclave unusable and generates another exception. |
| //! |
| #![crate_name = "sgx_trts"] |
| #![crate_type = "rlib"] |
| |
| #![cfg_attr(not(feature = "use_std"), no_std)] |
| #![allow(non_camel_case_types)] |
| |
| #[cfg(feature = "use_std")] |
| extern crate std as core; |
| |
| extern crate sgx_types; |
| use sgx_types::*; |
| use core::mem; |
| |
| /// |
| /// rsgx_read_rand function is used to generate a random number inside the enclave. |
| /// |
| /// # Description |
| /// |
| /// The rsgx_read_rand function is provided to replace the standard pseudo-random sequence generation functions |
| /// inside the enclave, since these standard functions are not supported in the enclave, such as rand, srand, etc. |
| /// For HW mode, the function generates a real-random sequence; while for simulation mode, the function generates |
| /// a pseudo-random sequence. |
| /// |
| /// # Parameters |
| /// |
| /// **rand** |
| /// |
| /// A pointer to the buffer that receives the random number. The rand buffer can be either within or outside the enclave, |
| /// but it is not allowed to be across the enclave boundary or wrapped around. |
| /// |
| /// # Requirements |
| /// |
| /// Library: libsgx_trts.a |
| /// |
| /// # Errors |
| /// |
| /// **SGX_ERROR_INVALID_PARAMETER** |
| /// |
| /// Invalid input parameters detected. |
| /// |
| /// **SGX_ERROR_UNEXPECTED** |
| /// |
| /// Indicates an unexpected error occurs during the valid random number gen- eration process. |
| /// |
| pub fn rsgx_read_rand(rand: &mut [u8]) -> SgxError { |
| |
| let ret = unsafe { sgx_read_rand(rand.as_mut_ptr(), rand.len()) }; |
| match ret { |
| sgx_status_t::SGX_SUCCESS => Ok(()), |
| _ => Err(ret), |
| } |
| } |
| |
| |
| pub type exception_handle = * const c_void; |
| |
| /// |
| /// rsgx_register_exception_handler register an exception handler. |
| /// |
| /// rsgx_register_exception_handler allows developers to register an exception handler, and specify whether to prepend |
| /// (when is_first_handler is equal to 1) or append the handler to the handler chain. |
| /// |
| /// # Description |
| /// |
| /// The Intel(R) SGX SDK supports the registration of custom exception handler functions. You can write your own code to |
| /// handle a limited set of hardware exceptions. For example, a CPUID instruction inside an enclave will effectively result |
| /// in a #UD fault (Invalid Opcode Exception). ISV enclave code can have an exception handler to prevent the enclave from |
| /// being trapped into an exception condition. |
| /// |
| /// Calling rsgx_register_exception_handler allows you to register an exception handler, and specify whether to prepend |
| /// (when is_first_handler is nonzero) or append the handler to the handler chain. |
| /// |
| /// After calling rsgx_register_exception_handler to prepend an exception handler, a subsequent call to this function may |
| /// add another exception handler at the beginning of the handler chain. Therefore the order in which exception handlers |
| /// are called does not only depend on the value of the is_first_handler parameter, but more importantly depends on the order |
| /// in which exception handlers are registered. |
| /// |
| /// # Parameters |
| /// |
| /// **is_first_handler** |
| /// |
| /// Specify the order in which the handler should be called. If the parameter is nonzero, the handler is the first handler |
| /// to be called. If the parameter is zero, the handler is the last handler to be called. |
| /// |
| /// **exception_handler** |
| /// |
| /// The exception handler to be called |
| /// |
| /// # Requirements |
| /// |
| /// Library: libsgx_trts.a |
| /// |
| /// # Return value |
| /// |
| /// **Some(exception_handle)** |
| /// |
| /// Indicates the exception handler is registered successfully. The return value is an open handle to the custom exception handler. |
| /// |
| /// **None** |
| /// |
| /// The exception handler was not registered. |
| /// |
| pub fn rsgx_register_exception_handler(is_first_handler: u32, exception_handler: sgx_exception_handler_t) -> Option<exception_handle> { |
| |
| let handle = unsafe { |
| sgx_register_exception_handler(is_first_handler, exception_handler) |
| }; |
| |
| if handle.is_null() { None } else { Some(handle) } |
| } |
| |
| /// |
| /// rsgx_unregister_exception_handler is used to unregister a custom exception handler. |
| /// |
| /// # Description |
| /// |
| /// The Intel(R) SGX SDK supports the registration of custom exception handler functions. An enclave developer |
| /// can write their own code to handle a limited set of hardware exceptions. |
| /// |
| /// Calling rsgx_unregister_exception_handler allows developers to unregister an exception handler that was registered earlier. |
| /// |
| /// # Parameters |
| /// |
| /// **handle** |
| /// |
| /// A handle to the custom exception handler previously registered using the rsgx_register_exception_handler function. |
| /// |
| /// # Requirements |
| /// |
| /// Library: libsgx_trts.a |
| /// |
| /// # Return value |
| /// |
| /// **true** |
| /// |
| /// The custom exception handler is unregistered successfully. |
| /// |
| /// **false** |
| /// |
| /// The exception handler was not unregistered (not a valid pointer, handler not found). |
| /// |
| pub fn rsgx_unregister_exception_handler(handle: exception_handle) -> bool { |
| |
| let ret = unsafe { sgx_unregister_exception_handler(handle) }; |
| if ret == 0 { false } else { true } |
| } |
| |
| /// |
| /// rsgx_data_is_within_enclave checks whether a given address is within enclave memory. |
| /// |
| #[inline] |
| pub fn rsgx_data_is_within_enclave<T: Copy>(data: &T) -> bool { |
| |
| rsgx_raw_is_within_enclave(data as * const _ as * const u8, mem::size_of::<T>()) |
| } |
| |
| /// |
| /// rsgx_slice_is_within_enclave checks whether a given address is within enclave memory. |
| /// |
| #[inline] |
| pub fn rsgx_slice_is_within_enclave<T: Copy>(data: &[T]) -> bool { |
| |
| rsgx_raw_is_within_enclave(data.as_ptr() as * const u8, mem::size_of::<T>() * data.len()) |
| } |
| |
| /// |
| /// rsgx_raw_is_within_enclave checks whether a given address is within enclave memory. |
| /// |
| /// The rsgx_raw_is_within_enclave function checks that the buffer located at the pointer addr with its |
| /// length of size is an address that is strictly within the calling enclave address space. |
| /// |
| /// # Description |
| /// |
| /// rsgx_raw_is_within_enclave simply compares the start and end address of the buffer with the calling |
| /// enclave address space. It does not check the property of the address. Given a function pointer, you |
| /// sometimes need to confirm whether such a function is within the enclave. In this case, it is recommended |
| /// to use rsgx_raw_is_within_enclave with a size of 1. |
| /// |
| /// # Parameters |
| /// |
| /// **addr** |
| /// |
| /// The start address of the buffer. |
| /// |
| /// **size** |
| /// |
| /// The size of the buffer. |
| /// |
| /// # Requirements |
| /// |
| /// Library: libsgx_trts.a |
| /// |
| /// # Return value |
| /// |
| /// **true** |
| /// |
| /// The buffer is strictly within the enclave address space. |
| /// |
| /// **false** |
| /// |
| /// The whole buffer or part of the buffer is not within the enclave, or the buffer is wrapped around. |
| /// |
| pub fn rsgx_raw_is_within_enclave(addr: * const u8, size: usize) -> bool { |
| |
| let ret = unsafe { sgx_is_within_enclave(addr as * const c_void, size) }; |
| if ret == 0 { false } else { true } |
| } |
| |
| /// |
| /// rsgx_data_is_outside_enclave checks whether a given address is outside enclave memory. |
| /// |
| #[inline] |
| pub fn rsgx_data_is_outside_enclave<T: Copy>(data: &T) -> bool { |
| |
| rsgx_raw_is_outside_enclave(data as * const _ as * const u8, mem::size_of::<T>()) |
| } |
| |
| /// |
| /// rsgx_slice_is_outside_enclave checks whether a given address is outside enclave memory. |
| /// |
| #[inline] |
| pub fn rsgx_slice_is_outside_enclave<T: Copy>(data: &[T]) -> bool { |
| |
| rsgx_raw_is_outside_enclave(data.as_ptr() as * const u8, mem::size_of::<T>() * data.len()) |
| } |
| |
| /// |
| /// rsgx_raw_is_outside_enclave checks whether a given address is outside enclave memory. |
| /// |
| /// The rsgx_raw_is_outside_enclave function checks that the buffer located at the pointer addr with its |
| /// length of size is an address that is strictly outside the calling enclave address space. |
| /// |
| /// # Description |
| /// |
| /// rsgx_raw_is_outside_enclave simply compares the start and end address of the buffer with the calling |
| /// enclave address space. It does not check the property of the address. |
| /// |
| /// # Parameters |
| /// |
| /// **addr** |
| /// |
| /// The start address of the buffer. |
| /// |
| /// **size** |
| /// |
| /// The size of the buffer. |
| /// |
| /// # Requirements |
| /// |
| /// Library: libsgx_trts.a |
| /// |
| /// # Return value |
| /// |
| /// **true** |
| /// |
| /// The buffer is strictly outside the enclave address space. |
| /// |
| /// **false** |
| /// |
| /// The whole buffer or part of the buffer is not outside the enclave, or the buffer is wrapped around. |
| /// |
| pub fn rsgx_raw_is_outside_enclave(addr: * const u8, size: usize) -> bool { |
| |
| let ret = unsafe { sgx_is_outside_enclave(addr as * const c_void, size) }; |
| if ret == 0 { false } else { true } |
| } |
| |
| /// |
| /// rsgx_get_thread_data is to get TD base address per thread. |
| /// |
| /// **Note** |
| /// |
| /// This API is only an experimental funtion. |
| /// |
| #[inline] |
| pub fn rsgx_get_thread_data() -> * const u8 { |
| |
| unsafe { get_thread_data() as * const u8 } |
| } |
| |
| /// |
| /// rsgx_get_enclave_base is to get enclave image base address. |
| /// |
| /// **Note** |
| /// |
| /// This API is only an experimental funtion. |
| /// |
| #[inline] |
| pub fn rsgx_get_enclave_base() -> * const u8 { |
| |
| unsafe { get_enclave_base() as * const u8 } |
| } |
| |
| /// |
| /// rsgx_get_heap_base is to get enclave heap base address. |
| /// |
| /// **Note** |
| /// |
| /// This API is only an experimental funtion. |
| /// |
| #[inline] |
| pub fn rsgx_get_heap_base() -> * const u8 { |
| |
| unsafe { get_heap_base() as * const u8 } |
| } |
| |
| /// |
| /// rsgx_get_heap_size is to get enclave heap size. |
| /// |
| /// **Note** |
| /// |
| /// This API is only an experimental funtion. |
| /// |
| #[inline] |
| pub fn rsgx_get_heap_size() -> usize { |
| |
| unsafe { get_heap_size() } |
| } |