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