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