• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-2023 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_service.h"
17 #include "hisysevent_adapter.h"
18 
19 #include <cinttypes>
20 
21 #include "accesstoken_kit.h"
22 #include "auth_common.h"
23 #include "auth_widget_helper.h"
24 #include "context_factory.h"
25 #include "auth_common.h"
26 #include "context_helper.h"
27 #include "hdi_wrapper.h"
28 #include "iam_check.h"
29 #include "iam_common_defines.h"
30 #include "iam_logger.h"
31 #include "iam_ptr.h"
32 #include "iam_time.h"
33 #include "ipc_common.h"
34 #include "ipc_skeleton.h"
35 #include "widget_client.h"
36 
37 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
38 
39 namespace OHOS {
40 namespace UserIam {
41 namespace UserAuth {
42 namespace {
43 const uint64_t BAD_CONTEXT_ID = 0;
44 const int32_t MINIMUM_VERSION = 0;
45 const int32_t CURRENT_VERSION = 1;
46 const uint32_t AUTH_TRUST_LEVEL_SYS = 1;
47 const int32_t USERIAM_IPC_THREAD_NUM = 4;
48 const uint32_t MAX_AUTH_TYPE_SIZE = 3;
49 
GetTemplatesByAuthType(int32_t userId,AuthType authType,std::vector<uint64_t> & templateIds)50 void GetTemplatesByAuthType(int32_t userId, AuthType authType, std::vector<uint64_t> &templateIds)
51 {
52     templateIds.clear();
53     auto credentialInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
54     if (credentialInfos.empty()) {
55         IAM_LOGE("user %{public}d has no credential type %{public}d", userId, authType);
56         return;
57     }
58 
59     templateIds.reserve(credentialInfos.size());
60     for (auto &info : credentialInfos) {
61         if (info == nullptr) {
62             IAM_LOGE("info is nullptr");
63             continue;
64         }
65         templateIds.push_back(info->GetTemplateId());
66     }
67 }
68 
IsTemplateIdListRequired(const std::vector<Attributes::AttributeKey> & keys)69 bool IsTemplateIdListRequired(const std::vector<Attributes::AttributeKey> &keys)
70 {
71     for (const auto &key : keys) {
72         if (key == Attributes::AttributeKey::ATTR_PIN_SUB_TYPE ||
73             key == Attributes::AttributeKey::ATTR_REMAIN_TIMES ||
74             key == Attributes::AttributeKey::ATTR_FREEZING_TIME) {
75             return true;
76         }
77     }
78     return false;
79 }
80 
GetResourceNodeByType(AuthType authType,std::vector<std::weak_ptr<ResourceNode>> & authTypeNodes)81 void GetResourceNodeByType(AuthType authType, std::vector<std::weak_ptr<ResourceNode>> &authTypeNodes)
82 {
83     authTypeNodes.clear();
84     ResourceNodePool::Instance().Enumerate(
85         [&authTypeNodes, authType](const std::weak_ptr<ResourceNode> &weakNode) {
86             auto node = weakNode.lock();
87             if (node == nullptr) {
88                 return;
89             }
90             if (node->GetAuthType() == authType) {
91                 authTypeNodes.push_back(node);
92             }
93         });
94 }
95 } // namespace
96 
97 REGISTER_SYSTEM_ABILITY_BY_ID(UserAuthService, SUBSYS_USERIAM_SYS_ABILITY_USERAUTH, true);
98 
UserAuthService(int32_t systemAbilityId,bool runOnCreate)99 UserAuthService::UserAuthService(int32_t systemAbilityId, bool runOnCreate)
100     : SystemAbility(systemAbilityId, runOnCreate)
101 {
102 }
103 
OnStart()104 void UserAuthService::OnStart()
105 {
106     IAM_LOGI("start service");
107     IPCSkeleton::SetMaxWorkThreadNum(USERIAM_IPC_THREAD_NUM);
108     if (!Publish(this)) {
109         IAM_LOGE("failed to publish service");
110     }
111 }
112 
OnStop()113 void UserAuthService::OnStop()
114 {
115     IAM_LOGI("stop service");
116 }
117 
GetAvailableStatus(int32_t apiVersion,AuthType authType,AuthTrustLevel authTrustLevel)118 int32_t UserAuthService::GetAvailableStatus(int32_t apiVersion, AuthType authType, AuthTrustLevel authTrustLevel)
119 {
120     IAM_LOGI("start");
121     ResultCode checkRet = CheckServicePermission(authType);
122     if (checkRet != SUCCESS) {
123         IAM_LOGE("failed to check permission");
124         return checkRet;
125     }
126     if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
127         IAM_LOGE("authTrustLevel is not in correct range");
128         return TRUST_LEVEL_NOT_SUPPORT;
129     }
130     int32_t userId;
131     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
132         IAM_LOGE("failed to get callingUserId");
133         return GENERAL_ERROR;
134     }
135     auto hdi = HdiWrapper::GetHdiInstance();
136     if (hdi == nullptr) {
137         IAM_LOGE("hdi interface is nullptr");
138         return GENERAL_ERROR;
139     }
140     uint32_t supportedAtl = AUTH_TRUST_LEVEL_SYS;
141     int32_t result =
142         hdi->GetAuthTrustLevel(userId, static_cast<HdiAuthType>(authType), supportedAtl);
143     if (result != SUCCESS) {
144         IAM_LOGE("failed to get current supported authTrustLevel from hdi apiVersion:%{public}d result:%{public}d",
145             apiVersion, result);
146         return result;
147     }
148     if (authTrustLevel > supportedAtl) {
149         IAM_LOGE("the current authTrustLevel does not support");
150         return TRUST_LEVEL_NOT_SUPPORT;
151     }
152     return SUCCESS;
153 }
154 
GetProperty(int32_t userId,AuthType authType,const std::vector<Attributes::AttributeKey> & keys,sptr<GetExecutorPropertyCallbackInterface> & callback)155 void UserAuthService::GetProperty(int32_t userId, AuthType authType,
156     const std::vector<Attributes::AttributeKey> &keys, sptr<GetExecutorPropertyCallbackInterface> &callback)
157 {
158     IAM_LOGI("start");
159     IF_FALSE_LOGE_AND_RETURN(callback != nullptr);
160     Attributes values;
161 
162     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
163         IAM_LOGE("failed to check permission");
164         callback->OnGetExecutorPropertyResult(CHECK_PERMISSION_FAILED, values);
165         return;
166     }
167 
168     std::vector<uint64_t> templateIds;
169     if (IsTemplateIdListRequired(keys)) {
170         GetTemplatesByAuthType(userId, authType, templateIds);
171         if (templateIds.size() == 0) {
172             IAM_LOGE("template id list is required, but templateIds size is 0");
173             callback->OnGetExecutorPropertyResult(NOT_ENROLLED, values);
174             return;
175         }
176     }
177 
178     std::vector<std::weak_ptr<ResourceNode>> authTypeNodes;
179     GetResourceNodeByType(authType, authTypeNodes);
180     if (authTypeNodes.size() != 1) {
181         IAM_LOGE("auth type %{public}d resource node num %{public}zu is not expected",
182             authType, authTypeNodes.size());
183         callback->OnGetExecutorPropertyResult(GENERAL_ERROR, values);
184         return;
185     }
186 
187     auto resourceNode = authTypeNodes[0].lock();
188     if (resourceNode == nullptr) {
189         IAM_LOGE("resourceNode is nullptr");
190         callback->OnGetExecutorPropertyResult(GENERAL_ERROR, values);
191         return;
192     }
193 
194     std::vector<uint32_t> uint32Keys;
195     uint32Keys.reserve(keys.size());
196     for (auto &key : keys) {
197         uint32Keys.push_back(static_cast<uint32_t>(key));
198     }
199 
200     Attributes attr;
201     attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authType);
202     attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
203     attr.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIds);
204     attr.SetUint64Value(Attributes::ATTR_CALLER_UID, static_cast<uint64_t>(this->GetCallingUid()));
205     attr.SetUint32ArrayValue(Attributes::ATTR_KEY_LIST, uint32Keys);
206 
207     int32_t result = resourceNode->GetProperty(attr, values);
208     if (result != SUCCESS) {
209         IAM_LOGE("failed to get property, result = %{public}d", result);
210     }
211     callback->OnGetExecutorPropertyResult(result, values);
212 }
213 
SetProperty(int32_t userId,AuthType authType,const Attributes & attributes,sptr<SetExecutorPropertyCallbackInterface> & callback)214 void UserAuthService::SetProperty(int32_t userId, AuthType authType, const Attributes &attributes,
215     sptr<SetExecutorPropertyCallbackInterface> &callback)
216 {
217     IAM_LOGI("start");
218     if (callback == nullptr) {
219         IAM_LOGE("callback is nullptr");
220         return;
221     }
222     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
223         IAM_LOGE("permission check failed");
224         callback->OnSetExecutorPropertyResult(CHECK_PERMISSION_FAILED);
225         return;
226     }
227 
228     std::vector<std::weak_ptr<ResourceNode>> authTypeNodes;
229     GetResourceNodeByType(authType, authTypeNodes);
230     if (authTypeNodes.size() != 1) {
231         IAM_LOGE("auth type %{public}d resource node num %{public}zu is not expected",
232             authType, authTypeNodes.size());
233         callback->OnSetExecutorPropertyResult(GENERAL_ERROR);
234         return;
235     }
236 
237     auto resourceNode = authTypeNodes[0].lock();
238     if (resourceNode == nullptr) {
239         IAM_LOGE("resourceNode is nullptr");
240         callback->OnSetExecutorPropertyResult(GENERAL_ERROR);
241         return;
242     }
243     int32_t result = resourceNode->SetProperty(attributes);
244     if (result != SUCCESS) {
245         IAM_LOGE("set property failed, result = %{public}d", result);
246     }
247     callback->OnSetExecutorPropertyResult(result);
248 }
249 
CheckNorthPermission(AuthType authType)250 ResultCode UserAuthService::CheckNorthPermission(AuthType authType)
251 {
252     if (!IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
253         IAM_LOGE("CheckNorthPermission failed, no permission");
254         return CHECK_PERMISSION_FAILED;
255     }
256     if (authType == PIN) {
257         IAM_LOGE("CheckNorthPermission, type error");
258         return TYPE_NOT_SUPPORT;
259     }
260     return SUCCESS;
261 }
262 
CheckWidgetNorthPermission()263 ResultCode UserAuthService::CheckWidgetNorthPermission()
264 {
265     if (!IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
266         IAM_LOGE("CheckWidgetNorthPermission failed, no permission");
267         return ResultCode::CHECK_PERMISSION_FAILED;
268     }
269     return ResultCode::SUCCESS;
270 }
271 
CheckServicePermission(AuthType authType)272 ResultCode UserAuthService::CheckServicePermission(AuthType authType)
273 {
274     if (IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
275         return SUCCESS;
276     }
277     return CheckNorthPermission(authType);
278 }
279 
CheckAuthWidgetParam(const AuthParam & authParam,const WidgetParam & widgetParam)280 ResultCode UserAuthService::CheckAuthWidgetParam(const AuthParam &authParam, const WidgetParam &widgetParam)
281 {
282     if (authParam.authType.size() == 0 || authParam.authType.size() > MAX_AUTH_TYPE_SIZE) {
283         IAM_LOGE("invalid authType size:%{public}zu", authParam.authType.size());
284         return ResultCode::INVALID_PARAMETERS;
285     }
286 
287     std::set<AuthType> authTypeChecker = {};
288     for (auto &type : authParam.authType) {
289         if (authTypeChecker.find(type) != authTypeChecker.end()) {
290             IAM_LOGE("duplicate auth type");
291             return ResultCode::INVALID_PARAMETERS;
292         }
293         switch (type) {
294             case AuthType::PIN:
295             case AuthType::FACE:
296             case AuthType::FINGERPRINT:
297                 break;
298             default:
299                 IAM_LOGE("invalid auth type");
300                 return ResultCode::TYPE_NOT_SUPPORT;
301         }
302         authTypeChecker.emplace(type);
303     }
304 
305     if (authParam.authTrustLevel != AuthTrustLevel::ATL1 && authParam.authTrustLevel != AuthTrustLevel::ATL2
306         && authParam.authTrustLevel != AuthTrustLevel::ATL3 && authParam.authTrustLevel != AuthTrustLevel::ATL4) {
307         IAM_LOGE("authType not match with trustLevel: %{public}u", authParam.authTrustLevel);
308         return ResultCode::TRUST_LEVEL_NOT_SUPPORT;
309     }
310 
311     if (widgetParam.title == "") {
312         IAM_LOGE("title shouldn't be empty");
313         return ResultCode::INVALID_PARAMETERS;
314     }
315 
316     if (widgetParam.navigationButtonText != "") {
317         IAM_LOGI("authParam.authType.size() = %{public}zu", authParam.authType.size());
318         if (authParam.authType.size() != 1 || (authParam.authType[0] != AuthType::FACE &&
319             authParam.authType[0] != AuthType::FINGERPRINT)) {
320             IAM_LOGE("navigationButtonText check fail");
321             return ResultCode::INVALID_PARAMETERS;
322         }
323     }
324 
325     if (widgetParam.windowMode == FULLSCREEN && authParam.authType.size() == 1 &&
326         (authParam.authType[0] == AuthType::FACE || authParam.authType[0] == AuthType::FINGERPRINT)) {
327         IAM_LOGE("Single fingerprint or single face does not support full screen");
328         return ResultCode::GENERAL_ERROR;
329     }
330     return ResultCode::SUCCESS;
331 }
332 
GetAuthContextCallback(const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)333 std::shared_ptr<ContextCallback> UserAuthService::GetAuthContextCallback(const std::vector<uint8_t> &challenge,
334     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
335 {
336     if (callback == nullptr) {
337         IAM_LOGE("callback is nullptr");
338         return nullptr;
339     }
340     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER);
341     if (contextCallback == nullptr) {
342         IAM_LOGE("failed to construct context callback");
343         Attributes extraInfo;
344         callback->OnResult(GENERAL_ERROR, extraInfo);
345         return nullptr;
346     }
347     auto callingUid = static_cast<uint64_t>(this->GetCallingUid());
348     contextCallback->SetTraceCallingUid(callingUid);
349     contextCallback->SetTraceAuthType(authType);
350     contextCallback->SetTraceAuthTrustLevel(authTrustLevel);
351     return contextCallback;
352 }
353 
Auth(int32_t apiVersion,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)354 uint64_t UserAuthService::Auth(int32_t apiVersion, const std::vector<uint8_t> &challenge,
355     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
356 {
357     IAM_LOGI("start");
358     auto contextCallback = GetAuthContextCallback(challenge, authType, authTrustLevel, callback);
359     if (contextCallback == nullptr) {
360         IAM_LOGE("contextCallback is nullptr");
361         return BAD_CONTEXT_ID;
362     }
363     Attributes extraInfo;
364     ResultCode checkRet = CheckNorthPermission(authType);
365     if (checkRet != SUCCESS) {
366         IAM_LOGE("CheckNorthPermission failed");
367         contextCallback->OnResult(checkRet, extraInfo);
368         return BAD_CONTEXT_ID;
369     }
370     int32_t userId;
371     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
372         IAM_LOGE("get callingUserId failed");
373         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
374         return BAD_CONTEXT_ID;
375     }
376     contextCallback->SetTraceUserId(userId);
377     if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
378         IAM_LOGE("authTrustLevel is not in correct range");
379         contextCallback->OnResult(TRUST_LEVEL_NOT_SUPPORT, extraInfo);
380         return BAD_CONTEXT_ID;
381     }
382     ContextFactory::AuthContextPara para = {};
383     para.tokenId = IpcCommon::GetAccessTokenId(*this);
384     para.userId = userId;
385     para.authType = authType;
386     para.atl = authTrustLevel;
387     para.challenge = std::move(challenge);
388     para.endAfterFirstFail = true;
389     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
390     if (!ContextPool::Instance().Insert(context)) {
391         IAM_LOGE("failed to insert context");
392         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
393         return BAD_CONTEXT_ID;
394     }
395 
396     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
397 
398     if (!context->Start()) {
399         int32_t errorCode = context->GetLatestError();
400         IAM_LOGE("failed to start auth apiVersion:%{public}d errorCode:%{public}d", apiVersion, errorCode);
401         contextCallback->OnResult(errorCode, extraInfo);
402         return BAD_CONTEXT_ID;
403     }
404     return context->GetContextId();
405 }
406 
AuthUser(int32_t userId,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)407 uint64_t UserAuthService::AuthUser(int32_t userId, const std::vector<uint8_t> &challenge,
408     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
409 {
410     IAM_LOGI("start");
411     auto contextCallback = GetAuthContextCallback(challenge, authType, authTrustLevel, callback);
412     if (contextCallback == nullptr) {
413         IAM_LOGE("contextCallback is nullptr");
414         return BAD_CONTEXT_ID;
415     }
416     contextCallback->SetTraceUserId(userId);
417     Attributes extraInfo;
418     if (authTrustLevel < ATL1 || authTrustLevel > ATL4) {
419         IAM_LOGE("authTrustLevel is not in correct range");
420         contextCallback->OnResult(TRUST_LEVEL_NOT_SUPPORT, extraInfo);
421         return BAD_CONTEXT_ID;
422     }
423     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
424         IAM_LOGE("failed to check permission");
425         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
426         return BAD_CONTEXT_ID;
427     }
428     ContextFactory::AuthContextPara para = {};
429     para.tokenId = IpcCommon::GetAccessTokenId(*this);
430     para.userId = userId;
431     para.authType = authType;
432     para.atl = authTrustLevel;
433     para.challenge = std::move(challenge);
434     para.endAfterFirstFail = false;
435     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
436     if (!ContextPool::Instance().Insert(context)) {
437         IAM_LOGE("failed to insert context");
438         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
439         return BAD_CONTEXT_ID;
440     }
441 
442     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
443 
444     if (!context->Start()) {
445         IAM_LOGE("failed to start auth");
446         contextCallback->OnResult(context->GetLatestError(), extraInfo);
447         return BAD_CONTEXT_ID;
448     }
449     return context->GetContextId();
450 }
451 
Identify(const std::vector<uint8_t> & challenge,AuthType authType,sptr<UserAuthCallbackInterface> & callback)452 uint64_t UserAuthService::Identify(const std::vector<uint8_t> &challenge, AuthType authType,
453     sptr<UserAuthCallbackInterface> &callback)
454 {
455     IAM_LOGI("start");
456 
457     if (callback == nullptr) {
458         IAM_LOGE("callback is nullptr");
459         return BAD_CONTEXT_ID;
460     }
461     Attributes extraInfo;
462     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_IDENTIFY);
463     if (contextCallback == nullptr) {
464         IAM_LOGE("failed to construct context callback");
465         callback->OnResult(GENERAL_ERROR, extraInfo);
466         return BAD_CONTEXT_ID;
467     }
468     if (authType == PIN) {
469         IAM_LOGE("pin not support");
470         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
471         return BAD_CONTEXT_ID;
472     }
473     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
474         IAM_LOGE("failed to check permission");
475         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
476         return BAD_CONTEXT_ID;
477     }
478 
479     ContextFactory::IdentifyContextPara para = {};
480     para.tokenId = IpcCommon::GetAccessTokenId(*this);
481     para.authType = authType;
482     para.challenge = std::move(challenge);
483     auto context = ContextFactory::CreateIdentifyContext(para, contextCallback);
484     if (!ContextPool::Instance().Insert(context)) {
485         IAM_LOGE("failed to insert context");
486         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
487         return BAD_CONTEXT_ID;
488     }
489 
490     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
491 
492     if (!context->Start()) {
493         IAM_LOGE("failed to start identify");
494         contextCallback->OnResult(context->GetLatestError(), extraInfo);
495         return BAD_CONTEXT_ID;
496     }
497     return context->GetContextId();
498 }
499 
CancelAuthOrIdentify(uint64_t contextId)500 int32_t UserAuthService::CancelAuthOrIdentify(uint64_t contextId)
501 {
502     IAM_LOGI("start");
503     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
504         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
505     if (checkRet) {
506         IAM_LOGE("failed to check permission");
507         return CHECK_PERMISSION_FAILED;
508     }
509     auto context = ContextPool::Instance().Select(contextId).lock();
510     if (context == nullptr) {
511         IAM_LOGE("context not exist");
512         return GENERAL_ERROR;
513     }
514 
515     if (context->GetTokenId() != IpcCommon::GetAccessTokenId(*this)) {
516         IAM_LOGE("failed to check tokenId");
517         return INVALID_CONTEXT_ID;
518     }
519 
520     if (!context->Stop()) {
521         IAM_LOGE("failed to cancel auth or identify");
522         return context->GetLatestError();
523     }
524 
525     return SUCCESS;
526 }
527 
GetVersion(int32_t & version)528 int32_t UserAuthService::GetVersion(int32_t &version)
529 {
530     IAM_LOGI("start");
531     version = MINIMUM_VERSION;
532     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
533         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
534     if (checkRet) {
535         IAM_LOGE("failed to check permission");
536         return CHECK_PERMISSION_FAILED;
537     }
538     version = CURRENT_VERSION;
539     return SUCCESS;
540 }
541 
CheckParam(const AuthParam & authParam,const WidgetParam & widgetParam)542 ResultCode UserAuthService::CheckParam(const AuthParam &authParam, const WidgetParam &widgetParam)
543 {
544     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP) &&
545         widgetParam.windowMode != WindowModeType::UNKNOWN_WINDOW_MODE) {
546         IAM_LOGE("normal app can't set window mode.");
547         return INVALID_PARAMETERS;
548     }
549     ResultCode checkRet = CheckWidgetNorthPermission();
550     if (checkRet != SUCCESS) {
551         IAM_LOGE("CheckWidgetNorthPermission failed. errCode: %{public}d", checkRet);
552         return checkRet;
553     }
554     checkRet = CheckAuthWidgetParam(authParam, widgetParam);
555     if (checkRet != SUCCESS) {
556         IAM_LOGE("parameter failed. errCode: %{public}d", checkRet);
557         return checkRet;
558     }
559     return SUCCESS;
560 }
561 
AuthWidget(int32_t apiVersion,const AuthParam & authParam,const WidgetParam & widgetParam,sptr<UserAuthCallbackInterface> & callback)562 uint64_t UserAuthService::AuthWidget(int32_t apiVersion, const AuthParam &authParam,
563     const WidgetParam &widgetParam, sptr<UserAuthCallbackInterface> &callback)
564 {
565     IAM_LOGI("start");
566     auto contextCallback = GetAuthContextCallback(authParam, widgetParam, callback);
567     if (contextCallback == nullptr) {
568         IAM_LOGE("contextCallback is nullptr");
569         return BAD_CONTEXT_ID;
570     }
571     Attributes extraInfo;
572     ResultCode checkRet = CheckParam(authParam, widgetParam);
573     if (checkRet != SUCCESS) {
574         contextCallback->OnResult(checkRet, extraInfo);
575         return BAD_CONTEXT_ID;
576     }
577     int32_t userId;
578     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
579         IAM_LOGE("get callingUserId failed");
580         contextCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
581         return BAD_CONTEXT_ID;
582     }
583     contextCallback->SetTraceUserId(userId);
584     int32_t ret = AuthWidgetHelper::CheckValidSolution(userId, authParam.authType, authParam.authTrustLevel);
585     if (ret != SUCCESS) {
586         contextCallback->OnResult(ret, extraInfo);
587         return BAD_CONTEXT_ID;
588     }
589 
590     ContextFactory::AuthWidgetContextPara para;
591     para.userId = userId;
592     para.tokenId = IpcCommon::GetAccessTokenId(*this);
593     para.callingUid = GetCallingUid();
594     if (!AuthWidgetHelper::InitWidgetContextParam(userId, authParam, widgetParam, para)) {
595         IAM_LOGE("init widgetContext failed");
596         contextCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
597         return BAD_CONTEXT_ID;
598     }
599     auto context = ContextFactory::CreateWidgetContext(para, contextCallback);
600     if (!Insert2ContextPool(context)) {
601         contextCallback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
602         return BAD_CONTEXT_ID;
603     }
604 
605     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
606     if (!context->Start()) {
607         int32_t errorCode = context->GetLatestError();
608         IAM_LOGE("failed to start auth apiVersion:%{public}d errorCode:%{public}d", apiVersion, errorCode);
609         contextCallback->OnResult(errorCode, extraInfo);
610         return BAD_CONTEXT_ID;
611     }
612     IAM_LOGI("authWidget end, receive message success.");
613     return context->GetContextId();
614 }
615 
Insert2ContextPool(const std::shared_ptr<Context> & context)616 bool UserAuthService::Insert2ContextPool(const std::shared_ptr<Context> &context)
617 {
618     bool ret = false;
619     const int32_t retryTimes = 3;
620     for (auto i = 0; i < retryTimes; i++) {
621         ret = ContextPool::Instance().Insert(context);
622         if (ret) {
623             break;
624         }
625     }
626     IAM_LOGI("insert context to pool, retry %{public}d times", retryTimes);
627     return ret;
628 }
629 
GetAuthContextCallback(const AuthParam & authParam,const WidgetParam & widgetParam,sptr<UserAuthCallbackInterface> & callback)630 std::shared_ptr<ContextCallback> UserAuthService::GetAuthContextCallback(const AuthParam &authParam,
631     const WidgetParam &widgetParam, sptr<UserAuthCallbackInterface> &callback)
632 {
633     if (callback == nullptr) {
634         IAM_LOGE("callback is nullptr");
635         return nullptr;
636     }
637     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER);
638     if (contextCallback == nullptr) {
639         IAM_LOGE("failed to construct context callback");
640         Attributes extraInfo;
641         callback->OnResult(ResultCode::GENERAL_ERROR, extraInfo);
642         return nullptr;
643     }
644     auto callingUid = static_cast<uint64_t>(this->GetCallingUid());
645     contextCallback->SetTraceCallingUid(callingUid);
646     contextCallback->SetTraceAuthTrustLevel(authParam.authTrustLevel);
647 
648     uint32_t authWidgetType = 0;
649     for (const auto authType : authParam.authType) {
650         authWidgetType |= static_cast<uint32_t>(authType);
651     }
652     static const uint32_t BIT_WINDOW_MODE = 0x40000000;
653     if (widgetParam.windowMode == FULLSCREEN) {
654         authWidgetType |= BIT_WINDOW_MODE;
655     }
656     static const uint32_t BIT_NAVIGATION = 0x80000000;
657     if (!widgetParam.navigationButtonText.empty()) {
658         authWidgetType |= BIT_NAVIGATION;
659     }
660     IAM_LOGE("SetTraceAuthWidgetType %{public}u", authWidgetType);
661     contextCallback->SetTraceAuthWidgetType(authWidgetType);
662 
663     return contextCallback;
664 }
665 
Notice(NoticeType noticeType,const std::string & eventData)666 int32_t UserAuthService::Notice(NoticeType noticeType, const std::string &eventData)
667 {
668     IAM_LOGI("start");
669     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP)) {
670         IAM_LOGE("the caller is not a system application");
671         return ResultCode::CHECK_SYSTEM_APP_FAILED;
672     }
673 
674     if (!IpcCommon::CheckPermission(*this, SUPPORT_USER_AUTH)) {
675         IAM_LOGE("failed to check permission");
676         return ResultCode::CHECK_PERMISSION_FAILED;
677     }
678     return WidgetClient::Instance().OnNotice(noticeType, eventData);
679 }
680 
RegisterWidgetCallback(int32_t version,sptr<WidgetCallbackInterface> & callback)681 int32_t UserAuthService::RegisterWidgetCallback(int32_t version, sptr<WidgetCallbackInterface> &callback)
682 {
683     if (!IpcCommon::CheckPermission(*this, IS_SYSTEM_APP)) {
684         IAM_LOGE("the caller is not a system application");
685         return ResultCode::CHECK_SYSTEM_APP_FAILED;
686     }
687 
688     if (!IpcCommon::CheckPermission(*this, SUPPORT_USER_AUTH)) {
689         IAM_LOGE("CheckWidgetNorthPermission failed, no permission");
690         return ResultCode::CHECK_PERMISSION_FAILED;
691     }
692 
693     uint32_t tokenId = IpcCommon::GetTokenId(*this);
694     IAM_LOGE("RegisterWidgetCallback tokenId %{public}u", tokenId);
695 
696     int32_t curVersion = std::stoi(NOTICE_VERSION_STR);
697     if (version != curVersion) {
698         return ResultCode::INVALID_PARAMETERS;
699     }
700     if (callback == nullptr) {
701         IAM_LOGE("callback is nullptr");
702         return ResultCode::INVALID_PARAMETERS;
703     }
704     WidgetClient::Instance().SetWidgetCallback(callback);
705     WidgetClient::Instance().SetAuthTokenId(tokenId);
706     return ResultCode::SUCCESS;
707 }
708 
709 } // namespace UserAuth
710 } // namespace UserIam
711 } // namespace OHOS