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 
18 use proto;
19 use url;
20 use optee_teec::{Context, Uuid, ParamType, ParamTmpRef, ParamValue, ParamNone, Operation};
21 
22 type Result<T> = optee_teec::Result<T>;
23 
24 pub struct EnclaveClient {
25     uuid: String,
26     context: optee_teec::Context,
27     buffer: Vec<u8>
28 }
29 
30 impl EnclaveClient {
open(url: &str) -> Result<Self>31     pub fn open(url: &str) -> Result<Self> {
32         let url = url::Url::parse(url).unwrap();
33         match url.scheme() {
34             "trustzone-enclave" => {
35                 Self::open_uuid(url.host_str().unwrap())
36             },
37             _ => unimplemented!(),
38         }
39     }
40 
open_uuid(uuid: &str) -> Result<Self>41     fn open_uuid(uuid: &str) -> Result<Self> {
42         let context = Context::new()?;
43         Ok(Self {
44             uuid: uuid.to_string(),
45             context: context,
46             buffer: vec![0; 128]
47         })
48     }
49 
invoke(&mut self, input: &proto::EnclaveInput) -> Result<proto::EnclaveOutput>50     pub fn invoke(&mut self, input: &proto::EnclaveInput) -> Result<proto::EnclaveOutput> {
51         let command_id = input.command as u32;
52         let mut serialized_input = proto::serde_json::to_vec(input).unwrap();
53 
54         let p0 = ParamTmpRef::new_input(serialized_input.as_mut_slice());
55         let p1 = ParamTmpRef::new_output(&mut self.buffer);
56         let p2 = ParamValue::new(0, 0, ParamType::ValueInout);
57 
58         let mut operation = Operation::new(0, p0, p1, p2, ParamNone);
59 
60         let uuid = Uuid::parse_str(&self.uuid).unwrap();
61         let mut session = self.context.open_session(uuid)?;
62         session.invoke_command(command_id, &mut operation)?;
63         let len = operation.parameters().2.a() as usize;
64 
65         let output: proto::EnclaveOutput = proto::serde_json::from_slice(&self.buffer[0..len]).unwrap();
66         Ok(output)
67     }
68 }
69 
main() -> optee_teec::Result<()>70 fn main() -> optee_teec::Result<()> {
71     let url = format!("trustzone-enclave://{}", proto::UUID);
72     let mut enclave = EnclaveClient::open(&url).unwrap();
73     let input = proto::EnclaveInput {
74         command: proto::Command::Hello,
75         message: String::from("World!")
76     };
77     let output = enclave.invoke(&input).unwrap();
78     println!("{:?}", output);
79 
80     Ok(())
81 }
82