1 /*
2 * Copyright (c) 2021-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 #include "dh_utils_tool.h"
17
18 #include <algorithm>
19 #include <iomanip>
20 #include <iostream>
21 #include <random>
22 #include <sstream>
23 #include <string>
24 #include <sys/time.h>
25 #include <vector>
26 #include <zlib.h>
27
28 #include "openssl/sha.h"
29 #include "parameter.h"
30
31 #include "device_manager.h"
32 #include "dm_device_info.h"
33
34 #include "constants.h"
35 #include "distributed_hardware_errno.h"
36 #include "distributed_hardware_log.h"
37
38 namespace OHOS {
39 namespace DistributedHardware {
40 namespace {
41 constexpr uint32_t MAX_MESSAGE_LEN = 40 * 1024 * 1024;
42 constexpr uint32_t MIN_MESSAGE_LEN = 0;
43 constexpr uint32_t MAX_ID_LEN = 256;
44 constexpr uint32_t MAX_ARR_SIZE = 10000;
45 constexpr uint32_t MAX_JSON_SIZE = 40 * 1024 * 1024;
46 constexpr uint32_t MAX_HASH_SIZE = 64;
47 constexpr uint32_t MAX_KEY_SIZE = 256;
48 constexpr int32_t MS_ONE_SECOND = 1000;
49 constexpr int32_t WORD_WIDTH_8 = 8;
50 constexpr int32_t WORD_WIDTH_4 = 4;
51 constexpr int32_t WIDTH = 4;
52 constexpr unsigned char MASK = 0x0F;
53 constexpr int32_t DOUBLE_TIMES = 2;
54 constexpr int32_t COMPRESS_SLICE_SIZE = 1024;
55 constexpr const char *PARAM_KEY_OS_TYPE = "OS_TYPE";
56 }
57
GetCurrentTime()58 int64_t GetCurrentTime()
59 {
60 struct timeval tv {
61 0
62 };
63 gettimeofday(&tv, nullptr);
64 return tv.tv_sec * MS_ONE_SECOND + tv.tv_usec / MS_ONE_SECOND;
65 }
66
GetRandomID()67 std::string GetRandomID()
68 {
69 static std::random_device rd;
70 static std::uniform_int_distribution<uint64_t> dist(0ULL, 0xFFFFFFFFFFFFFFFFULL);
71 uint64_t ab = dist(rd);
72 uint64_t cd = dist(rd);
73 uint32_t a;
74 uint32_t b;
75 uint32_t c;
76 uint32_t d;
77 std::stringstream ss;
78 ab = (ab & 0xFFFFFFFFFFFF0FFFULL) | 0x0000000000004000ULL;
79 cd = (cd & 0x3FFFFFFFFFFFFFFFULL) | 0x8000000000000000ULL;
80 a = (ab >> 32U);
81 b = (ab & 0xFFFFFFFFU);
82 c = (cd >> 32U);
83 d = (cd & 0xFFFFFFFFU);
84 ss << std::hex << std::nouppercase << std::setfill('0');
85 ss << std::setw(WORD_WIDTH_8) << (a);
86 ss << std::setw(WORD_WIDTH_4) << (b >> 16U);
87 ss << std::setw(WORD_WIDTH_4) << (b & 0xFFFFU);
88 ss << std::setw(WORD_WIDTH_4) << (c >> 16U);
89 ss << std::setw(WORD_WIDTH_4) << (c & 0xFFFFU);
90 ss << std::setw(WORD_WIDTH_8) << d;
91
92 return ss.str();
93 }
94
GetUUIDByDm(const std::string & networkId)95 std::string GetUUIDByDm(const std::string &networkId)
96 {
97 if (!IsIdLengthValid(networkId)) {
98 return "";
99 }
100 std::string uuid = "";
101 auto ret = DeviceManager::GetInstance().GetUuidByNetworkId(DH_FWK_PKG_NAME, networkId, uuid);
102 return (ret == DH_FWK_SUCCESS) ? uuid : "";
103 }
104
GetUDIDByDm(const std::string & networkId)105 std::string GetUDIDByDm(const std::string &networkId)
106 {
107 if (!IsIdLengthValid(networkId)) {
108 return "";
109 }
110 std::string udid = "";
111 auto ret = DeviceManager::GetInstance().GetUdidByNetworkId(DH_FWK_PKG_NAME, networkId, udid);
112 return (ret == DH_FWK_SUCCESS) ? udid : "";
113 }
114
GetDeviceIdByUUID(const std::string & uuid)115 std::string GetDeviceIdByUUID(const std::string &uuid)
116 {
117 if (!IsIdLengthValid(uuid)) {
118 DHLOGE("uuid is invalid!");
119 return "";
120 }
121 return Sha256(uuid);
122 }
123
Sha256(const std::string & in)124 std::string Sha256(const std::string& in)
125 {
126 unsigned char out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES + 1] = {0};
127 SHA256_CTX ctx;
128 SHA256_Init(&ctx);
129 SHA256_Update(&ctx, in.data(), in.size());
130 SHA256_Final(&out[SHA256_DIGEST_LENGTH], &ctx);
131 // here we translate sha256 hash to hexadecimal. each 8-bit char will be presented by two characters([0-9a-f])
132 const char* hexCode = "0123456789abcdef";
133 for (int32_t i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
134 unsigned char value = out[SHA256_DIGEST_LENGTH + i];
135 // uint8_t is 2 digits in hexadecimal.
136 out[i * DOUBLE_TIMES] = hexCode[(value >> WIDTH) & MASK];
137 out[i * DOUBLE_TIMES + 1] = hexCode[value & MASK];
138 }
139 out[SHA256_DIGEST_LENGTH * DOUBLE_TIMES] = 0;
140 return std::string(reinterpret_cast<char*>(out));
141 }
142
GetLocalDeviceInfo()143 DeviceInfo GetLocalDeviceInfo()
144 {
145 DeviceInfo devInfo { "", "", "", "", "", "", 0 };
146 DmDeviceInfo info;
147 auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(DH_FWK_PKG_NAME, info);
148 if (ret != DH_FWK_SUCCESS) {
149 DHLOGE("GetLocalNodeDeviceInfo failed, errCode = %{public}d", ret);
150 return devInfo;
151 }
152 devInfo.networkId = info.networkId;
153 devInfo.uuid = GetUUIDByDm(info.networkId);
154 devInfo.deviceId = GetDeviceIdByUUID(devInfo.uuid);
155 devInfo.udid = GetUDIDByDm(info.networkId);
156 devInfo.udidHash = Sha256(devInfo.udid);
157 devInfo.deviceName = info.deviceName;
158 devInfo.deviceType = info.deviceTypeId;
159 return devInfo;
160 }
161
GetLocalNetworkId()162 std::string GetLocalNetworkId()
163 {
164 DmDeviceInfo info;
165 auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(DH_FWK_PKG_NAME, info);
166 if (ret != DH_FWK_SUCCESS) {
167 DHLOGE("GetLocalNodeDeviceInfo failed, errCode = %{public}d", ret);
168 return "";
169 }
170 return info.networkId;
171 }
172
GetLocalUdid()173 std::string GetLocalUdid()
174 {
175 DmDeviceInfo info;
176 auto ret = DeviceManager::GetInstance().GetLocalDeviceInfo(DH_FWK_PKG_NAME, info);
177 if (ret != DH_FWK_SUCCESS) {
178 DHLOGE("GetLocalNodeDeviceInfo failed, errCode = %{public}d", ret);
179 return "";
180 }
181 return GetUDIDByDm(info.networkId);
182 }
183
IsUInt8(const cJSON * jsonObj)184 bool IsUInt8(const cJSON* jsonObj)
185 {
186 if (jsonObj == NULL || !cJSON_IsNumber(jsonObj)) {
187 return false;
188 }
189 return (jsonObj->valueint >= 0 && static_cast<uint8_t>(jsonObj->valueint) <= UINT8_MAX);
190 }
191
IsUInt16(const cJSON * jsonObj)192 bool IsUInt16(const cJSON* jsonObj)
193 {
194 if (jsonObj == NULL || !cJSON_IsNumber(jsonObj)) {
195 return false;
196 }
197 return (jsonObj->valueint >= 0 && static_cast<uint16_t>(jsonObj->valueint) <= UINT16_MAX);
198 }
199
IsInt32(const cJSON * jsonObj)200 bool IsInt32(const cJSON* jsonObj)
201 {
202 if (jsonObj == NULL || !cJSON_IsNumber(jsonObj)) {
203 return false;
204 }
205 return (jsonObj->valueint >= INT32_MIN && jsonObj->valueint <= INT32_MAX);
206 }
207
IsUInt32(const cJSON * jsonObj)208 bool IsUInt32(const cJSON* jsonObj)
209 {
210 if (jsonObj == NULL || !cJSON_IsNumber(jsonObj)) {
211 return false;
212 }
213 return (jsonObj->valueint >= 0 && static_cast<uint32_t>(jsonObj->valueint) <= UINT32_MAX);
214 }
215
IsBool(const cJSON * jsonObj)216 bool IsBool(const cJSON* jsonObj)
217 {
218 return (jsonObj != NULL && cJSON_IsBool(jsonObj));
219 }
220
IsString(const cJSON * jsonObj)221 bool IsString(const cJSON* jsonObj)
222 {
223 if (jsonObj == NULL || !cJSON_IsString(jsonObj)) {
224 return false;
225 }
226 return (strlen(jsonObj->valuestring) > MIN_MESSAGE_LEN && strlen(jsonObj->valuestring) <= MAX_MESSAGE_LEN);
227 }
228
IsArray(const cJSON * jsonObj)229 bool IsArray(const cJSON* jsonObj)
230 {
231 if (jsonObj == NULL || !cJSON_IsArray(jsonObj)) {
232 return false;
233 }
234 return ((uint32_t)cJSON_GetArraySize(jsonObj) >= 0 && (uint32_t)cJSON_GetArraySize(jsonObj) <= MAX_ARR_SIZE);
235 }
236
Compress(const std::string & data)237 std::string Compress(const std::string& data)
238 {
239 z_stream strm;
240 strm.zalloc = Z_NULL;
241 strm.zfree = Z_NULL;
242 strm.opaque = Z_NULL;
243 deflateInit(&strm, Z_DEFAULT_COMPRESSION);
244
245 strm.next_in = reinterpret_cast<Bytef*>(const_cast<char *>(data.data()));
246 strm.avail_in = data.size();
247 std::string out;
248 std::vector<Bytef> temp_out(COMPRESS_SLICE_SIZE, 0);
249
250 do {
251 strm.next_out = temp_out.data();
252 strm.avail_out = COMPRESS_SLICE_SIZE;
253 deflate(&strm, Z_FINISH);
254 out.append(reinterpret_cast<char*>(temp_out.data()), COMPRESS_SLICE_SIZE - strm.avail_out);
255 } while (strm.avail_out == 0);
256
257 deflateEnd(&strm);
258 return out;
259 }
260
Decompress(const std::string & data)261 std::string Decompress(const std::string& data)
262 {
263 z_stream strm;
264 strm.zalloc = Z_NULL;
265 strm.zfree = Z_NULL;
266 strm.opaque = Z_NULL;
267 strm.avail_in = 0;
268 strm.next_in = Z_NULL;
269 inflateInit(&strm);
270
271 strm.next_in = reinterpret_cast<Bytef*>(const_cast<char *>(data.data()));
272 strm.avail_in = data.size();
273 std::string out;
274 std::vector<Bytef> temp_out(COMPRESS_SLICE_SIZE, 0);
275
276 do {
277 strm.next_out = temp_out.data();
278 strm.avail_out = COMPRESS_SLICE_SIZE;
279 inflate(&strm, Z_NO_FLUSH);
280 out.append(reinterpret_cast<char*>(temp_out.data()), COMPRESS_SLICE_SIZE - strm.avail_out);
281 } while (strm.avail_out == 0);
282
283 inflateEnd(&strm);
284 return out;
285 }
286
GetSysPara(const char * key,bool & value)287 bool GetSysPara(const char *key, bool &value)
288 {
289 if (key == nullptr) {
290 DHLOGE("GetSysPara: key is nullptr");
291 return false;
292 }
293 char paraValue[20] = {0}; // 20 for system parameter
294 auto res = GetParameter(key, "false", paraValue, sizeof(paraValue));
295 if (res <= 0) {
296 DHLOGD("GetSysPara fail, key:%{public}s res:%{public}d", key, res);
297 return false;
298 }
299 DHLOGI("GetSysPara: key:%{public}s value:%{public}s", key, paraValue);
300 std::stringstream valueStr;
301 valueStr << paraValue;
302 valueStr >> std::boolalpha >> value;
303 return true;
304 }
305
IsIdLengthValid(const std::string & inputID)306 bool IsIdLengthValid(const std::string &inputID)
307 {
308 if (inputID.empty() || inputID.length() > MAX_ID_LEN) {
309 DHLOGE("On parameter length error, maybe empty or beyond MAX_ID_LEN!");
310 return false;
311 }
312 return true;
313 }
314
IsMessageLengthValid(const std::string & inputMessage)315 bool IsMessageLengthValid(const std::string &inputMessage)
316 {
317 if (inputMessage.empty() || inputMessage.length() > MAX_MESSAGE_LEN) {
318 DHLOGE("On parameter error, maybe empty or beyond MAX_MESSAGE_LEN!");
319 return false;
320 }
321 return true;
322 }
323
IsJsonLengthValid(const std::string & inputJsonStr)324 bool IsJsonLengthValid(const std::string &inputJsonStr)
325 {
326 if (inputJsonStr.empty() || inputJsonStr.length() > MAX_JSON_SIZE) {
327 DHLOGE("On parameter error, maybe empty or beyond MAX_JSON_SIZE");
328 return false;
329 }
330 return true;
331 }
332
IsArrayLengthValid(const std::vector<std::string> & inputArray)333 bool IsArrayLengthValid(const std::vector<std::string> &inputArray)
334 {
335 if (inputArray.empty() || inputArray.size() > MAX_ARR_SIZE) {
336 DHLOGE("On parameter error, maybe empty or beyond MAX_ARR_SIZE");
337 return false;
338 }
339 return true;
340 }
341
IsKeySizeValid(const std::string & inputKey)342 bool IsKeySizeValid(const std::string &inputKey)
343 {
344 if (inputKey.empty() || inputKey.length() > MAX_KEY_SIZE) {
345 DHLOGE("On parameter error, maybe empty or beyond MAX_KEY_SIZE");
346 return false;
347 }
348 return true;
349 }
350
IsHashSizeValid(const std::string & inputHashValue)351 bool IsHashSizeValid(const std::string &inputHashValue)
352 {
353 if (inputHashValue.empty() || inputHashValue.length() > MAX_HASH_SIZE) {
354 DHLOGE("On parameter error, maybe empty or beyond MAX_HASH_SIZE");
355 return false;
356 }
357 return true;
358 }
359
GetDeviceSystemType(const std::string & extraData)360 int32_t GetDeviceSystemType(const std::string &extraData)
361 {
362 cJSON *jsonObj = cJSON_Parse(extraData.c_str());
363 if (jsonObj == NULL) {
364 DHLOGE("jsonStr parse failed");
365 return ERR_DH_FWK_INVALID_OSTYPE;
366 }
367 cJSON *paramKey = cJSON_GetObjectItem(jsonObj, PARAM_KEY_OS_TYPE);
368 if (paramKey == NULL || !cJSON_IsNumber(paramKey)) {
369 DHLOGE("paramKey is null or paramKey is invaild type!");
370 cJSON_Delete(jsonObj);
371 return ERR_DH_FWK_INVALID_OSTYPE;
372 }
373 int32_t osType = paramKey->valueint;
374 cJSON_Delete(jsonObj);
375 return osType;
376 }
377 } // namespace DistributedHardware
378 } // namespace OHOS
379