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_install_app_cert.h"
17 #include "cm_napi_install_app_cert_common.h"
18
19 #include "securec.h"
20
21 #include "cert_manager_api.h"
22 #include "cm_log.h"
23 #include "cm_mem.h"
24 #include "cm_type.h"
25 #include "cm_napi_common.h"
26
27 namespace CMNapi {
28 namespace {
29 constexpr int CM_NAPI_INSTALL_APP_CERT_MIN_ARGS = 3;
30 constexpr int CM_NAPI_INSTALL_APP_CERT_MAX_ARGS = 4;
31 } // namespace
32
CreateInstallAppCertAsyncContext()33 InstallAppCertAsyncContext CreateInstallAppCertAsyncContext()
34 {
35 InstallAppCertAsyncContext context =
36 static_cast<InstallAppCertAsyncContext>(CmMalloc(sizeof(InstallAppCertAsyncContextT)));
37 if (context != nullptr) {
38 (void)memset_s(context, sizeof(InstallAppCertAsyncContextT), 0, sizeof(InstallAppCertAsyncContextT));
39 }
40 return context;
41 }
42
DeleteInstallAppCertAsyncContext(napi_env env,InstallAppCertAsyncContext & context)43 void DeleteInstallAppCertAsyncContext(napi_env env, InstallAppCertAsyncContext &context)
44 {
45 if (context == nullptr) {
46 return;
47 }
48
49 DeleteNapiContext(env, context->asyncWork, context->callback);
50
51 if (context->keystore != nullptr) {
52 FreeCmBlob(context->keystore);
53 }
54
55 if (context->keystorePwd != nullptr) {
56 FreeCmBlob(context->keystorePwd);
57 }
58
59 if (context->keyAlias != nullptr) {
60 FreeCmBlob(context->keyAlias);
61 }
62
63 if (context->keyUri != nullptr) {
64 FreeCmBlob(context->keyUri);
65 }
66
67 CmFree(context);
68 context = nullptr;
69 }
70
GetCredAlias(napi_env env,napi_value napiObject,CmBlob * & certAlias,uint32_t store)71 static napi_value GetCredAlias(napi_env env, napi_value napiObject, CmBlob *&certAlias, uint32_t store)
72 {
73 if (store == APPLICATION_PRIVATE_CERTIFICATE_STORE) {
74 return ParseString(env, napiObject, certAlias);
75 }
76 return ParseCertAlias(env, napiObject, certAlias);
77 }
78
InstallAppCertParseParams(napi_env env,napi_callback_info info,InstallAppCertAsyncContext context,uint32_t store)79 napi_value InstallAppCertParseParams(
80 napi_env env, napi_callback_info info, InstallAppCertAsyncContext context, uint32_t store)
81 {
82 size_t argc = CM_NAPI_INSTALL_APP_CERT_MAX_ARGS;
83 napi_value argv[CM_NAPI_INSTALL_APP_CERT_MAX_ARGS] = { nullptr };
84 NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
85
86 if ((argc != CM_NAPI_INSTALL_APP_CERT_MIN_ARGS) && (argc != CM_NAPI_INSTALL_APP_CERT_MAX_ARGS)) {
87 ThrowError(env, PARAM_ERROR, "arguments count invalid, arguments count need between 3 and 4.");
88 CM_LOG_E("arguments count invalid. argc = %d", argc);
89 return nullptr;
90 }
91
92 size_t index = 0;
93 context->keystore = static_cast<CmBlob *>(CmMalloc(sizeof(CmBlob)));
94 if (context->keystore == nullptr) {
95 CM_LOG_E("could not alloc memory");
96 return nullptr;
97 }
98 (void)memset_s(context->keystore, sizeof(CmBlob), 0, sizeof(CmBlob));
99
100 napi_value result = GetUint8Array(env, argv[index], *context->keystore);
101 if (result == nullptr) {
102 ThrowError(env, PARAM_ERROR, "keystore is not a uint8Array or the length is 0 or too long.");
103 CM_LOG_E("could not get keystore");
104 return nullptr;
105 }
106
107 index++;
108 result = ParseString(env, argv[index], context->keystorePwd);
109 if (result == nullptr) {
110 ThrowError(env, PARAM_ERROR, "keystore Pwd is not a string or the length is 0 or too long.");
111 CM_LOG_E("could not get keystore Pwd");
112 return nullptr;
113 }
114
115 index++;
116 result = GetCredAlias(env, argv[index], context->keyAlias, store);
117 if (result == nullptr) {
118 ThrowError(env, PARAM_ERROR, "keyAlias is not a string or the length is 0 or too long.");
119 CM_LOG_E("could not get uri");
120 return nullptr;
121 }
122
123 index++;
124 if (index < argc) {
125 int32_t ret = GetCallback(env, argv[index], context->callback);
126 if (ret != CM_SUCCESS) {
127 ThrowError(env, PARAM_ERROR, "Get callback failed, callback must be a function.");
128 CM_LOG_E("get callback function faild when install application cert");
129 return nullptr;
130 }
131 }
132
133 return GetInt32(env, 0);
134 }
135
InitKeyUri(struct CmBlob * & keyUri)136 static void InitKeyUri(struct CmBlob *&keyUri)
137 {
138 keyUri = static_cast<struct CmBlob *>(CmMalloc(sizeof(struct CmBlob)));
139 if (keyUri == nullptr) {
140 CM_LOG_E("malloc keyUri buffer failed");
141 return;
142 }
143
144 keyUri->data = static_cast<uint8_t *>(CmMalloc(MAX_LEN_URI));
145 if (keyUri->data == nullptr) {
146 CM_LOG_E("malloc keyUri->data buffer failed");
147 return;
148 }
149
150 (void)memset_s(keyUri->data, MAX_LEN_URI, 0, MAX_LEN_URI);
151 keyUri->size = MAX_LEN_URI;
152 }
153
InstallAppCertWriteResult(napi_env env,InstallAppCertAsyncContext context)154 static napi_value InstallAppCertWriteResult(napi_env env, InstallAppCertAsyncContext context)
155 {
156 napi_value result = nullptr;
157 NAPI_CALL(env, napi_create_object(env, &result));
158
159 napi_value keyUri = nullptr;
160 NAPI_CALL(env, napi_create_string_latin1(env, reinterpret_cast<char *>(context->keyUri->data),
161 NAPI_AUTO_LENGTH, &keyUri));
162 if (keyUri != nullptr) {
163 napi_set_named_property(env, result, CM_CERT_PROPERTY_URI.c_str(), keyUri);
164 } else {
165 NAPI_CALL(env, napi_get_undefined(env, &result));
166 }
167 return result;
168 }
169
GenAppCertBusinessError(napi_env env,int32_t errorCode,uint32_t store)170 static napi_value GenAppCertBusinessError(napi_env env, int32_t errorCode, uint32_t store)
171 {
172 if ((errorCode == CMR_ERROR_PASSWORD_IS_ERR) && (store == APPLICATION_PRIVATE_CERTIFICATE_STORE)) {
173 errorCode = CMR_ERROR_INVALID_CERT_FORMAT;
174 }
175 return GenerateBusinessError(env, errorCode);
176 }
177
InstallAppCertAsyncWork(napi_env env,InstallAppCertAsyncContext asyncContext)178 napi_value InstallAppCertAsyncWork(napi_env env, InstallAppCertAsyncContext asyncContext)
179 {
180 napi_value promise = nullptr;
181 GenerateNapiPromise(env, asyncContext->callback, &asyncContext->deferred, &promise);
182
183 napi_value resourceName = nullptr;
184 NAPI_CALL(env, napi_create_string_latin1(env, "InstallAppCertAsyncWork", NAPI_AUTO_LENGTH, &resourceName));
185
186 NAPI_CALL(env, napi_create_async_work(
187 env,
188 nullptr,
189 resourceName,
190 [](napi_env env, void *data) {
191 InstallAppCertAsyncContext context = static_cast<InstallAppCertAsyncContext>(data);
192 InitKeyUri(context->keyUri);
193 context->result = CmInstallAppCert(context->keystore,
194 context->keystorePwd, context->keyAlias, context->store, context->keyUri);
195 },
196 [](napi_env env, napi_status status, void *data) {
197 InstallAppCertAsyncContext context = static_cast<InstallAppCertAsyncContext>(data);
198 napi_value result[RESULT_NUMBER] = { nullptr };
199 if (context->result == CM_SUCCESS) {
200 NAPI_CALL_RETURN_VOID(env, napi_create_uint32(env, 0, &result[0]));
201 result[1] = InstallAppCertWriteResult(env, context);
202 } else {
203 result[0] = GenAppCertBusinessError(env, context->result, context->store);
204 NAPI_CALL_RETURN_VOID(env, napi_get_undefined(env, &result[1]));
205 }
206 if (context->deferred != nullptr) {
207 GeneratePromise(env, context->deferred, context->result, result, CM_ARRAY_SIZE(result));
208 } else {
209 GenerateCallback(env, context->callback, result, CM_ARRAY_SIZE(result), context->result);
210 }
211 DeleteInstallAppCertAsyncContext(env, context);
212 },
213 static_cast<void *>(asyncContext),
214 &asyncContext->asyncWork));
215
216 napi_status status = napi_queue_async_work(env, asyncContext->asyncWork);
217 if (status != napi_ok) {
218 GET_AND_THROW_LAST_ERROR((env));
219 DeleteInstallAppCertAsyncContext(env, asyncContext);
220 CM_LOG_E("could not queue async work");
221 return nullptr;
222 }
223 return promise;
224 }
225
CMNapiInstallAppCertCommon(napi_env env,napi_callback_info info,uint32_t store)226 napi_value CMNapiInstallAppCertCommon(napi_env env, napi_callback_info info, uint32_t store)
227 {
228 InstallAppCertAsyncContext context = CreateInstallAppCertAsyncContext();
229 if (context == nullptr) {
230 CM_LOG_E("could not create context");
231 return nullptr;
232 }
233
234 context->store = store;
235
236 napi_value result = InstallAppCertParseParams(env, info, context, store);
237 if (result == nullptr) {
238 CM_LOG_E("could not parse params");
239 DeleteInstallAppCertAsyncContext(env, context);
240 return nullptr;
241 }
242 result = InstallAppCertAsyncWork(env, context);
243 if (result == nullptr) {
244 CM_LOG_E("could not start async work");
245 DeleteInstallAppCertAsyncContext(env, context);
246 return nullptr;
247 }
248 return result;
249 }
250 } // namespace CertManagerNapi
251