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, CallingInfo, 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 calling_info: CallingInfo, 48 challenge: Vec<u8>, 49 handle: Vec<u8>, 50 valid_time: u32, 51 start_time: Instant, 52 } 53 54 impl Crypto { 55 /// Create a crypto instance. build(key: SecretKey, calling_info: CallingInfo, valid_time: u32) -> Result<Self>56 pub fn build(key: SecretKey, calling_info: CallingInfo, valid_time: u32) -> Result<Self> { 57 Ok(Self { 58 key, 59 calling_info, 60 challenge: vec![0; CHALLENGE_LEN], 61 handle: vec![0; HANDLE_LEN], 62 valid_time, 63 start_time: Instant::now(), 64 }) 65 } 66 67 /// Init secret key and get challenge. init_key(&mut self) -> Result<&Vec<u8>>68 pub fn init_key(&mut self) -> Result<&Vec<u8>> { 69 let key_alias = HksBlob { size: self.key.alias().len() as u32, data: self.key.alias().as_ptr() }; 70 let mut challenge = OutBlob { size: self.challenge.len() as u32, data: self.challenge.as_mut_ptr() }; 71 let mut handle = OutBlob { size: self.handle.len() as u32, data: self.handle.as_mut_ptr() }; 72 let key_id = KeyId::new(self.key.user_id(), key_alias, self.key.access_type()); 73 74 let ret = unsafe { 75 InitKey( 76 &key_id as *const KeyId, 77 self.valid_time, 78 &mut challenge as *mut OutBlob, 79 &mut handle as *mut OutBlob, 80 ) 81 }; 82 match ret { 83 SUCCESS => Ok(&self.challenge), 84 _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)), 85 } 86 } 87 88 /// Decrypt data that requires user authentication. exec_crypt(&self, cipher: &Vec<u8>, aad: &Vec<u8>, auth_token: &Vec<u8>) -> Result<Vec<u8>>89 pub fn exec_crypt(&self, cipher: &Vec<u8>, aad: &Vec<u8>, auth_token: &Vec<u8>) -> Result<Vec<u8>> { 90 if cipher.len() <= (TAG_SIZE + NONCE_SIZE) { 91 return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The cipher length is too short."); 92 } 93 94 let aad = HksBlob { size: aad.len() as u32, data: aad.as_ptr() }; 95 let auth_token = HksBlob { size: auth_token.len() as u32, data: auth_token.as_ptr() }; 96 let handle = HksBlob { size: self.handle.len() as u32, data: self.handle.as_ptr() }; 97 let in_data = HksBlob { size: cipher.len() as u32, data: cipher.as_ptr() }; 98 let mut msg: Vec<u8> = vec![0; cipher.len() - TAG_SIZE - NONCE_SIZE]; 99 let mut out_data = OutBlob { size: msg.len() as u32, data: msg.as_mut_ptr() }; 100 101 let ret = unsafe { 102 ExecCrypt( 103 &handle as *const HksBlob, 104 &aad as *const HksBlob, 105 &auth_token as *const HksBlob, 106 &in_data as *const HksBlob, 107 &mut out_data as *mut OutBlob, 108 ) 109 }; 110 match ret { 111 SUCCESS => Ok(msg), 112 _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)), 113 } 114 } 115 116 /// Encrypt data at one-time. encrypt(key: &SecretKey, msg: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>>117 pub fn encrypt(key: &SecretKey, msg: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>> { 118 let mut cipher: Vec<u8> = vec![0; msg.len() + TAG_SIZE + NONCE_SIZE]; 119 let key_alias = HksBlob { size: key.alias().len() as u32, data: key.alias().as_ptr() }; 120 let aad_data = HksBlob { size: aad.len() as u32, data: aad.as_ptr() }; 121 let in_data = HksBlob { size: msg.len() as u32, data: msg.as_ptr() }; 122 let mut out_data = OutBlob { size: cipher.len() as u32, data: cipher.as_mut_ptr() }; 123 let key_id = KeyId::new(key.user_id(), key_alias, key.access_type()); 124 125 let ret = unsafe { 126 EncryptData( 127 &key_id as *const KeyId, 128 &aad_data as *const HksBlob, 129 &in_data as *const HksBlob, 130 &mut out_data as *mut OutBlob, 131 ) 132 }; 133 match ret { 134 SUCCESS => Ok(cipher), 135 _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)), 136 } 137 } 138 139 /// Encrypt data at one-time. decrypt(key: &SecretKey, cipher: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>>140 pub fn decrypt(key: &SecretKey, cipher: &Vec<u8>, aad: &Vec<u8>) -> Result<Vec<u8>> { 141 if cipher.len() <= (TAG_SIZE + NONCE_SIZE) { 142 return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The cipher length is too short."); 143 } 144 145 let mut plain: Vec<u8> = vec![0; cipher.len() - TAG_SIZE - NONCE_SIZE]; 146 let key_alias = HksBlob { size: key.alias().len() as u32, data: key.alias().as_ptr() }; 147 let aad_data = HksBlob { size: aad.len() as u32, data: aad.as_ptr() }; 148 let in_data = HksBlob { size: cipher.len() as u32, data: cipher.as_ptr() }; 149 let mut out_data = OutBlob { size: plain.len() as u32, data: plain.as_mut_ptr() }; 150 let key_id = KeyId::new(key.user_id(), key_alias, key.access_type()); 151 152 let ret = unsafe { 153 DecryptData( 154 &key_id as *const KeyId, 155 &aad_data as *const HksBlob, 156 &in_data as *const HksBlob, 157 &mut out_data as *mut OutBlob, 158 ) 159 }; 160 match ret { 161 SUCCESS => Ok(plain), 162 _ => Err(transfer_error_code(ErrCode::try_from(ret as u32)?)), 163 } 164 } 165 key(&self) -> &SecretKey166 pub(crate) fn key(&self) -> &SecretKey { 167 &self.key 168 } 169 calling_info(&self) -> &CallingInfo170 pub(crate) fn calling_info(&self) -> &CallingInfo { 171 &self.calling_info 172 } 173 challenge(&self) -> &Vec<u8>174 pub(crate) fn challenge(&self) -> &Vec<u8> { 175 &self.challenge 176 } 177 start_time(&self) -> &Instant178 pub(crate) fn start_time(&self) -> &Instant { 179 &self.start_time 180 } 181 valid_time(&self) -> u32182 pub(crate) fn valid_time(&self) -> u32 { 183 self.valid_time 184 } 185 } 186 187 impl Drop for Crypto { drop(&mut self)188 fn drop(&mut self) { 189 let handle = HksBlob { size: self.handle.len() as u32, data: self.handle.as_ptr() }; 190 unsafe { Drop(&handle as *const HksBlob) }; 191 } 192 } 193