1 /*
2 * Copyright (C) 2023-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_ecc_key_util.h"
17 #include "securec.h"
18 #include "detailed_ecc_key_params.h"
19 #include "log.h"
20
21 #include "memory.h"
22 #include "napi_crypto_framework_defines.h"
23 #include "napi_utils.h"
24 #include "napi_key_pair.h"
25 #include "napi_pri_key.h"
26 #include "napi_pub_key.h"
27 #include "utils.h"
28
29 namespace OHOS {
30 namespace CryptoFramework {
NapiECCKeyUtil()31 NapiECCKeyUtil::NapiECCKeyUtil() {}
32
~NapiECCKeyUtil()33 NapiECCKeyUtil::~NapiECCKeyUtil() {}
34
CheckEccCommonParamSpecBase(napi_env env,HcfEccCommParamsSpec * blob)35 static bool CheckEccCommonParamSpecBase(napi_env env, HcfEccCommParamsSpec *blob)
36 {
37 if (blob->a.data == nullptr || blob->a.len == 0) {
38 LOGE("Invalid blob a!");
39 return false;
40 }
41 if (blob->b.data == nullptr || blob->b.len == 0) {
42 LOGE("Invalid blob b!");
43 return false;
44 }
45 if (blob->n.data == nullptr || blob->n.len == 0) {
46 LOGE("Invalid blob n!");
47 return false;
48 }
49 return true;
50 }
51
CheckEccCommonParamSpec(napi_env env,HcfEccCommParamsSpec * blob)52 static bool CheckEccCommonParamSpec(napi_env env, HcfEccCommParamsSpec *blob)
53 {
54 if (blob == nullptr) {
55 LOGE("Invalid blob!");
56 return false;
57 }
58 if (!CheckEccCommonParamSpecBase(env, blob)) {
59 LOGE("Invalid blob ecc commonParamSpec base!");
60 return false;
61 }
62 if (blob->base.algName == nullptr) {
63 LOGE("Invalid blob algName!");
64 return false;
65 }
66 if (blob->field == nullptr) {
67 LOGE("Invalid blob field!");
68 return false;
69 }
70 if (blob->field->fieldType == nullptr) {
71 LOGE("Invalid blob fieldType!");
72 return false;
73 }
74 if (blob->g.x.data == nullptr || blob->g.x.len == 0) {
75 LOGE("Invalid blob point x!");
76 return false;
77 }
78 if (blob->g.y.data == nullptr || blob->g.y.len == 0) {
79 LOGE("Invalid blob point y!");
80 return false;
81 }
82 HcfECFieldFp *tmpField = reinterpret_cast<HcfECFieldFp *>(blob->field);
83 if (tmpField->p.data == nullptr || tmpField->p.len == 0) {
84 LOGE("Invalid blob p!");
85 return false;
86 }
87 return true;
88 }
89
ConvertEccCommonParamFieldFpToNapiValue(napi_env env,HcfEccCommParamsSpec * blob)90 static napi_value ConvertEccCommonParamFieldFpToNapiValue(napi_env env, HcfEccCommParamsSpec *blob)
91 {
92 napi_value fieldFp;
93 napi_value fieldType;
94 napi_status status = napi_create_object(env, &fieldFp);
95 if (status != napi_ok) {
96 LOGE("create fieldFp failed!");
97 return NapiGetNull(env);
98 }
99 size_t fieldTypeLength = HcfStrlen(blob->field->fieldType);
100 if (!fieldTypeLength) {
101 LOGE("fieldType is empty!");
102 return NapiGetNull(env);
103 }
104 status = napi_create_string_utf8(env, blob->field->fieldType, fieldTypeLength, &fieldType);
105 if (status != napi_ok) {
106 LOGE("create object failed!");
107 return NapiGetNull(env);
108 }
109 status = napi_set_named_property(env, fieldFp, "fieldType", fieldType);
110 if (status != napi_ok) {
111 LOGE("create object failed!");
112 return NapiGetNull(env);
113 }
114 HcfECFieldFp *tmpField = reinterpret_cast<HcfECFieldFp *>(blob->field);
115 napi_value p = ConvertBigIntToNapiValue(env, &(tmpField->p));
116 if (p == nullptr) {
117 LOGE("p is null!");
118 return NapiGetNull(env);
119 }
120 status = napi_set_named_property(env, fieldFp, "p", p);
121 if (status != napi_ok) {
122 LOGE("create object failed!");
123 return NapiGetNull(env);
124 }
125 return fieldFp;
126 }
127
IsNapiNull(napi_env env,napi_value value)128 static bool IsNapiNull(napi_env env, napi_value value)
129 {
130 napi_valuetype valueType;
131 napi_typeof(env, value, &valueType);
132 return (valueType == napi_null);
133 }
134
ConvertEccPointToNapiValue(napi_env env,HcfPoint * p)135 static napi_value ConvertEccPointToNapiValue(napi_env env, HcfPoint *p)
136 {
137 if (p == nullptr) {
138 LOGE("Invalid point data!");
139 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid point data!"));
140 return nullptr;
141 }
142
143 napi_value point;
144 napi_status status = napi_create_object(env, &point);
145 if (status != napi_ok) {
146 LOGE("create object failed!");
147 napi_throw(env, GenerateBusinessError(env, HCF_ERR_MALLOC, "create object failed!"));
148 return nullptr;
149 }
150
151 napi_value x = ConvertBigIntToNapiValue(env, &(p->x));
152 if (x == nullptr || IsNapiNull(env, x)) {
153 LOGE("Failed to convert x to NapiValue!");
154 return nullptr;
155 }
156
157 napi_value y = ConvertBigIntToNapiValue(env, &(p->y));
158 if (y == nullptr || IsNapiNull(env, y)) {
159 LOGE("Failed to convert y to NapiValue!");
160 return nullptr;
161 }
162
163 status = napi_set_named_property(env, point, "x", x);
164 if (status != napi_ok) {
165 LOGE("set x property failed!");
166 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "set x property failed!"));
167 return nullptr;
168 }
169
170 status = napi_set_named_property(env, point, "y", y);
171 if (status != napi_ok) {
172 LOGE("set y property failed!");
173 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "set y property failed!"));
174 return nullptr;
175 }
176
177 return point;
178 }
179
ConvertEccCommonParamPointToNapiValue(napi_env env,HcfEccCommParamsSpec * blob)180 static napi_value ConvertEccCommonParamPointToNapiValue(napi_env env, HcfEccCommParamsSpec *blob)
181 {
182 napi_value point;
183 napi_status status = napi_create_object(env, &point);
184 if (status != napi_ok) {
185 LOGE("create object failed!");
186 return NapiGetNull(env);
187 }
188 napi_value x = ConvertBigIntToNapiValue(env, &(blob->g.x));
189 if (x == nullptr) {
190 LOGE("x is null!");
191 return NapiGetNull(env);
192 }
193
194 napi_value y = ConvertBigIntToNapiValue(env, &(blob->g.y));
195 if (y == nullptr) {
196 LOGE("y is null!");
197 return NapiGetNull(env);
198 }
199 status = napi_set_named_property(env, point, "x", x);
200 if (status != napi_ok) {
201 LOGE("create object failed!");
202 return NapiGetNull(env);
203 }
204 status = napi_set_named_property(env, point, "y", y);
205 if (status != napi_ok) {
206 LOGE("create object failed!");
207 return NapiGetNull(env);
208 }
209 return point;
210 }
211
BuildIntancePartertoNapiValueSon(napi_env env,napi_status status,HcfEccCommParamsSpec * blob,napi_value * instance)212 static bool BuildIntancePartertoNapiValueSon(napi_env env, napi_status status, HcfEccCommParamsSpec *blob,
213 napi_value *instance)
214 {
215 if (!BuildSetNamedProperty(env, &(blob->a), "a", instance)) {
216 LOGE("build setNamedProperty a failed!");
217 return false;
218 }
219 if (!BuildSetNamedProperty(env, &(blob->b), "b", instance)) {
220 LOGE("build setNamedProperty b failed!");
221 return false;
222 }
223 if (!BuildSetNamedProperty(env, &(blob->n), "n", instance)) {
224 LOGE("build setNamedProperty n failed!");
225 return false;
226 }
227 napi_value h;
228 status = napi_create_int32(env, blob->h, &h);
229 if (status != napi_ok) {
230 LOGE("create h uint32 failed!");
231 return false;
232 }
233 status = napi_set_named_property(env, *instance, "h", h);
234 if (status != napi_ok) {
235 LOGE("create h uint32 failed!");
236 return false;
237 }
238 return true;
239 }
240
BuildInstanceParterToNapiValue(napi_env env,HcfEccCommParamsSpec * blob,napi_value * instance)241 static bool BuildInstanceParterToNapiValue(napi_env env, HcfEccCommParamsSpec *blob, napi_value *instance)
242 {
243 napi_value algName;
244 size_t algNameLength = HcfStrlen(blob->base.algName);
245 if (!algNameLength) {
246 LOGE("algName is empty!");
247 return false;
248 }
249 napi_status status = napi_create_string_utf8(env, blob->base.algName, algNameLength, &algName);
250 if (status != napi_ok) {
251 LOGE("create algName failed!");
252 return false;
253 }
254 napi_value specType;
255 status = napi_create_uint32(env, blob->base.specType, &specType);
256 if (status != napi_ok) {
257 LOGE("create uint32 failed!");
258 return false;
259 }
260 status = napi_set_named_property(env, *instance, "algName", algName);
261 if (status != napi_ok) {
262 LOGE("create set algName failed!");
263 return false;
264 }
265 status = napi_set_named_property(env, *instance, "specType", specType);
266 if (status != napi_ok) {
267 LOGE("create set specType failed!");
268 return false;
269 }
270 if (!BuildIntancePartertoNapiValueSon(env, status, blob, instance)) {
271 LOGE("create intance parter napi value failed!");
272 return false;
273 }
274 return true;
275 }
276
ConvertEccCommParamsSpecToNapiValue(napi_env env,HcfEccCommParamsSpec * blob)277 static napi_value ConvertEccCommParamsSpecToNapiValue(napi_env env, HcfEccCommParamsSpec *blob)
278 {
279 if (!CheckEccCommonParamSpec(env, blob)) {
280 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "Invalid blob!"));
281 LOGE("Invalid blob!");
282 return NapiGetNull(env);
283 }
284 napi_value instance;
285 napi_status status = napi_create_object(env, &instance);
286 if (status != napi_ok) {
287 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create object failed!"));
288 LOGE("create object failed!");
289 return NapiGetNull(env);
290 }
291 napi_value point = ConvertEccCommonParamPointToNapiValue(env, blob);
292 if (point == NapiGetNull(env)) {
293 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "covert commonParam failed!"));
294 LOGE("Covert commonParam failed!");
295 return NapiGetNull(env);
296 }
297 napi_value field = ConvertEccCommonParamFieldFpToNapiValue(env, blob);
298 if (field == NapiGetNull(env)) {
299 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "covert commonParam fieldFp failed!"));
300 LOGE("Covert commonParam fieldFp failed!");
301 return NapiGetNull(env);
302 }
303 if (!BuildInstanceParterToNapiValue(env, blob, &instance)) {
304 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "build object failed!"));
305 LOGE("Build object failed!");
306 return NapiGetNull(env);
307 }
308 status = napi_set_named_property(env, instance, "field", field);
309 if (status != napi_ok) {
310 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "set fieldFp failed!"));
311 LOGE("set fieldFp failed!");
312 return NapiGetNull(env);
313 }
314 status = napi_set_named_property(env, instance, "g", point);
315 if (status != napi_ok) {
316 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "set g failed!"));
317 LOGE("set g failed!");
318 return NapiGetNull(env);
319 }
320 return instance;
321 }
322
JsGenECCCommonParamsSpec(napi_env env,napi_callback_info info)323 napi_value NapiECCKeyUtil::JsGenECCCommonParamsSpec(napi_env env, napi_callback_info info)
324 {
325 size_t expectedArgc = ARGS_SIZE_ONE;
326 size_t argc = ARGS_SIZE_ONE;
327 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
328 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
329
330 if (argc != expectedArgc) {
331 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
332 LOGE("The input args num is invalid.");
333 return nullptr;
334 }
335
336 std::string algName;
337 if (!GetStringFromJSParams(env, argv[0], algName)) {
338 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get algoName."));
339 LOGE("failed to get algoName.");
340 return NapiGetNull(env);
341 }
342
343 HcfEccCommParamsSpec *eccCommParamsSpec = nullptr;
344 if (HcfEccKeyUtilCreate(algName.c_str(), &eccCommParamsSpec) != HCF_SUCCESS) {
345 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "create c generator fail."));
346 LOGE("create c generator fail.");
347 return NapiGetNull(env);
348 }
349 napi_value instance = ConvertEccCommParamsSpecToNapiValue(env, eccCommParamsSpec);
350 FreeEccCommParamsSpec(eccCommParamsSpec);
351 HcfFree(eccCommParamsSpec);
352 eccCommParamsSpec = nullptr;
353 return instance;
354 }
355
JsConvertPoint(napi_env env,napi_callback_info info)356 napi_value NapiECCKeyUtil::JsConvertPoint(napi_env env, napi_callback_info info)
357 {
358 size_t expectedArgc = ARGS_SIZE_TWO;
359 size_t argc = ARGS_SIZE_TWO;
360 napi_value argv[ARGS_SIZE_TWO] = { nullptr };
361 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
362
363 if (argc != expectedArgc) {
364 LOGE("The input args num is invalid.");
365 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
366 return nullptr;
367 }
368
369 std::string curveName;
370 if (!GetStringFromJSParams(env, argv[PARAM0], curveName)) {
371 LOGE("failed to get curveName.");
372 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get curveName."));
373 return nullptr;
374 }
375
376 HcfBlob *pointBlob = GetBlobFromNapiUint8Arr(env, argv[PARAM1]);
377 if (pointBlob == nullptr) {
378 LOGE("failed to get point blob.");
379 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get point blob."));
380 return nullptr;
381 }
382
383 HcfPoint point;
384 HcfResult ret = HcfConvertPoint(curveName.c_str(), pointBlob, &point);
385 if (ret != HCF_SUCCESS) {
386 LOGE("failed to convert point.");
387 HcfBlobDataFree(pointBlob);
388 HcfFree(pointBlob);
389 pointBlob = nullptr;
390 napi_throw(env, GenerateBusinessError(env, ret, "failed to convert point."));
391 return nullptr;
392 }
393 napi_value instance = ConvertEccPointToNapiValue(env, &point);
394 FreeEcPointMem(&point);
395 HcfBlobDataFree(pointBlob);
396 HcfFree(pointBlob);
397 pointBlob = nullptr;
398 return instance;
399 }
400
JsGetEncodedPoint(napi_env env,napi_callback_info info)401 napi_value NapiECCKeyUtil::JsGetEncodedPoint(napi_env env, napi_callback_info info)
402 {
403 size_t expectedArgc = ARGS_SIZE_THREE;
404 size_t argc = ARGS_SIZE_THREE;
405 napi_value argv[ARGS_SIZE_THREE] = { nullptr };
406 napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
407
408 if (argc != expectedArgc) {
409 LOGE("The input args num is invalid.");
410 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
411 return nullptr;
412 }
413
414 std::string curveName;
415 if (!GetStringFromJSParams(env, argv[PARAM0], curveName)) {
416 LOGE("failed to get curveName.");
417 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get curveName."));
418 return nullptr;
419 }
420
421 HcfPoint point;
422 if (!GetPointFromNapiValue(env, argv[PARAM1], &point)) {
423 LOGE("failed to get point.");
424 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get point."));
425 return nullptr;
426 }
427
428 std::string format;
429 if (!GetStringFromJSParams(env, argv[PARAM2], format)) {
430 LOGE("failed to get format.");
431 FreeEcPointMem(&point);
432 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get format."));
433 return nullptr;
434 }
435
436 HcfBlob returnBlob;
437 HcfResult ret = HcfGetEncodedPoint(curveName.c_str(), &point, format.c_str(), &returnBlob);
438 if (ret != HCF_SUCCESS) {
439 LOGE("fail to get point data.");
440 FreeEcPointMem(&point);
441 napi_throw(env, GenerateBusinessError(env, ret, "failed to get point data."));
442 return nullptr;
443 }
444 napi_value instance = ConvertObjectBlobToNapiValue(env, &returnBlob);
445 FreeEcPointMem(&point);
446 HcfBlobDataFree(&returnBlob);
447 return instance;
448 }
449
ECCKeyUtilConstructor(napi_env env,napi_callback_info info)450 napi_value NapiECCKeyUtil::ECCKeyUtilConstructor(napi_env env, napi_callback_info info)
451 {
452 napi_value thisVar = nullptr;
453 size_t argc = ARGS_SIZE_ONE;
454 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
455 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr));
456 return thisVar;
457 }
458
GenECCCommonParamSpec(napi_env env)459 napi_value NapiECCKeyUtil::GenECCCommonParamSpec(napi_env env)
460 {
461 napi_value cons = nullptr;
462 napi_property_descriptor clzDes[] = {
463 DECLARE_NAPI_STATIC_FUNCTION("genECCCommonParamsSpec", NapiECCKeyUtil::JsGenECCCommonParamsSpec),
464 DECLARE_NAPI_STATIC_FUNCTION("convertPoint", NapiECCKeyUtil::JsConvertPoint),
465 DECLARE_NAPI_STATIC_FUNCTION("getEncodedPoint", NapiECCKeyUtil::JsGetEncodedPoint),
466 };
467 NAPI_CALL(env, napi_define_class(env, "ECCKeyUtil", NAPI_AUTO_LENGTH, NapiECCKeyUtil::ECCKeyUtilConstructor,
468 nullptr, sizeof(clzDes) / sizeof(clzDes[0]), clzDes, &cons));
469 return cons;
470 }
471
DefineNapiECCKeyUtilJSClass(napi_env env,napi_value exports)472 void NapiECCKeyUtil::DefineNapiECCKeyUtilJSClass(napi_env env, napi_value exports)
473 {
474 napi_set_named_property(env, exports, "ECCKeyUtil", NapiECCKeyUtil::GenECCCommonParamSpec(env));
475 }
476 } // CryptoFramework
477 } // OHOS
478