diff --git a/optee-teec/Cargo.toml b/optee-teec/Cargo.toml index fe09b698..0db13f44 100644 --- a/optee-teec/Cargo.toml +++ b/optee-teec/Cargo.toml @@ -30,6 +30,10 @@ optee-teec-macros = { path = "macros" } libc = "0.2" uuid = "0.7" hex = "0.3" +self_cell = { version = "1.0", optional = true } + +[features] +owned = ["self_cell"] [workspace] members = ['systest'] diff --git a/optee-teec/src/context.rs b/optee-teec/src/context.rs index 5f791244..f24fdd16 100644 --- a/optee-teec/src/context.rs +++ b/optee-teec/src/context.rs @@ -21,6 +21,11 @@ use libc; use optee_teec_sys as raw; use std::ptr; +#[cfg(feature = "owned")] +use crate::OwnedSession; +#[cfg(feature = "owned")] +use std::sync::Arc; + /// An abstraction of the logical connection between a client application and a /// TEE. pub struct Context { @@ -68,8 +73,8 @@ impl Context { /// let mut ctx = Context::new().unwrap(); /// let mut raw_ptr: *mut optee_teec_sys::TEEC_Context = ctx.as_mut_raw_ptr(); /// ``` - pub fn as_mut_raw_ptr(&mut self) -> *mut raw::TEEC_Context { - &mut self.raw + pub(crate) fn as_mut_raw_ptr(&self) -> *mut raw::TEEC_Context { + &self.raw as *const _ as *mut _ } /// Opens a new session with the specified trusted application. @@ -83,7 +88,7 @@ impl Context { /// let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b").unwrap(); /// let session = ctx.open_session(uuid).unwrap(); /// ``` - pub fn open_session(&mut self, uuid: Uuid) -> Result { + pub fn open_session(&self, uuid: Uuid) -> Result { Session::new( self, uuid, @@ -91,6 +96,27 @@ impl Context { ) } + #[cfg(feature = "owned")] + /// Opens a new owned session with the specified trusted application. + /// + /// The target trusted application is specified by `uuid`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// let mut ctx = Arc::new(Context::new().unwrap()); + /// let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b").unwrap(); + /// let session = ctx.open_owned_session(uuid).unwrap(); + /// ``` + pub fn open_owned_session(self: Arc, uuid: Uuid) -> Result { + OwnedSession::new( + self, + uuid, + None::<&mut Operation>, + ) + } + /// Opens a new session with the specified trusted application, pass some /// parameters to TA by an operation. /// @@ -106,12 +132,37 @@ impl Context { /// let session = ctx.open_session_with_operation(uuid, operation).unwrap(); /// ``` pub fn open_session_with_operation( - &mut self, + &self, uuid: Uuid, operation: &mut Operation, ) -> Result { Session::new(self, uuid, Some(operation)) } + + #[cfg(feature = "owned")] + /// Opens a new owned session with the specified trusted application, pass some + /// parameters to TA by an operation. + /// + /// The target trusted application is specified by `uuid`. + /// + /// # Examples + /// + /// ``` + /// use std::sync::Arc; + /// let mut ctx = Arc::new(Context::new().unwrap()); + /// let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b").unwrap(); + /// let p0 = ParamValue(42, 0, ParamType::ValueInout); + /// let mut operation = Operation::new(0, p0, ParamNone, ParamNone, ParamNone); + /// let session = ctx.open_session_with_operation(uuid, operation).unwrap(); + /// ``` + pub fn open_owned_session_with_operation( + self: Arc, + uuid: Uuid, + operation: &mut Operation, + ) -> Result { + OwnedSession::new(self, uuid, Some(operation)) + } + } impl Drop for Context { diff --git a/optee-teec/src/lib.rs b/optee-teec/src/lib.rs index 26ad2f71..138fc315 100644 --- a/optee-teec/src/lib.rs +++ b/optee-teec/src/lib.rs @@ -20,6 +20,8 @@ pub use self::error::{Error, ErrorKind, Result}; pub use self::operation::Operation; pub use self::parameter::{Param, ParamNone, ParamTmpRef, ParamType, ParamTypes, ParamValue}; pub use self::session::{ConnectionMethods, Session}; +#[cfg(feature = "owned")] +pub use self::session::OwnedSession; pub use self::uuid::Uuid; pub use self::extension::*; pub use optee_teec_macros::{plugin_init, plugin_invoke}; diff --git a/optee-teec/src/session.rs b/optee-teec/src/session.rs index fe7624a8..d0bd86be 100644 --- a/optee-teec/src/session.rs +++ b/optee-teec/src/session.rs @@ -17,6 +17,10 @@ use libc; use optee_teec_sys as raw; +#[cfg(feature = "owned")] +use self_cell::self_cell; +#[cfg(feature = "owned")] +use std::sync::Arc; use std::ptr; use std::marker; @@ -40,16 +44,58 @@ pub enum ConnectionMethods { LoginGroupApplication, } +// Sessions are documented as threadsafe in GP. Sessions with non-static lifetimes +// cannot be send because we cannot ensure that their context lives long enough, but +// sessions with 'static lifetime should be Send. +// +// A few ways to construct a session with static lifetime: +// 1. With the "owned" feature, use an `OwnedSession` +// 2. Use `once_cell::sync::Lazy` or `lazy_static` or anything similar to produce a global context +// 3. Use `Box::leak` or similar to permanently consume heap resources by creating a &'static +// Context +unsafe impl Send for Session<'static> {} + /// Represents a connection between a client application and a trusted application. pub struct Session<'ctx> { raw: raw::TEEC_Session, - _marker: marker::PhantomData<&'ctx mut Context>, + _marker: marker::PhantomData<&'ctx Context>, +} + +#[cfg(feature = "owned")] +self_cell! { + struct SessionPair { + owner: Arc, + #[covariant] + dependent: Session, + } +} + +/// Represents an owned variant of `Session`, whose Context is reference counted. +#[cfg(feature = "owned")] +pub struct OwnedSession(SessionPair); + +#[cfg(feature = "owned")] +impl OwnedSession { + /// Initializes an owned TEE session object with specified context and uuid. + pub fn new( + context: Arc, + uuid: Uuid, + operation: Option<&mut Operation>, + ) -> Result { + Ok(Self(SessionPair::try_new(context, |context| Session::new(context, uuid, operation))?)) + } + + /// Provides access to an unowned session, borrowed from the owned version + pub fn session(&self) -> &Session<'_> { + self.0.borrow_dependent() + } + } impl<'ctx> Session<'ctx> { /// Initializes a TEE session object with specified context and uuid. pub fn new( - context: &'ctx mut Context, + context: &'ctx Context, uuid: Uuid, operation: Option<&mut Operation>, ) -> Result {