1 /*
2 * Copyright (c) 2023-2024 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_widget_helper.h"
17
18 #include <cinttypes>
19 #include "securec.h"
20
21 #include "iam_check.h"
22 #include "iam_logger.h"
23 #include "resource_node_pool.h"
24 #include "user_idm_database.h"
25 #include "widget_client.h"
26
27 #define LOG_TAG "USER_AUTH_SA"
28
29 namespace OHOS {
30 namespace UserIam {
31 namespace UserAuth {
32
InitWidgetContextParam(const AuthParamInner & authParam,std::vector<AuthType> & validType,const WidgetParamInner & widgetParam,ContextFactory::AuthWidgetContextPara & para)33 bool AuthWidgetHelper::InitWidgetContextParam(const AuthParamInner &authParam, std::vector<AuthType> &validType,
34 const WidgetParamInner &widgetParam, ContextFactory::AuthWidgetContextPara ¶)
35 {
36 for (auto &authType : validType) {
37 ContextFactory::AuthProfile profile;
38 if (!GetUserAuthProfile(para.userId, authType, profile)) {
39 IAM_LOGE("get user auth profile failed");
40 return false;
41 }
42 para.authProfileMap[authType] = profile;
43 if (authType == AuthType::PIN || authType == AuthType::PRIVATE_PIN) {
44 WidgetClient::Instance().SetPinSubType(static_cast<PinSubType>(profile.pinSubType));
45 } else if (authType == AuthType::FINGERPRINT) {
46 WidgetClient::Instance().SetSensorInfo(profile.sensorInfo);
47 }
48 }
49 para.challenge = std::move(authParam.challenge);
50 para.authTypeList = std::move(validType);
51 para.atl = authParam.authTrustLevel;
52 para.skipLockedBiometricAuth = authParam.skipLockedBiometricAuth;
53 para.widgetParam = widgetParam;
54 if (widgetParam.windowMode == WindowModeType::UNKNOWN_WINDOW_MODE) {
55 para.widgetParam.windowMode = WindowModeType::DIALOG_BOX;
56 }
57 return true;
58 }
59
GetUserAuthProfile(int32_t userId,const AuthType & authType,ContextFactory::AuthProfile & profile)60 bool AuthWidgetHelper::GetUserAuthProfile(int32_t userId, const AuthType &authType,
61 ContextFactory::AuthProfile &profile)
62 {
63 Attributes values;
64 std::vector<std::shared_ptr<CredentialInfoInterface>> credentialInfos;
65 int32_t ret = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType, credentialInfos);
66 if (ret != SUCCESS) {
67 IAM_LOGE("get credential fail, ret:%{public}d, userId:%{public}d, authType:%{public}d", ret,
68 userId, authType);
69 return false;
70 }
71 if (credentialInfos.empty() || credentialInfos[0] == nullptr) {
72 IAM_LOGE("user %{public}d has no credential type %{public}d", userId, authType);
73 return false;
74 }
75 uint64_t executorIndex = credentialInfos[0]->GetExecutorIndex();
76 auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
77 if (resourceNode == nullptr) {
78 IAM_LOGE("resourceNode is nullptr");
79 return false;
80 }
81 std::vector<uint64_t> templateIds;
82 templateIds.reserve(credentialInfos.size());
83 for (auto &info : credentialInfos) {
84 if (info == nullptr) {
85 IAM_LOGE("info is null");
86 continue;
87 }
88 templateIds.push_back(info->GetTemplateId());
89 }
90 std::vector<uint32_t> uint32Keys = {
91 Attributes::ATTR_REMAIN_TIMES,
92 Attributes::ATTR_FREEZING_TIME
93 };
94 if (authType == AuthType::PIN || authType == AuthType::PRIVATE_PIN) {
95 uint32Keys.push_back(Attributes::ATTR_PIN_SUB_TYPE);
96 }
97 if (authType == AuthType::FINGERPRINT) {
98 uint32Keys.push_back(Attributes::ATTR_SENSOR_INFO);
99 }
100 Attributes attr;
101 attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authType);
102 attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
103 attr.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIds);
104 attr.SetUint32ArrayValue(Attributes::ATTR_KEY_LIST, uint32Keys);
105 int32_t result = resourceNode->GetProperty(attr, values);
106 if (result != SUCCESS) {
107 IAM_LOGE("failed to get property, result = %{public}d", result);
108 return false;
109 }
110 return ParseAttributes(values, authType, profile);
111 }
112
ParseAttributes(const Attributes & values,const AuthType & authType,ContextFactory::AuthProfile & profile)113 bool AuthWidgetHelper::ParseAttributes(const Attributes &values, const AuthType &authType,
114 ContextFactory::AuthProfile &profile)
115 {
116 if (authType == AuthType::PIN || authType == AuthType::PRIVATE_PIN) {
117 if (!values.GetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, profile.pinSubType)) {
118 IAM_LOGE("get ATTR_PIN_SUB_TYPE failed");
119 return false;
120 }
121 }
122 if (authType == AuthType::FINGERPRINT && (!values.GetStringValue(Attributes::ATTR_SENSOR_INFO,
123 profile.sensorInfo))) {
124 IAM_LOGE("get ATTR_SENSOR_INFO failed");
125 return false;
126 }
127 if (!values.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, profile.remainTimes)) {
128 IAM_LOGE("get ATTR_REMAIN_TIMES failed");
129 return false;
130 }
131 if (!values.GetInt32Value(Attributes::ATTR_FREEZING_TIME, profile.freezingTime)) {
132 IAM_LOGE("get ATTR_FREEZING_TIME failed");
133 return false;
134 }
135 return true;
136 }
137
CheckValidSolution(int32_t userId,const std::vector<AuthType> & authTypeList,const AuthTrustLevel & atl,std::vector<AuthType> & validTypeList)138 int32_t AuthWidgetHelper::CheckValidSolution(int32_t userId,
139 const std::vector<AuthType> &authTypeList, const AuthTrustLevel &atl, std::vector<AuthType> &validTypeList)
140 {
141 IAM_LOGI("start userId:%{public}d atl:%{public}u typeSize:%{public}zu", userId, atl, authTypeList.size());
142 auto hdi = HdiWrapper::GetHdiInstance();
143 if (hdi == nullptr) {
144 IAM_LOGE("hdi interface is nullptr");
145 return GENERAL_ERROR;
146 }
147 std::vector<int32_t> inputAuthType;
148 std::vector<int32_t> validTypes;
149 uint32_t inputAtl = atl;
150 for (auto &type : authTypeList) {
151 inputAuthType.emplace_back(static_cast<int32_t>(type));
152 }
153 int32_t result = hdi->GetValidSolution(userId, inputAuthType, inputAtl, validTypes);
154 if (result != SUCCESS) {
155 IAM_LOGE("GetValidSolution failed result:%{public}d userId:%{public}d", result, userId);
156 return result;
157 }
158 validTypeList.clear();
159 for (auto &type : validTypes) {
160 IAM_LOGI("get valid authType:%{public}d", type);
161 validTypeList.emplace_back(static_cast<AuthType>(type));
162 }
163 return result;
164 }
165
SetReuseUnlockResult(int32_t apiVersion,const HdiReuseUnlockInfo & info,Attributes & extraInfo)166 int32_t AuthWidgetHelper::SetReuseUnlockResult(int32_t apiVersion, const HdiReuseUnlockInfo &info,
167 Attributes &extraInfo)
168 {
169 bool setSignatureResult = extraInfo.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, info.token);
170 IF_FALSE_LOGE_AND_RETURN_VAL(setSignatureResult == true, GENERAL_ERROR);
171 bool setAuthTypeResult = extraInfo.SetInt32Value(Attributes::ATTR_AUTH_TYPE,
172 static_cast<int32_t>(info.authType));
173 IF_FALSE_LOGE_AND_RETURN_VAL(setAuthTypeResult == true, GENERAL_ERROR);
174 bool setResultCodeRet = extraInfo.SetInt32Value(Attributes::ATTR_RESULT_CODE, SUCCESS);
175 IF_FALSE_LOGE_AND_RETURN_VAL(setResultCodeRet == true, GENERAL_ERROR);
176 uint64_t credentialDigest = info.enrolledState.credentialDigest;
177 if (apiVersion < INNER_API_VERSION_10000) {
178 credentialDigest = info.enrolledState.credentialDigest & UINT16_MAX;
179 }
180 bool setCredentialDigestRet = extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST, credentialDigest);
181 IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialDigestRet == true, GENERAL_ERROR);
182 bool setCredentialCountRet = extraInfo.SetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT,
183 info.enrolledState.credentialCount);
184 IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialCountRet == true, GENERAL_ERROR);
185 return SUCCESS;
186 }
187
QueryReusableAuthResult(const int32_t userId,const AuthParamInner & authParam,HdiReuseUnlockInfo & reuseResultInfo)188 int32_t AuthWidgetHelper::QueryReusableAuthResult(const int32_t userId, const AuthParamInner &authParam,
189 HdiReuseUnlockInfo &reuseResultInfo)
190 {
191 IAM_LOGI("start userId:%{public}d, reuseMode:%{public}u, reuseDuration: %{public}" PRIu64 ".",
192 userId, authParam.reuseUnlockResult.reuseMode, authParam.reuseUnlockResult.reuseDuration);
193 if (!authParam.reuseUnlockResult.isReuse || authParam.reuseUnlockResult.reuseDuration == 0 ||
194 authParam.reuseUnlockResult.reuseDuration > MAX_ALLOWABLE_REUSE_DURATION ||
195 (authParam.reuseUnlockResult.reuseMode != AUTH_TYPE_RELEVANT &&
196 authParam.reuseUnlockResult.reuseMode != AUTH_TYPE_IRRELEVANT &&
197 authParam.reuseUnlockResult.reuseMode != CALLER_IRRELEVANT_AUTH_TYPE_RELEVANT &&
198 authParam.reuseUnlockResult.reuseMode != CALLER_IRRELEVANT_AUTH_TYPE_IRRELEVANT)) {
199 IAM_LOGE("CheckReuseUnlockResult invalid param");
200 return INVALID_PARAMETERS;
201 }
202 auto hdi = HdiWrapper::GetHdiInstance();
203 if (hdi == nullptr) {
204 IAM_LOGE("hdi interface is nullptr");
205 return GENERAL_ERROR;
206 }
207
208 HdiReuseUnlockParam unlockParam = {};
209 unlockParam.baseParam.userId = userId;
210 unlockParam.baseParam.authTrustLevel = authParam.authTrustLevel;
211 for (auto &type : authParam.authTypes) {
212 unlockParam.authTypes.emplace_back(static_cast<HdiAuthType>(type));
213 }
214 unlockParam.baseParam.challenge = authParam.challenge;
215 unlockParam.reuseUnlockResultMode = authParam.reuseUnlockResult.reuseMode;
216 unlockParam.reuseUnlockResultDuration = authParam.reuseUnlockResult.reuseDuration;
217
218 return hdi->CheckReuseUnlockResult(unlockParam, reuseResultInfo);
219 }
220
CheckReuseUnlockResult(const ContextFactory::AuthWidgetContextPara & para,const AuthParamInner & authParam,Attributes & extraInfo)221 int32_t AuthWidgetHelper::CheckReuseUnlockResult(const ContextFactory::AuthWidgetContextPara ¶,
222 const AuthParamInner &authParam, Attributes &extraInfo)
223 {
224 IAM_LOGI("start userId:%{public}d, reuseMode:%{public}u, reuseDuration: %{public}" PRIu64 ".",
225 para.userId, authParam.reuseUnlockResult.reuseMode, authParam.reuseUnlockResult.reuseDuration);
226 HdiReuseUnlockInfo reuseResultInfo = {};
227 int32_t result = QueryReusableAuthResult(para.userId, authParam, reuseResultInfo);
228 if (result != SUCCESS) {
229 IAM_LOGE("QueryReusableAuthResult failed result:%{public}d userId:%{public}d", result, para.userId);
230 return result;
231 }
232
233 return SetReuseUnlockResult(para.sdkVersion, reuseResultInfo, extraInfo);
234 }
235 } // namespace UserAuth
236 } // namespace UserIam
237 } // namespace OHOS