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