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