• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_sm2_crypto_util.h"
17 
18 #include <string>
19 #include "securec.h"
20 #include "log.h"
21 #include "memory.h"
22 #include "napi_crypto_framework_defines.h"
23 #include "napi_utils.h"
24 
25 namespace OHOS {
26 namespace CryptoFramework {
NapiSm2CryptoUtil()27 NapiSm2CryptoUtil::NapiSm2CryptoUtil() {}
~NapiSm2CryptoUtil()28 NapiSm2CryptoUtil::~NapiSm2CryptoUtil() {}
29 
GetBlobFromNapi(napi_env env,napi_value arg,const std::string & name)30 static HcfBlob *GetBlobFromNapi(napi_env env, napi_value arg, const std::string &name)
31 {
32     // get uint8Array attribute
33     napi_value data = nullptr;
34     napi_valuetype valueType = napi_undefined;
35     napi_status status = napi_get_named_property(env, arg, name.c_str(), &data);
36     napi_typeof(env, data, &valueType);
37     if ((status != napi_ok) || (data == nullptr) || (valueType == napi_undefined)) {
38         LOGE("failed to get valid salt");
39         return nullptr;
40     }
41     return GetBlobFromNapiUint8Arr(env, data);
42 }
43 
GetSm2CipherTextSpecFromNapiValue(napi_env env,napi_value arg,Sm2CipherTextSpec ** returnSpec)44 static bool GetSm2CipherTextSpecFromNapiValue(napi_env env, napi_value arg, Sm2CipherTextSpec **returnSpec)
45 {
46     if ((env == nullptr) || (arg == nullptr) || (returnSpec == nullptr)) {
47         LOGE("Invalid params.");
48         return false;
49     }
50     Sm2CipherTextSpec *tempSpec = static_cast<Sm2CipherTextSpec *>(HcfMalloc(sizeof(Sm2CipherTextSpec), 0));
51     if (tempSpec == nullptr) {
52         LOGE("Malloc failed!");
53         return false;
54     }
55     napi_value xCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_UTIL_PARAM_X_COORDINATE);
56     napi_value yCoordinate = GetDetailAsyKeySpecValue(env, arg, SM2_UTIL_PARAM_Y_COORDINATE);
57     if ((xCoordinate == nullptr) || (yCoordinate == nullptr)) {
58         LOGE("Invalid params!");
59         DestroySm2CipherTextSpec(tempSpec);
60         return false;
61     }
62     bool ret = GetBigIntFromNapiValue(env, xCoordinate, &tempSpec->xCoordinate);
63     if (!ret) {
64         LOGE("Failed to get valid x coordinate.");
65         DestroySm2CipherTextSpec(tempSpec);
66         return false;
67     }
68     ret = GetBigIntFromNapiValue(env, yCoordinate, &tempSpec->yCoordinate);
69     if (!ret) {
70         LOGE("Failed to get valid y coordinate.");
71         DestroySm2CipherTextSpec(tempSpec);
72         return false;
73     }
74     HcfBlob *cipherTextBlob = GetBlobFromNapi(env, arg, SM2_UTIL_PARAM_CIPHER_TEXT_DATA);
75     if (cipherTextBlob == nullptr) {
76         LOGE("Failed to get valid cipherTextData.");
77         DestroySm2CipherTextSpec(tempSpec);
78         return false;
79     }
80     HcfBlob *hashDataBlob = GetBlobFromNapi(env, arg, SM2_UTIL_PARAM_HASH_DATA);
81     if (hashDataBlob == nullptr) {
82         LOGE("Failed to get valid hashData.");
83         HcfBlobDataFree(cipherTextBlob);
84         HCF_FREE_PTR(cipherTextBlob);
85         DestroySm2CipherTextSpec(tempSpec);
86         return false;
87     }
88     tempSpec->cipherTextData = *cipherTextBlob;
89     tempSpec->hashData = *hashDataBlob;
90     *returnSpec = tempSpec;
91     HCF_FREE_PTR(cipherTextBlob);
92     HCF_FREE_PTR(hashDataBlob);
93     return true;
94 }
95 
DealMode(napi_env env,napi_value arg,std::string & returnStr)96 static bool DealMode(napi_env env, napi_value arg, std::string &returnStr)
97 {
98     napi_valuetype valueType;
99     napi_typeof(env, arg, &valueType);
100     if (valueType == napi_null || valueType == napi_undefined) {
101         return true;
102     }
103     if (!GetStringFromJSParams(env, arg, returnStr)) {
104         return false;
105     }
106     return true;
107 }
108 
JsGenCipherTextBySpec(napi_env env,napi_callback_info info)109 napi_value NapiSm2CryptoUtil::JsGenCipherTextBySpec(napi_env env, napi_callback_info info)
110 {
111     size_t expectedArgc = PARAMS_NUM_TWO;
112     size_t argc = ARGS_SIZE_TWO;
113     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
114     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
115     // second attribute mode can be null
116     if ((argc != expectedArgc) && (argc != (expectedArgc - 1))) {
117         LOGE("The input args num is invalid.");
118         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
119         return nullptr;
120     }
121     Sm2CipherTextSpec *spec = nullptr;
122     if (!GetSm2CipherTextSpecFromNapiValue(env, argv[0], &spec)) {
123         LOGE("Failed to get spec.");
124         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get spec."));
125         return nullptr;
126     }
127     std::string dataMode;
128     if (argc == expectedArgc) {
129         if (!DealMode(env, argv[1], dataMode)) {
130             LOGE("Failed to get mode.");
131             DestroySm2CipherTextSpec(spec);
132             napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get mode."));
133             return nullptr;
134         }
135     }
136     HcfBlob *output = static_cast<HcfBlob *>(HcfMalloc(sizeof(HcfBlob), 0));
137     if (output == NULL) {
138         LOGE("Failed to allocate HcfBlob memory!");
139         DestroySm2CipherTextSpec(spec);
140         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "Failed to allocate memory."));
141         return nullptr;
142     }
143     HcfResult res = HcfGenCipherTextBySpec(spec, dataMode.c_str(), output);
144     if (res != HCF_SUCCESS) {
145         LOGE("Gen cipher text by spec fail.");
146         HcfFree(output);
147         output = nullptr;
148         DestroySm2CipherTextSpec(spec);
149         napi_throw(env, GenerateBusinessError(env, res, "gen cipher text by spec fail."));
150         return nullptr;
151     }
152     napi_value instance = ConvertBlobToNapiValue(env, output);
153     HcfBlobDataFree(output);
154     HcfFree(output);
155     output = nullptr;
156     DestroySm2CipherTextSpec(spec);
157     return instance;
158 }
159 
CheckSm2CipherTextSpec(Sm2CipherTextSpec * spec)160 static bool CheckSm2CipherTextSpec(Sm2CipherTextSpec *spec)
161 {
162     if (spec == nullptr) {
163         LOGE("Invalid spec!");
164         return false;
165     }
166     if (spec->xCoordinate.data == nullptr || spec->xCoordinate.len == 0) {
167         LOGE("Invalid xCoordinate!");
168         return false;
169     }
170     if (spec->yCoordinate.data == nullptr || spec->yCoordinate.len == 0) {
171         LOGE("Invalid yCoordinate!");
172         return false;
173     }
174     if (spec->cipherTextData.data == nullptr || spec->cipherTextData.len == 0) {
175         LOGE("Invalid cipherTextData!");
176         return false;
177     }
178     if (spec->hashData.data == nullptr || spec->hashData.len == 0) {
179         LOGE("Invalid hashData!");
180         return false;
181     }
182     return true;
183 }
184 
BuildBlobNapiValue(napi_env env,HcfBlob * blob,const char * name,napi_value * instance)185 static bool BuildBlobNapiValue(napi_env env, HcfBlob *blob, const char *name, napi_value *instance)
186 {
187     napi_value napiData = ConvertObjectBlobToNapiValue(env, blob);
188     napi_status status = napi_set_named_property(env, *instance, name, napiData);
189     if (status != napi_ok) {
190         LOGE("Build blob[napi_value] failed!");
191         return false;
192     }
193     return true;
194 }
195 
BuildSm2CipherTextSpecToNapiValue(napi_env env,Sm2CipherTextSpec * spec,napi_value * instance)196 static bool BuildSm2CipherTextSpecToNapiValue(napi_env env, Sm2CipherTextSpec *spec, napi_value *instance)
197 {
198     if (!BuildSetNamedProperty(env, &(spec->xCoordinate), SM2_UTIL_PARAM_X_COORDINATE.c_str(), instance)) {
199         LOGE("Build xCoordinate failed!");
200         return false;
201     }
202     if (!BuildSetNamedProperty(env, &(spec->yCoordinate), SM2_UTIL_PARAM_Y_COORDINATE.c_str(), instance)) {
203         LOGE("Build yCoordinate failed!");
204         return false;
205     }
206     if (!BuildBlobNapiValue(env, &(spec->cipherTextData), SM2_UTIL_PARAM_CIPHER_TEXT_DATA.c_str(), instance)) {
207         LOGE("Build cipherTextData failed!");
208         return false;
209     }
210     if (!BuildBlobNapiValue(env, &(spec->hashData), SM2_UTIL_PARAM_HASH_DATA.c_str(), instance)) {
211         LOGE("Build hashData failed!");
212         return false;
213     }
214     return true;
215 }
216 
ConvertSm2CipherTextSpecToNapiValue(napi_env env,Sm2CipherTextSpec * spec)217 static napi_value ConvertSm2CipherTextSpecToNapiValue(napi_env env, Sm2CipherTextSpec *spec)
218 {
219     if (!CheckSm2CipherTextSpec(spec)) {
220         LOGE("Invalid spec!");
221         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid spec!"));
222         return NapiGetNull(env);
223     }
224     napi_value instance;
225     napi_status status = napi_create_object(env, &instance);
226     if (status != napi_ok) {
227         LOGE("Create object failed!");
228         napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create object failed!"));
229         return NapiGetNull(env);
230     }
231     if (!BuildSm2CipherTextSpecToNapiValue(env, spec, &instance)) {
232         LOGE("Build object failed!");
233         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build object failed!"));
234         return NapiGetNull(env);
235     }
236     return instance;
237 }
238 
JsGetCipherTextSpec(napi_env env,napi_callback_info info)239 napi_value NapiSm2CryptoUtil::JsGetCipherTextSpec(napi_env env, napi_callback_info info)
240 {
241     size_t expectedArgc = PARAMS_NUM_TWO;
242     size_t argc = ARGS_SIZE_TWO;
243     napi_value argv[ARGS_SIZE_TWO] = { nullptr };
244     napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
245     // second attribute mode can be null
246     if ((argc != expectedArgc) && (argc != (expectedArgc - 1))) {
247         LOGE("The input args num is invalid.");
248         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
249         return nullptr;
250     }
251     HcfBlob *cipherText = GetBlobFromNapiDataBlob(env, argv[0]);
252     if (cipherText == nullptr) {
253         LOGE("Failed to get cipherText.");
254         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get cipherText."));
255         return nullptr;
256     }
257     std::string dataMode;
258     if (argc == expectedArgc) {
259         if (!DealMode(env, argv[1], dataMode)) {
260             LOGE("Failed to get mode.");
261             HcfBlobDataFree(cipherText);
262             HcfFree(cipherText);
263             cipherText = nullptr;
264             napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get mode."));
265             return nullptr;
266         }
267     }
268     Sm2CipherTextSpec *returnSpec = nullptr;
269     HcfResult res = HcfGetCipherTextSpec(cipherText, dataMode.c_str(), &returnSpec);
270     if (res != HCF_SUCCESS) {
271         LOGE("Get cipher text spec fail.");
272         HcfBlobDataFree(cipherText);
273         HcfFree(cipherText);
274         cipherText = nullptr;
275         napi_throw(env, GenerateBusinessError(env, res, "get cipher text spec fail."));
276         return nullptr;
277     }
278     napi_value instance = ConvertSm2CipherTextSpecToNapiValue(env, returnSpec);
279     DestroySm2CipherTextSpec(returnSpec);
280     HcfBlobDataFree(cipherText);
281     HcfFree(cipherText);
282     cipherText = nullptr;
283     return instance;
284 }
285 
Sm2CryptoUtilConstructor(napi_env env,napi_callback_info info)286 napi_value NapiSm2CryptoUtil::Sm2CryptoUtilConstructor(napi_env env, napi_callback_info info)
287 {
288     napi_value thisVar = nullptr;
289     size_t argc = ARGS_SIZE_ONE;
290     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
291     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
292     return thisVar;
293 }
294 
Sm2CryptoUtilConstructorClass(napi_env env)295 napi_value NapiSm2CryptoUtil::Sm2CryptoUtilConstructorClass(napi_env env)
296 {
297     napi_value cons = nullptr;
298     napi_property_descriptor clzDes[] = {
299         DECLARE_NAPI_STATIC_FUNCTION("genCipherTextBySpec", NapiSm2CryptoUtil::JsGenCipherTextBySpec),
300         DECLARE_NAPI_STATIC_FUNCTION("getCipherTextSpec", NapiSm2CryptoUtil::JsGetCipherTextSpec),
301     };
302     NAPI_CALL(env, napi_define_class(env, "SM2CryptoUtil", NAPI_AUTO_LENGTH,
303         NapiSm2CryptoUtil::Sm2CryptoUtilConstructor,
304         nullptr, sizeof(clzDes) / sizeof(clzDes[0]), clzDes, &cons));
305     return cons;
306 }
307 
DefineNapiSm2CryptoUtilJSClass(napi_env env,napi_value exports)308 void NapiSm2CryptoUtil::DefineNapiSm2CryptoUtilJSClass(napi_env env, napi_value exports)
309 {
310     napi_set_named_property(env, exports, "SM2CryptoUtil", NapiSm2CryptoUtil::Sm2CryptoUtilConstructorClass(env));
311 }
312 } // CryptoFramework
313 } // OHOS
314