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