• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "napi_mac.h"
17 
18 #include "securec.h"
19 #include "log.h"
20 #include "memory.h"
21 
22 #include "napi_sym_key.h"
23 #include "napi_utils.h"
24 #include "napi_crypto_framework_defines.h"
25 
26 namespace OHOS {
27 namespace CryptoFramework {
28 thread_local napi_ref NapiMac::classRef_ = nullptr;
29 
30 struct MacCtx {
31     napi_env env = nullptr;
32 
33     CfAsyncType asyncType = ASYNC_TYPE_CALLBACK;
34     napi_ref callback = nullptr;
35     napi_deferred deferred = nullptr;
36     napi_value promise = nullptr;
37     napi_async_work asyncWork = nullptr;
38 
39     NapiMac *macClass = nullptr;
40     std::string algoName = "";
41     HcfSymKey *symKey = nullptr;
42     HcfBlob *inBlob = nullptr;
43 
44     HcfResult errCode = HCF_SUCCESS;
45     const char *errMsg = nullptr;
46     HcfBlob *outBlob = nullptr;
47 };
48 
FreeCryptoFwkCtx(napi_env env,MacCtx * context)49 static void FreeCryptoFwkCtx(napi_env env, MacCtx *context)
50 {
51     if (context == nullptr) {
52         return;
53     }
54     if (context->asyncWork != nullptr) {
55         napi_delete_async_work(env, context->asyncWork);
56         context->asyncWork = nullptr;
57     }
58     if (context->callback != nullptr) {
59         napi_delete_reference(env, context->callback);
60         context->callback = nullptr;
61     }
62     context->symKey = nullptr;
63     if (context->inBlob != nullptr) {
64         HcfFree(context->inBlob->data);
65         context->inBlob->data = nullptr;
66         context->inBlob->len = 0;
67     }
68     if (context->outBlob != nullptr) {
69         HcfFree(context->outBlob->data);
70         context->outBlob->data = nullptr;
71         context->outBlob->len = 0;
72     }
73     HcfFree(context);
74 }
75 
ReturnCallbackResult(napi_env env,MacCtx * context,napi_value result)76 static void ReturnCallbackResult(napi_env env, MacCtx *context, napi_value result)
77 {
78     napi_value businessError = nullptr;
79     if (context->errCode != HCF_SUCCESS) {
80         businessError = GenerateBusinessError(env, context->errCode, context->errMsg, false);
81     }
82     napi_value params[ARGS_SIZE_TWO] = { businessError, result };
83 
84     napi_value func = nullptr;
85     napi_get_reference_value(env, context->callback, &func);
86 
87     napi_value recv = nullptr;
88     napi_value callFuncRet = nullptr;
89     napi_get_undefined(env, &recv);
90     napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
91 }
92 
ReturnPromiseResult(napi_env env,MacCtx * context,napi_value result)93 static void ReturnPromiseResult(napi_env env, MacCtx *context, napi_value result)
94 {
95     if (context->errCode == HCF_SUCCESS) {
96         napi_resolve_deferred(env, context->deferred, result);
97     } else {
98         napi_reject_deferred(env, context->deferred,
99             GenerateBusinessError(env, context->errCode, context->errMsg, false));
100     }
101 }
102 
CreateCallbackAndPromise(napi_env env,MacCtx * context,size_t argc,size_t maxCount,napi_value callbackValue)103 static bool CreateCallbackAndPromise(napi_env env, MacCtx *context, size_t argc,
104     size_t maxCount, napi_value callbackValue)
105 {
106     context->asyncType = (argc == maxCount) ? ASYNC_TYPE_CALLBACK : ASYNC_TYPE_PROMISE;
107     if (context->asyncType == ASYNC_TYPE_CALLBACK) {
108         if (!GetCallbackFromJSParams(env, callbackValue, &context->callback, false)) {
109             LOGE("get callback failed!");
110             return false;
111         }
112     } else {
113         napi_create_promise(env, &context->deferred, &context->promise);
114     }
115     return true;
116 }
117 
NapiMac(HcfMac * macObj)118 NapiMac::NapiMac(HcfMac *macObj)
119 {
120     this->macObj_ = macObj;
121 }
122 
~NapiMac()123 NapiMac::~NapiMac()
124 {
125     HcfObjDestroy(this->macObj_);
126 }
127 
MacInitExecute(napi_env env,void * data)128 static void MacInitExecute(napi_env env, void *data)
129 {
130     LOGI("enter MacInitExecute ...");
131     MacCtx *context = static_cast<MacCtx *>(data);
132     NapiMac *macClass = context->macClass;
133     HcfMac *macObj = macClass->GetMac();
134     HcfSymKey *symKey = context->symKey;
135     context->errCode = macObj->init(macObj, symKey);
136     if (context->errCode != HCF_SUCCESS) {
137         LOGE("init failed!");
138         context->errMsg = "init failed";
139     }
140 }
141 
MacInitComplete(napi_env env,napi_status status,void * data)142 static void MacInitComplete(napi_env env, napi_status status, void *data)
143 {
144     MacCtx *context = static_cast<MacCtx *>(data);
145     napi_value nullInstance = nullptr;
146     napi_get_null(env, &nullInstance);
147     if (context->asyncType == ASYNC_TYPE_CALLBACK) {
148         ReturnCallbackResult(env, context, nullInstance);
149     } else {
150         ReturnPromiseResult(env, context, nullInstance);
151     }
152     FreeCryptoFwkCtx(env, context);
153 }
154 
MacUpdateExecute(napi_env env,void * data)155 static void MacUpdateExecute(napi_env env, void *data)
156 {
157     MacCtx *context = static_cast<MacCtx *>(data);
158     NapiMac *macClass = context->macClass;
159     HcfMac *macObj = macClass->GetMac();
160     HcfBlob *inBlob = reinterpret_cast<HcfBlob *>(context->inBlob);
161     context->errCode = macObj->update(macObj, inBlob);
162     if (context->errCode != HCF_SUCCESS) {
163         LOGE("update failed!");
164         context->errMsg = "update failed";
165     }
166 }
167 
MacUpdateComplete(napi_env env,napi_status status,void * data)168 static void MacUpdateComplete(napi_env env, napi_status status, void *data)
169 {
170     MacCtx *context = static_cast<MacCtx *>(data);
171     napi_value nullInstance = nullptr;
172     napi_get_null(env, &nullInstance);
173     if (context->asyncType == ASYNC_TYPE_CALLBACK) {
174         ReturnCallbackResult(env, context, nullInstance);
175     } else {
176         ReturnPromiseResult(env, context, nullInstance);
177     }
178     FreeCryptoFwkCtx(env, context);
179 }
180 
MacDoFinalExecute(napi_env env,void * data)181 static void MacDoFinalExecute(napi_env env, void *data)
182 {
183     MacCtx *context = static_cast<MacCtx *>(data);
184     NapiMac *macClass = context->macClass;
185     HcfMac *macObj = macClass->GetMac();
186     HcfBlob *outBlob = reinterpret_cast<HcfBlob *>(HcfMalloc(sizeof(HcfBlob), 0));
187     if (outBlob == nullptr) {
188         LOGE("outBlob is null!");
189         context->errCode = HCF_ERR_MALLOC;
190         context->errMsg = "malloc data blob failed";
191         return;
192     }
193     context->errCode = macObj->doFinal(macObj, outBlob);
194     if (context->errCode != HCF_SUCCESS) {
195         LOGE("doFinal failed!");
196         context->errMsg = "doFinal failed";
197         return;
198     }
199     context->outBlob = outBlob;
200 }
201 
MacDoFinalComplete(napi_env env,napi_status status,void * data)202 static void MacDoFinalComplete(napi_env env, napi_status status, void *data)
203 {
204     LOGI("enter MacDoFinalComplete ...");
205     MacCtx *context = static_cast<MacCtx *>(data);
206     napi_value returnOutBlob = ConvertBlobToNapiValue(env, context->outBlob);
207     if (returnOutBlob == nullptr) {
208         LOGE("returnOutBlob is nullptr!");
209         returnOutBlob = NapiGetNull(env);
210     }
211     if (context->asyncType == ASYNC_TYPE_CALLBACK) {
212         ReturnCallbackResult(env, context, returnOutBlob);
213     } else {
214         ReturnPromiseResult(env, context, returnOutBlob);
215     }
216     FreeCryptoFwkCtx(env, context);
217 }
218 
MacInit(napi_env env,napi_callback_info info)219 napi_value NapiMac::MacInit(napi_env env, napi_callback_info info)
220 {
221     size_t expectedArgsCount = ARGS_SIZE_TWO;
222     size_t argc = expectedArgsCount;
223     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
224     napi_value thisVar = nullptr;
225     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
226     if (!CheckArgsCount(env, argc, ARGS_SIZE_TWO, false, false)) {
227         return nullptr;
228     }
229     MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
230     if (context == nullptr) {
231         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed", false));
232         LOGE("malloc context failed!");
233         return nullptr;
234     }
235     context->macClass = this;
236     NapiSymKey *symKey = nullptr;
237     napi_unwrap(env, argv[PARAM0], reinterpret_cast<void **>(&symKey));
238     if (symKey == nullptr) {
239         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "symKey is null", false));
240         LOGE("symKey is null!");
241         FreeCryptoFwkCtx(env, context);
242         return nullptr;
243     }
244     context->symKey = symKey->GetSymKey();
245     context->asyncType = (argc == expectedArgsCount) ? ASYNC_TYPE_CALLBACK : ASYNC_TYPE_PROMISE;
246     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, argv[PARAM1])) {
247         FreeCryptoFwkCtx(env, context);
248         return nullptr;
249     }
250     napi_create_async_work(
251         env, nullptr, GetResourceName(env, "Init"),
252         MacInitExecute,
253         MacInitComplete,
254         static_cast<void *>(context),
255         &context->asyncWork);
256     napi_queue_async_work(env, context->asyncWork);
257     if (context->asyncType == ASYNC_TYPE_PROMISE) {
258         return context->promise;
259     } else {
260         return NapiGetNull(env);
261     }
262 }
263 
MacUpdate(napi_env env,napi_callback_info info)264 napi_value NapiMac::MacUpdate(napi_env env, napi_callback_info info)
265 {
266     size_t expectedArgsCount = ARGS_SIZE_TWO;
267     size_t argc = expectedArgsCount;
268     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
269     napi_value thisVar = nullptr;
270     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
271     if (!CheckArgsCount(env, argc, ARGS_SIZE_TWO, false, false)) {
272         return nullptr;
273     }
274     MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
275     if (context == nullptr) {
276         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed", false));
277         LOGE("malloc context failed!");
278         return nullptr;
279     }
280     context->macClass = this;
281     context->inBlob = GetBlobFromNapiValue(env, argv[PARAM0]);
282     if (context->inBlob == nullptr) {
283         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "inBlob is null", false));
284         LOGE("inBlob is null!");
285         return nullptr;
286     }
287     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_TWO, argv[PARAM1])) {
288         FreeCryptoFwkCtx(env, context);
289         return nullptr;
290     }
291     napi_create_async_work(
292         env, nullptr, GetResourceName(env, "MacUpate"),
293         MacUpdateExecute,
294         MacUpdateComplete,
295         static_cast<void *>(context),
296         &context->asyncWork);
297     napi_queue_async_work(env, context->asyncWork);
298     if (context->asyncType == ASYNC_TYPE_PROMISE) {
299         return context->promise;
300     } else {
301         return NapiGetNull(env);
302     }
303 }
304 
MacDoFinal(napi_env env,napi_callback_info info)305 napi_value NapiMac::MacDoFinal(napi_env env, napi_callback_info info)
306 {
307     size_t expectedArgsCount = ARGS_SIZE_ONE;
308     size_t argc = expectedArgsCount;
309     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
310     napi_value thisVar = nullptr;
311     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
312     if (!CheckArgsCount(env, argc, ARGS_SIZE_ONE, false, false)) {
313         return nullptr;
314     }
315     MacCtx *context = static_cast<MacCtx *>(HcfMalloc(sizeof(MacCtx), 0));
316     if (context == nullptr) {
317         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "malloc context failed", false));
318         LOGE("malloc context failed!");
319         return nullptr;
320     }
321     context->macClass = this;
322     context->asyncType = (argc == expectedArgsCount) ? ASYNC_TYPE_CALLBACK : ASYNC_TYPE_PROMISE;
323     if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_ONE, argv[PARAM0])) {
324         FreeCryptoFwkCtx(env, context);
325         return nullptr;
326     }
327     napi_create_async_work(
328         env, nullptr, GetResourceName(env, "MacDoFinal"),
329         MacDoFinalExecute,
330         MacDoFinalComplete,
331         static_cast<void *>(context),
332         &context->asyncWork);
333     napi_queue_async_work(env, context->asyncWork);
334     if (context->asyncType == ASYNC_TYPE_PROMISE) {
335         return context->promise;
336     } else {
337         return NapiGetNull(env);
338     }
339 }
340 
GetMacLength(napi_env env,napi_callback_info info)341 napi_value NapiMac::GetMacLength(napi_env env, napi_callback_info info)
342 {
343     HcfMac *macObj = GetMac();
344     uint32_t retLen = macObj->getMacLength(macObj);
345     napi_value napiLen = nullptr;
346     napi_create_uint32(env, retLen, &napiLen);
347     return napiLen;
348 }
349 
NapiMacInit(napi_env env,napi_callback_info info)350 static napi_value NapiMacInit(napi_env env, napi_callback_info info)
351 {
352     napi_value thisVar = nullptr;
353     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
354     NapiMac *macObj = nullptr;
355     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&macObj));
356     if (macObj == nullptr) {
357         LOGE("macObj is nullptr!");
358         return NapiGetNull(env);
359     }
360     return macObj->MacInit(env, info);
361 }
362 
NapiMacUpdate(napi_env env,napi_callback_info info)363 static napi_value NapiMacUpdate(napi_env env, napi_callback_info info)
364 {
365     napi_value thisVar = nullptr;
366     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
367     NapiMac *macObj = nullptr;
368     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&macObj));
369     if (macObj == nullptr) {
370         LOGE("macObj is nullptr!");
371         return NapiGetNull(env);
372     }
373     return macObj->MacUpdate(env, info);
374 }
375 
NapiMacDoFinal(napi_env env,napi_callback_info info)376 static napi_value NapiMacDoFinal(napi_env env, napi_callback_info info)
377 {
378     napi_value thisVar = nullptr;
379     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
380     NapiMac *macObj = nullptr;
381     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&macObj));
382     if (macObj == nullptr) {
383         LOGE("macObj is nullptr!");
384         return NapiGetNull(env);
385     }
386     return macObj->MacDoFinal(env, info);
387 }
388 
NapiGetMacLength(napi_env env,napi_callback_info info)389 static napi_value NapiGetMacLength(napi_env env, napi_callback_info info)
390 {
391     napi_value thisVar = nullptr;
392     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
393     NapiMac *macObj = nullptr;
394     napi_unwrap(env, thisVar, reinterpret_cast<void **>(&macObj));
395     if (macObj == nullptr) {
396         LOGE("macObj is nullptr!");
397         return NapiGetNull(env);
398     }
399     return macObj->GetMacLength(env, info);
400 }
401 
MacConstructor(napi_env env,napi_callback_info info)402 napi_value NapiMac::MacConstructor(napi_env env, napi_callback_info info)
403 {
404     napi_value thisVar = nullptr;
405     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
406     return thisVar;
407 }
408 
CreateMac(napi_env env,napi_callback_info info)409 napi_value NapiMac::CreateMac(napi_env env, napi_callback_info info)
410 {
411     size_t expectedArgc = ARGS_SIZE_ONE;
412     size_t argc = expectedArgc;
413     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
414     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
415     if (argc != expectedArgc) {
416         LOGE("The input args num is invalid.");
417         return nullptr;
418     }
419     std::string algoName;
420     if (!GetStringFromJSParams(env, argv[PARAM0], algoName, false)) {
421         LOGE("Failed to get algorithm.");
422         return nullptr;
423     }
424     HcfMac *macObj = nullptr;
425     HcfResult res = HcfMacCreate(algoName.c_str(), &macObj);
426     if (res != HCF_SUCCESS) {
427         napi_throw(env, GenerateBusinessError(env, res, "create C obj failed.", false));
428         LOGE("create c macObj failed.");
429         return nullptr;
430     }
431     napi_value napiAlgName = nullptr;
432     napi_create_string_utf8(env, algoName.c_str(), NAPI_AUTO_LENGTH, &napiAlgName);
433     napi_value instance = nullptr;
434     napi_value constructor = nullptr;
435     napi_get_reference_value(env, classRef_, &constructor);
436     napi_new_instance(env, constructor, argc, argv, &instance);
437     napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
438     NapiMac *macNapiObj = new (std::nothrow) NapiMac(macObj);
439     if (macNapiObj == nullptr) {
440         LOGE("create napi obj failed");
441         return nullptr;
442     }
443     napi_wrap(
444         env, instance, macNapiObj,
445         [](napi_env env, void *data, void *hint) {
446             NapiMac *mac = static_cast<NapiMac *>(data);
447             delete mac;
448             return;
449         },
450         nullptr,
451         nullptr);
452     return instance;
453 }
454 
DefineMacJSClass(napi_env env,napi_value exports)455 void NapiMac::DefineMacJSClass(napi_env env, napi_value exports)
456 {
457     napi_property_descriptor desc[] = {
458         DECLARE_NAPI_FUNCTION("createMac", CreateMac),
459     };
460     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
461     napi_property_descriptor classDesc[] = {
462         DECLARE_NAPI_FUNCTION("init", NapiMacInit),
463         DECLARE_NAPI_FUNCTION("update", NapiMacUpdate),
464         DECLARE_NAPI_FUNCTION("doFinal", NapiMacDoFinal),
465         DECLARE_NAPI_FUNCTION("getMacLength", NapiGetMacLength),
466     };
467     napi_value constructor = nullptr;
468     napi_define_class(env, "Mac", NAPI_AUTO_LENGTH, MacConstructor, nullptr,
469         sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
470     napi_create_reference(env, constructor, 1, &classRef_);
471 }
472 } // CryptoFramework
473 } // OHOS