• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-2025 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 is used to provide common capabilities for the Asset operations.
17 
18 mod argument_check;
19 mod permission_check;
20 
21 use std::time::Instant;
22 
23 pub(crate) use argument_check::{
24     check_group_validity, check_required_tags, check_tag_validity, check_value_validity, MAX_LABEL_SIZE,
25 };
26 pub(crate) use permission_check::check_system_permission;
27 
28 use asset_common::{CallingInfo, OwnerType, OWNER_INFO_SEPARATOR};
29 use asset_crypto_manager::secret_key::SecretKey;
30 use asset_db_operator::types::{column, DbMap, DB_DATA_VERSION, DB_DATA_VERSION_V1};
31 use asset_definition::{
32     log_throw_error, Accessibility, AssetMap, AuthType, ErrCode, Extension, OperationType, Result, Tag, Value, WrapType,
33 };
34 use asset_log::{loge, logi};
35 use asset_plugin::asset_plugin::AssetPlugin;
36 use asset_sdk::plugin_interface::{EventType, ExtDbMap, PARAM_NAME_BUNDLE_NAME, PARAM_NAME_USER_ID};
37 
38 use crate::sys_event::upload_statistic_system_event;
39 
40 const TAG_COLUMN_TABLE: [(Tag, &str); 21] = [
41     (Tag::Secret, column::SECRET),
42     (Tag::Alias, column::ALIAS),
43     (Tag::Accessibility, column::ACCESSIBILITY),
44     (Tag::AuthType, column::AUTH_TYPE),
45     (Tag::SyncType, column::SYNC_TYPE),
46     (Tag::UpdateTime, column::UPDATE_TIME),
47     (Tag::IsPersistent, column::IS_PERSISTENT),
48     (Tag::RequirePasswordSet, column::REQUIRE_PASSWORD_SET),
49     (Tag::DataLabelCritical1, column::CRITICAL1),
50     (Tag::DataLabelCritical2, column::CRITICAL2),
51     (Tag::DataLabelCritical3, column::CRITICAL3),
52     (Tag::DataLabelCritical4, column::CRITICAL4),
53     (Tag::DataLabelNormal1, column::NORMAL1),
54     (Tag::DataLabelNormal2, column::NORMAL2),
55     (Tag::DataLabelNormal3, column::NORMAL3),
56     (Tag::DataLabelNormal4, column::NORMAL4),
57     (Tag::DataLabelNormalLocal1, column::NORMAL_LOCAL1),
58     (Tag::DataLabelNormalLocal2, column::NORMAL_LOCAL2),
59     (Tag::DataLabelNormalLocal3, column::NORMAL_LOCAL3),
60     (Tag::DataLabelNormalLocal4, column::NORMAL_LOCAL4),
61     (Tag::WrapType, column::WRAP_TYPE),
62 ];
63 
64 const AAD_ATTR: [&str; 15] = [
65     column::ALIAS,
66     column::OWNER,
67     column::OWNER_TYPE,
68     column::GROUP_ID,
69     column::SYNC_TYPE,
70     column::ACCESSIBILITY,
71     column::REQUIRE_PASSWORD_SET,
72     column::AUTH_TYPE,
73     column::IS_PERSISTENT,
74     column::VERSION,
75     column::CRITICAL1,
76     column::CRITICAL2,
77     column::CRITICAL3,
78     column::CRITICAL4,
79     column::WRAP_TYPE,
80 ];
81 
82 pub(crate) const CRITICAL_LABEL_ATTRS: [Tag; 4] =
83     [Tag::DataLabelCritical1, Tag::DataLabelCritical2, Tag::DataLabelCritical3, Tag::DataLabelCritical4];
84 
85 pub(crate) const NORMAL_LABEL_ATTRS: [Tag; 4] =
86     [Tag::DataLabelNormal1, Tag::DataLabelNormal2, Tag::DataLabelNormal3, Tag::DataLabelNormal4];
87 
88 pub(crate) const NORMAL_LOCAL_LABEL_ATTRS: [Tag; 4] =
89     [Tag::DataLabelNormalLocal1, Tag::DataLabelNormalLocal2, Tag::DataLabelNormalLocal3, Tag::DataLabelNormalLocal4];
90 
91 pub(crate) const ACCESS_CONTROL_ATTRS: [Tag; 10] = [
92     Tag::Alias,
93     Tag::Accessibility,
94     Tag::AuthType,
95     Tag::IsPersistent,
96     Tag::SyncType,
97     Tag::RequirePasswordSet,
98     Tag::RequireAttrEncrypted,
99     Tag::GroupId,
100     Tag::WrapType,
101     Tag::UserId,
102 ];
103 
104 pub(crate) const ASSET_SYNC_ATTRS: [Tag; 1] = [Tag::OperationType];
105 
get_cloumn_name(tag: Tag) -> Option<&'static str>106 pub(crate) fn get_cloumn_name(tag: Tag) -> Option<&'static str> {
107     for (table_tag, table_column) in TAG_COLUMN_TABLE {
108         if table_tag == tag {
109             return Some(table_column);
110         }
111     }
112     None
113 }
114 
into_db_map(attrs: &AssetMap) -> DbMap115 pub(crate) fn into_db_map(attrs: &AssetMap) -> DbMap {
116     let mut db_data = DbMap::new();
117     for (attr_tag, attr_value) in attrs.iter() {
118         for (table_tag, table_column) in TAG_COLUMN_TABLE {
119             if *attr_tag == table_tag {
120                 db_data.insert(table_column, attr_value.clone());
121                 break;
122             }
123         }
124     }
125     db_data
126 }
127 
into_asset_map(db_data: &DbMap) -> AssetMap128 pub(crate) fn into_asset_map(db_data: &DbMap) -> AssetMap {
129     let mut map = AssetMap::new();
130     for (column, data) in db_data.iter() {
131         for (table_tag, table_column) in TAG_COLUMN_TABLE {
132             if (*column).eq(table_column) {
133                 map.insert(table_tag, data.clone());
134                 break;
135             }
136         }
137     }
138     map
139 }
140 
add_owner_info(calling_info: &CallingInfo, db_data: &mut DbMap)141 pub(crate) fn add_owner_info(calling_info: &CallingInfo, db_data: &mut DbMap) {
142     db_data.insert(column::OWNER, Value::Bytes(calling_info.owner_info().clone()));
143     db_data.insert(column::OWNER_TYPE, Value::Number(calling_info.owner_type()));
144 }
145 
add_group(calling_info: &CallingInfo, db_data: &mut DbMap)146 pub(crate) fn add_group(calling_info: &CallingInfo, db_data: &mut DbMap) {
147     if let Some(group) = calling_info.group() {
148         db_data.insert(column::GROUP_ID, Value::Bytes(group));
149     };
150 }
151 
add_calling_info(calling_info: &CallingInfo, db_data: &mut DbMap)152 pub(crate) fn add_calling_info(calling_info: &CallingInfo, db_data: &mut DbMap) {
153     add_owner_info(calling_info, db_data);
154     add_group(calling_info, db_data);
155 }
156 
build_secret_key(calling: &CallingInfo, attrs: &DbMap) -> Result<SecretKey>157 pub(crate) fn build_secret_key(calling: &CallingInfo, attrs: &DbMap) -> Result<SecretKey> {
158     let auth_type = attrs.get_enum_attr::<AuthType>(&column::AUTH_TYPE)?;
159     let access_type = attrs.get_enum_attr::<Accessibility>(&column::ACCESSIBILITY)?;
160     let require_password_set = attrs.get_bool_attr(&column::REQUIRE_PASSWORD_SET)?;
161     SecretKey::new_without_alias(calling, auth_type, access_type, require_password_set)
162 }
163 
check_if_need_addition_aad(attr: &str, map: &DbMap) -> bool164 fn check_if_need_addition_aad(attr: &str, map: &DbMap) -> bool {
165     match attr {
166         column::WRAP_TYPE => match map.get_enum_attr::<WrapType>(&attr) {
167             Ok(v) => v != WrapType::default(),
168             Err(_) => false,
169         },
170         _ => true,
171     }
172 }
173 
build_aad_v1(attrs: &DbMap) -> Vec<u8>174 fn build_aad_v1(attrs: &DbMap) -> Vec<u8> {
175     let mut aad = Vec::new();
176     for column in &AAD_ATTR {
177         if !check_if_need_addition_aad(column, attrs) {
178             continue;
179         }
180         match attrs.get(column) {
181             Some(Value::Bytes(bytes)) => aad.extend(bytes),
182             Some(Value::Number(num)) => aad.extend(num.to_le_bytes()),
183             Some(Value::Bool(num)) => aad.push(*num as u8),
184             None => continue,
185         }
186     }
187     aad
188 }
189 
to_hex(bytes: &Vec<u8>) -> Result<Vec<u8>>190 fn to_hex(bytes: &Vec<u8>) -> Result<Vec<u8>> {
191     let bytes_len = bytes.len();
192     if bytes_len > MAX_LABEL_SIZE {
193         return log_throw_error!(ErrCode::DataCorrupted, "The data in DB has been tampered with.");
194     }
195 
196     let scale_capacity = 2;
197     let mut hex_vec = Vec::with_capacity(bytes_len * scale_capacity);
198     for byte in bytes.iter() {
199         hex_vec.extend(format!("{:02x}", byte).as_bytes());
200     }
201     Ok(hex_vec)
202 }
203 
build_aad_v2(attrs: &DbMap) -> Result<Vec<u8>>204 fn build_aad_v2(attrs: &DbMap) -> Result<Vec<u8>> {
205     let mut aad = Vec::new();
206     for column in &AAD_ATTR {
207         if !check_if_need_addition_aad(column, attrs) {
208             continue;
209         }
210         aad.extend(format!("{}:", column).as_bytes());
211         match attrs.get(column) {
212             Some(Value::Bytes(bytes)) => aad.extend(to_hex(bytes)?),
213             Some(Value::Number(num)) => aad.extend(num.to_le_bytes()),
214             Some(Value::Bool(num)) => aad.push(*num as u8),
215             None => (),
216         }
217         aad.push(b'_');
218     }
219     Ok(aad)
220 }
221 
build_aad(attrs: &DbMap) -> Result<Vec<u8>>222 pub(crate) fn build_aad(attrs: &DbMap) -> Result<Vec<u8>> {
223     let version = attrs.get_num_attr(&column::VERSION)?;
224     if version == DB_DATA_VERSION_V1 {
225         let tmp_calling_info = CallingInfo::new_part_info(
226             attrs.get_bytes_attr(&column::OWNER)?.clone(),
227             attrs.get_enum_attr::<OwnerType>(&column::OWNER_TYPE)?,
228         );
229         upload_statistic_system_event(&tmp_calling_info, Instant::now(), "V1_AAD_DATA", "V1_AAD_DATA");
230         Ok(build_aad_v1(attrs))
231     } else {
232         build_aad_v2(attrs)
233     }
234 }
235 
need_upgrade(db_date: &DbMap) -> Result<bool>236 pub(crate) fn need_upgrade(db_date: &DbMap) -> Result<bool> {
237     let version = db_date.get_num_attr(&column::VERSION)?;
238     Ok(version != DB_DATA_VERSION)
239 }
240 
inform_asset_ext(calling_info: &CallingInfo, input: &AssetMap)241 pub(crate) fn inform_asset_ext(calling_info: &CallingInfo, input: &AssetMap) {
242     if let Some(Value::Number(operation_type)) = input.get(&Tag::OperationType) {
243         match operation_type {
244             x if *x == OperationType::NeedSync as u32 => {
245                 if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
246                     let owner_info_str = String::from_utf8_lossy(calling_info.owner_info()).to_string();
247                     let owner_info_vec: Vec<_> = owner_info_str.split(OWNER_INFO_SEPARATOR).collect();
248                     let caller_name = owner_info_vec[0];
249                     let mut params = ExtDbMap::new();
250                     params.insert(PARAM_NAME_USER_ID, Value::Number(calling_info.user_id() as u32));
251                     params.insert(PARAM_NAME_BUNDLE_NAME, Value::Bytes(caller_name.as_bytes().to_vec()));
252                     match load.process_event(EventType::Sync, &mut params) {
253                         Ok(()) => logi!("process sync ext event success."),
254                         Err(code) => loge!("process sync ext event failed, code: {}", code),
255                     }
256                 }
257             },
258             x if *x == OperationType::NeedLogout as u32 => {
259                 if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
260                     let owner_info_str = String::from_utf8_lossy(calling_info.owner_info()).to_string();
261                     let owner_info_vec: Vec<_> = owner_info_str.split(OWNER_INFO_SEPARATOR).collect();
262                     let caller_name = owner_info_vec[0];
263                     let mut params = ExtDbMap::new();
264                     params.insert(PARAM_NAME_USER_ID, Value::Number(calling_info.user_id() as u32));
265                     params.insert(PARAM_NAME_BUNDLE_NAME, Value::Bytes(caller_name.as_bytes().to_vec()));
266                     match load.process_event(EventType::CleanCloudFlag, &mut params) {
267                         Ok(()) => logi!("process clean cloud flag ext event success."),
268                         Err(code) => loge!("process clean cloud flag ext event failed, code: {}", code),
269                     }
270                 }
271             },
272             x if *x == OperationType::NeedDeleteCloudData as u32 => {
273                 if let Ok(load) = AssetPlugin::get_instance().load_plugin() {
274                     let mut params = ExtDbMap::new();
275                     params.insert(PARAM_NAME_USER_ID, Value::Number(calling_info.user_id() as u32));
276                     params.insert(PARAM_NAME_BUNDLE_NAME, Value::Bytes(calling_info.owner_info().clone()));
277                     match load.process_event(EventType::DeleteCloudData, &mut params) {
278                         Ok(()) => logi!("process delete cloud data ext event success."),
279                         Err(code) => loge!("process delete cloud data ext event failed, code: {}", code),
280                     }
281                 }
282             },
283             _ => {},
284         }
285     }
286 }
287