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 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 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