Skip to content

Commit

Permalink
Add the mc-sgx-tstdc crate
Browse files Browse the repository at this point in the history
  • Loading branch information
nick-mobilecoin committed Jan 13, 2023
1 parent 8a519a2 commit 3c9aa94
Show file tree
Hide file tree
Showing 6 changed files with 140 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Synchronization constants and defaults to `mc-sgx-tstdc-sys-types`.
- `mc-sgx-tstdc` crate with rust wrappers around synchronization primitives.

## [0.4.0] - 2022-12-14

Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ members = [
"tservice/sys",
"tservice/sys/types",
"tservice/types",
"tstdc",
"tstdc/sys",
"tstdc/sys/types",
"urts",
Expand Down
18 changes: 18 additions & 0 deletions tstdc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "mc-sgx-tstdc"
version = "0.4.1-beta.0"
edition = "2021"
authors = ["MobileCoin"]
rust-version = "1.62.1"
license = "Apache-2.0"
readme = "README.md"
repository = "https://github.com/mobilecoinfoundation/sgx"
description = "Rust wrappers around SGX synchronization primitives"
categories = ["api-bindings", "hardware-support"]
keywords = ["sgx"]

[dependencies]
displaydoc = { version = "0.2.3", default-features = false }
libc = {version = "0.2.139", default-features = false }
mc-sgx-tstdc-sys = { path = "sys", version = "0.4.1-beta.0" }
mc-sgx-tstdc-sys-types = { path = "sys/types", version = "0.4.1-beta.0" }
21 changes: 21 additions & 0 deletions tstdc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# MobileCoin: Rust wrappers around SGX synchronization primitives

[![Project Chat][chat-image]][chat-link]<!--
-->![License][license-image]<!--
-->![Target][target-image]<!--
-->[![Crates.io][crate-image]][crate-link]<!--
-->[![Docs Status][docs-image]][docs-link]<!--
-->[![Dependency Status][deps-image]][deps-link]

Rust wrappers around SGX synchronization primitives

[chat-image]: https://img.shields.io/discord/844353360348971068?style=flat-square
[chat-link]: https://mobilecoin.chat
[license-image]: https://img.shields.io/crates/l/mc-sgx-tstdc?style=flat-square
[target-image]: https://img.shields.io/badge/target-sgx-red?style=flat-square
[crate-image]: https://img.shields.io/crates/v/mc-sgx-tstdc.svg?style=flat-square
[crate-link]: https://crates.io/crates/mc-sgx-tstdc
[docs-image]: https://img.shields.io/docsrs/mc-sgx-tstdc?style=flat-square
[docs-link]: https://docs.rs/crate/mc-sgx-tstdc
[deps-image]: https://deps.rs/crate/mc-sgx-tstdc/0.1.0/status.svg?style=flat-square
[deps-link]: https://deps.rs/crate/mc-sgx-tstdc/0.1.0
8 changes: 8 additions & 0 deletions tstdc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) 2023 The MobileCoin Foundation

#![doc = include_str!("../README.md")]
#![deny(missing_docs, missing_debug_implementations)]
#![no_std]

mod mutex;
pub use mutex::{Error as MutexError, Mutex};
91 changes: 91 additions & 0 deletions tstdc/src/mutex.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
// Copyright (c) 2023 The MobileCoin Foundation

//! Mutex functionality for an SGX enclave
use mc_sgx_tstdc_sys::{
sgx_thread_mutex_destroy, sgx_thread_mutex_lock, sgx_thread_mutex_trylock,
sgx_thread_mutex_unlock,
};
use mc_sgx_tstdc_sys_types::sgx_thread_mutex_t;

/// Errors when interacting with [`Mutex`]es
#[derive(Copy, Clone, Debug, displaydoc::Display, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum Error {
/// Invalid operation on the mutex
Invalid,
/// Mutex is currently locked by another thread
Busy,
}

type Result<T> = core::result::Result<T, Error>;

/// A mutex inside of an SGX enclave
///
/// Use `Mutex::default()` to create an instance.
///
/// NB: per the documentation of
/// [`sgx_thread_mutex_lock()`](https://download.01.org/intel-sgx/sgx-linux/2.18/docs/Intel_SGX_Developer_Reference_Linux_2.18_Open_Source.pdf#%5B%7B%22num%22%3A303%2C%22gen%22%3A0%7D%2C%7B%22name%22%3A%22XYZ%22%7D%2C94.5%2C341.25%2C0%5D)
/// a mutex should not be locked across root ECALLs.
#[derive(Debug, Default, Eq, PartialEq)]
pub struct Mutex(sgx_thread_mutex_t);

impl Mutex {
/// Lock self
///
/// Blocks the current thread waiting for the mutex lock or an error.
///
/// # Errors
/// [`Error::Invalid`] will be returned if self is invalid or trying to lock
/// self when already holding a lock on self.
pub fn lock(&mut self) -> Result<()> {
let result = unsafe { sgx_thread_mutex_lock(&mut self.0) };
match result {
0 => Ok(()),
_ => Err(Error::Invalid),
}
}

/// Try to lock self
///
/// Returns immediately with the mutex or an error
///
/// # Errors
/// - [`Error::Busy`] if another thread has the lock, or higher precedence
/// in obtaining the lock.
/// - [`Error::Invalid`] if self is invalid or trying to lock self when
/// already holding a lock on self.
pub fn try_lock(&mut self) -> Result<()> {
let result = unsafe { sgx_thread_mutex_trylock(&mut self.0) };
match result {
0 => Ok(()),
libc::EBUSY => Err(Error::Busy),
_ => Err(Error::Invalid),
}
}

/// Unlock self
///
/// Returns immediately with the mutex or an error
///
/// # Errors
/// - [`Error::Busy`] if another thread has the lock.
/// - [`Error::Invalid`] if self is invalid or trying to unlock self when
/// self is not locked.
pub fn unlock(&mut self) -> Result<()> {
let result = unsafe { sgx_thread_mutex_unlock(&mut self.0) };
match result {
0 => Ok(()),
libc::EPERM => Err(Error::Busy),
_ => Err(Error::Invalid),
}
}
}

impl Drop for Mutex {
fn drop(&mut self) {
let result = unsafe { sgx_thread_mutex_destroy(&mut self.0) };
// There is no good way to recover from failing to destroy the mutex so
// we leak it in release
debug_assert_eq!(result, 0);
}
}

0 comments on commit 3c9aa94

Please sign in to comment.