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 #include "enrollment_impl.h"
16
17 #include "credential_info_impl.h"
18 #include "event_listener_manager.h"
19 #include "hdi_wrapper.h"
20 #include "iam_hitrace_helper.h"
21 #include "iam_logger.h"
22 #include "iam_ptr.h"
23 #include "ipc_common.h"
24 #include "load_mode_handler.h"
25 #include "publish_event_adapter.h"
26 #include "schedule_node_helper.h"
27 #include "update_pin_param_impl.h"
28 #include "user_idm_database.h"
29
30 #define LOG_TAG "USER_AUTH_SA"
31
32 namespace OHOS {
33 namespace UserIam {
34 namespace UserAuth {
EnrollmentImpl(EnrollmentPara enrollPara)35 EnrollmentImpl::EnrollmentImpl(EnrollmentPara enrollPara) : enrollPara_(enrollPara)
36 {
37 }
38
~EnrollmentImpl()39 EnrollmentImpl::~EnrollmentImpl()
40 {
41 Cancel();
42 }
43
SetLatestError(int32_t error)44 void EnrollmentImpl::SetLatestError(int32_t error)
45 {
46 if (error != ResultCode::SUCCESS) {
47 latestError_ = error;
48 }
49 }
50
GetLatestError() const51 int32_t EnrollmentImpl::GetLatestError() const
52 {
53 return latestError_;
54 }
55
SetExecutorSensorHint(uint32_t executorSensorHint)56 void EnrollmentImpl::SetExecutorSensorHint(uint32_t executorSensorHint)
57 {
58 executorSensorHint_ = executorSensorHint;
59 }
60
SetAuthToken(const std::vector<uint8_t> & authToken)61 void EnrollmentImpl::SetAuthToken(const std::vector<uint8_t> &authToken)
62 {
63 authToken_ = authToken;
64 }
65
SetAccessTokenId(uint32_t tokenId)66 void EnrollmentImpl::SetAccessTokenId(uint32_t tokenId)
67 {
68 tokenId_ = tokenId;
69 }
70
GetAccessTokenId() const71 uint32_t EnrollmentImpl::GetAccessTokenId() const
72 {
73 return tokenId_;
74 }
75
SetPinSubType(PinSubType pinSubType)76 void EnrollmentImpl::SetPinSubType(PinSubType pinSubType)
77 {
78 pinSubType_ = pinSubType;
79 }
80
SetIsUpdate(bool isUpdate)81 void EnrollmentImpl::SetIsUpdate(bool isUpdate)
82 {
83 isUpdate_ = isUpdate;
84 }
85
GetUserId() const86 int32_t EnrollmentImpl::GetUserId() const
87 {
88 return enrollPara_.userId;
89 }
90
Start(std::vector<std::shared_ptr<ScheduleNode>> & scheduleList,std::shared_ptr<ScheduleNodeCallback> callback)91 bool EnrollmentImpl::Start(std::vector<std::shared_ptr<ScheduleNode>> &scheduleList,
92 std::shared_ptr<ScheduleNodeCallback> callback)
93 {
94 IAM_LOGE("UserId:%{public}d, AuthType:%{public}d, pinSubType:%{public}d", enrollPara_.userId, enrollPara_.authType,
95 enrollPara_.pinType);
96 auto hdi = HdiWrapper::GetHdiInstance();
97 if (!hdi) {
98 IAM_LOGE("bad hdi");
99 return false;
100 }
101 // cache secUserId first in case of update
102 if (isUpdate_ && !GetSecUserId(secUserId_)) {
103 IAM_LOGE("get and cache secUserId fail");
104 return false;
105 }
106
107 HdiScheduleInfo info = {};
108 int32_t userType;
109 if (IpcCommon::GetUserTypeByUserId(enrollPara_.userId, userType) != SUCCESS) {
110 IAM_LOGE("failed to get userType");
111 return false;
112 }
113 HdiCallerType callerType = ConvertATokenTypeToCallerType(enrollPara_.callerType);
114 if (callerType == HDI_CALLER_TYPE_INVALID) {
115 IAM_LOGE("ConvertATokenTypeToCallerType failed, ATokenType:%{public}d", enrollPara_.callerType);
116 return false;
117 }
118 HdiEnrollParam param = {
119 .authType = static_cast<HdiAuthType>(enrollPara_.authType),
120 .executorSensorHint = executorSensorHint_,
121 .callerName = enrollPara_.callerName,
122 .callerType = callerType,
123 .apiVersion = enrollPara_.sdkVersion,
124 .userId = enrollPara_.userId,
125 .userType = userType,
126 .authSubType = enrollPara_.pinType,
127 };
128 IamHitraceHelper traceHelper("hdi BeginEnrollment");
129 auto result = hdi->BeginEnrollment(authToken_, param, info);
130 if (result != HDF_SUCCESS) {
131 IAM_LOGE("hdi BeginEnrollment failed, err is %{public}d", result);
132 SetLatestError(result);
133 return false;
134 }
135
136 return StartSchedule(enrollPara_.userId, info, scheduleList, callback);
137 }
138
GetSecUserId(std::optional<uint64_t> & secUserId)139 bool EnrollmentImpl::GetSecUserId(std::optional<uint64_t> &secUserId)
140 {
141 secUserId = std::nullopt;
142 if (enrollPara_.authType != PIN) {
143 IAM_LOGI("no need return sec user id");
144 return true;
145 }
146 std::shared_ptr<SecureUserInfoInterface> userInfo = nullptr;
147 int32_t ret = UserIdmDatabase::Instance().GetSecUserInfo(enrollPara_.userId, userInfo);
148 if (ret != SUCCESS) {
149 IAM_LOGE("get secUserInfo fail, ret:%{public}d, userId:%{public}d", ret, enrollPara_.userId);
150 return false;
151 }
152 if (userInfo != nullptr) {
153 secUserId = userInfo->GetSecUserId();
154 return true;
155 }
156
157 // do not delete users in case of updates
158 if (isUpdate_) {
159 return false;
160 }
161
162 IAM_LOGE("current user id %{public}d get fail", enrollPara_.userId);
163 std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
164 if (UserIdmDatabase::Instance().DeleteUserEnforce(enrollPara_.userId, credInfos) != SUCCESS) {
165 IAM_LOGE("failed to enforce delete user");
166 }
167 return false;
168 }
169
Update(const std::vector<uint8_t> & scheduleResult,uint64_t & credentialId,std::shared_ptr<CredentialInfoInterface> & info,std::shared_ptr<UpdatePinParamInterface> & pinInfo,std::optional<uint64_t> & secUserId)170 bool EnrollmentImpl::Update(const std::vector<uint8_t> &scheduleResult, uint64_t &credentialId,
171 std::shared_ptr<CredentialInfoInterface> &info, std::shared_ptr<UpdatePinParamInterface> &pinInfo,
172 std::optional<uint64_t> &secUserId)
173 {
174 auto hdi = HdiWrapper::GetHdiInstance();
175 if (!hdi) {
176 IAM_LOGE("bad hdi");
177 return false;
178 }
179
180 HdiEnrollResultInfo resultInfo = {};
181 auto result = hdi->UpdateEnrollmentResult(enrollPara_.userId, scheduleResult, resultInfo);
182 if (result != HDF_SUCCESS) {
183 IAM_LOGE("hdi UpdateEnrollmentResult failed, err is %{public}d, userId is %{public}d", result,
184 enrollPara_.userId);
185 SetLatestError(result);
186 return false;
187 }
188 IAM_LOGI("hdi UpdateEnrollmentResult success, userId is %{public}d", enrollPara_.userId);
189
190 credentialId = resultInfo.credentialId;
191 pinInfo = Common::MakeShared<UpdatePinParamImpl>(resultInfo.oldInfo.credentialId, resultInfo.oldRootSecret,
192 resultInfo.rootSecret, resultInfo.authToken);
193 if (pinInfo == nullptr) {
194 IAM_LOGE("pinInfo bad alloc");
195 return false;
196 }
197
198 if (isUpdate_) {
199 secUserId = secUserId_;
200 info = Common::MakeShared<CredentialInfoImpl>(enrollPara_.userId, resultInfo.oldInfo);
201 if (info == nullptr) {
202 IAM_LOGE("bad alloc");
203 return false;
204 }
205 } else {
206 if (!GetSecUserId(secUserId)) {
207 IAM_LOGE("enroll get secUserId fail");
208 return false;
209 }
210 IAM_LOGI("enroll not need to delete old cred");
211 info = nullptr;
212 }
213 PublishCredentialChangeEvent(resultInfo);
214 return true;
215 }
216
PublishCredentialChangeEvent(const HdiEnrollResultInfo & resultInfo)217 void EnrollmentImpl::PublishCredentialChangeEvent(const HdiEnrollResultInfo &resultInfo)
218 {
219 CredChangeEventInfo changeInfo = {
220 enrollPara_.callerName, enrollPara_.callerType, resultInfo.credentialId, 0, false};
221 if (isUpdate_ && enrollPara_.authType == PIN) {
222 changeInfo.lastCredentialId = resultInfo.oldInfo.credentialId;
223 PublishEventAdapter::GetInstance().CachePinUpdateParam(enrollPara_.userId, scheduleId_, changeInfo);
224 return;
225 }
226
227 std::vector<std::shared_ptr<CredentialInfoInterface>> credentialInfos;
228 if (UserIdmDatabase::Instance().GetCredentialInfo(
229 enrollPara_.userId, enrollPara_.authType, credentialInfos) != SUCCESS) {
230 IAM_LOGE("get credential fail");
231 return;
232 }
233 PublishEventAdapter::GetInstance().PublishCredentialUpdatedEvent(enrollPara_.userId,
234 static_cast<int32_t>(enrollPara_.authType), credentialInfos.size());
235
236 if (isUpdate_ && enrollPara_.authType != PIN) {
237 changeInfo.lastCredentialId = resultInfo.oldInfo.credentialId;
238 CredChangeEventListenerManager::GetInstance().OnNotifyCredChangeEvent(enrollPara_.userId,
239 enrollPara_.authType, UPDATE_CRED, changeInfo);
240 } else if (!isUpdate_ && enrollPara_.authType != PIN) {
241 CredChangeEventListenerManager::GetInstance().OnNotifyCredChangeEvent(enrollPara_.userId,
242 enrollPara_.authType, ADD_CRED, changeInfo);
243 } else {
244 PublishEventAdapter::GetInstance().PublishCreatedEvent(enrollPara_.userId, scheduleId_);
245 CredChangeEventListenerManager::GetInstance().OnNotifyCredChangeEvent(enrollPara_.userId,
246 enrollPara_.authType, ADD_CRED, changeInfo);
247 }
248 }
249
Cancel()250 bool EnrollmentImpl::Cancel()
251 {
252 if (!running_) {
253 return false;
254 }
255 running_ = false;
256
257 auto hdi = HdiWrapper::GetHdiInstance();
258 if (!hdi) {
259 IAM_LOGE("bad hdi");
260 return false;
261 }
262
263 auto result = hdi->CancelEnrollment(enrollPara_.userId);
264 if (result != HDF_SUCCESS) {
265 IAM_LOGE("hdi CancelEnrollment failed, err is %{public}d", result);
266 SetLatestError(result);
267 return false;
268 }
269 return true;
270 }
271
StartSchedule(int32_t userId,HdiScheduleInfo & info,std::vector<std::shared_ptr<ScheduleNode>> & scheduleList,std::shared_ptr<ScheduleNodeCallback> callback)272 bool EnrollmentImpl::StartSchedule(int32_t userId, HdiScheduleInfo &info,
273 std::vector<std::shared_ptr<ScheduleNode>> &scheduleList, std::shared_ptr<ScheduleNodeCallback> callback)
274 {
275 IAM_LOGI("start");
276 std::vector<HdiScheduleInfo> infos = {};
277 infos.emplace_back(info);
278
279 ScheduleNodeHelper::NodeOptionalPara para;
280 para.tokenId = tokenId_;
281 para.userId = userId;
282
283 if (!ScheduleNodeHelper::BuildFromHdi(infos, callback, scheduleList, para)) {
284 IAM_LOGE("BuildFromHdi failed");
285 return false;
286 }
287 if (scheduleList.size() == 0 || scheduleList[0] == nullptr) {
288 IAM_LOGE("Bad Parameter!");
289 return false;
290 }
291
292 scheduleId_ = scheduleList[0]->GetScheduleId();
293 running_ = true;
294 return true;
295 }
296 } // namespace UserAuth
297 } // namespace UserIam
298 } // namespace OHOS