1# Fingerprint Authentication 2 3## Overview 4 5### Function 6 7Fingerprint authentication is indispensable in identity authentication scenarios, such as device unlocking, payment, and app logins. The fingerprint authentication (Fingerprint_auth) module provides fingerprint authentication for a device after a user enrolls a fingerprint. The figure below shows the fingerprint authentication architecture. 8 9The Fingerprint_auth driver is developed based on the Hardware Driver Foundation (HDF). It shields hardware differences and provides stable fingerprint authentication capabilities for the upper-layer user authentication (User_auth) framework and Fingerprint_auth service. It provides APIs for obtaining the fingerprint authentication executor list, executor information, and template information by template ID, comparing fingerprint template information of the executor and that of User_auth, enrolling or deleting fingerprints, and performing fingerprint authentication. 10 11**Figure 1** Fingerprint authentication architecture 12 13 14 15### Basic Concepts 16 17The identity authentication consists of the User_auth framework and basic authentication services. It supports basic functions such as setting and deleting user credentials and performing authentication. The system supports user identity authentication and data collection, processing, storage, and comparison. 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- Authentication credential 47 48 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. 49 50- Data verification by the executor 51 52 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. 53 54- HAPs 55 56 In a broad sense, Harmony Ability Packages (HAPs) are application packages that can be installed on OpenHarmony. In this document, the HAPs only refer to the upper-layer applications of the Face_auth driver. 57 58- IDL interface 59 60 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 Fingerprint_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md). 61 62- IPC 63 64 Inter-Process Communication (IPC) implements data exchange between two processes. For details, see [IPC](https://gitee.com/openharmony/communication_ipc/blob/master/README.md). 65 66- HDI 67 68 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). 69 70### Working Principles 71 72The fingerprint_auth driver provides stable basic fingerprint authentication capabilities for the upper-layer User_auth framework and Fingerprint_auth service to ensure successful fingerprint authentication on devices. The figure below shows the interaction between the Fingerprint_auth service and the Fingerprint_auth driver. The Fingerprint_auth service obtains executor information by using **GetExecutorInfo()** and registers the executor with the User_auth framework. The Fingerprint_auth service exchanges information with the Fingerprint_auth driver for authentication, identification, and query through the executor APIs. 73You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. 74 75**Figure 2** Interaction between the Fingerprint_auth service and Fingerprint_auth driver 76 77 78 79### Constraints 80 81A Trusted Execution Environment (TEE) must be available on the device to store encrypted fingerprint feature information. 82 83## Development Guidelines 84 85### When to Use 86 87The fingerprint_auth driver provides stable basic fingerprint authentication capabilities for the upper-layer User_auth framework and Fingerprint_auth service to ensure successful fingerprint authentication on devices. To implement the preceding functions, you need to develop the Fingerprint_auth driver based on the HDF, and then implement the APIs for obtaining the executor list and functional APIs such as authentication and query. 88 89### Available APIs 90 91The 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/fingerprint_auth/**. 92**Table 1** describes the HDI APIs for fingerprint credential enrollment, authentication, recognition, and deletion. **Table 2** describes the callbacks used to return the executor operation result to the framework or return the authentication tip information to upper-layer applications. 93 94**Table 1** Available APIs 95 96| API | Description | 97| -------------------------------- | ----------------------------------- | 98| GetExecutorList(std::vector\<sptr\<IAllInOneExecutor>>& allInOneExecutors) | Obtains the executor list of V2_0. | 99| GetExecutorInfo(ExecutorInfo &executorInfo) | Obtains the executor information, including the executor type, executor role, authentication type, security level, and executor public key. | 100| OnRegisterFinish(const std::vector\<uint64_t>& templateIdList,<br> const std::vector\<uint8_t>& frameworkPublicKey, const std::vector\<uint8_t>& extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully. | 101| Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Enrolls a fingerprint. | 102| Authenticate(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList, bool endAfterFirstFail,<br>const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Authenticates a fingerprint template (V2_0). | 103| Identify(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Identifies a fingerprint. | 104| Delete(const std::vector\<uint64_t>& templateIdList) | Deletes a fingerprint. | 105| Cancel(uint64_t scheduleId) | Cancels a fingerprint enrollment, authentication, or identification operation based on the **scheduleId**. | 106| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Sends commands to the Fingerprint_auth driver. | 107| GetProperty(const std::vector\<uint64_t>& templateIdList,<br>const std::vector\<int32_t>& propertyTypes, Property& property) | Obtains executor property information. | 108| SetCachedTemplates(const std::vector\<uint64_t\> &templateIdList) | Sets a list of templates to be cached. | 109| RegisterSaCommandCallback(const sptr\<ISaCommandCallback\> &callbackObj) | Registers a callback to be invoked when an SA command is executed. | 110 111**Table 2** Callbacks 112 113| API | Description | 114| ------------------------------------------------------------ | ------------------------ | 115| IExecutorCallback::OnResult(int32_t result, const std::vector\<uint8_t>& extraInfo) | Called to return the operation result. | 116| IExecutorCallback::OnTip(int32_t tip, const std::vector\<uint8_t>& extraInfo) | Called to return the interaction information about the operation process. | 117| ISaCommandCallback::OnSaCommands(const std::vector\<SaCommand>& commands) | Called to send the command list. | 118 119### How to Develop 120 121The following uses the Hi3516D V300 development board as an example to demonstrate how to develop the Fingerprint_auth driver. <br/>The directory structure is as follows: 122 123```undefined 124// drivers/peripheral/fingerprint_auth 125├── BUILD.gn # Build script 126├── bundle.json # Component description file 127└── hdi_service # Fingerprint_auth driver implementation 128 ├── BUILD.gn # Build script 129 ├── include # Header files 130 └── src # Source files 131 ├── executor_impl.cpp # Implementation of authentication and enrollment APIs 132 ├── fingerprint_auth_interface_driver.cpp # Fingerprint_auth driver entry 133 └── fingerprint_auth_interface_service.cpp # Implementation of the API for obtaining the executor list 134``` 135 136The development procedure is as follows: 137 1381. Develop the Fingerprint_auth driver based on the HDF using the **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions. For details about the code, see [fingerprint_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/fingerprint_auth/hdi_service/src/fingerprint_auth_interface_driver.cpp).<br>The sample code is as follows: 139 140 ```c++ 141 // Create an IRemoteObject object by using the custom HdfFingerprintAuthInterfaceHost object, which consists of the IoService object and HDI service. 142 struct HdfFingerprintAuthInterfaceHost { 143 struct IDeviceIoService ioService; 144 OHOS::sptr<OHOS::IRemoteObject> stub; 145 }; 146 147 // Enable the IPC service to call the response API. 148 static int32_t FingerprintAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 149 struct HdfSBuf *reply) 150 { 151 auto *hdfFingerprintAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfFingerprintAuthInterfaceHost, ioService); 152 153 OHOS::MessageParcel *dataParcel = nullptr; 154 OHOS::MessageParcel *replyParcel = nullptr; 155 OHOS::MessageOption option; 156 157 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 158 HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__); 159 return HDF_ERR_INVALID_PARAM; 160 } 161 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 162 HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__); 163 return HDF_ERR_INVALID_PARAM; 164 } 165 166 return hdfFingerprintAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 167 } 168 169 // Initialize the HdfFingerprintAuthInterfaceDriver object. 170 static int HdfFingerprintAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 171 { 172 HDF_LOGI("%{public}s: driver init start", __func__); 173 return HDF_SUCCESS; 174 } 175 176 // Bind the service provided by the Fingerprint_auth driver to the HDF. 177 static int HdfFingerprintAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 178 { 179 HDF_LOGI("%{public}s: driver bind start", __func__); 180 auto *hdfFingerprintAuthInterfaceHost = new (std::nothrow) HdfFingerprintAuthInterfaceHost; 181 if (hdfFingerprintAuthInterfaceHost == nullptr) { 182 HDF_LOGE("%{public}s: failed to create create HdfFingerprintAuthInterfaceHost object", __func__); 183 return HDF_FAILURE; 184 } 185 186 hdfFingerprintAuthInterfaceHost->ioService.Dispatch = FingerprintAuthInterfaceDriverDispatch; 187 hdfFingerprintAuthInterfaceHost->ioService.Open = NULL; 188 hdfFingerprintAuthInterfaceHost->ioService.Release = NULL; 189 190 auto serviceImpl = OHOS::HDI::FingerprintAuth::V2_0::IFingerprintAuthInterface::Get(true); 191 if (serviceImpl == nullptr) { 192 HDF_LOGE("%{public}s: failed to get of implement service", __func__); 193 delete hdfFingerprintAuthInterfaceHost; 194 return HDF_FAILURE; 195 } 196 197 hdfFingerprintAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 198 OHOS::HDI::FingerprintAuth::V2_0::IFingerprintAuthInterface::GetDescriptor()); 199 if (hdfFingerprintAuthInterfaceHost->stub == nullptr) { 200 HDF_LOGE("%{public}s: failed to get stub object", __func__); 201 delete hdfFingerprintAuthInterfaceHost; 202 return HDF_FAILURE; 203 } 204 205 deviceObject->service = &hdfFingerprintAuthInterfaceHost->ioService; 206 return HDF_SUCCESS; 207 } 208 209 // Release the resources used by the Fingerprint_auth driver. 210 static void HdfFingerprintAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) 211 { 212 HDF_LOGI("%{public}s: driver release start", __func__); 213 if (deviceObject->service == nullptr) { 214 return; 215 } 216 auto *hdfFingerprintAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfFingerprintAuthInterfaceHost, ioService); 217 if (hdfFingerprintAuthInterfaceHost != nullptr) { 218 delete hdfFingerprintAuthInterfaceHost; 219 } 220 } 221 222 // Register the Fingerprint_auth driver entry data structure object. 223 struct HdfDriverEntry g_fingerprintAuthInterfaceDriverEntry = { 224 .moduleVersion = 1, 225 .moduleName = "drivers_peripheral_fingerprint_auth", 226 .Bind = HdfFingerprintAuthInterfaceDriverBind, 227 .Init = HdfFingerprintAuthInterfaceDriverInit, 228 .Release = HdfFingerprintAuthInterfaceDriverRelease, 229 }; 230 231 // 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. 232 HDF_INIT(g_fingerprintAuthInterfaceDriverEntry); 233 ``` 234 2352. Implement the API for obtaining the executor list. For details about the code, see [fingerprint_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/fingerprint_auth/hdi_service/src/fingerprint_auth_interface_service.cpp).<br>The sample code is as follows: 236 237 ```c++ 238 // Executor implementation class 239 class AllInOneExecutorImpl : public IAllInOneExecutor { 240 public: 241 AllInOneExecutorImpl(struct ExecutorInfo executorInfo); 242 virtual ~AllInOneExecutorImpl() {} 243 244 private: 245 struct ExecutorInfo executorInfo_; // Executor information 246 }; 247 248 static constexpr uint16_t SENSOR_ID = 123; // Executor sensor ID 249 static constexpr uint32_t EXECUTOR_TYPE = 123; // Executor type 250 static constexpr size_t PUBLIC_KEY_LEN = 32; //32-byte public key of the executor 251 252 // Create an HDI service object. 253 extern "C" IFingerprintAuthInterface *FingerprintAuthInterfaceImplGetInstance(void) 254 { 255 auto fingerprintAuthInterfaceService = new (std::nothrow) FingerprintAuthInterfaceService(); 256 if (fingerprintAuthInterfaceService == nullptr) { 257 IAM_LOGE("fingerprintAuthInterfaceService is nullptr"); 258 return nullptr; 259 } 260 return fingerprintAuthInterfaceService; 261 } 262 263 // Obtain the executor list of V2_0. 264 int32_t FingerprintAuthInterfaceService::GetExecutorList(std::vector<sptr<IAllInOneExecutor>> &executorList) 265 { 266 IAM_LOGI("interface mock start"); 267 for (auto executor : executorList_) { 268 executorList.push_back(executor); 269 } 270 IAM_LOGI("interface mock success"); 271 return HDF_SUCCESS; 272 } 273 ``` 274 2753. Implement each function of the executor. For details about the code, see [all_in_one_executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/fingerprint_auth/hdi_service/src/all_in_one_executor_impl.cpp).<br>The sample code is as follows: 276 277 ```c++ 278 // Obtain the executor information. 279 int32_t AllInOneExecutorImpl::GetExecutorInfo(ExecutorInfo &executorInfo) 280 { 281 IAM_LOGI("interface mock start"); 282 executorInfo = executorInfo_; 283 IAM_LOGI("get executor information success"); 284 return HDF_SUCCESS; 285 } 286 287 // After the executor is successfully registered, obtain the public key and template ID list from User_auth and save the public key. The executor compares its template ID list with the template ID list obtained and updates its template ID list. 288 int32_t AllInOneExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList, 289 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) 290 { 291 IAM_LOGI("interface mock start"); 292 static_cast<void>(templateIdList); 293 static_cast<void>(extraInfo); 294 static_cast<void>(frameworkPublicKey); 295 IAM_LOGI("register finish"); 296 return HDF_SUCCESS; 297 } 298 299 // Enroll fingerprints. 300 int32_t AllInOneExecutorImpl::Enroll( 301 uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 302 { 303 IAM_LOGI("interface mock start"); 304 static_cast<void>(scheduleId); 305 static_cast<void>(extraInfo); 306 if (callbackObj == nullptr) { 307 IAM_LOGE("callbackObj is nullptr"); 308 return HDF_ERR_INVALID_PARAM; 309 } 310 IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 311 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 312 if (ret != HDF_SUCCESS) { 313 IAM_LOGE("callback result is %{public}d", ret); 314 return HDF_FAILURE; 315 } 316 return HDF_SUCCESS; 317 } 318 319 // Perform fingerprint authentication. 320 int32_t AllInOneExecutorService::Authenticate(uint64_t scheduleId, const std::vector<uint64_t> &templateIdList, 321 const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 322 { 323 IAM_LOGI("interface mock start"); 324 static_cast<void>(scheduleId); 325 static_cast<void>(templateIdList); 326 static_cast<void>(extraInfo); 327 if (callbackObj == nullptr) { 328 IAM_LOGE("callbackObj is nullptr"); 329 return HDF_ERR_INVALID_PARAM; 330 } 331 IAM_LOGI("authenticate, result is %{public}d", ResultCode::NOT_ENROLLED); 332 int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {}); 333 if (ret != HDF_SUCCESS) { 334 IAM_LOGE("callback result is %{public}d", ret); 335 return HDF_FAILURE; 336 } 337 return HDF_SUCCESS; 338 } 339 340 // Identify fingerprints. 341 int32_t AllInOneExecutorService::Identify( 342 uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 343 { 344 IAM_LOGI("interface mock start"); 345 static_cast<void>(scheduleId); 346 static_cast<void>(extraInfo); 347 if (callbackObj == nullptr) { 348 IAM_LOGE("callbackObj is nullptr"); 349 return HDF_ERR_INVALID_PARAM; 350 } 351 IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 352 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 353 if (ret != HDF_SUCCESS) { 354 IAM_LOGE("callback result is %{public}d", ret); 355 return HDF_FAILURE; 356 } 357 return HDF_SUCCESS; 358 } 359 360 // Delete fingerprints. 361 int32_t AllInOneExecutorService::Delete(const std::vector<uint64_t> &templateIdList) 362 { 363 IAM_LOGI("interface mock start"); 364 static_cast<void>(templateIdList); 365 IAM_LOGI("delete success"); 366 return HDF_SUCCESS; 367 } 368 369 // Cancel the operation based on the specified scheduleId. 370 int32_t AllInOneExecutorService::Cancel(uint64_t scheduleId) 371 { 372 IAM_LOGI("interface mock start"); 373 static_cast<void>(scheduleId); 374 IAM_LOGI("cancel success"); 375 return HDF_SUCCESS; 376 } 377 378 // Send template locking or unlocking command from the Fingerprint_auth service to the Fingerprint_auth driver. 379 int32_t AllInOneExecutorService::SendCommand( 380 int32_t commandId, const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 381 { 382 IAM_LOGI("interface mock start"); 383 static_cast<void>(extraInfo); 384 if (callbackObj == nullptr) { 385 IAM_LOGE("callbackObj is nullptr"); 386 return HDF_ERR_INVALID_PARAM; 387 } 388 int32_t ret; 389 switch (commandId) { 390 case DriverCommandId::LOCK_TEMPLATE: 391 IAM_LOGI("lock template, result is %{public}d", ResultCode::SUCCESS); 392 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 393 if (ret != HDF_SUCCESS) { 394 IAM_LOGE("callback result is %{public}d", ret); 395 return HDF_FAILURE; 396 } 397 break; 398 case DriverCommandId::UNLOCK_TEMPLATE: 399 IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); 400 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 401 if (ret != HDF_SUCCESS) { 402 IAM_LOGE("callback result is %{public}d", ret); 403 return HDF_FAILURE; 404 } 405 break; 406 case DriverCommandId::INIT_ALGORITHM: 407 IAM_LOGI("init algorithm, result is %{public}d", ResultCode::SUCCESS); 408 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 409 if (ret != HDF_SUCCESS) { 410 IAM_LOGE("callback result is %{public}d", ret); 411 return HDF_FAILURE; 412 } 413 break; 414 default: 415 IAM_LOGD("not support DriverCommandId : %{public}d", commandId); 416 ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 417 if (ret != HDF_SUCCESS) { 418 IAM_LOGE("callback result is %{public}d", ret); 419 return HDF_FAILURE; 420 } 421 } 422 return HDF_SUCCESS; 423 } 424 425 // Obtain executor properties. 426 int32_t AllInOneExecutorService::GetProperty( 427 const std::vector<uint64_t> &templateIdList, const std::vector<int32_t> &propertyTypes, Property &property) 428 { 429 IAM_LOGI("interface mock start"); 430 property = {}; 431 IAM_LOGI("get property success"); 432 return HDF_SUCCESS; 433 } 434 435 // Set a list of templates to be cached. 436 int32_t AllInOneExecutorService::SetCachedTemplates(const std::vector<uint64_t> &templateIdList) 437 { 438 IAM_LOGI("interface mock start"); 439 IAM_LOGI("set cached templates success"); 440 return HDF_SUCCESS; 441 } 442 443 // Register the callback to be invoked when the SA command is executed. 444 int32_t AllInOneExecutorService::RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj) 445 { 446 IAM_LOGI("interface mock start"); 447 IAM_LOGI("register sa command callback success"); 448 return HDF_SUCCESS; 449 } 450 ``` 451 4524. Modify **serviceName2Config** in the **fingerprint_auth_service.cpp** file if you need to add a driver or modify driver information. 453 454 ```c++ 455 // base/user_iam/fingerprint_auth/services/src/fingerprint_auth_service.cpp 456 void FingerprintAuthService::StartDriverManager() 457 { 458 IAM_LOGI("start"); 459 int32_t ret = UserAuth::IDriverManager::Start(HDI_NAME_2_CONFIG); 460 if (ret != UserAuth::ResultCode::SUCCESS) { 461 IAM_LOGE("start driver manager failed"); 462 } 463 } 464 ``` 465 466### Verification 467 468Use the [User Authentication APIs](../../application-dev/reference/apis-user-authentication-kit/js-apis-useriam-userauth.md) to develop a HAP and verify the application on the RK3568 platform. The sample code for starting and canceling an authentication is as follows: 469 4701. Initiate a request for user authentication and obtain the authentication result. 471 472```ts 473 // API version 10 474 import type {BusinessError} from '@ohos.base'; 475 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 476 477 // Set authentication parameters. 478 const authParam: userIAM_userAuth.AuthParam = { 479 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 480 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FINGERPRINT], 481 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 482 }; 483 484 // Set the authentication page. 485 const widgetParam: userIAM_userAuth.WidgetParam = { 486 title: 'Verify identity', 487 }; 488 489 try { 490 // Obtain an authentication object. 491 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 492 console.info('get userAuth instance success'); 493 // Subscribe to the authentication result. 494 userAuthInstance.on('result', { 495 onResult(result) { 496 console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); 497 // Unsubscribe from the authentication result if required. 498 userAuthInstance.off('result'); 499 } 500 }); 501 console.info('auth on success'); 502 userAuthInstance.start(); 503 console.info('auth start success'); 504 } catch (error) { 505 const err: BusinessError = error as BusinessError; 506 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 507 } 508``` 509 5102. Cancel an authentication. 511 512```ts 513 // API version 10 514 import type {BusinessError} from '@ohos.base'; 515 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 516 517 const authParam: userIAM_userAuth.AuthParam = { 518 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 519 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FINGERPRINT], 520 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 521 }; 522 523 const widgetParam: userIAM_userAuth.WidgetParam = { 524 title: 'Verify identity', 525 }; 526 527 try { 528 // Obtain an authentication object. 529 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 530 console.info('get userAuth instance success'); 531 // Start user authentication. 532 userAuthInstance.start(); 533 console.info('auth start success'); 534 // Cancel the authentication. 535 userAuthInstance.cancel(); 536 console.info('auth cancel success'); 537 } catch (error) { 538 const err: BusinessError = error as BusinessError; 539 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 540 } 541``` 542