• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 verify the validity of asset attributes.
17 
18 use asset_common::{is_user_id_exist, CallingInfo, OwnerType, ROOT_USER_UPPERBOUND};
19 use asset_definition::{
20     log_throw_error, Accessibility, AssetMap, AuthType, ConflictResolution, Conversion, ErrCode, OperationType, Result,
21     ReturnType, Tag, Value,
22 };
23 use asset_sdk::WrapType;
24 
25 use crate::operations::common::{CRITICAL_LABEL_ATTRS, NORMAL_LABEL_ATTRS, NORMAL_LOCAL_LABEL_ATTRS};
26 
27 const MIN_NUMBER_VALUE: u32 = 0;
28 const MAX_RETURN_LIMIT: u32 = 0x10000; // 65536
29 const MAX_AUTH_VALID_PERIOD: u32 = 600; // 10min
30 
31 const MIN_ARRAY_SIZE: usize = 0;
32 const MAX_SECRET_SIZE: usize = 1024;
33 const MAX_TIME_SIZE: usize = 1024;
34 
35 const MAX_ALIAS_SIZE: usize = 256;
36 pub const MAX_LABEL_SIZE: usize = 2048;
37 
38 const MAX_GROUP_ID_LEN: usize = 127;
39 const MIN_GROUP_ID_LEN: usize = 7;
40 
41 const MAX_AUTH_TOKEN_SIZE: usize = 1024;
42 const CHALLENGE_SIZE: usize = 32;
43 const SYNC_TYPE_MIN_BITS: u32 = 0;
44 const SYNC_TYPE_MAX_BITS: u32 = 3;
45 
check_data_type(tag: &Tag, value: &Value) -> Result<()>46 fn check_data_type(tag: &Tag, value: &Value) -> Result<()> {
47     if tag.data_type() != value.data_type() {
48         return log_throw_error!(
49             ErrCode::InvalidArgument,
50             "[FATAL]The data type[{}] of the tag[{}] does not match that of the value.",
51             value.data_type(),
52             tag
53         );
54     }
55     Ok(())
56 }
57 
check_array_size(tag: &Tag, value: &Value, min: usize, max: usize) -> Result<()>58 fn check_array_size(tag: &Tag, value: &Value, min: usize, max: usize) -> Result<()> {
59     let Value::Bytes(v) = value else {
60         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a bytes.", tag);
61     };
62     if v.len() > max || v.len() <= min {
63         return log_throw_error!(
64             ErrCode::InvalidArgument,
65             "[FATAL]The array length[{}] of Tag[{}], exceeds the valid range.",
66             v.len(),
67             tag
68         );
69     }
70     Ok(())
71 }
72 
check_enum_variant<T: TryFrom<u32>>(tag: &Tag, value: &Value) -> Result<()>73 fn check_enum_variant<T: TryFrom<u32>>(tag: &Tag, value: &Value) -> Result<()> {
74     let Value::Number(n) = value else {
75         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a number.", tag);
76     };
77     if T::try_from(*n).is_err() {
78         return log_throw_error!(
79             ErrCode::InvalidArgument,
80             "[FATAL]The value[{}] of Tag[{}] is not a legal enumeration variant",
81             *n,
82             tag
83         );
84     }
85     Ok(())
86 }
87 
check_valid_bits(tag: &Tag, value: &Value, min_bits: u32, max_bits: u32) -> Result<()>88 fn check_valid_bits(tag: &Tag, value: &Value, min_bits: u32, max_bits: u32) -> Result<()> {
89     let Value::Number(n) = value else {
90         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a number.", tag);
91     };
92     if *n >= 2_u32.pow(max_bits) || *n < (2_u32.pow(min_bits) - 1) {
93         // 2: binary system
94         return log_throw_error!(
95             ErrCode::InvalidArgument,
96             "[FATAL]The value[{}] of Tag[{}] is not in the valid bit number.",
97             *n,
98             tag
99         );
100     }
101     Ok(())
102 }
103 
check_number_range(tag: &Tag, value: &Value, min: u32, max: u32) -> Result<()>104 fn check_number_range(tag: &Tag, value: &Value, min: u32, max: u32) -> Result<()> {
105     let Value::Number(n) = value else {
106         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a number.", tag);
107     };
108     if *n <= min || *n > max {
109         return log_throw_error!(
110             ErrCode::InvalidArgument,
111             "[FATAL]The value[{}] of Tag[{}] is not in the valid number range.",
112             *n,
113             tag
114         );
115     }
116     Ok(())
117 }
118 
check_tag_range(tag: &Tag, value: &Value, tags: &[Tag]) -> Result<()>119 fn check_tag_range(tag: &Tag, value: &Value, tags: &[Tag]) -> Result<()> {
120     let Value::Number(n) = value else {
121         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a number.", tag);
122     };
123     match Tag::try_from(*n) {
124         Ok(value) if tags.contains(&value) => Ok(()),
125         _ => {
126             log_throw_error!(
127                 ErrCode::InvalidArgument,
128                 "[FATAL]The value[{}] of Tag[{}] is not in the valid tag range.",
129                 *n,
130                 tag
131             )
132         },
133     }
134 }
135 
check_user_id(tag: &Tag, value: &Value) -> Result<()>136 fn check_user_id(tag: &Tag, value: &Value) -> Result<()> {
137     check_number_range(tag, value, ROOT_USER_UPPERBOUND, i32::MAX as u32)?;
138     let Value::Number(n) = value else {
139         return log_throw_error!(ErrCode::InvalidArgument, "[FATAL][{}] is not a number.", tag);
140     };
141     match is_user_id_exist(*n as i32) {
142         Ok(res) if res => Ok(()),
143         Ok(_) => log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The user id [{}] is not exist.", *n),
144         Err(e) => Err(e),
145     }
146 }
147 
check_data_value(tag: &Tag, value: &Value) -> Result<()>148 fn check_data_value(tag: &Tag, value: &Value) -> Result<()> {
149     match tag {
150         Tag::Secret => check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_SECRET_SIZE),
151         Tag::Alias => check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_ALIAS_SIZE),
152         Tag::Accessibility => check_enum_variant::<Accessibility>(tag, value),
153         Tag::RequirePasswordSet | Tag::IsPersistent | Tag::RequireAttrEncrypted => Ok(()),
154         Tag::AuthType => check_enum_variant::<AuthType>(tag, value),
155         Tag::AuthValidityPeriod => check_number_range(tag, value, MIN_NUMBER_VALUE, MAX_AUTH_VALID_PERIOD),
156         Tag::AuthChallenge => check_array_size(tag, value, CHALLENGE_SIZE - 1, CHALLENGE_SIZE),
157         Tag::AuthToken => check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_AUTH_TOKEN_SIZE),
158         Tag::SyncType => check_valid_bits(tag, value, SYNC_TYPE_MIN_BITS, SYNC_TYPE_MAX_BITS),
159         Tag::ConflictResolution => check_enum_variant::<ConflictResolution>(tag, value),
160         Tag::DataLabelCritical1 | Tag::DataLabelCritical2 | Tag::DataLabelCritical3 | Tag::DataLabelCritical4 => {
161             check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_LABEL_SIZE)
162         },
163         Tag::DataLabelNormal1 | Tag::DataLabelNormal2 | Tag::DataLabelNormal3 | Tag::DataLabelNormal4 => {
164             check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_LABEL_SIZE)
165         },
166         Tag::DataLabelNormalLocal1
167         | Tag::DataLabelNormalLocal2
168         | Tag::DataLabelNormalLocal3
169         | Tag::DataLabelNormalLocal4 => check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_LABEL_SIZE),
170         Tag::ReturnType => check_enum_variant::<ReturnType>(tag, value),
171         Tag::ReturnLimit => check_number_range(tag, value, MIN_NUMBER_VALUE, MAX_RETURN_LIMIT),
172         Tag::ReturnOffset => Ok(()),
173         Tag::ReturnOrderedBy => {
174             check_tag_range(tag, value, &[CRITICAL_LABEL_ATTRS, NORMAL_LABEL_ATTRS, NORMAL_LOCAL_LABEL_ATTRS].concat())
175         },
176         Tag::UserId => check_user_id(tag, value),
177         Tag::UpdateTime => check_array_size(tag, value, MIN_ARRAY_SIZE, MAX_TIME_SIZE),
178         Tag::OperationType => check_enum_variant::<OperationType>(tag, value),
179         Tag::GroupId => check_array_size(tag, value, MIN_GROUP_ID_LEN, MAX_GROUP_ID_LEN),
180         Tag::WrapType => check_enum_variant::<WrapType>(tag, value),
181     }
182 }
183 
check_value_validity(attrs: &AssetMap) -> Result<()>184 pub(crate) fn check_value_validity(attrs: &AssetMap) -> Result<()> {
185     for (tag, value) in attrs {
186         check_data_type(tag, value)?;
187         check_data_value(tag, value)?;
188     }
189     Ok(())
190 }
191 
check_required_tags(attrs: &AssetMap, required_tags: &[Tag]) -> Result<()>192 pub(crate) fn check_required_tags(attrs: &AssetMap, required_tags: &[Tag]) -> Result<()> {
193     for tag in required_tags {
194         if !attrs.contains_key(tag) {
195             return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The required tag [{}] is missing.", tag);
196         }
197     }
198     Ok(())
199 }
200 
check_tag_validity(attrs: &AssetMap, valid_tags: &[Tag]) -> Result<()>201 pub(crate) fn check_tag_validity(attrs: &AssetMap, valid_tags: &[Tag]) -> Result<()> {
202     for tag in attrs.keys() {
203         if !valid_tags.contains(tag) {
204             return log_throw_error!(ErrCode::InvalidArgument, "[FATAL]The tag [{}] is illegal.", tag);
205         }
206     }
207     Ok(())
208 }
209 
check_group_validity(attrs: &AssetMap, calling_info: &CallingInfo) -> Result<()>210 pub(crate) fn check_group_validity(attrs: &AssetMap, calling_info: &CallingInfo) -> Result<()> {
211     if attrs.get(&Tag::GroupId).is_some() {
212         if let Some(Value::Bool(true)) = attrs.get(&Tag::IsPersistent) {
213             return log_throw_error!(
214                 ErrCode::InvalidArgument,
215                 "[FATAL]The value of the tag [{}] cannot be set to true when the tag [{}] is specified.",
216                 &Tag::IsPersistent,
217                 &Tag::GroupId
218             );
219         }
220         if calling_info.owner_type_enum() == OwnerType::Native {
221             return log_throw_error!(
222                 ErrCode::Unsupported,
223                 "[FATAL]The tag [{}] is not yet supported for [{}] owner.",
224                 &Tag::GroupId,
225                 OwnerType::Native
226             );
227         }
228         if calling_info.app_index() > 0 {
229             return log_throw_error!(
230                 ErrCode::Unsupported,
231                 "[FATAL]The tag [{}] is not yet supported for clone or sandbox app.",
232                 &Tag::GroupId
233             );
234         }
235     }
236     Ok(())
237 }
238