1 /* 2 * Copyright (c) 2022 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 "commonlibrary/ets_utils/js_util_module/util/js_uuid.h" 17 18 #include <map> 19 #include "securec.h" 20 #include "tools/log.h" 21 22 #include "napi/native_api.h" 23 #include "napi/native_node_api.h" 24 25 namespace OHOS::Util { 26 static thread_local std::queue<UUID> g_uuidCache; 27 CharToHex(char in)28 unsigned char CharToHex(char in) 29 { 30 unsigned char res = 0; // 0: initialization 31 static const std::map<char, unsigned char> hexMap = { 32 {'0', HEX_ZERO_FLG}, 33 {'1', HEX_ONE_FLG}, 34 {'2', HEX_TWO_FLG}, 35 {'3', HEX_THREE_FLG}, 36 {'4', HEX_FOUR_FLG}, 37 {'5', HEX_FIVE_FLG}, 38 {'6', HEX_SIX_FLG}, 39 {'7', HEX_SEVEN_FLG}, 40 {'8', HEX_EIGHT_FLG}, 41 {'9', HEX_NINE_FLG}, 42 {'a', HEX_TEN_FLG}, 43 {'b', HEX_ELEVEN_FLG}, 44 {'c', HEX_TWELVE_FLG}, 45 {'d', HEX_THIRTEEN_FLG}, 46 {'e', HEX_FOURTEEN_FLG}, 47 {'f', HEX_FIFTEEN_FLG}, 48 {'A', HEX_TEN_FLG}, 49 {'B', HEX_ELEVEN_FLG}, 50 {'C', HEX_TWELVE_FLG}, 51 {'D', HEX_THIRTEEN_FLG}, 52 {'E', HEX_FOURTEEN_FLG}, 53 {'F', HEX_FIFTEEN_FLG} 54 }; 55 56 auto it = hexMap.find(in); 57 if (it != hexMap.end()) { 58 res = it->second; 59 } else { 60 res = HEX_ZERO_FLG; 61 } 62 return res; 63 } 64 HexToChar(unsigned char in)65 unsigned char HexToChar(unsigned char in) 66 { 67 unsigned char res = '0'; 68 switch (in) { 69 case HEX_ZERO_FLG: res = '0'; break; 70 case HEX_ONE_FLG: res = '1'; break; 71 case HEX_TWO_FLG: res = '2'; break; 72 case HEX_THREE_FLG: res = '3'; break; 73 case HEX_FOUR_FLG: res = '4'; break; 74 case HEX_FIVE_FLG: res = '5'; break; 75 case HEX_SIX_FLG: res = '6'; break; 76 case HEX_SEVEN_FLG: res = '7'; break; 77 case HEX_EIGHT_FLG: res = '8'; break; 78 case HEX_NINE_FLG: res = '9'; break; 79 case HEX_TEN_FLG: res = 'a'; break; 80 case HEX_ELEVEN_FLG: res = 'b'; break; 81 case HEX_TWELVE_FLG: res = 'c'; break; 82 case HEX_THIRTEEN_FLG: res = 'd'; break; 83 case HEX_FOURTEEN_FLG: res = 'e'; break; 84 case HEX_FIFTEEN_FLG: res = 'f'; break; 85 default : res = 'x'; 86 } 87 return res; 88 } 89 ConvertBits(std::string & input)90 unsigned char ConvertBits(std::string &input) 91 { 92 unsigned char temp = 0; // 0: initialization 93 if (input[0] == '-') { 94 input.erase(0, 1); 95 } 96 temp = CharToHex(input[0]); 97 temp *= HEX_SIXTEEN_FLG; 98 input.erase(0, 1); 99 temp += CharToHex(input[0]); 100 input.erase(0, 1); 101 return temp; 102 } 103 GenerateUuid(unsigned char * data,int32_t size)104 bool GenerateUuid(unsigned char *data, int32_t size) 105 { 106 unsigned char buf[UUID_SIZE] = { 0 }; // 0: initialization 107 if (memcpy_s(data, size, buf, size) != EOK) { 108 return false; 109 } 110 RAND_priv_bytes(data, size); 111 data[HEX_SIX_FLG] = (data[HEX_SIX_FLG] & 0x0F) | 0x40; // 0x0F,0x40 Operate the mark 112 int m = 0x8; // Upper of numerical range 113 int n = 0xb; // down of numerical range 114 int r = static_cast<int>(data[HEX_EIGHT_FLG]); 115 unsigned char num = static_cast<unsigned char>(r % (n - m + 1) + m); 116 data[HEX_EIGHT_FLG] = (data[HEX_EIGHT_FLG] & 0x0F) | (num << 4); // 0x0F,4 Operate the mark 117 return true; 118 } 119 GetUUID(napi_env env,bool entropyCache,UUID & uuid)120 bool GetUUID(napi_env env, bool entropyCache, UUID &uuid) 121 { 122 uint32_t size = g_uuidCache.size(); 123 if ((entropyCache == true) && (size != 0)) { 124 uuid = g_uuidCache.front(); 125 g_uuidCache.pop(); 126 } else { 127 if (size > MAX_CACHE_MASK) { 128 for (uint32_t i = 0; i < size; i++) { 129 g_uuidCache.pop(); 130 } 131 } 132 bool res = GenerateUuid(uuid.elements, sizeof(uuid.elements)); 133 if (!res) { 134 napi_throw_error(env, "-1", "uuid generate failed"); 135 return false; 136 } 137 g_uuidCache.push(uuid); 138 res = GenerateUuid(uuid.elements, sizeof(uuid.elements)); 139 if (!res) { 140 napi_throw_error(env, "-1", "uuid generate failed"); 141 return false; 142 } 143 } 144 return true; 145 } 146 GetStringUUID(napi_env env,bool entropyCache)147 std::string GetStringUUID(napi_env env, bool entropyCache) 148 { 149 UUID uuid; 150 std::string uuidString = ""; 151 if (!GetUUID(env, entropyCache, uuid)) { 152 uuidString = '0'; 153 } else { 154 uuidString = GetFormatUUID(uuid); 155 } 156 return uuidString; 157 } 158 GetFormatUUID(const UUID & uuid)159 std::string GetFormatUUID(const UUID &uuid) 160 { 161 std::string format = ""; 162 for (size_t i = 0; i < sizeof(uuid.elements); i++) { 163 unsigned char value = uuid.elements[i]; 164 if (i >= HEX_FOUR_FLG && i % 2 == 0 && i <= HEX_TEN_FLG) { // 2: step value 165 format += "-"; 166 } 167 format += HexToChar(value >> HEX_FOUR_FLG); 168 unsigned char high = value & 0xF0; // Operate the mark 169 if (high == 0) { 170 format += HexToChar(value); 171 } else { 172 format += HexToChar(value % (value & high)); 173 } 174 } 175 return format; 176 } 177 GetBinaryUUID(napi_env env,bool entropyCache)178 napi_value GetBinaryUUID(napi_env env, bool entropyCache) 179 { 180 UUID uuid; 181 if (!GetUUID(env, entropyCache, uuid)) { 182 return nullptr; 183 } 184 void *data = nullptr; 185 napi_value arrayBuffer = nullptr; 186 size_t bufferSize = sizeof(uuid.elements); 187 napi_create_arraybuffer(env, bufferSize, &data, &arrayBuffer); 188 if (memcpy_s(data, bufferSize, uuid.elements, bufferSize) != EOK) { 189 HILOG_ERROR("get uuid memcpy_s failed"); 190 return nullptr; 191 } 192 napi_value result = nullptr; 193 napi_create_typedarray(env, napi_uint8_array, bufferSize, arrayBuffer, 0, &result); 194 return result; 195 } 196 DoParseUUID(napi_env env,napi_value src)197 napi_value DoParseUUID(napi_env env, napi_value src) 198 { 199 size_t outLen = 16; // 16: the length of UUID 200 std::string buffer = ""; 201 size_t bufferSize = 0; // 0: initialization 202 napi_status status = napi_ok; 203 status = napi_get_value_string_utf8(env, src, nullptr, 0, &bufferSize); 204 if (status != napi_ok) { 205 HILOG_ERROR("can not get src size"); 206 return nullptr; 207 } 208 buffer.resize(bufferSize); 209 status = napi_get_value_string_utf8(env, src, buffer.data(), bufferSize + 1, &bufferSize); 210 if (status != napi_ok) { 211 HILOG_ERROR("can not get src value"); 212 return nullptr; 213 } 214 void *data = nullptr; 215 napi_value arrayBuffer = nullptr; 216 napi_create_arraybuffer(env, outLen, &data, &arrayBuffer); 217 unsigned char *count = static_cast<unsigned char*>(data); 218 for (size_t i = 0; !buffer.empty() && i < outLen; i++) { 219 *count = ConvertBits(buffer); 220 count++; 221 } 222 napi_value result = nullptr; 223 napi_create_typedarray(env, napi_uint8_array, outLen, arrayBuffer, 0, &result); 224 return result; 225 } 226 }