1 /*
2 * Copyright (c) 2023 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_crl_entry.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_node_api.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 NapiX509CrlEntry::classCrlRef_ = nullptr;
31 thread_local napi_ref NapiX509CrlEntry::classCRLRef_ = nullptr;
32
33 struct CfCtx {
34 AsyncType asyncType = ASYNC_TYPE_CALLBACK;
35 napi_value promise = nullptr;
36 napi_ref callback = nullptr;
37 napi_deferred deferred = nullptr;
38 napi_async_work asyncWork = nullptr;
39
40 NapiX509CrlEntry *crlEntryClass = nullptr;
41
42 int32_t errCode = 0;
43 const char *errMsg = nullptr;
44 CfEncodingBlob *encoded = nullptr;
45 CfBlob *blob = nullptr;
46 };
47
FreeCryptoFwkCtx(napi_env env,CfCtx * context)48 static void FreeCryptoFwkCtx(napi_env env, CfCtx *context)
49 {
50 if (context == nullptr) {
51 return;
52 }
53
54 if (context->asyncWork != nullptr) {
55 napi_delete_async_work(env, context->asyncWork);
56 }
57
58 if (context->callback != nullptr) {
59 napi_delete_reference(env, context->callback);
60 }
61
62 CfEncodingBlobDataFree(context->encoded);
63 CfFree(context->encoded);
64 context->encoded = nullptr;
65
66 CfBlobDataFree(context->blob);
67 CfFree(context->blob);
68 context->blob = nullptr;
69
70 CfFree(context);
71 }
72
ReturnCallbackResult(napi_env env,CfCtx * context,napi_value result)73 static void ReturnCallbackResult(napi_env env, CfCtx *context, napi_value result)
74 {
75 napi_value businessError = nullptr;
76 if (context->errCode != CF_SUCCESS) {
77 businessError = CertGenerateBusinessError(env, context->errCode, context->errMsg);
78 }
79 napi_value params[ARGS_SIZE_TWO] = { businessError, result };
80
81 napi_value func = nullptr;
82 napi_get_reference_value(env, context->callback, &func);
83
84 napi_value recv = nullptr;
85 napi_value callFuncRet = nullptr;
86 napi_get_undefined(env, &recv);
87 napi_call_function(env, recv, func, ARGS_SIZE_TWO, params, &callFuncRet);
88 }
89
ReturnPromiseResult(napi_env env,CfCtx * context,napi_value result)90 static void ReturnPromiseResult(napi_env env, CfCtx *context, napi_value result)
91 {
92 if (context->errCode == CF_SUCCESS) {
93 napi_resolve_deferred(env, context->deferred, result);
94 } else {
95 napi_reject_deferred(env, context->deferred, CertGenerateBusinessError(env, context->errCode, context->errMsg));
96 }
97 }
98
ReturnResult(napi_env env,CfCtx * context,napi_value result)99 static void ReturnResult(napi_env env, CfCtx *context, napi_value result)
100 {
101 if (context->asyncType == ASYNC_TYPE_CALLBACK) {
102 ReturnCallbackResult(env, context, result);
103 } else {
104 ReturnPromiseResult(env, context, result);
105 }
106 }
107
CreateCallbackAndPromise(napi_env env,CfCtx * context,size_t argc,size_t maxCount,napi_value callbackValue)108 static bool CreateCallbackAndPromise(
109 napi_env env, CfCtx *context, size_t argc, size_t maxCount, napi_value callbackValue)
110 {
111 context->asyncType = GetAsyncType(env, argc, maxCount, callbackValue);
112 if (context->asyncType == ASYNC_TYPE_CALLBACK) {
113 if (!CertGetCallbackFromJSParams(env, callbackValue, &context->callback)) {
114 LOGE("x509 crl entry: get callback failed!");
115 return false;
116 }
117 } else {
118 napi_create_promise(env, &context->deferred, &context->promise);
119 }
120 return true;
121 }
122
NapiX509CrlEntry(HcfX509CrlEntry * x509CrlEntry)123 NapiX509CrlEntry::NapiX509CrlEntry(HcfX509CrlEntry *x509CrlEntry)
124 {
125 this->x509CrlEntry_ = x509CrlEntry;
126 }
127
~NapiX509CrlEntry()128 NapiX509CrlEntry::~NapiX509CrlEntry()
129 {
130 CfObjDestroy(this->x509CrlEntry_);
131 }
132
GetEncodedExecute(napi_env env,void * data)133 static void GetEncodedExecute(napi_env env, void *data)
134 {
135 CfCtx *context = static_cast<CfCtx *>(data);
136 HcfX509CrlEntry *x509CrlEntry = context->crlEntryClass->GetX509CrlEntry();
137 CfEncodingBlob *encodingBlob = static_cast<CfEncodingBlob *>(HcfMalloc(sizeof(CfEncodingBlob), 0));
138 if (encodingBlob == nullptr) {
139 LOGE("malloc encoding blob failed!");
140 context->errCode = CF_ERR_MALLOC;
141 context->errMsg = "malloc encoding blob failed";
142 return;
143 }
144
145 context->errCode = x509CrlEntry->getEncoded(x509CrlEntry, encodingBlob);
146 if (context->errCode != CF_SUCCESS) {
147 LOGE("get encoded failed!");
148 context->errMsg = "get encoded failed";
149 }
150 context->encoded = encodingBlob;
151 }
152
GetEncodedComplete(napi_env env,napi_status status,void * data)153 static void GetEncodedComplete(napi_env env, napi_status status, void *data)
154 {
155 CfCtx *context = static_cast<CfCtx *>(data);
156 if (context->errCode != CF_SUCCESS) {
157 ReturnResult(env, context, nullptr);
158 FreeCryptoFwkCtx(env, context);
159 return;
160 }
161 napi_value returnEncodingBlob = ConvertEncodingBlobToNapiValue(env, context->encoded);
162 ReturnResult(env, context, returnEncodingBlob);
163 FreeCryptoFwkCtx(env, context);
164 }
165
GetEncoded(napi_env env,napi_callback_info info)166 napi_value NapiX509CrlEntry::GetEncoded(napi_env env, napi_callback_info info)
167 {
168 size_t argc = ARGS_SIZE_ONE;
169 napi_value argv[ARGS_SIZE_ONE] = { nullptr };
170 napi_value thisVar = nullptr;
171 napi_get_cb_info(env, info, &argc, argv, &thisVar, nullptr);
172 if (!CertCheckArgsCount(env, argc, ARGS_SIZE_ONE, false)) {
173 return nullptr;
174 }
175
176 CfCtx *context = static_cast<CfCtx *>(HcfMalloc(sizeof(CfCtx), 0));
177 if (context == nullptr) {
178 LOGE("malloc context failed!");
179 return nullptr;
180 }
181 context->crlEntryClass = this;
182
183 if (!CreateCallbackAndPromise(env, context, argc, ARGS_SIZE_ONE, argv[PARAM0])) {
184 FreeCryptoFwkCtx(env, context);
185 return nullptr;
186 }
187
188 napi_create_async_work(env, nullptr, CertGetResourceName(env, "GetEncoded"), GetEncodedExecute, GetEncodedComplete,
189 static_cast<void *>(context), &context->asyncWork);
190
191 napi_queue_async_work(env, context->asyncWork);
192 if (context->asyncType == ASYNC_TYPE_PROMISE) {
193 return context->promise;
194 } else {
195 return CertNapiGetNull(env);
196 }
197 }
198
GetCrlEntrySerialNumber(napi_env env,napi_callback_info info)199 napi_value NapiX509CrlEntry::GetCrlEntrySerialNumber(napi_env env, napi_callback_info info)
200 {
201 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
202 CfBlob blob = { 0, nullptr };
203 CfResult ret = x509CrlEntry->getSerialNumber(x509CrlEntry, &blob);
204 if (ret != CF_SUCCESS) {
205 napi_throw(env, CertGenerateBusinessError(env, ret, "crl entry get serial num failed"));
206 LOGE("crl entry get serial num failed!");
207 return nullptr;
208 }
209
210 napi_value result = ConvertBlobToInt64(env, blob);
211 CfBlobDataFree(&blob);
212 return result;
213 }
214
GetCRLEntrySerialNumber(napi_env env,napi_callback_info info)215 napi_value NapiX509CrlEntry::GetCRLEntrySerialNumber(napi_env env, napi_callback_info info)
216 {
217 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
218 CfBlob blob = { 0, nullptr };
219 CfResult ret = x509CrlEntry->getSerialNumber(x509CrlEntry, &blob);
220 if (ret != CF_SUCCESS) {
221 napi_throw(env, CertGenerateBusinessError(env, ret, "crl entry get serial num failed"));
222 LOGE("crl entry get serial num failed!");
223 return nullptr;
224 }
225
226 napi_value result = ConvertBlobToBigIntWords(env, blob);
227 CfBlobDataFree(&blob);
228 return result;
229 }
230
GetCertificateIssuer(napi_env env,napi_callback_info info)231 napi_value NapiX509CrlEntry::GetCertificateIssuer(napi_env env, napi_callback_info info)
232 {
233 CfBlob *blob = reinterpret_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
234 if (blob == nullptr) {
235 LOGE("malloc blob failed!");
236 return nullptr;
237 }
238
239 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
240 CfResult ret = x509CrlEntry->getCertIssuer(x509CrlEntry, blob);
241 if (ret != CF_SUCCESS) {
242 napi_throw(env, CertGenerateBusinessError(env, ret, "get subject name failed"));
243 LOGE("get cert issuer failed!");
244 CfFree(blob);
245 blob = nullptr;
246 return nullptr;
247 }
248 napi_value returnValue = CertConvertBlobToNapiValue(env, blob);
249 CfBlobDataFree(blob);
250 CfFree(blob);
251 blob = nullptr;
252 return returnValue;
253 }
254
GetRevocationDate(napi_env env,napi_callback_info info)255 napi_value NapiX509CrlEntry::GetRevocationDate(napi_env env, napi_callback_info info)
256 {
257 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
258 CfBlob *blob = reinterpret_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
259 if (blob == nullptr) {
260 LOGE("malloc blob failed!");
261 return nullptr;
262 }
263 CfResult ret = x509CrlEntry->getRevocationDate(x509CrlEntry, blob);
264 if (ret != CF_SUCCESS) {
265 napi_throw(env, CertGenerateBusinessError(env, ret, "get revocation date failed"));
266 LOGE("get revocation date failed!");
267 CfFree(blob);
268 blob = nullptr;
269 return nullptr;
270 }
271 napi_value returnDate = nullptr;
272 napi_create_string_utf8(env, reinterpret_cast<char *>(blob->data), blob->size, &returnDate);
273 CfBlobDataFree(blob);
274 CfFree(blob);
275 blob = nullptr;
276 return returnDate;
277 }
278
GetExtensions(napi_env env,napi_callback_info info)279 napi_value NapiX509CrlEntry::GetExtensions(napi_env env, napi_callback_info info)
280 {
281 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
282 CfBlob *blob = reinterpret_cast<CfBlob *>(HcfMalloc(sizeof(CfBlob), 0));
283 if (blob == nullptr) {
284 LOGE("malloc blob failed!");
285 return nullptr;
286 }
287 CfResult result = x509CrlEntry->getExtensions(x509CrlEntry, blob);
288 if (result != CF_SUCCESS) {
289 napi_throw(env, CertGenerateBusinessError(env, result, "get extensions failed"));
290 LOGE("getExtensions failed!");
291 CfFree(blob);
292 blob = nullptr;
293 return nullptr;
294 }
295 napi_value returnBlob = CertConvertBlobToNapiValue(env, blob);
296 CfBlobDataFree(blob);
297 CfFree(blob);
298 blob = nullptr;
299 return returnBlob;
300 }
301
HasExtensions(napi_env env,napi_callback_info info)302 napi_value NapiX509CrlEntry::HasExtensions(napi_env env, napi_callback_info info)
303 {
304 HcfX509CrlEntry *x509CrlEntry = GetX509CrlEntry();
305 bool boolResult = false;
306 CfResult result = x509CrlEntry->hasExtensions(x509CrlEntry, &boolResult);
307 if (result != CF_SUCCESS) {
308 napi_throw(env, CertGenerateBusinessError(env, result, "has extensions failed"));
309 LOGE("hasExtensions failed!");
310 return nullptr;
311 }
312 napi_value ret = nullptr;
313 napi_get_boolean(env, boolResult, &ret);
314 return ret;
315 }
316
NapiGetEncoded(napi_env env,napi_callback_info info)317 static napi_value NapiGetEncoded(napi_env env, napi_callback_info info)
318 {
319 napi_value thisVar = nullptr;
320 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
321 NapiX509CrlEntry *x509CrlEntry = nullptr;
322 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
323 if (x509CrlEntry == nullptr) {
324 LOGE("x509CrlEntry is nullptr!");
325 return nullptr;
326 }
327 return x509CrlEntry->GetEncoded(env, info);
328 }
329
NapiCrlEntryGetSerialNumber(napi_env env,napi_callback_info info)330 static napi_value NapiCrlEntryGetSerialNumber(napi_env env, napi_callback_info info)
331 {
332 napi_value thisVar = nullptr;
333 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
334 NapiX509CrlEntry *x509CrlEntry = nullptr;
335 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
336 if (x509CrlEntry == nullptr) {
337 LOGE("x509CrlEntry is nullptr!");
338 return nullptr;
339 }
340 return x509CrlEntry->GetCrlEntrySerialNumber(env, info);
341 }
342
NapiCRLEntryGetSerialNumber(napi_env env,napi_callback_info info)343 static napi_value NapiCRLEntryGetSerialNumber(napi_env env, napi_callback_info info)
344 {
345 napi_value thisVar = nullptr;
346 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
347 NapiX509CrlEntry *x509CrlEntry = nullptr;
348 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
349 if (x509CrlEntry == nullptr) {
350 LOGE("x509CrlEntry is nullptr!");
351 return nullptr;
352 }
353 return x509CrlEntry->GetCRLEntrySerialNumber(env, info);
354 }
355
NapiGetCertificateIssuer(napi_env env,napi_callback_info info)356 static napi_value NapiGetCertificateIssuer(napi_env env, napi_callback_info info)
357 {
358 napi_value thisVar = nullptr;
359 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
360 NapiX509CrlEntry *x509CrlEntry = nullptr;
361 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
362 if (x509CrlEntry == nullptr) {
363 LOGE("x509CrlEntry is nullptr!");
364 return nullptr;
365 }
366 return x509CrlEntry->GetCertificateIssuer(env, info);
367 }
368
NapiGetRevocationDate(napi_env env,napi_callback_info info)369 static napi_value NapiGetRevocationDate(napi_env env, napi_callback_info info)
370 {
371 napi_value thisVar = nullptr;
372 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
373 NapiX509CrlEntry *x509CrlEntry = nullptr;
374 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
375 if (x509CrlEntry == nullptr) {
376 LOGE("x509CrlEntry is nullptr!");
377 return nullptr;
378 }
379 return x509CrlEntry->GetRevocationDate(env, info);
380 }
381
NapiGetExtensions(napi_env env,napi_callback_info info)382 static napi_value NapiGetExtensions(napi_env env, napi_callback_info info)
383 {
384 napi_value thisVar = nullptr;
385 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
386 NapiX509CrlEntry *x509CrlEntry = nullptr;
387 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
388 if (x509CrlEntry == nullptr) {
389 LOGE("x509CrlEntry is nullptr!");
390 return nullptr;
391 }
392 return x509CrlEntry->GetExtensions(env, info);
393 }
394
NapiHasExtensions(napi_env env,napi_callback_info info)395 static napi_value NapiHasExtensions(napi_env env, napi_callback_info info)
396 {
397 napi_value thisVar = nullptr;
398 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
399 NapiX509CrlEntry *x509CrlEntry = nullptr;
400 napi_unwrap(env, thisVar, reinterpret_cast<void **>(&x509CrlEntry));
401 if (x509CrlEntry == nullptr) {
402 LOGE("x509CrlEntry is nullptr!");
403 return nullptr;
404 }
405 return x509CrlEntry->HasExtensions(env, info);
406 }
407
X509CrlEntryConstructor(napi_env env,napi_callback_info info)408 static napi_value X509CrlEntryConstructor(napi_env env, napi_callback_info info)
409 {
410 napi_value thisVar = nullptr;
411 napi_get_cb_info(env, info, nullptr, nullptr, &thisVar, nullptr);
412 return thisVar;
413 }
414
DefineX509CrlEntryJSClass(napi_env env,std::string className)415 void NapiX509CrlEntry::DefineX509CrlEntryJSClass(napi_env env, std::string className)
416 {
417 if (className == std::string("X509CrlEntry")) {
418 napi_property_descriptor x509CrlEntryDesc[] = {
419 DECLARE_NAPI_FUNCTION("getEncoded", NapiGetEncoded),
420 DECLARE_NAPI_FUNCTION("getSerialNumber", NapiCrlEntryGetSerialNumber),
421 DECLARE_NAPI_FUNCTION("getCertIssuer", NapiGetCertificateIssuer),
422 DECLARE_NAPI_FUNCTION("getRevocationDate", NapiGetRevocationDate),
423 };
424 napi_value constructor = nullptr;
425 napi_define_class(env, className.c_str(), NAPI_AUTO_LENGTH, X509CrlEntryConstructor, nullptr,
426 sizeof(x509CrlEntryDesc) / sizeof(x509CrlEntryDesc[0]), x509CrlEntryDesc, &constructor);
427 napi_create_reference(env, constructor, 1, &classCrlRef_);
428 } else {
429 napi_property_descriptor x509CrlEntryDesc[] = {
430 DECLARE_NAPI_FUNCTION("getEncoded", NapiGetEncoded),
431 DECLARE_NAPI_FUNCTION("getSerialNumber", NapiCRLEntryGetSerialNumber),
432 DECLARE_NAPI_FUNCTION("getCertIssuer", NapiGetCertificateIssuer),
433 DECLARE_NAPI_FUNCTION("getRevocationDate", NapiGetRevocationDate),
434 DECLARE_NAPI_FUNCTION("getExtensions", NapiGetExtensions),
435 DECLARE_NAPI_FUNCTION("hasExtensions", NapiHasExtensions),
436 };
437 napi_value constructor = nullptr;
438 napi_define_class(env, className.c_str(), NAPI_AUTO_LENGTH, X509CrlEntryConstructor, nullptr,
439 sizeof(x509CrlEntryDesc) / sizeof(x509CrlEntryDesc[0]), x509CrlEntryDesc, &constructor);
440 napi_create_reference(env, constructor, 1, &classCRLRef_);
441 }
442 }
443
CreateX509CrlEntry(napi_env env,std::string className)444 napi_value NapiX509CrlEntry::CreateX509CrlEntry(napi_env env, std::string className)
445 {
446 napi_value constructor = nullptr;
447 napi_value instance = nullptr;
448 if (className == std::string("X509CrlEntry")) {
449 napi_get_reference_value(env, classCrlRef_, &constructor);
450 } else {
451 napi_get_reference_value(env, classCRLRef_, &constructor);
452 }
453 napi_new_instance(env, constructor, 0, nullptr, &instance);
454 return instance;
455 }
456 } // namespace CertFramework
457 } // namespace OHOS
458