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