• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 "napi_cert_utils.h"
17 #include <string>
18 #include "cf_log.h"
19 #include "cf_memory.h"
20 #include "cipher.h"
21 #include "config.h"
22 #include "detailed_ccm_params.h"
23 #include "detailed_gcm_params.h"
24 #include "detailed_iv_params.h"
25 #include "napi_cert_defines.h"
26 #include "securec.h"
27 #include "utils.h"
28 #include "napi/native_api.h"
29 #include "napi/native_common.h"
30 
31 namespace OHOS {
32 namespace CertFramework {
33 using namespace std;
34 
35 struct CfResultCodeMap {
36     CfResult retValue;
37     ResultCode retCode;
38 };
39 
40 const struct CfResultCodeMap CODE_MAP[] = {
41     { CF_SUCCESS, JS_SUCCESS },
42     { CF_INVALID_PARAMS, JS_ERR_CERT_INVALID_PARAMS },
43     { CF_NOT_SUPPORT, JS_ERR_CERT_NOT_SUPPORT },
44     { CF_ERR_MALLOC, JS_ERR_CERT_OUT_OF_MEMORY },
45     { CF_ERR_CRYPTO_OPERATION, JS_ERR_CERT_CRYPTO_OPERATION },
46     { CF_ERR_CERT_SIGNATURE_FAILURE, JS_ERR_CERT_SIGNATURE_FAILURE },
47     { CF_ERR_CERT_NOT_YET_VALID, JS_ERR_CERT_NOT_YET_VALID },
48     { CF_ERR_CERT_HAS_EXPIRED, JS_ERR_CERT_HAS_EXPIRED },
49     { CF_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, JS_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY },
50     { CF_ERR_KEYUSAGE_NO_CERTSIGN, JS_ERR_KEYUSAGE_NO_CERTSIGN },
51     { CF_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE, JS_ERR_KEYUSAGE_NO_DIGITAL_SIGNATURE },
52     { CF_ERR_CERT_INVALID_PRIVATE_KEY, JS_ERR_CERT_INVALID_PRIVATE_KEY },
53 };
54 
CertNapiGetNull(napi_env env)55 napi_value CertNapiGetNull(napi_env env)
56 {
57     napi_value result = nullptr;
58     napi_get_null(env, &result);
59     return result;
60 }
61 
ConvertArrayToNapiValue(napi_env env,CfArray * array)62 napi_value ConvertArrayToNapiValue(napi_env env, CfArray *array)
63 {
64     if (array == nullptr) {
65         LOGE("array is null!");
66         return nullptr;
67     }
68     if (array->count == 0) {
69         LOGE("array count is 0!");
70         return nullptr;
71     }
72     napi_value returnArray = nullptr;
73     napi_create_array(env, &returnArray);
74     if (returnArray == nullptr) {
75         LOGE("create return array failed!");
76         return nullptr;
77     }
78     for (uint32_t i = 0; i < array->count; i++) {
79         CfBlob *blob = reinterpret_cast<CfBlob *>(array->data + i);
80         napi_value outBuffer = GenerateArrayBuffer(env, blob->data, blob->size);
81         if (outBuffer == nullptr) {
82             LOGE("generate array buffer failed!");
83             return nullptr;
84         }
85         napi_value element = nullptr;
86         napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &element);
87         napi_set_element(env, returnArray, i, element);
88     }
89     napi_value returnValue = nullptr;
90     napi_create_object(env, &returnValue);
91     napi_set_named_property(env, returnValue, CERT_TAG_DATA.c_str(), returnArray);
92     return returnValue;
93 }
94 
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)95 napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
96 {
97     uint8_t *buffer = static_cast<uint8_t *>(CfMalloc(size, 0));
98     if (buffer == nullptr) {
99         LOGE("malloc uint8 array buffer failed!");
100         return nullptr;
101     }
102 
103     if (memcpy_s(buffer, size, data, size) != EOK) {
104         LOGE("memcpy_s data to buffer failed!");
105         CfFree(buffer);
106         return nullptr;
107     }
108 
109     napi_value outBuffer = nullptr;
110     napi_status status = napi_create_external_arraybuffer(
111         env, buffer, size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
112     if (status != napi_ok) {
113         LOGE("create uint8 array buffer failed!");
114         CfFree(buffer);
115         return nullptr;
116     }
117     buffer = nullptr;
118     return outBuffer;
119 }
120 
GetDataOfEncodingBlob(napi_env env,napi_value data,CfEncodingBlob * encodingBlob)121 static bool GetDataOfEncodingBlob(napi_env env, napi_value data, CfEncodingBlob *encodingBlob)
122 {
123     napi_typedarray_type arrayType;
124     napi_value arrayBuffer = nullptr;
125     size_t length = 0;
126     size_t offset = 0;
127     void *rawData = nullptr;
128 
129     napi_status status = napi_get_typedarray_info(env, data, &arrayType, &length,
130         reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
131     if (status != napi_ok) {
132         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get array data failed"));
133         LOGE("failed to get array data!");
134         return false;
135     }
136     if (arrayType != napi_uint8_array) {
137         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array type is not uint8 array"));
138         LOGE("array is not uint8 array!");
139         return false;
140     }
141 
142     if (length == 0) {
143         LOGE("input data length is 0");
144         return false;
145     }
146     encodingBlob->data = static_cast<uint8_t *>(CfMalloc(length, 0));
147     if (encodingBlob->data == nullptr) {
148         LOGE("malloc encoding blob data failed!");
149         return false;
150     }
151     if (memcpy_s(encodingBlob->data, length, rawData, length) != EOK) {
152         LOGE("memcpy_s encoding blob data failed!");
153         CfFree(encodingBlob->data);
154         encodingBlob->data = nullptr;
155         return false;
156     }
157     encodingBlob->len = length;
158     return true;
159 }
160 
CertGetStringFromValue(napi_env env,napi_value arg)161 static char *CertGetStringFromValue(napi_env env, napi_value arg)
162 {
163     napi_valuetype valueType;
164     napi_typeof(env, arg, &valueType);
165     if (valueType != napi_string) {
166         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not string"));
167         LOGE("wrong argument type. expect string type. [Type]: %d", valueType);
168         return nullptr;
169     }
170 
171     size_t length = 0;
172     if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
173         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "can not get string length!"));
174         LOGE("can not get string length");
175         return nullptr;
176     }
177 
178     if (length == 0) {
179         LOGE("string length is 0");
180         return nullptr;
181     }
182 
183     char *value = static_cast<char *>(CfMalloc(length + 1, 0));
184     if (value == nullptr) {
185         LOGE("Failed to allocate value memory!");
186         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
187         return nullptr;
188     }
189 
190     if (napi_get_value_string_utf8(env, arg, value, length + 1, &length) != napi_ok) {
191         LOGE("can not get value value");
192         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get value failed"));
193         memset_s(value, length + 1, 0, length + 1);
194         CfFree(value);
195         return nullptr;
196     }
197     return value;
198 }
199 
GetEncodingBlobFromValue(napi_env env,napi_value obj,CfEncodingBlob ** encodingBlob)200 bool GetEncodingBlobFromValue(napi_env env, napi_value obj, CfEncodingBlob **encodingBlob)
201 {
202     *encodingBlob = static_cast<CfEncodingBlob *>(CfMalloc(sizeof(CfEncodingBlob), 0));
203     if (*encodingBlob == nullptr) {
204         LOGE("malloc encoding blob failed!");
205         return false;
206     }
207     napi_value data = nullptr;
208     napi_status status = napi_get_named_property(env, obj, CERT_TAG_DATA.c_str(), &data);
209     if (status != napi_ok) {
210         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get encoding blob data failed"));
211         LOGE("failed to get encoding blob data!");
212         CfFree(*encodingBlob);
213         *encodingBlob = nullptr;
214         return false;
215     }
216     if (!GetDataOfEncodingBlob(env, data, *encodingBlob)) {
217         CfFree(*encodingBlob);
218         *encodingBlob = nullptr;
219         return false;
220     }
221     napi_value format = nullptr;
222     status = napi_get_named_property(env, obj, CERT_TAG_ENCODING_FORMAT.c_str(), &format);
223     if (status != napi_ok) {
224         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get encoding blob format failed"));
225         LOGE("failed to get encoding blob format!");
226         CfFree((*encodingBlob)->data);
227         (*encodingBlob)->data = nullptr;
228         CfFree(*encodingBlob);
229         *encodingBlob = nullptr;
230         return false;
231     }
232     napi_get_value_uint32(env, format, reinterpret_cast<uint32_t *>(&(*encodingBlob)->encodingFormat));
233     return true;
234 }
235 
AllocatePrivateKey(PrivateKeyInfo ** privateKey)236 static bool AllocatePrivateKey(PrivateKeyInfo **privateKey)
237 {
238     (*privateKey)->privateKey = static_cast<CfEncodingBlob *>(CfMalloc(sizeof(CfEncodingBlob), 0));
239     return (*privateKey)->privateKey != nullptr;
240 }
241 
GetBlobFromData(napi_env env,napi_value data,CfBlob ** blob,napi_valuetype valueType)242 static bool GetBlobFromData(napi_env env, napi_value data, CfBlob **blob, napi_valuetype valueType)
243 {
244     if (valueType == napi_string) {
245         *blob = CertGetBlobFromStringJSParams(env, data);
246         if (*blob == nullptr) {
247             LOGE("get private key from string failed!");
248             return false;
249         }
250         return true;
251     } else {
252         *blob = CertGetBlobFromUint8ArrJSParams(env, data);
253         if (*blob == nullptr) {
254             LOGE("get private key from uint8 array failed!");
255             return false;
256         }
257         return true;
258     }
259 }
260 
CopyBlobDataToPrivateKey(CfBlob * blob,CfEncodingBlob * privateKey)261 static bool CopyBlobDataToPrivateKey(CfBlob *blob, CfEncodingBlob *privateKey)
262 {
263     privateKey->data = static_cast<uint8_t *>(CfMalloc(blob->size, 0));
264     if (privateKey->data == nullptr) {
265         LOGE("malloc private key data failed!");
266         return false;
267     }
268     if (memcpy_s(privateKey->data, blob->size, blob->data, blob->size) != EOK) {
269         LOGE("memcpy_s private key data failed!");
270         CfFree(privateKey->data);
271         privateKey->data = nullptr;
272         return false;
273     }
274     privateKey->len = blob->size;
275     return true;
276 }
277 
GetPrivateKeyFromValue(napi_env env,napi_value obj,PrivateKeyInfo ** privateKey)278 static bool GetPrivateKeyFromValue(napi_env env, napi_value obj, PrivateKeyInfo **privateKey)
279 {
280     napi_value data = nullptr;
281     napi_valuetype valueType = napi_undefined;
282     napi_status status = napi_get_named_property(env, obj, CERT_PRIVATE_KEY.c_str(), &data);
283     if (status != napi_ok || data == nullptr) {
284         LOGE("Failed to get private key property!");
285         return false;
286     }
287 
288     napi_typeof(env, data, &valueType);
289     if (valueType == napi_undefined) {
290         LOGE("Invalid type for private key property!");
291         return false;
292     }
293 
294     if (!AllocatePrivateKey(privateKey)) {
295         LOGE("malloc private key failed!");
296         return false;
297     }
298 
299     CfBlob *blob = nullptr;
300     if (!GetBlobFromData(env, data, &blob, valueType)) {
301         CfFree((*privateKey)->privateKey);
302         (*privateKey)->privateKey = nullptr;
303         return false;
304     }
305 
306     (*privateKey)->privateKey->encodingFormat = (valueType == napi_string) ? CF_FORMAT_PEM : CF_FORMAT_DER;
307 
308     if (!CopyBlobDataToPrivateKey(blob, (*privateKey)->privateKey)) {
309         CfFree(blob);
310         CfFree((*privateKey)->privateKey);
311         (*privateKey)->privateKey = nullptr;
312         return false;
313     }
314 
315     CfFree(blob);
316     return true;
317 }
318 
GetPrivateKeyPasswordFromValue(napi_env env,napi_value obj,PrivateKeyInfo ** privateKey)319 static bool GetPrivateKeyPasswordFromValue(napi_env env, napi_value obj, PrivateKeyInfo **privateKey)
320 {
321     bool result = false;
322     napi_has_named_property(env, obj, CERT_PASSWORD.c_str(), &result);
323     if (!result) {
324         return true;
325     }
326     napi_value password = nullptr;
327     napi_status status = napi_get_named_property(env, obj, CERT_PASSWORD.c_str(), &password);
328     if (status != napi_ok || password == nullptr) {
329         LOGE("get property %s failed!", CERT_PASSWORD.c_str());
330         return false;
331     }
332     (*privateKey)->privateKeyPassword = CertGetStringFromValue(env, password);
333     return true;
334 }
335 
GetPrivateKeyInfoFromValue(napi_env env,napi_value obj,PrivateKeyInfo ** privateKey)336 bool GetPrivateKeyInfoFromValue(napi_env env, napi_value obj, PrivateKeyInfo **privateKey)
337 {
338     *privateKey = static_cast<PrivateKeyInfo *>(CfMalloc(sizeof(PrivateKeyInfo), 0));
339     if (*privateKey == nullptr) {
340         LOGE("malloc private key failed!");
341         return false;
342     }
343     if (!GetPrivateKeyFromValue(env, obj, privateKey)) {
344         CfFree(*privateKey);
345         *privateKey = nullptr;
346         return false;
347     }
348     if (!GetPrivateKeyPasswordFromValue(env, obj, privateKey)) {
349         CfFree(*privateKey);
350         *privateKey = nullptr;
351         return false;
352     }
353     return true;
354 }
355 
FreePrivateKeyInfo(PrivateKeyInfo * privateKey)356 void FreePrivateKeyInfo(PrivateKeyInfo *privateKey)
357 {
358     if (privateKey != nullptr) {
359         if (privateKey->privateKey != nullptr) {
360             memset_s(privateKey->privateKey->data, privateKey->privateKey->len, 0, privateKey->privateKey->len);
361             CF_FREE_PTR(privateKey->privateKey->data);
362             CF_FREE_PTR(privateKey->privateKey);
363         }
364         if (privateKey->privateKeyPassword != nullptr) {
365             (void)memset_s(privateKey->privateKeyPassword, strlen(privateKey->privateKeyPassword), 0,
366                 strlen(privateKey->privateKeyPassword));
367             CF_FREE_PTR(privateKey->privateKeyPassword);
368         }
369         CF_FREE_PTR(privateKey);
370     }
371 }
372 
GetMdName(napi_env env,napi_value arg,char ** mdName)373 static bool GetMdName(napi_env env, napi_value arg, char **mdName)
374 {
375     bool result = false;
376     napi_has_named_property(env, arg, CMS_GENERATOR_MDNAME.c_str(), &result);
377     if (!result) {
378         LOGI("%s do not exist!", CMS_GENERATOR_MDNAME.c_str());
379         return false;
380     }
381     napi_value obj = nullptr;
382     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_MDNAME.c_str(), &obj);
383     if (status != napi_ok || obj == nullptr) {
384         LOGE("get property %s failed!", CMS_GENERATOR_MDNAME.c_str());
385         return false;
386     }
387     napi_valuetype valueType;
388     napi_typeof(env, obj, &valueType);
389     if (valueType == napi_undefined) {
390         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_MDNAME.c_str());
391         return false;
392     }
393     *mdName = CertGetStringFromValue(env, obj);
394     return true;
395 }
396 
GetAddCert(napi_env env,napi_value arg,bool * addCert)397 static bool GetAddCert(napi_env env, napi_value arg, bool *addCert)
398 {
399     bool result = false;
400     napi_has_named_property(env, arg, CMS_GENERATOR_ADD_CERT.c_str(), &result);
401     if (!result) {
402         LOGI("%s do not exist!", CMS_GENERATOR_ADD_CERT.c_str());
403         *addCert = true;
404         return true;
405     }
406     napi_value obj = nullptr;
407     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_ADD_CERT.c_str(), &obj);
408     if (status != napi_ok || obj == nullptr) {
409         LOGE("get property %s failed!", CMS_GENERATOR_ADD_CERT.c_str());
410         return false;
411     }
412     napi_valuetype valueType;
413     napi_typeof(env, obj, &valueType);
414     if (valueType == napi_undefined) {
415         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_ADD_CERT.c_str());
416         return false;
417     }
418     napi_get_value_bool(env, obj, addCert);
419     return true;
420 }
421 
GetAddSmimeCapAttr(napi_env env,napi_value arg,bool * addSmimeCapAttr)422 static bool GetAddSmimeCapAttr(napi_env env, napi_value arg, bool *addSmimeCapAttr)
423 {
424     bool result = false;
425     napi_has_named_property(env, arg, CMS_GENERATOR_ADD_SMIME_CAP_ATTR.c_str(), &result);
426     if (!result) {
427         LOGI("%s do not exist!", CMS_GENERATOR_ADD_SMIME_CAP_ATTR.c_str());
428         *addSmimeCapAttr = true;
429         return true;
430     }
431     napi_value obj = nullptr;
432     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_ADD_SMIME_CAP_ATTR.c_str(), &obj);
433     if (status != napi_ok || obj == nullptr) {
434         LOGE("get property %s failed!", CMS_GENERATOR_ADD_SMIME_CAP_ATTR.c_str());
435         return false;
436     }
437     napi_valuetype valueType;
438     napi_typeof(env, obj, &valueType);
439     if (valueType == napi_undefined) {
440         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_ADD_SMIME_CAP_ATTR.c_str());
441         return false;
442     }
443     napi_get_value_bool(env, obj, addSmimeCapAttr);
444     return true;
445 }
446 
GetAddAttr(napi_env env,napi_value arg,bool * addAttr)447 static bool GetAddAttr(napi_env env, napi_value arg, bool *addAttr)
448 {
449     bool result = false;
450     napi_has_named_property(env, arg, CMS_GENERATOR_ADD_ATTR.c_str(), &result);
451     if (!result) {
452         LOGI("%s do not exist!", CMS_GENERATOR_ADD_ATTR.c_str());
453         *addAttr = true;
454         return true;
455     }
456     napi_value obj = nullptr;
457     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_ADD_ATTR.c_str(), &obj);
458     if (status != napi_ok || obj == nullptr) {
459         LOGE("get property %s failed!", CMS_GENERATOR_ADD_ATTR.c_str());
460         return false;
461     }
462     napi_valuetype valueType;
463     napi_typeof(env, obj, &valueType);
464     if (valueType == napi_undefined) {
465         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_ADD_ATTR.c_str());
466         return false;
467     }
468     napi_get_value_bool(env, obj, addAttr);
469     return true;
470 }
471 
BuildCmsSignerOptions(napi_env env,napi_value obj,HcfCmsSignerOptions * options)472 static bool BuildCmsSignerOptions(napi_env env, napi_value obj, HcfCmsSignerOptions *options)
473 {
474     napi_valuetype type;
475     napi_typeof(env, obj, &type);
476     if (type != napi_object) {
477         LOGE("wrong argument type. expect object type. [Type]: %d", type);
478         return false;
479     }
480     if (!GetMdName(env, obj, &options->mdName)) {
481         return false;
482     }
483     if (!GetAddCert(env, obj, &options->addCert)) {
484         return false;
485     }
486     if (!GetAddAttr(env, obj, &options->addAttr)) {
487         return false;
488     }
489     if (!GetAddSmimeCapAttr(env, obj, &options->addSmimeCapAttr)) {
490         return false;
491     }
492     return true;
493 }
494 
GetCmsSignerOptionsFromValue(napi_env env,napi_value obj,HcfCmsSignerOptions ** cmsSignerOptions)495 bool GetCmsSignerOptionsFromValue(napi_env env, napi_value obj, HcfCmsSignerOptions **cmsSignerOptions)
496 {
497     *cmsSignerOptions = static_cast<HcfCmsSignerOptions *>(CfMalloc(sizeof(HcfCmsSignerOptions), 0));
498     if (*cmsSignerOptions == nullptr) {
499         LOGE("malloc cms signer options failed!");
500         return false;
501     }
502     if (!BuildCmsSignerOptions(env, obj, *cmsSignerOptions)) {
503         CfFree((*cmsSignerOptions)->mdName);
504         (*cmsSignerOptions)->mdName = nullptr;
505         CfFree(*cmsSignerOptions);
506         *cmsSignerOptions = nullptr;
507         return false;
508     }
509     return true;
510 }
511 
GetFormat(napi_env env,napi_value arg,HcfCmsFormat * format)512 static bool GetFormat(napi_env env, napi_value arg, HcfCmsFormat *format)
513 {
514     bool result = false;
515     napi_has_named_property(env, arg, CMS_GENERATOR_OUT_FORMAT.c_str(), &result);
516     if (!result) {
517         LOGI("%s do not exist!", CMS_GENERATOR_OUT_FORMAT.c_str());
518         return true;
519     }
520     napi_value obj = nullptr;
521     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_OUT_FORMAT.c_str(), &obj);
522     if (status != napi_ok || obj == nullptr) {
523         LOGE("get property %s failed!", CMS_GENERATOR_OUT_FORMAT.c_str());
524         return false;
525     }
526     napi_valuetype valueType;
527     napi_typeof(env, obj, &valueType);
528     if (valueType == napi_undefined) {
529         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_OUT_FORMAT.c_str());
530         return false;
531     }
532     napi_get_value_uint32(env, obj, reinterpret_cast<uint32_t *>(format));
533     return true;
534 }
535 
GetIsDetachedContent(napi_env env,napi_value arg,bool * isDetachedContent)536 static bool GetIsDetachedContent(napi_env env, napi_value arg, bool *isDetachedContent)
537 {
538     bool result = false;
539     napi_has_named_property(env, arg, CMS_GENERATOR_IS_DETACHED_CONTENT.c_str(), &result);
540     if (!result) {
541         LOGI("%s do not exist!", CMS_GENERATOR_IS_DETACHED_CONTENT.c_str());
542         return true;
543     }
544     napi_value obj = nullptr;
545     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_IS_DETACHED_CONTENT.c_str(), &obj);
546     if (status != napi_ok || obj == nullptr) {
547         LOGE("get property %s failed!", CMS_GENERATOR_IS_DETACHED_CONTENT.c_str());
548         return false;
549     }
550     napi_valuetype valueType;
551     napi_typeof(env, obj, &valueType);
552     if (valueType == napi_undefined) {
553         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_IS_DETACHED_CONTENT.c_str());
554         return false;
555     }
556     napi_get_value_bool(env, obj, isDetachedContent);
557     return true;
558 }
559 
GetContentDataFormat(napi_env env,napi_value arg,HcfCmsContentDataFormat * dataFormat)560 static bool GetContentDataFormat(napi_env env, napi_value arg, HcfCmsContentDataFormat *dataFormat)
561 {
562     bool result = false;
563     napi_has_named_property(env, arg, CMS_GENERATOR_CONTENT_DATA_FORMAT.c_str(), &result);
564     if (!result) {
565         LOGI("%s do not exist!", CMS_GENERATOR_CONTENT_DATA_FORMAT.c_str());
566         return true;
567     }
568     napi_value obj = nullptr;
569     napi_status status = napi_get_named_property(env, arg, CMS_GENERATOR_CONTENT_DATA_FORMAT.c_str(), &obj);
570     if (status != napi_ok || obj == nullptr) {
571         LOGE("get property %s failed!", CMS_GENERATOR_CONTENT_DATA_FORMAT.c_str());
572         return false;
573     }
574     napi_valuetype valueType;
575     napi_typeof(env, obj, &valueType);
576     if (valueType == napi_undefined) {
577         LOGE("%s valueType is null or undefined.", CMS_GENERATOR_CONTENT_DATA_FORMAT.c_str());
578         return false;
579     }
580     napi_get_value_uint32(env, obj, reinterpret_cast<uint32_t *>(dataFormat));
581     return true;
582 }
583 
GetCmsGeneratorOptionsFromValue(napi_env env,napi_value obj,HcfCmsGeneratorOptions ** options)584 bool GetCmsGeneratorOptionsFromValue(napi_env env, napi_value obj, HcfCmsGeneratorOptions **options)
585 {
586     napi_valuetype type;
587     napi_typeof(env, obj, &type);
588     if (type != napi_object) {
589         LOGE("wrong argument type. expect object type. [Type]: %d", type);
590         return false;
591     }
592     if (!GetContentDataFormat(env, obj, &(*options)->dataFormat)) {
593         LOGE("GetContentDataFormat failed!");
594         return false;
595     }
596     if (!GetFormat(env, obj, &(*options)->outFormat)) {
597         LOGE("GetFormat failed!");
598         return false;
599     }
600     if (!GetIsDetachedContent(env, obj, &(*options)->isDetachedContent)) {
601         LOGE("GetIsDetachedContent failed!");
602         return false;
603     }
604     return true;
605 }
ConvertEncodingBlobToNapiValue(napi_env env,CfEncodingBlob * encodingBlob)606 napi_value ConvertEncodingBlobToNapiValue(napi_env env, CfEncodingBlob *encodingBlob)
607 {
608     napi_value outBuffer = GenerateArrayBuffer(env, encodingBlob->data, encodingBlob->len);
609     if (outBuffer == nullptr) {
610         LOGE("generate array buffer failed!");
611         return nullptr;
612     }
613     napi_value outData = nullptr;
614     napi_create_typedarray(env, napi_uint8_array, encodingBlob->len, outBuffer, 0, &outData);
615     napi_value encoding = nullptr;
616     napi_create_uint32(env, encodingBlob->encodingFormat, &encoding);
617     napi_value returnEncodingBlob = nullptr;
618     napi_create_object(env, &returnEncodingBlob);
619     napi_set_named_property(env, returnEncodingBlob, CERT_TAG_DATA.c_str(), outData);
620     napi_set_named_property(env, returnEncodingBlob, CERT_TAG_ENCODING_FORMAT.c_str(), encoding);
621     return returnEncodingBlob;
622 }
623 
CertGetBlobFromNapiValue(napi_env env,napi_value arg)624 CfBlob *CertGetBlobFromNapiValue(napi_env env, napi_value arg)
625 {
626     if ((env == nullptr) || (arg == nullptr)) {
627         LOGE("Invalid parmas!");
628         return nullptr;
629     }
630     napi_value data = nullptr;
631     napi_status status = napi_get_named_property(env, arg, CERT_TAG_DATA.c_str(), &data);
632     if ((status != napi_ok) || (data == nullptr)) {
633         LOGE("failed to get valid data property!");
634         return nullptr;
635     }
636     return CertGetBlobFromUint8ArrJSParams(env, data);
637 }
638 
CertConvertBlobToNapiValue(napi_env env,CfBlob * blob)639 napi_value CertConvertBlobToNapiValue(napi_env env, CfBlob *blob)
640 {
641     napi_value outData = ConvertBlobToUint8ArrNapiValue(env, blob);
642     if (outData == nullptr) {
643         LOGE("convert to uint8 arr failed");
644         return nullptr;
645     }
646     napi_value dataBlob = nullptr;
647     napi_create_object(env, &dataBlob);
648     napi_set_named_property(env, dataBlob, CERT_TAG_DATA.c_str(), outData);
649 
650     return dataBlob;
651 }
652 
ConvertBlobToUint8ArrNapiValue(napi_env env,CfBlob * blob)653 napi_value ConvertBlobToUint8ArrNapiValue(napi_env env, CfBlob *blob)
654 {
655     if (blob == nullptr || blob->data == nullptr || blob->size == 0) {
656         LOGE("Invalid blob!");
657         return nullptr;
658     }
659     /* free in napi_create_external_arraybuffer, not in this scope. */
660     uint8_t *buffer = static_cast<uint8_t *>(CfMalloc(blob->size, 0));
661     if (buffer == nullptr) {
662         LOGE("malloc uint8 array buffer failed!");
663         return nullptr;
664     }
665 
666     if (memcpy_s(buffer, blob->size, blob->data, blob->size) != EOK) {
667         LOGE("memcpy_s data to buffer failed!");
668         CfFree(buffer);
669         return nullptr;
670     }
671 
672     napi_value outBuffer = nullptr;
673     napi_status status = napi_create_external_arraybuffer(
674         env, buffer, blob->size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
675     if (status != napi_ok) {
676         LOGE("create uint8 array buffer failed!");
677         CfFree(buffer);
678         return nullptr;
679     }
680     buffer = nullptr;
681 
682     napi_value outData = nullptr;
683     napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &outData);
684 
685     return outData;
686 }
687 
GetDataOfCertChain(napi_env env,napi_value data,HcfCertChainData * certChain)688 static bool GetDataOfCertChain(napi_env env, napi_value data, HcfCertChainData *certChain)
689 {
690     napi_typedarray_type arrayType;
691     napi_value arrayBuffer = nullptr;
692     size_t length = 0;
693     size_t offset = 0;
694     void *rawData = nullptr;
695 
696     napi_status status = napi_get_typedarray_info(env, data, &arrayType, &length,
697         reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
698     if (status != napi_ok) {
699         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get array data failed"));
700         LOGE("failed to get array data!");
701         return false;
702     }
703     if (arrayType != napi_uint8_array) {
704         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array type is not uint8 array"));
705         LOGE("array is not uint8 array!");
706         return false;
707     }
708 
709     if (length == 0) {
710         LOGE("input data length is 0");
711         return false;
712     }
713     certChain->data = static_cast<uint8_t *>(CfMalloc(length, 0));
714     if (certChain->data == nullptr) {
715         LOGE("malloc cert chain data failed!");
716         return false;
717     }
718     if (memcpy_s(certChain->data, length, rawData, length) != EOK) {
719         LOGE("memcpy_s cert chain data failed!");
720         CfFree(certChain->data);
721         certChain->data = nullptr;
722         return false;
723     }
724     certChain->dataLen = length;
725     return true;
726 }
727 
GetCertChainFromValue(napi_env env,napi_value obj,HcfCertChainData ** certChainData)728 bool GetCertChainFromValue(napi_env env, napi_value obj, HcfCertChainData **certChainData)
729 {
730     *certChainData = static_cast<HcfCertChainData *>(CfMalloc(sizeof(HcfCertChainData), 0));
731     if (*certChainData == nullptr) {
732         LOGE("malloc certChainData failed!");
733         return false;
734     }
735     napi_value data = nullptr;
736     napi_status status = napi_get_named_property(env, obj, CERT_TAG_DATA.c_str(), &data);
737     if (status != napi_ok) {
738         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain data failed"));
739         LOGE("failed to get cert chain data!");
740         CfFree(*certChainData);
741         *certChainData = nullptr;
742         return false;
743     }
744     if (!GetDataOfCertChain(env, data, *certChainData)) {
745         CfFree(*certChainData);
746         *certChainData = nullptr;
747         return false;
748     }
749 
750     napi_value certCount = nullptr;
751     status = napi_get_named_property(env, obj, CERT_TAG_COUNT.c_str(), &certCount);
752     if (status != napi_ok) {
753         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain count failed"));
754         LOGE("failed to get cert count!");
755         CfFree((*certChainData)->data);
756         (*certChainData)->data = nullptr;
757         CfFree(*certChainData);
758         *certChainData = nullptr;
759         return false;
760     }
761     napi_get_value_uint32(env, certCount, reinterpret_cast<uint32_t *>(&(*certChainData)->count));
762 
763     napi_value format = nullptr;
764     status = napi_get_named_property(env, obj, CERT_TAG_ENCODING_FORMAT.c_str(), &format);
765     if (status != napi_ok) {
766         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get cert chain format failed"));
767         LOGE("failed to get cert chain format!");
768         CfFree((*certChainData)->data);
769         (*certChainData)->data = nullptr;
770         CfFree(*certChainData);
771         *certChainData = nullptr;
772         return false;
773     }
774     napi_get_value_uint32(env, format, reinterpret_cast<uint32_t *>(&(*certChainData)->format));
775     return true;
776 }
777 
CertGetBlobFromUint8ArrJSParams(napi_env env,napi_value arg)778 CfBlob *CertGetBlobFromUint8ArrJSParams(napi_env env, napi_value arg)
779 {
780     size_t length = 0;
781     size_t offset = 0;
782     void *rawData = nullptr;
783     napi_value arrayBuffer = nullptr;
784     napi_typedarray_type arrayType;
785     // Warning: Do not release the rawData returned by this interface because the rawData is managed by VM.
786     napi_status status = napi_get_typedarray_info(
787         env, arg, &arrayType, &length, reinterpret_cast<void **>(&rawData), &arrayBuffer, &offset);
788     if (status != napi_ok) {
789         LOGE("failed to get valid rawData.");
790         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "failed to get valid rawData!"));
791         return nullptr;
792     }
793     if (arrayType != napi_uint8_array) {
794         LOGE("input data is not uint8 array.");
795         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input data is not uint8 array!"));
796         return nullptr;
797     }
798 
799     if (length == 0 || rawData == nullptr) {
800         LOGE("array length is 0!");
801         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array length is 0!"));
802         return nullptr;
803     }
804 
805     CfBlob *newBlob = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
806     if (newBlob == nullptr) {
807         LOGE("Failed to allocate newBlob memory!");
808         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
809         return nullptr;
810     }
811 
812     newBlob->size = length;
813     newBlob->data = static_cast<uint8_t *>(CfMalloc(length, 0));
814     if (newBlob->data == nullptr) {
815         LOGE("malloc blob data failed!");
816         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
817         CfFree(newBlob);
818         return nullptr;
819     }
820     if (memcpy_s(newBlob->data, length, rawData, length) != EOK) {
821         LOGE("memcpy_s blob data failed!");
822         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_COPY, "copy memory failed!"));
823         CfFree(newBlob->data);
824         CfFree(newBlob);
825         return nullptr;
826     }
827     return newBlob;
828 }
829 
CertGetBlobFromStringJSParams(napi_env env,napi_value arg)830 CfBlob *CertGetBlobFromStringJSParams(napi_env env, napi_value arg)
831 {
832     napi_valuetype valueType;
833     napi_typeof(env, arg, &valueType);
834     if (valueType != napi_string) {
835         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not string"));
836         LOGE("wrong argument type. expect string type. [Type]: %d", valueType);
837         return nullptr;
838     }
839 
840     size_t length = 0;
841     if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
842         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "can not get string length!"));
843         LOGE("can not get string length");
844         return nullptr;
845     }
846 
847     if (length == 0) {
848         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "string length is 0!"));
849         LOGE("string length is 0");
850         return nullptr;
851     }
852 
853     CfBlob *newBlob = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
854     if (newBlob == nullptr) {
855         LOGE("Failed to allocate newBlob memory!");
856         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed!"));
857         return nullptr;
858     }
859 
860     newBlob->size = length + 1;
861     newBlob->data = static_cast<uint8_t *>(CfMalloc(newBlob->size, 0));
862     if (newBlob->data == nullptr) {
863         LOGE("malloc blob data failed!");
864         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
865         CfFree(newBlob);
866         return nullptr;
867     }
868 
869     if (napi_get_value_string_utf8(env, arg, reinterpret_cast<char *>(newBlob->data), newBlob->size, &length) !=
870         napi_ok) {
871         LOGE("can not get string value");
872         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get string failed"));
873         CfFree(newBlob->data);
874         CfFree(newBlob);
875         return nullptr;
876     }
877     return newBlob;
878 }
879 
GetProp(napi_env env,napi_value arg,const char * name)880 napi_value GetProp(napi_env env, napi_value arg, const char *name)
881 {
882     bool result = false;
883     napi_has_named_property(env, arg, name, &result);
884     if (!result) {
885         LOGI("%s do not exist!", name);
886         return nullptr;
887     }
888     napi_value obj = nullptr;
889     napi_status status = napi_get_named_property(env, arg, name, &obj);
890     if (status != napi_ok || obj == nullptr) {
891         LOGI("get property %s failed!", name);
892         return nullptr;
893     }
894     napi_valuetype valueType;
895     napi_typeof(env, obj, &valueType);
896     if (valueType == napi_undefined) {
897         LOGI("%s valueType is null or undefined.", name);
898         return nullptr;
899     }
900 
901     LOGI("%s is not null!", name);
902     return obj;
903 }
904 
CertGetBlobArrFromArrUarrJSParams(napi_env env,napi_value arg)905 CfBlobArray *CertGetBlobArrFromArrUarrJSParams(napi_env env, napi_value arg)
906 {
907     bool flag = false;
908     napi_status status = napi_is_array(env, arg, &flag);
909     if (status != napi_ok || !flag) {
910         LOGE("not array!");
911         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "not array!"));
912         return nullptr;
913     }
914     uint32_t length = 0;
915     status = napi_get_array_length(env, arg, &length);
916     if (status != napi_ok || length == 0 || length > MAX_NAPI_ARRAY_OF_U8ARR) {
917         LOGE("length is invalid!");
918         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "length is invalid!"));
919         return nullptr;
920     }
921 
922     CfBlobArray *newBlobArr = static_cast<CfBlobArray *>(CfMalloc(sizeof(CfBlobArray), 0));
923     if (newBlobArr == nullptr) {
924         LOGE("Failed to allocate newBlobArr memory!");
925         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
926         return nullptr;
927     }
928 
929     newBlobArr->count = length;
930     newBlobArr->data = static_cast<CfBlob *>(CfMalloc(length * sizeof(CfBlob), 0));
931     if (newBlobArr->data == nullptr) {
932         LOGE("Failed to allocate data memory!");
933         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
934         CfFree(newBlobArr);
935         return nullptr;
936     }
937     for (uint32_t i = 0; i < length; i++) {
938         napi_value element;
939         if (napi_get_element(env, arg, i, &element) == napi_ok) {
940             CfBlob *blob = CertGetBlobFromUint8ArrJSParams(env, element);
941             if (blob != nullptr) {
942                 newBlobArr->data[i] = *blob;
943                 CfFree(blob); // release blob object, not release blob data
944                 continue;
945             }
946         }
947         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input arr is invalid"));
948         FreeCfBlobArray(newBlobArr->data, newBlobArr->count);
949         CfFree(newBlobArr);
950         LOGE("Failed to allocate data memory!");
951         return nullptr;
952     }
953     return newBlobArr;
954 }
955 
GetArrayLen(napi_env env,napi_value arg,uint32_t & length)956 static bool GetArrayLen(napi_env env, napi_value arg, uint32_t &length)
957 {
958     bool flag = false;
959     napi_status status = napi_is_array(env, arg, &flag);
960     if (status != napi_ok || !flag) {
961         LOGE("not array!");
962         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "not array!"));
963         return false;
964     }
965 
966     status = napi_get_array_length(env, arg, &length);
967     if (status != napi_ok || length == 0) {
968         LOGE("array length = 0!");
969         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "array length = 0!"));
970         return false;
971     }
972     return true;
973 }
974 
CertGetBlobFromArrBoolJSParams(napi_env env,napi_value arg)975 CfBlob *CertGetBlobFromArrBoolJSParams(napi_env env, napi_value arg)
976 {
977     uint32_t length = 0;
978     if (!GetArrayLen(env, arg, length)) {
979         LOGE("get array length failed!");
980         return nullptr;
981     }
982 
983     CfBlob *newBlob = static_cast<CfBlob *>(CfMalloc(sizeof(CfBlob), 0));
984     if (newBlob == nullptr) {
985         LOGE("Failed to allocate newBlob memory!");
986         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
987         return nullptr;
988     }
989 
990     newBlob->size = length;
991     newBlob->data = static_cast<uint8_t *>(CfMalloc(length, 0));
992     if (newBlob->data == nullptr) {
993         LOGE("Failed to allocate data memory!");
994         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
995         CfFree(newBlob);
996         return nullptr;
997     }
998     napi_status status = napi_ok;
999     for (uint32_t i = 0; i < length; i++) {
1000         napi_value element;
1001         status = napi_get_element(env, arg, i, &element);
1002         if (status != napi_ok) {
1003             LOGE("Failed to get element!");
1004             break;
1005         }
1006         bool elemResult = false;
1007         status = napi_get_value_bool(env, element, &elemResult);
1008         if (status != napi_ok) {
1009             LOGE("Failed to get value bool!");
1010             break;
1011         }
1012         newBlob->data[i] = (elemResult ? 1 : 0);
1013     }
1014 
1015     if (status != napi_ok) {
1016         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params!"));
1017         CfFree(newBlob->data);
1018         CfFree(newBlob);
1019         return nullptr;
1020     }
1021 
1022     return newBlob;
1023 }
1024 
ParserArray(napi_env env,napi_value arg,uint32_t & arrayLen)1025 bool ParserArray(napi_env env, napi_value arg, uint32_t &arrayLen)
1026 {
1027     bool flag = false;
1028     napi_status status = napi_is_array(env, arg, &flag);
1029     if (status != napi_ok || !flag) {
1030         return false;
1031     }
1032     uint32_t length = 0;
1033     status = napi_get_array_length(env, arg, &length);
1034     if (status != napi_ok || length == 0 || length > MAX_NAPI_ARRAY_OF_U8ARR) {
1035         return false;
1036     }
1037     arrayLen = length;
1038     return true;
1039 }
1040 
SubAltNameArrayDataClearAndFree(SubAltNameArray * array)1041 void SubAltNameArrayDataClearAndFree(SubAltNameArray *array)
1042 {
1043     if (array == NULL) {
1044         LOGD("The input array is null, no need to free.");
1045         return;
1046     }
1047     if (array->data != NULL) {
1048         for (uint32_t i = 0; i < array->count; ++i) {
1049             CF_FREE_BLOB(array->data[i].name);
1050         }
1051         CfFree(array->data);
1052         array->data = NULL;
1053         array->count = 0;
1054     }
1055 }
1056 
CertGetSANArrFromArrUarrJSParams(napi_env env,napi_value arg)1057 SubAltNameArray *CertGetSANArrFromArrUarrJSParams(napi_env env, napi_value arg)
1058 {
1059     uint32_t length = 0;
1060     if (!ParserArray(env, arg, length)) {
1061         LOGE("Length is invalid!");
1062         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "length is invalid!"));
1063         return nullptr;
1064     }
1065 
1066     SubAltNameArray *newSANArr = static_cast<SubAltNameArray *>(CfMalloc(sizeof(SubAltNameArray), 0));
1067     if (newSANArr == nullptr) {
1068         LOGE("Failed to allocate newSANArr memory!");
1069         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
1070         return nullptr;
1071     }
1072 
1073     newSANArr->count = length;
1074     newSANArr->data =
1075         static_cast<SubjectAlternaiveNameData *>(CfMalloc(length * sizeof(SubjectAlternaiveNameData), 0));
1076     if (newSANArr->data == nullptr) {
1077         LOGE("Failed to allocate data memory!");
1078         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
1079         SubAltNameArrayDataClearAndFree(newSANArr);
1080         CfFree(newSANArr);
1081         return nullptr;
1082     }
1083     for (uint32_t i = 0; i < length; i++) {
1084         napi_value element;
1085         if (napi_get_element(env, arg, i, &element) == napi_ok) {
1086             napi_value obj = GetProp(env, element, CERT_MATCH_TAG_SUBJECT_ALT_NAMES_TYPE.c_str());
1087             if (obj == nullptr || napi_get_value_int32(env, obj, (int32_t *)&(newSANArr->data[i].type)) != napi_ok) {
1088                 LOGE("Failed to get type!");
1089                 SubAltNameArrayDataClearAndFree(newSANArr);
1090                 CfFree(newSANArr);
1091                 return nullptr;
1092             }
1093             obj = GetProp(env, element, CERT_MATCH_TAG_SUBJECT_ALT_NAMES_DATA.c_str());
1094             CfBlob *blob = CertGetBlobFromUint8ArrJSParams(env, obj);
1095             if (blob != nullptr) {
1096                 newSANArr->data[i].name = *blob;
1097                 CfFree(blob);
1098                 continue;
1099             }
1100         }
1101         LOGE("Failed to allocate data memory!");
1102         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input arr is invalid"));
1103         SubAltNameArrayDataClearAndFree(newSANArr);
1104         CfFree(newSANArr);
1105         return nullptr;
1106     }
1107     return newSANArr;
1108 }
1109 
CertGetArrFromArrUarrJSParams(napi_env env,napi_value arg)1110 CfArray *CertGetArrFromArrUarrJSParams(napi_env env, napi_value arg)
1111 {
1112     bool flag = false;
1113     napi_status status = napi_is_array(env, arg, &flag);
1114     if (status != napi_ok || !flag) {
1115         LOGE("Not array!");
1116         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "not array!"));
1117         return nullptr;
1118     }
1119     uint32_t length = 0;
1120     status = napi_get_array_length(env, arg, &length);
1121     if (status != napi_ok || length == 0 || length > MAX_NAPI_ARRAY_OF_U8ARR) {
1122         LOGE("Length is invalid!");
1123         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "length is invalid!"));
1124         return nullptr;
1125     }
1126     CfArray *newBlobArr = static_cast<CfArray *>(CfMalloc(sizeof(CfArray), 0));
1127     if (newBlobArr == nullptr) {
1128         LOGE("Failed to allocate newBlobArr memory!");
1129         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
1130         return nullptr;
1131     }
1132     newBlobArr->count = length;
1133     newBlobArr->format = CF_FORMAT_DER;
1134     newBlobArr->data = static_cast<CfBlob *>(CfMalloc(length * sizeof(CfBlob), 0));
1135     if (newBlobArr->data == nullptr) {
1136         LOGE("Failed to allocate data memory!");
1137         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc failed"));
1138         CfFree(newBlobArr);
1139         return nullptr;
1140     }
1141     for (uint32_t i = 0; i < length; i++) {
1142         napi_value element;
1143         if (napi_get_element(env, arg, i, &element) == napi_ok) {
1144             CfBlob *blob = CertGetBlobFromStringJSParams(env, element);
1145             if (blob != nullptr) {
1146                 newBlobArr->data[i] = *blob;
1147                 CfFree(blob);
1148                 continue;
1149             }
1150         }
1151         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "input arr is invalid"));
1152         FreeCfBlobArray(newBlobArr->data, newBlobArr->count);
1153         CfFree(newBlobArr);
1154         LOGE("Failed to allocate data memory!");
1155         return nullptr;
1156     }
1157     return newBlobArr;
1158 }
1159 
CertGetBlobFromBigIntJSParams(napi_env env,napi_value arg,CfBlob & outBlob)1160 bool CertGetBlobFromBigIntJSParams(napi_env env, napi_value arg, CfBlob &outBlob)
1161 {
1162     napi_valuetype valueType;
1163     napi_typeof(env, arg, &valueType);
1164     if (valueType != napi_bigint) {
1165         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type error"));
1166         LOGE("Wrong argument type. expect int type. [Type]: %d", valueType);
1167         return false;
1168     }
1169 
1170     int signBit;
1171     size_t wordCount;
1172 
1173     napi_get_value_bigint_words(env, arg, nullptr, &wordCount, nullptr);
1174     if ((wordCount == 0) || (wordCount > (MAX_SN_BYTE_CNT / sizeof(uint64_t)))) {
1175         LOGE("Get big int failed.");
1176         return false;
1177     }
1178     int length = wordCount * sizeof(uint64_t);
1179     uint8_t *retArr = reinterpret_cast<uint8_t *>(CfMalloc(length, 0));
1180     if (retArr == nullptr) {
1181         LOGE("Malloc blob data failed!");
1182         return false;
1183     }
1184     if (napi_get_value_bigint_words(env, arg, &signBit, &wordCount, reinterpret_cast<uint64_t *>(retArr)) != napi_ok) {
1185         CfFree(retArr);
1186         LOGE("Failed to get valid rawData.");
1187         return false;
1188     }
1189     if (signBit != 0) {
1190         CfFree(retArr);
1191         LOGE("Failed to get gegative rawData.");
1192         return false;
1193     }
1194     outBlob.data = retArr;
1195     outBlob.size = (uint32_t)length;
1196     return true;
1197 }
1198 
CertGetSerialNumberFromBigIntJSParams(napi_env env,napi_value arg,CfBlob & outBlob)1199 bool CertGetSerialNumberFromBigIntJSParams(napi_env env, napi_value arg, CfBlob &outBlob)
1200 {
1201     napi_valuetype valueType;
1202     napi_typeof(env, arg, &valueType);
1203     if (valueType != napi_bigint) {
1204         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type error"));
1205         LOGE("wrong argument type. expect int type. [Type]: %d", valueType);
1206         return false;
1207     }
1208 
1209     size_t wordCount = 0;
1210     if (napi_get_value_bigint_words(env, arg, nullptr, &wordCount, nullptr) != napi_ok) {
1211         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum failed"));
1212         LOGE("can not get word count");
1213         return false;
1214     }
1215     if (wordCount == 0 || wordCount > (MAX_SN_BYTE_CNT / sizeof(int64_t))) {
1216         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum len failed"));
1217         LOGE("can not get wordCount, wordCount = %u", wordCount);
1218         return false;
1219     }
1220 
1221     uint8_t serialBuf[MAX_SN_BYTE_CNT] = { 0 };
1222     uint32_t serialLen = sizeof(int64_t) * wordCount;
1223 
1224     int sign = 0;
1225     if (napi_get_value_bigint_words(env, arg, &sign, &wordCount, reinterpret_cast<uint64_t *>(serialBuf)) != napi_ok ||
1226         sign > 0) {
1227         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "get serialNum len failed"));
1228         LOGE("can not get bigint value, sign = %d", sign); // sign 0 : positive, sign 1 : negative
1229         return false;
1230     }
1231     outBlob.data = static_cast<uint8_t *>(CfMalloc(serialLen, 0));
1232     if (outBlob.data == nullptr) {
1233         napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "malloc serialNum failed"));
1234         LOGE("malloc blob data failed!");
1235         return false;
1236     }
1237     outBlob.size = serialLen;
1238     // reverse data: because BN_bin2bn() converts the positive integer in big-endian form of length len into a BIGNUM
1239     for (uint32_t i = 0; i < serialLen; ++i) {
1240         outBlob.data[i] = serialBuf[outBlob.size - 1 - i];
1241     }
1242 
1243     return true;
1244 }
1245 
CertGetStringFromJSParams(napi_env env,napi_value arg,string & returnStr)1246 bool CertGetStringFromJSParams(napi_env env, napi_value arg, string &returnStr)
1247 {
1248     napi_valuetype valueType;
1249     napi_typeof(env, arg, &valueType);
1250     if (valueType != napi_string) {
1251         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not string"));
1252         LOGE("wrong argument type. expect string type. [Type]: %d", valueType);
1253         return false;
1254     }
1255 
1256     size_t length = 0;
1257     if (napi_get_value_string_utf8(env, arg, nullptr, 0, &length) != napi_ok) {
1258         LOGE("can not get string length");
1259         return false;
1260     }
1261     returnStr.reserve(length + 1);
1262     returnStr.resize(length);
1263     if (napi_get_value_string_utf8(env, arg, returnStr.data(), (length + 1), &length) != napi_ok) {
1264         LOGE("can not get string value");
1265         return false;
1266     }
1267     return true;
1268 }
1269 
CertGetInt32FromJSParams(napi_env env,napi_value arg,int32_t & returnInt)1270 bool CertGetInt32FromJSParams(napi_env env, napi_value arg, int32_t &returnInt)
1271 {
1272     napi_valuetype valueType;
1273     napi_typeof(env, arg, &valueType);
1274     if (valueType != napi_number) {
1275         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not number"));
1276         LOGE("wrong argument type. expect int type. [Type]: %d", valueType);
1277         return false;
1278     }
1279 
1280     if (napi_get_value_int32(env, arg, &returnInt) != napi_ok) {
1281         LOGE("can not get int value");
1282         return false;
1283     }
1284     return true;
1285 }
1286 
CertGetCallbackFromJSParams(napi_env env,napi_value arg,napi_ref * returnCb)1287 bool CertGetCallbackFromJSParams(napi_env env, napi_value arg, napi_ref *returnCb)
1288 {
1289     napi_valuetype valueType = napi_undefined;
1290     napi_typeof(env, arg, &valueType);
1291     if (valueType != napi_function) {
1292         napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "param type is not function"));
1293         LOGE("wrong argument type. expect callback type. [Type]: %d", valueType);
1294         return false;
1295     }
1296 
1297     napi_create_reference(env, arg, 1, returnCb);
1298     return true;
1299 }
1300 
GetCertErrValueByErrCode(int32_t errCode)1301 static uint32_t GetCertErrValueByErrCode(int32_t errCode)
1302 {
1303     uint32_t count = sizeof(CODE_MAP) / sizeof(CODE_MAP[0]);
1304     for (uint32_t i = 0; i < count; i++) {
1305         if (errCode == CODE_MAP[i].retValue) {
1306             return CODE_MAP[i].retCode;
1307         }
1308     }
1309     return JS_ERR_CERT_RUNTIME_ERROR;
1310 }
1311 
CertGenerateBusinessError(napi_env env,int32_t errCode,const char * errMsg)1312 napi_value CertGenerateBusinessError(napi_env env, int32_t errCode, const char *errMsg)
1313 {
1314     napi_value businessError = nullptr;
1315 
1316     napi_value code = nullptr;
1317     napi_create_uint32(env, GetCertErrValueByErrCode(errCode), &code);
1318 
1319     napi_value msg = nullptr;
1320     napi_create_string_utf8(env, errMsg, NAPI_AUTO_LENGTH, &msg);
1321 
1322     napi_create_error(env, nullptr, msg, &businessError);
1323     napi_set_named_property(env, businessError, CERT_TAG_ERR_CODE.c_str(), code);
1324 
1325     return businessError;
1326 }
1327 
CertCheckArgsCount(napi_env env,size_t argc,size_t expectedCount,bool isSync)1328 bool CertCheckArgsCount(napi_env env, size_t argc, size_t expectedCount, bool isSync)
1329 {
1330     if (isSync) {
1331         if (argc != expectedCount) {
1332             napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params count"));
1333             LOGE("invalid params count!");
1334             return false;
1335         }
1336     } else {
1337         if ((argc != expectedCount) && (argc != (expectedCount - ARGS_SIZE_ONE))) {
1338             napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "invalid params count"));
1339             LOGE("invalid params count!");
1340             return false;
1341         }
1342     }
1343     return true;
1344 }
1345 
GetAsyncType(napi_env env,size_t argc,size_t maxCount,napi_value arg)1346 AsyncType GetAsyncType(napi_env env, size_t argc, size_t maxCount, napi_value arg)
1347 {
1348     if (argc == (maxCount - 1)) { /* inner caller func: maxCount is bigger than 1 */
1349         return ASYNC_TYPE_PROMISE;
1350     }
1351 
1352     napi_valuetype valueType = napi_undefined;
1353     napi_typeof(env, arg, &valueType);
1354     /* If the input is undefined or null, the value is processed as promise type. */
1355     if ((valueType == napi_undefined) || (valueType == napi_null)) {
1356         CF_LOG_I("input value is undefined or null");
1357         return ASYNC_TYPE_PROMISE;
1358     }
1359 
1360     return ASYNC_TYPE_CALLBACK;
1361 }
1362 
CertGetResourceName(napi_env env,const char * name)1363 napi_value CertGetResourceName(napi_env env, const char *name)
1364 {
1365     napi_value resourceName = nullptr;
1366     napi_create_string_utf8(env, name, NAPI_AUTO_LENGTH, &resourceName);
1367     return resourceName;
1368 }
1369 
GetBoolFromNapiValue(napi_env env,napi_value arg,bool & out,const char * name)1370 bool GetBoolFromNapiValue(napi_env env, napi_value arg, bool &out, const char *name)
1371 {
1372     napi_value obj = GetProp(env, arg, name);
1373     if (obj == nullptr) {
1374         return true;
1375     }
1376 
1377     napi_valuetype valueType;
1378     napi_typeof(env, obj, &valueType);
1379     if (valueType != napi_boolean) {
1380         LOGE("Get %s obj is not bool!", name);
1381         return false;
1382     }
1383 
1384     napi_status status = napi_get_value_bool(env, obj, &out);
1385     if (status != napi_ok) {
1386         LOGE("Failed to get value bool!");
1387         return false;
1388     }
1389     return true;
1390 }
1391 
GetIsPemFromStringNapiValue(napi_env env,napi_value arg,bool & out,const char * name)1392 bool GetIsPemFromStringNapiValue(napi_env env, napi_value arg, bool &out, const char *name)
1393 {
1394     napi_value obj = GetProp(env, arg, name);
1395     if (obj == nullptr) {
1396         return true;
1397     }
1398     CfEncodinigBaseFormat encodingBaseFormat = PEM;
1399     napi_status status = napi_get_value_int32(env, obj, (int32_t *)&encodingBaseFormat);
1400     if (status != napi_ok) {
1401         LOGE("get privateKeyFormat failed!");
1402         return false;
1403     }
1404     if (encodingBaseFormat == DER) {
1405         out = false;
1406     }
1407     return true;
1408 }
1409 
ConvertBlobToNapiValue(napi_env env,const CfBlob * blob)1410 napi_value ConvertBlobToNapiValue(napi_env env, const CfBlob *blob)
1411 {
1412     if (blob == nullptr || blob->data == nullptr || blob->size == 0) {
1413         LOGE("Invalid blob!");
1414         return nullptr;
1415     }
1416     uint8_t *buffer = static_cast<uint8_t *>(CfMalloc(blob->size, 0));
1417     if (buffer == nullptr) {
1418         LOGE("malloc uint8 array buffer failed!");
1419         return nullptr;
1420     }
1421 
1422     (void)memcpy_s(buffer, blob->size, blob->data, blob->size);
1423     napi_value outBuffer = nullptr;
1424     napi_status status = napi_create_external_arraybuffer(
1425         env, buffer, blob->size, [](napi_env env, void *data, void *hint) { CfFree(data); }, nullptr, &outBuffer);
1426     if (status != napi_ok) {
1427         LOGE("create uint8 array buffer failed!");
1428         CfFree(buffer);
1429         return nullptr;
1430     }
1431     buffer = nullptr;
1432 
1433     napi_value outData = nullptr;
1434     napi_create_typedarray(env, napi_uint8_array, blob->size, outBuffer, 0, &outData);
1435     napi_value dataBlob = nullptr;
1436     napi_create_object(env, &dataBlob);
1437     napi_set_named_property(env, dataBlob, CERT_TAG_DATA.c_str(), outData);
1438 
1439     return dataBlob;
1440 }
1441 
ConvertBlobToWords(const CfBlob & blob,uint64_t * & words,uint32_t & wordsCount)1442 static CfResult ConvertBlobToWords(const CfBlob &blob, uint64_t *&words, uint32_t &wordsCount)
1443 {
1444     uint32_t blockSize = sizeof(uint64_t);
1445     uint32_t convertDataSize = ((blob.size + (blockSize - 1)) >> QUAD_WORD_ALIGN_UP) << QUAD_WORD_ALIGN_UP;
1446     uint8_t *convertData = static_cast<uint8_t *>(CfMalloc(convertDataSize, 0));
1447     if (convertData == nullptr) {
1448         LOGE("malloc convert data failed");
1449         return CF_ERR_MALLOC;
1450     }
1451 
1452     /* convertData has been initialized 0, reverse blob data */
1453     for (uint32_t i = 0; i < blob.size; ++i) {
1454         convertData[i] = blob.data[blob.size - 1 - i];
1455     }
1456 
1457     words = reinterpret_cast<uint64_t *>(convertData);
1458     wordsCount = convertDataSize / blockSize;
1459     return CF_SUCCESS;
1460 }
1461 
ConvertBlobToBigIntWords(napi_env env,const CfBlob & blob)1462 napi_value ConvertBlobToBigIntWords(napi_env env, const CfBlob &blob)
1463 {
1464     if (blob.data == nullptr || blob.size == 0 || blob.size > MAX_SN_BYTE_CNT) {
1465         LOGE("Invalid blob!");
1466         return nullptr;
1467     }
1468 
1469     uint64_t *words = nullptr;
1470     uint32_t wordsCount = 0;
1471     CfResult ret = ConvertBlobToWords(blob, words, wordsCount);
1472     if (ret != CF_SUCCESS) {
1473         napi_throw(env, CertGenerateBusinessError(env, ret, "convert data to words failed"));
1474         LOGE("convert data to words failed");
1475         return nullptr;
1476     }
1477 
1478     napi_value result = nullptr;
1479     napi_create_bigint_words(env, 0, wordsCount, words, &result);
1480     CfFree(words);
1481     return result;
1482 }
1483 
ConvertBlobToInt64(napi_env env,const CfBlob & blob)1484 napi_value ConvertBlobToInt64(napi_env env, const CfBlob &blob)
1485 {
1486     if (blob.data == nullptr || blob.size == 0 || blob.size > sizeof(int64_t)) {
1487         LOGE("Invalid blob!");
1488         return nullptr;
1489     }
1490 
1491     uint64_t serialNumber = 0;
1492     for (uint32_t i = 0; i < blob.size; ++i) {
1493         serialNumber = ((serialNumber << (BYTE_TO_BIT_CNT * i)) | static_cast<uint64_t>(blob.data[i]));
1494     }
1495 
1496     napi_value result = nullptr;
1497     napi_create_int64(env, static_cast<long>(serialNumber), &result);
1498     return result;
1499 }
1500 
ConvertArrayStringToNapiValue(napi_env env,CfArray * array)1501 napi_value ConvertArrayStringToNapiValue(napi_env env, CfArray *array)
1502 {
1503     if (array == nullptr) {
1504         LOGE("array is null!");
1505         return nullptr;
1506     }
1507     if (array->count == 0) {
1508         LOGE("array count is 0!");
1509         return nullptr;
1510     }
1511     napi_value returnArray = nullptr;
1512     napi_create_array(env, &returnArray);
1513     if (returnArray == nullptr) {
1514         LOGE("create return array failed!");
1515         return nullptr;
1516     }
1517     for (uint32_t i = 0; i < array->count; i++) {
1518         CfBlob *blob = reinterpret_cast<CfBlob *>(array->data + i);
1519         napi_value element = nullptr;
1520         napi_create_string_utf8(env, reinterpret_cast<char *>(blob->data), blob->size, &element);
1521         napi_set_element(env, returnArray, i, element);
1522     }
1523     return returnArray;
1524 }
1525 
ConvertBlobToEncodingBlob(const CfBlob & blob,CfEncodingBlob * encodingBlob)1526 bool ConvertBlobToEncodingBlob(const CfBlob &blob, CfEncodingBlob *encodingBlob)
1527 {
1528     if (blob.data == nullptr || blob.size == 0) {
1529         LOGE("Invalid blob!");
1530         return false;
1531     }
1532 
1533     encodingBlob->data = static_cast<uint8_t *>(CfMalloc(blob.size, 0));
1534     if (encodingBlob->data == nullptr) {
1535         LOGE("malloc encoding blob data failed!");
1536         return false;
1537     }
1538     if (memcpy_s(encodingBlob->data, blob.size, blob.data, blob.size) != EOK) {
1539         LOGE("memcpy_s encoding blob data failed!");
1540         CfFree(encodingBlob->data);
1541         encodingBlob->data = nullptr;
1542         return false;
1543     }
1544     encodingBlob->len = blob.size;
1545     encodingBlob->encodingFormat = CF_FORMAT_DER;
1546     return true;
1547 }
1548 }  // namespace CertFramework
1549 }  // namespace OHOS
1550