• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 "huks_napi_attest_key.h"
17 
18 #include "securec.h"
19 
20 #include "hks_api.h"
21 #include "hks_log.h"
22 #include "hks_mem.h"
23 #include "hks_param.h"
24 #include "hks_type.h"
25 #include "huks_napi_common.h"
26 
27 namespace HuksNapi {
28 namespace {
29 constexpr int HUKS_NAPI_ATTEST_KEY_MIN_ARGS = 2;
30 constexpr int HUKS_NAPI_ATTEST_KEY_MAX_ARGS = 3;
31 }  // namespace
32 
33 struct AttestKeyAsyncContextT {
34     napi_async_work asyncWork = nullptr;
35     napi_deferred deferred = nullptr;
36     napi_ref callback = nullptr;
37 
38     int32_t result = 0;
39     struct HksBlob *keyAlias = nullptr;
40     struct HksParamSet *paramSet = nullptr;
41     struct HksCertChain *certChain = nullptr;
42 };
43 using AttestKeyAsyncContext = AttestKeyAsyncContextT *;
44 
CreateAttestKeyAsyncContext()45 static AttestKeyAsyncContext CreateAttestKeyAsyncContext()
46 {
47     AttestKeyAsyncContext context = (AttestKeyAsyncContext)HksMalloc(sizeof(AttestKeyAsyncContextT));
48     if (context != nullptr) {
49         (void)memset_s(context, sizeof(AttestKeyAsyncContextT), 0, sizeof(AttestKeyAsyncContextT));
50     }
51     return context;
52 }
53 
DeleteAttestKeyAsyncContext(napi_env env,AttestKeyAsyncContext & context)54 static void DeleteAttestKeyAsyncContext(napi_env env, AttestKeyAsyncContext &context)
55 {
56     if (context == nullptr) {
57         return;
58     }
59 
60     if (context->asyncWork != nullptr) {
61         napi_delete_async_work(env, context->asyncWork);
62         context->asyncWork = nullptr;
63     }
64 
65     if (context->callback != nullptr) {
66         napi_delete_reference(env, context->callback);
67         context->callback = nullptr;
68     }
69 
70     if (context->keyAlias != nullptr) {
71         FreeHksBlob(context->keyAlias);
72     }
73 
74     if (context->paramSet != nullptr) {
75         HksFreeParamSet(&context->paramSet);
76     }
77 
78     if (context->certChain != nullptr) {
79         FreeHksCertChain(context->certChain);
80     }
81 
82     HksFree(context);
83     context = nullptr;
84 }
85 
AttestKeyParseParams(napi_env env,napi_callback_info info,AttestKeyAsyncContext context)86 static napi_value AttestKeyParseParams(napi_env env, napi_callback_info info, AttestKeyAsyncContext context)
87 {
88     size_t argc = HUKS_NAPI_ATTEST_KEY_MAX_ARGS;
89     napi_value argv[HUKS_NAPI_ATTEST_KEY_MAX_ARGS] = {0};
90     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
91 
92     if (argc < HUKS_NAPI_ATTEST_KEY_MIN_ARGS) {
93         napi_throw_error(env, NULL, "invalid arguments");
94         HKS_LOG_E("no enough params");
95         return nullptr;
96     }
97 
98     size_t index = 0;
99     napi_value result = ParseKeyAlias(env, argv[index], context->keyAlias);
100     if (result == nullptr) {
101         HKS_LOG_E("could not get alias");
102         return nullptr;
103     }
104 
105     index++;
106     napi_value properties = nullptr;
107     napi_status status =
108         napi_get_named_property(env, argv[index], HKS_OPTIONS_PROPERTY_PROPERTIES.c_str(), &properties);
109     if (status != napi_ok || properties == nullptr) {
110         GET_AND_THROW_LAST_ERROR((env));
111         HKS_LOG_E("could not get property %s", HKS_OPTIONS_PROPERTY_PROPERTIES.c_str());
112         return nullptr;
113     }
114     result = ParseHksParamSet(env, properties, context->paramSet);
115     if (result == nullptr) {
116         HKS_LOG_E("could not get paramset");
117         return nullptr;
118     }
119 
120     index++;
121     if (index < argc) {
122         context->callback = GetCallback(env, argv[index]);
123     }
124 
125     return GetInt32(env, 0);
126 }
127 
AttestKeyWriteResult(napi_env env,AttestKeyAsyncContext context)128 static napi_value AttestKeyWriteResult(napi_env env, AttestKeyAsyncContext context)
129 {
130     napi_value result = GenerateHksResult(env, context->result, nullptr, 0);
131     if (result != nullptr) {
132         napi_value certChains = GenerateStringArray(env, context->certChain->certs, context->certChain->certsCount);
133         if (certChains != nullptr) {
134             napi_set_named_property(env, result, HKS_RESULT_PRPPERTY_CERTCHAINS.c_str(), certChains);
135         }
136     }
137     return result;
138 }
139 
AttestKeyAsyncWork(napi_env env,AttestKeyAsyncContext context)140 static napi_value AttestKeyAsyncWork(napi_env env, AttestKeyAsyncContext context)
141 {
142     napi_value promise = nullptr;
143     if (context->callback == nullptr) {
144         NAPI_CALL(env, napi_create_promise(env, &context->deferred, &promise));
145     }
146 
147     napi_value resourceName = nullptr;
148     napi_create_string_latin1(env, "attestKeyAsyncWork", NAPI_AUTO_LENGTH, &resourceName);
149 
150     napi_create_async_work(
151         env,
152         nullptr,
153         resourceName,
154         [](napi_env env, void *data) {
155             AttestKeyAsyncContext context = static_cast<AttestKeyAsyncContext>(data);
156 
157             context->certChain = (struct HksCertChain *)HksMalloc(sizeof(struct HksCertChain));
158             if (context->certChain != nullptr) {
159                 context->certChain->certs = nullptr;
160                 context->certChain->certsCount = 0;
161             }
162 
163             context->result = HksAttestKey(context->keyAlias, context->paramSet, context->certChain);
164         },
165         [](napi_env env, napi_status status, void *data) {
166             AttestKeyAsyncContext context = static_cast<AttestKeyAsyncContext>(data);
167             napi_value result = AttestKeyWriteResult(env, context);
168             if (result == nullptr) {
169                 return;
170             }
171             if (context->callback != nullptr) {
172                 CallAsyncCallback(env, context->callback, context->result, result);
173             } else {
174                 napi_resolve_deferred(env, context->deferred, result);
175             }
176             DeleteAttestKeyAsyncContext(env, context);
177         },
178         (void *)context,
179         &context->asyncWork);
180 
181     napi_status status = napi_queue_async_work(env, context->asyncWork);
182     if (status != napi_ok) {
183         GET_AND_THROW_LAST_ERROR((env));
184         DeleteAttestKeyAsyncContext(env, context);
185         HKS_LOG_E("could not queue async work");
186         return nullptr;
187     }
188 
189     if (context->callback == nullptr) {
190         return promise;
191     } else {
192         return GetNull(env);
193     }
194     return nullptr;
195 }
196 
HuksNapiAttestKey(napi_env env,napi_callback_info info)197 napi_value HuksNapiAttestKey(napi_env env, napi_callback_info info)
198 {
199     AttestKeyAsyncContext context = CreateAttestKeyAsyncContext();
200     if (context == nullptr) {
201         HKS_LOG_E("could not create context");
202         return nullptr;
203     }
204 
205     napi_value result = AttestKeyParseParams(env, info, context);
206     if (result == nullptr) {
207         HKS_LOG_E("could not parse params");
208         DeleteAttestKeyAsyncContext(env, context);
209         return nullptr;
210     }
211 
212     result = AttestKeyAsyncWork(env, context);
213     if (result == nullptr) {
214         HKS_LOG_E("could not start async work");
215         DeleteAttestKeyAsyncContext(env, context);
216         return nullptr;
217     }
218     return result;
219 }
220 }  // namespace HuksNapi
221