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