Skip to main content

optee_teec/
context.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use crate::{ConnectionMethods, Error, Operation, Param, ParamNone, Result, Session, Uuid, raw};
19use std::{cell::RefCell, ptr, rc::Rc};
20
21pub struct InnerContext(pub raw::TEEC_Context);
22
23impl Drop for InnerContext {
24    fn drop(&mut self) {
25        unsafe {
26            raw::TEEC_FinalizeContext(&mut self.0);
27        }
28    }
29}
30
31/// An abstraction of the logical connection between a client application and a
32/// TEE.
33pub struct Context {
34    // Use Rc to share it with Session, eliminating the lifetime constraint.
35    // Use RefCell to allow conversion into a raw mutable pointer.
36    // As RefCell is not Send + Sync, there is no need to use Arc.
37    raw: Rc<RefCell<InnerContext>>,
38}
39
40// Since RefCell is used for Context, Rust does not automatically implement
41// Send and Sync for it. We need to manually implement them and ensure that
42// InnerContext is used correctly.
43unsafe impl Send for Context {}
44unsafe impl Sync for Context {}
45
46impl Context {
47    /// Creates a TEE client context object.
48    ///
49    /// # Examples
50    ///
51    /// ``` no_run
52    /// # use optee_teec::Context;
53    /// # fn main() -> optee_teec::Result<()> {
54    /// let mut ctx = Context::new()?;
55    /// # Ok(())
56    /// # }
57    /// ```
58    pub fn new() -> Result<Context> {
59        // SAFETY:
60        // raw_ctx is a C struct(TEEC_Context), which zero value is valid.
61        let mut raw_ctx = unsafe { std::mem::zeroed() };
62        match unsafe { raw::TEEC_InitializeContext(ptr::null_mut(), &mut raw_ctx) } {
63            raw::TEEC_SUCCESS => Ok(Self {
64                raw: Rc::new(RefCell::new(InnerContext(raw_ctx))),
65            }),
66            code => Err(Error::from_raw_error(code)),
67        }
68    }
69
70    /// Opens a new session with the specified trusted application.
71    ///
72    /// The target trusted application is specified by `uuid`.
73    ///
74    /// # Examples
75    ///
76    /// ``` no_run
77    /// use optee_teec::{Context, ErrorKind, Uuid};
78    ///
79    /// fn main() -> optee_teec::Result<()> {
80    ///     let mut ctx = Context::new()?;
81    ///     let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b").map_err(|err| {
82    ///         println!("bad uuid: {:?}", err);
83    ///         ErrorKind::BadParameters
84    ///     })?;
85    ///     let session = ctx.open_session(uuid)?;
86    ///     Ok(())
87    /// }
88    /// ```
89    pub fn open_session(&mut self, uuid: Uuid) -> Result<Session> {
90        Session::new(
91            self,
92            uuid,
93            ConnectionMethods::LoginPublic,
94            None::<&mut Operation<ParamNone, ParamNone, ParamNone, ParamNone>>,
95        )
96    }
97
98    pub fn open_session_with_login(
99        &mut self,
100        uuid: Uuid,
101        login: ConnectionMethods,
102    ) -> Result<Session> {
103        Session::new(
104            self,
105            uuid,
106            login,
107            None::<&mut Operation<ParamNone, ParamNone, ParamNone, ParamNone>>,
108        )
109    }
110
111    /// Opens a new session with the specified trusted application, pass some
112    /// parameters to TA by an operation.
113    ///
114    /// The target trusted application is specified by `uuid`.
115    ///
116    /// # Examples
117    ///
118    /// ``` no_run
119    /// use optee_teec::{Context, ErrorKind, Operation, ParamNone, ParamType, ParamValue, Uuid};
120    ///
121    /// fn main() -> optee_teec::Result<()> {
122    ///     let mut ctx = Context::new()?;
123    ///     let uuid = Uuid::parse_str("8abcf200-2450-11e4-abe2-0002a5d5c51b").map_err(|err| {
124    ///         println!("bad uuid: {:?}", err);
125    ///         ErrorKind::BadParameters
126    ///     })?;
127    ///     let p0 = ParamValue::new(42, 0, ParamType::ValueInout);
128    ///     let mut operation = Operation::new(0, p0, ParamNone, ParamNone, ParamNone);
129    ///     let session = ctx.open_session_with_operation(uuid, &mut operation)?;
130    ///     Ok(())
131    /// }
132    /// ```
133    pub fn open_session_with_operation<A: Param, B: Param, C: Param, D: Param>(
134        &mut self,
135        uuid: Uuid,
136        operation: &mut Operation<A, B, C, D>,
137    ) -> Result<Session> {
138        Session::new(self, uuid, ConnectionMethods::LoginPublic, Some(operation))
139    }
140}
141
142// Internal usage only
143impl Context {
144    // anyone who wants to access the inner_context must take this as mut.
145    pub(crate) fn inner_context(&mut self) -> Rc<RefCell<InnerContext>> {
146        self.raw.clone()
147    }
148}