1# User Authentication 2 3## Overview 4 5### Function 6 7User authentication is indispensable in identity authentication scenarios, such as device unlocking, payment, and app logins. The user authentication framework (User_auth) manages the mappings between user identities and authentication credential templates in a unified manner. It schedules executors implemented by basic authentication services (including PIN authentication and facial recognition) to register user authentication credentials, delete credentials, obtain related information, and complete authentication. The figure below shows the architecture of user authentication. 8 9The User_auth driver is developed based on the Hardware Driver Foundation (HDF). It shields hardware differences and provides stable user authentication capabilities for apps and account management system ability (SA). It supports user credential management, authentication information enrollment, authentication scheme generation, and executor information management. 10 11**Figure 1** User authentication architecture 12 13 14 15### Basic Concepts 16The identity authentication consists of the User_auth framework 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- Authentication credential information 19 20 An authentication credential template is generated when a user sets a password or enrolls facial information. The credential information consists of the user identity information and credential template information. The authentication is successful when the credential data generated matches the credential template information. 21 22- Authentication credential template 23 24 The authentication credential template is generated and stored by the authentication service when a user sets the authentication credential. 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. 25 26- Executor 27 28 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. 29 30- Executor role 31 32 - 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. 33 34 - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication. 35 36 - Authenticator: processes data, obtains the stored credential template, and compares it with the authentication information generated. 37 38- Executor type 39 40 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. 41 42- Executor security level 43 44 Security level of the runtime environment when an executor provides capabilities. 45 46- User_auth public key & executor public key 47 48 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. 49 50 - The executor uses the User_auth public key to verify scheduling instructions. For example, if a face image template is locked, the related facial authentication capability cannot be used. The instruction for unlocking the face image template must be verified before being executed. 51 52 - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. 53 54 55- Authentication result trust level 56 57 The trust level of the authentication result varies, depending on the authentication mode and the security level of the authentication execution environment. 58 59- Authentication scheme 60 61 An authentication scheme contains information about the authentication mode, trust level of the authentication result, executor, and credential. 62 63- Scheduling information 64 65 Scheduling information includes the executor information and credential template information required by the executor to process requests. User_auth schedules the executor to implement basic authentication capabilities. 66 67- SA 68 69 SAs are loaded by the System Ability Manager to provide basic system capabilities for OpenHarmony devices. 70 71- Kit 72 73 The kit provides basic APIs for third-party applications. 74 75- Inner API 76 77 Inner API is an API provided by OpenHarmony for system applications. 78 79- IDL interface 80 81 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 User_auth service and driver. For details, see [IDL](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md). 82 83- IPC 84 85 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). 86 87- HDI 88 89 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). 90 91### Working Principles 92 93The User_auth driver shields the differences of security devices and environments. It provides unified interfaces for the User_auth service to implement management of executors and credentials as well as authentication scheme generation. 94You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. 95 96**Figure 2** User_auth service and User_auth driver APIs 97 98 99 100### Constraints 101 102The User_auth driver must be implemented in a Trusted Execution Environment (TEE) to ensure secure storage of user credentials and trustworthiness of user authentication results. 103 104## Development Guidelines 105 106### When to Use 107 108The User_auth driver provides stable user credential management, authentication session management, and executor information management for the User_auth service to ensure successful PIN authentication and biometric recognition on devices. 109 110### Available APIs 111 112The 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/user_auth**. 113**Table 1** describes the HDI APIs for executor registration, credential enrollment and deletion, user authentication, and user identification. 114 115**Table 1** Available APIs 116 117| API | Description | 118| --------------------------- | --------------------------- | 119| Init() | Initializes cached information. | 120| AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index, std::vector\<uint8_t>& publicKey,<br> std::vector\<uint64_t>& templateIds) | Adds an executor to obtain the authentication capability. | 121| DeleteExecutor(uint64_t index) | Deletes an executor. | 122| OpenSession(int32_t userId, std::vector\<uint8_t>& challenge) | Opens a session for authentication credential management. | 123| CloseSession(int32_t userId) | Closes a session for authentication credential management. | 124| BeginEnrollment(int32_t userId, const std::vector\<uint8_t>& authToken, const EnrollParam& param,<br> ScheduleInfo& info) | Enrolls the user authentication credential (version V1_0). If a user has enrolled a PIN, the old PIN will be overwritten .| 125| UpdateEnrollmentResult(int32_t userId, const std::vector\<uint8_t>& scheduleResult, uint64_t& credentialId,<br> CredentialInfo& oldInfo) | Updates the data to complete this enrollment. | 126| CancelEnrollment(int32_t userId) | Cancels an enrollment operation. | 127| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector\<uint8_t>& authToken,<br> CredentialInfo& info) | Deletes credential information based on the specified **credentialId**. | 128| DeleteUser(int32_t userId, const std::vector\<uint8_t>& authToken,<br> std::vector\<CredentialInfo>& deletedInfos) | Deletes a user PIN from User_auth. | 129| EnforceDeleteUser(int32_t userId, std::vector\<CredentialInfo>& deletedInfos) | Forcibly deletes a user. This API will be called when a user is deleted from the system. | 130| GetCredential(int32_t userId, AuthType authType, std::vector\<CredentialInfo>& infos) | Obtains user credential information by authentication type. | 131| GetSecureInfo(int32_t userId, uint64_t& secureUid, std::vector\<EnrolledInfo>& infos) | Obtains the secure user ID and the enrolled tag ID of each authentication type. | 132| BeginAuthentication(uint64_t contextId, const AuthSolution& param,<br> std::vector\<ScheduleInfo>& scheduleInfos) | Starts authentication and generates the authentication scheme and scheduling information (version V1_0). | 133| UpdateAuthenticationResult(uint64_t contextId, const std::vector\<uint8_t>& scheduleResult,<br> AuthResultInfo& info) | Updates the authentication result to evaluate the authentication scheme. | 134| CancelAuthentication(uint64_t contextId) | Cancels an authentication. | 135| BeginIdentification(uint64_t contextId, AuthType authType, const std::vector\<int8_t>& challenge,<br> uint32_t executorId, ScheduleInfo& scheduleInfo) | Starts identification and generates the identification scheme and scheduling information (version V1_0). | 136| UpdateIdentificationResult(uint64_t contextId, const std::vector\<uint8_t>& scheduleResult,<br> IdentifyResultInfo& info) | Updates the identification result to evaluate the identification scheme. | 137| CancelIdentification(uint64_t contextId) | Cancels an identification. | 138| GetAuthTrustLevel(int32_t userId, AuthType authType, uint32_t& authTrustLevel) | Obtains the authentication trust level of the specified authentication type. | 139| GetValidSolution(int32_t userId, const std::vector\<AuthType>& authTypes, uint32_t authTrustLevel,<br> std::vector\<AuthType>& validTypes) | Obtains the valid authentication scheme based on the authentication trust level for a user. | 140| BeginEnrollmentV1_1(int32_t userId, const std::vector\<uint8_t>& authToken, const EnrollParam& param, ScheduleInfoV1_1& info) | Enrolls the user authentication credential (version V1_1). If a user has enrolled a PIN, the old PIN will be overwritten.| 141| BeginAuthenticationV1_1(uint64_t contextId, const AuthSolution& param, std::vector\<ScheduleInfoV1_1>& scheduleInfos) | Starts authentication and generates the authentication scheme and scheduling information (version V1_1). | 142| BeginIdentificationV1_1(uint64_t contextId, AuthType authType,<br/> const std::vector\<uint8_t>& challenge, uint32_t executorSensorHint, ScheduleInfoV1_1& scheduleInfo) | Starts identification and generates the identification scheme and scheduling information (version V1_1). | 143### How to Develop 144 145The following uses the Hi3516D V300 development board as an example to demonstrate how to develop the User_auth driver. <br/>The directory structure is as follows: 146 147```undefined 148// drivers/peripheral/user_auth 149├── BUILD.gn # Build script 150├── bundle.json # Component description file 151└── hdi_service # User_auth driver implementation 152 ├── BUILD.gn # Build script 153 ├── module # Implementation of functionalities 154 └── service 155 ├── user_auth_interface_driver.cpp # User_auth driver entry 156 └── user_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list 157``` 158 159The development procedure is as follows: 160 1611. Develop the User_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [user_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_driver.cpp). 162 163 ```c++ 164 // Create an IRemoteObject object by using the custom HdfUserAuthInterfaceHost object, which consists of the IoService object and HDI service. 165 struct HdfUserAuthInterfaceHost { 166 struct IDeviceIoService ioService; 167 OHOS::sptr<OHOS::IRemoteObject> stub; 168 }; 169 170 // Enable the IPC service to call the response API. 171 static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 172 struct HdfSBuf *reply) 173 { 174 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService); 175 176 OHOS::MessageParcel *dataParcel = nullptr; 177 OHOS::MessageParcel *replyParcel = nullptr; 178 OHOS::MessageOption option; 179 180 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 181 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 182 return HDF_ERR_INVALID_PARAM; 183 } 184 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 185 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 186 return HDF_ERR_INVALID_PARAM; 187 } 188 189 return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 190 } 191 192 // Initialize the HdfUserAuthInterfaceDriver object. 193 int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 194 { 195 HDF_LOGI("HdfUserAuthInterfaceDriverInit enter"); 196 OHOS::UserIAM::Common::Init(); 197 return HDF_SUCCESS; 198 } 199 200 // Bind the service provided by the User_auth driver to the HDF. 201 int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 202 { 203 HDF_LOGI("HdfUserAuthInterfaceDriverBind enter"); 204 205 auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost; 206 if (hdfUserAuthInterfaceHost == nullptr) { 207 HDF_LOGE("%{public}s: failed to create HdfUserAuthInterfaceHost object", __func__); 208 return HDF_FAILURE; 209 } 210 211 hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch; 212 hdfUserAuthInterfaceHost->ioService.Open = NULL; 213 hdfUserAuthInterfaceHost->ioService.Release = NULL; 214 215 auto serviceImpl = IUserAuthInterface::Get(true); 216 if (serviceImpl == nullptr) { 217 HDF_LOGE("%{public}s: failed to implement service", __func__); 218 return HDF_FAILURE; 219 } 220 221 hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 222 IUserAuthInterface::GetDescriptor()); 223 if (hdfUserAuthInterfaceHost->stub == nullptr) { 224 HDF_LOGE("%{public}s: failed to get stub object", __func__); 225 return HDF_FAILURE; 226 } 227 228 deviceObject->service = &hdfUserAuthInterfaceHost->ioService; 229 return HDF_SUCCESS; 230 } 231 232 // Release resources of the User_auth driver. 233 void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){ 234 HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter"); 235 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService); 236 delete hdfUserAuthInterfaceHost; 237 } 238 239 // Register the User_auth driver entry data structure object. 240 struct HdfDriverEntry g_userAuthInterfaceDriverEntry = { 241 .moduleVersion = 1, 242 .moduleName = "user_auth_device_driver", 243 .Bind = HdfUserAuthInterfaceDriverBind, 244 .Init = HdfUserAuthInterfaceDriverInit, 245 .Release = HdfUserAuthInterfaceDriverRelease, 246 }; 247 248 // 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. 249 #ifndef __cplusplus 250 extern "C" { 251 #endif 252 HDF_INIT(g_userAuthInterfaceDriverEntry); 253 #ifndef __cplusplus 254 } 255 #endif 256 ``` 257 2582. Register the executor. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 259 260 ```c++ 261 // Add an executor. 262 int32_t UserAuthInterfaceService::AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index, 263 std::vector<uint8_t>& publicKey, std::vector<uint64_t>& templateIds) 264 { 265 GlobalLock(); 266 ExecutorInfoHal executorInfoHal; 267 CopyExecutorInfo(info, executorInfoHal); 268 int32_t ret = RegisterExecutor(&executorInfoHal, &index); 269 GlobalUnLock(); 270 return ret; 271 } 272 273 // Delete the executor. 274 int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index) 275 { 276 return UnRegisterExecutor(index); 277 } 278 ``` 279 2803. Enroll user authentication data. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 281 282 ```c++ 283 // Open a session for authentication credential management. 284 int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector<uint8_t>& challenge) 285 { 286 GlobalLock(); 287 uint64_t challengeU64 = 0; 288 int32_t ret = OpenEditSession(userId, &challengeU64); 289 challenge.resize(sizeof(uint64_t)); 290 if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) { 291 IAM_LOGE("failed to copy challengeU64"); 292 return RESULT_BAD_COPY; 293 } 294 GlobalUnLock(); 295 return ret; 296 } 297 298 // Close the session for authentication credential management. 299 int32_t UserAuthInterfaceService::CloseSession(int32_t userId) 300 { 301 GlobalLock(); 302 int32_t ret = CloseEditSession(); 303 GlobalUnLock(); 304 return ret; 305 } 306 307 // Start enrollment and generate scheduling information (V1_1). 308 int32_t UserAuthInterfaceService::BeginEnrollmentV1_1(int32_t userId, const std::vector<uint8_t>& authToken, 309 const EnrollParam& param, ScheduleInfoV1_1& info) 310 { 311 IAM_LOGI("start"); 312 GlobalLock(); 313 if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) { 314 IAM_LOGE("authToken len is invalid"); 315 GlobalUnLock(); 316 return RESULT_BAD_PARAM; 317 } 318 PermissionCheckParam checkParam; 319 if (authToken.size() == sizeof(UserAuthTokenHal) && 320 memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) { 321 GlobalUnLock(); 322 return RESULT_BAD_COPY; 323 } 324 checkParam.authType = param.authType; 325 checkParam.userId = userId; 326 checkParam.authSubType = (uint64_t)param.executorType; 327 CoAuthSchedule scheduleInfo; 328 int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId); 329 if (ret != RESULT_SUCCESS) { 330 IAM_LOGE("Failed to check permission"); 331 GlobalUnLock(); 332 return ret; 333 } 334 ret = GetCoAuthSchedule(&scheduleInfo); 335 if (ret != RESULT_SUCCESS) { 336 IAM_LOGE("Failed to get schedule info"); 337 GlobalUnLock(); 338 return ret; 339 } 340 if (!CopyScheduleInfo(&scheduleInfo, &info)) { 341 IAM_LOGE("Failed to copy schedule info"); 342 ret = RESULT_BAD_COPY; 343 } 344 GlobalUnLock(); 345 return ret; 346 } 347 348 // Start enrollment and generate scheduling information (V1_0 version). The method of V1_0 is called to invoke the method of V1_1 through parameter conversion. 349 int32_t UserAuthInterfaceService::BeginEnrollment(int32_t userId, const std::vector<uint8_t> &authToken, 350 const EnrollParam ¶m, ScheduleInfo &info) 351 { 352 IAM_LOGI("start"); 353 ScheduleInfoV1_1 infoV1_1; 354 int32_t ret = BeginEnrollmentV1_1(userId, authToken, param, infoV1_1); 355 CopyScheduleInfoV1_1ToV1_0(infoV1_1, info); 356 return ret; 357 } 358 359 // Cancel the enrollment operation. 360 int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId) 361 { 362 IAM_LOGI("start"); 363 BreakOffCoauthSchedule(userId); 364 return RESULT_SUCCESS; 365 } 366 367 // Update the enrolled credential information. 368 int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t>& scheduleResult, 369 uint64_t& credentialId, CredentialInfo& oldInfo) 370 { 371 IAM_LOGI("start"); 372 GlobalLock(); 373 if (scheduleResult.size() == 0) { 374 IAM_LOGE("enrollToken is invalid"); 375 GlobalUnLock(); 376 return RESULT_BAD_PARAM; 377 } 378 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 379 if (scheduleResultBuffer == nullptr) { 380 IAM_LOGE("scheduleTokenBuffer is null"); 381 GlobalUnLock(); 382 return RESULT_NO_MEMORY; 383 } 384 bool isUpdate; 385 int32_t ret = GetIsUpdate(&isUpdate); 386 if (ret != RESULT_SUCCESS) { 387 IAM_LOGE("Failed to get isUpdate"); 388 return ret; 389 } 390 if (isUpdate) { 391 CredentialInfoHal oldCredentialHal; 392 ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal); 393 oldInfo.authType = static_cast<AuthType>(oldCredentialHal.authType); 394 oldInfo.credentialId = oldCredentialHal.credentialId; 395 oldInfo.templateId = oldCredentialHal.templateId; 396 oldInfo.executorType = static_cast<uint32_t>(oldCredentialHal.authSubType); 397 oldInfo.executorId = 0; 398 oldInfo.index = 0; 399 } else { 400 ret = AddCredentialFunc(scheduleResultBuffer, &credentialId); 401 } 402 DestoryBuffer(scheduleResultBuffer); 403 GlobalUnLock(); 404 return ret; 405 } 406 ``` 407 4084. Perform the authentication. For details about the code, see [user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp). 409 410 ```c++ 411 // Create an HDI service object. 412 extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void) 413 { 414 auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService(); 415 if (userAuthInterfaceService == nullptr) { 416 IAM_LOGE("userAuthInterfaceService is nullptr"); 417 return nullptr; 418 } 419 return userAuthInterfaceService; 420 } 421 422 // Start an authentication to generate the authentication scheme and scheduling information. 423 int32_t UserAuthInterfaceService::BeginAuthenticationV1_1(uint64_t contextId, const AuthSolution& param, 424 std::vector<ScheduleInfoV1_1>& infos) 425 { 426 IAM_LOGI("start"); 427 if (param.challenge.size() != sizeof(uint64_t)) { 428 IAM_LOGE("Failed to copy challenge"); 429 return RESULT_BAD_PARAM; 430 } 431 GlobalLock(); 432 CoAuthSchedule *schedulesGet = nullptr; 433 uint32_t scheduleIdNum = 0; 434 AuthSolutionHal solutionIn; 435 solutionIn.contextId = contextId; 436 solutionIn.userId = param.userId; 437 solutionIn.authType = static_cast<uint32_t>(param.authType); 438 solutionIn.authTrustLevel = param.authTrustLevel; 439 if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), ¶m.challenge[0], 440 param.challenge.size()) != EOK) { 441 IAM_LOGE("Failed to copy challenge"); 442 GlobalUnLock(); 443 return RESULT_BAD_COPY; 444 } 445 int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum); 446 if (ret != RESULT_SUCCESS) { 447 IAM_LOGE("Failed to generate solution"); 448 GlobalUnLock(); 449 return ret; 450 } 451 for (uint32_t i = 0; i < scheduleIdNum; i++) { 452 ScheduleInfoV1_1 temp; 453 if (!CopyScheduleInfo(schedulesGet + i, &temp)) { 454 infos.clear(); 455 ret = RESULT_GENERAL_ERROR; 456 break; 457 } 458 infos.push_back(temp); 459 } 460 free(schedulesGet); 461 GlobalUnLock(); 462 return ret; 463 } 464 465 // Start user authentication, generate the authentication scheme and scheduling information. The method of V1_0 is called to invoke the method of V1_1 through parameter conversion. 466 int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const AuthSolution ¶m, 467 std::vector<ScheduleInfo> &infos) 468 { 469 IAM_LOGI("start"); 470 std::vector<ScheduleInfoV1_1> infosV1_1; 471 int32_t ret = BeginAuthenticationV1_1(contextId, param, infosV1_1); 472 CopyScheduleInfosV1_1ToV1_0(infosV1_1, infos); 473 return ret; 474 } 475 476 // Update the authentication result to evaluate the authentication scheme. 477 int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId, 478 const std::vector<uint8_t>& scheduleResult, AuthResultInfo& info) 479 { 480 IAM_LOGI("start"); 481 GlobalLock(); 482 if (scheduleResult.size() == 0) { 483 IAM_LOGE("param is invalid"); 484 info.result = RESULT_BAD_PARAM; 485 GlobalUnLock(); 486 return RESULT_BAD_PARAM; 487 } 488 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 489 if (scheduleResultBuffer == nullptr) { 490 IAM_LOGE("scheduleTokenBuffer is null"); 491 info.result = RESULT_GENERAL_ERROR; 492 GlobalUnLock(); 493 return RESULT_NO_MEMORY; 494 } 495 UserAuthTokenHal authTokenHal; 496 info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal); 497 if (info.result != RESULT_SUCCESS) { 498 IAM_LOGE("Failed to execute func"); 499 DestoryBuffer(scheduleResultBuffer); 500 GlobalUnLock(); 501 return info.result; 502 } 503 info.token.resize(sizeof(UserAuthTokenHal)); 504 if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) { 505 IAM_LOGE("Failed to copy authToken"); 506 DestoryBuffer(scheduleResultBuffer); 507 GlobalUnLock(); 508 return RESULT_BAD_COPY; 509 } 510 DestoryBuffer(scheduleResultBuffer); 511 GlobalUnLock(); 512 return RESULT_SUCCESS; 513 } 514 515 // Cancel the authentication. 516 int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId) 517 { 518 IAM_LOGI("start"); 519 GlobalLock(); 520 uint32_t scheduleIdNum = 0; 521 int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum); 522 if (ret != RESULT_SUCCESS) { 523 IAM_LOGE("Failed to execute func"); 524 GlobalUnLock(); 525 return ret; 526 } 527 GlobalUnLock(); 528 return RESULT_SUCCESS; 529 } 530 ``` 531 532### Verification 533 534Use 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 sample code for verifying and canceling the authentication is as follows: 535 536 ```js 537 // API version 9 538 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 539 540 let challenge = new Uint8Array([1, 2, 3, 4, 5, 6, 7, 8]); 541 let authType = userIAM_userAuth.UserAuthType.FACE; 542 let authTrustLevel = userIAM_userAuth.AuthTrustLevel.ATL1; 543 544 // Obtain an authentication object. 545 let auth; 546 try { 547 auth = userIAM_userAuth.getAuthInstance(challenge, authType, authTrustLevel); 548 console.log("get auth instance success"); 549 } catch (error) { 550 console.log("get auth instance failed" + error); 551 } 552 553 // Subscribe to the authentication result. 554 try { 555 auth.on("result", { 556 callback: (result: userIAM_userAuth.AuthResultInfo) => { 557 console.log("authV9 result " + result.result); 558 console.log("authV9 token " + result.token); 559 console.log("authV9 remainAttempts " + result.remainAttempts); 560 console.log("authV9 lockoutDuration " + result.lockoutDuration); 561 } 562 }); 563 console.log("subscribe authentication event success"); 564 } catch (error) { 565 console.log("subscribe authentication event failed " + error); 566 } 567 568 // Start user authentication. 569 try { 570 auth.start(); 571 console.info("authV9 start auth success"); 572 } catch (error) { 573 console.info("authV9 start auth failed, error = " + error); 574 } 575 576 // Cancel the authentication. 577 try { 578 auth.cancel(); 579 console.info("Authentication canceled successfully"); 580 } catch (error) { 581 console.info("cancel auth failed, error = " + error); 582 } 583 584 // Unsubscribe from the authentication result. 585 try { 586 auth.off("result"); 587 console.info("cancel subscribe authentication event success"); 588 } catch (error) { 589 console.info("cancel subscribe authentication event failed, error = " + error); 590 } 591 ``` 592