1 /*
2 * Copyright (c) 2022 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 "cm_napi_common.h"
17
18 #include "securec.h"
19
20 #include "cm_log.h"
21 #include "cm_type.h"
22
23 namespace CMNapi {
24 namespace {
25 constexpr int CM_MAX_DATA_LEN = 0x6400000; // The maximum length is 100M
26 constexpr int RESULT_ARG_NUMBER = 2;
27 } // namespace
28
ParseUint32(napi_env env,napi_value object,uint32_t & store)29 napi_value ParseUint32(napi_env env, napi_value object, uint32_t &store)
30 {
31 napi_valuetype valueType;
32 napi_typeof(env, object, &valueType);
33 if (valueType != napi_number) {
34 CM_LOG_E("param type is not number");
35 return nullptr;
36 }
37 uint32_t temp = 0;
38 napi_get_value_uint32(env, object, &temp);
39 store = temp;
40 return GetInt32(env, 0);
41 }
42
ParseBoolean(napi_env env,napi_value object,bool & status)43 napi_value ParseBoolean(napi_env env, napi_value object, bool &status)
44 {
45 napi_valuetype valueType;
46 napi_typeof(env, object, &valueType);
47 if (valueType != napi_boolean) {
48 CM_LOG_E("param type is not bool");
49 return nullptr;
50 }
51 bool temp = false;
52 napi_get_value_bool(env, object, &temp);
53 status = temp;
54 return GetInt32(env, 0);
55 }
56
ParseString(napi_env env,napi_value object,CmBlob * & certUri)57 napi_value ParseString(napi_env env, napi_value object, CmBlob *&certUri)
58 {
59 napi_valuetype valueType = napi_undefined;
60 NAPI_CALL(env, napi_typeof(env, object, &valueType));
61 if (valueType != napi_string) {
62 CM_LOG_E("the type of param is not string");
63 return nullptr;
64 }
65 size_t length = 0;
66 napi_status status = napi_get_value_string_utf8(env, object, nullptr, 0, &length);
67 if (status != napi_ok) {
68 GET_AND_THROW_LAST_ERROR((env));
69 CM_LOG_E("could not get string length");
70 return nullptr;
71 }
72
73 if (length > CM_MAX_DATA_LEN) {
74 CM_LOG_E("input key alias length too large");
75 return nullptr;
76 }
77
78 char *data = static_cast<char *>(CmMalloc(length + 1));
79 if (data == nullptr) {
80 napi_throw_error(env, nullptr, "could not alloc memory");
81 CM_LOG_E("could not alloc memory");
82 return nullptr;
83 }
84 (void)memset_s(data, length + 1, 0, length + 1);
85
86 size_t result = 0;
87 status = napi_get_value_string_utf8(env, object, data, length + 1, &result);
88 if (status != napi_ok) {
89 CmFree(data);
90 GET_AND_THROW_LAST_ERROR((env));
91 CM_LOG_E("could not get string");
92 return nullptr;
93 }
94
95 certUri = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
96 if (certUri == nullptr) {
97 CmFree(data);
98 napi_throw_error(env, nullptr, "could not alloc memory");
99 CM_LOG_E("could not alloc memory");
100 return nullptr;
101 }
102 certUri->data = reinterpret_cast<uint8_t *>(data);
103 certUri->size = static_cast<uint32_t>((length + 1) & UINT32_MAX);
104
105 return GetInt32(env, 0);
106 }
107
GetUint8Array(napi_env env,napi_value object,CmBlob & arrayBlob)108 napi_value GetUint8Array(napi_env env, napi_value object, CmBlob &arrayBlob)
109 {
110 napi_typedarray_type arrayType;
111 napi_value arrayBuffer = nullptr;
112 size_t length = 0;
113 size_t offset = 0;
114 void *rawData = nullptr;
115 NAPI_CALL(
116 env, napi_get_typedarray_info(env, object, &arrayType, &length,
117 static_cast<void **>(&rawData), &arrayBuffer, &offset));
118 NAPI_ASSERT(env, arrayType == napi_uint8_array, "Param is not uint8 array");
119
120 if (length > CM_MAX_DATA_LEN) {
121 CM_LOG_E("Data is too large, length = %x", length);
122 return nullptr;
123 }
124 if (length == 0) {
125 CM_LOG_I("The memory length created is only 1 Byte");
126 // The memory length created is only 1 Byte
127 arrayBlob.data = static_cast<uint8_t *>(CmMalloc(1));
128 } else {
129 arrayBlob.data = static_cast<uint8_t *>(CmMalloc(length));
130 }
131 if (arrayBlob.data == nullptr) {
132 CM_LOG_E("Malloc failed");
133 return nullptr;
134 }
135 (void)memset_s(arrayBlob.data, length, 0, length);
136 if (memcpy_s(arrayBlob.data, length, rawData, length) != EOK) {
137 return nullptr;
138 }
139 arrayBlob.size = static_cast<uint32_t>(length);
140
141 return GetInt32(env, 0);
142 }
143
GetCallback(napi_env env,napi_value object)144 napi_ref GetCallback(napi_env env, napi_value object)
145 {
146 napi_valuetype valueType = napi_undefined;
147 napi_status status = napi_typeof(env, object, &valueType);
148 if (status != napi_ok) {
149 CM_LOG_E("could not get object type");
150 return nullptr;
151 }
152
153 if (valueType != napi_function) {
154 CM_LOG_E("invalid type");
155 return nullptr;
156 }
157
158 napi_ref ref = nullptr;
159 status = napi_create_reference(env, object, 1, &ref);
160 if (status != napi_ok) {
161 CM_LOG_E("could not create reference");
162 return nullptr;
163 }
164 return ref;
165 }
166
GenerateAarrayBuffer(napi_env env,uint8_t * data,uint32_t size)167 static napi_value GenerateAarrayBuffer(napi_env env, uint8_t *data, uint32_t size)
168 {
169 uint8_t *buffer = static_cast<uint8_t *>(CmMalloc(size));
170 if (buffer == nullptr) {
171 return nullptr;
172 }
173 (void)memcpy_s(buffer, size, data, size);
174
175 napi_value outBuffer = nullptr;
176 napi_status status = napi_create_external_arraybuffer(
177 env, buffer, size, [](napi_env env, void *data, void *hint) { CmFree(data); }, nullptr, &outBuffer);
178 if (status == napi_ok) {
179 // free by finalize callback
180 buffer = nullptr;
181 } else {
182 CmFree(buffer);
183 GET_AND_THROW_LAST_ERROR((env));
184 }
185
186 return outBuffer;
187 }
188
GenerateCertAbstractArray(napi_env env,const struct CertAbstract * certAbstract,const uint32_t certCount)189 napi_value GenerateCertAbstractArray(napi_env env, const struct CertAbstract *certAbstract, const uint32_t certCount)
190 {
191 if (certCount == 0 || certAbstract == nullptr) {
192 return nullptr;
193 }
194 napi_value array = nullptr;
195 NAPI_CALL(env, napi_create_array(env, &array));
196 for (uint32_t i = 0; i < certCount; i++) {
197 napi_value uri = nullptr;
198 napi_value certAlias = nullptr;
199 napi_value subjectName = nullptr;
200 napi_value status = nullptr;
201
202 napi_create_string_latin1(env, static_cast<const char *>(certAbstract[i].uri), NAPI_AUTO_LENGTH, &uri);
203 napi_create_string_latin1(env, static_cast<const char *>(certAbstract[i].certAlias),
204 NAPI_AUTO_LENGTH, &certAlias);
205 napi_create_string_latin1(env, static_cast<const char *>(certAbstract[i].subjectName),
206 NAPI_AUTO_LENGTH, &subjectName);
207 napi_get_boolean(env, certAbstract[i].status, &status);
208
209 napi_value element = nullptr;
210 napi_create_object(env, &element);
211 napi_set_named_property (env, element, CM_CERT_PROPERTY_URI.c_str(), uri);
212 napi_set_named_property (env, element, CM_CERT_PROPERTY_CERTALIAS.c_str(), certAlias);
213 napi_set_named_property (env, element, CM_CERT_PROPERTY_STATUS.c_str(), status);
214 napi_set_named_property (env, element, CM_CERT_PROPERTY_SUBJECTNAME.c_str(), subjectName);
215
216 napi_set_element(env, array, i, element);
217 }
218 return array;
219 }
220
GenerateCredentialAbstractArray(napi_env env,const struct CredentialAbstract * credentialAbstract,const uint32_t credentialCount)221 napi_value GenerateCredentialAbstractArray(napi_env env,
222 const struct CredentialAbstract *credentialAbstract, const uint32_t credentialCount)
223 {
224 if (credentialCount == 0 || credentialAbstract == nullptr) {
225 return nullptr;
226 }
227 napi_value array = nullptr;
228 NAPI_CALL(env, napi_create_array(env, &array));
229 for (uint32_t i = 0; i < credentialCount; i++) {
230 napi_value type = nullptr;
231 napi_value alias = nullptr;
232 napi_value keyUri = nullptr;
233 napi_create_string_latin1(env, static_cast<const char *>(credentialAbstract[i].type),
234 NAPI_AUTO_LENGTH, &type);
235 napi_create_string_latin1(env, static_cast<const char *>(credentialAbstract[i].alias),
236 NAPI_AUTO_LENGTH, &alias);
237 napi_create_string_latin1(env, static_cast<const char *>(credentialAbstract[i].keyUri),
238 NAPI_AUTO_LENGTH, &keyUri);
239
240 napi_value element = nullptr;
241 napi_create_object(env, &element);
242 napi_set_named_property (env, element, CM_CERT_PROPERTY_TYPE.c_str(), type);
243 napi_set_named_property (env, element, CM_CERT_PROPERTY_CREDENTIAL_ALIAS.c_str(), alias);
244 napi_set_named_property (env, element, CM_CERT_PROPERTY_KEY_URI.c_str(), keyUri);
245
246 napi_set_element(env, array, i, element);
247 }
248 return array;
249 }
250
GenerateCertInfo(napi_env env,const struct CertInfo * certInfo)251 napi_value GenerateCertInfo(napi_env env, const struct CertInfo *certInfo)
252 {
253 if (certInfo == nullptr) {
254 return nullptr;
255 }
256 napi_value result = nullptr;
257 NAPI_CALL(env, napi_create_object(env, &result));
258
259 struct CertInfoValue cInfVal = { nullptr };
260 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->uri),
261 NAPI_AUTO_LENGTH, &cInfVal.uri));
262 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->certAlias),
263 NAPI_AUTO_LENGTH, &cInfVal.certAlias));
264 NAPI_CALL(env, napi_get_boolean(env, certInfo->status, &cInfVal.status));
265 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->issuerName),
266 NAPI_AUTO_LENGTH, &cInfVal.issuerName));
267 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->subjectName),
268 NAPI_AUTO_LENGTH, &cInfVal.subjectName));
269 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->serial),
270 NAPI_AUTO_LENGTH, &cInfVal.serial));
271 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->notBefore),
272 NAPI_AUTO_LENGTH, &cInfVal.notBefore));
273 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->notAfter),
274 NAPI_AUTO_LENGTH, &cInfVal.notAfter));
275 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(certInfo->fingerprintSha256),
276 NAPI_AUTO_LENGTH, &cInfVal.fingerprintSha256));
277
278 napi_value certBuffer = GenerateAarrayBuffer(env, certInfo->certInfo.data, certInfo->certInfo.size);
279 if (certBuffer != nullptr) {
280 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, certInfo->certInfo.size,
281 certBuffer, 0, &cInfVal.certInfoBlob));
282 }
283
284 napi_value elem = nullptr;
285 NAPI_CALL(env, napi_create_object(env, &elem));
286 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_URI.c_str(), cInfVal.uri));
287 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_CERTALIAS.c_str(), cInfVal.certAlias));
288 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_STATUS.c_str(), cInfVal.status));
289 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_ISSUERNAME.c_str(), cInfVal.issuerName));
290 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_SUBJECTNAME.c_str(), cInfVal.subjectName));
291 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_SERIAL.c_str(), cInfVal.serial));
292 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_BEFORE.c_str(), cInfVal.notBefore));
293 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_AFTER.c_str(), cInfVal.notAfter));
294 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_FINGERSHA256.c_str(),
295 cInfVal.fingerprintSha256));
296 NAPI_CALL(env, napi_set_named_property(env, elem, CM_CERT_PROPERTY_CERT_DATA.c_str(), cInfVal.certInfoBlob));
297
298 return elem;
299 }
300
TranformErrorCode(int32_t errorCode)301 int32_t TranformErrorCode(int32_t errorCode)
302 {
303 if (errorCode == CMR_ERROR_INVALID_CERT_FORMAT || errorCode == CMR_ERROR_INSUFFICIENT_DATA) {
304 return INVALID_CERT_FORMAT;
305 }
306 if (errorCode == CMR_ERROR_NOT_FOUND || errorCode == CMR_ERROR_NOT_EXIST) {
307 return NOT_FOUND;
308 }
309 if (errorCode == CMR_ERROR_NOT_PERMITTED) {
310 return NO_PERMISSION;
311 }
312 if (errorCode == CMR_ERROR_NOT_SYSTEMP_APP) {
313 return NOT_SYSTEM_APP;
314 }
315 return INNER_FAILURE;
316 }
317
GenerateBusinessError(napi_env env,int32_t errorCode,const char * errorMsg)318 napi_value GenerateBusinessError(napi_env env, int32_t errorCode, const char *errorMsg)
319 {
320 napi_value businessError = nullptr;
321 NAPI_CALL(env, napi_create_object(env, &businessError));
322
323 napi_value code = nullptr;
324 int32_t outCode = TranformErrorCode(errorCode);
325 NAPI_CALL(env, napi_create_int32(env, outCode, &code));
326 NAPI_CALL(env, napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code));
327 napi_value message = nullptr;
328 NAPI_CALL(env, napi_create_string_utf8(env, errorMsg, NAPI_AUTO_LENGTH, &message));
329 NAPI_CALL(env, napi_set_named_property(env, businessError, BUSINESS_ERROR_PROPERTY_MESSAGE.c_str(), message));
330 return businessError;
331 }
332
ThrowParamsError(napi_env env,int32_t errorCode,std::string errMsg)333 void ThrowParamsError(napi_env env, int32_t errorCode, std::string errMsg)
334 {
335 napi_value paramsError = nullptr;
336 napi_value code = nullptr;
337 napi_value message = nullptr;
338 NAPI_CALL_RETURN_VOID(env, napi_create_int32(env, errorCode, &code));
339 NAPI_CALL_RETURN_VOID(env, napi_create_string_utf8(env, errMsg.c_str(), NAPI_AUTO_LENGTH, &message));
340 NAPI_CALL_RETURN_VOID(env, napi_create_error(env, nullptr, message, ¶msError));
341 NAPI_CALL_RETURN_VOID(env, napi_set_named_property(env, paramsError, BUSINESS_ERROR_PROPERTY_CODE.c_str(), code));
342 NAPI_CALL_RETURN_VOID(env, napi_throw(env, paramsError));
343 }
344
GenerateAppCertInfo(napi_env env,const struct Credential * credential)345 napi_value GenerateAppCertInfo(napi_env env, const struct Credential *credential)
346 {
347 if (credential == nullptr) {
348 return nullptr;
349 }
350 napi_value result = nullptr;
351 NAPI_CALL(env, napi_create_object(env, &result));
352 napi_value type = nullptr;
353 napi_value alias = nullptr;
354 napi_value keyUri = nullptr;
355 napi_value certNum = nullptr;
356 napi_value keyNum = nullptr;
357 napi_value credData = nullptr;
358 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(credential->type),
359 NAPI_AUTO_LENGTH, &type));
360 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(credential->alias),
361 NAPI_AUTO_LENGTH, &alias));
362 NAPI_CALL(env, napi_create_string_latin1(env, static_cast<const char *>(credential->keyUri),
363 NAPI_AUTO_LENGTH, &keyUri));
364
365 NAPI_CALL(env, napi_create_int32(env, credential->certNum, &certNum));
366 NAPI_CALL(env, napi_create_int32(env, credential->keyNum, &keyNum));
367
368 napi_value crendentialBuffer = GenerateAarrayBuffer(env, credential->credData.data, credential->credData.size);
369 if (crendentialBuffer != nullptr) {
370 NAPI_CALL(env, napi_create_typedarray(env, napi_uint8_array, credential->credData.size,
371 crendentialBuffer, 0, &credData));
372 }
373
374 napi_value element = nullptr;
375 NAPI_CALL(env, napi_create_object(env, &element));
376 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_TYPE.c_str(), type));
377 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_CREDENTIAL_ALIAS.c_str(), alias));
378 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_KEY_URI.c_str(), keyUri));
379 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_CERT_NUM.c_str(), certNum));
380 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_KEY_NUM.c_str(), keyNum));
381
382 NAPI_CALL(env, napi_set_named_property(env, element, CM_CERT_PROPERTY_CREDENTIAL_DATA.c_str(), credData));
383
384 return element;
385 }
386
GeneratePromise(napi_env env,napi_deferred deferred,int32_t resultCode,napi_value * result,int32_t arrLength)387 void GeneratePromise(napi_env env, napi_deferred deferred, int32_t resultCode,
388 napi_value *result, int32_t arrLength)
389 {
390 if (arrLength < RESULT_NUMBER) {
391 return;
392 }
393 if (resultCode == CM_SUCCESS) {
394 NAPI_CALL_RETURN_VOID(env, napi_resolve_deferred(env, deferred, result[1]));
395 } else {
396 NAPI_CALL_RETURN_VOID(env, napi_reject_deferred(env, deferred, result[0]));
397 }
398 }
399
GenerateCallback(napi_env env,napi_ref callback,napi_value * result,int32_t arrLength)400 void GenerateCallback(napi_env env, napi_ref callback, napi_value *result, int32_t arrLength)
401 {
402 napi_value func = nullptr;
403 napi_value returnVal = nullptr;
404 if (arrLength < RESULT_NUMBER) {
405 return;
406 }
407 NAPI_CALL_RETURN_VOID(env, napi_get_reference_value(env, callback, &func));
408 NAPI_CALL_RETURN_VOID(env, napi_call_function(env, nullptr, func, RESULT_ARG_NUMBER, result, &returnVal));
409 }
410
GenerateNapiPromise(napi_env env,napi_ref callback,napi_deferred * deferred,napi_value * promise)411 void GenerateNapiPromise(napi_env env, napi_ref callback, napi_deferred *deferred, napi_value *promise)
412 {
413 if (callback == nullptr) {
414 NAPI_CALL_RETURN_VOID(env, napi_create_promise(env, deferred, promise));
415 } else {
416 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, promise));
417 }
418 }
419
DeleteNapiContext(napi_env env,napi_async_work & asyncWork,napi_ref & callback)420 void DeleteNapiContext(napi_env env, napi_async_work &asyncWork, napi_ref &callback)
421 {
422 if (asyncWork != nullptr) {
423 napi_delete_async_work(env, asyncWork);
424 asyncWork = nullptr;
425 }
426
427 if (callback != nullptr) {
428 napi_delete_reference(env, callback);
429 callback = nullptr;
430 }
431 }
432
FreeCmContext(CmContext * & context)433 void FreeCmContext(CmContext *&context)
434 {
435 if (context == nullptr) {
436 return;
437 }
438
439 context->userId = 0;
440 context->uid = 0;
441
442 CmFree(context);
443 context = nullptr;
444 }
445
FreeCertList(CertList * & certList)446 void FreeCertList(CertList *&certList)
447 {
448 if (certList == nullptr || certList->certAbstract == nullptr) {
449 return;
450 }
451
452 FreeCertAbstract(certList->certAbstract);
453 certList->certAbstract = nullptr;
454
455 CmFree(certList);
456 certList = nullptr;
457 }
458
FreeCredentialList(CredentialList * & credentialList)459 void FreeCredentialList(CredentialList *&credentialList)
460 {
461 if (credentialList == nullptr || credentialList->credentialAbstract == nullptr) {
462 return;
463 }
464
465 FreeCredentialAbstract(credentialList->credentialAbstract);
466 credentialList->credentialAbstract = nullptr;
467
468 CmFree(credentialList);
469 credentialList = nullptr;
470 }
471
FreeCertInfo(CertInfo * & certInfo)472 void FreeCertInfo(CertInfo *&certInfo)
473 {
474 if (certInfo == nullptr) {
475 return;
476 }
477
478 certInfo->status = false;
479
480 if (certInfo->certInfo.data != nullptr) {
481 CmFree(certInfo->certInfo.data);
482 }
483
484 CmFree(certInfo);
485 certInfo = nullptr;
486 }
487
FreeCredential(Credential * & credential)488 void FreeCredential(Credential *&credential)
489 {
490 if (credential == nullptr) {
491 return;
492 }
493
494 if (credential->credData.data != nullptr) {
495 CmFree(credential->credData.data);
496 }
497
498 CmFree(credential);
499 credential = nullptr;
500 }
501 } // namespace CertManagerNapi
502