1dfe32fa1Soh_ci/* 2dfe32fa1Soh_ci * Copyright (c) 2024 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 implements functions related to Asset database key. 17dfe32fa1Soh_ci 18dfe32fa1Soh_ciuse asset_common::SUCCESS; 19dfe32fa1Soh_ciuse asset_crypto_manager::{crypto::Crypto, secret_key::SecretKey}; 20dfe32fa1Soh_ciuse asset_definition::{log_throw_error, Accessibility, AuthType, ErrCode, Result}; 21dfe32fa1Soh_ciuse asset_file_operator::ce_operator::{is_db_key_cipher_file_exist, read_db_key_cipher, write_db_key_cipher}; 22dfe32fa1Soh_ciuse asset_log::logi; 23dfe32fa1Soh_ciuse std::sync::Mutex; 24dfe32fa1Soh_ci 25dfe32fa1Soh_ciconst TRIVIAL_AAD_FOR_DB_KEY: &str = "trivial_aad_for_db_key"; 26dfe32fa1Soh_cistatic GEN_KEY_MUTEX: Mutex<()> = Mutex::new(()); 27dfe32fa1Soh_cistatic GET_DB_KEY_MUTEX: Mutex<()> = Mutex::new(()); 28dfe32fa1Soh_ci 29dfe32fa1Soh_cifn build_db_key_secret_key(user_id: i32) -> Result<SecretKey> { 30dfe32fa1Soh_ci let auth_type = AuthType::None; 31dfe32fa1Soh_ci let access_type = Accessibility::DeviceFirstUnlocked; 32dfe32fa1Soh_ci let require_password_set = false; 33dfe32fa1Soh_ci let alias = "db_key_secret_key".as_bytes().to_vec(); 34dfe32fa1Soh_ci 35dfe32fa1Soh_ci SecretKey::new_with_alias(user_id, auth_type, access_type, require_password_set, alias) 36dfe32fa1Soh_ci} 37dfe32fa1Soh_ci 38dfe32fa1Soh_ci/// Generate secret key if it does not exist. 39dfe32fa1Soh_cipub fn generate_secret_key_if_needed(secret_key: &SecretKey) -> Result<()> { 40dfe32fa1Soh_ci match secret_key.exists() { 41dfe32fa1Soh_ci Ok(true) => Ok(()), 42dfe32fa1Soh_ci Ok(false) => { 43dfe32fa1Soh_ci let _lock = GEN_KEY_MUTEX.lock().unwrap(); 44dfe32fa1Soh_ci match secret_key.exists() { 45dfe32fa1Soh_ci Ok(true) => Ok(()), 46dfe32fa1Soh_ci Ok(false) => { 47dfe32fa1Soh_ci logi!("[INFO]The key does not exist, generate it."); 48dfe32fa1Soh_ci secret_key.generate() 49dfe32fa1Soh_ci }, 50dfe32fa1Soh_ci Err(ret) => Err(ret), 51dfe32fa1Soh_ci } 52dfe32fa1Soh_ci }, 53dfe32fa1Soh_ci Err(ret) => Err(ret), 54dfe32fa1Soh_ci } 55dfe32fa1Soh_ci} 56dfe32fa1Soh_ci 57dfe32fa1Soh_ciextern "C" { 58dfe32fa1Soh_ci fn GenerateRandom(random: *mut u8, random_len: u32) -> i32; 59dfe32fa1Soh_ci} 60dfe32fa1Soh_ci 61dfe32fa1Soh_ci/// db key obj 62dfe32fa1Soh_cipub struct DbKey { 63dfe32fa1Soh_ci /// db key 64dfe32fa1Soh_ci pub db_key: Vec<u8>, 65dfe32fa1Soh_ci} 66dfe32fa1Soh_ci 67dfe32fa1Soh_ciimpl DbKey { 68dfe32fa1Soh_ci fn decrypt_db_key_cipher(user_id: i32, db_key_cipher: &Vec<u8>) -> Result<DbKey> { 69dfe32fa1Soh_ci let secret_key = build_db_key_secret_key(user_id)?; 70dfe32fa1Soh_ci let aad: Vec<u8> = TRIVIAL_AAD_FOR_DB_KEY.as_bytes().to_vec(); 71dfe32fa1Soh_ci let db_key = Crypto::decrypt(&secret_key, db_key_cipher, &aad)?; 72dfe32fa1Soh_ci Ok(Self { db_key }) 73dfe32fa1Soh_ci } 74dfe32fa1Soh_ci 75dfe32fa1Soh_ci fn generate_db_key() -> Result<DbKey> { 76dfe32fa1Soh_ci const KEY_LEN_IN_BYTES: usize = 32; // aes-256-gcm requires key length 256 bits = 32 bytes. 77dfe32fa1Soh_ci let mut db_key = [0; KEY_LEN_IN_BYTES]; 78dfe32fa1Soh_ci 79dfe32fa1Soh_ci if unsafe { GenerateRandom(db_key.as_mut_ptr(), db_key.len() as u32) } != SUCCESS { 80dfe32fa1Soh_ci return log_throw_error!(ErrCode::CryptoError, "[FATAL]Generate random failed!"); 81dfe32fa1Soh_ci } 82dfe32fa1Soh_ci Ok(Self { db_key: db_key.to_vec() }) 83dfe32fa1Soh_ci } 84dfe32fa1Soh_ci 85dfe32fa1Soh_ci fn encrypt_db_key(&self, user_id: i32) -> Result<Vec<u8>> { 86dfe32fa1Soh_ci let secret_key = build_db_key_secret_key(user_id)?; 87dfe32fa1Soh_ci generate_secret_key_if_needed(&secret_key)?; 88dfe32fa1Soh_ci let aad: Vec<u8> = TRIVIAL_AAD_FOR_DB_KEY.as_bytes().to_vec(); 89dfe32fa1Soh_ci let db_key_cipher = Crypto::encrypt(&secret_key, &self.db_key, &aad)?; 90dfe32fa1Soh_ci 91dfe32fa1Soh_ci Ok(db_key_cipher) 92dfe32fa1Soh_ci } 93dfe32fa1Soh_ci 94dfe32fa1Soh_ci /// Check whether the database key exists. 95dfe32fa1Soh_ci pub fn check_existance(user_id: i32) -> Result<bool> { 96dfe32fa1Soh_ci is_db_key_cipher_file_exist(user_id) 97dfe32fa1Soh_ci } 98dfe32fa1Soh_ci 99dfe32fa1Soh_ci /// Read db key cipher and decrypt if the db key cipher file exists, generate db_key if not. 100dfe32fa1Soh_ci pub fn get_db_key(user_id: i32) -> Result<DbKey> { 101dfe32fa1Soh_ci match is_db_key_cipher_file_exist(user_id) { 102dfe32fa1Soh_ci Ok(true) => { 103dfe32fa1Soh_ci let db_key_cipher = read_db_key_cipher(user_id)?; 104dfe32fa1Soh_ci Self::decrypt_db_key_cipher(user_id, &db_key_cipher) 105dfe32fa1Soh_ci }, 106dfe32fa1Soh_ci Ok(false) => { 107dfe32fa1Soh_ci let _lock = GET_DB_KEY_MUTEX.lock().unwrap(); 108dfe32fa1Soh_ci match is_db_key_cipher_file_exist(user_id) { 109dfe32fa1Soh_ci Ok(true) => { 110dfe32fa1Soh_ci let db_key_cipher = read_db_key_cipher(user_id)?; 111dfe32fa1Soh_ci Self::decrypt_db_key_cipher(user_id, &db_key_cipher) 112dfe32fa1Soh_ci }, 113dfe32fa1Soh_ci Ok(false) => { 114dfe32fa1Soh_ci let db_key = Self::generate_db_key()?; 115dfe32fa1Soh_ci let db_key_cipher = db_key.encrypt_db_key(user_id)?; 116dfe32fa1Soh_ci write_db_key_cipher(user_id, &db_key_cipher)?; 117dfe32fa1Soh_ci Ok(db_key) 118dfe32fa1Soh_ci }, 119dfe32fa1Soh_ci Err(e) => Err(e), 120dfe32fa1Soh_ci } 121dfe32fa1Soh_ci }, 122dfe32fa1Soh_ci Err(e) => Err(e), 123dfe32fa1Soh_ci } 124dfe32fa1Soh_ci } 125dfe32fa1Soh_ci} 126dfe32fa1Soh_ci 127dfe32fa1Soh_ciimpl Drop for DbKey { 128dfe32fa1Soh_ci fn drop(&mut self) { 129dfe32fa1Soh_ci self.db_key.fill(0); 130dfe32fa1Soh_ci } 131dfe32fa1Soh_ci} 132