1 /*
2 * Copyright (c) 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_x509_distinguished_name.h"
17
18 #include "cf_log.h"
19 #include "cf_memory.h"
20 #include "cf_object_base.h"
21 #include "cf_result.h"
22 #include "napi/native_api.h"
23 #include "napi/native_common.h"
24 #include "napi_cert_defines.h"
25 #include "napi_cert_utils.h"
26 #include "utils.h"
27
28 namespace OHOS {
29 namespace CertFramework {
30 thread_local napi_ref NapiX509DistinguishedName::classRef_ = nullptr;
31
32 struct CfCtx {
33 napi_value promise = nullptr;
34 napi_deferred deferred = nullptr;
35 napi_async_work asyncWork = nullptr;
36 napi_ref cfRef = nullptr;
37
38 CfBlob *inPara = nullptr;
39 bool paraIsString = true;
40 HcfX509DistinguishedName *x509Name = nullptr;
41 NapiX509DistinguishedName *nameClass = nullptr;
42 int32_t errCode = 0;
43 const char *errMsg = nullptr;
44 };
45
NapiX509DistinguishedName(HcfX509DistinguishedName * x509Name_)46 NapiX509DistinguishedName::NapiX509DistinguishedName(HcfX509DistinguishedName *x509Name_)
47 {
48 this->x509Name_ = x509Name_;
49 }
50
~NapiX509DistinguishedName()51 NapiX509DistinguishedName::~NapiX509DistinguishedName()
52 {
53 CfObjDestroy(this->x509Name_);
54 }
55
FreeCryptoFwkCtx(napi_env env,CfCtx * context)56 static void FreeCryptoFwkCtx(napi_env env, CfCtx *context)
57 {
58 if (context == nullptr) {
59 return;
60 }
61
62 if (context->asyncWork != nullptr) {
63 napi_delete_async_work(env, context->asyncWork);
64 }
65
66 if (context->cfRef != nullptr) {
67 napi_delete_reference(env, context->cfRef);
68 context->cfRef = nullptr;
69 }
70
71 if (context->inPara != nullptr) {
72 CfBlobFree(&(context->inPara));
73 }
74
75 CfFree(context);
76 }
77
ReturnPromiseResult(napi_env env,CfCtx * context,napi_value result)78 static void ReturnPromiseResult(napi_env env, CfCtx *context, napi_value result)
79 {
80 if (context->errCode == CF_SUCCESS) {
81 napi_resolve_deferred(env, context->deferred, result);
82 } else {
83 napi_reject_deferred(env, context->deferred,
84 CertGenerateBusinessError(env, context->errCode, context->errMsg));
85 }
86 }
87
CreateDistinguishedNameExecute(napi_env env,void * data)88 void NapiX509DistinguishedName::CreateDistinguishedNameExecute(napi_env env, void *data)
89 {
90 CfCtx *context = static_cast<CfCtx *>(data);
91
92 context->errCode = HcfX509DistinguishedNameCreate(context->inPara, context->paraIsString, &context->x509Name);
93 if (context->errCode != CF_SUCCESS) {
94 context->errMsg = "create x509DistinguishedName failed";
95 }
96 }
97
CreateDistinguishedNameComplete(napi_env env,napi_status status,void * data)98 void NapiX509DistinguishedName::CreateDistinguishedNameComplete(napi_env env, napi_status status, void *data)
99 {
100 CfCtx *context = static_cast<CfCtx *>(data);
101 if (context->errCode != CF_SUCCESS) {
102 LOGE("call create x509DistinguisehdName failed!");
103 ReturnPromiseResult(env, context, nullptr);
104 FreeCryptoFwkCtx(env, context);
105 return;
106 }
107 napi_value instance = CreateX509DistinguishedName(env);
108 NapiX509DistinguishedName *x509NameClass = new (std::nothrow) NapiX509DistinguishedName(context->x509Name);
109 if (x509NameClass == nullptr) {
110 context->errCode = CF_ERR_MALLOC;
111 context->errMsg = "Failed to create x509DistinguisehdName class";
112 LOGE("Failed to create x509DistinguisehdName class");
113 ReturnPromiseResult(env, context, nullptr);
114 CfObjDestroy(context->x509Name);
115 FreeCryptoFwkCtx(env, context);
116 return;
117 }
118 napi_wrap(
119 env, instance, x509NameClass,
120 [](napi_env env, void *data, void *hint) {
121 NapiX509DistinguishedName *nameClass = static_cast<NapiX509DistinguishedName *>(data);
122 delete nameClass;
123 return;
124 },
125 nullptr, nullptr);
126 ReturnPromiseResult(env, context, instance);
127 FreeCryptoFwkCtx(env, context);
128 }
129
GetEncoded(napi_env env,napi_callback_info info)130 napi_value NapiX509DistinguishedName::GetEncoded(napi_env env, napi_callback_info info)
131 {
132 HcfX509DistinguishedName *x509Name = GetX509DistinguishedName();
133 CfEncodingBlob blob = {nullptr, 0, CF_FORMAT_DER};
134 CfResult ret = x509Name->getEncode(x509Name, &blob);
135 if (ret != CF_SUCCESS) {
136 LOGE("Distinguished Name get encoded failed");
137 napi_throw(env, CertGenerateBusinessError(env, ret, "Distinguished Name get encoded failed"));
138 return nullptr;
139 }
140 napi_value result = ConvertEncodingBlobToNapiValue(env, &blob);
141 CfEncodingBlobDataFree(&blob);
142 return result;
143 }
144
GetName(napi_env env,napi_callback_info info)145 napi_value NapiX509DistinguishedName::GetName(napi_env env, napi_callback_info info)
146 {
147 size_t argc = ARGS_SIZE_ONE;
148 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
149 napi_value thisVar = nullptr;
150 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
151 if (!CertCheckArgsCount(env, argc, ARGS_SIZE_ONE, false)) {
152 LOGE("CertCheckArgsCount error");
153 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed"));
154 return nullptr;
155 }
156 HcfX509DistinguishedName *x509Name = GetX509DistinguishedName();
157 if (argc == PARAM0) {
158 CfBlob blob = { 0, nullptr };
159 CfResult ret = x509Name->getName(x509Name, NULL, &blob, NULL);
160 if (ret != CF_SUCCESS) {
161 LOGE("Distinguished Name get name failed");
162 napi_throw(env, CertGenerateBusinessError(env, ret, "Distinguished Name get name failed"));
163 return nullptr;
164 }
165
166 napi_value result = nullptr;
167 napi_create_string_utf8(env, reinterpret_cast<char *>(blob.data), blob.size, &result);
168 CfBlobDataFree(&blob);
169 return result;
170 } else if (argc == ARGS_SIZE_ONE) {
171 CfBlob *inPara = CertGetBlobFromStringJSParams(env, argv[PARAM0]);
172 if (inPara != nullptr) {
173 CfArray outArr = { nullptr, CF_FORMAT_DER, 0 };
174 CfResult ret = x509Name->getName(x509Name, inPara, NULL, &outArr);
175 if (ret != CF_SUCCESS) {
176 LOGE("Distinguished Name get name failed");
177 CfBlobFree(&inPara);
178 napi_throw(env, CertGenerateBusinessError(env, ret, "Distinguished Name get name failed"));
179 return nullptr;
180 }
181
182 napi_value result = ConvertArrayStringToNapiValue(env, &outArr);
183 CfBlobFree(&inPara);
184 CfArrayDataClearAndFree(&outArr);
185 return result;
186 }
187 }
188 return nullptr;
189 }
190
NapiGetEncoded(napi_env env,napi_callback_info info)191 static napi_value NapiGetEncoded(napi_env env, napi_callback_info info)
192 {
193 napi_value thisVar = nullptr;
194 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
195 NapiX509DistinguishedName *x509Name = nullptr;
196 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509Name));
197 if (x509Name == nullptr) {
198 LOGE("x509Name is nullptr!");
199 return nullptr;
200 }
201 return x509Name->GetEncoded(env, info);
202 }
203
NapiGetName(napi_env env,napi_callback_info info)204 static napi_value NapiGetName(napi_env env, napi_callback_info info)
205 {
206 napi_value thisVar = nullptr;
207 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
208 NapiX509DistinguishedName *x509Name = nullptr;
209 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509Name));
210 if (x509Name == nullptr) {
211 LOGE("x509Name is nullptr!");
212 return nullptr;
213 }
214 return x509Name->GetName(env, info);
215 }
216
X509DistinguishedNameConstructor(napi_env env,napi_callback_info info)217 static napi_value X509DistinguishedNameConstructor(napi_env env, napi_callback_info info)
218 {
219 napi_value thisVar = nullptr;
220 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
221 return thisVar;
222 }
223
NapiCreateX509DistinguishedName(napi_env env,napi_callback_info info)224 napi_value NapiX509DistinguishedName::NapiCreateX509DistinguishedName(napi_env env, napi_callback_info info)
225 {
226 size_t argc = ARGS_SIZE_ONE;
227 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
228 napi_value thisVar = nullptr;
229 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
230 if (!CertCheckArgsCount(env, argc, ARGS_SIZE_ONE, false)) {
231 LOGE("CertCheckArgsCount error");
232 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "CertCheckArgsCount failed"));
233 return nullptr;
234 }
235
236 CfCtx *context = static_cast<CfCtx *>(CfMalloc(sizeof(CfCtx), 0));
237 if (context == nullptr) {
238 LOGE("malloc context failed!");
239 napi_throw(env, CertGenerateBusinessError(env, CF_ERR_MALLOC, "CfMalloc failed"));
240 return nullptr;
241 }
242
243 napi_create_promise(env, &context->deferred, &context->promise);
244
245 napi_valuetype valueType;
246 napi_typeof(env, argv[PARAM0], &valueType);
247 if (valueType != napi_string) {
248 context->inPara = CertGetBlobFromUint8ArrJSParams(env, argv[PARAM0]);
249 context->paraIsString = false;
250 } else {
251 context->inPara = CertGetBlobFromStringJSParams(env, argv[PARAM0]);
252 context->paraIsString = true;
253 }
254
255 if (napi_create_reference(env, thisVar, 1, &context->cfRef) != napi_ok) {
256 LOGE("create reference failed!");
257 FreeCryptoFwkCtx(env, context);
258 napi_throw(env, CertGenerateBusinessError(env, CF_INVALID_PARAMS, "Create reference failed"));
259 return nullptr;
260 }
261
262 napi_create_async_work(env, nullptr, CertGetResourceName(env, "createX500DistinguishedName"),
263 CreateDistinguishedNameExecute,
264 CreateDistinguishedNameComplete,
265 static_cast<void *>(context),
266 &context->asyncWork);
267
268 napi_queue_async_work(env, context->asyncWork);
269 return context->promise;
270 }
271
DefineX509DistinguishedNameJSClass(napi_env env,napi_value exports)272 void NapiX509DistinguishedName::DefineX509DistinguishedNameJSClass(napi_env env, napi_value exports)
273 {
274 napi_property_descriptor desc[] = {
275 DECLARE_NAPI_FUNCTION("createX500DistinguishedName", NapiCreateX509DistinguishedName),
276 };
277 napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
278
279 napi_property_descriptor x509NameDesc[] = {
280 DECLARE_NAPI_FUNCTION("getEncoded", NapiGetEncoded),
281 DECLARE_NAPI_FUNCTION("getName", NapiGetName),
282 };
283 napi_value constructor = nullptr;
284 napi_define_class(env, "X500DistinguishedName", NAPI_AUTO_LENGTH, X509DistinguishedNameConstructor, nullptr,
285 sizeof(x509NameDesc) / sizeof(x509NameDesc[0]), x509NameDesc, &constructor);
286 napi_create_reference(env, constructor, 1, &classRef_);
287 }
288
CreateX509DistinguishedName(napi_env env)289 napi_value NapiX509DistinguishedName::CreateX509DistinguishedName(napi_env env)
290 {
291 napi_value constructor = nullptr;
292 napi_value instance = nullptr;
293 napi_get_reference_value(env, classRef_, &constructor);
294 napi_new_instance(env, constructor, 0, nullptr, &instance);
295 return instance;
296 }
297 } // namespace CertFramework
298 } // namespace OHOS
299