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 #include <algorithm>
17 #include <climits>
18 #include <cmath>
19 #include <functional>
20 #include <unordered_map>
21 #include <vector>
22
23 #include "securec.h"
24
25 #include "asset_log.h"
26 #include "asset_system_api.h"
27 #include "asset_system_type.h"
28
29 #include "asset_napi_check.h"
30 #include "asset_napi_common.h"
31
32 namespace OHOS {
33 namespace Security {
34 namespace Asset {
35 namespace {
36
37 #define MIN_ARRAY_SIZE 0
38 #define MAX_SECRET_SIZE 1024
39 #define MAX_ALIAS_SIZE 256
40 #define MIN_NUMBER_VALUE 0
41 #define MAX_AUTH_VALID_PERIOD 600
42 #define CHALLENGE_SIZE 32
43 #define AUTH_TOKEN_SIZE 280
44 #define MAX_LABEL_SIZE 2048
45 #define MAX_RETURN_LIMIT 0x10000
46 #define SYNC_TYPE_MIN_BITS 0
47 #define SYNC_TYPE_MAX_BITS 3
48 #define ROOT_USER_UPPERBOUND 99
49 #define MAX_TIME_SIZE 1024
50 #define SYSTEM_USER_ID_MAX 99
51 #define BINARY_BASE 2
52 #define MIN_GROUP_ID_SIZE 7
53 #define MAX_GROUP_ID_SIZE 127
54
CheckArraySize(const napi_env env,const AssetAttr & attr,uint32_t min,uint32_t max)55 bool CheckArraySize(const napi_env env, const AssetAttr &attr, uint32_t min, uint32_t max)
56 {
57 if (attr.value.blob.size > max || attr.value.blob.size <= min) {
58 NAPI_THROW_INVALID_ARGUMENT(env,
59 "Value byte length[%u] of tag[asset.Tag.%s] is out of range[%u, %u].",
60 attr.value.blob.size, TAG_MAP.at(attr.tag), min + 1, max);
61 return false;
62 }
63 return true;
64 }
65
CheckEnumVariant(const napi_env env,const AssetAttr & attr,const std::vector<uint32_t> & enumVec)66 bool CheckEnumVariant(const napi_env env, const AssetAttr &attr, const std::vector<uint32_t> &enumVec)
67 {
68 auto it = std::find(enumVec.begin(), enumVec.end(), attr.value.u32);
69 if (it == enumVec.end()) {
70 NAPI_THROW_INVALID_ARGUMENT(env,
71 "Value[%u] of tag[asset.Tag.%s] is an illegal enumeration variant.",
72 attr.value.u32, TAG_MAP.at(attr.tag));
73 return false;
74 }
75 return true;
76 }
77
CheckNumberRange(const napi_env env,const AssetAttr & attr,uint32_t min,uint32_t max)78 bool CheckNumberRange(const napi_env env, const AssetAttr &attr, uint32_t min, uint32_t max)
79 {
80 if (attr.value.u32 > max || attr.value.u32 <= min) {
81 NAPI_THROW_INVALID_ARGUMENT(env,
82 "Value[%u] of tag[asset.Tag.%s] is out of range[%u, %u].",
83 attr.value.u32, TAG_MAP.at(attr.tag), min, max);
84 return false;
85 }
86 return true;
87 }
88
CheckValidBits(const napi_env env,const AssetAttr & attr,uint32_t minBits,uint32_t maxBits)89 bool CheckValidBits(const napi_env env, const AssetAttr &attr, uint32_t minBits, uint32_t maxBits)
90 {
91 if (attr.value.u32 >= pow(BINARY_BASE, maxBits) || attr.value.u32 < pow(BINARY_BASE, minBits) - 1) {
92 NAPI_THROW_INVALID_ARGUMENT(env,
93 "Value[%u] of tag[asset.Tag.%s] has bit count out of range[%u, %u].",
94 attr.value.u32, TAG_MAP.at(attr.tag), minBits + 1, maxBits);
95 return false;
96 }
97 return true;
98 }
99
CheckTagRange(const napi_env env,const AssetAttr & attr,const std::vector<uint32_t> & tags)100 bool CheckTagRange(const napi_env env, const AssetAttr &attr, const std::vector<uint32_t> &tags)
101 {
102 auto it = std::find(tags.begin(), tags.end(), attr.value.u32);
103 if (it == tags.end()) {
104 NAPI_THROW_INVALID_ARGUMENT(env,
105 "Value[0x%X] of tag[asset.Tag.(%s)] is not tags allowed for sorting, "
106 "which should start with \"DATA_LABEL\".", attr.value.u32, TAG_MAP.at(attr.tag));
107 return false;
108 }
109 return true;
110 }
111
112 struct CheckContinuousRange {
113 std::function<bool(const napi_env, const AssetAttr &, uint32_t, uint32_t)> funcPtr;
114 uint32_t min;
115 uint32_t max;
116 };
117
118 const std::unordered_map<uint32_t, CheckContinuousRange> CHECK_CONTINOUS_RANGE_FUNC_MAP = {
119 { SEC_ASSET_TAG_SECRET, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_SECRET_SIZE } },
120 { SEC_ASSET_TAG_ALIAS, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_ALIAS_SIZE } },
121 { SEC_ASSET_TAG_AUTH_VALIDITY_PERIOD, { &CheckNumberRange, MIN_NUMBER_VALUE, MAX_AUTH_VALID_PERIOD } },
122 { SEC_ASSET_TAG_AUTH_CHALLENGE, { &CheckArraySize, CHALLENGE_SIZE - 1, CHALLENGE_SIZE } },
123 { SEC_ASSET_TAG_AUTH_TOKEN, { &CheckArraySize, AUTH_TOKEN_SIZE - 1, AUTH_TOKEN_SIZE } },
124 { SEC_ASSET_TAG_SYNC_TYPE, { &CheckValidBits, SYNC_TYPE_MIN_BITS, SYNC_TYPE_MAX_BITS } },
125 { SEC_ASSET_TAG_DATA_LABEL_CRITICAL_1, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
126 { SEC_ASSET_TAG_DATA_LABEL_CRITICAL_2, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
127 { SEC_ASSET_TAG_DATA_LABEL_CRITICAL_3, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
128 { SEC_ASSET_TAG_DATA_LABEL_CRITICAL_4, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
129 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_1, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
130 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_2, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
131 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_3, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
132 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_4, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
133 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_LOCAL_1, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
134 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_LOCAL_2, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
135 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_LOCAL_3, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
136 { SEC_ASSET_TAG_DATA_LABEL_NORMAL_LOCAL_4, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_LABEL_SIZE } },
137 { SEC_ASSET_TAG_RETURN_LIMIT, { &CheckNumberRange, MIN_NUMBER_VALUE, MAX_RETURN_LIMIT } },
138 { SEC_ASSET_TAG_GROUP_ID, { &CheckArraySize, MIN_GROUP_ID_SIZE, MAX_GROUP_ID_SIZE } },
139 { SEC_ASSET_TAG_USER_ID, { &CheckNumberRange, ROOT_USER_UPPERBOUND, INT32_MAX } },
140 { SEC_ASSET_TAG_UPDATE_TIME, { &CheckArraySize, MIN_ARRAY_SIZE, MAX_TIME_SIZE } }
141 };
142
143 struct CheckDiscreteRange {
144 std::function<bool(const napi_env, const AssetAttr &, const std::vector<uint32_t> &)> funcPtr;
145 const std::vector<uint32_t> validRange;
146 };
147
148 const std::unordered_map<uint32_t, CheckDiscreteRange> CHECK_DISCRETE_RANGE_FUNC_MAP = {
149 { SEC_ASSET_TAG_ACCESSIBILITY, { &CheckEnumVariant, ASSET_ACCESSIBILITY_VEC } },
150 { SEC_ASSET_TAG_AUTH_TYPE, { &CheckEnumVariant, ASSET_AUTH_TYPE_VEC } },
151 { SEC_ASSET_TAG_CONFLICT_RESOLUTION, { &CheckEnumVariant, ASSET_CONFLICT_RESOLUTION_VEC } },
152 { SEC_ASSET_TAG_RETURN_TYPE, { &CheckEnumVariant, ASSET_RETURN_TYPE_VEC } },
153 { SEC_ASSET_TAG_RETURN_ORDERED_BY, { &CheckTagRange, ASSET_RETURN_ORDER_BY_TAGS } },
154 { SEC_ASSET_TAG_WRAP_TYPE, { &CheckEnumVariant, ASSET_WRAP_TYPE_VEC } }
155 };
156
157 } // anonymous namespace
158
CheckAssetRequiredTag(const napi_env env,const std::vector<AssetAttr> & attrs,const std::vector<uint32_t> & requiredTags)159 bool CheckAssetRequiredTag(const napi_env env, const std::vector<AssetAttr> &attrs,
160 const std::vector<uint32_t> &requiredTags)
161 {
162 for (uint32_t requiredTag : requiredTags) {
163 auto it = std::find_if(attrs.begin(), attrs.end(), [requiredTag](const AssetAttr &attr) {
164 return attr.tag == requiredTag;
165 });
166 if (it == attrs.end()) {
167 NAPI_THROW_INVALID_ARGUMENT(env, "Missing required tag[asset.Tag.%s].", TAG_MAP.at(requiredTag));
168 return false;
169 }
170 }
171 return true;
172 }
173
CheckAssetTagValidity(const napi_env env,const std::vector<AssetAttr> & attrs,const std::vector<uint32_t> & validTags)174 bool CheckAssetTagValidity(const napi_env env, const std::vector<AssetAttr> &attrs,
175 const std::vector<uint32_t> &validTags)
176 {
177 for (AssetAttr attr : attrs) {
178 if (std::count(validTags.begin(), validTags.end(), attr.tag) == 0) {
179 NAPI_THROW_INVALID_ARGUMENT(env, "Unsupported tag[asset.Tag.%s] for the function.",
180 TAG_MAP.at(attr.tag));
181 return false;
182 }
183 }
184 return true;
185 }
186
CheckAssetValueValidity(const napi_env env,const std::vector<AssetAttr> & attrs)187 bool CheckAssetValueValidity(const napi_env env, const std::vector<AssetAttr> &attrs)
188 {
189 return std::all_of(attrs.begin(), attrs.end(), [env](const AssetAttr &attr) {
190 if (CHECK_CONTINOUS_RANGE_FUNC_MAP.find(attr.tag) != CHECK_CONTINOUS_RANGE_FUNC_MAP.end()) {
191 auto funcPtr = CHECK_CONTINOUS_RANGE_FUNC_MAP.at(attr.tag).funcPtr;
192 uint32_t min = CHECK_CONTINOUS_RANGE_FUNC_MAP.at(attr.tag).min;
193 uint32_t max = CHECK_CONTINOUS_RANGE_FUNC_MAP.at(attr.tag).max;
194 return funcPtr(env, attr, min, max);
195 }
196 if (CHECK_DISCRETE_RANGE_FUNC_MAP.find(attr.tag) != CHECK_DISCRETE_RANGE_FUNC_MAP.end()) {
197 auto funcPtr = CHECK_DISCRETE_RANGE_FUNC_MAP.at(attr.tag).funcPtr;
198 auto validRangePtr = CHECK_DISCRETE_RANGE_FUNC_MAP.at(attr.tag).validRange;
199 return funcPtr(env, attr, validRangePtr);
200 }
201 return true;
202 });
203 }
204
205 } // Asset
206 } // Security
207 } // OHOS
208