1# PIN Authentication
2
3## Overview
4
5### Function
6
7Personal Identification Number (PIN) authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. After a user registers a PIN, the PIN authentication (Pin_auth) module unlocks the device only when the correct PIN is entered. The figure below shows the architecture of PIN authentication.
8
9The Pin_auth driver is developed based on the Hardware Driver Foundation (HDF). The Pin_auth driver model shields hardware differences and provides stable PIN authentication capabilities for the user User_auth framework (User_auth) and PIN authentication system ability (SA). The PIN authentication capabilities include obtaining the PIN authentication executor list, executor information, and anti-brute force information of the specified template, comparing the template ID list of the executor and that of User_auth, enrolling or deleting PINs, and performing PIN authentication.
10
11**Figure 1** PIN authentication architecture
12
13![image](figures/pin_auth_architecture.png "PIN authentication architecture")
14
15### Basic Concepts
16The identity authentication consists of User_auth and basic authentication services (including PIN authentication and facial recognition). It supports basic functions such as setting and deleting user credentials and performing authentication.
17
18- Executor
19
20  The executor collects, processes, stores, and compares data for authentication. Each authentication service provides the executor capabilities, which are scheduled by User_auth to implement basic capabilities.
21
22- Executor security level
23
24  Security level of the runtime environment when an executor provides capabilities.
25
26- Executor role
27
28  - ​    Executor: independently completes the entire process of credential registration and identity authentication. The executor can collect, process, store, and compare data to complete the authentication.
29
30  - ​    Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication.
31
32  - ​    Authenticator: only processes data, obtains the stored credential template, and compares it with the authentication information generated.
33
34- Executor type
35
36  The authentication algorithm varies depending on the authentication mode and device used. Different executor types are defined based on the supported algorithm type or the device in use.
37
38- User_auth public key & executor public key
39
40  To ensure user data security and authentication result accuracy, measures must be taken to protect the integrity of the key information exchanged between User_auth and basic authentication services. Public keys must be exchanged when the executor provided by a basic authentication service interworks with User_auth.
41
42    - The executor uses the User_auth public key to verify scheduling instructions.
43
44    - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor.
45
46
47- PIN authentication credential template
48
49  Authentication credentials are generated and stored by the authentication service when users set authentication credentials. Each template has an ID to index a set of template information files. The template information needs to be compared with the authentication data generated during authentication to complete identity authentication.
50
51- Data verification by the executor
52
53  User_auth manages the mappings between user identities and credential IDs in a unified manner. When connecting to User_auth, the executor obtains the template ID list from User_auth and updates its template ID list based on the template ID list obtained.
54
55- IDL interface
56
57  An Interface Definition Language (IDL) is a language that lets a program or object written in one language communicate with another program written in an unknown language. An IDL compiler generates client stub files and server framework files. This document describes how to use the client and server generated by the IDL interface to implement communication between the Pin_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md).
58
59- IPC
60
61  Inter-Process Communication (IPC) is a mechanism that allows processes to communicate with each other. For details, see [IPC](https://gitee.com/openharmony/communication_ipc/blob/master/README.md).
62
63- HDI
64
65  The hardware device interface (HDI) is located between the basic system service layer and the device driver layer. It provides APIs for abstracting hardware device functions, which shields underlying hardware device differences for system services. For details, see [HDI Specifications](../../design/hdi-design-specifications.md).
66
67### Working Principles
68
69The Pin_auth driver provides basic PIN authentication capabilities for the upper-layer User_auth and Pin_auth service to ensure successful PIN authentication. You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use.
70
71**Figure 2** Pin_auth service and Pin_auth driver APIs
72
73![image](figures/pin_auth_service_and_driver_interaction.png "interaction between the pin_auth service and driver")
74
75### Constraints
76PIN authentication must be implemented in a TEE, and the confidential information, such as PINs and credentials, must be stored in a TEE.
77## Development Guidelines
78
79### When to Use
80The Pin_auth driver provides basic PIN authentication capabilities for the User_auth and Pin_auth service to ensure successful PIN authentication.
81
82### Available APIs
83
84The following table describes the C++ APIs generated from the Interface Definition Language (IDL) interface description. For details about the interface declaration, see the .idl file in **/drivers/interface/pin_auth**.
85**Table 1** describes the HDI APIs for PIN credential enrollment, authentication, and deletion. **Table 2** describes the callbacks used to return the executor operation result to the framework or return the PIN entered by the user.
86
87**Table 1** Available APIs
88
89|    API   |   Description  |
90| ------------------------------- | ------------------------------------------- |
91| GetExecutorInfo(ExecutorInfo& executorInfo)  | Obtains information about an executor.|
92| GetExecutorList(std::vector<sptr<V2_0::IAllInOneExecutor>>& allInOneExecutors, <br>std::vector<sptr<V2_0::IVerifier>>& verifiers, <br>std::vector<sptr<V2_0::ICollector>>& collectors)  | Obtains the V2_0 executor list.|
93| OnRegisterFinish(const std::vector<uint64_t>& templateIdList,<br>const std::vector<uint8_t>& frameworkPublicKey,<br>const std::vector<uint8_t>&  extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully.|
94| Cancel(uint64_t scheduleId) | Cancels an operation.      |
95| SetData(uint64_t scheduleId, uint64_t authSubType, <br>const std::vector<uint8_t> &data, int32_t resultCode) | Called to return the subtype of the PIN enrolled by the user and the anonymization PIN data.      |
96| Enroll(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo, <br>const sptr<IExecutorCallback>& callbackObj) | Enrolls a PIN.     |
97| Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList, const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& callbackObj) | Starts PIN authentication.     |
98| Delete(uint64_t templateId)       | Deletes a PIN template.      |
99| GetProperty(const std::vector<uint64_t>& templateIdList, <br>const std::vector<GetPropertyType>& propertyTypes, Property& property) | Obtains executor property information.|
100
101
102**Table 2** Callbacks
103
104| API                                                      | Description            |
105| ------------------------------------------------------------ | -------------------- |
106| IExecutorCallback::OnResult(int32_t result, const std::vector<uint8_t>& extraInfo) | Called to return the operation result.|
107| IExecutorCallback::OnTip(int32_t tip, const std::vector<uint8_t>& extraInfo) | Called to return the prompt information about the operation process.|
108| IExecutorCallback::OnGetData(const std::vector<uint8_t>& algoParameter, uint64_t authSubType, uint32_t algoVersion, const std::vector<uint8_t>& challenge)| Called to return the PIN information obtained. |
109| IExecutorCallback::OnMessage(int32_t destRole, const std::vector<uint8_t>& msg)| Called to return the interaction information about the operation process. |
110
111### How to Develop
112
113The following uses the RK3568 platform as an example to demonstrate how to develop the Pin_auth driver. <br/>The directory structure is as follows:
114
115```text
116// drivers/peripheral/pin_auth
117├── BUILD.gn     # Build script
118├── bundle.json # Component description file
119├── test         # Test cases
120└── hdi_service # Pin_auth driver implementation
121    ├── BUILD.gn     # Build script
122    ├── adaptor # Implementation of related algorithms
123    ├── common # Implementation of common interfaces
124    ├── database # Database implementation
125    ├── main # Entry for implementing PIN-related functions
126    └── service # Entry for implementing the Pin_auth driver
127        ├── inc # Header files
128        └── src         # Source files
129            ├── all_in_one_impl.cpp             # Implementation of authentication and enrollment APIs for the all-in-one executor
130            ├── verifier_impl.cpp               # Implementation of authentication and enrollment APIs for the verifier
131            ├── collector_impl.cpp              # Implementation of authentication and enrollment APIs for the collector
132            ├── executor_impl_common.cpp        # Utilities
133            ├── pin_auth_interface_driver.cpp # Pin_auth driver entry
134            └── pin_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list
135```
136
137
138The development procedure is as follows:
139
1401. Develop the Pin_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [pin_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/pin_auth_interface_driver.cpp).
141
142   ```c++
143   // Create the PinAuthInterfaceService object by using the custom HdfPinAuthInterfaceHost object, which consists of the IoService object and HDI service.
144   struct HdfPinAuthInterfaceHost {
145       struct IDeviceIoService ioService;
146       OHOS::sptr<OHOS::IRemoteObject> stub;
147   };
148
149   // Enable the IPC service to call the response API.
150   static int32_t PinAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
151   {
152       IAM_LOGI("start");
153       auto *hdfPinAuthInterfaceHost = CONTAINER_OF(client->device->service,
154           struct HdfPinAuthInterfaceHost, ioService);
155
156       OHOS::MessageParcel *dataParcel = nullptr;
157       OHOS::MessageParcel *replyParcel = nullptr;
158       OHOS::MessageOption option;
159
160       if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
161           IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
162           return HDF_ERR_INVALID_PARAM;
163       }
164       if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
165           IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
166           return HDF_ERR_INVALID_PARAM;
167       }
168
169       return hdfPinAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
170   }
171
172   // Initialize the HdfPinAuthInterfaceDriver object.
173   static int HdfPinAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
174   {
175       IAM_LOGI("start");
176       std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi =
177           OHOS::UserIAM::Common::MakeShared<OHOS::UserIAM::PinAuth::PinAuth>();
178       constexpr uint32_t SUCCESS = 0;
179       if (pinHdi == nullptr || pinHdi->Init() != SUCCESS) {
180           IAM_LOGE("Pin hal init failed");
181           return HDF_FAILURE;
182       }
183       return HDF_SUCCESS;
184   }
185
186   // Bind the service provided by the Pin_auth driver to the HDF.
187   static int HdfPinAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
188   {
189       IAM_LOGI("start");
190       auto *hdfPinAuthInterfaceHost = new (std::nothrow) HdfPinAuthInterfaceHost;
191       if (hdfPinAuthInterfaceHost == nullptr) {
192           IAM_LOGE("%{public}s: failed to create HdfPinAuthInterfaceHost object", __func__);
193           return HDF_FAILURE;
194       }
195
196       hdfPinAuthInterfaceHost->ioService.Dispatch = PinAuthInterfaceDriverDispatch;
197       hdfPinAuthInterfaceHost->ioService.Open = NULL;
198       hdfPinAuthInterfaceHost->ioService.Release = NULL;
199
200       auto serviceImpl = IPinAuthInterface::Get(true);
201       if (serviceImpl == nullptr) {
202           IAM_LOGE("%{public}s: failed to get of implement service", __func__);
203           return HDF_FAILURE;
204       }
205
206       hdfPinAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
207           IPinAuthInterface::GetDescriptor());
208       if (hdfPinAuthInterfaceHost->stub == nullptr) {
209           IAM_LOGE("%{public}s: failed to get stub object", __func__);
210           return HDF_FAILURE;
211       }
212
213       deviceObject->service = &hdfPinAuthInterfaceHost->ioService;
214       IAM_LOGI("success");
215       return HDF_SUCCESS;
216   }
217
218   // Release resources of the Pin_auth driver.
219   static void HdfPinAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
220   {
221       IAM_LOGI("start");
222       auto *hdfPinAuthInterfaceHost = CONTAINER_OF(deviceObject->service,
223           struct HdfPinAuthInterfaceHost, ioService);
224       delete hdfPinAuthInterfaceHost;
225       IAM_LOGI("success");
226   }
227
228   static struct HdfDriverEntry g_pinAuthInterfaceDriverEntry = {
229       .moduleVersion = 1,
230       .moduleName = "pinauth_interface_service",
231       .Bind = HdfPinAuthInterfaceDriverBind,
232       .Init = HdfPinAuthInterfaceDriverInit,
233       .Release = HdfPinAuthInterfaceDriverRelease,
234   };
235
236   // Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls the Bind() function and then the Init() function. If the Init() function fails to be called, the HDF will call Release() to release driver resources and exit the driver model.
237   HDF_INIT(g_pinauthinterfaceDriverEntry);
238   ```
239
240
241
2422. Obtain the executor list. For details about the code, see [pin_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/pin_auth_interface_service.cpp).
243
244   ```c++
245   // Executor implementation class
246    class ExecutorImpl : public HdiIExecutor, public NoCopyable {
247    public:
248        explicit ExecutorImpl(std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi);
249        ~ExecutorImpl() override;
250
251        int32_t GetExecutorInfo(HdiExecutorInfo &info) override;
252        int32_t OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
253            const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) override;
254        int32_t Cancel(uint64_t scheduleId) override;
255        int32_t SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t>& msg) override;
256        int32_t SetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data,
257            int32_t resultCode) override;
258        int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
259            const sptr<HdiIExecutorCallback> &callbackObj) override;
260        int32_t Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList,
261            const std::vector<uint8_t> &extraInfo, const sptr<HdiIExecutorCallback> &callbackObj) override;
262        int32_t Delete(uint64_t templateId) override;
263        int32_t GetProperty(const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes,
264            HdiProperty &property) override;
265
266    private:
267        class ScheduleMap {
268        public:
269            uint32_t AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId,
270                const sptr<HdiIExecutorCallback> callback, const uint64_t templateId,
271                const std::vector<uint8_t> algoParameter);
272            uint32_t GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId, sptr<HdiIExecutorCallback> &callback,
273                uint64_t &templateId, std::vector<uint8_t> &algoParameter);
274            uint32_t DeleteScheduleId(const uint64_t scheduleId);
275
276        private:
277            struct ScheduleInfo {
278                uint32_t commandId;
279                sptr<HdiIExecutorCallback> callback;
280                uint64_t templateId;
281                std::vector<uint8_t> algoParameter;
282            };
283
284            std::mutex mutex_;
285            std::map<uint64_t, struct ScheduleInfo> scheduleInfo_;
286        };
287
288    private:
289        void CallError(const sptr<HdiIExecutorCallback> &callbackObj, uint32_t errorCode);
290        int32_t AuthPin(uint64_t scheduleId, uint64_t templateId,
291            const std::vector<uint8_t> &data, std::vector<uint8_t> &resultTlv);
292        int32_t AuthenticateInner(uint64_t scheduleId, uint64_t templateId, std::vector<uint8_t> &algoParameter,
293            const sptr<HdiIExecutorCallback> &callbackObj);
294        int32_t EnrollInner(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
295            const sptr<HdiIExecutorCallback> &callbackObj, std::vector<uint8_t> &algoParameter, uint32_t &algoVersion);
296        void ReportAuthenticate(uint64_t scheduleId, uint64_t templateId, PinAuthResultBigData pinAuthResultBigData);
297        std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi_;
298        ScheduleMap scheduleMap_;
299        OHOS::ThreadPool threadPool_;
300    };
301
302   // Obtain the executor list and create an executor (example only).
303   int32_t PinAuthInterfaceService::GetExecutorList(std::vector<sptr<HdiIExecutor>>& allInOneExecutors,
304        std::vector<sptr<HdiIVerifier>>& verifiers, std::vector<sptr<HdiICollector>>& collectors)
305   {
306       IAM_LOGI("start");
307       static_cast<void>(verifiers);
308       static_cast<void>(collectors);
309       std::shared_ptr<OHOS::UserIam::PinAuth::PinAuth> pinHdi =
310           OHOS::UserIam::Common::MakeShared<OHOS::UserIam::PinAuth::PinAuth>();
311       if (pinHdi == nullptr) {
312           IAM_LOGE("Generate pinHdi failed");
313           return HDF_FAILURE;
314       }
315       sptr<HdiIExecutor> executor = new (std::nothrow) ExecutorImpl(pinHdi);
316       if (executor == nullptr) {
317           IAM_LOGE("Generate executor failed");
318           return HDF_FAILURE;
319       }
320       allInOneExecutors.push_back(executor);
321       IAM_LOGI("end");
322       return HDF_SUCCESS;
323   }
324   ```
325
326
327
3283. Implement each function of the executor. For details about the code, see [all_in_one_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/all_in_one_impl.cpp).
329
330   ```c++
331   // Obtain executor information (example only).
332   int32_t ExecutorImpl::GetExecutorInfo(HdiExecutorInfo &info)
333   {
334       IAM_LOGI("start");
335       if (pinHdi_ == nullptr) {
336           IAM_LOGE("pinHdi_ is nullptr");
337           return HDF_FAILURE;
338       }
339       constexpr unsigned short SENSOR_ID = 1;
340       info.sensorId = SENSOR_ID;
341       info.executorMatcher = EXECUTOR_TYPE;
342       info.executorRole = HdiExecutorRole::ALL_IN_ONE;
343       info.authType = HdiAuthType::PIN;
344       uint32_t eslRet = 0;
345       int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet);
346       if (result != SUCCESS) {
347           IAM_LOGE("Get ExecutorInfo failed, fail code : %{public}d", result);
348           return result;
349       }
350       info.esl = static_cast<HdiExecutorSecureLevel>(eslRet);
351
352       return HDF_SUCCESS;
353   }
354
355   // After the executor is successfully registered, obtain the public key and template ID list from User_auth and save the public key obtained. The executor compares its template ID list with the template ID list obtained and updates its template ID list.
356   int32_t ExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
357       const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
358   {
359       IAM_LOGI("start");
360       static_cast<void>(frameworkPublicKey);
361       static_cast<void>(extraInfo);
362       if (pinHdi_ == nullptr) {
363           IAM_LOGE("pinHdi_ is nullptr");
364           return HDF_FAILURE;
365       }
366       int32_t result = pinHdi_->VerifyTemplateData(templateIdList);
367       if (result != SUCCESS) {
368           IAM_LOGE("Verify templateData failed");
369           return result;
370       }
371
372       return HDF_SUCCESS;
373   }
374
375   // Enroll the PIN.
376   int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
377       const sptr<IExecutorCallback> &callbackObj)
378   {
379       IAM_LOGI("start");
380       if (callbackObj == nullptr) {
381           IAM_LOGE("callbackObj is nullptr");
382           return HDF_ERR_INVALID_PARAM;
383       }
384       if (pinHdi_ == nullptr) {
385           IAM_LOGE("pinHdi_ is nullptr");
386           CallError(callbackObj, INVALID_PARAMETERS);
387           return HDF_SUCCESS;
388       }
389       std::vector<uint8_t> algoParameter;
390       uint32_t algoVersion = 0;
391       int32_t result = EnrollInner(scheduleId, extraInfo, callbackObj, algoParameter, algoVersion);
392       if (result != SUCCESS) {
393           IAM_LOGE("EnrollInner failed, fail code : %{public}d", result);
394           return HDF_SUCCESS;
395       }
396
397       std::vector<uint8_t> challenge;
398       result = callbackObj->OnGetData(algoParameter, 0, algoVersion, challenge);
399       if (result != SUCCESS) {
400           IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
401           CallError(callbackObj, GENERAL_ERROR);
402           // If the enrollment fails, delete scheduleId of scheduleMap.
403           if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
404               IAM_LOGI("delete scheduleId failed");
405           }
406       }
407
408       return HDF_SUCCESS;
409   }
410
411   // Implement the callback for returning data.
412   int32_t ExecutorImpl::SetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data,
413       int32_t resultCode)
414   {
415       IAM_LOGI("start");
416       if (pinHdi_ == nullptr) {
417           IAM_LOGE("pinHdi_ is nullptr");
418           return HDF_FAILURE;
419       }
420       std::vector<uint8_t> resultTlv;
421       int32_t result = GENERAL_ERROR;
422       constexpr uint32_t INVALID_ID = 2;
423       uint32_t commandId = INVALID_ID;
424       sptr<HdiIExecutorCallback> callback = nullptr;
425       uint64_t templateId = 0;
426       std::vector<uint8_t> algoParameter(0, 0);
427       if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, algoParameter) != HDF_SUCCESS) {
428           IAM_LOGE("Get ScheduleInfo failed, fail code : %{public}d", result);
429           return HDF_FAILURE;
430       }
431       if (resultCode != SUCCESS && callback != nullptr) {
432           IAM_LOGE("SetData failed, resultCode is %{public}d", resultCode);
433           CallError(callback, resultCode);
434           return resultCode;
435       }
436       switch (commandId) {
437           case ENROLL_PIN:
438               result = pinHdi_->EnrollPin(scheduleId, authSubType, algoParameter, data, resultTlv);
439               if (result != SUCCESS) {
440                   IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result);
441               }
442               break;
443           case AUTH_PIN:
444               result = AuthPin(scheduleId, templateId, data, resultTlv);
445               if (result != SUCCESS) {
446                   IAM_LOGE("Auth Pin failed, fail code : %{public}d", result);
447               }
448               break;
449           default:
450               IAM_LOGE("Error commandId");
451       }
452
453       if (callback == nullptr || callback->OnResult(result, resultTlv) != SUCCESS) {
454           IAM_LOGE("callbackObj Pin failed");
455       }
456       // Delete scheduleId from scheduleMap when the enrollment and authentication are successful.
457       if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
458           IAM_LOGI("delete scheduleId failed");
459       }
460
461       return HDF_SUCCESS;
462   }
463
464   // Perform PIN authentication.
465   int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList,
466       const std::vector<uint8_t> &extraInfo, const sptr<HdiIExecutorCallback> &callbackObj)
467   {
468       IAM_LOGI("start");
469       if (callbackObj == nullptr) {
470           IAM_LOGE("callbackObj is nullptr");
471           return HDF_ERR_INVALID_PARAM;
472       }
473       if (pinHdi_ == nullptr || templateIdList.size() != 1) {
474           IAM_LOGE("pinHdi_ is nullptr or templateIdList size not 1");
475           CallError(callbackObj, INVALID_PARAMETERS);
476           return HDF_SUCCESS;
477       }
478       static_cast<void>(extraInfo);
479       std::vector<uint8_t> algoParameter;
480       uint32_t algoVersion = 0;
481       uint64_t templateId = templateIdList[0];
482       int32_t result = pinHdi_->GetAlgoParameter(templateId, algoParameter, algoVersion);
483       if (result != SUCCESS) {
484           IAM_LOGE("Get algorithm parameter failed, fail code : %{public}d", result);
485           CallError(callbackObj, result);
486           return GENERAL_ERROR;
487       }
488       result = AuthenticateInner(scheduleId, templateId, algoParameter, callbackObj);
489       if (result != SUCCESS) {
490           IAM_LOGE("AuthenticateInner failed, fail code : %{public}d", result);
491           return HDF_SUCCESS;
492       }
493
494       std::vector<uint8_t> challenge;
495       result = callbackObj->OnGetData(algoParameter, 0, algoVersion, challenge);
496       if (result != SUCCESS) {
497           IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result);
498           CallError(callbackObj, GENERAL_ERROR);
499           // If the authentication fails, delete scheduleId of scheduleMap.
500           if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
501               IAM_LOGI("delete scheduleId failed");
502           }
503       }
504
505       return HDF_SUCCESS;
506   }
507
508   // Delete the PIN template.
509   int32_t ExecutorImpl::Delete(uint64_t templateId)
510   {
511       IAM_LOGI("start");
512       if (pinHdi_ == nullptr) {
513           IAM_LOGE("pinHdi_ is nullptr");
514           return HDF_FAILURE;
515       }
516       int32_t result = pinHdi_->DeleteTemplate(templateId);
517       if (result != SUCCESS) {
518           IAM_LOGE("Verify templateData failed, fail code : %{public}d", result);
519           return result;
520       }
521
522       return HDF_SUCCESS;
523   }
524
525   // Cancel the operation based on the specified scheduleId.
526   int32_t ExecutorImpl::Cancel(uint64_t scheduleId)
527   {
528       IAM_LOGI("start");
529       if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
530           IAM_LOGE("scheduleId is not found");
531           return HDF_FAILURE;
532       }
533       return HDF_SUCCESS;
534   }
535
536   // Obtain the executor property information.
537   int32_t ExecutorImpl::GetProperty(
538       const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property)
539   {
540       IAM_LOGI("start");
541       if (pinHdi_ == nullptr) {
542           IAM_LOGE("pinHdi_ is nullptr");
543           return HDF_FAILURE;
544       }
545
546       if (templateIdList.size() != 1) {
547           IAM_LOGE("templateIdList size is not 1");
548           return HDF_FAILURE;
549       }
550
551       uint64_t templateId = templateIdList[0];
552       OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
553       int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
554       if (result != SUCCESS) {
555           IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result);
556           return HDF_FAILURE;
557       }
558
559       property.authSubType = infoRet.subType;
560       property.remainAttempts = infoRet.remainTimes;
561       property.lockoutDuration = infoRet.freezingTime;
562       return HDF_SUCCESS;
563   }
564   ```
565
566
567### Verification
568Verify whether PIN authentication can be successfully performed on the RK3568 platform as follows:
569
5701.  Touch **Settings** > **Biometrics & passwords** > **Password**, and enter your password.
5712.  Press the power button to lock the screen. Press the power button again and enter the password. The screen is unlocked if a correct password is entered.
5723.  Touch **Settings** > **Biometrics & passwords** > **Password**, and verify **Disable lock screen password** and **Change lock screen password**.
5734.  After step 1 is complete, enter incorrect passwords for a specified number of times to check whether the anti-brute force cracking capability is normal. For example, if you enter incorrect passwords for five consecutive times, the device will be frozen for 60s.
574