• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_pri_key.h"
17 
18 #include "log.h"
19 #include "memory.h"
20 #include "napi_crypto_framework_defines.h"
21 #include "napi_utils.h"
22 #include "securec.h"
23 #include "key.h"
24 
25 namespace OHOS {
26 namespace CryptoFramework {
27 thread_local napi_ref NapiPriKey::classRef_ = nullptr;
28 
NapiPriKey(HcfPriKey * priKey)29 NapiPriKey::NapiPriKey(HcfPriKey *priKey) : NapiKey(reinterpret_cast<HcfKey *>(priKey)) {}
30 
~NapiPriKey()31 NapiPriKey::~NapiPriKey() {}
32 
GetPriKey()33 HcfPriKey *NapiPriKey::GetPriKey()
34 {
35     return reinterpret_cast<HcfPriKey *>(NapiKey::GetHcfKey());
36 }
37 
PriKeyConstructor(napi_env env,napi_callback_info info)38 napi_value NapiPriKey::PriKeyConstructor(napi_env env, napi_callback_info info)
39 {
40     napi_value thisVar = nullptr;
41     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
42     return thisVar;
43 }
44 
FreeEncodeParamsSpec(HcfParamsSpec * paramsSpec)45 static void FreeEncodeParamsSpec(HcfParamsSpec *paramsSpec)
46 {
47     if (paramsSpec == nullptr) {
48         return;
49     }
50     HcfKeyEncodingParamsSpec *spec = reinterpret_cast<HcfKeyEncodingParamsSpec *>(paramsSpec);
51     if (spec->password != nullptr) {
52         size_t pwdLen = strlen(spec->password);
53         (void)memset_s((void*)spec->password, pwdLen, 0, pwdLen);
54         HcfFree(static_cast<void *>(spec->password));
55         spec->password = nullptr;
56     }
57     if (spec->cipher != nullptr) {
58         HcfFree(static_cast<void *>(spec->cipher));
59         spec->cipher = nullptr;
60     }
61     HcfFree(paramsSpec);
62     paramsSpec = nullptr;
63 }
64 
ConvertToJsPriKey(napi_env env)65 napi_value NapiPriKey::ConvertToJsPriKey(napi_env env)
66 {
67     napi_value instance;
68     napi_value constructor = nullptr;
69     napi_get_reference_value(env, classRef_, &constructor);
70     napi_new_instance(env, constructor, 0, nullptr, &instance);
71 
72     const char *algName = this->GetPriKey()->base.getAlgorithm(&(this->GetPriKey()->base));
73     const char *format = this->GetPriKey()->base.getFormat(&(this->GetPriKey()->base));
74 
75     napi_value napiAlgName = nullptr;
76     napi_create_string_utf8(env, algName, NAPI_AUTO_LENGTH, &napiAlgName);
77     napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
78 
79     napi_value napiFormat = nullptr;
80     napi_create_string_utf8(env, format, NAPI_AUTO_LENGTH, &napiFormat);
81     napi_set_named_property(env, instance, CRYPTO_TAG_FORMAT.c_str(), napiFormat);
82     return instance;
83 }
84 
JsGetEncoded(napi_env env,napi_callback_info info)85 napi_value NapiPriKey::JsGetEncoded(napi_env env, napi_callback_info info)
86 {
87     napi_value thisVar = nullptr;
88     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
89     NapiPriKey *napiPriKey = nullptr;
90     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
91     if (status != napi_ok || napiPriKey == nullptr) {
92         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
93         LOGE("failed to unwrap napiPriKey obj!");
94         return nullptr;
95     }
96 
97     HcfPriKey *priKey = napiPriKey->GetPriKey();
98     if (priKey == nullptr) {
99         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
100         LOGE("failed to get priKey obj!");
101         return nullptr;
102     }
103 
104     HcfBlob returnBlob;
105     HcfResult res = priKey->base.getEncoded(&priKey->base, &returnBlob);
106     if (res != HCF_SUCCESS) {
107         napi_throw(env, GenerateBusinessError(env, res, "c getEncoded fail."));
108         LOGD("[error] c getEncoded fail.");
109         return nullptr;
110     }
111 
112     napi_value instance = ConvertBlobToNapiValue(env, &returnBlob);
113     if (instance == nullptr) {
114         HcfBlobDataFree(&returnBlob);
115         napi_throw(env, GenerateBusinessError(env, res, "covert blob to napi value failed."));
116         LOGE("covert blob to napi value failed.");
117         return nullptr;
118     }
119     HcfBlobDataClearAndFree(&returnBlob);
120     return instance;
121 }
122 
ValidateAndGetParams(napi_env env,napi_callback_info info,std::string & format,HcfParamsSpec ** paramsSpec,NapiPriKey ** napiPriKey)123 static bool ValidateAndGetParams(napi_env env, napi_callback_info info, std::string &format,
124     HcfParamsSpec **paramsSpec, NapiPriKey **napiPriKey)
125 {
126     size_t expectedArgc = PARAMS_NUM_TWO;
127     size_t argc = expectedArgc;
128     napi_value thisVar = nullptr;
129     napi_value argv[PARAMS_NUM_TWO] = { nullptr };
130     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
131     if ((argc != expectedArgc) && (argc != (expectedArgc - 1))) {
132         LOGE("The input args num is invalid.");
133         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
134         return false;
135     }
136 
137     if (!GetStringFromJSParams(env, argv[0], format)) {
138         LOGE("failed to get formatStr.");
139         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get formatStr."));
140         return false;
141     }
142 
143     if (argc == expectedArgc) {
144         if (!GetEncodingParamsSpec(env, argv[1], paramsSpec)) {
145             LOGE("get params failed!");
146             napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "get napi paramsSpec failed!"));
147             return false;
148         }
149     }
150 
151     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(napiPriKey));
152     if (status != napi_ok || napiPriKey == nullptr) {
153         LOGE("failed to unwrap napiPriKey obj!");
154         FreeEncodeParamsSpec(*paramsSpec);
155         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
156         return false;
157     }
158     return true;
159 }
160 
JsGetEncodedPem(napi_env env,napi_callback_info info)161 napi_value NapiPriKey::JsGetEncodedPem(napi_env env, napi_callback_info info)
162 {
163     std::string format;
164     HcfParamsSpec *paramsSpec = nullptr;
165     NapiPriKey *napiPriKey = nullptr;
166     if (!ValidateAndGetParams(env, info, format, &paramsSpec, &napiPriKey)) {
167         return NapiGetNull(env);
168     }
169 
170     HcfPriKey *priKey = napiPriKey->GetPriKey();
171     if (priKey == nullptr) {
172         FreeEncodeParamsSpec(paramsSpec);
173         paramsSpec = nullptr;
174         LOGE("failed to get priKey obj!");
175         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
176         return nullptr;
177     }
178 
179     char *returnString = nullptr;
180     HcfResult res = priKey->getEncodedPem(priKey, paramsSpec, format.c_str(), &returnString);
181     if (res != HCF_SUCCESS) {
182         FreeEncodeParamsSpec(paramsSpec);
183         paramsSpec = nullptr;
184         LOGE("getEncodedPem fail.");
185         napi_throw(env, GenerateBusinessError(env, res, "getEncodedPem fail."));
186         return nullptr;
187     }
188     napi_value instance = nullptr;
189     napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
190     HcfFree(returnString);
191     returnString = nullptr;
192     FreeEncodeParamsSpec(paramsSpec);
193     paramsSpec = nullptr;
194     return instance;
195 }
196 
JsClearMem(napi_env env,napi_callback_info info)197 napi_value NapiPriKey::JsClearMem(napi_env env, napi_callback_info info)
198 {
199     napi_value thisVar = nullptr;
200     napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
201     NapiPriKey *napiPriKey = nullptr;
202     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
203     if (status != napi_ok || napiPriKey == nullptr) {
204         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
205         LOGE("failed to unwrap napiPriKey obj!");
206         return nullptr;
207     }
208 
209     HcfPriKey *priKey = napiPriKey->GetPriKey();
210     if (priKey == nullptr) {
211         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
212         LOGE("failed to get priKey obj!");
213         return nullptr;
214     }
215 
216     priKey->clearMem(priKey);
217     return nullptr;
218 }
219 
GetAsyKeySpecBigInt(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)220 static napi_value GetAsyKeySpecBigInt(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
221 {
222     HcfBigInteger returnBigInteger = { 0 };
223     HcfResult res = priKey->getAsyKeySpecBigInteger(priKey, item, &returnBigInteger);
224     if (res != HCF_SUCCESS) {
225         napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecBigInteger failed."));
226         LOGE("C getAsyKeySpecBigInteger failed.");
227         return nullptr;
228     }
229 
230     napi_value instance = ConvertBigIntToNapiValue(env, &returnBigInteger);
231     (void)memset_s(returnBigInteger.data, returnBigInteger.len, 0, returnBigInteger.len);
232     HcfFree(returnBigInteger.data);
233     returnBigInteger.data = nullptr;
234     if (instance == nullptr) {
235         napi_throw(env, GenerateBusinessError(env, res, "covert bigInt to napi value failed."));
236         LOGE("covert bigInt to napi value failed.");
237         return nullptr;
238     }
239     return instance;
240 }
241 
GetAsyKeySpecNumber(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)242 static napi_value GetAsyKeySpecNumber(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
243 {
244     int returnInt = 0;
245     HcfResult res = priKey->getAsyKeySpecInt(priKey, item, &returnInt);
246     if (res != HCF_SUCCESS) {
247         napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecInt failed."));
248         LOGE("C getAsyKeySpecInt fail.");
249         return nullptr;
250     }
251 
252     napi_value instance = nullptr;
253     napi_create_int32(env, returnInt, &instance);
254     return instance;
255 }
256 
GetAsyKeySpecString(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)257 static napi_value GetAsyKeySpecString(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
258 {
259     char *returnString = nullptr;
260     HcfResult res = priKey->getAsyKeySpecString(priKey, item, &returnString);
261     if (res != HCF_SUCCESS) {
262         napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecString failed."));
263         LOGE("c getAsyKeySpecString fail.");
264         return nullptr;
265     }
266 
267     napi_value instance = nullptr;
268     napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
269     HcfFree(returnString);
270     returnString = nullptr;
271     return instance;
272 }
273 
JsGetAsyKeySpec(napi_env env,napi_callback_info info)274 napi_value NapiPriKey::JsGetAsyKeySpec(napi_env env, napi_callback_info info)
275 {
276     napi_value thisVar = nullptr;
277     NapiPriKey *napiPriKey = nullptr;
278     size_t expectedArgc = ARGS_SIZE_ONE;
279     size_t argc = ARGS_SIZE_ONE;
280     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
281     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
282     if (argc != expectedArgc) {
283         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "JsGetAsyKeySpec fail, wrong argument num."));
284         LOGE("wrong argument num. require 1 arguments. [Argc]: %{public}zu!", argc);
285         return nullptr;
286     }
287 
288     AsyKeySpecItem item;
289     if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
290         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "JsGetAsyKeySpec failed!"));
291         LOGE("JsGetAsyKeySpec failed!");
292         return nullptr;
293     }
294 
295     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
296     if (status != napi_ok || napiPriKey == nullptr) {
297         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
298         LOGE("failed to unwrap napiPriKey obj!");
299         return nullptr;
300     }
301     HcfPriKey *priKey = napiPriKey->GetPriKey();
302     if (priKey == nullptr) {
303         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
304         LOGE("failed to get priKey obj!");
305         return nullptr;
306     }
307     LOGD("prepare priKey ok.");
308 
309     int32_t type = GetAsyKeySpecType(item);
310     if (type == SPEC_ITEM_TYPE_BIG_INT) {
311         return GetAsyKeySpecBigInt(env, item, priKey);
312     } else if (type == SPEC_ITEM_TYPE_NUM) {
313         return GetAsyKeySpecNumber(env, item, priKey);
314     } else if (type == SPEC_ITEM_TYPE_STR) {
315         return GetAsyKeySpecString(env, item, priKey);
316     } else {
317         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "AsyKeySpecItem not support!"));
318         return nullptr;
319     }
320 }
321 
JsGetEncodedDer(napi_env env,napi_callback_info info)322 napi_value NapiPriKey::JsGetEncodedDer(napi_env env, napi_callback_info info)
323 {
324     napi_value thisVar = nullptr;
325     NapiPriKey *napiPriKey = nullptr;
326     size_t argc = ARGS_SIZE_ONE;
327     napi_value argv[ARGS_SIZE_ONE] = { nullptr };
328     napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
329     if (argc != ARGS_SIZE_ONE) {
330         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
331         LOGE("wrong argument num. require 1 arguments. [Argc]: %{public}zu!", argc);
332         return nullptr;
333     }
334     std::string format;
335     if (!GetStringFromJSParams(env, argv[0], format)) {
336         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get format."));
337         LOGE("get format fail.");
338         return nullptr;
339     }
340     napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
341     if (status != napi_ok || napiPriKey == nullptr) {
342         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap private key obj!"));
343         LOGE("failed to unwrap private key obj!");
344         return nullptr;
345     }
346     HcfPriKey *priKey = napiPriKey->GetPriKey();
347     if (priKey == nullptr) {
348         napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get private key obj!"));
349         LOGE("failed to get private key obj!");
350         return nullptr;
351     }
352     HcfBlob returnBlob = { .data = nullptr, .len = 0 };
353     HcfResult res = priKey->getEncodedDer(priKey, format.c_str(), &returnBlob);
354     if (res != HCF_SUCCESS) {
355         napi_throw(env, GenerateBusinessError(env, res, "get private key encodedDer fail."));
356         LOGE("get private key encodeDer fail.");
357         return nullptr;
358     }
359 
360     napi_value instance = ConvertBlobToNapiValue(env, &returnBlob);
361     HcfBlobDataClearAndFree(&returnBlob);
362     return instance;
363 }
364 
DefinePriKeyJSClass(napi_env env)365 void NapiPriKey::DefinePriKeyJSClass(napi_env env)
366 {
367     napi_property_descriptor classDesc[] = {
368         DECLARE_NAPI_FUNCTION("getEncoded", NapiPriKey::JsGetEncoded),
369         DECLARE_NAPI_FUNCTION("getEncodedDer", NapiPriKey::JsGetEncodedDer),
370         DECLARE_NAPI_FUNCTION("getEncodedPem", NapiPriKey::JsGetEncodedPem),
371         DECLARE_NAPI_FUNCTION("clearMem", NapiPriKey::JsClearMem),
372         DECLARE_NAPI_FUNCTION("getAsyKeySpec", NapiPriKey::JsGetAsyKeySpec),
373     };
374     napi_value constructor = nullptr;
375     napi_define_class(env, "PriKey", NAPI_AUTO_LENGTH, NapiPriKey::PriKeyConstructor, nullptr,
376         sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
377     napi_create_reference(env, constructor, 1, &classRef_);
378 }
379 } // CryptoFramework
380 } // OHOS
381