• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 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 "napi_cert_utils.h"
17 
18 #include "cf_log.h"
19 #include "cf_memory.h"
20 #include "config.h"
21 #include "securec.h"
22 #include "cipher.h"
23 #include "napi_cert_defines.h"
24 #include "detailed_iv_params.h"
25 #include "detailed_gcm_params.h"
26 #include "detailed_ccm_params.h"
27 
28 namespace OHOS {
29 namespace CertFramework {
30 using namespace std;
31 
32 struct CfResultCodeMap {
33     CfResult retValue;
34     ResultCode retCode;
35 };
36 
37 const struct CfResultCodeMap CODE_MAP[] = {
38     { CF_SUCCESS, JS_SUCCESS },
39     { CF_INVALID_PARAMS, JS_ERR_CERT_INVALID_PARAMS },
40     { CF_NOT_SUPPORT, JS_ERR_CERT_NOT_SUPPORT },
41     { CF_ERR_MALLOC, JS_ERR_CERT_OUT_OF_MEMORY },
42     { CF_ERR_CRYPTO_OPERATION, JS_ERR_CERT_CRYPTO_OPERATION },
43     { CF_ERR_CERT_SIGNATURE_FAILURE, JS_ERR_CERT_SIGNATURE_FAILURE },
44     { CF_ERR_CERT_NOT_YET_VALID, JS_ERR_CERT_NOT_YET_VALID },
45     { CF_ERR_CERT_HAS_EXPIRED, JS_ERR_CERT_HAS_EXPIRED },
46     { CF_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, JS_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY },
47     { CF_ERR_KEYUSAGE_NO_CERTSIGN, JS_ERR_KEYUSAGE_NO_CERTSIGN },
48     { CF_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, JS_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE },
49 };
50 
CertNapiGetNull(napi_env env)51 napi_value CertNapiGetNull(napi_env env)
52 {
53     napi_value result = nullptr;
54     napi_get_null(env, &result);
55     return result;
56 }
57 
ConvertArrayToNapiValue(napi_env env,CfArray * array)58 napi_value ConvertArrayToNapiValue(napi_env env, CfArray *array)
59 {
60     if (array == nullptr) {
61         LOGE("array is null!");
62         return nullptr;
63     }
64     if (array->count == 0) {
65         LOGE("array count is 0!");
66         return nullptr;
67     }
68     napi_value returnArray = nullptr;
69     napi_create_array(env, &returnArray);
70     if (returnArray == nullptr) {
71         LOGE("create return array failed!");
72         return nullptr;
73     }
74     for (uint32_t i = 0; i < array->count; i++) {
75         CfBlob *blob = reinterpret_cast<CfBlob *>(array->data + i);
76         napi_value outBuffer = GenerateArrayBuffer(env, blob->data, blob->size);
77         if (outBuffer == nullptr) {
78             LOGE("generate array buffer failed!");
79             return nullptr;
80         }
81         napi_value element = nullptr;
82         napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &element);
83         napi_set_element(env, returnArray, i, element);
84     }
85     napi_value returnValue = nullptr;
86     napi_create_object(env, &returnValue);
87     napi_set_named_property(env, returnValue, CERT_TAG_DATA.c_str(), returnArray);
88     return returnValue;
89 }
90 
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)91 napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
92 {
93     uint8_t *buffer = static_cast<uint8_t *>(HcfMalloc(size, 0));
94     if (buffer == nullptr) {
95         LOGE("malloc uint8 array buffer failed!");
96         return nullptr;
97     }
98 
99     if (memcpy_s(buffer, size, data, size) != EOK) {
100         LOGE("memcpy_s data to buffer failed!");
101         CfFree(buffer);
102         return nullptr;
103     }
104 
105     napi_value outBuffer = nullptr;
106     napi_status status = napi_create_external_arraybuffer(
107         env, buffer, size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
108     if (status != napi_ok) {
109         LOGE("create uint8 array buffer failed!");
110         CfFree(buffer);
111         return nullptr;
112     }
113     buffer = nullptr;
114     return outBuffer;
115 }
116 
GetDataOfEncodingBlob(napi_env env,napi_value data,CfEncodingBlob * encodingBlob)117 static bool GetDataOfEncodingBlob(napi_env env, napi_value data, CfEncodingBlob *encodingBlob)
118 {
119     napi_typedarray_type arrayType;
120     napi_value arrayBuffer = nullptr;
121     size_t length = 0;
122     size_t offset = 0;
123     void *rawData = nullptr;
124 
125     napi_status status = napi_get_typedarray_info(env, data, &arrayType, &length,
126         reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
127     if (status != napi_ok) {
128         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get array data failed"));
129         LOGE("failed to get array data!");
130         return false;
131     }
132     if (arrayType != napi_uint8_array) {
133         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array type is not uint8 array"));
134         LOGE("array is not uint8 array!");
135         return false;
136     }
137 
138     if (length == 0) {
139         LOGE("input data length is 0");
140         return false;
141     }
142     encodingBlob->data = static_cast<uint8_t *>(HcfMalloc(length, 0));
143     if (encodingBlob->data == nullptr) {
144         LOGE("malloc encoding blob data failed!");
145         return false;
146     }
147     if (memcpy_s(encodingBlob->data, length, rawData, length) != EOK) {
148         LOGE("memcpy_s encoding blob data failed!");
149         CfFree(encodingBlob->data);
150         encodingBlob->data = nullptr;
151         return false;
152     }
153     encodingBlob->len = length;
154     return true;
155 }
156 
GetEncodingBlobFromValue(napi_env env,napi_value obj,CfEncodingBlob ** encodingBlob)157 bool GetEncodingBlobFromValue(napi_env env, napi_value obj, CfEncodingBlob **encodingBlob)
158 {
159     *encodingBlob = static_cast<CfEncodingBlob *>(HcfMalloc(sizeof(CfEncodingBlob), 0));
160     if (*encodingBlob == nullptr) {
161         LOGE("malloc encoding blob failed!");
162         return false;
163     }
164     napi_value data = nullptr;
165     napi_status status = napi_get_named_property(env, obj, CERT_TAG_DATA.c_str(), &data);
166     if (status != napi_ok) {
167         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get encoding blob data failed"));
168         LOGE("failed to get encoding blob data!");
169         CfFree(*encodingBlob);
170         *encodingBlob = nullptr;
171         return false;
172     }
173     if (!GetDataOfEncodingBlob(env, data, *encodingBlob)) {
174         CfFree(*encodingBlob);
175         *encodingBlob = nullptr;
176         return false;
177     }
178     napi_value format = nullptr;
179     status = napi_get_named_property(env, obj, CERT_TAG_ENCODING_FORMAT.c_str(), &format);
180     if (status != napi_ok) {
181         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get encoding blob format failed"));
182         LOGE("failed to get encoding blob format!");
183         CfFree((*encodingBlob)->data);
184         (*encodingBlob)->data = nullptr;
185         CfFree(*encodingBlob);
186         *encodingBlob = nullptr;
187         return false;
188     }
189     napi_get_value_uint32(env, format, reinterpret_cast<uint32_t *>(&(*encodingBlob)->encodingFormat));
190     return true;
191 }
192 
ConvertEncodingBlobToNapiValue(napi_env env,CfEncodingBlob * encodingBlob)193 napi_value ConvertEncodingBlobToNapiValue(napi_env env, CfEncodingBlob *encodingBlob)
194 {
195     napi_value outBuffer = GenerateArrayBuffer(env, encodingBlob->data, encodingBlob->len);
196     if (outBuffer == nullptr) {
197         LOGE("generate array buffer failed!");
198         return nullptr;
199     }
200     napi_value outData = nullptr;
201     napi_create_typedarray(env, napi_uint8_array, encodingBlob->len, outBuffer, 0, &outData);
202     napi_value encoding = nullptr;
203     napi_create_uint32(env, encodingBlob->encodingFormat, &encoding);
204     napi_value returnEncodingBlob = nullptr;
205     napi_create_object(env, &returnEncodingBlob);
206     napi_set_named_property(env, returnEncodingBlob, CERT_TAG_DATA.c_str(), outData);
207     napi_set_named_property(env, returnEncodingBlob, CERT_TAG_ENCODING_FORMAT.c_str(), encoding);
208     return returnEncodingBlob;
209 }
210 
CertGetBlobFromNapiValue(napi_env env,napi_value arg)211 CfBlob *CertGetBlobFromNapiValue(napi_env env, napi_value arg)
212 {
213     if ((env == nullptr) || (arg == nullptr)) {
214         LOGE("Invalid parmas!");
215         return nullptr;
216     }
217     napi_value data = nullptr;
218     napi_status status = napi_get_named_property(env, arg, CERT_TAG_DATA.c_str(), &data);
219     if ((status != napi_ok) || (data == nullptr)) {
220         LOGE("failed to get valid data property!");
221         return nullptr;
222     }
223     return CertGetBlobFromUint8ArrJSParams(env, data);
224 }
225 
CertConvertBlobToNapiValue(napi_env env,CfBlob * blob)226 napi_value CertConvertBlobToNapiValue(napi_env env, CfBlob *blob)
227 {
228     napi_value outData = ConvertBlobToUint8ArrNapiValue(env, blob);
229     if (outData == nullptr) {
230         LOGE("convert to uint8 arr failed");
231         return nullptr;
232     }
233     napi_value dataBlob = nullptr;
234     napi_create_object(env, &dataBlob);
235     napi_set_named_property(env, dataBlob, CERT_TAG_DATA.c_str(), outData);
236 
237     return dataBlob;
238 }
239 
ConvertBlobToUint8ArrNapiValue(napi_env env,CfBlob * blob)240 napi_value ConvertBlobToUint8ArrNapiValue(napi_env env, CfBlob *blob)
241 {
242     if (blob == nullptr || blob->data == nullptr || blob->size == 0) {
243         LOGE("Invalid blob!");
244         return nullptr;
245     }
246     /* free in napi_create_external_arraybuffer, not in this scope. */
247     uint8_t *buffer = static_cast<uint8_t *>(HcfMalloc(blob->size, 0));
248     if (buffer == nullptr) {
249         LOGE("malloc uint8 array buffer failed!");
250         return nullptr;
251     }
252 
253     if (memcpy_s(buffer, blob->size, blob->data, blob->size) != EOK) {
254         LOGE("memcpy_s data to buffer failed!");
255         CfFree(buffer);
256         return nullptr;
257     }
258 
259     napi_value outBuffer = nullptr;
260     napi_status status = napi_create_external_arraybuffer(
261         env, buffer, blob->size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
262     if (status != napi_ok) {
263         LOGE("create uint8 array buffer failed!");
264         CfFree(buffer);
265         return nullptr;
266     }
267     buffer = nullptr;
268 
269     napi_value outData = nullptr;
270     napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &outData);
271 
272     return outData;
273 }
274 
GetDataOfCertChain(napi_env env,napi_value data,HcfCertChainData * certChain)275 static bool GetDataOfCertChain(napi_env env, napi_value data, HcfCertChainData *certChain)
276 {
277     napi_typedarray_type arrayType;
278     napi_value arrayBuffer = nullptr;
279     size_t length = 0;
280     size_t offset = 0;
281     void *rawData = nullptr;
282 
283     napi_status status = napi_get_typedarray_info(env, data, &arrayType, &length,
284         reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
285     if (status != napi_ok) {
286         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get array data failed"));
287         LOGE("failed to get array data!");
288         return false;
289     }
290     if (arrayType != napi_uint8_array) {
291         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array type is not uint8 array"));
292         LOGE("array is not uint8 array!");
293         return false;
294     }
295 
296     if (length == 0) {
297         LOGE("input data length is 0");
298         return false;
299     }
300     certChain->data = static_cast<uint8_t *>(HcfMalloc(length, 0));
301     if (certChain->data == nullptr) {
302         LOGE("malloc cert chain data failed!");
303         return false;
304     }
305     if (memcpy_s(certChain->data, length, rawData, length) != EOK) {
306         LOGE("memcpy_s cert chain data failed!");
307         CfFree(certChain->data);
308         certChain->data = nullptr;
309         return false;
310     }
311     certChain->dataLen = length;
312     return true;
313 }
314 
GetCertChainFromValue(napi_env env,napi_value obj,HcfCertChainData ** certChainData)315 bool GetCertChainFromValue(napi_env env, napi_value obj, HcfCertChainData **certChainData)
316 {
317     *certChainData = static_cast<HcfCertChainData *>(HcfMalloc(sizeof(HcfCertChainData), 0));
318     if (*certChainData == nullptr) {
319         LOGE("malloc certChainData failed!");
320         return false;
321     }
322     napi_value data = nullptr;
323     napi_status status = napi_get_named_property(env, obj, CERT_TAG_DATA.c_str(), &data);
324     if (status != napi_ok) {
325         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain data failed"));
326         LOGE("failed to get cert chain data!");
327         CfFree(*certChainData);
328         *certChainData = nullptr;
329         return false;
330     }
331     if (!GetDataOfCertChain(env, data, *certChainData)) {
332         CfFree(*certChainData);
333         *certChainData = nullptr;
334         return false;
335     }
336 
337     napi_value certCount = nullptr;
338     status = napi_get_named_property(env, obj, CERT_TAG_COUNT.c_str(), &certCount);
339     if (status != napi_ok) {
340         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain count failed"));
341         LOGE("failed to get cert count!");
342         CfFree((*certChainData)->data);
343         (*certChainData)->data = nullptr;
344         CfFree(*certChainData);
345         *certChainData = nullptr;
346         return false;
347     }
348     napi_get_value_uint32(env, certCount, reinterpret_cast<uint32_t *>(&(*certChainData)->count));
349 
350     napi_value format = nullptr;
351     status = napi_get_named_property(env, obj, CERT_TAG_ENCODING_FORMAT.c_str(), &format);
352     if (status != napi_ok) {
353         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain format failed"));
354         LOGE("failed to get cert chain format!");
355         CfFree((*certChainData)->data);
356         (*certChainData)->data = nullptr;
357         CfFree(*certChainData);
358         *certChainData = nullptr;
359         return false;
360     }
361     napi_get_value_uint32(env, format, reinterpret_cast<uint32_t *>(&(*certChainData)->format));
362     return true;
363 }
364 
CertGetBlobFromUint8ArrJSParams(napi_env env,napi_value arg)365 CfBlob *CertGetBlobFromUint8ArrJSParams(napi_env env, napi_value arg)
366 {
367     size_t length = 0;
368     size_t offset = 0;
369     void *rawData = nullptr;
370     napi_value arrayBuffer = nullptr;
371     napi_typedarray_type arrayType;
372     // Warning: Do not release the rawData returned by this interface because the rawData is managed by VM.
373     napi_status status = napi_get_typedarray_info(
374         env, arg, &arrayType, &length, reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
375     if (status != napi_ok) {
376         LOGE("failed to get valid rawData.");
377         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "failed to get valid rawData!"));
378         return nullptr;
379     }
380     if (arrayType != napi_uint8_array) {
381         LOGE("input data is not uint8 array.");
382         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input data is not uint8 array!"));
383         return nullptr;
384     }
385 
386     if (length == 0 || rawData == nullptr) {
387         LOGI("array length is 0!");
388         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array length is 0!"));
389         return nullptr;
390     }
391 
392     CfBlob *newBlob = static_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
393     if (newBlob == nullptr) {
394         LOGE("Failed to allocate newBlob memory!");
395         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
396         return nullptr;
397     }
398 
399     newBlob->size = length;
400     newBlob->data = static_cast<uint8_t *>(HcfMalloc(length, 0));
401     if (newBlob->data == nullptr) {
402         LOGE("malloc blob data failed!");
403         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
404         CfFree(newBlob);
405         return nullptr;
406     }
407     if (memcpy_s(newBlob->data, length, rawData, length) != EOK) {
408         LOGE("memcpy_s blob data failed!");
409         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_COPY, "copy memory failed!"));
410         CfFree(newBlob->data);
411         CfFree(newBlob);
412         return nullptr;
413     }
414 
415     return newBlob;
416 }
417 
CertGetBlobFromStringJSParams(napi_env env,napi_value arg)418 CfBlob *CertGetBlobFromStringJSParams(napi_env env, napi_value arg)
419 {
420     napi_valuetype valueType;
421     napi_typeof(env, arg, &valueType);
422     if (valueType != napi_string) {
423         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not string"));
424         LOGE("wrong argument type. expect string type. [Type]: %d", valueType);
425         return nullptr;
426     }
427 
428     size_t length = 0;
429     if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
430         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "can not get string length!"));
431         LOGE("can not get string length");
432         return nullptr;
433     }
434 
435     if (length == 0) {
436         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "string length is 0!"));
437         LOGE("string length is 0");
438         return nullptr;
439     }
440 
441     CfBlob *newBlob = static_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
442     if (newBlob == nullptr) {
443         LOGE("Failed to allocate newBlob memory!");
444         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
445         return nullptr;
446     }
447 
448     newBlob->size = length + 1;
449     newBlob->data = static_cast<uint8_t *>(HcfMalloc(newBlob->size, 0));
450     if (newBlob->data == nullptr) {
451         LOGE("malloc blob data failed!");
452         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
453         CfFree(newBlob);
454         return nullptr;
455     }
456 
457     if (napi_get_value_string_utf8(env, arg, reinterpret_cast<char *>(newBlob->data), newBlob->size, &length) !=
458         napi_ok) {
459         LOGE("can not get string value");
460         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get string failed"));
461         CfFree(newBlob->data);
462         CfFree(newBlob);
463         return nullptr;
464     }
465 
466     return newBlob;
467 }
468 
GetProp(napi_env env,napi_value arg,const char * name)469 napi_value GetProp(napi_env env, napi_value arg, const char *name)
470 {
471     bool result = false;
472     napi_has_named_property(env, arg, name, &result);
473     if (!result) {
474         LOGI("%s do not exist!", name);
475         return nullptr;
476     }
477     napi_value obj = nullptr;
478     napi_status status = napi_get_named_property(env, arg, name, &obj);
479     if (status != napi_ok || obj == nullptr) {
480         LOGI("get property %s failed!", name);
481         return nullptr;
482     }
483     napi_valuetype valueType;
484     napi_typeof(env, obj, &valueType);
485     if (valueType == napi_undefined) {
486         LOGI("%s valueType is null or undefined.", name);
487         return nullptr;
488     }
489 
490     LOGI("%s is not null!", name);
491     return obj;
492 }
493 
CertGetBlobArrFromArrUarrJSParams(napi_env env,napi_value arg)494 CfBlobArray *CertGetBlobArrFromArrUarrJSParams(napi_env env, napi_value arg)
495 {
496     bool flag = false;
497     napi_status status = napi_is_array(env, arg, &flag);
498     if (status != napi_ok || !flag) {
499         LOGE("not array!");
500         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "not array!"));
501         return nullptr;
502     }
503     uint32_t length = 0;
504     status = napi_get_array_length(env, arg, &length);
505     if (status != napi_ok || length == 0 || length > MAX_NAPI_ARRAY_OF_U8ARR) {
506         LOGI("length is invalid!");
507         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "length is invalid!"));
508         return nullptr;
509     }
510 
511     CfBlobArray *newBlobArr = static_cast<CfBlobArray *>(HcfMalloc(sizeof(CfBlobArray), 0));
512     if (newBlobArr == nullptr) {
513         LOGE("Failed to allocate newBlobArr memory!");
514         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
515         return nullptr;
516     }
517 
518     newBlobArr->count = length;
519     newBlobArr->data = static_cast<CfBlob *>(HcfMalloc(length * sizeof(CfBlob), 0));
520     if (newBlobArr->data == nullptr) {
521         LOGE("Failed to allocate data memory!");
522         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
523         CfFree(newBlobArr);
524         return nullptr;
525     }
526     for (uint32_t i = 0; i < length; i++) {
527         napi_value element;
528         if (napi_get_element(env, arg, i, &element) == napi_ok) {
529             CfBlob *blob = CertGetBlobFromUint8ArrJSParams(env, element);
530             if (blob != nullptr) {
531                 newBlobArr->data[i] = *blob;
532                 CfFree(blob); // release blob object, not release blob data
533                 continue;
534             }
535         }
536         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input arr is invalid"));
537         FreeCfBlobArray(newBlobArr->data, newBlobArr->count);
538         CfFree(newBlobArr);
539         LOGE("Failed to allocate data memory!");
540         return nullptr;
541     }
542     return newBlobArr;
543 }
544 
GetArrayLen(napi_env env,napi_value arg,uint32_t & length)545 static bool GetArrayLen(napi_env env, napi_value arg, uint32_t &length)
546 {
547     bool flag = false;
548     napi_status status = napi_is_array(env, arg, &flag);
549     if (status != napi_ok || !flag) {
550         LOGE("not array!");
551         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "not array!"));
552         return false;
553     }
554 
555     status = napi_get_array_length(env, arg, &length);
556     if (status != napi_ok || length == 0) {
557         LOGI("array length = 0!");
558         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array length = 0!"));
559         return false;
560     }
561     return true;
562 }
563 
CertGetBlobFromArrBoolJSParams(napi_env env,napi_value arg)564 CfBlob *CertGetBlobFromArrBoolJSParams(napi_env env, napi_value arg)
565 {
566     uint32_t length = 0;
567     if (!GetArrayLen(env, arg, length)) {
568         LOGI("get array length failed!");
569         return nullptr;
570     }
571 
572     CfBlob *newBlob = static_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
573     if (newBlob == nullptr) {
574         LOGE("Failed to allocate newBlob memory!");
575         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
576         return nullptr;
577     }
578 
579     newBlob->size = length;
580     newBlob->data = static_cast<uint8_t *>(HcfMalloc(length, 0));
581     if (newBlob->data == nullptr) {
582         LOGE("Failed to allocate data memory!");
583         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
584         CfFree(newBlob);
585         return nullptr;
586     }
587     napi_status status = napi_ok;
588     for (uint32_t i = 0; i < length; i++) {
589         napi_value element;
590         status = napi_get_element(env, arg, i, &element);
591         if (status != napi_ok) {
592             LOGE("Failed to get element!");
593             break;
594         }
595         bool elemResult = false;
596         status = napi_get_value_bool(env, element, &elemResult);
597         if (status != napi_ok) {
598             LOGE("Failed to get value bool!");
599             break;
600         }
601         newBlob->data[i] = (elemResult ? 1 : 0);
602     }
603 
604     if (status != napi_ok) {
605         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params!"));
606         CfFree(newBlob->data);
607         CfFree(newBlob);
608         return nullptr;
609     }
610 
611     return newBlob;
612 }
613 
CertGetSerialNumberFromBigIntJSParams(napi_env env,napi_value arg,CfBlob & outBlob)614 bool CertGetSerialNumberFromBigIntJSParams(napi_env env, napi_value arg, CfBlob &outBlob)
615 {
616     napi_valuetype valueType;
617     napi_typeof(env, arg, &valueType);
618     if (valueType != napi_bigint) {
619         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type error"));
620         LOGE("wrong argument type. expect int type. [Type]: %d", valueType);
621         return false;
622     }
623 
624     size_t wordCount = 0;
625     if (napi_get_value_bigint_words(env, arg, nullptr, &wordCount, nullptr) != napi_ok) {
626         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum failed"));
627         LOGE("can not get word count");
628         return false;
629     }
630     if (wordCount == 0 || wordCount > (MAX_SN_BYTE_CNT / sizeof(int64_t))) {
631         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum len failed"));
632         LOGE("can not get wordCount, wordCount = %u", wordCount);
633         return false;
634     }
635 
636     uint8_t serialBuf[MAX_SN_BYTE_CNT] = { 0 };
637     uint32_t serialLen = sizeof(int64_t) * wordCount;
638 
639     int sign = 0;
640     if (napi_get_value_bigint_words(env, arg, &sign, &wordCount, reinterpret_cast<uint64_t *>(serialBuf)) != napi_ok ||
641         sign > 0) {
642         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum len failed"));
643         LOGE("can not get bigint value, sign = %d", sign); // sign 0 : positive, sign 1 : negative
644         return false;
645     }
646     outBlob.data = static_cast<uint8_t *>(HcfMalloc(serialLen, 0));
647     if (outBlob.data == nullptr) {
648         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc serialNum failed"));
649         LOGE("malloc blob data failed!");
650         return false;
651     }
652     outBlob.size = serialLen;
653     // reverse data: because BN_bin2bn() converts the positive integer in big-endian form of length len into a BIGNUM
654     for (uint32_t i = 0; i < serialLen; ++i) {
655         outBlob.data[i] = serialBuf[outBlob.size - 1 - i];
656     }
657 
658     return true;
659 }
660 
CertGetStringFromJSParams(napi_env env,napi_value arg,string & returnStr)661 bool CertGetStringFromJSParams(napi_env env, napi_value arg, string &returnStr)
662 {
663     napi_valuetype valueType;
664     napi_typeof(env, arg, &valueType);
665     if (valueType != napi_string) {
666         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not string"));
667         LOGE("wrong argument type. expect string type. [Type]: %d", valueType);
668         return false;
669     }
670 
671     size_t length = 0;
672     if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
673         LOGE("can not get string length");
674         return false;
675     }
676     returnStr.reserve(length + 1);
677     returnStr.resize(length);
678     if (napi_get_value_string_utf8(env, arg, returnStr.data(), (length + 1), &length) != napi_ok) {
679         LOGE("can not get string value");
680         return false;
681     }
682     return true;
683 }
684 
CertGetInt32FromJSParams(napi_env env,napi_value arg,int32_t & returnInt)685 bool CertGetInt32FromJSParams(napi_env env, napi_value arg, int32_t &returnInt)
686 {
687     napi_valuetype valueType;
688     napi_typeof(env, arg, &valueType);
689     if (valueType != napi_number) {
690         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not number"));
691         LOGE("wrong argument type. expect int type. [Type]: %d", valueType);
692         return false;
693     }
694 
695     if (napi_get_value_int32(env, arg, &returnInt) != napi_ok) {
696         LOGE("can not get int value");
697         return false;
698     }
699     return true;
700 }
701 
CertGetCallbackFromJSParams(napi_env env,napi_value arg,napi_ref * returnCb)702 bool CertGetCallbackFromJSParams(napi_env env, napi_value arg, napi_ref *returnCb)
703 {
704     napi_valuetype valueType = napi_undefined;
705     napi_typeof(env, arg, &valueType);
706     if (valueType != napi_function) {
707         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not function"));
708         LOGE("wrong argument type. expect callback type. [Type]: %d", valueType);
709         return false;
710     }
711 
712     napi_create_reference(env, arg, 1, returnCb);
713     return true;
714 }
715 
GetCertErrValueByErrCode(int32_t errCode)716 static uint32_t GetCertErrValueByErrCode(int32_t errCode)
717 {
718     uint32_t count = sizeof(CODE_MAP) / sizeof(CODE_MAP[0]);
719     for (uint32_t i = 0; i < count; i++) {
720         if (errCode == CODE_MAP[i].retValue) {
721             return CODE_MAP[i].retCode;
722         }
723     }
724     return JS_ERR_CERT_RUNTIME_ERROR;
725 }
726 
CertGenerateBusinessError(napi_env env,int32_t errCode,const char * errMsg)727 napi_value CertGenerateBusinessError(napi_env env, int32_t errCode, const char *errMsg)
728 {
729     napi_value businessError = nullptr;
730 
731     napi_value code = nullptr;
732     napi_create_uint32(env, GetCertErrValueByErrCode(errCode), &code);
733 
734     napi_value msg = nullptr;
735     napi_create_string_utf8(env, errMsg, NAPI_AUTO_LENGTH, &msg);
736 
737     napi_create_error(env, nullptr, msg, &businessError);
738     napi_set_named_property(env, businessError, CERT_TAG_ERR_CODE.c_str(), code);
739 
740     return businessError;
741 }
742 
CertCheckArgsCount(napi_env env,size_t argc,size_t expectedCount,bool isSync)743 bool CertCheckArgsCount(napi_env env, size_t argc, size_t expectedCount, bool isSync)
744 {
745     if (isSync) {
746         if (argc != expectedCount) {
747             napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params count"));
748             LOGE("invalid params count!");
749             return false;
750         }
751     } else {
752         if ((argc != expectedCount) && (argc != (expectedCount - ARGS_SIZE_ONE))) {
753             napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params count"));
754             LOGE("invalid params count!");
755             return false;
756         }
757     }
758     return true;
759 }
760 
GetAsyncType(napi_env env,size_t argc,size_t maxCount,napi_value arg)761 AsyncType GetAsyncType(napi_env env, size_t argc, size_t maxCount, napi_value arg)
762 {
763     if (argc == (maxCount - 1)) { /* inner caller func: maxCount is bigger than 1 */
764         return ASYNC_TYPE_PROMISE;
765     }
766 
767     napi_valuetype valueType = napi_undefined;
768     napi_typeof(env, arg, &valueType);
769     /* If the input is undefined or null, the value is processed as promise type. */
770     if ((valueType == napi_undefined) || (valueType == napi_null)) {
771         CF_LOG_I("input value is undefined or null");
772         return ASYNC_TYPE_PROMISE;
773     }
774 
775     return ASYNC_TYPE_CALLBACK;
776 }
777 
CertGetResourceName(napi_env env,const char * name)778 napi_value CertGetResourceName(napi_env env, const char *name)
779 {
780     napi_value resourceName = nullptr;
781     napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &resourceName);
782     return resourceName;
783 }
784 
ConvertBlobToNapiValue(napi_env env,const CfBlob * blob)785 napi_value ConvertBlobToNapiValue(napi_env env, const CfBlob *blob)
786 {
787     if (blob == nullptr || blob->data == nullptr || blob->size == 0) {
788         LOGE("Invalid blob!");
789         return nullptr;
790     }
791     uint8_t *buffer = static_cast<uint8_t *>(HcfMalloc(blob->size, 0));
792     if (buffer == nullptr) {
793         LOGE("malloc uint8 array buffer failed!");
794         return nullptr;
795     }
796 
797     if (memcpy_s(buffer, blob->size, blob->data, blob->size) != EOK) {
798         LOGE("memcpy_s data to buffer failed!");
799         CfFree(buffer);
800         return nullptr;
801     }
802 
803     napi_value outBuffer = nullptr;
804     napi_status status = napi_create_external_arraybuffer(
805         env, buffer, blob->size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
806     if (status != napi_ok) {
807         LOGE("create uint8 array buffer failed!");
808         CfFree(buffer);
809         return nullptr;
810     }
811     buffer = nullptr;
812 
813     napi_value outData = nullptr;
814     napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &outData);
815     napi_value dataBlob = nullptr;
816     napi_create_object(env, &dataBlob);
817     napi_set_named_property(env, dataBlob, CERT_TAG_DATA.c_str(), outData);
818 
819     return dataBlob;
820 }
821 
ConvertBlobToWords(const CfBlob & blob,uint64_t * & words,uint32_t & wordsCount)822 static CfResult ConvertBlobToWords(const CfBlob &blob, uint64_t *&words, uint32_t &wordsCount)
823 {
824     uint32_t blockSize = sizeof(uint64_t);
825     uint32_t convertDataSize = ((blob.size + (blockSize - 1)) >> QUAD_WORD_ALIGN_UP) << QUAD_WORD_ALIGN_UP;
826     uint8_t *convertData = static_cast<uint8_t *>(CfMalloc(convertDataSize));
827     if (convertData == nullptr) {
828         LOGE("malloc convert data failed");
829         return CF_ERR_MALLOC;
830     }
831 
832     /* convertData has been initialized 0, reverse blob data */
833     for (uint32_t i = 0; i < blob.size; ++i) {
834         convertData[i] = blob.data[blob.size - 1 - i];
835     }
836 
837     words = reinterpret_cast<uint64_t *>(convertData);
838     wordsCount = convertDataSize / blockSize;
839     return CF_SUCCESS;
840 }
841 
ConvertBlobToBigIntWords(napi_env env,const CfBlob & blob)842 napi_value ConvertBlobToBigIntWords(napi_env env, const CfBlob &blob)
843 {
844     if (blob.data == nullptr || blob.size == 0 || blob.size > MAX_SN_BYTE_CNT) {
845         LOGE("Invalid blob!");
846         return nullptr;
847     }
848 
849     uint64_t *words = nullptr;
850     uint32_t wordsCount = 0;
851     CfResult ret = ConvertBlobToWords(blob, words, wordsCount);
852     if (ret != CF_SUCCESS) {
853         napi_throw(env, CertGenerateBusinessError(env, ret, "convert data to words failed"));
854         LOGE("convert data to words failed");
855         return nullptr;
856     }
857 
858     napi_value result = nullptr;
859     napi_create_bigint_words(env, 0, wordsCount, words, &result);
860     CfFree(words);
861     return result;
862 }
863 
ConvertBlobToInt64(napi_env env,const CfBlob & blob)864 napi_value ConvertBlobToInt64(napi_env env, const CfBlob &blob)
865 {
866     if (blob.data == nullptr || blob.size == 0 || blob.size > sizeof(int64_t)) {
867         LOGE("Invalid blob!");
868         return nullptr;
869     }
870 
871     uint64_t serialNumber = 0;
872     for (uint32_t i = 0; i < blob.size; ++i) {
873         serialNumber = ((serialNumber << (BYTE_TO_BIT_CNT * i)) | static_cast<uint64_t>(blob.data[i]));
874     }
875 
876     napi_value result = nullptr;
877     napi_create_int64(env, static_cast<long>(serialNumber), &result);
878     return result;
879 }
880 }  // namespace CertFramework
881 }  // namespace OHOS
882