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