diff options
Diffstat (limited to 'library/std/src/os/fortanix_sgx')
-rw-r--r-- | library/std/src/os/fortanix_sgx/arch.rs | 80 | ||||
-rw-r--r-- | library/std/src/os/fortanix_sgx/ffi.rs | 41 | ||||
-rw-r--r-- | library/std/src/os/fortanix_sgx/io.rs | 144 | ||||
-rw-r--r-- | library/std/src/os/fortanix_sgx/mod.rs | 53 |
4 files changed, 318 insertions, 0 deletions
diff --git a/library/std/src/os/fortanix_sgx/arch.rs b/library/std/src/os/fortanix_sgx/arch.rs new file mode 100644 index 000000000..8358cb9e8 --- /dev/null +++ b/library/std/src/os/fortanix_sgx/arch.rs @@ -0,0 +1,80 @@ +//! SGX-specific access to architectural features. +//! +//! The functionality in this module is further documented in the Intel +//! Software Developer's Manual, Volume 3, Chapter 40. +#![unstable(feature = "sgx_platform", issue = "56975")] + +use crate::mem::MaybeUninit; +use core::arch::asm; + +/// Wrapper struct to force 16-byte alignment. +#[repr(align(16))] +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct Align16<T>(pub T); + +/// Wrapper struct to force 128-byte alignment. +#[repr(align(128))] +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct Align128<T>(pub T); + +/// Wrapper struct to force 512-byte alignment. +#[repr(align(512))] +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct Align512<T>(pub T); + +const ENCLU_EREPORT: u32 = 0; +const ENCLU_EGETKEY: u32 = 1; + +/// Call the `EGETKEY` instruction to obtain a 128-bit secret key. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub fn egetkey(request: &Align512<[u8; 512]>) -> Result<Align16<[u8; 16]>, u32> { + unsafe { + let mut out = MaybeUninit::uninit(); + let error; + + asm!( + // rbx is reserved by LLVM + "xchg %rbx, {0}", + "enclu", + "mov {0}, %rbx", + inout(reg) request => _, + inlateout("eax") ENCLU_EGETKEY => error, + in("rcx") out.as_mut_ptr(), + options(att_syntax, nostack), + ); + + match error { + 0 => Ok(out.assume_init()), + err => Err(err), + } + } +} + +/// Call the `EREPORT` instruction. +/// +/// This creates a cryptographic report describing the contents of the current +/// enclave. The report may be verified by the enclave described in +/// `targetinfo`. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub fn ereport( + targetinfo: &Align512<[u8; 512]>, + reportdata: &Align128<[u8; 64]>, +) -> Align512<[u8; 432]> { + unsafe { + let mut report = MaybeUninit::uninit(); + + asm!( + // rbx is reserved by LLVM + "xchg %rbx, {0}", + "enclu", + "mov {0}, %rbx", + inout(reg) targetinfo => _, + in("eax") ENCLU_EREPORT, + in("rcx") reportdata, + in("rdx") report.as_mut_ptr(), + options(att_syntax, preserves_flags, nostack), + ); + + report.assume_init() + } +} diff --git a/library/std/src/os/fortanix_sgx/ffi.rs b/library/std/src/os/fortanix_sgx/ffi.rs new file mode 100644 index 000000000..ac1db0e5e --- /dev/null +++ b/library/std/src/os/fortanix_sgx/ffi.rs @@ -0,0 +1,41 @@ +//! SGX-specific extension to the primitives in the `std::ffi` module +//! +//! # Examples +//! +//! ``` +//! use std::ffi::OsString; +//! use std::os::fortanix_sgx::ffi::OsStringExt; +//! +//! let bytes = b"foo".to_vec(); +//! +//! // OsStringExt::from_vec +//! let os_string = OsString::from_vec(bytes); +//! assert_eq!(os_string.to_str(), Some("foo")); +//! +//! // OsStringExt::into_vec +//! let bytes = os_string.into_vec(); +//! assert_eq!(bytes, b"foo"); +//! ``` +//! +//! ``` +//! use std::ffi::OsStr; +//! use std::os::fortanix_sgx::ffi::OsStrExt; +//! +//! let bytes = b"foo"; +//! +//! // OsStrExt::from_bytes +//! let os_str = OsStr::from_bytes(bytes); +//! assert_eq!(os_str.to_str(), Some("foo")); +//! +//! // OsStrExt::as_bytes +//! let bytes = os_str.as_bytes(); +//! assert_eq!(bytes, b"foo"); +//! ``` + +#![unstable(feature = "sgx_platform", issue = "56975")] + +#[path = "../unix/ffi/os_str.rs"] +mod os_str; + +#[unstable(feature = "sgx_platform", issue = "56975")] +pub use self::os_str::{OsStrExt, OsStringExt}; diff --git a/library/std/src/os/fortanix_sgx/io.rs b/library/std/src/os/fortanix_sgx/io.rs new file mode 100644 index 000000000..7223ade68 --- /dev/null +++ b/library/std/src/os/fortanix_sgx/io.rs @@ -0,0 +1,144 @@ +//! SGX-specific extensions to general I/O primitives +//! +//! SGX file descriptors behave differently from Unix file descriptors. See the +//! description of [`TryIntoRawFd`] for more details. +#![unstable(feature = "sgx_platform", issue = "56975")] + +use crate::net; +pub use crate::sys::abi::usercalls::raw::Fd as RawFd; +use crate::sys::{self, AsInner, FromInner, IntoInner, TryIntoInner}; + +/// A trait to extract the raw SGX file descriptor from an underlying +/// object. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait AsRawFd { + /// Extracts the raw file descriptor. + /// + /// This method does **not** pass ownership of the raw file descriptor + /// to the caller. The descriptor is only guaranteed to be valid while + /// the original object has not yet been destroyed. + #[unstable(feature = "sgx_platform", issue = "56975")] + fn as_raw_fd(&self) -> RawFd; +} + +/// A trait to express the ability to construct an object from a raw file +/// descriptor. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait FromRawFd { + /// An associated type that contains relevant metadata for `Self`. + type Metadata: Default; + + /// Constructs a new instance of `Self` from the given raw file + /// descriptor and metadata. + /// + /// This function **consumes ownership** of the specified file + /// descriptor. The returned object will take responsibility for closing + /// it when the object goes out of scope. + /// + /// This function is also unsafe as the primitives currently returned + /// have the contract that they are the sole owner of the file + /// descriptor they are wrapping. Usage of this function could + /// accidentally allow violating this contract which can cause memory + /// unsafety in code that relies on it being true. + #[unstable(feature = "sgx_platform", issue = "56975")] + unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> Self; +} + +/// A trait to express the ability to consume an object and acquire ownership of +/// its raw file descriptor. +#[unstable(feature = "sgx_platform", issue = "56975")] +pub trait TryIntoRawFd: Sized { + /// Consumes this object, returning the raw underlying file descriptor, if + /// this object is not cloned. + /// + /// This function **transfers ownership** of the underlying file descriptor + /// to the caller. Callers are then the unique owners of the file descriptor + /// and must close the descriptor once it's no longer needed. + /// + /// Unlike other platforms, on SGX, the file descriptor is shared between + /// all clones of an object. To avoid race conditions, this function will + /// only return `Ok` when called on the final clone. + #[unstable(feature = "sgx_platform", issue = "56975")] + fn try_into_raw_fd(self) -> Result<RawFd, Self>; +} + +impl AsRawFd for net::TcpStream { + #[inline] + fn as_raw_fd(&self) -> RawFd { + *self.as_inner().as_inner().as_inner().as_inner() + } +} + +impl AsRawFd for net::TcpListener { + #[inline] + fn as_raw_fd(&self) -> RawFd { + *self.as_inner().as_inner().as_inner().as_inner() + } +} + +/// Metadata for `TcpStream`. +#[derive(Debug, Clone, Default)] +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct TcpStreamMetadata { + /// Local address of the TCP stream + pub local_addr: Option<String>, + /// Peer address of the TCP stream + pub peer_addr: Option<String>, +} + +impl FromRawFd for net::TcpStream { + type Metadata = TcpStreamMetadata; + + #[inline] + unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpStream { + let fd = sys::fd::FileDesc::from_inner(fd); + let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); + net::TcpStream::from_inner(sys::net::TcpStream::from_inner((socket, metadata.peer_addr))) + } +} + +/// Metadata for `TcpListener`. +#[derive(Debug, Clone, Default)] +#[unstable(feature = "sgx_platform", issue = "56975")] +pub struct TcpListenerMetadata { + /// Local address of the TCP listener + pub local_addr: Option<String>, +} + +impl FromRawFd for net::TcpListener { + type Metadata = TcpListenerMetadata; + + #[inline] + unsafe fn from_raw_fd(fd: RawFd, metadata: Self::Metadata) -> net::TcpListener { + let fd = sys::fd::FileDesc::from_inner(fd); + let socket = sys::net::Socket::from_inner((fd, metadata.local_addr)); + net::TcpListener::from_inner(sys::net::TcpListener::from_inner(socket)) + } +} + +impl TryIntoRawFd for net::TcpStream { + #[inline] + fn try_into_raw_fd(self) -> Result<RawFd, Self> { + let (socket, peer_addr) = self.into_inner().into_inner(); + match socket.try_into_inner() { + Ok(fd) => Ok(fd.into_inner()), + Err(socket) => { + let sys = sys::net::TcpStream::from_inner((socket, peer_addr)); + Err(net::TcpStream::from_inner(sys)) + } + } + } +} + +impl TryIntoRawFd for net::TcpListener { + #[inline] + fn try_into_raw_fd(self) -> Result<RawFd, Self> { + match self.into_inner().into_inner().try_into_inner() { + Ok(fd) => Ok(fd.into_inner()), + Err(socket) => { + let sys = sys::net::TcpListener::from_inner(socket); + Err(net::TcpListener::from_inner(sys)) + } + } + } +} diff --git a/library/std/src/os/fortanix_sgx/mod.rs b/library/std/src/os/fortanix_sgx/mod.rs new file mode 100644 index 000000000..a40dabe19 --- /dev/null +++ b/library/std/src/os/fortanix_sgx/mod.rs @@ -0,0 +1,53 @@ +//! Functionality specific to the `x86_64-fortanix-unknown-sgx` target. +//! +//! This includes functions to deal with memory isolation, usercalls, and the +//! SGX instruction set. + +#![deny(missing_docs)] +#![unstable(feature = "sgx_platform", issue = "56975")] + +/// Low-level interfaces to usercalls. See the [ABI documentation] for more +/// information. +/// +/// [ABI documentation]: https://docs.rs/fortanix-sgx-abi/ +pub mod usercalls { + pub use crate::sys::abi::usercalls::*; + + /// Primitives for allocating memory in userspace as well as copying data + /// to and from user memory. + pub mod alloc { + pub use crate::sys::abi::usercalls::alloc::*; + } + + /// Lowest-level interfaces to usercalls and usercall ABI type definitions. + pub mod raw { + pub use crate::sys::abi::usercalls::raw::{ + accept_stream, alloc, async_queues, bind_stream, close, connect_stream, exit, flush, + free, insecure_time, launch_thread, read, read_alloc, send, wait, write, + }; + pub use crate::sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs}; + + // fortanix-sgx-abi re-exports + pub use crate::sys::abi::usercalls::raw::Error; + pub use crate::sys::abi::usercalls::raw::{ByteBuffer, FifoDescriptor, Return, Usercall}; + pub use crate::sys::abi::usercalls::raw::{Fd, Result, Tcs}; + pub use crate::sys::abi::usercalls::raw::{ + EV_RETURNQ_NOT_EMPTY, EV_UNPARK, EV_USERCALLQ_NOT_FULL, FD_STDERR, FD_STDIN, FD_STDOUT, + RESULT_SUCCESS, USERCALL_USER_DEFINED, WAIT_INDEFINITE, WAIT_NO, + }; + } +} + +/// Functions for querying mapping information for pointers. +pub mod mem { + pub use crate::sys::abi::mem::*; +} + +pub mod arch; +pub mod ffi; +pub mod io; + +/// Functions for querying thread-related information. +pub mod thread { + pub use crate::sys::abi::thread::current; +} |