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
22 #include "credential_info_impl.h"
23 #include "schedule_node_helper.h"
24 #include "user_idm_database.h"
25
26 #define LOG_LABEL UserIam::Common::LABEL_USER_AUTH_SA
27
28 namespace OHOS {
29 namespace UserIam {
30 namespace UserAuth {
EnrollmentImpl(int32_t userId,AuthType authType)31 EnrollmentImpl::EnrollmentImpl(int32_t userId, AuthType authType) : userId_(userId), authType_(authType)
32 {
33 }
34
~EnrollmentImpl()35 EnrollmentImpl::~EnrollmentImpl()
36 {
37 Cancel();
38 }
39
SetLatestError(int32_t error)40 void EnrollmentImpl::SetLatestError(int32_t error)
41 {
42 if (error != ResultCode::SUCCESS) {
43 latestError_ = error;
44 }
45 }
46
GetLatestError() const47 int32_t EnrollmentImpl::GetLatestError() const
48 {
49 return latestError_;
50 }
51
SetExecutorSensorHint(uint32_t executorSensorHint)52 void EnrollmentImpl::SetExecutorSensorHint(uint32_t executorSensorHint)
53 {
54 executorSensorHint_ = executorSensorHint;
55 }
56
SetAuthToken(const std::vector<uint8_t> & authToken)57 void EnrollmentImpl::SetAuthToken(const std::vector<uint8_t> &authToken)
58 {
59 authToken_ = authToken;
60 }
61
SetAccessTokenId(uint32_t tokenId)62 void EnrollmentImpl::SetAccessTokenId(uint32_t tokenId)
63 {
64 tokenId_ = tokenId;
65 }
66
GetAccessTokenId() const67 uint32_t EnrollmentImpl::GetAccessTokenId() const
68 {
69 return tokenId_;
70 }
71
SetPinSubType(PinSubType pinSubType)72 void EnrollmentImpl::SetPinSubType(PinSubType pinSubType)
73 {
74 pinSubType_ = pinSubType;
75 }
76
SetIsUpdate(bool isUpdate)77 void EnrollmentImpl::SetIsUpdate(bool isUpdate)
78 {
79 isUpdate_ = isUpdate;
80 }
81
Start(std::vector<std::shared_ptr<ScheduleNode>> & scheduleList,std::shared_ptr<ScheduleNodeCallback> callback)82 bool EnrollmentImpl::Start(std::vector<std::shared_ptr<ScheduleNode>> &scheduleList,
83 std::shared_ptr<ScheduleNodeCallback> callback)
84 {
85 auto hdi = HdiWrapper::GetHdiInstance();
86 if (!hdi) {
87 IAM_LOGE("bad hdi");
88 return false;
89 }
90 // cache secUserId first in case of update
91 if (isUpdate_ && !GetSecUserId(secUserId_)) {
92 IAM_LOGE("get and cache secUserId fail");
93 return false;
94 }
95
96 HdiScheduleInfo info = {};
97 HdiEnrollParam param = {
98 .authType = static_cast<HdiAuthType>(authType_),
99 .executorSensorHint = executorSensorHint_,
100 };
101 IamHitraceHelper traceHelper("hdi BeginEnrollment");
102 auto result = hdi->BeginEnrollmentV1_1(userId_, authToken_, param, info);
103 if (result != HDF_SUCCESS) {
104 IAM_LOGE("hdi BeginEnrollment failed, err is %{public}d", result);
105 SetLatestError(result);
106 return false;
107 }
108
109 std::vector<HdiScheduleInfo> infos = {};
110 infos.emplace_back(info);
111
112 ScheduleNodeHelper::NodeOptionalPara para;
113 para.tokenId = tokenId_;
114
115 if (!ScheduleNodeHelper::BuildFromHdi(infos, callback, scheduleList, para)) {
116 IAM_LOGE("BuildFromHdi failed");
117 return false;
118 }
119
120 running_ = true;
121 return true;
122 }
123
GetSecUserId(std::optional<uint64_t> & secUserId)124 bool EnrollmentImpl::GetSecUserId(std::optional<uint64_t> &secUserId)
125 {
126 secUserId = std::nullopt;
127 if (authType_ != PIN) {
128 IAM_LOGI("no need return sec user id");
129 return true;
130 }
131 auto userInfo = UserIdmDatabase::Instance().GetSecUserInfo(userId_);
132 if (userInfo != nullptr) {
133 secUserId = userInfo->GetSecUserId();
134 return true;
135 }
136
137 // do not delete users in case of updates
138 if (isUpdate_) {
139 return false;
140 }
141
142 IAM_LOGE("current user id %{public}d get fail", userId_);
143 std::vector<std::shared_ptr<CredentialInfoInterface>> credInfos;
144 if (UserIdmDatabase::Instance().DeleteUserEnforce(userId_, credInfos) != SUCCESS) {
145 IAM_LOGE("failed to enforce delete user");
146 }
147 return false;
148 }
149
Update(const std::vector<uint8_t> & scheduleResult,uint64_t & credentialId,std::shared_ptr<CredentialInfoInterface> & info,std::vector<uint8_t> & rootSecret,std::optional<uint64_t> & secUserId)150 bool EnrollmentImpl::Update(const std::vector<uint8_t> &scheduleResult, uint64_t &credentialId,
151 std::shared_ptr<CredentialInfoInterface> &info, std::vector<uint8_t> &rootSecret,
152 std::optional<uint64_t> &secUserId)
153 {
154 auto hdi = HdiWrapper::GetHdiInstance();
155 if (!hdi) {
156 IAM_LOGE("bad hdi");
157 return false;
158 }
159
160 HdiEnrollResultInfo resultInfo = {};
161 auto result = hdi->UpdateEnrollmentResult(userId_, scheduleResult, resultInfo);
162 if (result != HDF_SUCCESS) {
163 IAM_LOGE("hdi UpdateEnrollmentResult failed, err is %{public}d, userId is %{public}d", result, userId_);
164 SetLatestError(result);
165 return false;
166 }
167 IAM_LOGI("hdi UpdateEnrollmentResult success, userId is %{public}d", userId_);
168
169 credentialId = resultInfo.credentialId;
170 rootSecret = resultInfo.rootSecret;
171 if (isUpdate_) {
172 secUserId = secUserId_;
173 } else {
174 if (!GetSecUserId(secUserId)) {
175 IAM_LOGE("enroll get secUserId fail");
176 return false;
177 }
178 IAM_LOGI("enroll not need to delete old cred");
179 info = nullptr;
180 return true;
181 }
182
183 info = Common::MakeShared<CredentialInfoImpl>(userId_, resultInfo.oldInfo);
184 if (info == nullptr) {
185 IAM_LOGE("bad alloc");
186 return false;
187 }
188 return true;
189 }
190
Cancel()191 bool EnrollmentImpl::Cancel()
192 {
193 if (!running_) {
194 return false;
195 }
196 running_ = false;
197
198 auto hdi = HdiWrapper::GetHdiInstance();
199 if (!hdi) {
200 IAM_LOGE("bad hdi");
201 return false;
202 }
203
204 auto result = hdi->CancelEnrollment(userId_);
205 if (result != HDF_SUCCESS) {
206 IAM_LOGE("hdi CancelEnrollment failed, err is %{public}d", result);
207 SetLatestError(result);
208 return false;
209 }
210 return true;
211 }
212 } // namespace UserAuth
213 } // namespace UserIam
214 } // namespace OHOS