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