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 "auth_instance_v9.h"
17 
18 #include <string>
19 
20 #include "iam_logger.h"
21 #include "iam_ptr.h"
22 
23 #include "user_auth_client_impl.h"
24 
25 #define LOG_TAG "USER_AUTH_NAPI"
26 
27 namespace OHOS {
28 namespace UserIam {
29 namespace UserAuth {
30 namespace {
31     const std::string AUTH_EVENT_RESULT = "result";
32     const std::string AUTH_EVENT_TIP = "tip";
33 }
34 
GetAvailableStatus(napi_env env,napi_callback_info info)35 UserAuthResultCode AuthInstanceV9::GetAvailableStatus(napi_env env, napi_callback_info info)
36 {
37     napi_value argv[ARGS_TWO];
38     size_t argc = ARGS_TWO;
39     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
40     if (ret != napi_ok) {
41         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
42         return UserAuthResultCode::GENERAL_ERROR;
43     }
44     if (argc != ARGS_TWO) {
45         IAM_LOGE("invalid param, argc:%{public}zu", argc);
46         std::string msgStr = "Parameter error. The number of parameters should be 2.";
47         return UserAuthNapiHelper::ThrowErrorMsg(env, UserAuthResultCode::OHOS_INVALID_PARAM, msgStr);
48     }
49     int32_t type;
50     ret = napi_get_value_int32(env, argv[PARAM0], &type);
51     if (ret != napi_ok) {
52         IAM_LOGE("napi_get_value_int32 fail:%{public}d", ret);
53         return UserAuthResultCode::GENERAL_ERROR;
54     }
55     if (!UserAuthNapiHelper::CheckUserAuthType(type)) {
56         IAM_LOGE("CheckUserAuthType fail");
57         return UserAuthResultCode::TYPE_NOT_SUPPORT;
58     }
59     uint32_t level;
60     ret = napi_get_value_uint32(env, argv[PARAM1], &level);
61     if (ret != napi_ok) {
62         IAM_LOGE("napi_get_value_int32 fail:%{public}d", ret);
63         return UserAuthResultCode::GENERAL_ERROR;
64     }
65     if (!UserAuthNapiHelper::CheckAuthTrustLevel(level)) {
66         IAM_LOGE("CheckAuthTrustLevel fail");
67         return UserAuthResultCode::TRUST_LEVEL_NOT_SUPPORT;
68     }
69     AuthType authType = AuthType(type);
70     AuthTrustLevel authTrustLevel = AuthTrustLevel(level);
71     int32_t status = UserAuthClientImpl::Instance().GetNorthAvailableStatus(API_VERSION_9, authType, authTrustLevel);
72     IAM_LOGI("result = %{public}d", status);
73     if (status == PIN_EXPIRED) {
74         return UserAuthResultCode::PIN_EXPIRED;
75     }
76     return UserAuthResultCode(UserAuthNapiHelper::GetResultCodeV9(status));
77 }
78 
AuthInstanceV9(napi_env env)79 AuthInstanceV9::AuthInstanceV9(napi_env env) : callback_(Common::MakeShared<UserAuthCallbackV9>(env))
80 {
81     if (callback_ == nullptr) {
82         IAM_LOGE("get null callback");
83     }
84 }
85 
InitChallenge(napi_env env,napi_value value)86 napi_status AuthInstanceV9::InitChallenge(napi_env env, napi_value value)
87 {
88     challenge_.clear();
89     napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_null);
90     if (ret == napi_ok) {
91         IAM_LOGI("challenge is null");
92         return ret;
93     }
94     ret = UserAuthNapiHelper::GetUint8ArrayValue(env, value, MAX_CHALLENG_LEN, challenge_);
95     if (ret != napi_ok) {
96         IAM_LOGE("GetUint8ArrayValue fail:%{public}d", ret);
97     }
98     IAM_LOGI("challenge size:%{public}zu", challenge_.size());
99     return ret;
100 }
101 
Init(napi_env env,napi_callback_info info)102 UserAuthResultCode AuthInstanceV9::Init(napi_env env, napi_callback_info info)
103 {
104     if (callback_ == nullptr) {
105         IAM_LOGE("callback is null");
106         return UserAuthResultCode::GENERAL_ERROR;
107     }
108     napi_value argv[ARGS_THREE];
109     size_t argc = ARGS_THREE;
110     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
111     if (ret != napi_ok) {
112         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
113         return UserAuthResultCode::GENERAL_ERROR;
114     }
115     if (argc != ARGS_THREE) {
116         IAM_LOGE("invalid param, argc:%{public}zu", argc);
117         return UserAuthResultCode::OHOS_INVALID_PARAM;
118     }
119     challenge_.clear();
120     ret = InitChallenge(env, argv[PARAM0]);
121     if (ret != napi_ok) {
122         IAM_LOGE("InitChallenge fail:%{public}d", ret);
123         return UserAuthResultCode::OHOS_INVALID_PARAM;
124     }
125     int32_t authType;
126     ret = UserAuthNapiHelper::GetInt32Value(env, argv[PARAM1], authType);
127     if (ret != napi_ok) {
128         IAM_LOGE("GetInt32Value fail:%{public}d", ret);
129         return UserAuthResultCode::OHOS_INVALID_PARAM;
130     }
131     if (!UserAuthNapiHelper::CheckAuthType(authType)) {
132         IAM_LOGE("CheckAuthType fail");
133         return UserAuthResultCode::TYPE_NOT_SUPPORT;
134     }
135     authType_ = AuthType(authType);
136     uint32_t authTrustLevel;
137     ret = UserAuthNapiHelper::GetUint32Value(env, argv[PARAM2], authTrustLevel);
138     if (ret != napi_ok) {
139         IAM_LOGE("GetUint32Value fail:%{public}d", ret);
140         return UserAuthResultCode::OHOS_INVALID_PARAM;
141     }
142     if (!UserAuthNapiHelper::CheckAuthTrustLevel(authTrustLevel)) {
143         IAM_LOGE("CheckAuthTrustLevel fail");
144         return UserAuthResultCode::TRUST_LEVEL_NOT_SUPPORT;
145     }
146     authTrustLevel_ = AuthTrustLevel(authTrustLevel);
147     return UserAuthResultCode::SUCCESS;
148 }
149 
GetCallback(napi_env env,napi_value value)150 std::shared_ptr<JsRefHolder> AuthInstanceV9::GetCallback(napi_env env, napi_value value)
151 {
152     napi_status ret = UserAuthNapiHelper::CheckNapiType(env, value, napi_object);
153     if (ret != napi_ok) {
154         IAM_LOGE("CheckNapiType fail:%{public}d", ret);
155         return nullptr;
156     }
157     napi_value callbackValue;
158     ret = napi_get_named_property(env, value, "callback", &callbackValue);
159     if (ret != napi_ok) {
160         IAM_LOGE("napi_get_named_property fail:%{public}d", ret);
161         return nullptr;
162     }
163     return Common::MakeShared<JsRefHolder>(env, callbackValue);
164 }
165 
On(napi_env env,napi_callback_info info)166 UserAuthResultCode AuthInstanceV9::On(napi_env env, napi_callback_info info)
167 {
168     if (callback_ == nullptr) {
169         IAM_LOGE("callback is null");
170         return UserAuthResultCode::GENERAL_ERROR;
171     }
172     napi_value argv[ARGS_TWO];
173     size_t argc = ARGS_TWO;
174     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
175     if (ret != napi_ok) {
176         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
177         return UserAuthResultCode::GENERAL_ERROR;
178     }
179     if (argc != ARGS_TWO) {
180         IAM_LOGE("invalid param, argc:%{public}zu", argc);
181         return UserAuthResultCode::OHOS_INVALID_PARAM;
182     }
183     static const size_t maxLen = 10;
184     char str[maxLen] = {0};
185     size_t len = maxLen;
186     ret = UserAuthNapiHelper::GetStrValue(env, argv[PARAM0], str, len);
187     if (ret != napi_ok) {
188         IAM_LOGE("GetStrValue fail:%{public}d", ret);
189         return UserAuthResultCode::OHOS_INVALID_PARAM;
190     }
191     auto callbackRef = GetCallback(env, argv[PARAM1]);
192     if (callbackRef == nullptr || !callbackRef->IsValid()) {
193         IAM_LOGE("GetCallback fail");
194         return UserAuthResultCode::OHOS_INVALID_PARAM;
195     }
196     if (str == AUTH_EVENT_RESULT) {
197         IAM_LOGI("SetResultCallback");
198         callback_->SetResultCallback(callbackRef);
199         return UserAuthResultCode::SUCCESS;
200     } else if (str == AUTH_EVENT_TIP) {
201         IAM_LOGI("SetAcquireCallback");
202         callback_->SetAcquireCallback(callbackRef);
203         return UserAuthResultCode::SUCCESS;
204     } else {
205         IAM_LOGE("invalid event:%{public}s", str);
206         return UserAuthResultCode::OHOS_INVALID_PARAM;
207     }
208 }
209 
Off(napi_env env,napi_callback_info info)210 UserAuthResultCode AuthInstanceV9::Off(napi_env env, napi_callback_info info)
211 {
212     if (callback_ == nullptr) {
213         IAM_LOGE("callback is null");
214         return UserAuthResultCode::GENERAL_ERROR;
215     }
216     napi_value argv[ARGS_ONE];
217     size_t argc = ARGS_ONE;
218     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
219     if (ret != napi_ok) {
220         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
221         return UserAuthResultCode::GENERAL_ERROR;
222     }
223     if (argc != ARGS_ONE) {
224         IAM_LOGE("invalid param, argc:%{public}zu", argc);
225         return UserAuthResultCode::OHOS_INVALID_PARAM;
226     }
227     static const size_t maxLen = 10;
228     char str[maxLen] = {0};
229     size_t len = maxLen;
230     ret = UserAuthNapiHelper::GetStrValue(env, argv[PARAM0], str, len);
231     if (ret != napi_ok) {
232         IAM_LOGE("GetStrValue fail:%{public}d", ret);
233         return UserAuthResultCode::GENERAL_ERROR;
234     }
235     if (str == AUTH_EVENT_RESULT) {
236         callback_->ClearResultCallback();
237         IAM_LOGI("clear result callback");
238         return UserAuthResultCode::SUCCESS;
239     } else if (str == AUTH_EVENT_TIP) {
240         callback_->ClearAcquireCallback();
241         IAM_LOGI("clear tip callback");
242         return UserAuthResultCode::SUCCESS;
243     } else {
244         IAM_LOGE("invalid event:%{public}s", str);
245         return UserAuthResultCode::OHOS_INVALID_PARAM;
246     }
247 }
248 
Start(napi_env env,napi_callback_info info)249 UserAuthResultCode AuthInstanceV9::Start(napi_env env, napi_callback_info info)
250 {
251     if (callback_ == nullptr) {
252         IAM_LOGE("callback is null");
253         return UserAuthResultCode::GENERAL_ERROR;
254     }
255     napi_value argv[ARGS_ONE];
256     size_t argc = ARGS_ONE;
257     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
258     if (ret != napi_ok) {
259         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
260         return UserAuthResultCode::GENERAL_ERROR;
261     }
262     if (argc != ARGS_ZERO) {
263         IAM_LOGE("invalid param, argc:%{public}zu", argc);
264         return UserAuthResultCode::OHOS_INVALID_PARAM;
265     }
266     std::lock_guard<std::mutex> guard(mutex_);
267     if (isAuthStarted_) {
268         IAM_LOGE("auth already started");
269         return UserAuthResultCode::GENERAL_ERROR;
270     }
271     contextId_ = UserAuthClientImpl::Instance().BeginNorthAuthentication(API_VERSION_9,
272         challenge_, authType_, authTrustLevel_, callback_);
273     isAuthStarted_ = true;
274     return UserAuthResultCode::SUCCESS;
275 }
276 
Cancel(napi_env env,napi_callback_info info)277 UserAuthResultCode AuthInstanceV9::Cancel(napi_env env, napi_callback_info info)
278 {
279     if (callback_ == nullptr) {
280         IAM_LOGE("callback is null");
281         return UserAuthResultCode::GENERAL_ERROR;
282     }
283     napi_value argv[ARGS_ONE];
284     size_t argc = ARGS_ONE;
285     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
286     if (ret != napi_ok) {
287         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
288         return UserAuthResultCode::GENERAL_ERROR;
289     }
290     if (argc != ARGS_ZERO) {
291         IAM_LOGE("invalid param, argc:%{public}zu", argc);
292         return UserAuthResultCode::OHOS_INVALID_PARAM;
293     }
294     std::lock_guard<std::mutex> guard(mutex_);
295     if (!isAuthStarted_) {
296         IAM_LOGE("auth not started");
297         return UserAuthResultCode::GENERAL_ERROR;
298     }
299     int32_t result = UserAuthClient::GetInstance().CancelAuthentication(contextId_);
300     if (result != ResultCode::SUCCESS) {
301         IAM_LOGE("CancelAuthentication fail:%{public}d", result);
302         return UserAuthResultCode(UserAuthNapiHelper::GetResultCodeV9(result));
303     }
304     return UserAuthResultCode::SUCCESS;
305 }
306 } // namespace UserAuth
307 } // namespace UserIam
308 } // namespace OHOS
309