• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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, &paramsError));
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