• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "huks_napi_common.h"
17 
18 #include "securec.h"
19 
20 #include "hks_log.h"
21 #include "hks_param.h"
22 #include "hks_type.h"
23 
24 namespace HuksNapi {
25 namespace {
26 constexpr int HKS_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M
27 constexpr size_t ASYNCCALLBACK_ARGC = 2;
28 }  // namespace
29 
ParseKeyAlias(napi_env env,napi_value object,HksBlob * & alias)30 napi_value ParseKeyAlias(napi_env env, napi_value object, HksBlob *&alias)
31 {
32     size_t length = 0;
33     napi_status status = napi_get_value_string_utf8(env, object, nullptr, 0, &length);
34     if (status != napi_ok) {
35         GET_AND_THROW_LAST_ERROR((env));
36         HKS_LOG_E("could not get string length");
37         return nullptr;
38     }
39 
40     if (length > HKS_MAX_DATA_LEN) {
41         HKS_LOG_E("input key alias length too large");
42         return nullptr;
43     }
44 
45     char *data = (char *)HksMalloc(length + 1);
46     if (data == nullptr) {
47         napi_throw_error(env, NULL, "could not alloc memory");
48         HKS_LOG_E("could not alloc memory");
49         return nullptr;
50     }
51     (void)memset_s(data, length + 1, 0, length + 1);
52 
53     size_t result = 0;
54     status = napi_get_value_string_utf8(env, object, data, length + 1, &result);
55     if (status != napi_ok) {
56         HksFree(data);
57         GET_AND_THROW_LAST_ERROR((env));
58         HKS_LOG_E("could not get string");
59         return nullptr;
60     }
61 
62     alias = (HksBlob *)HksMalloc(sizeof(HksBlob));
63     if (alias == nullptr) {
64         HksFree(data);
65         napi_throw_error(env, NULL, "could not alloc memory");
66         HKS_LOG_E("could not alloc memory");
67         return nullptr;
68     }
69     alias->data = (uint8_t *)data;
70     alias->size = (uint32_t)(length & UINT32_MAX);
71 
72     return GetInt32(env, 0);
73 }
74 
GetUint8Array(napi_env env,napi_value object,HksBlob & arrayBlob)75 napi_value GetUint8Array(napi_env env, napi_value object, HksBlob &arrayBlob)
76 {
77     napi_typedarray_type arrayType;
78     napi_value arrayBuffer = nullptr;
79     size_t length = 0;
80     size_t offset = 0;
81     void *rawData = nullptr;
82 
83     NAPI_CALL(
84         env, napi_get_typedarray_info(env, object, &arrayType, &length, (void **)&rawData, &arrayBuffer, &offset));
85     NAPI_ASSERT(env, arrayType == napi_uint8_array, "it's not uint8 array");
86 
87     if (length > HKS_MAX_DATA_LEN) {
88         HKS_LOG_E("data len is too large, len = %x", length);
89         return nullptr;
90     }
91     if (length == 0) {
92         HKS_LOG_I("the created memory length just 1 Byte");
93         // the created memory length just 1 Byte
94         arrayBlob.data = (uint8_t *)HksMalloc(1);
95     } else {
96         arrayBlob.data = (uint8_t *)HksMalloc(length);
97     }
98     if (arrayBlob.data == nullptr) {
99         return nullptr;
100     }
101     (void)memcpy_s(arrayBlob.data, length, rawData, length);
102     arrayBlob.size = (uint32_t)length;
103 
104     return GetInt32(env, 0);
105 }
106 
GetHksParam(napi_env env,napi_value object,HksParam & param)107 static napi_value GetHksParam(napi_env env, napi_value object, HksParam &param)
108 {
109     napi_value tag = nullptr;
110     NAPI_CALL(env, napi_get_named_property(env, object, HKS_PARAM_PROPERTY_TAG.c_str(), &tag));
111     NAPI_CALL(env, napi_get_value_uint32(env, tag, &param.tag));
112 
113     napi_value value = nullptr;
114     NAPI_CALL(env, napi_get_named_property(env, object, HKS_PARAM_PROPERTY_VALUE.c_str(), &value));
115 
116     napi_value result = nullptr;
117 
118     switch (param.tag & HKS_TAG_TYPE_MASK) {
119         case HKS_TAG_TYPE_INT:
120             NAPI_CALL(env, napi_get_value_int32(env, value, &param.int32Param));
121             result = GetInt32(env, 0);
122             break;
123         case HKS_TAG_TYPE_UINT:
124             NAPI_CALL(env, napi_get_value_uint32(env, value, &param.uint32Param));
125             result = GetInt32(env, 0);
126             break;
127         case HKS_TAG_TYPE_ULONG:
128             NAPI_CALL(env, napi_get_value_int64(env, value, (int64_t *)&param.uint64Param));
129             result = GetInt32(env, 0);
130             break;
131         case HKS_TAG_TYPE_BOOL:
132             NAPI_CALL(env, napi_get_value_bool(env, value, &param.boolParam));
133             result = GetInt32(env, 0);
134             break;
135         case HKS_TAG_TYPE_BYTES:
136             result = GetUint8Array(env, value, param.blob);
137             if (result == nullptr) {
138                 HKS_LOG_E("get uint8 array fail.");
139             } else {
140                 HKS_LOG_D("tag 0x%x, len 0x%x", param.tag, param.blob.size);
141             }
142             break;
143         default:
144             HKS_LOG_E("invalid tag value 0x%x", param.tag);
145             break;
146     }
147 
148     return result;
149 }
150 
ParseHksParamSet(napi_env env,napi_value object,HksParamSet * & paramSet)151 napi_value ParseHksParamSet(napi_env env, napi_value object, HksParamSet *&paramSet)
152 {
153     if (HksInitParamSet(&paramSet) != HKS_SUCCESS) {
154         napi_throw_error(env, NULL, "native error");
155         HKS_LOG_E("init paramset failed");
156         return nullptr;
157     }
158 
159     size_t index = 0;
160     bool hasNextElement = false;
161     napi_value result = nullptr;
162     while ((napi_has_element(env, object, index, &hasNextElement) == napi_ok) && hasNextElement) {
163         napi_value element = nullptr;
164         NAPI_CALL(env, napi_get_element(env, object, index, &element));
165 
166         HksParam param = {0};
167         result = GetHksParam(env, element, param);
168         if (result == nullptr) {
169             HKS_LOG_E("GetHksParam failed.");
170             HksFreeParamSet(&paramSet);
171             return nullptr;
172         }
173 
174         if (HksAddParams(paramSet, &param, 1) != HKS_SUCCESS) {
175             HKS_LOG_E("HksAddParams failed.");
176             HksFreeParamSet(&paramSet);
177             return nullptr;
178         }
179         index++;
180     }
181 
182     if (HksBuildParamSet(&paramSet) != HKS_SUCCESS) {
183         HKS_LOG_E("HksBuildParamSet failed.");
184         HksFreeParamSet(&paramSet);
185         return nullptr;
186     }
187 
188     return GetInt32(env, 0);
189 }
190 
GetCallback(napi_env env,napi_value object)191 napi_ref GetCallback(napi_env env, napi_value object)
192 {
193     napi_valuetype valueType = napi_undefined;
194     napi_status status = napi_typeof(env, object, &valueType);
195     if (status != napi_ok) {
196         GET_AND_THROW_LAST_ERROR((env));
197         HKS_LOG_E("could not get object type");
198         return nullptr;
199     }
200 
201     if (valueType != napi_function) {
202         HKS_LOG_E("invalid type");
203         return nullptr;
204     }
205 
206     napi_ref ref = nullptr;
207     status = napi_create_reference(env, object, 1, &ref);
208     if (status != napi_ok) {
209         GET_AND_THROW_LAST_ERROR((env));
210         HKS_LOG_E("could not create reference");
211         return nullptr;
212     }
213     return ref;
214 }
215 
GenerateAarrayBuffer(napi_env env,uint8_t * data,uint32_t size)216 static napi_value GenerateAarrayBuffer(napi_env env, uint8_t *data, uint32_t size)
217 {
218     uint8_t *buffer = (uint8_t *)HksMalloc(size);
219     if (buffer == nullptr) {
220         return nullptr;
221     }
222 
223     napi_value outBuffer = nullptr;
224     (void)memcpy_s(buffer, size, data, size);
225 
226     napi_status status = napi_create_external_arraybuffer(
227         env, buffer, size, [](napi_env env, void *data, void *hint) { HksFree(data); }, nullptr, &outBuffer);
228     if (status == napi_ok) {
229         // free by finalize callback
230         buffer = nullptr;
231     } else {
232         HksFree(buffer);
233         GET_AND_THROW_LAST_ERROR((env));
234     }
235 
236     return outBuffer;
237 }
238 
GenerateHksParam(napi_env env,const HksParam & param)239 static napi_value GenerateHksParam(napi_env env, const HksParam &param)
240 {
241     napi_value hksParam = nullptr;
242     NAPI_CALL(env, napi_create_object(env, &hksParam));
243 
244     napi_value tag = nullptr;
245     NAPI_CALL(env, napi_create_uint32(env, param.tag, &tag));
246     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_TAG.c_str(), tag));
247 
248     napi_value value = nullptr;
249     switch (param.tag & HKS_TAG_TYPE_MASK) {
250         case HKS_TAG_TYPE_INT:
251             NAPI_CALL(env, napi_create_int32(env, param.int32Param, &value));
252             break;
253         case HKS_TAG_TYPE_UINT:
254             NAPI_CALL(env, napi_create_uint32(env, param.uint32Param, &value));
255             break;
256         case HKS_TAG_TYPE_ULONG:
257             NAPI_CALL(env, napi_create_int64(env, param.uint64Param, &value));
258             break;
259         case HKS_TAG_TYPE_BOOL:
260             NAPI_CALL(env, napi_get_boolean(env, param.boolParam, &value));
261             break;
262         case HKS_TAG_TYPE_BYTES:
263             value = GenerateAarrayBuffer(env, param.blob.data, param.blob.size);
264             break;
265         default:
266             value = GetNull(env);
267             break;
268     }
269     NAPI_CALL(env, napi_set_named_property(env, hksParam, HKS_PARAM_PROPERTY_VALUE.c_str(), value));
270 
271     return hksParam;
272 }
273 
GenerateHksParamArray(napi_env env,const HksParamSet & paramSet)274 static napi_value GenerateHksParamArray(napi_env env, const HksParamSet &paramSet)
275 {
276     napi_value paramArray = nullptr;
277     NAPI_CALL(env, napi_create_array(env, &paramArray));
278 
279     for (uint32_t i = 0; i < paramSet.paramsCnt; i++) {
280         napi_value element = nullptr;
281         element = GenerateHksParam(env, paramSet.params[i]);
282         napi_set_element(env, paramArray, i, element);
283     }
284 
285     return paramArray;
286 }
287 
GenerateHksResult(napi_env env,int32_t error)288 napi_value GenerateHksResult(napi_env env, int32_t error)
289 {
290     napi_value result = nullptr;
291     NAPI_CALL(env, napi_create_object(env, &result));
292 
293     napi_value errorCode = nullptr;
294     NAPI_CALL(env, napi_create_int32(env, error, &errorCode));
295     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_ERRORCODE.c_str(), errorCode));
296 
297     napi_value outData = GetNull(env);
298     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_OUTDATA.c_str(), outData));
299 
300     napi_value properties = GetNull(env);
301     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_PROPERTIES.c_str(), properties));
302 
303     return result;
304 }
305 
GenerateHksResult(napi_env env,int32_t error,uint8_t * data,uint32_t size)306 napi_value GenerateHksResult(napi_env env, int32_t error, uint8_t *data, uint32_t size)
307 {
308     napi_value result = nullptr;
309     NAPI_CALL(env, napi_create_object(env, &result));
310 
311     napi_value errorCode = nullptr;
312     NAPI_CALL(env, napi_create_int32(env, error, &errorCode));
313     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_ERRORCODE.c_str(), errorCode));
314 
315     napi_value outData = nullptr;
316     if (data != nullptr && size != 0) {
317         napi_value outBuffer = GenerateAarrayBuffer(env, data, size);
318         if (outBuffer != nullptr) {
319             NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, size, outBuffer, 0, &outData));
320         }
321     } else {
322         outData = GetNull(env);
323     }
324     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_OUTDATA.c_str(), outData));
325 
326     napi_value properties = GetNull(env);
327     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_PROPERTIES.c_str(), properties));
328 
329     return result;
330 }
331 
GenerateHksResult(napi_env env,int32_t error,uint8_t * data,uint32_t size,const HksParamSet & paramSet)332 napi_value GenerateHksResult(napi_env env, int32_t error, uint8_t *data, uint32_t size, const HksParamSet &paramSet)
333 {
334     napi_value result = nullptr;
335     NAPI_CALL(env, napi_create_object(env, &result));
336 
337     napi_value errorCode = nullptr;
338     NAPI_CALL(env, napi_create_int32(env, error, &errorCode));
339     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_ERRORCODE.c_str(), errorCode));
340 
341     napi_value outData = nullptr;
342     if (data != nullptr && size != 0) {
343         napi_value outBuffer = GenerateAarrayBuffer(env, data, size);
344         if (outBuffer != nullptr) {
345             NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, size, outBuffer, 0, &outData));
346         }
347     } else {
348         outData = GetNull(env);
349     }
350     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PROPERTY_OUTDATA.c_str(), outData));
351 
352     napi_value properties = GenerateHksParamArray(env, paramSet);
353     NAPI_CALL(env, napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_PROPERTIES.c_str(), properties));
354 
355     return result;
356 }
357 
GenerateBusinessError(napi_env env,int32_t errorCode)358 static napi_value GenerateBusinessError(napi_env env, int32_t errorCode)
359 {
360     napi_value businessError = nullptr;
361     NAPI_CALL(env, napi_create_object(env, &businessError));
362 
363     napi_value code = nullptr;
364     NAPI_CALL(env, napi_create_int32(env, errorCode, &code));
365     NAPI_CALL(env, napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code));
366 
367     return businessError;
368 }
369 
CallAsyncCallback(napi_env env,napi_ref callback,int32_t error,napi_value data)370 void CallAsyncCallback(napi_env env, napi_ref callback, int32_t error, napi_value data)
371 {
372     napi_value businessError = GenerateBusinessError(env, error);
373 
374     napi_value params[ASYNCCALLBACK_ARGC] = { businessError, data };
375 
376     napi_value func = nullptr;
377     NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
378 
379     napi_value recv = nullptr;
380     napi_value result = nullptr;
381     NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &recv));
382     NAPI_CALL_RETURN_VOID(env, napi_call_function(env, recv, func, ASYNCCALLBACK_ARGC, params, &result));
383 }
384 
GenerateStringArray(napi_env env,const struct HksBlob * blob,const uint32_t blobCount)385 napi_value GenerateStringArray(napi_env env, const struct HksBlob *blob, const uint32_t blobCount)
386 {
387     if (blobCount == 0 || blob == nullptr) {
388         return nullptr;
389     }
390     napi_value array = nullptr;
391     NAPI_CALL(env, napi_create_array(env, &array));
392     for (uint32_t i = 0; i < blobCount; i++) {
393         napi_value element = nullptr;
394         napi_create_string_latin1(env, (const char *)blob[i].data, blob[i].size, &element);
395         napi_set_element(env, array, i, element);
396     }
397     return array;
398 }
399 
FreeHksCertChain(HksCertChain * & certChain)400 void FreeHksCertChain(HksCertChain *&certChain)
401 {
402     if (certChain == nullptr) {
403         return;
404     }
405 
406     if (certChain->certsCount > 0 && certChain->certs != nullptr) {
407         for (uint32_t i = 0; i < certChain->certsCount; i++) {
408             if (certChain->certs[i].data != nullptr) {
409                 HksFree(certChain->certs[i].data);
410                 certChain->certs[i].data = nullptr;
411             }
412         }
413     }
414 
415     HksFree(certChain);
416     certChain = nullptr;
417 }
418 
GenerateHksHandle(napi_env env,int32_t error,uint8_t * data,uint32_t size)419 napi_value GenerateHksHandle(napi_env env, int32_t error, uint8_t *data, uint32_t size)
420 {
421     napi_value result = nullptr;
422     NAPI_CALL(env, napi_create_object(env, &result));
423 
424     napi_value errorCode = nullptr;
425     NAPI_CALL(env, napi_create_int32(env, error, &errorCode));
426     NAPI_CALL(env, napi_set_named_property(env, result, HKS_HANDLE_PROPERTY_ERRORCODE.c_str(), errorCode));
427 
428     if (data == nullptr) {
429         HKS_LOG_E("data: invalid pointer");
430         return result;
431     }
432 
433     uint64_t tempHandle = *(uint64_t *)data;
434     uint32_t handle = (uint32_t)tempHandle; /* Temporarily only use 32 bit handle */
435     HKS_LOG_I("init handle:%u", handle);
436 
437     napi_value handlejs = nullptr;
438     NAPI_CALL(env, napi_create_uint32(env, handle, &handlejs));
439     NAPI_CALL(env, napi_set_named_property(env, result, HKS_HANDLE_PROPERTY_HANDLE.c_str(), handlejs));
440 
441     return result;
442 }
443 }  // namespace HuksNapi
444