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