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
16 #include "executor_impl.h"
17 #include <hdf_base.h>
18 #include <securec.h>
19 #include "defines.h"
20 #include "iam_logger.h"
21
22 #define LOG_LABEL OHOS::UserIam::Common::LABEL_PIN_AUTH_IMPL
23
24 namespace OHOS {
25 namespace HDI {
26 namespace PinAuth {
27 namespace {
28 constexpr uint32_t EXECUTOR_TYPE = 0;
29 constexpr uint32_t ENROLL_PIN = 0;
30 constexpr uint32_t AUTH_PIN = 1;
31 constexpr uint32_t GENERAL_ERROR = 2;
32 constexpr uint32_t SUCCESS = 0;
33 } // namespace
34
ExecutorImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)35 ExecutorImpl::ExecutorImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi)
36 : pinHdi_(pinHdi),
37 threadPool_("pin_async")
38 {
39 threadPool_.Start(1);
40 }
41
~ExecutorImpl()42 ExecutorImpl::~ExecutorImpl()
43 {
44 threadPool_.Stop();
45 }
46
GetExecutorInfo(ExecutorInfo & info)47 int32_t ExecutorImpl::GetExecutorInfo(ExecutorInfo &info)
48 {
49 IAM_LOGI("start");
50 if (pinHdi_ == nullptr) {
51 IAM_LOGE("pinHdi_ is nullptr");
52 return HDF_FAILURE;
53 }
54 constexpr unsigned short SENSOR_ID = 1;
55 info.sensorId = SENSOR_ID;
56 info.executorType = EXECUTOR_TYPE;
57 info.executorRole = ExecutorRole::ALL_IN_ONE;
58 info.authType = AuthType::PIN;
59 uint32_t eslRet = 0;
60 int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet);
61 if (result != SUCCESS) {
62 IAM_LOGE("Get ExecutorInfo failed, fail code : %{public}d", result);
63 return result;
64 }
65 info.esl = static_cast<ExecutorSecureLevel>(eslRet);
66
67 return HDF_SUCCESS;
68 }
69
GetTemplateInfo(uint64_t templateId,TemplateInfo & info)70 int32_t ExecutorImpl::GetTemplateInfo(uint64_t templateId, TemplateInfo &info)
71 {
72 IAM_LOGI("start");
73 if (pinHdi_ == nullptr) {
74 IAM_LOGE("pinHdi_ is nullptr");
75 return HDF_FAILURE;
76 }
77 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
78 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
79 if (result != SUCCESS) {
80 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
81 return result;
82 }
83 /* subType is stored in extraInfo */
84 info.extraInfo.resize(sizeof(infoRet.subType));
85 if (memcpy_s(&(info.extraInfo[0]), sizeof(infoRet.subType), &(infoRet.subType), sizeof(infoRet.subType)) != EOK) {
86 IAM_LOGE("copy subType to extraInfo fail!");
87 return HDF_FAILURE;
88 }
89
90 info.executorType = EXECUTOR_TYPE;
91 info.remainAttempts = infoRet.remainTimes;
92 info.lockoutDuration = infoRet.freezingTime;
93
94 return HDF_SUCCESS;
95 }
96
OnRegisterFinish(const std::vector<uint64_t> & templateIdList,const std::vector<uint8_t> & frameworkPublicKey,const std::vector<uint8_t> & extraInfo)97 int32_t ExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
98 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
99 {
100 IAM_LOGI("start");
101 static_cast<void>(frameworkPublicKey);
102 static_cast<void>(extraInfo);
103 if (pinHdi_ == nullptr) {
104 IAM_LOGE("pinHdi_ is nullptr");
105 return HDF_FAILURE;
106 }
107 int32_t result = pinHdi_->VerifyTemplateData(templateIdList);
108 if (result != SUCCESS) {
109 IAM_LOGE("Verify templateData failed");
110 return result;
111 }
112
113 return HDF_SUCCESS;
114 }
115
CallError(const sptr<IExecutorCallbackV1_0> & callbackObj,uint32_t errorCode)116 void ExecutorImpl::CallError(const sptr<IExecutorCallbackV1_0> &callbackObj, uint32_t errorCode)
117 {
118 IAM_LOGI("start");
119 std::vector<uint8_t> ret(0);
120 if (callbackObj->OnResult(errorCode, ret) != SUCCESS) {
121 IAM_LOGE("callback failed");
122 }
123 }
124
EnrollInner(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_0> & callbackObj,std::vector<uint8_t> & algoParameter,uint32_t & algoVersion)125 int32_t ExecutorImpl::EnrollInner(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
126 const sptr<IExecutorCallbackV1_0> &callbackObj, std::vector<uint8_t> &algoParameter, uint32_t &algoVersion)
127 {
128 IAM_LOGI("start");
129 static_cast<void>(extraInfo);
130 if (pinHdi_->GenerateAlgoParameter(algoParameter, algoVersion) != SUCCESS) {
131 IAM_LOGE("Generate algorithm parameter failed");
132 CallError(callbackObj, GENERAL_ERROR);
133 return GENERAL_ERROR;
134 }
135
136 int32_t result = scheduleMap_.AddScheduleInfo(scheduleId, ENROLL_PIN, callbackObj, 0, algoParameter);
137 if (result != HDF_SUCCESS) {
138 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result);
139 CallError(callbackObj, GENERAL_ERROR);
140 return GENERAL_ERROR;
141 }
142
143 return HDF_SUCCESS;
144 }
145
Enroll(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_0> & callbackObj)146 int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
147 const sptr<IExecutorCallbackV1_0> &callbackObj)
148 {
149 IAM_LOGI("start");
150 if (callbackObj == nullptr) {
151 IAM_LOGE("callbackObj is nullptr");
152 return HDF_ERR_INVALID_PARAM;
153 }
154 if (pinHdi_ == nullptr) {
155 IAM_LOGE("pinHdi_ is nullptr");
156 CallError(callbackObj, INVALID_PARAMETERS);
157 return HDF_SUCCESS;
158 }
159 std::vector<uint8_t> algoParameter;
160 uint32_t algoVersion = 0;
161 int32_t result = EnrollInner(scheduleId, extraInfo, callbackObj, algoParameter, algoVersion);
162 if (result != SUCCESS) {
163 IAM_LOGE("EnrollInner failed, fail code : %{public}d", result);
164 return HDF_SUCCESS;
165 }
166 result = callbackObj->OnGetData(scheduleId, algoParameter, 0);
167 if (result != SUCCESS) {
168 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
169 CallError(callbackObj, GENERAL_ERROR);
170 // If the enroll fails, delete scheduleId of scheduleMap
171 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
172 IAM_LOGI("delete scheduleId failed");
173 }
174 }
175
176 return HDF_SUCCESS;
177 }
178
EnrollV1_1(uint64_t scheduleId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)179 int32_t ExecutorImpl::EnrollV1_1(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
180 const sptr<IExecutorCallback> &callbackObj)
181 {
182 IAM_LOGI("start");
183 if (callbackObj == nullptr) {
184 IAM_LOGE("callbackObj is nullptr");
185 return HDF_ERR_INVALID_PARAM;
186 }
187 if (pinHdi_ == nullptr) {
188 IAM_LOGE("pinHdi_ is nullptr");
189 CallError(callbackObj, INVALID_PARAMETERS);
190 return HDF_SUCCESS;
191 }
192 std::vector<uint8_t> algoParameter;
193 uint32_t algoVersion = 0;
194 int32_t result = EnrollInner(scheduleId, extraInfo, callbackObj, algoParameter, algoVersion);
195 if (result != SUCCESS) {
196 IAM_LOGE("EnrollInner failed, fail code : %{public}d", result);
197 return HDF_SUCCESS;
198 }
199 result = callbackObj->OnGetDataV1_1(scheduleId, algoParameter, 0, algoVersion);
200 if (result != SUCCESS) {
201 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
202 CallError(callbackObj, GENERAL_ERROR);
203 // If the enroll fails, delete scheduleId of scheduleMap
204 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
205 IAM_LOGI("delete scheduleId failed");
206 }
207 }
208
209 return HDF_SUCCESS;
210 }
211
Authenticate(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_0> & callbackObj)212 int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
213 const sptr<IExecutorCallbackV1_0> &callbackObj)
214 {
215 IAM_LOGI("start");
216 if (callbackObj == nullptr) {
217 IAM_LOGE("callbackObj is nullptr");
218 return HDF_ERR_INVALID_PARAM;
219 }
220 if (pinHdi_ == nullptr) {
221 IAM_LOGE("pinHdi_ is nullptr");
222 CallError(callbackObj, INVALID_PARAMETERS);
223 return HDF_SUCCESS;
224 }
225 std::vector<uint8_t> algoParameter;
226 int32_t result = AuthenticateInner(scheduleId, templateId, algoParameter, callbackObj);
227 if (result != SUCCESS) {
228 IAM_LOGE("AuthenticateInner failed, fail code : %{public}d", result);
229 return HDF_SUCCESS;
230 }
231 result = callbackObj->OnGetData(scheduleId, algoParameter, 0);
232 if (result != SUCCESS) {
233 IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result);
234 CallError(callbackObj, GENERAL_ERROR);
235 // If the authentication fails, delete scheduleId of scheduleMap
236 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
237 IAM_LOGI("delete scheduleId failed");
238 }
239 }
240
241 return HDF_SUCCESS;
242 }
243
AuthenticateInner(uint64_t scheduleId,uint64_t templateId,std::vector<uint8_t> & algoParameter,const sptr<IExecutorCallbackV1_0> & callbackObj)244 int32_t ExecutorImpl::AuthenticateInner(uint64_t scheduleId, uint64_t templateId, std::vector<uint8_t> &algoParameter,
245 const sptr<IExecutorCallbackV1_0> &callbackObj)
246 {
247 IAM_LOGI("start");
248 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
249 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
250 if (result != SUCCESS) {
251 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
252 CallError(callbackObj, result);
253 return GENERAL_ERROR;
254 }
255 if (infoRet.remainTimes == 0 || infoRet.freezingTime > 0) {
256 IAM_LOGE("Pin authentication is now frozen state");
257 CallError(callbackObj, LOCKED);
258 return GENERAL_ERROR;
259 }
260 result = scheduleMap_.AddScheduleInfo(scheduleId, AUTH_PIN, callbackObj, templateId, algoParameter);
261 if (result != HDF_SUCCESS) {
262 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result);
263 CallError(callbackObj, GENERAL_ERROR);
264 return GENERAL_ERROR;
265 }
266
267 return SUCCESS;
268 }
269
AuthenticateV1_1(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallback> & callbackObj)270 int32_t ExecutorImpl::AuthenticateV1_1(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
271 const sptr<IExecutorCallback> &callbackObj)
272 {
273 IAM_LOGI("start");
274 if (callbackObj == nullptr) {
275 IAM_LOGE("callbackObj is nullptr");
276 return HDF_ERR_INVALID_PARAM;
277 }
278 if (pinHdi_ == nullptr) {
279 IAM_LOGE("pinHdi_ is nullptr");
280 CallError(callbackObj, INVALID_PARAMETERS);
281 return HDF_SUCCESS;
282 }
283 static_cast<void>(extraInfo);
284 std::vector<uint8_t> algoParameter;
285 uint32_t algoVersion = 0;
286 int32_t result = pinHdi_->GetAlgoParameter(templateId, algoParameter, algoVersion);
287 if (result != SUCCESS) {
288 IAM_LOGE("Get algorithm parameter failed, fail code : %{public}d", result);
289 CallError(callbackObj, result);
290 return GENERAL_ERROR;
291 }
292 result = AuthenticateInner(scheduleId, templateId, algoParameter, callbackObj);
293 if (result != SUCCESS) {
294 IAM_LOGE("AuthenticateInner failed, fail code : %{public}d", result);
295 return HDF_SUCCESS;
296 }
297
298 result = callbackObj->OnGetDataV1_1(scheduleId, algoParameter, 0, algoVersion);
299 if (result != SUCCESS) {
300 IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result);
301 CallError(callbackObj, GENERAL_ERROR);
302 // If the authentication fails, delete scheduleId of scheduleMap
303 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
304 IAM_LOGI("delete scheduleId failed");
305 }
306 }
307
308 return HDF_SUCCESS;
309 }
310
AuthPin(uint64_t scheduleId,uint64_t templateId,const std::vector<uint8_t> & data,std::vector<uint8_t> & resultTlv)311 int32_t ExecutorImpl::AuthPin(uint64_t scheduleId, uint64_t templateId,
312 const std::vector<uint8_t> &data, std::vector<uint8_t> &resultTlv)
313 {
314 int32_t result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv);
315 if (result != SUCCESS) {
316 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
317 return result;
318 }
319 threadPool_.AddTask([hdi = pinHdi_, id = templateId]() {
320 if (hdi == nullptr) {
321 return;
322 }
323 hdi->WriteAntiBrute(id);
324 });
325 IAM_LOGI("Auth Pin success");
326 return result;
327 }
328
OnSetData(uint64_t scheduleId,uint64_t authSubType,const std::vector<uint8_t> & data)329 int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data)
330 {
331 IAM_LOGI("start");
332 if (pinHdi_ == nullptr) {
333 IAM_LOGE("pinHdi_ is nullptr");
334 return HDF_FAILURE;
335 }
336 std::vector<uint8_t> resultTlv;
337 int32_t result = GENERAL_ERROR;
338 constexpr uint32_t INVALID_ID = 2;
339 uint32_t commandId = INVALID_ID;
340 sptr<IExecutorCallbackV1_0> callback = nullptr;
341 uint64_t templateId = 0;
342 std::vector<uint8_t> algoParameter(0, 0);
343 if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, algoParameter) != HDF_SUCCESS) {
344 IAM_LOGE("Get ScheduleInfo failed, fail code : %{public}d", result);
345 return HDF_FAILURE;
346 }
347 switch (commandId) {
348 case ENROLL_PIN:
349 result = pinHdi_->EnrollPin(scheduleId, authSubType, algoParameter, data, resultTlv);
350 if (result != SUCCESS) {
351 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
352 }
353 break;
354 case AUTH_PIN:
355 result = AuthPin(scheduleId, templateId, data, resultTlv);
356 if (result != SUCCESS) {
357 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
358 }
359 break;
360 default:
361 IAM_LOGE("Error commandId");
362 }
363
364 if (callback == nullptr || callback->OnResult(result, resultTlv) != SUCCESS) {
365 IAM_LOGE("callbackObj Pin failed");
366 }
367 // Delete scheduleId from the scheduleMap_ when the enroll and authentication are successful
368 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
369 IAM_LOGI("delete scheduleId failed");
370 }
371
372 return HDF_SUCCESS;
373 }
374
Delete(uint64_t templateId)375 int32_t ExecutorImpl::Delete(uint64_t templateId)
376 {
377 IAM_LOGI("start");
378 if (pinHdi_ == nullptr) {
379 IAM_LOGE("pinHdi_ is nullptr");
380 return HDF_FAILURE;
381 }
382 int32_t result = pinHdi_->DeleteTemplate(templateId);
383 if (result != SUCCESS) {
384 IAM_LOGE("Verify templateData failed, fail code : %{public}d", result);
385 return result;
386 }
387
388 return HDF_SUCCESS;
389 }
390
Cancel(uint64_t scheduleId)391 int32_t ExecutorImpl::Cancel(uint64_t scheduleId)
392 {
393 IAM_LOGI("start");
394 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
395 IAM_LOGE("scheduleId is not found");
396 return HDF_FAILURE;
397 }
398 return HDF_SUCCESS;
399 }
400
SendCommand(int32_t commandId,const std::vector<uint8_t> & extraInfo,const sptr<IExecutorCallbackV1_0> & callbackObj)401 int32_t ExecutorImpl::SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
402 const sptr<IExecutorCallbackV1_0> &callbackObj)
403 {
404 IAM_LOGI("Extension interface, temporarily useless");
405 static_cast<void>(commandId);
406 static_cast<void>(extraInfo);
407 static_cast<void>(callbackObj);
408 return HDF_SUCCESS;
409 }
410
AddScheduleInfo(const uint64_t scheduleId,const uint32_t commandId,const sptr<IExecutorCallbackV1_0> callback,const uint64_t templateId,const std::vector<uint8_t> algoParameter)411 uint32_t ExecutorImpl::ScheduleMap::AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId,
412 const sptr<IExecutorCallbackV1_0> callback, const uint64_t templateId, const std::vector<uint8_t> algoParameter)
413 {
414 IAM_LOGI("start");
415 std::lock_guard<std::mutex> guard(mutex_);
416 if (callback == nullptr) {
417 IAM_LOGE("callback is nullptr");
418 return HDF_ERR_INVALID_PARAM;
419 }
420 struct ExecutorImpl::ScheduleMap::ScheduleInfo info {
421 .commandId = commandId,
422 .callback = callback,
423 .templateId = templateId,
424 .algoParameter = algoParameter
425 };
426 scheduleInfo_[scheduleId] = info;
427
428 return HDF_SUCCESS;
429 }
430
GetScheduleInfo(const uint64_t scheduleId,uint32_t & commandId,sptr<IExecutorCallbackV1_0> & callback,uint64_t & templateId,std::vector<uint8_t> & algoParameter)431 uint32_t ExecutorImpl::ScheduleMap::GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId,
432 sptr<IExecutorCallbackV1_0> &callback, uint64_t &templateId, std::vector<uint8_t> &algoParameter)
433 {
434 IAM_LOGI("start");
435 std::lock_guard<std::mutex> guard(mutex_);
436 if (scheduleInfo_.find(scheduleId) == scheduleInfo_.end()) {
437 IAM_LOGE("scheduleId is invalid");
438 return HDF_FAILURE;
439 }
440 commandId = scheduleInfo_[scheduleId].commandId;
441 callback = scheduleInfo_[scheduleId].callback;
442 templateId = scheduleInfo_[scheduleId].templateId;
443 algoParameter = scheduleInfo_[scheduleId].algoParameter;
444
445 return HDF_SUCCESS;
446 }
447
DeleteScheduleId(const uint64_t scheduleId)448 uint32_t ExecutorImpl::ScheduleMap::DeleteScheduleId(const uint64_t scheduleId)
449 {
450 IAM_LOGI("start");
451 std::lock_guard<std::mutex> guard(mutex_);
452 if (scheduleInfo_.erase(scheduleId) == 1) {
453 IAM_LOGI("Delete scheduleId succ");
454 return HDF_SUCCESS;
455 }
456 IAM_LOGE("Delete scheduleId fail");
457 return HDF_FAILURE;
458 }
459
GetProperty(const std::vector<uint64_t> & templateIdList,const std::vector<GetPropertyType> & propertyTypes,Property & property)460 int32_t ExecutorImpl::GetProperty(
461 const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property)
462 {
463 IAM_LOGI("start");
464 if (pinHdi_ == nullptr) {
465 IAM_LOGE("pinHdi_ is nullptr");
466 return HDF_FAILURE;
467 }
468
469 if (templateIdList.size() != 1) {
470 IAM_LOGE("templateIdList size is not 1");
471 return HDF_ERR_INVALID_PARAM;
472 }
473
474 uint64_t templateId = templateIdList[0];
475 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
476 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
477 if (result != SUCCESS) {
478 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
479 return HDF_FAILURE;
480 }
481
482 property.authSubType = infoRet.subType;
483 property.remainAttempts = infoRet.remainTimes;
484 property.lockoutDuration = infoRet.freezingTime;
485 return HDF_SUCCESS;
486 }
487 } // PinAuth
488 } // HDI
489 } // OHOS