1 /*
2 * Copyright (c) 2022-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 "all_in_one_impl.h"
17
18 #include <chrono>
19 #include <cinttypes>
20 #include <hdf_base.h>
21
22 #include "defines.h"
23 #include "executor_impl_common.h"
24 #include "iam_logger.h"
25
26 #undef LOG_TAG
27 #define LOG_TAG "PIN_AUTH_IMPL_A"
28
29 namespace OHOS {
30 namespace HDI {
31 namespace PinAuth {
32 namespace {
33 constexpr uint32_t ENROLL_PIN = 0;
34 constexpr uint32_t AUTH_PIN = 1;
35
36 constexpr size_t MAX_SCHEDULE_SIZE = 50;
37 }
38
AllInOneImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)39 AllInOneImpl::AllInOneImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)
40 : pinHdi_(pinHdi),
41 threadPool_("pin_async")
42 {
43 threadPool_.Start(1);
44 }
45
~AllInOneImpl()46 AllInOneImpl::~AllInOneImpl()
47 {
48 threadPool_.Stop();
49 }
50
GetExecutorInfo(HdiExecutorInfo & info)51 int32_t AllInOneImpl::GetExecutorInfo(HdiExecutorInfo &info)
52 {
53 IAM_LOGI("start");
54 if (pinHdi_ == nullptr) {
55 IAM_LOGE("pinHdi_ is nullptr");
56 return HDF_FAILURE;
57 }
58 info.sensorId = SENSOR_ID;
59 info.executorMatcher = EXECUTOR_MATCHER;
60 info.executorRole = HdiExecutorRole::ALL_IN_ONE;
61 info.authType = HdiAuthType::PIN;
62 uint32_t eslRet = 0;
63 int32_t result = pinHdi_->GetExecutorInfo(HdiExecutorRole::ALL_IN_ONE, info.publicKey, eslRet,
64 info.maxTemplateAcl);
65 if (result != SUCCESS) {
66 IAM_LOGE("Get all in one ExecutorInfo failed, fail code:%{public}d", result);
67 return HDF_FAILURE;
68 }
69 info.esl = static_cast<HdiExecutorSecureLevel>(eslRet);
70 return HDF_SUCCESS;
71 }
72
OnRegisterFinish(const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & frameworkPublicKey,const std::vector<uint8_t> & extraInfo)73 int32_t AllInOneImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
74 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
75 {
76 IAM_LOGI("start");
77 static_cast<void>(extraInfo);
78 if (pinHdi_ == nullptr) {
79 IAM_LOGE("pinHdi_ is nullptr");
80 return HDF_FAILURE;
81 }
82 int32_t result = pinHdi_->SetAllInOneFwkParam(templateIdList, frameworkPublicKey);
83 if (result != SUCCESS) {
84 IAM_LOGE("Verify templateData failed");
85 return HDF_FAILURE;
86 }
87
88 return HDF_SUCCESS;
89 }
90
SendMessage(uint64_t scheduleId,int32_t srcRole,const std::vector<uint8_t> & msg)91 int32_t AllInOneImpl::SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t> &msg)
92 {
93 static_cast<void>(scheduleId);
94 static_cast<void>(srcRole);
95 static_cast<void>(msg);
96 IAM_LOGI("send message success");
97 return HDF_SUCCESS;
98 }
99
EnrollInner(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<HdiIExecutorCallback> & callbackObj,std::vector<uint8_t> & algoParameter,uint32_t & algoVersion)100 int32_t AllInOneImpl::EnrollInner(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
101 const sptr<HdiIExecutorCallback> &callbackObj, std::vector<uint8_t> &algoParameter, uint32_t &algoVersion)
102 {
103 IAM_LOGI("start");
104 static_cast<void>(extraInfo);
105 if (pinHdi_->GenerateAlgoParameter(algoParameter, algoVersion) != SUCCESS) {
106 IAM_LOGE("Generate algorithm parameter failed");
107 CallError(callbackObj, GENERAL_ERROR);
108 return GENERAL_ERROR;
109 }
110
111 ScheduleInfo scheduleInfo = {
112 .scheduleId = scheduleId,
113 .commandId = ENROLL_PIN,
114 .callback = callbackObj,
115 .templateId = 0,
116 .algoParameter = algoParameter,
117 };
118 if (!scheduleList_.AddScheduleInfo(scheduleInfo)) {
119 IAM_LOGE("Add scheduleInfo failed");
120 CallError(callbackObj, GENERAL_ERROR);
121 return GENERAL_ERROR;
122 }
123
124 return HDF_SUCCESS;
125 }
126
Enroll(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<HdiIExecutorCallback> & callbackObj)127 int32_t AllInOneImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
128 const sptr<HdiIExecutorCallback> &callbackObj)
129 {
130 IAM_LOGI("start");
131 if (callbackObj == nullptr) {
132 IAM_LOGE("callbackObj is nullptr");
133 return HDF_ERR_INVALID_PARAM;
134 }
135 if (pinHdi_ == nullptr) {
136 IAM_LOGE("pinHdi_ is nullptr");
137 CallError(callbackObj, INVALID_PARAMETERS);
138 return HDF_SUCCESS;
139 }
140 std::vector<uint8_t> algoParameter;
141 uint32_t algoVersion = 0;
142 int32_t result = EnrollInner(scheduleId, extraInfo, callbackObj, algoParameter, algoVersion);
143 if (result != SUCCESS) {
144 IAM_LOGE("EnrollInner failed, fail code : %{public}d", result);
145 return HDF_SUCCESS;
146 }
147
148 std::vector<uint8_t> challenge;
149 std::string pinComplexityReg = "";
150 result = callbackObj->OnGetData(algoParameter, 0, algoVersion, challenge, pinComplexityReg);
151 if (result != SUCCESS) {
152 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
153 CallError(callbackObj, GENERAL_ERROR);
154 // If the enroll fails, delete scheduleId of scheduleMap
155 scheduleList_.DelScheduleInfo(scheduleId);
156 }
157
158 return HDF_SUCCESS;
159 }
160
AuthenticateInner(uint64_t scheduleId,uint64_t templateId,std::vector<uint8_t> & algoParameter,const sptr<HdiIExecutorCallback> & callbackObj)161 int32_t AllInOneImpl::AuthenticateInner(uint64_t scheduleId, uint64_t templateId, std::vector<uint8_t> &algoParameter,
162 const sptr<HdiIExecutorCallback> &callbackObj)
163 {
164 IAM_LOGI("start");
165 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
166 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
167 if (result != SUCCESS) {
168 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
169 CallError(callbackObj, result);
170 return GENERAL_ERROR;
171 }
172 if (infoRet.remainTimes == 0 || infoRet.freezingTime > 0) {
173 IAM_LOGE("Pin authentication is now frozen state");
174 CallError(callbackObj, LOCKED);
175 return GENERAL_ERROR;
176 }
177 ScheduleInfo scheduleInfo = {
178 .scheduleId = scheduleId,
179 .commandId = AUTH_PIN,
180 .callback = callbackObj,
181 .templateId = templateId,
182 .algoParameter = algoParameter,
183 };
184 if (!scheduleList_.AddScheduleInfo(scheduleInfo)) {
185 IAM_LOGE("Add scheduleInfo failed");
186 CallError(callbackObj, GENERAL_ERROR);
187 return GENERAL_ERROR;
188 }
189
190 return SUCCESS;
191 }
192
Authenticate(uint64_t scheduleId,const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & extraInfo,const sptr<HdiIExecutorCallback> & callbackObj)193 int32_t AllInOneImpl::Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList,
194 const std::vector<uint8_t> &extraInfo, const sptr<HdiIExecutorCallback> &callbackObj)
195 {
196 IAM_LOGI("start");
197 if (callbackObj == nullptr) {
198 IAM_LOGE("callbackObj is nullptr");
199 return HDF_ERR_INVALID_PARAM;
200 }
201 if (pinHdi_ == nullptr || templateIdList.size() != 1) {
202 IAM_LOGE("pinHdi_ is nullptr or templateIdList size not 1");
203 CallError(callbackObj, INVALID_PARAMETERS);
204 return HDF_SUCCESS;
205 }
206 OHOS::UserIam::PinAuth::PinAlgoParam pinAlgoParam = {};
207 int32_t result = pinHdi_->AllInOneAuth(scheduleId, templateIdList[0], extraInfo, pinAlgoParam);
208 if (result != SUCCESS) {
209 IAM_LOGE("Get algorithm parameter failed, fail code : %{public}d", result);
210 CallError(callbackObj, result);
211 return HDF_SUCCESS;
212 }
213 IAM_LOGI("algorithm parameter len:%{public}zu version:%{public}u",
214 pinAlgoParam.algoParameter.size(), pinAlgoParam.algoVersion);
215 result = AuthenticateInner(
216 scheduleId, templateIdList[0], pinAlgoParam.algoParameter, callbackObj);
217 if (result != SUCCESS) {
218 IAM_LOGE("AuthenticateInner failed, fail code : %{public}d", result);
219 return HDF_SUCCESS;
220 }
221
222 std::string pinComplexityReg = "";
223 result = callbackObj->OnGetData(pinAlgoParam.algoParameter, pinAlgoParam.subType, pinAlgoParam.algoVersion,
224 pinAlgoParam.challenge, pinComplexityReg);
225 if (result != SUCCESS) {
226 IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result);
227 CallError(callbackObj, GENERAL_ERROR);
228 // If the authentication fails, delete scheduleId of scheduleMap
229 scheduleList_.DelScheduleInfo(scheduleId);
230 }
231
232 return HDF_SUCCESS;
233 }
234
AuthPin(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & data,std::vector<uint8_t> & resultTlv)235 int32_t AllInOneImpl::AuthPin(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &data,
236 std::vector<uint8_t> &resultTlv)
237 {
238 int32_t result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv);
239 if (result != SUCCESS) {
240 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
241 return result;
242 }
243 threadPool_.AddTask([hdi = pinHdi_, id = templateId]() {
244 if (hdi == nullptr) {
245 return;
246 }
247 hdi->WriteAntiBrute(id);
248 });
249 IAM_LOGI("Auth Pin success");
250 return result;
251 }
252
SetData(uint64_t scheduleId,uint64_t authSubType,const std::vector<uint8_t> & data,int32_t resultCode)253 int32_t AllInOneImpl::SetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data,
254 int32_t resultCode)
255 {
256 IAM_LOGI("start");
257 if (pinHdi_ == nullptr) {
258 IAM_LOGE("pinHdi_ is nullptr");
259 return HDF_FAILURE;
260 }
261 std::vector<uint8_t> resultTlv;
262 ScheduleInfo scheduleInfo;
263 if (!scheduleList_.GetAndDelScheduleInfo(scheduleId, scheduleInfo)) {
264 IAM_LOGE("Get ScheduleInfo failed");
265 return HDF_FAILURE;
266 }
267 if (resultCode != SUCCESS) {
268 IAM_LOGE("SetData failed, resultCode is %{public}d", resultCode);
269 CallError(scheduleInfo.callback, resultCode);
270 return HDF_SUCCESS;
271 }
272 int32_t result = GENERAL_ERROR;
273 switch (scheduleInfo.commandId) {
274 case ENROLL_PIN:
275 result = pinHdi_->EnrollPin(scheduleId, authSubType, scheduleInfo.algoParameter, data, resultTlv);
276 if (result != SUCCESS) {
277 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
278 }
279 break;
280 case AUTH_PIN:
281 result = AuthPin(scheduleId, scheduleInfo.templateId, data, resultTlv);
282 if (result != SUCCESS) {
283 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
284 }
285 break;
286 default:
287 IAM_LOGE("Error commandId");
288 }
289
290 if (scheduleInfo.callback->OnResult(result, resultTlv) != SUCCESS) {
291 IAM_LOGE("callback OnResult failed");
292 }
293 return HDF_SUCCESS;
294 }
295
Delete(uint64_t templateId)296 int32_t AllInOneImpl::Delete(uint64_t templateId)
297 {
298 IAM_LOGI("start");
299 if (pinHdi_ == nullptr) {
300 IAM_LOGE("pinHdi_ is nullptr");
301 return HDF_FAILURE;
302 }
303 int32_t result = pinHdi_->DeleteTemplate(templateId);
304 if (result != SUCCESS) {
305 IAM_LOGE("Verify templateData failed, fail code : %{public}d", result);
306 return HDF_FAILURE;
307 }
308
309 return HDF_SUCCESS;
310 }
311
Cancel(uint64_t scheduleId)312 int32_t AllInOneImpl::Cancel(uint64_t scheduleId)
313 {
314 IAM_LOGI("start");
315 ScheduleInfo scheduleInfo;
316 if (!scheduleList_.GetAndDelScheduleInfo(scheduleId, scheduleInfo)) {
317 IAM_LOGE("scheduleId %{public}x is not found", (uint16_t)scheduleId);
318 return HDF_FAILURE;
319 }
320 CallError(scheduleInfo.callback, CANCELED);
321 return HDF_SUCCESS;
322 }
323
GetProperty(const std::vector<uint64_t> & templateIdList,const std::vector<int32_t> & propertyTypes,HdiProperty & property)324 int32_t AllInOneImpl::GetProperty(
325 const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes, HdiProperty &property)
326 {
327 IAM_LOGI("start");
328 if (pinHdi_ == nullptr) {
329 IAM_LOGE("pinHdi_ is nullptr");
330 return HDF_FAILURE;
331 }
332
333 if (templateIdList.size() != 1) {
334 IAM_LOGE("templateIdList size is not 1");
335 return HDF_ERR_INVALID_PARAM;
336 }
337
338 uint64_t templateId = templateIdList[0];
339 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
340 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
341 if (result != SUCCESS) {
342 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
343 return HDF_FAILURE;
344 }
345
346 property.authSubType = infoRet.subType;
347 property.remainAttempts = infoRet.remainTimes;
348 property.lockoutDuration = infoRet.freezingTime;
349 property.nextFailLockoutDuration = infoRet.nextFailLockoutDuration;
350 return HDF_SUCCESS;
351 }
352
SendCommand(int32_t commandId,const std::vector<uint8_t> & extraInfo,const sptr<HdiIExecutorCallback> & callbackObj)353 int32_t AllInOneImpl::SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
354 const sptr<HdiIExecutorCallback> &callbackObj)
355 {
356 return HDF_SUCCESS;
357 }
358
AddScheduleInfo(const ScheduleInfo & scheduleInfo)359 bool AllInOneImpl::ScheduleList::AddScheduleInfo(const ScheduleInfo &scheduleInfo)
360 {
361 IAM_LOGI("start");
362 if (scheduleInfo.callback == nullptr) {
363 IAM_LOGE("callback is nullptr");
364 return false;
365 }
366
367 std::optional<ScheduleInfo> optScheduleInfo = std::nullopt;
368 {
369 std::lock_guard<std::mutex> guard(mutex_);
370 for (auto iter = scheduleInfoList_.begin(); iter != scheduleInfoList_.end(); ++iter) {
371 if ((*iter).scheduleId == scheduleInfo.scheduleId) {
372 IAM_LOGE("scheduleId %{public}x already exist", (uint16_t)(scheduleInfo.scheduleId));
373 return false;
374 }
375 }
376
377 if (scheduleInfoList_.size() >= MAX_SCHEDULE_SIZE) {
378 optScheduleInfo = scheduleInfoList_.front();
379 scheduleInfoList_.pop_front();
380 }
381 scheduleInfoList_.emplace_back(scheduleInfo);
382 }
383
384 if (optScheduleInfo.has_value()) {
385 IAM_LOGE("scheduleId %{public}x force stop", (uint16_t)(optScheduleInfo.value().scheduleId));
386 CallError(optScheduleInfo.value().callback, GENERAL_ERROR);
387 }
388 return true;
389 }
390
GetAndDelScheduleInfo(uint64_t scheduleId,ScheduleInfo & scheduleInfo)391 bool AllInOneImpl::ScheduleList::GetAndDelScheduleInfo(uint64_t scheduleId, ScheduleInfo &scheduleInfo)
392 {
393 IAM_LOGI("start");
394 std::lock_guard<std::mutex> guard(mutex_);
395 for (auto iter = scheduleInfoList_.begin(); iter != scheduleInfoList_.end(); ++iter) {
396 if ((*iter).scheduleId == scheduleId) {
397 scheduleInfo = (*iter);
398 scheduleInfoList_.erase(iter);
399 return true;
400 }
401 }
402
403 IAM_LOGE("Get scheduleId not exist");
404 return false;
405 }
406
DelScheduleInfo(uint64_t scheduleId)407 void AllInOneImpl::ScheduleList::DelScheduleInfo(uint64_t scheduleId)
408 {
409 IAM_LOGI("start");
410 std::lock_guard<std::mutex> guard(mutex_);
411 for (auto iter = scheduleInfoList_.begin(); iter != scheduleInfoList_.end(); ++iter) {
412 if ((*iter).scheduleId == scheduleId) {
413 scheduleInfoList_.erase(iter);
414 return;
415 }
416 }
417 IAM_LOGE("Delete scheduleId not exist");
418 }
419 } // PinAuth
420 } // HDI
421 } // OHOS