• 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 "user_auth_impl.h"
17 
18 #include <map>
19 
20 #include "securec.h"
21 
22 #include "iam_logger.h"
23 #include "iam_para2str.h"
24 #include "iam_ptr.h"
25 
26 #include "user_auth_helper.h"
27 #include "user_auth_napi_helper.h"
28 #include "user_auth_api_event_reporter.h"
29 #include "user_auth_callback_v6.h"
30 #include "user_auth_callback_v8.h"
31 #include "user_auth_client_impl.h"
32 #include "user_auth_param_utils.h"
33 
34 #define LOG_TAG "USER_AUTH_NAPI"
35 
36 namespace OHOS {
37 namespace UserIam {
38 namespace UserAuth {
GetVersion(napi_env env,napi_callback_info info)39 napi_value UserAuthImpl::GetVersion(napi_env env, napi_callback_info info)
40 {
41     int32_t version;
42     int32_t result = UserAuthClientImpl::Instance().GetVersion(version);
43     if (result != SUCCESS) {
44         IAM_LOGE("result = %{public}d", result);
45         version = 0;
46     }
47     IAM_LOGI("version = %{public}d", version);
48     napi_value jsVersion;
49     NAPI_CALL(env, napi_create_int32(env, version, &jsVersion));
50     return jsVersion;
51 }
52 
GetAvailableStatus(napi_env env,napi_callback_info info)53 napi_value UserAuthImpl::GetAvailableStatus(napi_env env, napi_callback_info info)
54 {
55     napi_value argv[ARGS_TWO] = {nullptr};
56     size_t argc = ARGS_TWO;
57     napi_value result;
58     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
59     if (argc != ARGS_TWO) {
60         IAM_LOGE("parms error");
61         NAPI_CALL(env, napi_create_int32(env, INVALID_PARAMETERS, &result));
62         return result;
63     }
64     int32_t type;
65     NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM0], &type));
66     int32_t level;
67     NAPI_CALL(env, napi_get_value_int32(env, argv[PARAM1], &level));
68     AuthType authType = AuthType(type);
69     AuthTrustLevel authTrustLevel = AuthTrustLevel(level);
70     ResultCode checkRet = CheckAuthTypeAndAuthTrustLevel(authType, authTrustLevel);
71     if (checkRet != SUCCESS) {
72         IAM_LOGE("CheckAuthTypeAndAuthTrsutLevel failed");
73         NAPI_CALL(env, napi_create_int32(env, checkRet, &result));
74         return result;
75     }
76     int32_t status = UserAuthClientImpl::Instance().GetNorthAvailableStatus(API_VERSION_8, authType, authTrustLevel);
77     IAM_LOGI("result = %{public}d", status);
78     NAPI_CALL(env, napi_create_int32(env, UserAuthNapiHelper::GetResultCodeV8(status), &result));
79     return result;
80 }
81 
Execute(napi_env env,napi_callback_info info)82 napi_value UserAuthImpl::Execute(napi_env env, napi_callback_info info)
83 {
84     IAM_LOGI("start");
85     size_t argc = ARGS_THREE;
86     napi_value argv[ARGS_THREE] = {nullptr};
87     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
88     napi_value retPromise = nullptr;
89     std::shared_ptr<JsRefHolder> callbackRef = nullptr;
90     napi_deferred promiseDeferred = nullptr;
91     if (argc == ARGS_THREE) {
92         callbackRef = Common::MakeShared<JsRefHolder>(env, argv[PARAM2]);
93         if (callbackRef == nullptr || !callbackRef->IsValid()) {
94             IAM_LOGE("make callback ref fail");
95             return nullptr;
96         }
97         NAPI_CALL(env, napi_get_null(env, &retPromise));
98     } else if (argc == ARGS_TWO) {
99         NAPI_CALL(env, napi_create_promise(env, &promiseDeferred, &retPromise));
100     } else {
101         IAM_LOGE("bad params");
102         return retPromise;
103     }
104     std::shared_ptr<UserAuthCallbackV6> callback =
105         Common::MakeShared<UserAuthCallbackV6>(env, callbackRef, promiseDeferred);
106     if (callback == nullptr) {
107         IAM_LOGE("callback is nullptr");
108         return nullptr;
109     }
110 
111     AuthType authType;
112     ResultCode resultCode;
113     NAPI_CALL(env, ParseExecuteAuthType(env, argv[PARAM0], authType, resultCode));
114     if (resultCode != ResultCode::SUCCESS) {
115         IAM_LOGE("ParseAuthType fail");
116         UserIam::UserAuth::Attributes extra;
117         callback->OnResult(resultCode, extra);
118         return retPromise;
119     }
120     AuthTrustLevel authTrustLevel;
121     NAPI_CALL(env, ParseExecuteSecureLevel(env, argv[PARAM1], authTrustLevel, resultCode));
122     if (resultCode != ResultCode::SUCCESS) {
123         IAM_LOGE("ParseExecuteSecureLevel fail");
124         UserIam::UserAuth::Attributes extra;
125         callback->OnResult(resultCode, extra);
126         return retPromise;
127     }
128 
129     std::vector<uint8_t> challenge;
130     UserAuthClientImpl::Instance().BeginNorthAuthentication(API_VERSION_6, challenge, FACE, authTrustLevel, callback);
131     return retPromise;
132 }
133 
ParseExecuteAuthType(napi_env env,napi_value value,AuthType & authType,ResultCode & resultCode)134 napi_status UserAuthImpl::ParseExecuteAuthType(napi_env env, napi_value value,
135     AuthType &authType, ResultCode &resultCode)
136 {
137     resultCode = ResultCode::GENERAL_ERROR;
138     static const size_t maxLen = 20;
139     char str[maxLen] = {0};
140     size_t len = maxLen;
141     napi_status result = UserAuthNapiHelper::GetStrValue(env, value, str, len);
142     if (result != napi_ok) {
143         IAM_LOGE("getStrValue fail");
144         return result;
145     }
146     static const char *authTypeAll = "ALL";
147     static const char *authTypeFaceOnly = "FACE_ONLY";
148     if (strcmp(str, authTypeAll) == 0) {
149         IAM_LOGE("type ALL not supported");
150         resultCode = ResultCode::TYPE_NOT_SUPPORT;
151         return napi_ok;
152     }
153     if (strcmp(str, authTypeFaceOnly) != 0) {
154         IAM_LOGE("type is invalid");
155         resultCode = ResultCode::INVALID_PARAMETERS;
156         return napi_ok;
157     }
158     resultCode = ResultCode::SUCCESS;
159     return napi_ok;
160 }
161 
ParseExecuteSecureLevel(napi_env env,napi_value value,AuthTrustLevel & authTrustLevel,ResultCode & resultCode)162 napi_status UserAuthImpl::ParseExecuteSecureLevel(napi_env env, napi_value value,
163     AuthTrustLevel &authTrustLevel, ResultCode &resultCode)
164 {
165     resultCode = ResultCode::GENERAL_ERROR;
166     static const size_t maxLen = 20;
167     char str[maxLen] = {0};
168     size_t len = maxLen;
169     napi_status result = UserAuthNapiHelper::GetStrValue(env, value, str, len);
170     if (result != napi_ok) {
171         IAM_LOGE("getStrValue fail");
172         return result;
173     }
174     static std::map<std::string, AuthTrustLevel> convertAuthTrustLevel = {
175         {"S1", ATL1},
176         {"S2", ATL2},
177         {"S3", ATL3},
178         {"S4", ATL4},
179     };
180     if (convertAuthTrustLevel.count(str) == 0) {
181         IAM_LOGE("trust level invalid");
182         resultCode = ResultCode::INVALID_PARAMETERS;
183         return napi_ok;
184     }
185     authTrustLevel = convertAuthTrustLevel[str];
186     resultCode = ResultCode::SUCCESS;
187     return napi_ok;
188 }
189 
Auth(napi_env env,napi_callback_info info)190 napi_value UserAuthImpl::Auth(napi_env env, napi_callback_info info)
191 {
192     IAM_LOGI("start");
193     size_t argc = ARGS_FOUR;
194     napi_value argv[ARGS_FOUR] = {nullptr};
195     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
196     if (argc != ARGS_FOUR) {
197         IAM_LOGE("parms error");
198         return nullptr;
199     }
200     std::vector<uint8_t> challenge;
201     if (UserAuthNapiHelper::GetUint8ArrayValue(env, argv[PARAM0], MAX_CHALLENG_LEN, challenge) != napi_ok) {
202         IAM_LOGE("challenge invalid, use null challenge");
203         challenge.clear();
204     }
205     int32_t authType;
206     NAPI_CALL(env, UserAuthNapiHelper::GetInt32Value(env, argv[PARAM1], authType));
207     int32_t authTrustLevel;
208     NAPI_CALL(env, UserAuthNapiHelper::GetInt32Value(env, argv[PARAM2], authTrustLevel));
209     NAPI_CALL(env, UserAuthNapiHelper::CheckNapiType(env, argv[PARAM3], napi_object));
210     napi_value onResultValue;
211     NAPI_CALL(env, napi_get_named_property(env, argv[PARAM3], "onResult", &onResultValue));
212     auto resultCallback = Common::MakeShared<JsRefHolder>(env, onResultValue);
213     napi_value onAcquireInfoValue;
214     NAPI_CALL(env, napi_get_named_property(env, argv[PARAM3], "onAcquireInfo", &onAcquireInfoValue));
215     auto acquireCallback = Common::MakeShared<JsRefHolder>(env, onAcquireInfoValue);
216     auto callback = Common::MakeShared<UserAuthCallbackV8>(env, resultCallback, acquireCallback);
217     if (callback == nullptr) {
218         IAM_LOGE("callback is nullptr");
219         return nullptr;
220     }
221     ResultCode checkRet = CheckAuthTypeAndAuthTrustLevel(AuthType(authType), AuthTrustLevel(authTrustLevel));
222     if (checkRet != SUCCESS) {
223         IAM_LOGE("CheckAuthTypeAndAuthTrsutLevel failed");
224         Attributes extraInfo;
225         callback->OnResult(checkRet, extraInfo);
226         napi_value key = UserAuthNapiHelper::Uint64ToNapiUint8Array(env, INVALID_CONTEXT_ID);
227         return key;
228     }
229     uint64_t result = UserAuthClientImpl::Instance().BeginNorthAuthentication(API_VERSION_8, challenge,
230         AuthType(authType), AuthTrustLevel(authTrustLevel), callback);
231     IAM_LOGI("result is %{public}s", GET_MASKED_STRING(result).c_str());
232     napi_value key = UserAuthNapiHelper::Uint64ToNapiUint8Array(env, result);
233     IAM_LOGI("end");
234     return key;
235 }
236 
CancelAuth(napi_env env,napi_callback_info info)237 napi_value UserAuthImpl::CancelAuth(napi_env env, napi_callback_info info)
238 {
239     size_t argc = ARGS_ONE;
240     napi_value argv[ARGS_ONE] = {nullptr};
241     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
242     if (argc != ARGS_ONE) {
243         IAM_LOGE("parms error");
244         return nullptr;
245     }
246     const size_t maxContextIdLen = 8;
247     std::vector<uint8_t> contextIdArray;
248     NAPI_CALL(env, UserAuthNapiHelper::GetUint8ArrayValue(env, argv[PARAM0], maxContextIdLen, contextIdArray));
249     uint64_t contextId;
250     if (memcpy_s(reinterpret_cast<void *>(&contextId), sizeof(contextId),
251         contextIdArray.data(), contextIdArray.size()) != EOK) {
252         IAM_LOGE("memcpy error");
253         return nullptr;
254     }
255     IAM_LOGI("contextId's low 16 bits is %{public}s", GET_MASKED_STRING(contextId).c_str());
256     if (contextId == 0) {
257         IAM_LOGE("invalid error");
258         return nullptr;
259     }
260     int32_t result = UserAuthClient::GetInstance().CancelAuthentication(contextId);
261     IAM_LOGI("result = %{public}d", result);
262     napi_value key;
263     NAPI_CALL(env, napi_create_int32(env, UserAuthNapiHelper::GetResultCodeV8(result), &key));
264     return key;
265 }
266 
CheckAuthTypeAndAuthTrustLevel(AuthType authType,AuthTrustLevel authTrustLevel)267 ResultCode UserAuthImpl::CheckAuthTypeAndAuthTrustLevel(AuthType authType, AuthTrustLevel authTrustLevel)
268 {
269     if (authType != FINGERPRINT && authType != FACE) {
270         IAM_LOGE("authType check fail:%{public}d", authType);
271         return TYPE_NOT_SUPPORT;
272     }
273     if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
274         IAM_LOGE("authTrustLevel check fail:%{public}d", authTrustLevel);
275         return TRUST_LEVEL_NOT_SUPPORT;
276     }
277     return SUCCESS;
278 }
279 
GetEnrolledState(napi_env env,napi_callback_info info)280 napi_value UserAuthImpl::GetEnrolledState(napi_env env, napi_callback_info info)
281 {
282     napi_value argv[ARGS_ONE] = {nullptr};
283     size_t argc = ARGS_ONE;
284     UserAuthApiEventReporter reporter("getEnrolledState");
285     NAPI_CALL(env, napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr));
286     if (argc != ARGS_ONE) {
287         IAM_LOGE("parms error");
288         std::string msgStr = "Parameter error. The number of parameters should be 1.";
289         napi_throw(env, UserAuthNapiHelper::GenerateErrorMsg(env, UserAuthResultCode::OHOS_INVALID_PARAM, msgStr));
290         reporter.ReportFailed(UserAuthResultCode::OHOS_INVALID_PARAM);
291         return nullptr;
292     }
293     int32_t type;
294     if (UserAuthNapiHelper::GetInt32Value(env, argv[PARAM0], type) != napi_ok) {
295         IAM_LOGE("napi_get_value_int32 fail");
296         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode::GENERAL_ERROR));
297         reporter.ReportFailed(UserAuthResultCode::GENERAL_ERROR);
298         return nullptr;
299     }
300     if (!UserAuthHelper::CheckUserAuthType(type)) {
301         IAM_LOGE("CheckUserAuthType fail");
302         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode::TYPE_NOT_SUPPORT));
303         reporter.ReportFailed(UserAuthResultCode::TYPE_NOT_SUPPORT);
304         return nullptr;
305     }
306     AuthType authType = AuthType(type);
307     EnrolledState enrolledState = {};
308     int32_t code = UserAuthClientImpl::Instance().GetEnrolledState(API_VERSION_12, authType, enrolledState);
309     if (code != SUCCESS) {
310         IAM_LOGE("failed to get enrolled state %{public}d", code);
311         int32_t resultCode = UserAuthHelper::GetResultCodeV10(code);
312         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode(resultCode)));
313         reporter.ReportFailed(resultCode);
314         return nullptr;
315     }
316     return DoGetEnrolledStateResult(env, enrolledState, reporter);
317 }
318 
DoGetEnrolledStateResult(napi_env env,EnrolledState enrolledState,UserAuthApiEventReporter & reporter)319 napi_value UserAuthImpl::DoGetEnrolledStateResult(napi_env env, EnrolledState enrolledState,
320     UserAuthApiEventReporter &reporter)
321 {
322     IAM_LOGD("start");
323     napi_value eventInfo;
324     napi_status ret = napi_create_object(env, &eventInfo);
325     if (ret != napi_ok) {
326         IAM_LOGE("napi_create_object failed %{public}d", ret);
327         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode::GENERAL_ERROR));
328         reporter.ReportFailed(UserAuthResultCode::GENERAL_ERROR);
329         return nullptr;
330     }
331     int32_t credentialDigest = static_cast<int32_t>(enrolledState.credentialDigest);
332     int32_t credentialCount = static_cast<int32_t>(enrolledState.credentialCount);
333     IAM_LOGI("get enrolled state success, credentialDigest = %{public}d, credentialCount = %{public}d",
334         credentialDigest, credentialCount);
335     ret = UserAuthNapiHelper::SetInt32Property(env, eventInfo, "credentialDigest", credentialDigest);
336     if (ret != napi_ok) {
337         IAM_LOGE("napi_create_int32 failed %{public}d", ret);
338         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode::GENERAL_ERROR));
339         reporter.ReportFailed(UserAuthResultCode::GENERAL_ERROR);
340         return nullptr;
341     }
342     ret = UserAuthNapiHelper::SetInt32Property(env, eventInfo, "credentialCount", credentialCount);
343     if (ret != napi_ok) {
344         IAM_LOGE("napi_create_int32 failed %{public}d", ret);
345         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode::GENERAL_ERROR));
346         reporter.ReportFailed(UserAuthResultCode::GENERAL_ERROR);
347         return nullptr;
348     }
349     IAM_LOGD("get enrolled state end");
350     reporter.ReportSuccess();
351     return eventInfo;
352 }
353 
ParseReusableAuthResultParam(napi_env env,napi_callback_info info,WidgetAuthParam & authParam)354 UserAuthResultCode UserAuthImpl::ParseReusableAuthResultParam(napi_env env, napi_callback_info info,
355     WidgetAuthParam &authParam)
356 {
357     napi_value argv[ARGS_ONE];
358     size_t argc = ARGS_ONE;
359     napi_status ret = napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr);
360     if (ret != napi_ok) {
361         IAM_LOGE("napi_get_cb_info fail:%{public}d", ret);
362         return UserAuthResultCode::GENERAL_ERROR;
363     }
364     if (argc != ARGS_ONE) {
365         IAM_LOGE("parms error");
366         std::string msgStr = "Parameter error. The number of parameters should be 1.";
367         napi_throw(env, UserAuthNapiHelper::GenerateErrorMsg(env, UserAuthResultCode::OHOS_INVALID_PARAM, msgStr));
368         return UserAuthResultCode::OHOS_INVALID_PARAM;
369     }
370     AuthParamInner authParamInner = {
371         .userId = INVALID_USER_ID,
372         .authTrustLevel = AuthTrustLevel::ATL1,
373     };
374     UserAuthResultCode errCode = UserAuthParamUtils::InitAuthParam(env, argv[PARAM0], authParamInner);
375     if (errCode != UserAuthResultCode::SUCCESS) {
376         IAM_LOGE("authParamInner type error, errorCode: %{public}d", errCode);
377         return errCode;
378     }
379     authParam.userId = authParamInner.userId;
380     authParam.challenge = authParamInner.challenge;
381     authParam.authTypes = authParamInner.authTypes;
382     authParam.authTrustLevel = authParamInner.authTrustLevel;
383     authParam.reuseUnlockResult.isReuse = authParamInner.reuseUnlockResult.isReuse;
384     authParam.reuseUnlockResult.reuseMode = authParamInner.reuseUnlockResult.reuseMode;
385     authParam.reuseUnlockResult.reuseDuration = authParamInner.reuseUnlockResult.reuseDuration;
386     return UserAuthResultCode::SUCCESS;
387 }
388 
QueryReusableAuthResult(napi_env env,napi_callback_info info)389 napi_value UserAuthImpl::QueryReusableAuthResult(napi_env env, napi_callback_info info)
390 {
391     UserAuthApiEventReporter reporter("QueryReusableAuthResult");
392     WidgetAuthParam authParam = {0};
393     UserAuthResultCode errCode = ParseReusableAuthResultParam(env, info, authParam);
394     if (errCode != UserAuthResultCode::SUCCESS) {
395         IAM_LOGE("AuthParamInner type error, errorCode: %{public}d", errCode);
396         reporter.ReportFailed(errCode);
397         return nullptr;
398     }
399 
400     std::vector<uint8_t> token;
401     int32_t code = UserAuthClientImpl::Instance().QueryReusableAuthResult(authParam, token);
402     if (code != SUCCESS) {
403         IAM_LOGE("failed to query reuse result %{public}d", code);
404         int32_t resultCode = UserAuthHelper::GetResultCodeV20(code);
405         napi_throw(env, UserAuthNapiHelper::GenerateBusinessErrorV9(env, UserAuthResultCode(resultCode)));
406         reporter.ReportFailed(UserAuthResultCode(resultCode));
407         return nullptr;
408     }
409     napi_value eventInfo = UserAuthNapiHelper::Uint8VectorToNapiUint8Array(env, token);
410     return eventInfo;
411 }
412 } // namespace UserAuth
413 } // namespace UserIam
414 } // namespace OHOS
415