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