• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 //! This module is used to implement cryptographic algorithm operations, including key usage.
17 
18 use std::time::Instant;
19 
20 use asset_common::{transfer_error_code, SUCCESS};
21 use asset_definition::{log_throw_error, ErrCode, Result};
22 
23 use crate::{secret_key::SecretKey, HksBlob, KeyId, OutBlob};
24 
25 extern "C" {
EncryptData(keyId: *const KeyId, aad: *const HksBlob, in_data: *const HksBlob, out_data: *mut OutBlob) -> i3226     fn EncryptData(keyId: *const KeyId, aad: *const HksBlob, in_data: *const HksBlob, out_data: *mut OutBlob) -> i32;
DecryptData(keyId: *const KeyId, aad: *const HksBlob, in_data: *const HksBlob, out_data: *mut OutBlob) -> i3227     fn DecryptData(keyId: *const KeyId, aad: *const HksBlob, in_data: *const HksBlob, out_data: *mut OutBlob) -> i32;
InitKey(keyId: *const KeyId, valid_time: u32, challenge: *mut OutBlob, handle: *mut OutBlob) -> i3228     fn InitKey(keyId: *const KeyId, valid_time: u32, challenge: *mut OutBlob, handle: *mut OutBlob) -> i32;
ExecCrypt( handle: *const HksBlob, aad: *const HksBlob, auth_token: *const HksBlob, in_data: *const HksBlob, out_data: *mut OutBlob, ) -> i3229     fn ExecCrypt(
30         handle: *const HksBlob,
31         aad: *const HksBlob,
32         auth_token: *const HksBlob,
33         in_data: *const HksBlob,
34         out_data: *mut OutBlob,
35     ) -> i32;
Drop(handle: *const HksBlob) -> i3236     fn Drop(handle: *const HksBlob) -> i32;
37 }
38 
39 const NONCE_SIZE: usize = 12;
40 const TAG_SIZE: usize = 16;
41 const HANDLE_LEN: usize = 8;
42 const CHALLENGE_LEN: usize = 32;
43 
44 /// Crypto for storing key attributes that require user authentication.
45 pub struct Crypto {
46     key: SecretKey,
47     challenge: Vec<u8>,
48     handle: Vec<u8>,
49     valid_time: u32,
50     start_time: Instant,
51 }
52 
53 impl Crypto {
54     /// Create a crypto instance.
build(key: SecretKey, valid_time: u32) -> Result<Self>55     pub fn build(key: SecretKey, valid_time: u32) -> Result<Self> {
56         Ok(Self {
57             key,
58             challenge: vec![0; CHALLENGE_LEN],
59             handle: vec![0; HANDLE_LEN],
60             valid_time,
61             start_time: Instant::now(),
62         })
63     }
64 
65     /// Init secret key and get challenge.
init_key(&mut self) -> Result<&Vec<u8>>66     pub fn init_key(&mut self) -> Result<&Vec<u8>> {
67         let key_alias = HksBlob { size: self.key.alias().len() as u32, data: self.key.alias().as_ptr() };
68         let mut challenge = OutBlob { size: self.challenge.len() as u32, data: self.challenge.as_mut_ptr() };
69         let mut handle = OutBlob { size: self.handle.len() as u32, data: self.handle.as_mut_ptr() };
70         let key_id = KeyId::new(self.key.calling_info().user_id(), key_alias, self.key.access_type());
71 
72         let ret = unsafe {
73             InitKey(
74                 &key_id as *const KeyId,
75                 self.valid_time,
76                 &mut challenge as *mut OutBlob,
77                 &mut handle as *mut OutBlob,
78             )
79         };
80         match ret {
81             SUCCESS => Ok(&self.challenge),
82             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
83         }
84     }
85 
86     /// Decrypt data that requires user authentication.
exec_crypt(&self, cipher: &Vec<u8>, aad: &Vec<u8>, auth_token: &Vec<u8>) -> Result<Vec<u8>>87     pub fn exec_crypt(&self, cipher: &Vec<u8>, aad: &Vec<u8>, auth_token: &Vec<u8>) -> Result<Vec<u8>> {
88         if cipher.len() <= (TAG_SIZE + NONCE_SIZE) {
89             return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The cipher length is too short.");
90         }
91 
92         let aad = HksBlob { size: aad.len() as u32, data: aad.as_ptr() };
93         let auth_token = HksBlob { size: auth_token.len() as u32, data: auth_token.as_ptr() };
94         let handle = HksBlob { size: self.handle.len() as u32, data: self.handle.as_ptr() };
95         let in_data = HksBlob { size: cipher.len() as u32, data: cipher.as_ptr() };
96         let mut msg: Vec<u8> = vec![0; cipher.len() - TAG_SIZE - NONCE_SIZE];
97         let mut out_data = OutBlob { size: msg.len() as u32, data: msg.as_mut_ptr() };
98 
99         let ret = unsafe {
100             ExecCrypt(
101                 &handle as *const HksBlob,
102                 &aad as *const HksBlob,
103                 &auth_token as *const HksBlob,
104                 &in_data as *const HksBlob,
105                 &mut out_data as *mut OutBlob,
106             )
107         };
108         match ret {
109             SUCCESS => Ok(msg),
110             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
111         }
112     }
113 
114     /// Encrypt data at one-time.
encrypt(key: &SecretKey, msg: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>>115     pub fn encrypt(key: &SecretKey, msg: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>> {
116         let mut cipher: Vec<u8> = vec![0; msg.len() + TAG_SIZE + NONCE_SIZE];
117         let key_alias = HksBlob { size: key.alias().len() as u32, data: key.alias().as_ptr() };
118         let aad_data = HksBlob { size: aad.len() as u32, data: aad.as_ptr() };
119         let in_data = HksBlob { size: msg.len() as u32, data: msg.as_ptr() };
120         let mut out_data = OutBlob { size: cipher.len() as u32, data: cipher.as_mut_ptr() };
121         let key_id = KeyId::new(key.calling_info().user_id(), key_alias, key.access_type());
122 
123         let ret = unsafe {
124             EncryptData(
125                 &key_id as *const KeyId,
126                 &aad_data as *const HksBlob,
127                 &in_data as *const HksBlob,
128                 &mut out_data as *mut OutBlob,
129             )
130         };
131         match ret {
132             SUCCESS => Ok(cipher),
133             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
134         }
135     }
136 
137     /// Encrypt data at one-time.
decrypt(key: &SecretKey, cipher: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>>138     pub fn decrypt(key: &SecretKey, cipher: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>> {
139         if cipher.len() <= (TAG_SIZE + NONCE_SIZE) {
140             return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The cipher length is too short.");
141         }
142 
143         let mut plain: Vec<u8> = vec![0; cipher.len() - TAG_SIZE - NONCE_SIZE];
144         let key_alias = HksBlob { size: key.alias().len() as u32, data: key.alias().as_ptr() };
145         let aad_data = HksBlob { size: aad.len() as u32, data: aad.as_ptr() };
146         let in_data = HksBlob { size: cipher.len() as u32, data: cipher.as_ptr() };
147         let mut out_data = OutBlob { size: plain.len() as u32, data: plain.as_mut_ptr() };
148         let key_id = KeyId::new(key.calling_info().user_id(), key_alias, key.access_type());
149 
150         let ret = unsafe {
151             DecryptData(
152                 &key_id as *const KeyId,
153                 &aad_data as *const HksBlob,
154                 &in_data as *const HksBlob,
155                 &mut out_data as *mut OutBlob,
156             )
157         };
158         match ret {
159             SUCCESS => Ok(plain),
160             _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)),
161         }
162     }
163 
key(&self) -> &SecretKey164     pub(crate) fn key(&self) -> &SecretKey {
165         &self.key
166     }
167 
challenge(&self) -> &Vec<u8>168     pub(crate) fn challenge(&self) -> &Vec<u8> {
169         &self.challenge
170     }
171 
start_time(&self) -> &Instant172     pub(crate) fn start_time(&self) -> &Instant {
173         &self.start_time
174     }
175 
valid_time(&self) -> u32176     pub(crate) fn valid_time(&self) -> u32 {
177         self.valid_time
178     }
179 }
180 
181 impl Drop for Crypto {
drop(&mut self)182     fn drop(&mut self) {
183         let handle = HksBlob { size: self.handle.len() as u32, data: self.handle.as_ptr() };
184         unsafe { Drop(&handle as *const HksBlob) };
185     }
186 }
187