1 /*
2 * Copyright (C) 2022-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "napi_mac.h"
17
18 #include "securec.h"
19 #include "log.h"
20 #include "memory.h"
21
22 #include "mac_params.h"
23 #include "detailed_hmac_params.h"
24 #include "detailed_cmac_params.h"
25 #include "napi_sym_key.h"
26 #include "napi_utils.h"
27 #include "napi_crypto_framework_defines.h"
28
29 namespace OHOS {
30 namespace CryptoFramework {
31 thread_local napi_ref NapiMac::classRef_ = nullptr;
32
33 struct MacCtx {
34 napi_env env = nullptr;
35
36 AsyncType asyncType = ASYNC_CALLBACK;
37 napi_ref callback = nullptr;
38 napi_deferred deferred = nullptr;
39 napi_value promise = nullptr;
40 napi_async_work asyncWork = nullptr;
41 napi_ref macRef = nullptr;
42 napi_ref symKeyRef = nullptr;
43
44 std::string algoName = "";
45 HcfSymKey *symKey = nullptr;
46 HcfBlob *inBlob = nullptr;
47
48 HcfResult errCode = HCF_SUCCESS;
49 const char *errMsg = nullptr;
50 HcfBlob *outBlob = nullptr;
51 HcfMac *mac = nullptr;
52 };
53
FreeCryptoFwkCtx(napi_env env,MacCtx * context)54 static void FreeCryptoFwkCtx(napi_env env, MacCtx *context)
55 {
56 if (context == nullptr) {
57 return;
58 }
59 if (context->asyncWork != nullptr) {
60 napi_delete_async_work(env, context->asyncWork);
61 context->asyncWork = nullptr;
62 }
63 if (context->callback != nullptr) {
64 napi_delete_reference(env, context->callback);
65 context->callback = nullptr;
66 }
67 if (context->macRef != nullptr) {
68 napi_delete_reference(env, context->macRef);
69 context->macRef = nullptr;
70 }
71 if (context->symKeyRef != nullptr) {
72 napi_delete_reference(env, context->symKeyRef);
73 context->symKeyRef = nullptr;
74 }
75 context->symKey = nullptr;
76 if (context->inBlob != nullptr) {
77 HcfFree(context->inBlob->data);
78 context->inBlob->data = nullptr;
79 context->inBlob->len = 0;
80 HcfFree(context->inBlob);
81 context->inBlob = nullptr;
82 }
83 if (context->outBlob != nullptr) {
84 HcfFree(context->outBlob->data);
85 context->outBlob->data = nullptr;
86 context->outBlob->len = 0;
87 HcfFree(context->outBlob);
88 context->outBlob = nullptr;
89 }
90 context->errMsg = nullptr;
91 context->mac = nullptr;
92 HcfFree(context);
93 }
94
FreeMacParams(HcfMacParamsSpec * params)95 static void FreeMacParams(HcfMacParamsSpec *params)
96 {
97 if (strcmp(params->algName, "HMAC") == 0) {
98 HcfFree(static_cast<void *>(const_cast<char *>(((HcfHmacParamsSpec *)params)->mdName)));
99 ((HcfHmacParamsSpec *)params)->mdName = nullptr;
100 } else if (strcmp(params->algName, "CMAC") == 0) {
101 HcfFree(static_cast<void *>(const_cast<char *>(((HcfCmacParamsSpec *)params)->cipherName)));
102 ((HcfCmacParamsSpec *)params)->cipherName = nullptr;
103 }
104 HcfFree(params);
105 }
106
ReturnCallbackResult(napi_env env,MacCtx * context,napi_value result)107 static void ReturnCallbackResult(napi_env env, MacCtx *context, napi_value result)
108 {
109 napi_value businessError = nullptr;
110 if (context->errCode != HCF_SUCCESS) {
111 businessError = GenerateBusinessError(env, context->errCode, context->errMsg);
112 }
113 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
114
115 napi_value func = nullptr;
116 napi_get_reference_value(env, context->callback, &func);
117
118 napi_value recv = nullptr;
119 napi_value callFuncRet = nullptr;
120 napi_get_undefined(env, &recv);
121 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
122 }
123
ReturnPromiseResult(napi_env env,MacCtx * context,napi_value result)124 static void ReturnPromiseResult(napi_env env, MacCtx *context, napi_value result)
125 {
126 if (context->errCode == HCF_SUCCESS) {
127 napi_resolve_deferred(env, context->deferred, result);
128 } else {
129 napi_reject_deferred(env, context->deferred,
130 GenerateBusinessError(env, context->errCode, context->errMsg));
131 }
132 }
133
MacInitExecute(napi_env env,void * data)134 static void MacInitExecute(napi_env env, void *data)
135 {
136 MacCtx *context = static_cast<MacCtx *>(data);
137 HcfMac *macObj = context->mac;
138 HcfSymKey *symKey = context->symKey;
139 context->errCode = macObj->init(macObj, symKey);
140 if (context->errCode != HCF_SUCCESS) {
141 LOGD("[error] init failed!");
142 context->errMsg = "init failed";
143 }
144 }
145
MacInitComplete(napi_env env,napi_status status,void * data)146 static void MacInitComplete(napi_env env, napi_status status, void *data)
147 {
148 MacCtx *context = static_cast<MacCtx *>(data);
149 napi_value nullInstance = nullptr;
150 napi_get_null(env, &nullInstance);
151 if (context->asyncType == ASYNC_CALLBACK) {
152 ReturnCallbackResult(env, context, nullInstance);
153 } else {
154 ReturnPromiseResult(env, context, nullInstance);
155 }
156 FreeCryptoFwkCtx(env, context);
157 }
158
MacUpdateExecute(napi_env env,void * data)159 static void MacUpdateExecute(napi_env env, void *data)
160 {
161 MacCtx *context = static_cast<MacCtx *>(data);
162 HcfMac *macObj = context->mac;
163 HcfBlob *inBlob = reinterpret_cast<HcfBlob *>(context->inBlob);
164 context->errCode = macObj->update(macObj, inBlob);
165 if (context->errCode != HCF_SUCCESS) {
166 LOGD("[error] update failed!");
167 context->errMsg = "update failed";
168 }
169 }
170
MacUpdateComplete(napi_env env,napi_status status,void * data)171 static void MacUpdateComplete(napi_env env, napi_status status, void *data)
172 {
173 MacCtx *context = static_cast<MacCtx *>(data);
174 napi_value nullInstance = nullptr;
175 napi_get_null(env, &nullInstance);
176 if (context->asyncType == ASYNC_CALLBACK) {
177 ReturnCallbackResult(env, context, nullInstance);
178 } else {
179 ReturnPromiseResult(env, context, nullInstance);
180 }
181 FreeCryptoFwkCtx(env, context);
182 }
183
MacDoFinalExecute(napi_env env,void * data)184 static void MacDoFinalExecute(napi_env env, void *data)
185 {
186 MacCtx *context = static_cast<MacCtx *>(data);
187 HcfMac *macObj = context->mac;
188 HcfBlob *outBlob = reinterpret_cast<HcfBlob *>(HcfMalloc(sizeof(HcfBlob), 0));
189 if (outBlob == nullptr) {
190 LOGD("[error] outBlob is null!");
191 context->errCode = HCF_ERR_MALLOC;
192 context->errMsg = "malloc data blob failed";
193 return;
194 }
195 context->errCode = macObj->doFinal(macObj, outBlob);
196 if (context->errCode != HCF_SUCCESS) {
197 HcfFree(outBlob);
198 outBlob = nullptr;
199 LOGE("doFinal failed!");
200 context->errMsg = "doFinal failed";
201 return;
202 }
203 context->outBlob = outBlob;
204 }
205
MacDoFinalComplete(napi_env env,napi_status status,void * data)206 static void MacDoFinalComplete(napi_env env, napi_status status, void *data)
207 {
208 MacCtx *context = static_cast<MacCtx *>(data);
209 napi_value returnOutBlob = ConvertBlobToNapiValue(env, context->outBlob);
210 if (returnOutBlob == nullptr) {
211 LOGE("returnOutBlob is nullptr!");
212 returnOutBlob = NapiGetNull(env);
213 }
214 if (context->asyncType == ASYNC_CALLBACK) {
215 ReturnCallbackResult(env, context, returnOutBlob);
216 } else {
217 ReturnPromiseResult(env, context, returnOutBlob);
218 }
219 FreeCryptoFwkCtx(env, context);
220 }
221
BuildMacJsInitCtx(napi_env env,napi_callback_info info,MacCtx * context)222 static bool BuildMacJsInitCtx(napi_env env, napi_callback_info info, MacCtx *context)
223 {
224 napi_value thisVar = nullptr;
225 NapiMac *napiMac = nullptr;
226 size_t expectedArgsCount = ARGS_SIZE_TWO;
227 size_t argc = expectedArgsCount;
228 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
229 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
230 if (!CheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
231 return false;
232 }
233
234 context->asyncType = isCallback(env, argv[expectedArgsCount - 1], argc, expectedArgsCount) ?
235 ASYNC_CALLBACK : ASYNC_PROMISE;
236 NapiSymKey *symKey = nullptr;
237 napi_status status = napi_unwrap(env, argv[PARAM0], reinterpret_cast<void **>(&symKey));
238 if (status != napi_ok || symKey == nullptr) {
239 LOGE("symKey is null!");
240 return false;
241 }
242 context->symKey = symKey->GetSymKey();
243 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
244 if (status != napi_ok || napiMac == nullptr) {
245 LOGE("failed to unwrap napiMac obj!");
246 return false;
247 }
248
249 context->mac = napiMac->GetMac();
250
251 if (napi_create_reference(env, thisVar, 1, &context->macRef) != napi_ok) {
252 LOGE("create mac ref failed when do mac init!");
253 return false;
254 }
255
256 if (napi_create_reference(env, argv[PARAM0], 1, &context->symKeyRef) != napi_ok) {
257 LOGE("create sym key ref failed when do mac init!");
258 return false;
259 }
260
261 if (context->asyncType == ASYNC_PROMISE) {
262 napi_create_promise(env, &context->deferred, &context->promise);
263 return true;
264 } else {
265 return GetCallbackFromJSParams(env, argv[PARAM1], &context->callback);
266 }
267 }
268
BuildMacJsUpdateCtx(napi_env env,napi_callback_info info,MacCtx * context)269 static bool BuildMacJsUpdateCtx(napi_env env, napi_callback_info info, MacCtx *context)
270 {
271 napi_value thisVar = nullptr;
272 NapiMac *napiMac = nullptr;
273 size_t expectedArgsCount = ARGS_SIZE_TWO;
274 size_t argc = expectedArgsCount;
275 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
276 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
277 if (!CheckArgsCount(env, argc, ARGS_SIZE_TWO, false)) {
278 return false;
279 }
280
281 context->asyncType = isCallback(env, argv[expectedArgsCount - 1], argc, expectedArgsCount) ?
282 ASYNC_CALLBACK : ASYNC_PROMISE;
283 context->inBlob = GetBlobFromNapiDataBlob(env, argv[PARAM0]);
284 if (context->inBlob == nullptr) {
285 LOGE("inBlob is null!");
286 return false;
287 }
288 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
289 if (status != napi_ok || napiMac == nullptr) {
290 LOGE("failed to unwrap napiMac obj!");
291 return false;
292 }
293
294 context->mac = napiMac->GetMac();
295
296 if (napi_create_reference(env, thisVar, 1, &context->macRef) != napi_ok) {
297 LOGE("create mac ref failed when do mac update!");
298 return false;
299 }
300
301 if (context->asyncType == ASYNC_PROMISE) {
302 napi_create_promise(env, &context->deferred, &context->promise);
303 return true;
304 } else {
305 return GetCallbackFromJSParams(env, argv[PARAM1], &context->callback);
306 }
307 }
308
BuildMacJsDoFinalCtx(napi_env env,napi_callback_info info,MacCtx * context)309 static bool BuildMacJsDoFinalCtx(napi_env env, napi_callback_info info, MacCtx *context)
310 {
311 napi_value thisVar = nullptr;
312 NapiMac *napiMac = nullptr;
313 size_t expectedArgsCount = ARGS_SIZE_ONE;
314 size_t argc = expectedArgsCount;
315 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
316 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
317 if (!CheckArgsCount(env, argc, ARGS_SIZE_ONE, false)) {
318 return false;
319 }
320
321 context->asyncType = isCallback(env, argv[expectedArgsCount - 1], argc, expectedArgsCount) ?
322 ASYNC_CALLBACK : ASYNC_PROMISE;
323 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
324 if (status != napi_ok || napiMac == nullptr) {
325 LOGE("failed to unwrap napiMac obj!");
326 return false;
327 }
328
329 context->mac = napiMac->GetMac();
330
331 if (napi_create_reference(env, thisVar, 1, &context->macRef) != napi_ok) {
332 LOGE("create mac ref failed when do mac final!");
333 return false;
334 }
335
336 if (context->asyncType == ASYNC_PROMISE) {
337 napi_create_promise(env, &context->deferred, &context->promise);
338 return true;
339 } else {
340 return GetCallbackFromJSParams(env, argv[PARAM0], &context->callback);
341 }
342 }
343
NewMacJsInitAsyncWork(napi_env env,MacCtx * context)344 static napi_value NewMacJsInitAsyncWork(napi_env env, MacCtx *context)
345 {
346 napi_create_async_work(
347 env, nullptr, GetResourceName(env, "MacInit"),
348 [](napi_env env, void *data) {
349 MacInitExecute(env, data);
350 return;
351 },
352 [](napi_env env, napi_status status, void *data) {
353 MacInitComplete(env, status, data);
354 return;
355 },
356 static_cast<void *>(context),
357 &context->asyncWork);
358
359 napi_queue_async_work(env, context->asyncWork);
360 if (context->asyncType == ASYNC_PROMISE) {
361 return context->promise;
362 } else {
363 return NapiGetNull(env);
364 }
365 }
366
NewMacJsUpdateAsyncWork(napi_env env,MacCtx * context)367 static napi_value NewMacJsUpdateAsyncWork(napi_env env, MacCtx *context)
368 {
369 napi_create_async_work(
370 env, nullptr, GetResourceName(env, "MacUpdate"),
371 [](napi_env env, void *data) {
372 MacUpdateExecute(env, data);
373 return;
374 },
375 [](napi_env env, napi_status status, void *data) {
376 MacUpdateComplete(env, status, data);
377 return;
378 },
379 static_cast<void *>(context),
380 &context->asyncWork);
381
382 napi_queue_async_work(env, context->asyncWork);
383 if (context->asyncType == ASYNC_PROMISE) {
384 return context->promise;
385 } else {
386 return NapiGetNull(env);
387 }
388 }
389
NewMacJsDoFinalAsyncWork(napi_env env,MacCtx * context)390 static napi_value NewMacJsDoFinalAsyncWork(napi_env env, MacCtx *context)
391 {
392 napi_create_async_work(
393 env, nullptr, GetResourceName(env, "MacDoFinal"),
394 [](napi_env env, void *data) {
395 MacDoFinalExecute(env, data);
396 return;
397 },
398 [](napi_env env, napi_status status, void *data) {
399 MacDoFinalComplete(env, status, data);
400 return;
401 },
402 static_cast<void *>(context),
403 &context->asyncWork);
404
405 napi_queue_async_work(env, context->asyncWork);
406 if (context->asyncType == ASYNC_PROMISE) {
407 return context->promise;
408 } else {
409 return NapiGetNull(env);
410 }
411 }
412
413
NapiMac(HcfMac * macObj)414 NapiMac::NapiMac(HcfMac *macObj)
415 {
416 this->macObj_ = macObj;
417 }
418
~NapiMac()419 NapiMac::~NapiMac()
420 {
421 HcfObjDestroy(this->macObj_);
422 this->macObj_ = nullptr;
423 }
424
GetMac()425 HcfMac *NapiMac::GetMac()
426 {
427 return this->macObj_;
428 }
429
JsMacInit(napi_env env,napi_callback_info info)430 napi_value NapiMac::JsMacInit(napi_env env, napi_callback_info info)
431 {
432 MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
433 if (context == nullptr) {
434 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed"));
435 LOGE("malloc context failed!");
436 return nullptr;
437 }
438
439 if (!BuildMacJsInitCtx(env, info, context)) {
440 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
441 LOGE("build context fail.");
442 FreeCryptoFwkCtx(env, context);
443 return nullptr;
444 }
445
446 return NewMacJsInitAsyncWork(env, context);
447 }
448
JsMacInitSync(napi_env env,napi_callback_info info)449 napi_value NapiMac::JsMacInitSync(napi_env env, napi_callback_info info)
450 {
451 napi_value thisVar = nullptr;
452 NapiMac *napiMac = nullptr;
453 size_t argc = ARGS_SIZE_ONE;
454 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
455 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
456 if (argc != ARGS_SIZE_ONE) {
457 LOGE("The input args num is invalid.");
458 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
459 return nullptr;
460 }
461 NapiSymKey *napiSysKey = nullptr;
462 napi_status status = napi_unwrap(env, argv[PARAM0], reinterpret_cast<void **>(&napiSysKey));
463 if (status != napi_ok || napiSysKey == nullptr) {
464 LOGE("napiSysKey is null!");
465 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "napiSysKey is null!"));
466 return nullptr;
467 }
468 HcfSymKey *symKey = napiSysKey->GetSymKey();
469 status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
470 if (status != napi_ok || napiMac == nullptr) {
471 LOGE("failed to unwrap napiMac obj!");
472 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiMac obj!"));
473 return nullptr;
474 }
475 HcfMac *mac = napiMac->GetMac();
476 if (mac == nullptr) {
477 LOGE("mac is nullptr!");
478 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "mac is nullptr!"));
479 return nullptr;
480 }
481 HcfResult errCode = mac->init(mac, symKey);
482 if (errCode != HCF_SUCCESS) {
483 LOGE("mac init failed!");
484 napi_throw(env, GenerateBusinessError(env, HCF_ERR_CRYPTO_OPERATION, "mac init failed!"));
485 return nullptr;
486 }
487 napi_value nullInstance = nullptr;
488 napi_get_null(env, &nullInstance);
489 return nullInstance;
490 }
491
JsMacUpdate(napi_env env,napi_callback_info info)492 napi_value NapiMac::JsMacUpdate(napi_env env, napi_callback_info info)
493 {
494 MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
495 if (context == nullptr) {
496 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed"));
497 LOGE("malloc context failed!");
498 return nullptr;
499 }
500
501 if (!BuildMacJsUpdateCtx(env, info, context)) {
502 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
503 LOGE("build context fail.");
504 FreeCryptoFwkCtx(env, context);
505 return nullptr;
506 }
507
508 return NewMacJsUpdateAsyncWork(env, context);
509 }
510
JsMacUpdateSync(napi_env env,napi_callback_info info)511 napi_value NapiMac::JsMacUpdateSync(napi_env env, napi_callback_info info)
512 {
513 napi_value thisVar = nullptr;
514 NapiMac *napiMac = nullptr;
515 size_t argc = ARGS_SIZE_ONE;
516 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
517 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
518 if (argc != ARGS_SIZE_ONE) {
519 LOGE("The input args num is invalid.");
520 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
521 return nullptr;
522 }
523
524 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
525 if (status != napi_ok || napiMac == nullptr) {
526 LOGE("failed to unwrap napiMac obj!");
527 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiMac obj!"));
528 return nullptr;
529 }
530
531 HcfBlob *inBlob = GetBlobFromNapiDataBlob(env, argv[PARAM0]);
532 if (inBlob == nullptr) {
533 LOGE("inBlob is null!");
534 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "inBlob is null!"));
535 return nullptr;
536 }
537
538 HcfMac *mac = napiMac->GetMac();
539 if (mac == nullptr) {
540 LOGE("mac is nullptr!");
541 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "mac is nullptr!"));
542 HcfBlobDataClearAndFree(inBlob);
543 HcfFree(inBlob);
544 inBlob = nullptr;
545 return nullptr;
546 }
547 HcfResult errCode = mac->update(mac, inBlob);
548 HcfBlobDataClearAndFree(inBlob);
549 HcfFree(inBlob);
550 inBlob = nullptr;
551 if (errCode != HCF_SUCCESS) {
552 LOGE("mac update failed!");
553 napi_throw(env, GenerateBusinessError(env, HCF_ERR_CRYPTO_OPERATION, "mac update failed!"));
554 return nullptr;
555 }
556 napi_value nullInstance = nullptr;
557 napi_get_null(env, &nullInstance);
558 return nullInstance;
559 }
560
JsMacDoFinal(napi_env env,napi_callback_info info)561 napi_value NapiMac::JsMacDoFinal(napi_env env, napi_callback_info info)
562 {
563 MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
564 if (context == nullptr) {
565 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed"));
566 LOGE("malloc context failed!");
567 return nullptr;
568 }
569
570 if (!BuildMacJsDoFinalCtx(env, info, context)) {
571 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build context fail."));
572 LOGE("build context fail.");
573 FreeCryptoFwkCtx(env, context);
574 return nullptr;
575 }
576
577 return NewMacJsDoFinalAsyncWork(env, context);
578 }
579
JsMacDoFinalSync(napi_env env,napi_callback_info info)580 napi_value NapiMac::JsMacDoFinalSync(napi_env env, napi_callback_info info)
581 {
582 napi_value thisVar = nullptr;
583 NapiMac *napiMac = nullptr;
584 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
585 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
586 if (status != napi_ok || napiMac == nullptr) {
587 LOGE("failed to unwrap napiMac obj!");
588 napi_throw(env, GenerateBusinessError(env, HCF_ERR_NAPI, "failed to unwrap napiMac obj."));
589 return nullptr;
590 }
591 HcfMac *mac = napiMac->GetMac();
592 if (mac == nullptr) {
593 LOGE("mac is nullptr!");
594 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "mac is nullptr!"));
595 return nullptr;
596 }
597 HcfBlob outBlob = { .data = nullptr, .len = 0 };
598 HcfResult errCode = mac->doFinal(mac, &outBlob);
599 if (errCode != HCF_SUCCESS) {
600 LOGE("mac doFinal failed!");
601 napi_throw(env, GenerateBusinessError(env, errCode, "mac doFinal failed!"));
602 HcfBlobDataClearAndFree(&outBlob);
603 return nullptr;
604 }
605
606 napi_value returnOutBlob = nullptr;
607 errCode = ConvertDataBlobToNapiValue(env, &outBlob, &returnOutBlob);
608 HcfBlobDataClearAndFree(&outBlob);
609 if (errCode != HCF_SUCCESS) {
610 LOGE("mac convert dataBlob to napi_value failed!");
611 napi_throw(env, GenerateBusinessError(env, errCode, "mac convert dataBlob to napi_value failed!"));
612 return nullptr;
613 }
614
615 return returnOutBlob;
616 }
617
JsGetMacLength(napi_env env,napi_callback_info info)618 napi_value NapiMac::JsGetMacLength(napi_env env, napi_callback_info info)
619 {
620 napi_value thisVar = nullptr;
621 NapiMac *napiMac = nullptr;
622
623 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
624 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiMac));
625 if (status != napi_ok || napiMac == nullptr) {
626 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiMac obj!"));
627 LOGE("failed to unwrap napiMac obj!");
628 return nullptr;
629 }
630
631 HcfMac *mac = napiMac->GetMac();
632 if (mac == nullptr) {
633 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "fail to get mac obj!"));
634 LOGE("fail to get mac obj!");
635 return nullptr;
636 }
637
638 uint32_t retLen = mac->getMacLength(mac);
639 napi_value napiLen = nullptr;
640 napi_create_uint32(env, retLen, &napiLen);
641 return napiLen;
642 }
643
MacConstructor(napi_env env,napi_callback_info info)644 napi_value NapiMac::MacConstructor(napi_env env, napi_callback_info info)
645 {
646 napi_value thisVar = nullptr;
647 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
648 return thisVar;
649 }
650
NapiWrapMac(napi_env env,napi_value instance,NapiMac * macNapiObj)651 static napi_value NapiWrapMac(napi_env env, napi_value instance, NapiMac *macNapiObj)
652 {
653 napi_status status = napi_wrap(
654 env, instance, macNapiObj,
655 [](napi_env env, void *data, void *hint) {
656 NapiMac *mac = static_cast<NapiMac *>(data);
657 delete mac;
658 return;
659 }, nullptr, nullptr);
660 if (status != napi_ok) {
661 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to wrap NapiMac obj!"));
662 delete macNapiObj;
663 LOGE("failed to wrap NapiMac obj!");
664 return nullptr;
665 }
666 return instance;
667 }
668
GetHmacParamsSpec(napi_env env,napi_value arg,const char * algName,HcfMacParamsSpec ** paramsSpec)669 static bool GetHmacParamsSpec(napi_env env, napi_value arg, const char *algName, HcfMacParamsSpec **paramsSpec)
670 {
671 napi_value data = nullptr;
672 napi_valuetype valueType = napi_undefined;
673 if ((env == nullptr) || (arg == nullptr) || (paramsSpec == nullptr)) {
674 LOGE("Invalid params!");
675 return false;
676 }
677
678 napi_status status = napi_get_named_property(env, arg, MD_NAME.c_str(), &data);
679 napi_typeof(env, data, &valueType);
680 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
681 LOGE("failed to get valid algo name!");
682 return false;
683 }
684 std::string mdName;
685 if (!GetStringFromJSParams(env, data, mdName)) {
686 LOGE("GetStringFromJSParams failed!");
687 return false;
688 }
689 HcfHmacParamsSpec *tmp = static_cast<HcfHmacParamsSpec *>(HcfMalloc(sizeof(HcfHmacParamsSpec), 0));
690 if (tmp == nullptr) {
691 LOGE("malloc hmac spec failed!");
692 return false;
693 }
694 char* mdNameCopy = static_cast<char*>(HcfMalloc(mdName.length() + 1, 0));
695 if (mdNameCopy == nullptr) {
696 LOGE("malloc mdName failed!");
697 HcfFree(tmp);
698 tmp = nullptr;
699 return false;
700 }
701 if (memcpy_s(mdNameCopy, mdName.length() + 1, mdName.c_str(), mdName.length() + 1) != EOK) {
702 LOGE("copy mdName failed!");
703 HcfFree(mdNameCopy);
704 mdNameCopy = nullptr;
705 HcfFree(tmp);
706 tmp = nullptr;
707 return false;
708 }
709 tmp->base.algName = algName;
710 tmp->mdName = mdNameCopy;
711 *paramsSpec = reinterpret_cast<HcfMacParamsSpec *>(tmp);
712 return true;
713 }
714
GetCmacParamsSpec(napi_env env,napi_value arg,const char * algName,HcfMacParamsSpec ** paramsSpec)715 static bool GetCmacParamsSpec(napi_env env, napi_value arg, const char *algName, HcfMacParamsSpec **paramsSpec)
716 {
717 napi_value data = nullptr;
718 napi_valuetype valueType = napi_undefined;
719 if ((env == nullptr) || (arg == nullptr) || (paramsSpec == nullptr)) {
720 LOGE("Invalid params!");
721 return false;
722 }
723
724 napi_status status = napi_get_named_property(env, arg, CIPHER_NAME.c_str(), &data);
725 napi_typeof(env, data, &valueType);
726 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
727 LOGE("failed to get valid algo name!");
728 return false;
729 }
730 std::string cipherName;
731 if (!GetStringFromJSParams(env, data, cipherName)) {
732 LOGE("GetStringFromJSParams failed!");
733 return false;
734 }
735 HcfCmacParamsSpec *tmp = nullptr;
736 tmp = static_cast<HcfCmacParamsSpec *>(HcfMalloc(sizeof(HcfCmacParamsSpec), 0));
737 if (tmp == nullptr) {
738 LOGE("malloc hmac spec failed!");
739 return false;
740 }
741 char* cipherNameCopy = static_cast<char*>(HcfMalloc(cipherName.length() + 1, 0));
742 if (cipherNameCopy == nullptr) {
743 LOGE("malloc cipherName failed!");
744 HcfFree(tmp);
745 tmp = nullptr;
746 return false;
747 }
748 if (memcpy_s(cipherNameCopy, cipherName.length() + 1, cipherName.c_str(), cipherName.length() + 1) != EOK) {
749 LOGE("copy cipherName failed!");
750 HcfFree(cipherNameCopy);
751 cipherNameCopy = nullptr;
752 HcfFree(tmp);
753 tmp = nullptr;
754 return false;
755 }
756 tmp->base.algName = algName;
757 tmp->cipherName = cipherNameCopy;
758 *paramsSpec = reinterpret_cast<HcfMacParamsSpec *>(tmp);
759 return true;
760 }
761
GetMacSpecFromJSParams(napi_env env,napi_value arg,HcfMacParamsSpec ** params)762 static bool GetMacSpecFromJSParams(napi_env env, napi_value arg, HcfMacParamsSpec **params)
763 {
764 napi_value data = nullptr;
765 napi_valuetype valueType = napi_undefined;
766 if ((env == nullptr) || (arg == nullptr) || (params == nullptr)) {
767 LOGE("Invalid params!");
768 return false;
769 }
770
771 napi_status status = napi_get_named_property(env, arg, ALGO_PARAMS.c_str(), &data);
772 napi_typeof(env, data, &valueType);
773 if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
774 LOGE("failed to get valid algo name!");
775 return false;
776 }
777 std::string algoName;
778 if (!GetStringFromJSParams(env, data, algoName)) {
779 LOGE("GetStringFromJSParams failed!");
780 return false;
781 }
782 if (algoName.compare("HMAC") == 0) {
783 return GetHmacParamsSpec(env, arg, algoName.c_str(), params);
784 } else if (algoName.compare("CMAC") == 0) {
785 return GetCmacParamsSpec(env, arg, algoName.c_str(), params);
786 } else {
787 LOGE("Not support that alg");
788 return false;
789 }
790 return true;
791 }
792
GetStringMacParams(napi_env env,napi_value argv,HcfMacParamsSpec ** paramsSpec)793 static bool GetStringMacParams(napi_env env, napi_value argv, HcfMacParamsSpec **paramsSpec)
794 {
795 if ((env == nullptr) || (paramsSpec == nullptr)) {
796 LOGE("Invalid params!");
797 return false;
798 }
799 std::string algoName;
800 if (!GetStringFromJSParams(env, argv, algoName)) {
801 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Failed to get algorithm."));
802 LOGE("Failed to get algorithm.");
803 return false;
804 }
805 *paramsSpec = reinterpret_cast<HcfMacParamsSpec *>(HcfMalloc(sizeof(HcfHmacParamsSpec), 0));
806 if (*paramsSpec == nullptr) {
807 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "Failed to allocate memory."));
808 LOGE("Failed to allocate memory.");
809 return false;
810 }
811 char* mdNameCopy = static_cast<char*>(HcfMalloc(algoName.length() + 1, 0));
812 if (mdNameCopy == nullptr) {
813 LOGE("malloc mdName failed!");
814 return false;
815 }
816 if (memcpy_s(mdNameCopy, algoName.length() + 1, algoName.c_str(), algoName.length() + 1) != EOK) {
817 LOGE("copy mdName failed!");
818 HcfFree(mdNameCopy);
819 mdNameCopy = nullptr;
820 return false;
821 }
822 (reinterpret_cast<HcfHmacParamsSpec *>(*paramsSpec))->base.algName = "HMAC";
823 (reinterpret_cast<HcfHmacParamsSpec *>(*paramsSpec))->mdName = mdNameCopy;
824 return true;
825 }
826
SetparamsSpec(napi_env env,napi_value argv,HcfMacParamsSpec ** paramsSpec)827 static bool SetparamsSpec(napi_env env, napi_value argv, HcfMacParamsSpec **paramsSpec)
828 {
829 napi_valuetype valueType;
830 napi_typeof(env, argv, &valueType);
831 if (valueType == napi_string) {
832 if (!GetStringMacParams(env, argv, paramsSpec)) {
833 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Failed to get mac params."));
834 LOGE("Failed to get mac params.");
835 return false;
836 }
837 } else {
838 if (!GetMacSpecFromJSParams(env, argv, paramsSpec)) {
839 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Failed to get mac params."));
840 LOGE("Failed to get mac params.");
841 return false;
842 }
843 }
844 return true;
845 }
846
CreateMac(napi_env env,napi_callback_info info)847 napi_value NapiMac::CreateMac(napi_env env, napi_callback_info info)
848 {
849 size_t expectedArgc = ARGS_SIZE_ONE;
850 size_t argc = expectedArgc;
851 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
852 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
853 if (argc != expectedArgc) {
854 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
855 LOGE("The input args num is invalid.");
856 return nullptr;
857 }
858
859 HcfMacParamsSpec *paramsSpec = nullptr;
860 if (!SetparamsSpec(env, argv[PARAM0], ¶msSpec)) {
861 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Failed to set mac params."));
862 LOGE("Failed to set mac params.");
863 return nullptr;
864 }
865
866 HcfMac *macObj = nullptr;
867 HcfResult res = HcfMacCreate(paramsSpec, &macObj);
868 if (res != HCF_SUCCESS) {
869 napi_throw(env, GenerateBusinessError(env, res, "create C obj failed."));
870 LOGE("create c macObj failed.");
871 FreeMacParams(paramsSpec);
872 paramsSpec = nullptr;
873 return nullptr;
874 }
875 napi_value napiAlgName = nullptr;
876 napi_create_string_utf8(env, paramsSpec->algName, NAPI_AUTO_LENGTH, &napiAlgName);
877 FreeMacParams(paramsSpec);
878 paramsSpec = nullptr;
879 napi_value instance = nullptr;
880 napi_value constructor = nullptr;
881 napi_get_reference_value(env, classRef_, &constructor);
882 napi_new_instance(env, constructor, argc, argv, &instance);
883 napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
884 NapiMac *macNapiObj = new (std::nothrow) NapiMac(macObj);
885 if (macNapiObj == nullptr) {
886 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "new mac napi obj failed."));
887 HcfObjDestroy(macObj);
888 macObj = nullptr;
889 LOGE("create napi obj failed");
890 return nullptr;
891 }
892
893 return NapiWrapMac(env, instance, macNapiObj);
894 }
895
DefineMacJSClass(napi_env env,napi_value exports)896 void NapiMac::DefineMacJSClass(napi_env env, napi_value exports)
897 {
898 napi_property_descriptor desc[] = {
899 DECLARE_NAPI_FUNCTION("createMac", NapiMac::CreateMac),
900 };
901 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
902 napi_property_descriptor classDesc[] = {
903 DECLARE_NAPI_FUNCTION("init", NapiMac::JsMacInit),
904 DECLARE_NAPI_FUNCTION("initSync", NapiMac::JsMacInitSync),
905 DECLARE_NAPI_FUNCTION("update", NapiMac::JsMacUpdate),
906 DECLARE_NAPI_FUNCTION("updateSync", NapiMac::JsMacUpdateSync),
907 DECLARE_NAPI_FUNCTION("doFinal", NapiMac::JsMacDoFinal),
908 DECLARE_NAPI_FUNCTION("doFinalSync", NapiMac::JsMacDoFinalSync),
909 DECLARE_NAPI_FUNCTION("getMacLength", NapiMac::JsGetMacLength),
910 };
911 napi_value constructor = nullptr;
912 napi_define_class(env, "Mac", NAPI_AUTO_LENGTH, MacConstructor, nullptr,
913 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
914 napi_create_reference(env, constructor, 1, &classRef_);
915 }
916 } // CryptoFramework
917 } // OHOS