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