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