• 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_service.h"
17 
18 #include <cinttypes>
19 
20 #include "accesstoken_kit.h"
21 #include "context_factory.h"
22 #include "context_helper.h"
23 #include "hdi_wrapper.h"
24 #include "iam_logger.h"
25 #include "iam_ptr.h"
26 #include "ipc_common.h"
27 #include "iam_common_defines.h"
28 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
29 
30 namespace OHOS {
31 namespace UserIam {
32 namespace UserAuth {
33 namespace {
34     const uint64_t BAD_CONTEXT_ID = 0;
35     const int32_t MINIMUM_VERSION = 0;
36     const int32_t CURRENT_VERSION = 1;
37     const uint32_t AUTH_TRUST_LEVEL_SYS = 1;
38 } // namespace
39 
40 REGISTER_SYSTEM_ABILITY_BY_ID(UserAuthService, SUBSYS_USERIAM_SYS_ABILITY_USERAUTH, true);
41 
UserAuthService(int32_t systemAbilityId,bool runOnCreate)42 UserAuthService::UserAuthService(int32_t systemAbilityId, bool runOnCreate)
43     : SystemAbility(systemAbilityId, runOnCreate)
44 {
45 }
46 
OnStart()47 void UserAuthService::OnStart()
48 {
49     IAM_LOGI("start service");
50     if (!Publish(this)) {
51         IAM_LOGE("failed to publish service");
52     }
53 }
54 
OnStop()55 void UserAuthService::OnStop()
56 {
57     IAM_LOGI("stop service");
58 }
59 
GetAvailableStatus(int32_t apiVersion,AuthType authType,AuthTrustLevel authTrustLevel)60 int32_t UserAuthService::GetAvailableStatus(int32_t apiVersion, AuthType authType, AuthTrustLevel authTrustLevel)
61 {
62     IAM_LOGI("start");
63     ResultCode checkRet = CheckServicePermission(authType);
64     if (checkRet != SUCCESS) {
65         IAM_LOGE("failed to check permission");
66         return checkRet;
67     }
68     if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
69         IAM_LOGE("authTrustLevel is not in correct range");
70         return TRUST_LEVEL_NOT_SUPPORT;
71     }
72     int32_t userId;
73     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
74         IAM_LOGE("failed to get callingUserId");
75         return GENERAL_ERROR;
76     }
77     auto hdi = HdiWrapper::GetHdiInstance();
78     if (hdi == nullptr) {
79         IAM_LOGE("hdi interface is nullptr");
80         return GENERAL_ERROR;
81     }
82     uint32_t supportedAtl = AUTH_TRUST_LEVEL_SYS;
83     int32_t result =
84         hdi->GetAuthTrustLevel(userId, static_cast<HDI::UserAuth::V1_0::AuthType>(authType), supportedAtl);
85     if (result != SUCCESS) {
86         IAM_LOGE("failed to get current supported authTrustLevel from hdi apiVersion:%{public}d result:%{public}d",
87             apiVersion, result);
88         return result;
89     }
90     if (authTrustLevel > supportedAtl) {
91         IAM_LOGE("the current authTrustLevel does not support");
92         return TRUST_LEVEL_NOT_SUPPORT;
93     }
94     return SUCCESS;
95 }
96 
GetProperty(int32_t userId,AuthType authType,const std::vector<Attributes::AttributeKey> & keys,sptr<GetExecutorPropertyCallbackInterface> & callback)97 void UserAuthService::GetProperty(int32_t userId, AuthType authType,
98     const std::vector<Attributes::AttributeKey> &keys, sptr<GetExecutorPropertyCallbackInterface> &callback)
99 {
100     IAM_LOGI("start");
101     Attributes values;
102     if (callback == nullptr) {
103         IAM_LOGE("callback is nullptr");
104         return;
105     }
106     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
107         IAM_LOGE("failed to check permission");
108         callback->OnGetExecutorPropertyResult(CHECK_PERMISSION_FAILED, values);
109         return;
110     }
111 
112     auto credentialInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
113     if (credentialInfos.empty() || credentialInfos[0] == nullptr) {
114         IAM_LOGE("user %{public}d has no credential type %{public}d", userId, authType);
115         callback->OnGetExecutorPropertyResult(NOT_ENROLLED, values);
116         return;
117     }
118     uint64_t executorIndex = credentialInfos[0]->GetExecutorIndex();
119     uint64_t templateId = credentialInfos[0]->GetTemplateId();
120 
121     auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
122     if (resourceNode == nullptr) {
123         IAM_LOGE("resourceNode is nullptr");
124         callback->OnGetExecutorPropertyResult(GENERAL_ERROR, values);
125         return;
126     }
127     Attributes attr;
128     attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authType);
129     attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
130     attr.SetUint64Value(Attributes::ATTR_TEMPLATE_ID, templateId);
131     attr.SetUint64Value(Attributes::ATTR_CALLER_UID, static_cast<uint64_t>(this->GetCallingUid()));
132 
133     int32_t result = resourceNode->GetProperty(attr, values);
134     if (result != SUCCESS) {
135         IAM_LOGE("failed to get property, result = %{public}d", result);
136     }
137     callback->OnGetExecutorPropertyResult(result, values);
138 }
139 
SetProperty(int32_t userId,AuthType authType,const Attributes & attributes,sptr<SetExecutorPropertyCallbackInterface> & callback)140 void UserAuthService::SetProperty(int32_t userId, AuthType authType, const Attributes &attributes,
141     sptr<SetExecutorPropertyCallbackInterface> &callback)
142 {
143     IAM_LOGI("start");
144     if (callback == nullptr) {
145         IAM_LOGE("callback is nullptr");
146         return;
147     }
148     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
149         IAM_LOGE("permission check failed");
150         callback->OnSetExecutorPropertyResult(CHECK_PERMISSION_FAILED);
151         return;
152     }
153 
154     auto credentialInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
155     if (credentialInfos.empty() || credentialInfos[0] == nullptr) {
156         IAM_LOGE("credential info is incorrect");
157         callback->OnSetExecutorPropertyResult(NOT_ENROLLED);
158         return;
159     }
160     uint64_t executorIndex = credentialInfos[0]->GetExecutorIndex();
161     auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
162     if (resourceNode == nullptr) {
163         IAM_LOGE("resourceNode is nullptr");
164         callback->OnSetExecutorPropertyResult(GENERAL_ERROR);
165         return;
166     }
167     int32_t result = resourceNode->SetProperty(attributes);
168     if (result != SUCCESS) {
169         IAM_LOGE("set property failed, result = %{public}d", result);
170     }
171     callback->OnSetExecutorPropertyResult(result);
172 }
173 
CheckAuthPermission(bool isInnerCaller,AuthType authType)174 bool UserAuthService::CheckAuthPermission(bool isInnerCaller, AuthType authType)
175 {
176     if (isInnerCaller && IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
177         return true;
178     }
179     if (!isInnerCaller && authType != PIN && IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
180         return true;
181     }
182     return false;
183 }
184 
CheckNorthPermission(AuthType authType)185 ResultCode UserAuthService::CheckNorthPermission(AuthType authType)
186 {
187     if (!IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION)) {
188         IAM_LOGE("CheckNorthPermission failed, no permission");
189         return CHECK_PERMISSION_FAILED;
190     }
191     if (authType == PIN) {
192         IAM_LOGE("CheckNorthPermission, type error");
193         return TYPE_NOT_SUPPORT;
194     }
195     return SUCCESS;
196 }
197 
CheckServicePermission(AuthType authType)198 ResultCode UserAuthService::CheckServicePermission(AuthType authType)
199 {
200     if (IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
201         return SUCCESS;
202     }
203     return CheckNorthPermission(authType);
204 }
205 
GetAuthContextCallback(const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)206 std::shared_ptr<ContextCallback> UserAuthService::GetAuthContextCallback(const std::vector<uint8_t> &challenge,
207     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
208 {
209     if (callback == nullptr) {
210         IAM_LOGE("callback is nullptr");
211         return nullptr;
212     }
213     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_AUTH_USER);
214     if (contextCallback == nullptr) {
215         IAM_LOGE("failed to construct context callback");
216         Attributes extraInfo;
217         callback->OnResult(GENERAL_ERROR, extraInfo);
218         return nullptr;
219     }
220     auto callingUid = static_cast<uint64_t>(this->GetCallingUid());
221     contextCallback->SetTraceCallingUid(callingUid);
222     contextCallback->SetTraceAuthType(authType);
223     contextCallback->SetTraceAuthTrustLevel(authTrustLevel);
224     return contextCallback;
225 }
226 
Auth(int32_t apiVersion,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)227 uint64_t UserAuthService::Auth(int32_t apiVersion, const std::vector<uint8_t> &challenge,
228     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
229 {
230     IAM_LOGI("start");
231     auto contextCallback = GetAuthContextCallback(challenge, authType, authTrustLevel, callback);
232     if (contextCallback == nullptr) {
233         IAM_LOGE("contextCallback is nullptr");
234         return BAD_CONTEXT_ID;
235     }
236     Attributes extraInfo;
237     ResultCode checkRet = CheckNorthPermission(authType);
238     if (checkRet != SUCCESS) {
239         IAM_LOGE("CheckNorthPermission failed");
240         contextCallback->OnResult(checkRet, extraInfo);
241         return BAD_CONTEXT_ID;
242     }
243     int32_t userId;
244     if (IpcCommon::GetCallingUserId(*this, userId) != SUCCESS) {
245         IAM_LOGE("get callingUserId failed");
246         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
247         return BAD_CONTEXT_ID;
248     }
249     contextCallback->SetTraceUserId(userId);
250     if (authTrustLevel != ATL1 && authTrustLevel != ATL2 && authTrustLevel != ATL3 && authTrustLevel != ATL4) {
251         IAM_LOGE("authTrustLevel is not in correct range");
252         contextCallback->OnResult(TRUST_LEVEL_NOT_SUPPORT, extraInfo);
253         return BAD_CONTEXT_ID;
254     }
255     ContextFactory::AuthContextPara para = {};
256     para.tokenId = IpcCommon::GetAccessTokenId(*this);
257     para.userId = userId;
258     para.authType = authType;
259     para.atl = authTrustLevel;
260     para.challenge = std::move(challenge);
261     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
262     if (!ContextPool::Instance().Insert(context)) {
263         IAM_LOGE("failed to insert context");
264         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
265         return BAD_CONTEXT_ID;
266     }
267 
268     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
269 
270     if (!context->Start()) {
271         int32_t errorCode = context->GetLatestError();
272         IAM_LOGE("failed to start auth apiVersion:%{public}d errorCode:%{public}d", apiVersion, errorCode);
273         contextCallback->OnResult(errorCode, extraInfo);
274         return BAD_CONTEXT_ID;
275     }
276     return context->GetContextId();
277 }
278 
AuthUser(int32_t userId,const std::vector<uint8_t> & challenge,AuthType authType,AuthTrustLevel authTrustLevel,sptr<UserAuthCallbackInterface> & callback)279 uint64_t UserAuthService::AuthUser(int32_t userId, const std::vector<uint8_t> &challenge,
280     AuthType authType, AuthTrustLevel authTrustLevel, sptr<UserAuthCallbackInterface> &callback)
281 {
282     IAM_LOGI("start");
283     auto contextCallback = GetAuthContextCallback(challenge, authType, authTrustLevel, callback);
284     if (contextCallback == nullptr) {
285         IAM_LOGE("contextCallback is nullptr");
286         return BAD_CONTEXT_ID;
287     }
288     contextCallback->SetTraceUserId(userId);
289     Attributes extraInfo;
290     if (authTrustLevel < ATL1 || authTrustLevel > ATL4) {
291         IAM_LOGE("authTrustLevel is not in correct range");
292         contextCallback->OnResult(TRUST_LEVEL_NOT_SUPPORT, extraInfo);
293         return BAD_CONTEXT_ID;
294     }
295     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
296         IAM_LOGE("failed to check permission");
297         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
298         return BAD_CONTEXT_ID;
299     }
300     ContextFactory::AuthContextPara para = {};
301     para.tokenId = IpcCommon::GetAccessTokenId(*this);
302     para.userId = userId;
303     para.authType = authType;
304     para.atl = authTrustLevel;
305     para.challenge = std::move(challenge);
306     auto context = ContextFactory::CreateSimpleAuthContext(para, contextCallback);
307     if (!ContextPool::Instance().Insert(context)) {
308         IAM_LOGE("failed to insert context");
309         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
310         return BAD_CONTEXT_ID;
311     }
312 
313     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
314 
315     if (!context->Start()) {
316         IAM_LOGE("failed to start auth");
317         contextCallback->OnResult(context->GetLatestError(), extraInfo);
318         return BAD_CONTEXT_ID;
319     }
320     return context->GetContextId();
321 }
322 
Identify(const std::vector<uint8_t> & challenge,AuthType authType,sptr<UserAuthCallbackInterface> & callback)323 uint64_t UserAuthService::Identify(const std::vector<uint8_t> &challenge, AuthType authType,
324     sptr<UserAuthCallbackInterface> &callback)
325 {
326     IAM_LOGI("start");
327 
328     if (callback == nullptr) {
329         IAM_LOGE("callback is nullptr");
330         return BAD_CONTEXT_ID;
331     }
332     Attributes extraInfo;
333     auto contextCallback = ContextCallback::NewInstance(callback, TRACE_IDENTIFY);
334     if (contextCallback == nullptr) {
335         IAM_LOGE("failed to construct context callback");
336         callback->OnResult(GENERAL_ERROR, extraInfo);
337         return BAD_CONTEXT_ID;
338     }
339     if (authType == PIN) {
340         IAM_LOGE("pin not support");
341         contextCallback->OnResult(TYPE_NOT_SUPPORT, extraInfo);
342         return BAD_CONTEXT_ID;
343     }
344     if (!IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION)) {
345         IAM_LOGE("failed to check permission");
346         contextCallback->OnResult(CHECK_PERMISSION_FAILED, extraInfo);
347         return BAD_CONTEXT_ID;
348     }
349 
350     ContextFactory::IdentifyContextPara para = {};
351     para.tokenId = IpcCommon::GetAccessTokenId(*this);
352     para.authType = authType;
353     para.challenge = std::move(challenge);
354     auto context = ContextFactory::CreateIdentifyContext(para, contextCallback);
355     if (!ContextPool::Instance().Insert(context)) {
356         IAM_LOGE("failed to insert context");
357         contextCallback->OnResult(GENERAL_ERROR, extraInfo);
358         return BAD_CONTEXT_ID;
359     }
360 
361     contextCallback->SetCleaner(ContextHelper::Cleaner(context));
362 
363     if (!context->Start()) {
364         IAM_LOGE("failed to start identify");
365         contextCallback->OnResult(context->GetLatestError(), extraInfo);
366         return BAD_CONTEXT_ID;
367     }
368     return context->GetContextId();
369 }
370 
CancelAuthOrIdentify(uint64_t contextId)371 int32_t UserAuthService::CancelAuthOrIdentify(uint64_t contextId)
372 {
373     IAM_LOGI("start");
374     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
375         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
376     if (checkRet) {
377         IAM_LOGE("failed to check permission");
378         return CHECK_PERMISSION_FAILED;
379     }
380     auto context = ContextPool::Instance().Select(contextId).lock();
381     if (context == nullptr) {
382         IAM_LOGE("context not exist");
383         return GENERAL_ERROR;
384     }
385 
386     if (!context->Stop()) {
387         IAM_LOGE("failed to cancel auth or identify");
388         return context->GetLatestError();
389     }
390 
391     return SUCCESS;
392 }
393 
GetVersion(int32_t & version)394 int32_t UserAuthService::GetVersion(int32_t &version)
395 {
396     IAM_LOGI("start");
397     version = MINIMUM_VERSION;
398     bool checkRet = !IpcCommon::CheckPermission(*this, ACCESS_USER_AUTH_INTERNAL_PERMISSION) &&
399         !IpcCommon::CheckPermission(*this, ACCESS_BIOMETRIC_PERMISSION);
400     if (checkRet) {
401         IAM_LOGE("failed to check permission");
402         return CHECK_PERMISSION_FAILED;
403     }
404     version = CURRENT_VERSION;
405     return SUCCESS;
406 }
407 } // namespace UserAuth
408 } // namespace UserIam
409 } // namespace OHOS