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}