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