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 WidgetParam &widgetParam, ContextFactory::AuthWidgetContextPara &para)33 bool AuthWidgetHelper::InitWidgetContextParam(const AuthParamInner &authParam, std::vector<AuthType> &validType,
34     const WidgetParam &widgetParam, ContextFactory::AuthWidgetContextPara &para)
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) {
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.widgetParam = widgetParam;
53     if (widgetParam.windowMode == WindowModeType::UNKNOWN_WINDOW_MODE) {
54         para.widgetParam.windowMode = WindowModeType::DIALOG_BOX;
55     }
56     return true;
57 }
58 
GetUserAuthProfile(int32_t userId, const AuthType &authType, ContextFactory::AuthProfile &profile)59 bool AuthWidgetHelper::GetUserAuthProfile(int32_t userId, const AuthType &authType,
60     ContextFactory::AuthProfile &profile)
61 {
62     Attributes values;
63     auto credentialInfos = UserIdmDatabase::Instance().GetCredentialInfo(userId, authType);
64     if (credentialInfos.empty() || credentialInfos[0] == nullptr) {
65         IAM_LOGE("user %{public}d has no credential type %{public}d", userId, authType);
66         return false;
67     }
68     uint64_t executorIndex = credentialInfos[0]->GetExecutorIndex();
69     auto resourceNode = ResourceNodePool::Instance().Select(executorIndex).lock();
70     if (resourceNode == nullptr) {
71         IAM_LOGE("resourceNode is nullptr");
72         return false;
73     }
74 
75     std::vector<uint64_t> templateIds;
76     templateIds.reserve(credentialInfos.size());
77     for (auto &info : credentialInfos) {
78         if (info == nullptr) {
79             IAM_LOGE("info is null");
80             continue;
81         }
82         templateIds.push_back(info->GetTemplateId());
83     }
84     std::vector<uint32_t> uint32Keys = {
85         Attributes::ATTR_SENSOR_INFO,
86         Attributes::ATTR_REMAIN_TIMES,
87         Attributes::ATTR_FREEZING_TIME
88     };
89     if (authType == AuthType::PIN) {
90         uint32Keys.push_back(Attributes::ATTR_PIN_SUB_TYPE);
91     }
92 
93     Attributes attr;
94     attr.SetInt32Value(Attributes::ATTR_AUTH_TYPE, authType);
95     attr.SetUint32Value(Attributes::ATTR_PROPERTY_MODE, PROPERTY_MODE_GET);
96     attr.SetUint64ArrayValue(Attributes::ATTR_TEMPLATE_ID_LIST, templateIds);
97     attr.SetUint32ArrayValue(Attributes::ATTR_KEY_LIST, uint32Keys);
98     int32_t result = resourceNode->GetProperty(attr, values);
99     if (result != SUCCESS) {
100         IAM_LOGE("failed to get property, result = %{public}d", result);
101         return false;
102     }
103     return ParseAttributes(values, authType, profile);
104 }
105 
ParseAttributes(const Attributes &values, const AuthType &authType, ContextFactory::AuthProfile &profile)106 bool AuthWidgetHelper::ParseAttributes(const Attributes &values, const AuthType &authType,
107     ContextFactory::AuthProfile &profile)
108 {
109     if (authType == AuthType::PIN) {
110         if (!values.GetInt32Value(Attributes::ATTR_PIN_SUB_TYPE, profile.pinSubType)) {
111             IAM_LOGE("get ATTR_PIN_SUB_TYPE failed");
112             return false;
113         }
114     }
115     if (!values.GetStringValue(Attributes::ATTR_SENSOR_INFO, profile.sensorInfo)) {
116         IAM_LOGE("get ATTR_SENSOR_INFO failed");
117         return false;
118     }
119     if (!values.GetInt32Value(Attributes::ATTR_REMAIN_TIMES, profile.remainTimes)) {
120         IAM_LOGE("get ATTR_REMAIN_TIMES failed");
121         return false;
122     }
123     if (!values.GetInt32Value(Attributes::ATTR_FREEZING_TIME, profile.freezingTime)) {
124         IAM_LOGE("get ATTR_FREEZING_TIME failed");
125         return false;
126     }
127     return true;
128 }
129 
CheckValidSolution(int32_t userId, const std::vector<AuthType> &authTypeList, const AuthTrustLevel &atl, std::vector<AuthType> &validTypeList)130 int32_t AuthWidgetHelper::CheckValidSolution(int32_t userId,
131     const std::vector<AuthType> &authTypeList, const AuthTrustLevel &atl, std::vector<AuthType> &validTypeList)
132 {
133     IAM_LOGI("start userId:%{public}d atl:%{public}u typeSize:%{public}zu", userId, atl, authTypeList.size());
134     auto hdi = HdiWrapper::GetHdiInstance();
135     if (hdi == nullptr) {
136         IAM_LOGE("hdi interface is nullptr");
137         return GENERAL_ERROR;
138     }
139     std::vector<int32_t> inputAuthType;
140     std::vector<int32_t> validTypes;
141     uint32_t inputAtl = atl;
142     for (auto &type : authTypeList) {
143         inputAuthType.emplace_back(static_cast<int32_t>(type));
144     }
145     int32_t result = hdi->GetValidSolution(userId, inputAuthType, inputAtl, validTypes);
146     if (result != SUCCESS) {
147         IAM_LOGE("GetValidSolution failed result:%{public}d userId:%{public}d", result, userId);
148         return result;
149     }
150     validTypeList.clear();
151     for (auto &type : validTypes) {
152         IAM_LOGI("get valid authType:%{public}d", type);
153         validTypeList.emplace_back(static_cast<AuthType>(type));
154     }
155     return result;
156 }
157 
SetReuseUnlockResult(int32_t apiVersion, const HdiReuseUnlockInfo &info, Attributes &extraInfo)158 int32_t AuthWidgetHelper::SetReuseUnlockResult(int32_t apiVersion, const HdiReuseUnlockInfo &info,
159     Attributes &extraInfo)
160 {
161     bool setSignatureResult = extraInfo.SetUint8ArrayValue(Attributes::ATTR_SIGNATURE, info.token);
162     IF_FALSE_LOGE_AND_RETURN_VAL(setSignatureResult == true, GENERAL_ERROR);
163     bool setAuthTypeResult = extraInfo.SetInt32Value(Attributes::ATTR_AUTH_TYPE,
164         static_cast<int32_t>(info.authType));
165     IF_FALSE_LOGE_AND_RETURN_VAL(setAuthTypeResult == true, GENERAL_ERROR);
166     bool setResultCodeRet = extraInfo.SetInt32Value(Attributes::ATTR_RESULT_CODE, SUCCESS);
167     IF_FALSE_LOGE_AND_RETURN_VAL(setResultCodeRet == true, GENERAL_ERROR);
168     uint64_t credentialDigest = info.enrolledState.credentialDigest;
169     if (apiVersion < INNER_API_VERSION_10000) {
170         credentialDigest = info.enrolledState.credentialDigest & UINT16_MAX;
171     }
172     bool setCredentialDigestRet = extraInfo.SetUint64Value(Attributes::ATTR_CREDENTIAL_DIGEST, credentialDigest);
173     IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialDigestRet == true, GENERAL_ERROR);
174     bool setCredentialCountRet = extraInfo.SetUint16Value(Attributes::ATTR_CREDENTIAL_COUNT,
175         info.enrolledState.credentialCount);
176     IF_FALSE_LOGE_AND_RETURN_VAL(setCredentialCountRet == true, GENERAL_ERROR);
177     return SUCCESS;
178 }
179 
CheckReuseUnlockResult(const ContextFactory::AuthWidgetContextPara &para, const AuthParamInner &authParam, Attributes &extraInfo)180 int32_t AuthWidgetHelper::CheckReuseUnlockResult(const ContextFactory::AuthWidgetContextPara &para,
181     const AuthParamInner &authParam, Attributes &extraInfo)
182 {
183     IAM_LOGI("start userId:%{public}d, reuseMode:%{public}u, reuseDuration: %{public}" PRIu64 ".",
184         para.userId, authParam.reuseUnlockResult.reuseMode, authParam.reuseUnlockResult.reuseDuration);
185     if (!authParam.reuseUnlockResult.isReuse || authParam.reuseUnlockResult.reuseDuration == 0 ||
186         authParam.reuseUnlockResult.reuseDuration > MAX_ALLOWABLE_REUSE_DURATION ||
187         (authParam.reuseUnlockResult.reuseMode != AUTH_TYPE_RELEVANT &&
188         authParam.reuseUnlockResult.reuseMode != AUTH_TYPE_IRRELEVANT)) {
189         IAM_LOGE("CheckReuseUnlockResult invalid param");
190         return INVALID_PARAMETERS;
191     }
192     auto hdi = HdiWrapper::GetHdiInstance();
193     if (hdi == nullptr) {
194         IAM_LOGE("hdi interface is nullptr");
195         return GENERAL_ERROR;
196     }
197 
198     HdiReuseUnlockParam unlockParam = {};
199     unlockParam.baseParam.userId = para.userId;
200     unlockParam.baseParam.authTrustLevel = authParam.authTrustLevel;
201     for (auto &type : authParam.authTypes) {
202         unlockParam.authTypes.emplace_back(static_cast<HdiAuthType>(type));
203     }
204     unlockParam.baseParam.challenge = authParam.challenge;
205     unlockParam.baseParam.callerName = para.callerName;
206     unlockParam.baseParam.callerType = para.callerType;
207     unlockParam.baseParam.apiVersion = para.sdkVersion;
208     unlockParam.reuseUnlockResultMode = authParam.reuseUnlockResult.reuseMode;
209     unlockParam.reuseUnlockResultDuration = authParam.reuseUnlockResult.reuseDuration;
210 
211     HdiReuseUnlockInfo reuseResultInfo = {};
212     int32_t result = hdi->CheckReuseUnlockResult(unlockParam, reuseResultInfo);
213     if (result != SUCCESS) {
214         IAM_LOGE("CheckReuseUnlockResult failed result:%{public}d userId:%{public}d", result, para.userId);
215         return result;
216     }
217 
218     return SetReuseUnlockResult(para.sdkVersion, reuseResultInfo, extraInfo);
219 }
220 } // namespace UserAuth
221 } // namespace UserIam
222 } // namespace OHOS