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 #![no_std]
19 #![no_main]
20 #![feature(c_size_t)]
21 
22 extern crate alloc;
23 
24 use alloc::vec;
25 use alloc::boxed::Box;
26 use optee_utee::{
27     ta_close_session, ta_create, ta_destroy, ta_invoke_command, ta_open_session, trace_println,
28 };
29 use optee_utee::{AlgorithmId, OperationMode, AE};
30 use optee_utee::{AttributeId, AttributeMemref, TransientObject, TransientObjectType};
31 use optee_utee::{Error, ErrorKind, Parameters, Result};
32 use proto::{Command, Mode, AAD_LEN, BUFFER_SIZE, KEY_SIZE, TAG_LEN};
33 
34 pub const PAYLOAD_NUMBER: usize = 2;
35 
36 pub struct AEOp {
37     pub op: AE,
38 }
39 
40 impl Default for AEOp {
default() -> Self41     fn default() -> Self {
42         Self {
43             op: AE::null()
44         }
45     }
46 }
47 
48 #[ta_create]
create() -> Result<()>49 fn create() -> Result<()> {
50     trace_println!("[+] TA create");
51     Ok(())
52 }
53 
54 #[ta_open_session]
open_session(_params: &mut Parameters, _sess_ctx: &mut AEOp) -> Result<()>55 fn open_session(_params: &mut Parameters, _sess_ctx: &mut AEOp) -> Result<()> {
56     trace_println!("[+] TA open session");
57     Ok(())
58 }
59 
60 #[ta_close_session]
close_session(_sess_ctx: &mut AEOp)61 fn close_session(_sess_ctx: &mut AEOp) {
62     trace_println!("[+] TA close session");
63 }
64 
65 #[ta_destroy]
destroy()66 fn destroy() {
67     trace_println!("[+] TA destroy");
68 }
69 
70 #[ta_invoke_command]
invoke_command(sess_ctx: &mut AEOp, cmd_id: u32, params: &mut Parameters) -> Result<()>71 fn invoke_command(sess_ctx: &mut AEOp, cmd_id: u32, params: &mut Parameters) -> Result<()> {
72     trace_println!("[+] TA invoke command");
73     match Command::from(cmd_id) {
74         Command::Prepare => {
75             trace_println!("[+] TA prepare");
76             return prepare(sess_ctx, params);
77         }
78         Command::Update => {
79             trace_println!("[+] TA update");
80             return update(sess_ctx, params);
81         }
82         Command::EncFinal => {
83             trace_println!("[+] TA encrypt_final");
84             return encrypt_final(sess_ctx, params);
85         }
86         Command::DecFinal => {
87             trace_println!("[+] TA decrypt_final");
88             return decrypt_final(sess_ctx, params);
89         }
90         _ => {
91             return Err(Error::new(ErrorKind::BadParameters));
92         }
93     }
94 }
95 
prepare(ae: &mut AEOp, params: &mut Parameters) -> Result<()>96 pub fn prepare(ae: &mut AEOp, params: &mut Parameters) -> Result<()> {
97     let p0 = unsafe { params.0.as_value().unwrap() };
98     let mut p1 = unsafe { params.1.as_memref().unwrap() };
99     let mut p2 = unsafe { params.2.as_memref().unwrap() };
100     let mut p3 = unsafe { params.3.as_memref().unwrap() };
101     let mode = match Mode::from(p0.a()) {
102         Mode::Encrypt => OperationMode::Encrypt,
103         Mode::Decrypt => OperationMode::Decrypt,
104         _ => OperationMode::IllegalValue,
105     };
106     let nonce = p1.buffer();
107     let key = p2.buffer();
108     let aad = p3.buffer();
109 
110     ae.op = AE::allocate(AlgorithmId::AesCcm, mode, KEY_SIZE * 8).unwrap();
111 
112     let mut key_object = TransientObject::allocate(TransientObjectType::Aes, KEY_SIZE * 8).unwrap();
113     let attr = AttributeMemref::from_ref(AttributeId::SecretValue, key);
114     key_object.populate(&[attr.into()])?;
115     ae.op.set_key(&key_object)?;
116     ae.op
117         .init(&nonce, TAG_LEN * 8, AAD_LEN, BUFFER_SIZE * PAYLOAD_NUMBER)?;
118     ae.op.update_aad(aad);
119     Ok(())
120 }
121 
update(digest: &mut AEOp, params: &mut Parameters) -> Result<()>122 pub fn update(digest: &mut AEOp, params: &mut Parameters) -> Result<()> {
123     let mut p0 = unsafe { params.0.as_memref().unwrap() };
124     let mut p1 = unsafe { params.1.as_memref().unwrap() };
125     let src = p0.buffer();
126     let res = p1.buffer();
127     digest.op.update(src, res)?;
128     Ok(())
129 }
130 
encrypt_final(digest: &mut AEOp, params: &mut Parameters) -> Result<()>131 pub fn encrypt_final(digest: &mut AEOp, params: &mut Parameters) -> Result<()> {
132     let mut p0 = unsafe { params.0.as_memref().unwrap() };
133     let mut p1 = unsafe { params.1.as_memref().unwrap() };
134     let mut p2 = unsafe { params.2.as_memref().unwrap() };
135 
136     let mut clear = vec![0; p0.buffer().len() as usize];
137     clear.copy_from_slice(p0.buffer());
138     let mut ciph = vec![0; p1.buffer().len() as usize];
139     ciph.copy_from_slice(p1.buffer());
140     let mut tag = vec![0; p2.buffer().len() as usize];
141     tag.copy_from_slice(p2.buffer());
142 
143     match digest.op.encrypt_final(&clear, &mut ciph, &mut tag) {
144 
145         Err(e) => Err(e),
146         Ok((_ciph_len, _tag_len)) => {
147             p0.buffer().copy_from_slice(&clear);
148             p1.buffer().copy_from_slice(&ciph);
149             p2.buffer().copy_from_slice(&tag);
150 
151             Ok(())
152         },
153     }
154 }
155 
decrypt_final(digest: &mut AEOp, params: &mut Parameters) -> Result<()>156 pub fn decrypt_final(digest: &mut AEOp, params: &mut Parameters) -> Result<()> {
157     let mut p0 = unsafe { params.0.as_memref().unwrap() };
158     let mut p1 = unsafe { params.1.as_memref().unwrap() };
159     let mut p2 = unsafe { params.2.as_memref().unwrap() };
160 
161     let mut clear = vec![0; p0.buffer().len() as usize];
162     clear.copy_from_slice(p0.buffer());
163     let mut ciph = vec![0; p1.buffer().len() as usize];
164     ciph.copy_from_slice(p1.buffer());
165     let mut tag = vec![0; p2.buffer().len() as usize];
166     tag.copy_from_slice(p2.buffer());
167 
168     match digest.op.decrypt_final(&clear, &mut ciph, &tag) {
169         Err(e) => Err(e),
170         Ok(_clear_len) => {
171             p0.buffer().copy_from_slice(&clear);
172             p1.buffer().copy_from_slice(&ciph);
173             p2.buffer().copy_from_slice(&tag);
174 
175             Ok(())
176         },
177     }
178 }
179 
180 // TA configurations
181 const TA_FLAGS: u32 = 0;
182 const TA_DATA_SIZE: u32 = 32 * 1024;
183 const TA_STACK_SIZE: u32 = 2 * 1024;
184 const TA_VERSION: &[u8] = b"0.1\0";
185 const TA_DESCRIPTION: &[u8] = b"This is an authentication encryption example.\0";
186 const EXT_PROP_VALUE_1: &[u8] = b"AE TA\0";
187 const EXT_PROP_VALUE_2: u32 = 0x0010;
188 const TRACE_LEVEL: i32 = 4;
189 const TRACE_EXT_PREFIX: &[u8] = b"TA\0";
190 const TA_FRAMEWORK_STACK_SIZE: u32 = 2048;
191 
192 include!(concat!(env!("OUT_DIR"), "/user_ta_header.rs"));
193