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, OpenHarmony 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) 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). 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\<V1_0::IExecutor>>& executorList) | Obtains the executor list (version V1_0).| 99| GetExecutorListV1_1(std::vector\<sptr\<V1_1::IExecutor>>& executorList) | Obtains the executor list (version V1_1). | 100| GetExecutorInfo(ExecutorInfo& info) | Obtains the executor information, including the executor type, executor role, authentication type, security level, and executor public key.| 101| GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | Obtains information about the template based on the specified ID. | 102| 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.| 103| Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Enrolls a fingerprint. | 104| Authenticate(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList,<br> const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Authenticates a fingerprint (version V1_0). | 105| AuthenticateV1_1(uint64_t scheduleId, const std::vector\<uint64_t>& templateIdList,<br> bool endAfterFirstFail, const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | Authenticates a fingerprint (version V1_1). | 106| Identify(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Identifies a fingerprint. | 107| Delete(const std::vector\<uint64_t>& templateIdList) | Deletes a fingerprint. | 108| Cancel(uint64_t scheduleId) | Cancels a fingerprint enrollment, authentication, or identification operation based on the **scheduleId**. | 109| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br> const sptr\<IExecutorCallback>& callbackObj) | Sends commands to the Fingerprint_auth driver. | 110| GetProperty(const std::vector\<uint64_t>& templateIdList,<br>const std::vector\<GetPropertyType>& propertyTypes, Property& property) | Obtains executor property information.| 111| SetCachedTemplates(const std::vector\<uint64_t> &templateIdList) | Sets a list of templates to be cached.| 112| RegisterSaCommandCallback(const sptr\<ISaCommandCallback> &callbackObj) | Registers a callback to be invoked when an SA command is executed.| 113 114**Table 2** Callbacks 115 116| API | Description | 117| ------------------------------------------------------------ | ------------------------ | 118| IExecutorCallback::OnResult(int32_t code, const std::vector\<uint8_t>& extraInfo) | Called to return the operation result. | 119| IExecutorCallback::OnTip(int32_t code, const std::vector\<uint8_t>& extraInfo) | Called to return the interaction information about the operation process.| 120| ISaCommandCallback::OnSaCommands(const std::vector\<SaCommand>& commands) | Called to send the command list.| 121 122### How to Develop 123 124The 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: 125 126```undefined 127// drivers/peripheral/fingerprint_auth 128├── BUILD.gn # Build script 129├── bundle.json # Component description file 130└── hdi_service # Fingerprint_auth driver implementation 131 ├── BUILD.gn # Build script 132 ├── include # Header files 133 └── src # Source files 134 ├── executor_impl.cpp # Implementation of authentication and enrollment APIs 135 ├── fingerprint_auth_interface_driver.cpp # Fingerprint_auth driver entry 136 └── fingerprint_auth_interface_service.cpp # Implementation of the API for obtaining the executor list 137``` 138 139The development procedure is as follows: 140 1411. 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: 142 143 ```c++ 144 // Create an IRemoteObject object by using the custom HdfFingerprintAuthInterfaceHost object, which consists of the IoService object and HDI service. 145 struct HdfFingerprintAuthInterfaceHost { 146 struct IDeviceIoService ioService; 147 OHOS::sptr<OHOS::IRemoteObject> stub; 148 }; 149 150 // Enable the IPC service to call the response API. 151 static int32_t FingerprintAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 152 struct HdfSBuf *reply) 153 { 154 IAM_LOGI("start"); 155 auto *hdfFingerprintAuthInterfaceHost = CONTAINER_OF(client->device->service, 156 struct HdfFingerprintAuthInterfaceHost, ioService); 157 158 OHOS::MessageParcel *dataParcel = nullptr; 159 OHOS::MessageParcel *replyParcel = nullptr; 160 OHOS::MessageOption option; 161 162 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 163 IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 164 return HDF_ERR_INVALID_PARAM; 165 } 166 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 167 IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 168 return HDF_ERR_INVALID_PARAM; 169 } 170 171 return hdfFingerprintAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 172 } 173 174 // Initialize the HdfFingerprintAuthInterfaceDriver object. 175 int HdfFingerprintAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 176 { 177 IAM_LOGI("start"); 178 if (!HdfDeviceSetClass(deviceObject, DEVICE_CLASS_USERAUTH)) { 179 IAM_LOGE("set fingerprint auth hdf class failed"); 180 return HDF_FAILURE; 181 } 182 return HDF_SUCCESS; 183 } 184 185 // Bind the service provided by the Fingerprint_auth driver to the HDF. 186 int HdfFingerprintAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 187 { 188 IAM_LOGI("start"); 189 auto *hdfFingerprintAuthInterfaceHost = new (std::nothrow) HdfFingerprintAuthInterfaceHost; 190 if (hdfFingerprintAuthInterfaceHost == nullptr) { 191 IAM_LOGE("%{public}s: failed to create HdfFaceAuthInterfaceHost object", __func__); 192 return HDF_FAILURE; 193 } 194 195 hdfFingerprintAuthInterfaceHost->ioService.Dispatch = FingerprintAuthInterfaceDriverDispatch; 196 hdfFingerprintAuthInterfaceHost->ioService.Open = NULL; 197 hdfFingerprintAuthInterfaceHost->ioService.Release = NULL; 198 199 auto serviceImpl = IFingerprintAuthInterface::Get(true); 200 if (serviceImpl == nullptr) { 201 IAM_LOGE("%{public}s: failed to implement service", __func__); 202 return HDF_FAILURE; 203 } 204 205 hdfFingerprintAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 206 IFaceAuthInterface::GetDescriptor()); 207 if (hdfFingerprintAuthInterfaceHost->stub == nullptr) { 208 IAM_LOGE("%{public}s: Failed to get stub object", __func__); 209 return HDF_FAILURE; 210 } 211 212 deviceObject->service = &hdfFingerprintAuthInterfaceHost->ioService; 213 IAM_LOGI("success"); 214 return HDF_SUCCESS; 215 } 216 217 // Release the resources used by the Fingerprint_auth driver. 218 void HdfFingerprintAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) 219 { 220 IAM_LOGI("start"); 221 auto *hdfFingerprintAuthInterfaceHost = CONTAINER_OF(deviceObject->service, 222 struct HdfFaceAuthInterfaceHost, ioService); 223 delete hdfFaceAuthInterfaceHost; 224 IAM_LOGI("success"); 225 } 226 227 // Register the Fingerprint_auth driver entry data structure object. 228 struct HdfDriverEntry g_fingerprintAuthInterfaceDriverEntry = { 229 .moduleVersion = 1, 230 .moduleName = "fingerprint_auth_interface_service", 231 .Bind = HdfFingerprintAuthInterfaceDriverBind, 232 .Init = HdfFingerprintAuthInterfaceDriverInit, 233 .Release = HdfFingerprintAuthInterfaceDriverRelease, 234 }; 235 236 // 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. 237 HDF_INIT(g_fingerprintAuthInterfaceDriverEntry); 238 ``` 239 2402. 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: 241 242 ```c++ 243 // Executor implementation class 244 class ExecutorImpl : public IExecutor { 245 public: 246 ExecutorImpl(struct ExecutorInfo executorInfo); 247 virtual ~ExecutorImpl() {} 248 249 private: 250 struct ExecutorInfo executorInfo_; // Executor information 251 }; 252 253 static constexpr uint16_t SENSOR_ID = 123; // Executor sensor ID 254 static constexpr uint32_t EXECUTOR_TYPE = 123; // Executor type 255 static constexpr size_t PUBLIC_KEY_LEN = 32; //32-byte public key of the executor 256 257 // Create an HDI service object. 258 extern "C" IFaceAuthInterface *FingerprintAuthInterfaceImplGetInstance(void) 259 { 260 auto fingerprintAuthInterfaceService = new (std::nothrow) FingerprintAuthInterfaceService(); 261 if (fingerprintAuthInterfaceService == nullptr) { 262 IAM_LOGE("faceAuthInterfaceService is nullptr"); 263 return nullptr; 264 } 265 return fingerprintAuthInterfaceService; 266 } 267 268 // Obtain the executor list and create an executor. 269 int32_t GetExecutorListV1_1(std::vector<sptr<V1_1::IExecutor>>& executorList) 270 { 271 IAM_LOGI("interface mock start"); 272 executorList.clear(); 273 struct ExecutorInfo executorInfoExample = { 274 .sensorId = SENSOR_ID, 275 .executorType = EXECUTOR_TYPE, 276 .executorRole = ExecutorRole::ALL_IN_ONE, 277 .authType = AuthType::FINGERPRINT, 278 .esl = ExecutorSecureLevel::ESL0, // Executor security level, which ranges from ESL0 to ESL3 (highest). 279 .publicKey = std::vector<uint8_t>(PUBLIC_KEY_LEN, 0), // 32-byte public key, using the Ed25519 algorithm. 280 .extraInfo = {}, 281 }; 282 auto executor = new (std::nothrow) ExecutorImpl(executorInfoExample); 283 if (executor == nullptr) { 284 IAM_LOGE("executor is nullptr"); 285 return HDF_FAILURE; 286 } 287 executorList.push_back(sptr<V1_1::IExecutor>(executor)); 288 IAM_LOGI("interface mock success"); 289 return HDF_SUCCESS; 290 } 291 292 // Obtain the executor list. The method of V1_0 is called to invoke the method of V1_1 through parameter conversion. 293 int32_t GetExecutorList(std::vector<sptr<V1_0::IExecutor>> &executorList) 294 { 295 std::vector<sptr<V1_1::IExecutor>> executorListV1_1; 296 int32_t result = GetExecutorListV1_1(executorListV1_1); 297 for (auto &executor : executorListV1_1) { 298 executorList.push_back(executor); 299 } 300 return result; 301 } 302 ``` 303 3043. Implement each function of the executor. For details about the code, see [executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/fingerprint_auth/hdi_service/src/executor_impl.cpp).<br>The sample code is as follows: 305 306 ```c++ 307 // Obtain the executor information. 308 int32_t GetExecutorInfo(ExecutorInfo& info) 309 { 310 IAM_LOGI("interface mock start"); 311 info = executorInfo_; 312 IAM_LOGI("Executor information got successfully"); 313 return HDF_SUCCESS; 314 } 315 316 // Obtain template information based on templateId. 317 int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo& info) 318 { 319 IAM_LOGI("interface mock start"); 320 static_cast<void>(templateId); 321 info = {0}; 322 IAM_LOGI("Template information got successfully"); 323 return HDF_SUCCESS; 324 } 325 326 // 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. 327 int32_t OnRegisterFinish(const std::vector<uint64_t>& templateIdList, 328 const std::vector<uint8_t>& frameworkPublicKey, const std::vector<uint8_t>& extraInfo) 329 { 330 IAM_LOGI("interface mock start"); 331 static_cast<void>(templateIdList); 332 static_cast<void>(extraInfo); 333 static_cast<void>(frameworkPublicKey); 334 IAM_LOGI("registration finished"); 335 return HDF_SUCCESS; 336 } 337 338 // Enroll fingerprints. 339 int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo, 340 const sptr<IExecutorCallback>& callbackObj) 341 { 342 IAM_LOGI("interface mock start"); 343 static_cast<void>(scheduleId); 344 static_cast<void>(extraInfo); 345 IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 346 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 347 if (ret != ResultCode::SUCCESS) { 348 IAM_LOGE("callback result is %{public}d", ret); 349 return HDF_FAILURE; 350 } 351 return HDF_SUCCESS; 352 } 353 354 // Call Authenticate() of V1_0 to invoke authenticate() of V1_1. 355 int32_t Authenticate(uint64_t scheduleId, const std::vector<uint64_t> &templateIdList, 356 const std::vector<uint8_t> &extraInfo, const sptr<IExecutorCallback> &callbackObj) 357 { 358 IAM_LOGI("interface mock start"); 359 return AuthenticateV1_1(scheduleId, templateIdList, true, extraInfo, callbackObj); 360 } 361 362 // Call Authenticate() of V1_1 to implement fingerprint authentication. 363 int32_t AuthenticateV1_1(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList, bool endAfterFirstFail, 364 const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& callbackObj) 365 { 366 IAM_LOGI("interface mock start"); 367 static_cast<void>(scheduleId); 368 static_cast<void>(templateIdList); 369 static_cast<void>(endAfterFirstFail); 370 static_cast<void>(extraInfo); 371 IAM_LOGI("authenticateV1_1, result is %{public}d", ResultCode::NOT_ENROLLED); 372 int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {}); 373 if (ret != ResultCode::SUCCESS) { 374 IAM_LOGE("callback result is %{public}d", ret); 375 return HDF_FAILURE; 376 } 377 return HDF_SUCCESS; 378 } 379 380 // Identify fingerprints. 381 int32_t Identify(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo, 382 const sptr<IExecutorCallback>& callbackObj) 383 { 384 IAM_LOGI("interface mock start"); 385 static_cast<void>(scheduleId); 386 static_cast<void>(extraInfo); 387 IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); 388 int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); 389 if (ret != ResultCode::SUCCESS) { 390 IAM_LOGE("callback result is %{public}d", ret); 391 return HDF_FAILURE; 392 } 393 return HDF_SUCCESS; 394 } 395 396 // Delete fingerprints. 397 int32_t Delete(const std::vector<uint64_t>& templateIdList) 398 { 399 IAM_LOGI("interface mock start"); 400 static_cast<void>(templateIdList); 401 IAM_LOGI("delete success"); 402 return HDF_SUCCESS; 403 } 404 405 // Cancel the operation based on the specified scheduleId. 406 int32_t Cancel(uint64_t scheduleId) 407 { 408 IAM_LOGI("interface mock start"); 409 static_cast<void>(scheduleId); 410 IAM_LOGI("cancel success"); 411 return HDF_SUCCESS; 412 } 413 414 // Send template locking or unlocking command from the Fingerprint_auth service to the Fingerprint_auth driver. 415 int32_t SendCommand(int32_t commandId, const std::vector<uint8_t>& extraInfo, 416 const sptr<IExecutorCallback>& callbackObj) 417 { 418 IAM_LOGI("interface mock start"); 419 static_cast<void>(extraInfo); 420 int32_t ret; 421 switch (commandId) { 422 case LOCK_TEMPLATE: 423 IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); 424 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 425 if (ret != ResultCode::SUCCESS) { 426 IAM_LOGE("callback result is %{public}d", ret); 427 return HDF_FAILURE; 428 } 429 break; 430 case UNLOCK_TEMPLATE: 431 IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); 432 ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); 433 if (ret != ResultCode::SUCCESS) { 434 IAM_LOGE("callback result is %{public}d", ret); 435 return HDF_FAILURE; 436 } 437 break; 438 default: 439 IAM_LOGD("not support CommandId : %{public}d", commandId); 440 ret = callbackObj->OnResult(ResultCode::GENERAL_ERROR, {}); 441 if (ret != ResultCode::SUCCESS) { 442 IAM_LOGE("callback result is %{public}d", ret); 443 return HDF_FAILURE; 444 } 445 } 446 return HDF_SUCCESS; 447 } 448 449 // Obtain executor properties. 450 int32_t ExecutorImpl::GetProperty( 451 const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property) 452 { 453 IAM_LOGI("interface mock start"); 454 property = {}; 455 IAM_LOGI("get property success"); 456 return HDF_SUCCESS; 457 } 458 459 // Set a list of templates to be cached. 460 int32_t ExecutorImpl::SetCachedTemplates(const std::vector<uint64_t> &templateIdList) 461 { 462 IAM_LOGI("interface mock start"); 463 IAM_LOGI("set cached templates success"); 464 return HDF_SUCCESS; 465 } 466 467 // Register the callback to be invoked when the SA command is executed. 468 int32_t ExecutorImpl::RegisterSaCommandCallback(const sptr<ISaCommandCallback> &callbackObj) 469 { 470 IAM_LOGI("interface mock start"); 471 IAM_LOGI("register sa command callback success"); 472 return HDF_SUCCESS; 473 } 474 ``` 475 4764. Modify **serviceName2Config** in the **fingerprint_auth_service.cpp** file if you need to add a driver or modify driver information. 477 478 ```c++ 479 // base/user_iam/fingerprint_auth/services/src/fingerprint_auth_service.cpp 480 void FingerprintAuthService::StartDriverManager() 481 { 482 IAM_LOGI("start"); 483 // Service name and ID of the driver to add or modify. The driver service name and ID must be globally unique. 484 const std::map<std::string, UserAuth::ServiceConfig> serviceName2Config = { 485 {"fingerprint_auth_interface_service", {2, std::make_shared<FingerprintAuthDriverHdi>()}}, 486 }; 487 UserIAM::UserAuth::IDriverManager::GetInstance().Start(serviceName2Config); 488 } 489 ``` 490 491### Verification 492 493Use the [User Authentication APIs](../../application-dev/reference/apis/js-apis-useriam-userauth.md) to develop a JavaScript application and verify the application on the Hi3516D V300 development board. The JavaScript application invokes the Fingerprint_auth driver via the Fingerprint_auth service. The sample code is as follows: 494 495 ```js 496 // API version 9 497 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 498 499 let challenge = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); 500 let authType = userIAM_userAuth.UserAuthType.FINGERPRINT; 501 let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 502 503 // Obtain an authentication object. 504 let auth; 505 try { 506 auth = userIAM_userAuth.getAuthInstance(challenge, authType, authTrustLevel); 507 console.log("get auth instance success"); 508 } catch (error) { 509 console.log("get auth instance failed" + error); 510 } 511 512 // Subscribe to the authentication result. 513 try { 514 auth.on("result", { 515 callback: (result: userIAM_userAuth.AuthResultInfo) => { 516 console.log("authV9 result " + result.result); 517 console.log("authV9 token " + result.token); 518 console.log("authV9 remainAttempts " + result.remainAttempts); 519 console.log("authV9 lockoutDuration " + result.lockoutDuration); 520 } 521 }); 522 console.log("subscribe authentication event success"); 523 } catch (error) { 524 console.log("subscribe authentication event failed " + error); 525 } 526 527 // Start user authentication. 528 try { 529 auth.start(); 530 console.info("authV9 start auth success"); 531 } catch (error) { 532 console.info("authV9 start auth failed, error = " + error); 533 } 534 535 // Cancel the authentication. 536 try { 537 auth.cancel(); 538 console.info("cancel auth success"); 539 } catch (error) { 540 console.info("cancel auth failed, error = " + error); 541 } 542 543 // Unsubscribe from the authentication result. 544 try { 545 auth.off("result"); 546 console.info("cancel subscribe authentication event success"); 547 } catch (error) { 548 console.info("cancel subscribe authentication event failed, error = " + error); 549 } 550 ``` 551