1 /*
2 * Copyright (c) 2022 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 "cm_napi_sign_verify.h"
17
18 #include "securec.h"
19
20 #include "cert_manager_api.h"
21 #include "cm_log.h"
22 #include "cm_mem.h"
23 #include "cm_type.h"
24 #include "cm_napi_common.h"
25
26 namespace CMNapi {
27 namespace {
28 constexpr int CM_NAPI_INIT_ARGS_CNT = 3;
29 constexpr int CM_NAPI_UPDATE_ARGS_CNT = 3;
30 constexpr int CM_NAPI_FINISH_ARGS_CNT = 3;
31 constexpr int CM_NAPI_ABORT_ARGS_CNT = 2;
32
33 constexpr int CM_NAPI_CALLBACK_ARG_CNT = 1;
34 constexpr int CM_NAPI_SIGNATURE_ARG_CNT = 1;
35
36 constexpr uint32_t OUT_SIGNATURE_SIZE = 1000;
37 constexpr uint32_t OUT_HANLDE_SIZE = 8;
38 } // namespace
39
40 struct SignVerifyAsyncContextT {
41 napi_async_work asyncWork = nullptr;
42 napi_deferred deferred = nullptr;
43 napi_ref callback = nullptr;
44
45 int32_t errCode = 0;
46 bool isSign = false;
47 struct CmBlob *authUri = nullptr;
48 struct CmBlob *handle = nullptr;
49 struct CmBlob *inData = nullptr;
50 struct CmBlob *signature = nullptr;
51 struct CmSignatureSpec *spec = nullptr;
52 };
53 using SignVerifyAsyncContext = SignVerifyAsyncContextT *;
54
InitSignVerifyAsyncContext(void)55 static SignVerifyAsyncContext InitSignVerifyAsyncContext(void)
56 {
57 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(CmMalloc(sizeof(SignVerifyAsyncContextT)));
58 if (context != nullptr) {
59 (void)memset_s(context, sizeof(SignVerifyAsyncContextT), 0, sizeof(SignVerifyAsyncContextT));
60 }
61 return context;
62 }
63
FreeSignVerifyAsyncContext(napi_env env,SignVerifyAsyncContext & context)64 static void FreeSignVerifyAsyncContext(napi_env env, SignVerifyAsyncContext &context)
65 {
66 if (context == nullptr) {
67 return;
68 }
69
70 DeleteNapiContext(env, context->asyncWork, context->callback);
71 FreeCmBlob(context->authUri);
72 FreeCmBlob(context->handle);
73 FreeCmBlob(context->inData);
74 FreeCmBlob(context->signature);
75 CM_FREE_PTR(context->spec);
76 CM_FREE_PTR(context);
77 }
78
79 struct CmJSKeyPaddingCmKeyPaddingMap {
80 CmJSKeyPadding key;
81 CmKeyPadding retPadding;
82 };
83
84 const struct CmJSKeyPaddingCmKeyPaddingMap PADDING_MAP[] = {
85 { CM_JS_PADDING_NONE, CM_PADDING_NONE },
86 { CM_JS_PADDING_PSS, CM_PADDING_PSS },
87 { CM_JS_PADDING_PKCS1_V1_5, CM_PADDING_PKCS1_V1_5 },
88 };
89
90 struct CmJSKeyDigestCmKeyDigestMap {
91 CmJSKeyDigest key;
92 CmKeyDigest retDigest;
93 };
94
95 const struct CmJSKeyDigestCmKeyDigestMap DIGEST_MAP[] = {
96 { CM_JS_DIGEST_NONE, CM_DIGEST_NONE },
97 { CM_JS_DIGEST_MD5, CM_DIGEST_MD5 },
98 { CM_JS_DIGEST_SHA1, CM_DIGEST_SHA1 },
99 { CM_JS_DIGEST_SHA224, CM_DIGEST_SHA224 },
100 { CM_JS_DIGEST_SHA256, CM_DIGEST_SHA256 },
101 { CM_JS_DIGEST_SHA384, CM_DIGEST_SHA384 },
102 { CM_JS_DIGEST_SHA512, CM_DIGEST_SHA512 },
103 };
104
GetPadding(napi_env env,napi_value object,uint32_t * paddingRet)105 static napi_value GetPadding(napi_env env, napi_value object, uint32_t *paddingRet)
106 {
107 napi_value padding = nullptr;
108 napi_status status = napi_get_named_property(env, object, "padding", &padding);
109 if (status != napi_ok || padding == nullptr) {
110 CM_LOG_E("get padding failed");
111 return nullptr;
112 }
113
114 napi_valuetype type = napi_undefined;
115 NAPI_CALL(env, napi_typeof(env, padding, &type));
116 if (type == napi_undefined) {
117 CM_LOG_D("padding is undefined, set padding value is default");
118 *paddingRet = CM_PADDING_PSS;
119 return GetInt32(env, 0);
120 }
121
122 if (type != napi_number) {
123 ThrowParamsError(env, PARAM_ERROR, "arguments invalid, type of param padding is not number");
124 CM_LOG_E("arguments invalid, type of param padding is not number");
125 return nullptr;
126 }
127
128 uint32_t paddingValue = 0;
129 status = napi_get_value_uint32(env, padding, &paddingValue);
130 if (status != napi_ok) {
131 CM_LOG_E("get padding value failed");
132 ThrowParamsError(env, PARAM_ERROR, "arguments invalid, get padding value failed");
133 return nullptr;
134 }
135
136 bool findFlag = false;
137 for (uint32_t i = 0; i < (sizeof(PADDING_MAP) / sizeof(PADDING_MAP[0])); i++) {
138 if (paddingValue == PADDING_MAP[i].key) {
139 *paddingRet = PADDING_MAP[i].retPadding;
140 findFlag = true;
141 break;
142 }
143 }
144 if (!findFlag) {
145 ThrowParamsError(env, PARAM_ERROR, "padding do not exist in PADDING_MAP");
146 CM_LOG_E("padding do not exist in PADDING_MAP.");
147 return nullptr;
148 }
149
150 return GetInt32(env, 0);
151 }
152
GetDigest(napi_env env,napi_value object,uint32_t * digestRet)153 static napi_value GetDigest(napi_env env, napi_value object, uint32_t *digestRet)
154 {
155 napi_value digest = nullptr;
156 napi_status status = napi_get_named_property(env, object, "digest", &digest);
157 if (status != napi_ok || digest == nullptr) {
158 CM_LOG_E("get digest failed");
159 return nullptr;
160 }
161 napi_valuetype type = napi_undefined;
162 NAPI_CALL(env, napi_typeof(env, digest, &type));
163 if (type == napi_undefined) {
164 CM_LOG_D("digest is undefined, set digest value is default");
165 *digestRet = CM_DIGEST_SHA256;
166 return GetInt32(env, 0);
167 }
168
169 if (type != napi_number) {
170 ThrowParamsError(env, PARAM_ERROR, "arguments invalid, type of param digest is not number");
171 CM_LOG_E("arguments invalid, type of param digest is not number.");
172 return nullptr;
173 }
174
175 uint32_t digestValue = 0;
176 status = napi_get_value_uint32(env, digest, &digestValue);
177 if (status != napi_ok) {
178 ThrowParamsError(env, PARAM_ERROR, "arguments invalid, get digest value failed");
179 CM_LOG_E("arguments invalid,get digest value failed.");
180 return nullptr;
181 }
182 bool findFlag = false;
183 for (uint32_t i = 0; i < (sizeof(DIGEST_MAP) / sizeof(DIGEST_MAP[0])); i++) {
184 if (digestValue == DIGEST_MAP[i].key) {
185 *digestRet = DIGEST_MAP[i].retDigest;
186 findFlag = true;
187 break;
188 }
189 }
190 if (!findFlag) {
191 ThrowParamsError(env, PARAM_ERROR, "digest do not exist in DIGEST_MAP");
192 CM_LOG_E("digest do not exist in DIGEST_MAP.");
193 return nullptr;
194 }
195
196 return GetInt32(env, 0);
197 }
198
ParseSpec(napi_env env,napi_value object,CmSignatureSpec * & spec)199 static napi_value ParseSpec(napi_env env, napi_value object, CmSignatureSpec *&spec)
200 {
201 napi_valuetype type = napi_undefined;
202 NAPI_CALL(env, napi_typeof(env, object, &type));
203 if (type != napi_object) {
204 CM_LOG_E("type of param spec is not object");
205 return nullptr;
206 }
207
208 napi_value purpose = nullptr;
209 napi_status status = napi_get_named_property(env, object, "purpose", &purpose);
210 if (status != napi_ok || purpose == nullptr) {
211 CM_LOG_E("get purpose failed");
212 return nullptr;
213 }
214
215 NAPI_CALL(env, napi_typeof(env, purpose, &type));
216 if (type != napi_number) {
217 CM_LOG_E("type of param purpose is not number");
218 return nullptr;
219 }
220
221 uint32_t purposeValue = 0;
222 status = napi_get_value_uint32(env, purpose, &purposeValue);
223 if (status != napi_ok) {
224 CM_LOG_E("get purpose value failed");
225 return nullptr;
226 }
227
228 spec = static_cast<CmSignatureSpec *>(CmMalloc(sizeof(CmSignatureSpec)));
229 if (spec == nullptr) {
230 CM_LOG_E("malloc spec struct failed");
231 return nullptr;
232 }
233 spec->purpose = purposeValue;
234
235 /* padding */
236 napi_value result = GetPadding(env, object, &spec->padding);
237 if (result == nullptr) {
238 CM_LOG_E("get padding failed when using GetPadding function");
239 CM_FREE_PTR(spec);
240 return nullptr;
241 }
242
243 /* digest */
244 result = GetDigest(env, object, &spec->digest);
245 if (result == nullptr) {
246 CM_LOG_E("get digest failed when using GetDigest function");
247 CM_FREE_PTR(spec);
248 return nullptr;
249 }
250
251 return GetInt32(env, 0);
252 }
253
GetBlob(napi_env env,napi_value object,CmBlob * & blob)254 static napi_value GetBlob(napi_env env, napi_value object, CmBlob *&blob)
255 {
256 blob = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
257 if (blob == nullptr) {
258 CM_LOG_E("malloc blob failed");
259 return nullptr;
260 }
261 (void)memset_s(blob, sizeof(CmBlob), 0, sizeof(CmBlob));
262
263 napi_value result = GetUint8Array(env, object, *blob);
264 if (result == nullptr) {
265 CM_LOG_E("parse blob data failed");
266 return nullptr;
267 }
268
269 return GetInt32(env, 0);
270 }
271
ParseCMInitParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)272 static napi_value ParseCMInitParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
273 {
274 size_t argc = CM_NAPI_INIT_ARGS_CNT;
275 napi_value argv[CM_NAPI_INIT_ARGS_CNT] = { nullptr };
276 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
277
278 if ((argc != CM_NAPI_INIT_ARGS_CNT) && (argc != (CM_NAPI_INIT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
279 ThrowParamsError(env, PARAM_ERROR, "init arguments count invalid");
280 CM_LOG_E("init arguments count is not expected");
281 return nullptr;
282 }
283
284 size_t index = 0;
285 napi_value result = ParseString(env, argv[index], context->authUri);
286 if (result == nullptr) {
287 ThrowParamsError(env, PARAM_ERROR, "get authUri type error");
288 CM_LOG_E("get uri failed when using init function");
289 return nullptr;
290 }
291
292 index++;
293 result = ParseSpec(env, argv[index], context->spec);
294 if (result == nullptr) {
295 ThrowParamsError(env, PARAM_ERROR, "get spec type error");
296 CM_LOG_E("get sepc failed when using init function");
297 return nullptr;
298 }
299
300 index++;
301 if (index < argc) {
302 int32_t ret = GetCallback(env, argv[index], context->callback);
303 if (ret != CM_SUCCESS) {
304 ThrowParamsError(env, PARAM_ERROR, "Get callback type failed.");
305 CM_LOG_E("get callback function failed when using init function");
306 return nullptr;
307 }
308 }
309
310 return GetInt32(env, 0);
311 }
312
ParseCMUpdateParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)313 static napi_value ParseCMUpdateParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
314 {
315 size_t argc = CM_NAPI_UPDATE_ARGS_CNT;
316 napi_value argv[CM_NAPI_UPDATE_ARGS_CNT] = { nullptr };
317 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
318
319 if ((argc != CM_NAPI_UPDATE_ARGS_CNT) && (argc != (CM_NAPI_UPDATE_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
320 ThrowParamsError(env, PARAM_ERROR, "update arguments count invalid");
321 CM_LOG_E("update arguments count is not expected");
322 return nullptr;
323 }
324
325 size_t index = 0;
326 napi_value result = GetBlob(env, argv[index], context->handle);
327 if (result == nullptr) {
328 ThrowParamsError(env, PARAM_ERROR, "get handle type error");
329 CM_LOG_E("get handle failed when using update function");
330 return nullptr;
331 }
332
333 index++;
334 result = GetBlob(env, argv[index], context->inData);
335 if (result == nullptr) {
336 ThrowParamsError(env, PARAM_ERROR, "get inData type error");
337 CM_LOG_E("get inData failed when using update function");
338 return nullptr;
339 }
340
341 index++;
342 if (index < argc) {
343 int32_t ret = GetCallback(env, argv[index], context->callback);
344 if (ret != CM_SUCCESS) {
345 ThrowParamsError(env, PARAM_ERROR, "get callback type error");
346 CM_LOG_E("get callback function failed when using update function");
347 return nullptr;
348 }
349 }
350
351 return GetInt32(env, 0);
352 }
353
MallocFinishOutData(napi_env env,SignVerifyAsyncContext context)354 static napi_value MallocFinishOutData(napi_env env, SignVerifyAsyncContext context)
355 {
356 context->signature = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
357 if (context->signature == nullptr) { /* signature will free after all process */
358 CM_LOG_E("malloc outData failed when process sign finish");
359 ThrowParamsError(env, PARAM_ERROR, "malloc failed");
360 return nullptr;
361 }
362 (void)memset_s(context->signature, sizeof(CmBlob), 0, sizeof(CmBlob));
363
364 uint8_t *data = static_cast<uint8_t *>(CmMalloc(OUT_SIGNATURE_SIZE));
365 if (data == nullptr) {
366 CM_LOG_E("malloc outData.data failed when process sign finish");
367 ThrowParamsError(env, PARAM_ERROR, "malloc failed");
368 return nullptr;
369 }
370 (void)memset_s(data, OUT_SIGNATURE_SIZE, 0, OUT_SIGNATURE_SIZE);
371
372 context->signature->data = data;
373 context->signature->size = OUT_SIGNATURE_SIZE;
374 return GetInt32(env, 0);
375 }
376
ProcessFinishOneParam(napi_env env,SignVerifyAsyncContext context)377 static napi_value ProcessFinishOneParam(napi_env env, SignVerifyAsyncContext context)
378 {
379 /* promise: sign */
380 context->isSign = true;
381 return MallocFinishOutData(env, context);
382 }
383
CheckIsCallback(napi_env env,napi_value object,bool & isFunc)384 static int32_t CheckIsCallback(napi_env env, napi_value object, bool &isFunc)
385 {
386 isFunc = false;
387 napi_valuetype valueType = napi_undefined;
388 napi_status status = napi_typeof(env, object, &valueType);
389 if (status != napi_ok) {
390 CM_LOG_E("could not get object type");
391 return CMR_ERROR_INVALID_ARGUMENT;
392 }
393
394 if (valueType == napi_function) {
395 isFunc = true;
396 }
397 return CM_SUCCESS;
398 }
399
ProcessFinishTwoParam(napi_env env,napi_value * argv,SignVerifyAsyncContext context,size_t curIndex,size_t maxIndex)400 static napi_value ProcessFinishTwoParam(napi_env env, napi_value *argv, SignVerifyAsyncContext context,
401 size_t curIndex, size_t maxIndex)
402 {
403 curIndex++;
404 if (curIndex >= maxIndex) {
405 return nullptr; /* not possible */
406 }
407
408 /*
409 * check wether arg 2 is callback: if true, get callback function and return: callback sign.
410 * else is promise verify, then get arg 2 as signature
411 */
412 bool isFunc = false;
413 int32_t ret = CheckIsCallback(env, argv[curIndex], isFunc);
414 if (ret != CM_SUCCESS) {
415 return nullptr;
416 }
417
418 napi_value result = nullptr;
419 if (isFunc) {
420 /* callback: sign */
421 context->isSign = true;
422 result = MallocFinishOutData(env, context);
423 if (result == nullptr) {
424 return nullptr;
425 }
426
427 ret = GetCallback(env, argv[curIndex], context->callback);
428 if (ret != CM_SUCCESS) {
429 ThrowParamsError(env, PARAM_ERROR, "Get callback type failed.");
430 CM_LOG_E("arg2 is callback: get sign callback function failed when using finish function");
431 return nullptr;
432 }
433
434 return GetInt32(env, 0);
435 }
436
437 /* promise verify */
438 context->isSign = false;
439 result = GetBlob(env, argv[curIndex], context->signature);
440 if (result == nullptr) {
441 ThrowParamsError(env, PARAM_ERROR, "get signature type error");
442 CM_LOG_E("get signature failed when process promise verify");
443 return nullptr;
444 }
445
446 return GetInt32(env, 0);
447 }
448
ProcessFinishThreeParam(napi_env env,napi_value * argv,SignVerifyAsyncContext context,size_t curIndex,size_t maxIndex)449 static napi_value ProcessFinishThreeParam(napi_env env, napi_value *argv, SignVerifyAsyncContext context,
450 size_t curIndex, size_t maxIndex)
451 {
452 /* callback: verify */
453 context->isSign = false;
454
455 curIndex++;
456 if (curIndex >= maxIndex) {
457 return nullptr; /* not possible */
458 }
459
460 napi_value result = GetBlob(env, argv[curIndex], context->signature);
461 if (result == nullptr) {
462 ThrowParamsError(env, PARAM_ERROR, "get signature type error");
463 CM_LOG_E("get signature failed when process callback verify");
464 return nullptr;
465 }
466
467 curIndex++;
468 if (curIndex >= maxIndex) {
469 return nullptr; /* not possible */
470 }
471
472 int32_t ret = GetCallback(env, argv[curIndex], context->callback);
473 if (ret != CM_SUCCESS) {
474 ThrowParamsError(env, PARAM_ERROR, "Get callback type failed.");
475 CM_LOG_E("get verify callback function failed when using finish function");
476 return nullptr;
477 }
478
479 return GetInt32(env, 0);
480 }
481
ParseCMFinishParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)482 static napi_value ParseCMFinishParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
483 {
484 size_t argc = CM_NAPI_FINISH_ARGS_CNT;
485 napi_value argv[CM_NAPI_FINISH_ARGS_CNT] = { nullptr };
486 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
487
488 if ((argc != CM_NAPI_FINISH_ARGS_CNT) && (argc != (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT)) &&
489 (argc != (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT - CM_NAPI_SIGNATURE_ARG_CNT))) {
490 ThrowParamsError(env, PARAM_ERROR, "finish arguments count invalid");
491 CM_LOG_E("finish arguments count is not expected");
492 return nullptr;
493 }
494
495 size_t index = 0;
496 napi_value result = GetBlob(env, argv[index], context->handle);
497 if (result == nullptr) {
498 ThrowParamsError(env, PARAM_ERROR, "get handle type error");
499 CM_LOG_E("get handle failed when using finish function");
500 return nullptr;
501 }
502
503 if (argc == CM_NAPI_FINISH_ARGS_CNT) {
504 return ProcessFinishThreeParam(env, argv, context, index, argc);
505 } else if (argc == (CM_NAPI_FINISH_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT)) {
506 return ProcessFinishTwoParam(env, argv, context, index, argc);
507 } else {
508 /* only this 3 types */
509 return ProcessFinishOneParam(env, context);
510 }
511 }
512
ParseCMAbortParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)513 static napi_value ParseCMAbortParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
514 {
515 size_t argc = CM_NAPI_ABORT_ARGS_CNT;
516 napi_value argv[CM_NAPI_ABORT_ARGS_CNT] = { nullptr };
517 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
518
519 if ((argc != CM_NAPI_ABORT_ARGS_CNT) && (argc != (CM_NAPI_ABORT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
520 ThrowParamsError(env, PARAM_ERROR, "abort arguments count invalid");
521 CM_LOG_E("abort arguments count is not expected");
522 return nullptr;
523 }
524
525 size_t index = 0;
526 napi_value result = GetBlob(env, argv[index], context->handle);
527 if (result == nullptr) {
528 ThrowParamsError(env, PARAM_ERROR, "get handle type error");
529 CM_LOG_E("get handle failed when using abort function");
530 return nullptr;
531 }
532
533 index++;
534 if (index < argc) {
535 int32_t ret = GetCallback(env, argv[index], context->callback);
536 if (ret != CM_SUCCESS) {
537 ThrowParamsError(env, PARAM_ERROR, "get callback type failed.");
538 CM_LOG_E("get callback function failed when using abort function");
539 return nullptr;
540 }
541 }
542
543 return GetInt32(env, 0);
544 }
545
InitExecute(napi_env env,void * data)546 static void InitExecute(napi_env env, void *data)
547 {
548 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
549 context->handle = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
550 if (context->handle == nullptr) {
551 CM_LOG_E("malloc handle out failed");
552 context->errCode = CMR_ERROR_MALLOC_FAIL;
553 return;
554 }
555 (void)memset_s(context->handle, sizeof(CmBlob), 0, sizeof(CmBlob));
556
557 context->handle->data = static_cast<uint8_t *>(CmMalloc(OUT_HANLDE_SIZE));
558 if (context->handle->data == nullptr) {
559 CM_LOG_E("malloc handle.data failed");
560 context->errCode = CMR_ERROR_MALLOC_FAIL;
561 return;
562 }
563 (void)memset_s(context->handle->data, OUT_HANLDE_SIZE, 0, OUT_HANLDE_SIZE);
564 context->handle->size = OUT_HANLDE_SIZE;
565
566 context->errCode = CmInit(context->authUri, context->spec, context->handle);
567 }
568
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)569 static napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
570 {
571 uint8_t *tempBuf = static_cast<uint8_t *>(CmMalloc(size));
572 if (tempBuf == nullptr) {
573 CM_LOG_E("malloc outbuf failed");
574 return nullptr;
575 }
576 (void)memcpy_s(tempBuf, size, data, size);
577
578 napi_value outBuffer = nullptr;
579 napi_status status = napi_create_external_arraybuffer(
580 env, tempBuf, size, [](napi_env env, void *data, void *hint) { CmFree(data); }, nullptr, &outBuffer);
581 if (status == napi_ok) {
582 tempBuf = nullptr; /* free by finalize callback */
583 } else {
584 CM_LOG_E("create external array buffer failed");
585 CM_FREE_PTR(tempBuf);
586 GET_AND_THROW_LAST_ERROR((env));
587 }
588
589 return outBuffer;
590 }
591
ConvertResultHandle(napi_env env,const CmBlob * handle)592 static napi_value ConvertResultHandle(napi_env env, const CmBlob *handle)
593 {
594 napi_value result = nullptr;
595 NAPI_CALL(env, napi_create_object(env, &result));
596
597 napi_value handleNapi = nullptr;
598 napi_value handleBuf = GenerateArrayBuffer(env, handle->data, handle->size);
599 if (handleBuf != nullptr) {
600 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, handle->size, handleBuf, 0, &handleNapi));
601 } else {
602 handleNapi = GetNull(env);
603 }
604 NAPI_CALL(env, napi_set_named_property(env, result, "handle", handleNapi));
605
606 return result;
607 }
608
InitComplete(napi_env env,napi_status status,void * data)609 static void InitComplete(napi_env env, napi_status status, void *data)
610 {
611 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
612 napi_value result[RESULT_NUMBER] = { nullptr };
613 if (context->errCode == CM_SUCCESS) {
614 napi_create_uint32(env, 0, &result[0]);
615 result[1] = ConvertResultHandle(env, context->handle);
616 } else {
617 result[0] = GenerateBusinessError(env, context->errCode, "init failed");
618 napi_get_undefined(env, &result[1]);
619 }
620
621 if (context->deferred != nullptr) {
622 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
623 } else {
624 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
625 }
626 FreeSignVerifyAsyncContext(env, context);
627 }
628
UpdateExecute(napi_env env,void * data)629 static void UpdateExecute(napi_env env, void *data)
630 {
631 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
632 context->errCode = CmUpdate(context->handle, context->inData);
633 }
634
UpdateOrAbortComplete(napi_env env,napi_status status,void * data)635 static void UpdateOrAbortComplete(napi_env env, napi_status status, void *data)
636 {
637 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
638 napi_value result[RESULT_NUMBER] = { nullptr };
639 if (context->errCode == CM_SUCCESS) {
640 napi_create_uint32(env, 0, &result[0]);
641 napi_get_undefined(env, &result[1]);
642 } else {
643 result[0] = GenerateBusinessError(env, context->errCode, "update or abort process failed");
644 napi_get_undefined(env, &result[1]);
645 }
646
647 if (context->deferred != nullptr) {
648 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
649 } else {
650 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
651 }
652 FreeSignVerifyAsyncContext(env, context);
653 }
654
FinishExecute(napi_env env,void * data)655 static void FinishExecute(napi_env env, void *data)
656 {
657 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
658 if (context->isSign) {
659 CmBlob inData = { 0, nullptr };
660 context->errCode = CmFinish(context->handle, &inData, context->signature);
661 return;
662 }
663
664 CmBlob outData = { 0, nullptr };
665 context->errCode = CmFinish(context->handle, context->signature, &outData);
666 }
667
ConvertResultSignature(napi_env env,bool isSign,const CmBlob * sign)668 static napi_value ConvertResultSignature(napi_env env, bool isSign, const CmBlob *sign)
669 {
670 napi_value result = nullptr;
671 NAPI_CALL(env, napi_create_object(env, &result));
672
673 napi_value signResultNapi = nullptr;
674 if (isSign) {
675 napi_value signBuf = GenerateArrayBuffer(env, sign->data, sign->size);
676 if (signBuf != nullptr) {
677 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, sign->size, signBuf, 0, &signResultNapi));
678 } else {
679 signResultNapi = GetNull(env);
680 }
681 } else {
682 signResultNapi = GetNull(env);
683 }
684 NAPI_CALL(env, napi_set_named_property(env, result, "outData", signResultNapi));
685
686 return result;
687 }
688
FinishComplete(napi_env env,napi_status status,void * data)689 static void FinishComplete(napi_env env, napi_status status, void *data)
690 {
691 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
692 napi_value result[RESULT_NUMBER] = { nullptr };
693 if (context->errCode == CM_SUCCESS) {
694 napi_create_uint32(env, 0, &result[0]);
695 result[1] = ConvertResultSignature(env, context->isSign, context->signature);
696 } else {
697 result[0] = GenerateBusinessError(env, context->errCode, "finish failed");
698 napi_get_undefined(env, &result[1]);
699 }
700
701 if (context->deferred != nullptr) {
702 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
703 } else {
704 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
705 }
706 FreeSignVerifyAsyncContext(env, context);
707 }
708
AbortExecute(napi_env env,void * data)709 static void AbortExecute(napi_env env, void *data)
710 {
711 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
712 context->errCode = CmAbort(context->handle);
713 }
714
CMInitAsyncWork(napi_env env,SignVerifyAsyncContext context)715 static napi_value CMInitAsyncWork(napi_env env, SignVerifyAsyncContext context)
716 {
717 napi_value promise = nullptr;
718 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
719
720 napi_value resourceName = nullptr;
721 NAPI_CALL(env, napi_create_string_latin1(env, "cminit", NAPI_AUTO_LENGTH, &resourceName));
722
723 NAPI_CALL(env, napi_create_async_work(
724 env, nullptr, resourceName,
725 InitExecute,
726 InitComplete,
727 static_cast<void *>(context),
728 &context->asyncWork));
729
730 napi_status status = napi_queue_async_work(env, context->asyncWork);
731 if (status != napi_ok) {
732 ThrowParamsError(env, PARAM_ERROR, "queue async work error");
733 CM_LOG_E("queue async work failed when using init function");
734 return nullptr;
735 }
736 return promise;
737 }
738
CMUpdateAsyncWork(napi_env env,SignVerifyAsyncContext context)739 static napi_value CMUpdateAsyncWork(napi_env env, SignVerifyAsyncContext context)
740 {
741 napi_value promise = nullptr;
742 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
743
744 napi_value resourceName = nullptr;
745 NAPI_CALL(env, napi_create_string_latin1(env, "cmupdate", NAPI_AUTO_LENGTH, &resourceName));
746
747 NAPI_CALL(env, napi_create_async_work(
748 env, nullptr, resourceName,
749 UpdateExecute,
750 UpdateOrAbortComplete,
751 static_cast<void *>(context),
752 &context->asyncWork));
753
754 napi_status status = napi_queue_async_work(env, context->asyncWork);
755 if (status != napi_ok) {
756 ThrowParamsError(env, PARAM_ERROR, "queue async work error");
757 CM_LOG_E("queue async work failed when using update function");
758 return nullptr;
759 }
760 return promise;
761 }
762
CMFinishAsyncWork(napi_env env,SignVerifyAsyncContext context)763 static napi_value CMFinishAsyncWork(napi_env env, SignVerifyAsyncContext context)
764 {
765 napi_value promise = nullptr;
766 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
767
768 napi_value resourceName = nullptr;
769 NAPI_CALL(env, napi_create_string_latin1(env, "cmfinish", NAPI_AUTO_LENGTH, &resourceName));
770
771 NAPI_CALL(env, napi_create_async_work(
772 env, nullptr, resourceName,
773 FinishExecute,
774 FinishComplete,
775 static_cast<void *>(context),
776 &context->asyncWork));
777
778 napi_status status = napi_queue_async_work(env, context->asyncWork);
779 if (status != napi_ok) {
780 ThrowParamsError(env, PARAM_ERROR, "queue async work error");
781 CM_LOG_E("queue async work failed when using finish function");
782 return nullptr;
783 }
784 return promise;
785 }
786
CMAbortAsyncWork(napi_env env,SignVerifyAsyncContext context)787 static napi_value CMAbortAsyncWork(napi_env env, SignVerifyAsyncContext context)
788 {
789 napi_value promise = nullptr;
790 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
791
792 napi_value resourceName = nullptr;
793 NAPI_CALL(env, napi_create_string_latin1(env, "cmabort", NAPI_AUTO_LENGTH, &resourceName));
794
795 NAPI_CALL(env, napi_create_async_work(
796 env, nullptr, resourceName,
797 AbortExecute,
798 UpdateOrAbortComplete,
799 static_cast<void *>(context),
800 &context->asyncWork));
801
802 napi_status status = napi_queue_async_work(env, context->asyncWork);
803 if (status != napi_ok) {
804 ThrowParamsError(env, PARAM_ERROR, "queue async work error");
805 CM_LOG_E("queue async work failed when using abort function");
806 return nullptr;
807 }
808 return promise;
809 }
810
CMNapiInit(napi_env env,napi_callback_info info)811 napi_value CMNapiInit(napi_env env, napi_callback_info info)
812 {
813 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
814 if (context == nullptr) {
815 CM_LOG_E("init cm init context failed");
816 return nullptr;
817 }
818
819 napi_value result = ParseCMInitParams(env, info, context);
820 if (result == nullptr) {
821 CM_LOG_E("parse cm init params failed");
822 FreeSignVerifyAsyncContext(env, context);
823 return nullptr;
824 }
825
826 result = CMInitAsyncWork(env, context);
827 if (result == nullptr) {
828 CM_LOG_E("start cm init async work failed");
829 FreeSignVerifyAsyncContext(env, context);
830 return nullptr;
831 }
832
833 return result;
834 }
835
CMNapiUpdate(napi_env env,napi_callback_info info)836 napi_value CMNapiUpdate(napi_env env, napi_callback_info info)
837 {
838 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
839 if (context == nullptr) {
840 CM_LOG_E("init cm update context failed");
841 return nullptr;
842 }
843
844 napi_value result = ParseCMUpdateParams(env, info, context);
845 if (result == nullptr) {
846 CM_LOG_E("parse cm update params failed");
847 FreeSignVerifyAsyncContext(env, context);
848 return nullptr;
849 }
850
851 result = CMUpdateAsyncWork(env, context);
852 if (result == nullptr) {
853 CM_LOG_E("start cm update async work failed");
854 FreeSignVerifyAsyncContext(env, context);
855 return nullptr;
856 }
857
858 return result;
859 }
860
CMNapiFinish(napi_env env,napi_callback_info info)861 napi_value CMNapiFinish(napi_env env, napi_callback_info info)
862 {
863 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
864 if (context == nullptr) {
865 CM_LOG_E("init cm finish context failed");
866 return nullptr;
867 }
868
869 napi_value result = ParseCMFinishParams(env, info, context);
870 if (result == nullptr) {
871 CM_LOG_E("parse cm finish params failed");
872 FreeSignVerifyAsyncContext(env, context);
873 return nullptr;
874 }
875
876 result = CMFinishAsyncWork(env, context);
877 if (result == nullptr) {
878 CM_LOG_E("start cm finish async work failed");
879 FreeSignVerifyAsyncContext(env, context);
880 return nullptr;
881 }
882
883 return result;
884 }
885
CMNapiAbort(napi_env env,napi_callback_info info)886 napi_value CMNapiAbort(napi_env env, napi_callback_info info)
887 {
888 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
889 if (context == nullptr) {
890 CM_LOG_E("init cm abort context failed");
891 return nullptr;
892 }
893
894 napi_value result = ParseCMAbortParams(env, info, context);
895 if (result == nullptr) {
896 CM_LOG_E("parse cm abort params failed");
897 FreeSignVerifyAsyncContext(env, context);
898 return nullptr;
899 }
900
901 result = CMAbortAsyncWork(env, context);
902 if (result == nullptr) {
903 CM_LOG_E("start cm abort async work failed");
904 FreeSignVerifyAsyncContext(env, context);
905 return nullptr;
906 }
907
908 return result;
909 }
910 } // namespace CMNapi
911
912