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