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![image](figures/fingerprint_auth_architecture.png "Fingerprint authentication architecture")
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![image](figures/fingerprint_auth_service_and_driver_interaction.png "Fingerprint_auth service and driver interaction")
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