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
ConvertToJsPriKey(napi_env env)45 napi_value NapiPriKey::ConvertToJsPriKey(napi_env env)
46 {
47 napi_value instance;
48 napi_value constructor = nullptr;
49 napi_get_reference_value(env, classRef_, &constructor);
50 napi_new_instance(env, constructor, 0, nullptr, &instance);
51
52 const char *algName = this->GetPriKey()->base.getAlgorithm(&(this->GetPriKey()->base));
53 const char *format = this->GetPriKey()->base.getFormat(&(this->GetPriKey()->base));
54
55 napi_value napiAlgName = nullptr;
56 napi_create_string_utf8(env, algName, NAPI_AUTO_LENGTH, &napiAlgName);
57 napi_set_named_property(env, instance, CRYPTO_TAG_ALG_NAME.c_str(), napiAlgName);
58
59 napi_value napiFormat = nullptr;
60 napi_create_string_utf8(env, format, NAPI_AUTO_LENGTH, &napiFormat);
61 napi_set_named_property(env, instance, CRYPTO_TAG_FORMAT.c_str(), napiFormat);
62 return instance;
63 }
64
JsGetEncoded(napi_env env,napi_callback_info info)65 napi_value NapiPriKey::JsGetEncoded(napi_env env, napi_callback_info info)
66 {
67 napi_value thisVar = nullptr;
68 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
69 NapiPriKey *napiPriKey = nullptr;
70 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
71 if (status != napi_ok || napiPriKey == nullptr) {
72 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
73 LOGE("failed to unwrap napiPriKey obj!");
74 return nullptr;
75 }
76
77 HcfPriKey *priKey = napiPriKey->GetPriKey();
78 if (priKey == nullptr) {
79 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
80 LOGE("failed to get priKey obj!");
81 return nullptr;
82 }
83
84 HcfBlob returnBlob;
85 HcfResult res = priKey->base.getEncoded(&priKey->base, &returnBlob);
86 if (res != HCF_SUCCESS) {
87 napi_throw(env, GenerateBusinessError(env, res, "c getEncoded fail."));
88 LOGD("[error] c getEncoded fail.");
89 return nullptr;
90 }
91
92 napi_value instance = ConvertBlobToNapiValue(env, &returnBlob);
93 if (instance == nullptr) {
94 HcfBlobDataFree(&returnBlob);
95 napi_throw(env, GenerateBusinessError(env, res, "covert blob to napi value failed."));
96 LOGE("covert blob to napi value failed.");
97 return nullptr;
98 }
99 HcfBlobDataClearAndFree(&returnBlob);
100 return instance;
101 }
102
JsGetEncodedPem(napi_env env,napi_callback_info info)103 napi_value NapiPriKey::JsGetEncodedPem(napi_env env, napi_callback_info info)
104 {
105 size_t expectedArgc = PARAMS_NUM_ONE;
106 size_t argc = expectedArgc;
107 napi_value argv[PARAMS_NUM_ONE] = { nullptr };
108 napi_value thisVar = nullptr;
109 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
110 if (argc != expectedArgc) {
111 LOGE("The input args num is invalid.");
112 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "The input args num is invalid."));
113 return NapiGetNull(env);
114 }
115
116 std::string format = "";
117 if (!GetStringFromJSParams(env, argv[0], format)) {
118 LOGE("failed to get formatStr.");
119 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get formatStr."));
120 return NapiGetNull(env);
121 }
122
123 NapiPriKey *napiPriKey = nullptr;
124 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
125 if (status != napi_ok || napiPriKey == nullptr) {
126 LOGE("failed to unwrap napiPriKey obj!");
127 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
128 return nullptr;
129 }
130
131 HcfPriKey *priKey = napiPriKey->GetPriKey();
132 if (priKey == nullptr) {
133 LOGE("failed to get priKey obj!");
134 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
135 return nullptr;
136 }
137
138 char *returnString = nullptr;
139 HcfResult res = priKey->base.getEncodedPem(&priKey->base, format.c_str(), &returnString);
140 if (res != HCF_SUCCESS) {
141 LOGE("getEncodedPem fail.");
142 napi_throw(env, GenerateBusinessError(env, res, "getEncodedPem fail."));
143 return nullptr;
144 }
145 napi_value instance = nullptr;
146 napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
147 HcfFree(returnString);
148 return instance;
149 }
150
JsClearMem(napi_env env,napi_callback_info info)151 napi_value NapiPriKey::JsClearMem(napi_env env, napi_callback_info info)
152 {
153 napi_value thisVar = nullptr;
154 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
155 NapiPriKey *napiPriKey = nullptr;
156 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
157 if (status != napi_ok || napiPriKey == nullptr) {
158 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
159 LOGE("failed to unwrap napiPriKey obj!");
160 return nullptr;
161 }
162
163 HcfPriKey *priKey = napiPriKey->GetPriKey();
164 if (priKey == nullptr) {
165 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
166 LOGE("failed to get priKey obj!");
167 return nullptr;
168 }
169
170 priKey->clearMem(priKey);
171 return nullptr;
172 }
173
GetAsyKeySpecBigInt(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)174 static napi_value GetAsyKeySpecBigInt(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
175 {
176 HcfBigInteger returnBigInteger = { 0 };
177 HcfResult res = priKey->getAsyKeySpecBigInteger(priKey, item, &returnBigInteger);
178 if (res != HCF_SUCCESS) {
179 napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecBigInteger failed."));
180 LOGE("C getAsyKeySpecBigInteger failed.");
181 return nullptr;
182 }
183
184 napi_value instance = ConvertBigIntToNapiValue(env, &returnBigInteger);
185 (void)memset_s(returnBigInteger.data, returnBigInteger.len, 0, returnBigInteger.len);
186 HcfFree(returnBigInteger.data);
187 if (instance == nullptr) {
188 napi_throw(env, GenerateBusinessError(env, res, "covert bigInt to napi value failed."));
189 LOGE("covert bigInt to napi value failed.");
190 return nullptr;
191 }
192 return instance;
193 }
194
GetAsyKeySpecNumber(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)195 static napi_value GetAsyKeySpecNumber(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
196 {
197 int returnInt = 0;
198 HcfResult res = priKey->getAsyKeySpecInt(priKey, item, &returnInt);
199 if (res != HCF_SUCCESS) {
200 napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecInt failed."));
201 LOGE("C getAsyKeySpecInt fail.");
202 return nullptr;
203 }
204
205 napi_value instance = nullptr;
206 napi_create_int32(env, returnInt, &instance);
207 return instance;
208 }
209
GetAsyKeySpecString(napi_env env,AsyKeySpecItem item,HcfPriKey * priKey)210 static napi_value GetAsyKeySpecString(napi_env env, AsyKeySpecItem item, HcfPriKey *priKey)
211 {
212 char *returnString = nullptr;
213 HcfResult res = priKey->getAsyKeySpecString(priKey, item, &returnString);
214 if (res != HCF_SUCCESS) {
215 napi_throw(env, GenerateBusinessError(env, res, "C getAsyKeySpecString failed."));
216 LOGE("c getAsyKeySpecString fail.");
217 return nullptr;
218 }
219
220 napi_value instance = nullptr;
221 napi_create_string_utf8(env, returnString, NAPI_AUTO_LENGTH, &instance);
222 HcfFree(returnString);
223 return instance;
224 }
225
JsGetAsyKeySpec(napi_env env,napi_callback_info info)226 napi_value NapiPriKey::JsGetAsyKeySpec(napi_env env, napi_callback_info info)
227 {
228 napi_value thisVar = nullptr;
229 NapiPriKey *napiPriKey = nullptr;
230 size_t expectedArgc = ARGS_SIZE_ONE;
231 size_t argc = ARGS_SIZE_ONE;
232 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
233 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
234 if (argc != expectedArgc) {
235 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "JsGetAsyKeySpec fail, wrong argument num."));
236 LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
237 return nullptr;
238 }
239
240 AsyKeySpecItem item;
241 if (napi_get_value_uint32(env, argv[0], reinterpret_cast<uint32_t *>(&item)) != napi_ok) {
242 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "JsGetAsyKeySpec failed!"));
243 LOGE("JsGetAsyKeySpec failed!");
244 return nullptr;
245 }
246
247 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
248 if (status != napi_ok || napiPriKey == nullptr) {
249 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap napiPriKey obj!"));
250 LOGE("failed to unwrap napiPriKey obj!");
251 return nullptr;
252 }
253 HcfPriKey *priKey = napiPriKey->GetPriKey();
254 if (priKey == nullptr) {
255 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get priKey obj!"));
256 LOGE("failed to get priKey obj!");
257 return nullptr;
258 }
259 LOGD("prepare priKey ok.");
260
261 int32_t type = GetAsyKeySpecType(item);
262 if (type == SPEC_ITEM_TYPE_BIG_INT) {
263 return GetAsyKeySpecBigInt(env, item, priKey);
264 } else if (type == SPEC_ITEM_TYPE_NUM) {
265 return GetAsyKeySpecNumber(env, item, priKey);
266 } else if (type == SPEC_ITEM_TYPE_STR) {
267 return GetAsyKeySpecString(env, item, priKey);
268 } else {
269 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "AsyKeySpecItem not support!"));
270 return nullptr;
271 }
272 }
273
JsGetEncodedDer(napi_env env,napi_callback_info info)274 napi_value NapiPriKey::JsGetEncodedDer(napi_env env, napi_callback_info info)
275 {
276 napi_value thisVar = nullptr;
277 NapiPriKey *napiPriKey = nullptr;
278 size_t argc = ARGS_SIZE_ONE;
279 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
280 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
281 if (argc != ARGS_SIZE_ONE) {
282 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "wrong argument num."));
283 LOGE("wrong argument num. require 1 arguments. [Argc]: %zu!", argc);
284 return nullptr;
285 }
286 std::string format;
287 if (!GetStringFromJSParams(env, argv[0], format)) {
288 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get format."));
289 LOGE("get format fail.");
290 return nullptr;
291 }
292 napi_status status = napi_unwrap(env, thisVar, reinterpret_cast<void **>(&napiPriKey));
293 if (status != napi_ok || napiPriKey == nullptr) {
294 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to unwrap private key obj!"));
295 LOGE("failed to unwrap private key obj!");
296 return nullptr;
297 }
298 HcfPriKey *priKey = napiPriKey->GetPriKey();
299 if (priKey == nullptr) {
300 napi_throw(env, GenerateBusinessError(env, HCF_INVALID_PARAMS, "failed to get private key obj!"));
301 LOGE("failed to get private key obj!");
302 return nullptr;
303 }
304 HcfBlob returnBlob = { .data = nullptr, .len = 0 };
305 HcfResult res = priKey->getEncodedDer(priKey, format.c_str(), &returnBlob);
306 if (res != HCF_SUCCESS) {
307 napi_throw(env, GenerateBusinessError(env, res, "get private key encodedDer fail."));
308 LOGE("get private key encodeDer fail.");
309 return nullptr;
310 }
311
312 napi_value instance = ConvertBlobToNapiValue(env, &returnBlob);
313 HcfBlobDataClearAndFree(&returnBlob);
314 return instance;
315 }
316
DefinePriKeyJSClass(napi_env env)317 void NapiPriKey::DefinePriKeyJSClass(napi_env env)
318 {
319 napi_property_descriptor classDesc[] = {
320 DECLARE_NAPI_FUNCTION("getEncoded", NapiPriKey::JsGetEncoded),
321 DECLARE_NAPI_FUNCTION("getEncodedDer", NapiPriKey::JsGetEncodedDer),
322 DECLARE_NAPI_FUNCTION("getEncodedPem", NapiPriKey::JsGetEncodedPem),
323 DECLARE_NAPI_FUNCTION("clearMem", NapiPriKey::JsClearMem),
324 DECLARE_NAPI_FUNCTION("getAsyKeySpec", NapiPriKey::JsGetAsyKeySpec),
325 };
326 napi_value constructor = nullptr;
327 napi_define_class(env, "PriKey", NAPI_AUTO_LENGTH, NapiPriKey::PriKeyConstructor, nullptr,
328 sizeof(classDesc) / sizeof(classDesc[0]), classDesc, &constructor);
329 napi_create_reference(env, constructor, 1, &classRef_);
330 }
331 } // CryptoFramework
332 } // OHOS
333