• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 Trusted Execution Environment (TEE), and the confidential information, such as PINs and credentials, must be encrypted and 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| GetExecutorList(std::vector\<sptr\<V1_0::IExecutor>>& executorList)  | Obtains the executor list (version V1_0).|
92| GetExecutorListV1_1(std::vector\<sptr\<V1_1::IExecutor>>& executorList)      | Obtains the executor list (version V1_1).                        |
93| GetTemplateInfo(uint64_t templateId, TemplateInfo& info)  | Obtains information about a template.  |
94| 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.|
95| OnSetData(uint64_t scheduleId, uint64_t authSubType, <br>const std::vector\<uint8_t> &data) | 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, uint64_t templateId, const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Starts PIN authentication.     |
98| Delete(uint64_t templateId)       | Deletes a PIN template.      |
99| Cancel(uint64_t scheduleId)     | Cancels an operation. |
100| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br>const sptr\<IExecutorCallback>& callbackObj) | Reserved. |
101| GetProperty(const std::vector\<uint64_t>& templateIdList,<br>const std::vector\<GetPropertyType>& propertyTypes, Property& property) | Obtains executor property information.|
102
103
104**Table 2** Callbacks
105
106| API                                                      | Description            |
107| ------------------------------------------------------------ | -------------------- |
108| IExecutorCallback::OnResult(int32_t code, const std::vector\<uint8_t>& extraInfo) | Called to return the operation result.|
109| IExecutorCallback::OnGetData(uint64_t scheduleId, const std::vector\<uint8_t>& salt,<br> uint64_t authSubType)| Called to return the PIN information obtained. |
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            ├── executor_impl.cpp                # Implementation of authentication and enrollment APIs
130            ├── pin_auth_interface_driver.cpp    # Pin_auth driver entry
131            └── pin_auth_interface_service.cpp   # Implementation of the APIs for obtaining the executor list
132```
133
134The development procedure is as follows:
135
1361. 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).
137
138   ```c++
139   // Create the PinAuthInterfaceService object by using the custom HdfPinAuthInterfaceHost object, which consists of the IoService object and HDI service.
140   struct HdfPinAuthInterfaceHost {
141       struct IDeviceIoService ioService;
142       OHOS::sptr<OHOS::IRemoteObject> stub;
143   };
144
145   // Enable the IPC service to call the response API.
146   static int32_t PinAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,  struct HdfSBuf *reply)
147   {
148       IAM_LOGI("start");
149       auto *hdfPinAuthInterfaceHost = CONTAINER_OF(client->device->service,
150           struct HdfPinAuthInterfaceHost, ioService);
151
152       OHOS::MessageParcel *dataParcel = nullptr;
153       OHOS::MessageParcel *replyParcel = nullptr;
154       OHOS::MessageOption option;
155
156       if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) {
157           IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__);
158           return HDF_ERR_INVALID_PARAM;
159       }
160       if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) {
161           IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__);
162           return HDF_ERR_INVALID_PARAM;
163       }
164
165       return hdfPinAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option);
166   }
167
168   // Initialize the HdfPinAuthInterfaceDriver object.
169   static int HdfPinAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject)
170   {
171       IAM_LOGI("start");
172       std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi =
173           OHOS::UserIAM::Common::MakeShared<OHOS::UserIAM::PinAuth::PinAuth>();
174       constexpr uint32_t SUCCESS = 0;
175       if (pinHdi == nullptr || pinHdi->Init() != SUCCESS) {
176           IAM_LOGE("PIN HAL initialization failed");
177           return HDF_FAILURE;
178       }
179       return HDF_SUCCESS;
180   }
181
182   // Bind the service provided by the Pin_auth driver to the HDF.
183   static int HdfPinAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
184   {
185       IAM_LOGI("start");
186       auto *hdfPinAuthInterfaceHost = new (std::nothrow) HdfPinAuthInterfaceHost;
187       if (hdfPinAuthInterfaceHost == nullptr) {
188           IAM_LOGE("%{public}s: Failed to create HdfPinAuthInterfaceHost object", __func__);
189           return HDF_FAILURE;
190       }
191
192       hdfPinAuthInterfaceHost->ioService.Dispatch = PinAuthInterfaceDriverDispatch;
193       hdfPinAuthInterfaceHost->ioService.Open = NULL;
194       hdfPinAuthInterfaceHost->ioService.Release = NULL;
195
196       auto serviceImpl = IPinAuthInterface::Get(true);
197       if (serviceImpl == nullptr) {
198           IAM_LOGE("%{public}s: Failed to implement the service", __func__);
199           return HDF_FAILURE;
200       }
201
202       hdfPinAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl,
203           IPinAuthInterface::GetDescriptor());
204       if (hdfPinAuthInterfaceHost->stub == nullptr) {
205           IAM_LOGE("%{public}s: Failed to get stub object", __func__);
206           return HDF_FAILURE;
207       }
208
209       deviceObject->service = &hdfPinAuthInterfaceHost->ioService;
210       IAM_LOGI("success");
211       return HDF_SUCCESS;
212   }
213
214   // Release resources of the Pin_auth driver.
215   static void HdfPinAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject)
216   {
217       IAM_LOGI("start");
218       auto *hdfPinAuthInterfaceHost = CONTAINER_OF(deviceObject->service,
219           struct HdfPinAuthInterfaceHost, ioService);
220       delete hdfPinAuthInterfaceHost;
221       IAM_LOGI("success");
222   }
223
224   static struct HdfDriverEntry g_pinAuthInterfaceDriverEntry = {
225       .moduleVersion = 1,
226       .moduleName = "pinauth_interface_service",
227       .Bind = HdfPinAuthInterfaceDriverBind,
228       .Init = HdfPinAuthInterfaceDriverInit,
229       .Release = HdfPinAuthInterfaceDriverRelease,
230   };
231
232   // 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.
233   HDF_INIT(g_pinauthinterfaceDriverEntry);
234   ```
235
236
237
2381. 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).
239
240   ```c++
241   // Executor implementation class
242   class ExecutorImpl : public V1_1::IExecutor, public NoCopyable {
243   public:
244       explicit ExecutorImpl(std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi);
245       virtual ~ExecutorImpl() {}
246       int32_t GetExecutorInfo(ExecutorInfo &info) override;
247       int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo &info) override;
248       int32_t OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
249           const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) override;
250       int32_t OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data) override;
251       int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
252           const sptr<IExecutorCallback> &callbackObj) override;
253       int32_t Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
254           const sptr<IExecutorCallback> &callbackObj) override;
255       int32_t Delete(uint64_t templateId) override;
256       int32_t Cancel(uint64_t scheduleId) override;
257       int32_t SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
258           const sptr<IExecutorCallback> &callbackObj) override;
259       int32_t GetProperty(const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes,
260           Property &property) override;
261
262   private:
263       class ScheduleMap {
264       public:
265           uint32_t AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId,
266               const sptr<IExecutorCallback> callback, const uint64_t templateId, const std::vector<uint8_t> salt);
267           uint32_t GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId, sptr<IExecutorCallback> &callback,
268               uint64_t &templateId, std::vector<uint8_t> &salt);
269           uint32_t DeleteScheduleId(const uint64_t scheduleId);
270
271       private:
272           struct ScheduleInfo {
273               uint32_t commandId;
274               sptr<IExecutorCallback> callback;
275               uint64_t templateId;
276               std::vector<uint8_t> salt;
277           };
278
279           std::mutex mutex_;
280           std::map<uint64_t, struct ScheduleInfo> scheduleInfo_;
281       };
282
283   private:
284       uint32_t NewSalt(std::vector<uint8_t> &salt);
285       void CallError(const sptr<IExecutorCallback> &callbackObj, const uint32_t errorCode);
286       std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi_;
287       ScheduleMap scheduleMap_;
288   };
289
290   // Obtain the executor list (using the method of version V1_1) and create an executor (example only).
291   int32_t PinAuthInterfaceService::GetExecutorListV1_1(std::vector<sptr<V1_1::IExecutor>> &executorList)
292   {
293       IAM_LOGI("start");
294       std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi =
295           OHOS::UserIAM::Common::MakeShared<OHOS::UserIAM::PinAuth::PinAuth>();
296       if (pinHdi == nullptr) {
297           IAM_LOGE("Failed to generate pinHdi");
298           return HDF_FAILURE;
299       }
300       sptr<IExecutor> executor = new (std::nothrow) ExecutorImpl(pinHdi);
301       if (executor == nullptr) {
302           IAM_LOGE("Failed to generate executor");
303           return HDF_FAILURE;
304       }
305       executorList.push_back(executor);
306       IAM_LOGI("end");
307       return HDF_SUCCESS;
308   }
309
310   // Obtain the executor list. The method of V1_0 is called to invoke the API of V1_1 through parameter conversion.
311   int32_t PinAuthInterfaceService::GetExecutorList(std::vector<sptr<V1_0::IExecutor>> &executorList)
312   {
313       std::vector<sptr<V1_1::IExecutor>> executorListV1_1;
314       int32_t result = GetExecutorListV1_1(executorListV1_1);
315       for (auto &executor : executorListV1_1) {
316           executorList.push_back(executor);
317       }
318       return result;
319   }
320   ```
321
322
323
3241. Implement each function of the executor. For details about the code, see [executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/executor_impl.cpp).
325
326   ```c++
327   // Obtain executor information (example only).
328   int32_t ExecutorImpl::GetExecutorInfo(ExecutorInfo &info)
329   {
330       IAM_LOGI("start");
331       constexpr unsigned short SENSOR_ID = 1;
332       info.sensorId = SENSOR_ID;
333       info.executorType = EXECUTOR_TYPE;
334       info.executorRole = ExecutorRole::ALL_IN_ONE;
335       info.authType = AuthType::PIN;
336       if (pinHdi_ == nullptr) {
337           IAM_LOGE("pinHdi_ is nullptr");
338           return HDF_FAILURE;
339       }
340       uint32_t eslRet = 0;
341       int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet);
342       if (result != SUCCESS) {
343           IAM_LOGE("Failed to get ExecutorInfo, error code : %{public}d", result);
344           return result;
345       }
346       info.esl = static_cast<ExecutorSecureLevel>(eslRet);
347
348       return HDF_SUCCESS;
349   }
350
351   // Obtain template information based on templateId.
352   int32_t ExecutorImpl::GetTemplateInfo(uint64_t templateId, TemplateInfo &info)
353   {
354       IAM_LOGI("start");
355       if (pinHdi_ == nullptr) {
356           IAM_LOGE("pinHdi_ is nullptr");
357           return HDF_FAILURE;
358       }
359       OHOS::UserIAM::PinAuth::PinCredentialInfo infoRet = {};
360       int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
361       if (result != SUCCESS) {
362           IAM_LOGE("Failed to get TemplateInfo, error code : %{public}d", result);
363           return result;
364       }
365       /* subType is stored in extraInfo. */
366       info.extraInfo.resize(infoRet.subType);
367       if (memcpy_s(&(info.extraInfo[0]), sizeof(infoRet.subType), &(infoRet.subType), sizeof(infoRet.subType)) != EOK) {
368           IAM_LOGE("Failed to copy subType to extraInfo.");
369           return HDF_FAILURE;
370       }
371
372       info.executorType = EXECUTOR_TYPE;
373       info.remainAttempts = infoRet.remainTimes;
374       info.lockoutDuration = infoRet.freezingTime;
375
376       return HDF_SUCCESS;
377   }
378
379   // 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.
380   int32_t ExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList,
381       const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
382   {
383       IAM_LOGI("start");
384       static_cast<void>(frameworkPublicKey);
385       static_cast<void>(extraInfo);
386       if (pinHdi_ == nullptr) {
387           IAM_LOGE("pinHdi_ is nullptr");
388           return HDF_FAILURE;
389       }
390       int32_t result = pinHdi_->VerifyTemplateData(templateIdList);
391       if (result != SUCCESS) {
392           IAM_LOGE("Failed to verify templateData");
393           return result;
394       }
395
396       return HDF_SUCCESS;
397   }
398
399   // Enroll the PIN.
400   int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo,
401       const sptr<IExecutorCallback> &callbackObj)
402   {
403       IAM_LOGI("start");
404       if (callbackObj == nullptr) {
405           IAM_LOGE("callbackObj is nullptr");
406           return HDF_FAILURE;
407       }
408       static_cast<void>(extraInfo);
409       std::vector<uint8_t> salt;
410       if (NewSalt(salt) != HDF_SUCCESS) {
411           IAM_LOGE("new salt failed");
412           CallError(callbackObj, HDF_FAILURE);
413           return HDF_FAILURE;
414       }
415       int32_t result = scheduleMap_.AddScheduleInfo(scheduleId, ENROLL_PIN, callbackObj, 0, salt);
416       if (result != HDF_SUCCESS) {
417           IAM_LOGE("Failed to add scheduleInfo, error code : %{public}d", result);
418           CallError(callbackObj, HDF_FAILURE);
419           return result;
420       }
421       result = callbackObj->OnGetData(scheduleId, salt, 0);
422       if (result != SUCCESS) {
423           IAM_LOGE("Failed to enroll PIN , error code : %{public}d", result);
424           // If the enrollment fails, delete scheduleId of scheduleMap.
425           if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
426               IAM_LOGI("Failed to delete scheduleId");
427           }
428           return result;
429       }
430
431       return HDF_SUCCESS;
432   }
433
434   // Implement the callback for returning data.
435   int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data)
436   {
437       IAM_LOGI("start");
438       if (pinHdi_ == nullptr) {
439           IAM_LOGE("pinHdi_ is nullptr");
440           return HDF_FAILURE;
441       }
442       std::vector<uint8_t> resultTlv;
443       int32_t result = SUCCESS;
444       constexpr uint32_t INVALID_ID = 2;
445       uint32_t commandId = INVALID_ID;
446       sptr<IExecutorCallback> callback = nullptr;
447       uint64_t templateId = 0;
448       std::vector<uint8_t> salt(0, 0);
449       if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, salt) != HDF_SUCCESS) {
450           IAM_LOGE("Failed to get ScheduleInfo, error code : %{public}d", result);
451           return HDF_FAILURE;
452       }
453       switch (commandId) {
454           case ENROLL_PIN:
455               result = pinHdi_->EnrollPin(scheduleId, authSubType, salt, data, resultTlv);
456               if (result != SUCCESS) {
457                   IAM_LOGE("Failed to enroll PIN, error code : %{public}d", result);
458               }
459               break;
460           case AUTH_PIN:
461               result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv);
462               if (result != SUCCESS) {
463                   IAM_LOGE("Failed to authenticate PIN, error code : %{public}d", result);
464               }
465               break;
466           default:
467               IAM_LOGE("Error commandId");
468       }
469
470       if (callback->OnResult(result, resultTlv) != SUCCESS) {
471           IAM_LOGE("callbackObj Pin failed");
472       }
473       // Delete scheduleId from scheduleMap when the enrollment and authentication are successful.
474       if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
475           IAM_LOGI("Failed to delete scheduleId");
476       }
477
478       return HDF_SUCCESS;
479   }
480   // Perform PIN authentication.
481   int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo,
482       const sptr<IExecutorCallback> &callbackObj)
483   {
484       IAM_LOGI("start");
485       if (callbackObj == nullptr) {
486           IAM_LOGE("callbackObj is nullptr");
487           return HDF_FAILURE;
488       }
489       if (pinHdi_ == nullptr) {
490           IAM_LOGE("pinHdi_ is nullptr");
491           CallError(callbackObj, HDF_FAILURE);
492           return HDF_FAILURE;
493       }
494       static_cast<void>(extraInfo);
495       std::vector<uint8_t> salt;
496       int32_t result = pinHdi_->GetSalt(templateId, salt);
497       if (result  != SUCCESS) {
498           IAM_LOGE("Failed to get salt, error code : %{public}d", result);
499           CallError(callbackObj, HDF_FAILURE);
500           return result;
501       }
502       result = scheduleMap_.AddScheduleInfo(scheduleId, AUTH_PIN, callbackObj, templateId, salt);
503       if (result != HDF_SUCCESS) {
504           IAM_LOGE("Failed to add scheduleInfo, error code : %{public}d", result);
505           CallError(callbackObj, HDF_FAILURE);
506           return result;
507       }
508       result = callbackObj->OnGetData(scheduleId, salt, 0);
509       if (result != SUCCESS) {
510           IAM_LOGE("Failed to authenticate PIN, error code : %{public}d", result);
511           // If the authentication fails, delete scheduleId of scheduleMap.
512           if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
513               IAM_LOGI("Failed to delete scheduleId");
514           }
515           return result;
516       }
517
518       return HDF_SUCCESS;
519   }
520
521   // Delete the PIN template.
522   int32_t ExecutorImpl::Delete(uint64_t templateId)
523   {
524       IAM_LOGI("start");
525       if (pinHdi_ == nullptr) {
526           IAM_LOGE("pinHdi_ is nullptr");
527           return HDF_FAILURE;
528       }
529       int32_t result = pinHdi_->DeleteTemplate(templateId);
530       if (result != SUCCESS) {
531           IAM_LOGE("Failed to verify templateData, error code : %{public}d", result);
532           return result;
533       }
534
535       return HDF_SUCCESS;
536   }
537
538   // Cancel the operation based on the specified scheduleId.
539   int32_t ExecutorImpl::Cancel(uint64_t scheduleId)
540   {
541       IAM_LOGI("start");
542       if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) {
543           IAM_LOGE("scheduleId is not found");
544           return HDF_FAILURE;
545       }
546       return HDF_SUCCESS;
547   }
548
549   // API reserved.
550   int32_t ExecutorImpl::SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo,
551       const sptr<IExecutorCallback> &callbackObj)
552   {
553       IAM_LOGI("Extension interface, temporarily useless");
554       static_cast<void>(commandId);
555       static_cast<void>(extraInfo);
556       static_cast<void>(callbackObj);
557       return HDF_SUCCESS;
558   }
559
560   // Obtain the executor property information.
561   int32_t ExecutorImpl::GetProperty(
562       const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property)
563   {
564       IAM_LOGI("start");
565       if (pinHdi_ == nullptr) {
566           IAM_LOGE("pinHdi_ is nullptr");
567           return HDF_FAILURE;
568       }
569
570       if (templateIdList.size() != 1) {
571           IAM_LOGE("templateIdList size is not 1");
572           return HDF_FAILURE;
573       }
574
575       uint64_t templateId = templateIdList[0];
576       OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {};
577       int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet);
578       if (result != SUCCESS) {
579           IAM_LOGE("Failed to get TemplateInfo, error code : %{public}d", result);
580           return HDF_FAILURE;
581       }
582
583       property.authSubType = infoRet.subType;
584       property.remainAttempts = infoRet.remainTimes;
585       property.lockoutDuration = infoRet.freezingTime;
586       return HDF_SUCCESS;
587   }
588   ```
589
590
591### Verification
592Verify whether PIN authentication can be successfully performed on the RK3568 platform as follows:
593
5941. Set a PIN.
595
596    Touch **Settings** > **Biometrics & passwords** > **Password**, and enter your password.
597
5982. Verify PIN authentication.
599
600    1) Press the power button to lock the screen.
601
602    2) Press the power button again, and enter an incorrect password for five consecutive times. The device will be locked for 60 seconds.
603
604    3) Enter the correct password. The screen is unlocked.
605
6063. Disable PIN authentication.
607
608    1) Touch **Settings** > **Biometrics & passwords** > **Password**.
609
610    2) Touch **Disable lock screen password** and **Disable**.
611
6124. Change the PIN.
613
614    1) Touch **Settings** > **Biometrics & passwords** > **Password**.
615
616    2) Touch **Change screen lock password** and set the new password.
617