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 38namespace OHOS { 39namespace DistributedHardware { 40namespace { 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 51int64_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 60std::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 88std::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 98std::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 108std::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 117std::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 136DeviceInfo 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 155std::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 166bool IsUInt8(const cJSON* jsonObj, const std::string& key) 167{ 168 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 169 if (value == NULL || !cJSON_IsNumber(value)) { 170 return false; 171 } 172 return (value->valuedouble >= 0 && value->valuedouble <= UINT8_MAX); 173} 174 175bool IsUInt16(const cJSON* jsonObj, const std::string& key) 176{ 177 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 178 if (value == NULL || !cJSON_IsNumber(value)) { 179 return false; 180 } 181 return (value->valuedouble >= 0 && value->valuedouble <= UINT16_MAX); 182} 183 184bool IsInt32(const cJSON* jsonObj, const std::string& key) 185{ 186 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 187 if (value == NULL || !cJSON_IsNumber(value)) { 188 return false; 189 } 190 return (value->valuedouble >= INT32_MIN && value->valuedouble <= INT32_MAX); 191} 192 193bool IsUInt32(const cJSON* jsonObj, const std::string& key) 194{ 195 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 196 if (value == NULL || !cJSON_IsNumber(value)) { 197 return false; 198 } 199 return (value->valuedouble >= 0 && value->valuedouble <= UINT32_MAX); 200} 201 202bool IsBool(const cJSON* jsonObj, const std::string& key) 203{ 204 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 205 return (value != NULL && cJSON_IsBool(value)); 206} 207 208bool IsString(const cJSON* jsonObj, const std::string& key) 209{ 210 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 211 if (value == NULL || !cJSON_IsString(value)) { 212 return false; 213 } 214 return (strlen(value->valuestring) > MIN_MESSAGE_LEN && strlen(value->valuestring) <= MAX_MESSAGE_LEN); 215} 216 217bool IsArray(const cJSON* jsonObj, const std::string& key) 218{ 219 const cJSON* value = cJSON_GetObjectItem(jsonObj, key.c_str()); 220 if (value == NULL || !cJSON_IsArray(value)) { 221 return false; 222 } 223 return ((uint32_t)cJSON_GetArraySize(value) >= 0 && (uint32_t)cJSON_GetArraySize(value) <= MAX_ARR_SIZE); 224} 225 226std::string Compress(const std::string& data) 227{ 228 z_stream strm; 229 strm.zalloc = Z_NULL; 230 strm.zfree = Z_NULL; 231 strm.opaque = Z_NULL; 232 deflateInit(&strm, Z_DEFAULT_COMPRESSION); 233 234 strm.next_in = reinterpret_cast<Bytef*>(const_cast<char *>(data.data())); 235 strm.avail_in = data.size(); 236 std::string out; 237 std::vector<Bytef> temp_out(COMPRESS_SLICE_SIZE, 0); 238 239 do { 240 strm.next_out = temp_out.data(); 241 strm.avail_out = COMPRESS_SLICE_SIZE; 242 deflate(&strm, Z_FINISH); 243 out.append(reinterpret_cast<char*>(temp_out.data()), COMPRESS_SLICE_SIZE - strm.avail_out); 244 } while (strm.avail_out == 0); 245 246 deflateEnd(&strm); 247 return out; 248} 249 250std::string Decompress(const std::string& data) 251{ 252 z_stream strm; 253 strm.zalloc = Z_NULL; 254 strm.zfree = Z_NULL; 255 strm.opaque = Z_NULL; 256 strm.avail_in = 0; 257 strm.next_in = Z_NULL; 258 inflateInit(&strm); 259 260 strm.next_in = reinterpret_cast<Bytef*>(const_cast<char *>(data.data())); 261 strm.avail_in = data.size(); 262 std::string out; 263 std::vector<Bytef> temp_out(COMPRESS_SLICE_SIZE, 0); 264 265 do { 266 strm.next_out = temp_out.data(); 267 strm.avail_out = COMPRESS_SLICE_SIZE; 268 inflate(&strm, Z_NO_FLUSH); 269 out.append(reinterpret_cast<char*>(temp_out.data()), COMPRESS_SLICE_SIZE - strm.avail_out); 270 } while (strm.avail_out == 0); 271 272 inflateEnd(&strm); 273 return out; 274} 275 276bool GetSysPara(const char *key, bool &value) 277{ 278 if (key == nullptr) { 279 DHLOGE("GetSysPara: key is nullptr"); 280 return false; 281 } 282 char paraValue[20] = {0}; // 20 for system parameter 283 auto res = GetParameter(key, "false", paraValue, sizeof(paraValue)); 284 if (res <= 0) { 285 DHLOGD("GetSysPara fail, key:%{public}s res:%{public}d", key, res); 286 return false; 287 } 288 DHLOGI("GetSysPara: key:%{public}s value:%{public}s", key, paraValue); 289 std::stringstream valueStr; 290 valueStr << paraValue; 291 valueStr >> std::boolalpha >> value; 292 return true; 293} 294 295bool IsIdLengthValid(const std::string &inputID) 296{ 297 if (inputID.empty() || inputID.length() > MAX_ID_LEN) { 298 DHLOGE("On parameter length error, maybe empty or beyond MAX_ID_LEN!"); 299 return false; 300 } 301 return true; 302} 303 304bool IsMessageLengthValid(const std::string &inputMessage) 305{ 306 if (inputMessage.empty() || inputMessage.length() > MAX_MESSAGE_LEN) { 307 DHLOGE("On parameter error, maybe empty or beyond MAX_MESSAGE_LEN!"); 308 return false; 309 } 310 return true; 311} 312 313bool IsJsonLengthValid(const std::string &inputJsonStr) 314{ 315 if (inputJsonStr.empty() || inputJsonStr.length() > MAX_JSON_SIZE) { 316 DHLOGE("On parameter error, maybe empty or beyond MAX_JSON_SIZE"); 317 return false; 318 } 319 return true; 320} 321 322bool IsArrayLengthValid(const std::vector<std::string> &inputArray) 323{ 324 if (inputArray.empty() || inputArray.size() > MAX_ARR_SIZE) { 325 DHLOGE("On parameter error, maybe empty or beyond MAX_ARR_SIZE"); 326 return false; 327 } 328 return true; 329} 330 331bool IsKeySizeValid(const std::string &inputKey) 332{ 333 if (inputKey.empty() || inputKey.length() > MAX_KEY_SIZE) { 334 DHLOGE("On parameter error, maybe empty or beyond MAX_KEY_SIZE"); 335 return false; 336 } 337 return true; 338} 339 340bool IsHashSizeValid(const std::string &inputHashValue) 341{ 342 if (inputHashValue.empty() || inputHashValue.length() > MAX_HASH_SIZE) { 343 DHLOGE("On parameter error, maybe empty or beyond MAX_HASH_SIZE"); 344 return false; 345 } 346 return true; 347} 348 349int32_t GetDeviceSystemType(const std::string &extraData) 350{ 351 cJSON *jsonObj = cJSON_Parse(extraData.c_str()); 352 if (jsonObj == NULL) { 353 DHLOGE("jsonStr parse failed"); 354 return ERR_DH_FWK_INVALID_OSTYPE; 355 } 356 cJSON *paramKey = cJSON_GetObjectItem(jsonObj, PARAM_KEY_OS_TYPE.c_str()); 357 if (paramKey == NULL || !cJSON_IsNumber(paramKey)) { 358 DHLOGE("paramKey is null or paramKey is invaild type!"); 359 cJSON_Delete(jsonObj); 360 return ERR_DH_FWK_INVALID_OSTYPE; 361 } 362 int32_t osType = paramKey->valueint; 363 cJSON_Delete(jsonObj); 364 return osType; 365} 366} // namespace DistributedHardware 367} // namespace OHOS 368