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