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 ThrowError(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 ThrowError(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 ThrowError(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 ThrowError(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 ThrowError(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 ThrowError(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 ThrowError(env, PARAM_ERROR, "init arguments count invalid, arguments count need between 2 and 3.");
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 ThrowError(env, PARAM_ERROR, "authUri is not a string or the length is 0 or too long.");
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 ThrowError(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 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
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 ThrowError(env, PARAM_ERROR, "update arguments count invalid, arguments count need between 2 and 3.");
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 ThrowError(env, PARAM_ERROR, "handle is not a uint8Array or the length is 0 or too long.");
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 ThrowError(env, PARAM_ERROR, "inData is not a uint8Array or the length is 0 or too long.");
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 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
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 ThrowError(env, INNER_FAILURE, "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 ThrowError(env, INNER_FAILURE, "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 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
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 ThrowError(env, PARAM_ERROR, "signature is not a uint8Array or the length is 0 or too long.");
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 ThrowError(env, PARAM_ERROR, "signature is not a uint8Array or the length is 0 or too long.");
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 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
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 ThrowError(env, PARAM_ERROR, "finish arguments count invalid, arguments count need between 1 and 3.");
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 ThrowError(env, PARAM_ERROR, "handle is not a uint8Array or the length is 0 or too long.");
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 { /* only three types */
508 return ProcessFinishOneParam(env, context);
509 }
510 }
511
ParseCMAbortParams(napi_env env,napi_callback_info info,SignVerifyAsyncContext context)512 static napi_value ParseCMAbortParams(napi_env env, napi_callback_info info, SignVerifyAsyncContext context)
513 {
514 size_t argc = CM_NAPI_ABORT_ARGS_CNT;
515 napi_value argv[CM_NAPI_ABORT_ARGS_CNT] = { nullptr };
516 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
517
518 if ((argc != CM_NAPI_ABORT_ARGS_CNT) && (argc != (CM_NAPI_ABORT_ARGS_CNT - CM_NAPI_CALLBACK_ARG_CNT))) {
519 ThrowError(env, PARAM_ERROR, "abort arguments count invalid, arguments count need between 1 and 2.");
520 CM_LOG_E("abort arguments count is not expected");
521 return nullptr;
522 }
523
524 size_t index = 0;
525 napi_value result = GetBlob(env, argv[index], context->handle);
526 if (result == nullptr) {
527 ThrowError(env, PARAM_ERROR, "handle is not a uint8Array or the length is 0 or too long.");
528 CM_LOG_E("get handle failed when using abort function");
529 return nullptr;
530 }
531
532 index++;
533 if (index < argc) {
534 int32_t ret = GetCallback(env, argv[index], context->callback);
535 if (ret != CM_SUCCESS) {
536 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
537 CM_LOG_E("get callback function failed when using abort function");
538 return nullptr;
539 }
540 }
541
542 return GetInt32(env, 0);
543 }
544
InitExecute(napi_env env,void * data)545 static void InitExecute(napi_env env, void *data)
546 {
547 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
548 context->handle = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
549 if (context->handle == nullptr) {
550 CM_LOG_E("malloc handle out failed");
551 context->errCode = CMR_ERROR_MALLOC_FAIL;
552 return;
553 }
554 (void)memset_s(context->handle, sizeof(CmBlob), 0, sizeof(CmBlob));
555
556 context->handle->data = static_cast<uint8_t *>(CmMalloc(OUT_HANLDE_SIZE));
557 if (context->handle->data == nullptr) {
558 CM_LOG_E("malloc handle.data failed");
559 context->errCode = CMR_ERROR_MALLOC_FAIL;
560 return;
561 }
562 (void)memset_s(context->handle->data, OUT_HANLDE_SIZE, 0, OUT_HANLDE_SIZE);
563 context->handle->size = OUT_HANLDE_SIZE;
564
565 context->errCode = CmInit(context->authUri, context->spec, context->handle);
566 }
567
GenerateArrayBuffer(napi_env env,uint8_t * data,uint32_t size)568 static napi_value GenerateArrayBuffer(napi_env env, uint8_t *data, uint32_t size)
569 {
570 uint8_t *tempBuf = static_cast<uint8_t *>(CmMalloc(size));
571 if (tempBuf == nullptr) {
572 CM_LOG_E("malloc outbuf failed");
573 return nullptr;
574 }
575 (void)memcpy_s(tempBuf, size, data, size);
576
577 napi_value outBuffer = nullptr;
578 napi_status status = napi_create_external_arraybuffer(
579 env, tempBuf, size, [](napi_env env, void *data, void *hint) { CmFree(data); }, nullptr, &outBuffer);
580 if (status == napi_ok) {
581 tempBuf = nullptr; /* free by finalize callback */
582 } else {
583 CM_LOG_E("create external array buffer failed");
584 CM_FREE_PTR(tempBuf);
585 GET_AND_THROW_LAST_ERROR((env));
586 }
587
588 return outBuffer;
589 }
590
ConvertResultHandle(napi_env env,const CmBlob * handle)591 static napi_value ConvertResultHandle(napi_env env, const CmBlob *handle)
592 {
593 napi_value result = nullptr;
594 NAPI_CALL(env, napi_create_object(env, &result));
595
596 napi_value handleNapi = nullptr;
597 napi_value handleBuf = GenerateArrayBuffer(env, handle->data, handle->size);
598 if (handleBuf != nullptr) {
599 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, handle->size, handleBuf, 0, &handleNapi));
600 } else {
601 handleNapi = GetNull(env);
602 }
603 NAPI_CALL(env, napi_set_named_property(env, result, "handle", handleNapi));
604
605 return result;
606 }
607
InitComplete(napi_env env,napi_status status,void * data)608 static void InitComplete(napi_env env, napi_status status, void *data)
609 {
610 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
611 napi_value result[RESULT_NUMBER] = { nullptr };
612 if (context->errCode == CM_SUCCESS) {
613 napi_create_uint32(env, 0, &result[0]);
614 result[1] = ConvertResultHandle(env, context->handle);
615 } else {
616 result[0] = GenerateBusinessError(env, context->errCode);
617 napi_get_undefined(env, &result[1]);
618 }
619
620 if (context->deferred != nullptr) {
621 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
622 } else {
623 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
624 }
625 FreeSignVerifyAsyncContext(env, context);
626 }
627
UpdateExecute(napi_env env,void * data)628 static void UpdateExecute(napi_env env, void *data)
629 {
630 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
631 context->errCode = CmUpdate(context->handle, context->inData);
632 }
633
UpdateOrAbortComplete(napi_env env,napi_status status,void * data)634 static void UpdateOrAbortComplete(napi_env env, napi_status status, void *data)
635 {
636 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
637 napi_value result[RESULT_NUMBER] = { nullptr };
638 if (context->errCode == CM_SUCCESS) {
639 napi_create_uint32(env, 0, &result[0]);
640 napi_get_undefined(env, &result[1]);
641 } else {
642 result[0] = GenerateBusinessError(env, context->errCode);
643 napi_get_undefined(env, &result[1]);
644 }
645
646 if (context->deferred != nullptr) {
647 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
648 } else {
649 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
650 }
651 FreeSignVerifyAsyncContext(env, context);
652 }
653
FinishExecute(napi_env env,void * data)654 static void FinishExecute(napi_env env, void *data)
655 {
656 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
657 if (context->isSign) {
658 CmBlob inData = { 0, nullptr };
659 context->errCode = CmFinish(context->handle, &inData, context->signature);
660 return;
661 }
662
663 CmBlob outData = { 0, nullptr };
664 context->errCode = CmFinish(context->handle, context->signature, &outData);
665 }
666
ConvertResultSignature(napi_env env,bool isSign,const CmBlob * sign)667 static napi_value ConvertResultSignature(napi_env env, bool isSign, const CmBlob *sign)
668 {
669 napi_value result = nullptr;
670 NAPI_CALL(env, napi_create_object(env, &result));
671
672 napi_value signResultNapi = nullptr;
673 if (isSign) {
674 napi_value signBuf = GenerateArrayBuffer(env, sign->data, sign->size);
675 if (signBuf != nullptr) {
676 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, sign->size, signBuf, 0, &signResultNapi));
677 } else {
678 signResultNapi = GetNull(env);
679 }
680 } else {
681 signResultNapi = GetNull(env);
682 }
683 NAPI_CALL(env, napi_set_named_property(env, result, "outData", signResultNapi));
684
685 return result;
686 }
687
FinishComplete(napi_env env,napi_status status,void * data)688 static void FinishComplete(napi_env env, napi_status status, void *data)
689 {
690 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
691 napi_value result[RESULT_NUMBER] = { nullptr };
692 if (context->errCode == CM_SUCCESS) {
693 napi_create_uint32(env, 0, &result[0]);
694 result[1] = ConvertResultSignature(env, context->isSign, context->signature);
695 } else {
696 result[0] = GenerateBusinessError(env, context->errCode);
697 napi_get_undefined(env, &result[1]);
698 }
699
700 if (context->deferred != nullptr) {
701 GeneratePromise(env, context->deferred, context->errCode, result, CM_ARRAY_SIZE(result));
702 } else {
703 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->errCode);
704 }
705 FreeSignVerifyAsyncContext(env, context);
706 }
707
AbortExecute(napi_env env,void * data)708 static void AbortExecute(napi_env env, void *data)
709 {
710 SignVerifyAsyncContext context = static_cast<SignVerifyAsyncContext>(data);
711 context->errCode = CmAbort(context->handle);
712 }
713
CMInitAsyncWork(napi_env env,SignVerifyAsyncContext context)714 static napi_value CMInitAsyncWork(napi_env env, SignVerifyAsyncContext context)
715 {
716 napi_value promise = nullptr;
717 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
718
719 napi_value resourceName = nullptr;
720 NAPI_CALL(env, napi_create_string_latin1(env, "cminit", NAPI_AUTO_LENGTH, &resourceName));
721
722 NAPI_CALL(env, napi_create_async_work(
723 env, nullptr, resourceName,
724 InitExecute,
725 InitComplete,
726 static_cast<void *>(context),
727 &context->asyncWork));
728
729 napi_status status = napi_queue_async_work(env, context->asyncWork);
730 if (status != napi_ok) {
731 ThrowError(env, PARAM_ERROR, "queue async work error");
732 CM_LOG_E("queue async work failed when using init function");
733 return nullptr;
734 }
735 return promise;
736 }
737
CMUpdateAsyncWork(napi_env env,SignVerifyAsyncContext context)738 static napi_value CMUpdateAsyncWork(napi_env env, SignVerifyAsyncContext context)
739 {
740 napi_value promise = nullptr;
741 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
742
743 napi_value resourceName = nullptr;
744 NAPI_CALL(env, napi_create_string_latin1(env, "cmupdate", NAPI_AUTO_LENGTH, &resourceName));
745
746 NAPI_CALL(env, napi_create_async_work(
747 env, nullptr, resourceName,
748 UpdateExecute,
749 UpdateOrAbortComplete,
750 static_cast<void *>(context),
751 &context->asyncWork));
752
753 napi_status status = napi_queue_async_work(env, context->asyncWork);
754 if (status != napi_ok) {
755 ThrowError(env, PARAM_ERROR, "queue async work error");
756 CM_LOG_E("queue async work failed when using update function");
757 return nullptr;
758 }
759 return promise;
760 }
761
CMFinishAsyncWork(napi_env env,SignVerifyAsyncContext context)762 static napi_value CMFinishAsyncWork(napi_env env, SignVerifyAsyncContext context)
763 {
764 napi_value promise = nullptr;
765 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
766
767 napi_value resourceName = nullptr;
768 NAPI_CALL(env, napi_create_string_latin1(env, "cmfinish", NAPI_AUTO_LENGTH, &resourceName));
769
770 NAPI_CALL(env, napi_create_async_work(
771 env, nullptr, resourceName,
772 FinishExecute,
773 FinishComplete,
774 static_cast<void *>(context),
775 &context->asyncWork));
776
777 napi_status status = napi_queue_async_work(env, context->asyncWork);
778 if (status != napi_ok) {
779 ThrowError(env, PARAM_ERROR, "queue async work error");
780 CM_LOG_E("queue async work failed when using finish function");
781 return nullptr;
782 }
783 return promise;
784 }
785
CMAbortAsyncWork(napi_env env,SignVerifyAsyncContext context)786 static napi_value CMAbortAsyncWork(napi_env env, SignVerifyAsyncContext context)
787 {
788 napi_value promise = nullptr;
789 GenerateNapiPromise(env, context->callback, &context->deferred, &promise);
790
791 napi_value resourceName = nullptr;
792 NAPI_CALL(env, napi_create_string_latin1(env, "cmabort", NAPI_AUTO_LENGTH, &resourceName));
793
794 NAPI_CALL(env, napi_create_async_work(
795 env, nullptr, resourceName,
796 AbortExecute,
797 UpdateOrAbortComplete,
798 static_cast<void *>(context),
799 &context->asyncWork));
800
801 napi_status status = napi_queue_async_work(env, context->asyncWork);
802 if (status != napi_ok) {
803 ThrowError(env, PARAM_ERROR, "queue async work error");
804 CM_LOG_E("queue async work failed when using abort function");
805 return nullptr;
806 }
807 return promise;
808 }
809
CMNapiInit(napi_env env,napi_callback_info info)810 napi_value CMNapiInit(napi_env env, napi_callback_info info)
811 {
812 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
813 if (context == nullptr) {
814 CM_LOG_E("init cm init context failed");
815 return nullptr;
816 }
817
818 napi_value result = ParseCMInitParams(env, info, context);
819 if (result == nullptr) {
820 CM_LOG_E("parse cm init params failed");
821 FreeSignVerifyAsyncContext(env, context);
822 return nullptr;
823 }
824
825 result = CMInitAsyncWork(env, context);
826 if (result == nullptr) {
827 CM_LOG_E("start cm init async work failed");
828 FreeSignVerifyAsyncContext(env, context);
829 return nullptr;
830 }
831
832 return result;
833 }
834
CMNapiUpdate(napi_env env,napi_callback_info info)835 napi_value CMNapiUpdate(napi_env env, napi_callback_info info)
836 {
837 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
838 if (context == nullptr) {
839 CM_LOG_E("init cm update context failed");
840 return nullptr;
841 }
842
843 napi_value result = ParseCMUpdateParams(env, info, context);
844 if (result == nullptr) {
845 CM_LOG_E("parse cm update params failed");
846 FreeSignVerifyAsyncContext(env, context);
847 return nullptr;
848 }
849
850 result = CMUpdateAsyncWork(env, context);
851 if (result == nullptr) {
852 CM_LOG_E("start cm update async work failed");
853 FreeSignVerifyAsyncContext(env, context);
854 return nullptr;
855 }
856
857 return result;
858 }
859
CMNapiFinish(napi_env env,napi_callback_info info)860 napi_value CMNapiFinish(napi_env env, napi_callback_info info)
861 {
862 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
863 if (context == nullptr) {
864 CM_LOG_E("init cm finish context failed");
865 return nullptr;
866 }
867
868 napi_value result = ParseCMFinishParams(env, info, context);
869 if (result == nullptr) {
870 CM_LOG_E("parse cm finish params failed");
871 FreeSignVerifyAsyncContext(env, context);
872 return nullptr;
873 }
874
875 result = CMFinishAsyncWork(env, context);
876 if (result == nullptr) {
877 CM_LOG_E("start cm finish async work failed");
878 FreeSignVerifyAsyncContext(env, context);
879 return nullptr;
880 }
881
882 return result;
883 }
884
CMNapiAbort(napi_env env,napi_callback_info info)885 napi_value CMNapiAbort(napi_env env, napi_callback_info info)
886 {
887 SignVerifyAsyncContext context = InitSignVerifyAsyncContext();
888 if (context == nullptr) {
889 CM_LOG_E("init cm abort context failed");
890 return nullptr;
891 }
892
893 napi_value result = ParseCMAbortParams(env, info, context);
894 if (result == nullptr) {
895 CM_LOG_E("parse cm abort params failed");
896 FreeSignVerifyAsyncContext(env, context);
897 return nullptr;
898 }
899
900 result = CMAbortAsyncWork(env, context);
901 if (result == nullptr) {
902 CM_LOG_E("start cm abort async work failed");
903 FreeSignVerifyAsyncContext(env, context);
904 return nullptr;
905 }
906
907 return result;
908 }
909 } // namespace CMNapi
910
911