1# User_auth 2 3## 概述 4 5### 功能简介 6 7用户认证功能是端侧设备不可或缺的一部分,可应用于设备解锁、支付、应用登录等身份认证场景。用户认证(User_auth)框架统一管理用户身份与认证凭据模板的映射关系,通过调度各认证基础服务(包含口令认证、人脸识别等)实现的执行器完成用户认证凭据注册、凭据删除、身份认证及相关信息查询。用户认证的整体架构如图1。 8 9基于HDF(Hardware Driver Foundation)驱动框架开发的User_auth驱动,能够屏蔽硬件器件差异,为上层应用(设置、锁屏等)和账号管理SA(System Ability)提供稳定的用户身份认证能力,支持用户凭据管理、认证信息录入、认证方案生成以及认证执行器信息管理能力。 10 11**图1** 用户认证功能整体框架 12 13 14 15### 基本概念 16用户认证框架与各个基础认证服务(包含口令认证、人脸识别等)组成的身份认证系统,支持用户认证凭据设置、删除、认证等基础功能。 17 18- 认证凭据信息 19 20 用户设置口令、录入人脸时,会生成认证凭据模板,凭据信息由用户身份信息与凭据模板信息组成,用于在认证用户时找到匹配指定用户的凭据模板。 21 22- 认证凭据模板 23 24 认证凭据模板在用户设置认证凭据时由认证服务产生并存储。每个模板有一个ID,用于索引模板信息文件。在认证时,读取模板信息并和当次认证过程中产生的认证数据做对比,完成身份认证。 25 26- 执行器 27 28 执行器是能够提供数据采集、处理、存储及比对能力的模块,各基础认证服务提供执行器能力,被身份认证框架调度完成各项基础功能。 29 30- 执行器角色 31 32 - 全功能执行器:执行器可独立处理凭据注册和身份认证请求,即可提供用户认证数据采集、处理、储存及比对能力。 33 34 - 采集器:执行器提供用户认证时的数据采集能力,需要和认证器配合完成用户认证。 35 36 - 认证器:认证器提供用户认证时的数据处理能力,读取存储凭据模板信息并完成比对。 37 38- 执行器类型 39 40 同一种身份认证类型的不同认证方式、设备器件差异都会产生认证算法差异,执行器根据这些差异定义不同的执行器类型。 41 42- 执行器安全等级 43 44 执行器提供能力时所在运行环境达到的安全级别。 45 46- 用户认证框架公钥 & 执行器公钥 47 48 用户身份认证处理需要保证用户数据安全以及认证结果的准确性,用户认证框架与基础认证服务间的关键交互信息需要做数据完整性保护,各基础认证服务将提供的执行器能力对接到用户认证框架时,需要交换各自的公钥,其中: 49 50 - 执行器通过用户认证框架公钥校验调度指令的准确性,如锁定一个人脸模板,这种情况导致无法使用人脸功能,属于敏感操作,需要确保指令准确,才可处理。 51 52 - 执行器公钥可被用户认证框架用于校验认证结果的准确性,同时用于执行器交互认证时的校验交互信息的完整性。 53 54 55- 认证结果可信等级 56 57 不同认证方式及认证过程运行环境的安全级别差异,使得生成的认证结果的可信级别不同。 58 59- 认证方案 60 61 用户发起认证请求所使用的认证方式、认证结果可信等级、执行器信息和凭据信息等相关信息。 62 63- 调度信息 64 65 包括执行器信息及执行器处理请求需要的凭据模板信息,用于用户认证框架调度执行器完成基础功能。 66 67- System Ability 68 69 系统能力,由系统服务管理服务(System Ability Manager)加载,向OpenHarmony系统提供系统基础能力的基础服务。 70 71- Kit 72 73 OpenHarmony系统向第三方应用提供的基础应用编程接口。 74 75- Inner API 76 77 OpenHarmony系统向系统应用提供的应用编程接口。 78 79- IDL接口 80 81 接口定义语言(Interface Definition Language),通过IDL编译器编译后,能够生成与编程语言相关的文件:客户端桩文件,服务器框架文件。本文主要是通过IDL接口生成的客户端和服务端来实现User_auth服务和驱动的通信,详细使用方法可参考[IDL简介](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md)。 82 83- IPC通信 84 85 IPC(Inter Process Communication),进程间通信是指两个进程的数据之间产生交互,详细原理可参考[IPC通信简介](https://gitee.com/openharmony/communication_ipc/blob/master/README_zh.md)。 86 87- HDI 88 89 HDI(Hardware Device Interface),硬件设备接口,位于基础系统服务层和设备驱动层之间,是提供给硬件系统服务开发者使用的、统一的硬件设备功能抽象接口,其目的是为系统服务屏蔽底层硬件设备差异,具体可参考[HDI规范](../../design/hdi-design-specifications.md)。 90 91### 运作机制 92 93User_auth驱动主要工作是屏蔽不同安全器件和安全环境的差异,通过统一的认证能力注册、录入、认证接口,向User_auth服务提供认证执行器管理、认证凭据管理和认证方案生成管理等能力。 94开发者可基于HDF框架对不同芯片进行各自驱动的开发及HDI层接口的调用。 95 96**图2** User_auth服务和User_auth驱动交互 97 98 99 100### 约束与限制 101 102User_auth驱动的实现需要在可信执行环境中实现,保证用户凭据信息的安全存储及用户身份认证结果的可信可靠。 103 104## 开发指导 105 106### 场景介绍 107 108User_auth驱动的主要工作是为User_auth服务提供稳定的用户凭据管理、认证会话管理以及执行器信息管理能力,保证设备上口令认证和生物识别功能可以正常运行。 109 110### 接口说明 111 112注:以下接口列举的为IDL接口描述生成的对应C++语言函数接口,接口声明见idl文件(/drivers/interface/user_auth)。 113在本文中,执行器注册、凭据录入、凭据删除、用户认证和用户识别相关的HDI接口如表1所示。 114 115**表1** 接口功能介绍 116 117| 接口名称 | 功能介绍 | 118| --------------------------- | --------------------------- | 119| Init() | 初始化缓存信息。 | 120| AddExecutor(const HdiExecutorRegisterInfo &info, uint64_t &index, std::vector<uint8_t> &publicKey, std::vector<uint64_t> &templateIds) |添加认证执行器,获得此认证能力。| 121| DeleteExecutor(uint64_t index) | 根据索引值index删除认证执行器。 | 122| OpenSession(int32_t userId, std::vector<uint8_t> &challenge) | 开启认证凭据管理Session。 | 123| CloseSession(int32_t userId) | 关闭认证凭据管理Session。 | 124| BeginEnrollment(const std::vector<uint8_t> &authToken, const HdiEnrollParam ¶m, HdiScheduleInfo &info) | 发起用户的认证凭据的录入,当录入类型为PIN码且当前用户已录入PIN码的情况下会更新PIN码。 | 125| UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> & scheduleResult, EnrollResultInfo &info)| 更新录入结果,完成此次录入。 | 126| CancelEnrollment(int32_t userId) | 取消此次录入。 | 127| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector<uint8_t> &authToken, CredentialInfo &info) | 根据credentialId删除凭据信息。 | 128| DeleteUser(int32_t userId, const std::vector<uint8_t> &authToken, std::vector<CredentialInfo> &deletedInfos, std::vector<uint8_t> &rootSecret) | 删除PIN码即在用户认证框架中删除用户。 | 129| EnforceDeleteUser(int32_t userId, std::vector<CredentialInfo> &deletedInfos) | 强制删除用户,当系统内此用户被删除时强制调用。 | 130| GetCredential(int32_t userId, int32_t authType, std::vector<CredentialInfo> &infos) | 查询用户某种认证类型下的凭据信息。 | 131| BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, std::vector<HdiScheduleInfo> &infos) | 发起认证,生成认证方案和调度信息。 | 132| UpdateAuthenticationResult(uint64_t contextId, const std::vector<uint8_t> & scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState)| 更新认证结果,进行此次认证方案结果的评估。 | 133| CancelAuthentication(uint64_t contextId) | 取消此次认证。 | 134| BeginIdentification(uint64_t contextId, int32_t authType, const std::vector<uint8_t> &challenge, uint32_t executorSensorHint, HdiScheduleInfo &scheduleInfo) | 发起识别,生成识别方案和调度信息。 | 135| UpdateIdentificationResult(uint64_t contextId, const std::vector<uint8_t> &scheduleResult, IdentifyResultInfo &info) | 更新识别结果,进行此次识别方案结果的评估。 | 136| CancelIdentification(uint64_t contextId) | 取消此次识别。 | 137| GetAuthTrustLevel(int32_t userId, int32_t authType, uint32_t &authTrustLevel) | 获取此用户当前认证类型的认证可信等级。 | 138| GetValidSolution(int32_t userId, const std::vector<int32_t> &authTypes, uint32_t authTrustLevel, std::vector<int32_t> &validTypes) | 筛选此用户当前认证可信等级下可用的认证方式。 | 139| GetAllUserInfo(std::vector<UserInfo> &userInfos) | 查询所有用户信息(不包含userId)。 | 140| GetUserInfo(int32_t userId, uint64_t &secureUid, int32_t &pinSubType, std::vector<EnrolledInfo> &infos) | 查询用户信息。 | 141| GetAllExtUserInfo(std::vector<ExtUserInfo> &userInfos) | 查询所有用户信息(包含userId)。 | 142| GetEnrolledState(int32_t userId, int32_t authType, HdiEnrolledState &enrolledState) | 查询录入信息。 | 143| CheckReuseUnlockResult(const ReuseUnlockParam& param, ReuseUnlockInfo& info) | 检查是否复用设备解锁结果。 | 144| SendMessage(uint64_t scheduleId, int32_t srcRole, const std::vector<uint8_t>& msg) | 向执行器发消息。 | 145| RegisterMessageCallback(const sptr<IMessageCallback>& messageCallback) | 注册执行器消息回调。 | 146| GetLocalScheduleFromMessage(const std::vector<uint8_t>& remoteDeviceId, const std::vector<uint8_t>& message, HdiScheduleInfo& scheduleInfo) | 获取本地执行器调度信息。 | 147| GetSignedExecutorInfo(const std::vector<int32_t>& authTypes, int32_t executorRole, const std::vector<uint8_t>& remoteDeviceId, std::vector<uint8_t>& signedExecutorInfo) | 获取签名后的执行器信息。 | 148 149### 开发步骤 150 151以Hi3516DV300平台为例,我们提供了User_auth驱动DEMO实例,以下是目录结构及各部分功能简介。 152 153```undefined 154// drivers/peripheral/user_auth 155├── BUILD.gn # 编译脚本 156├── bundle.json # 组件描述文件 157└── hdi_service # User_auth驱动实现 158 ├── BUILD.gn # 编译脚本 159 ├── module # 功能实现 160 └── service 161 ├── user_auth_interface_driver.cpp # User_auth驱动入口 162 └── user_auth_interface_service.cpp # 获取执行器列表接口实现 163``` 164 165下面结合DEMO实例介绍驱动开发的具体步骤。 166 1671. 基于HDF驱动框架,按照驱动Driver Entry程序,完成User_auth驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现,详细代码参见[user_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_driver.cpp)文件。 168 169 ```c++ 170 // 通过自定义的HdfUserAuthInterfaceHost对象包含IoService对象和真正的HDI Service实现IRemoteObject对象 171 struct HdfUserAuthInterfaceHost { 172 struct IDeviceIoService ioService; 173 OHOS::sptr<OHOS::IRemoteObject> stub; 174 }; 175 176 // 服务接口调用响应接口 177 static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, 178 struct HdfSBuf *reply) 179 { 180 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService); 181 182 OHOS::MessageParcel *dataParcel = nullptr; 183 OHOS::MessageParcel *replyParcel = nullptr; 184 OHOS::MessageOption option; 185 186 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 187 HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 188 return HDF_ERR_INVALID_PARAM; 189 } 190 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 191 HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 192 return HDF_ERR_INVALID_PARAM; 193 } 194 195 return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 196 } 197 198 // 初始化接口 199 int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 200 { 201 HDF_LOGI("HdfUserAuthInterfaceDriverInit enter"); 202 OHOS::UserIAM::Common::Init(); 203 return HDF_SUCCESS; 204 } 205 206 // User_auth驱动对外提供的服务绑定到HDF框架 207 int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 208 { 209 HDF_LOGI("HdfUserAuthInterfaceDriverBind enter"); 210 211 auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost; 212 if (hdfUserAuthInterfaceHost == nullptr) { 213 HDF_LOGE("%{public}s: failed to create HdfUserAuthInterfaceHost object", __func__); 214 return HDF_FAILURE; 215 } 216 217 hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch; 218 hdfUserAuthInterfaceHost->ioService.Open = NULL; 219 hdfUserAuthInterfaceHost->ioService.Release = NULL; 220 221 auto serviceImpl = IUserAuthInterface::Get(true); 222 if (serviceImpl == nullptr) { 223 HDF_LOGE("%{public}s: failed to implement service", __func__); 224 return HDF_FAILURE; 225 } 226 227 hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 228 IUserAuthInterface::GetDescriptor()); 229 if (hdfUserAuthInterfaceHost->stub == nullptr) { 230 HDF_LOGE("%{public}s: failed to get stub object", __func__); 231 return HDF_FAILURE; 232 } 233 234 deviceObject->service = &hdfUserAuthInterfaceHost->ioService; 235 return HDF_SUCCESS; 236 } 237 238 // 释放User_auth驱动中的资源 239 void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){ 240 HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter"); 241 auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService); 242 delete hdfUserAuthInterfaceHost; 243 } 244 245 // 注册User_auth驱动入口数据结构体对象 246 struct HdfDriverEntry g_userAuthInterfaceDriverEntry = { 247 .moduleVersion = 1, 248 .moduleName = "user_auth_device_driver", 249 .Bind = HdfUserAuthInterfaceDriverBind, 250 .Init = HdfUserAuthInterfaceDriverInit, 251 .Release = HdfUserAuthInterfaceDriverRelease, 252 }; 253 254 // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 255 #ifndef __cplusplus 256 extern "C" { 257 #endif 258 HDF_INIT(g_userAuthInterfaceDriverEntry); 259 #ifndef __cplusplus 260 } 261 #endif 262 ``` 263 2642. 执行器注册接口举例实现,详细代码参见[user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp)文件。 265 266 ```c++ 267 // 添加执行器 268 int32_t UserAuthInterfaceService::AddExecutor(const HdiExecutorRegisterInfo &info, uint64_t &index, 269 std::vector<uint8_t> &publicKey, std::vector<uint64_t> &templateIds) 270 { 271 GlobalLock(); 272 ExecutorInfoHal executorInfoHal; 273 CopyExecutorInfo(info, executorInfoHal); 274 int32_t ret = RegisterExecutor(&executorInfoHal, &index); 275 GlobalUnLock(); 276 return ret; 277 } 278 279 // 删除执行器 280 int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index) 281 { 282 return UnRegisterExecutor(index); 283 } 284 ``` 285 2863. 录入接口举例实现,详细代码参见[user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp)文件。 287 288 ```c++ 289 // 开启认证凭据管理会话 290 int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector<uint8_t>& challenge) 291 { 292 GlobalLock(); 293 uint64_t challengeU64 = 0; 294 int32_t ret = OpenEditSession(userId, &challengeU64); 295 challenge.resize(sizeof(uint64_t)); 296 if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) { 297 IAM_LOGE("failed to copy challengeU64"); 298 return RESULT_BAD_COPY; 299 } 300 GlobalUnLock(); 301 return ret; 302 } 303 304 // 关闭认证凭据管理会话 305 int32_t UserAuthInterfaceService::CloseSession(int32_t userId) 306 { 307 GlobalLock(); 308 int32_t ret = CloseEditSession(); 309 GlobalUnLock(); 310 return ret; 311 } 312 313 // 发起录入,生成录入调度信息 314 int32_t UserAuthInterfaceService::BeginEnrollment( 315 const std::vector<uint8_t> &authToken, const HdiEnrollParam ¶m, HdiScheduleInfo &info) 316 { 317 IAM_LOGI("start"); 318 GlobalLock(); 319 if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) { 320 IAM_LOGE("authToken len is invalid"); 321 GlobalUnLock(); 322 return RESULT_BAD_PARAM; 323 } 324 PermissionCheckParam checkParam; 325 if (authToken.size() == sizeof(UserAuthTokenHal) && 326 memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) { 327 GlobalUnLock(); 328 return RESULT_BAD_COPY; 329 } 330 checkParam.authType = param.authType; 331 checkParam.userId = userId; 332 checkParam.authSubType = (uint64_t)param.executorType; 333 CoAuthSchedule scheduleInfo; 334 int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId); 335 if (ret != RESULT_SUCCESS) { 336 IAM_LOGE("Failed to check permission"); 337 GlobalUnLock(); 338 return ret; 339 } 340 ret = GetCoAuthSchedule(&scheduleInfo); 341 if (ret != RESULT_SUCCESS) { 342 IAM_LOGE("Failed to get schedule info"); 343 GlobalUnLock(); 344 return ret; 345 } 346 if (!CopyScheduleInfo(&scheduleInfo, &info)) { 347 IAM_LOGE("Failed to copy schedule info"); 348 ret = RESULT_BAD_COPY; 349 } 350 GlobalUnLock(); 351 return ret; 352 } 353 354 // 取消录入接口实现 355 int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId) 356 { 357 IAM_LOGI("start"); 358 BreakOffCoauthSchedule(userId); 359 return RESULT_SUCCESS; 360 } 361 362 // 录入凭据信息存储接口实现 363 int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector<uint8_t> &scheduleResult, EnrollResultInfo &info) 364 { 365 IAM_LOGI("start"); 366 GlobalLock(); 367 if (scheduleResult.size() == 0) { 368 IAM_LOGE("enrollToken is invalid"); 369 GlobalUnLock(); 370 return RESULT_BAD_PARAM; 371 } 372 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 373 if (scheduleResultBuffer == nullptr) { 374 IAM_LOGE("scheduleTokenBuffer is null"); 375 GlobalUnLock(); 376 return RESULT_NO_MEMORY; 377 } 378 bool isUpdate; 379 int32_t ret = GetIsUpdate(&isUpdate); 380 if (ret != RESULT_SUCCESS) { 381 IAM_LOGE("Failed to get isUpdate"); 382 return ret; 383 } 384 if (isUpdate) { 385 CredentialInfoHal oldCredentialHal; 386 ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal); 387 oldInfo.authType = static_cast<AuthType>(oldCredentialHal.authType); 388 oldInfo.credentialId = oldCredentialHal.credentialId; 389 oldInfo.templateId = oldCredentialHal.templateId; 390 oldInfo.executorType = static_cast<uint32_t>(oldCredentialHal.authSubType); 391 oldInfo.executorId = 0; 392 oldInfo.index = 0; 393 } else { 394 ret = AddCredentialFunc(scheduleResultBuffer, &credentialId); 395 } 396 DestoryBuffer(scheduleResultBuffer); 397 GlobalUnLock(); 398 return ret; 399 } 400 ``` 401 4024. 认证接口举例实现,详细代码参见[user_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/user_auth/hdi_service/service/user_auth_interface_service.cpp)文件。 403 404 ```c++ 405 // 创建HDI服务对象 406 extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void) 407 { 408 auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService(); 409 if (userAuthInterfaceService == nullptr) { 410 IAM_LOGE("userAuthInterfaceService is nullptr"); 411 return nullptr; 412 } 413 return userAuthInterfaceService; 414 } 415 416 // 发起认证,生成认证方案和调度信息 417 int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const HdiAuthParam ¶m, 418 std::vector<HdiScheduleInfo> &infos) 419 { 420 IAM_LOGI("start"); 421 if (param.challenge.size() != sizeof(uint64_t)) { 422 IAM_LOGE("Failed to copy challenge"); 423 return RESULT_BAD_PARAM; 424 } 425 GlobalLock(); 426 CoAuthSchedule *schedulesGet = nullptr; 427 uint32_t scheduleIdNum = 0; 428 AuthSolutionHal solutionIn; 429 solutionIn.contextId = contextId; 430 solutionIn.userId = param.userId; 431 solutionIn.authType = static_cast<uint32_t>(param.authType); 432 solutionIn.authTrustLevel = param.authTrustLevel; 433 if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), ¶m.challenge[0], 434 param.challenge.size()) != EOK) { 435 IAM_LOGE("Failed to copy challenge"); 436 GlobalUnLock(); 437 return RESULT_BAD_COPY; 438 } 439 int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum); 440 if (ret != RESULT_SUCCESS) { 441 IAM_LOGE("Failed to generate solution"); 442 GlobalUnLock(); 443 return ret; 444 } 445 for (uint32_t i = 0; i < scheduleIdNum; i++) { 446 ScheduleInfoV1_1 temp; 447 if (!CopyScheduleInfo(schedulesGet + i, &temp)) { 448 infos.clear(); 449 ret = RESULT_GENERAL_ERROR; 450 break; 451 } 452 infos.push_back(temp); 453 } 454 free(schedulesGet); 455 GlobalUnLock(); 456 return ret; 457 } 458 459 // 更新认证结果,进行此次认证方案结果的评估 460 int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId, 461 const std::vector<uint8_t> &scheduleResult, HdiAuthResultInfo &info, HdiEnrolledState &enrolledState) 462 { 463 IAM_LOGI("start"); 464 GlobalLock(); 465 if (scheduleResult.size() == 0) { 466 IAM_LOGE("param is invalid"); 467 info.result = RESULT_BAD_PARAM; 468 GlobalUnLock(); 469 return RESULT_BAD_PARAM; 470 } 471 Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); 472 if (scheduleResultBuffer == nullptr) { 473 IAM_LOGE("scheduleTokenBuffer is null"); 474 info.result = RESULT_GENERAL_ERROR; 475 GlobalUnLock(); 476 return RESULT_NO_MEMORY; 477 } 478 UserAuthTokenHal authTokenHal; 479 info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal); 480 if (info.result != RESULT_SUCCESS) { 481 IAM_LOGE("Failed to execute func"); 482 DestoryBuffer(scheduleResultBuffer); 483 GlobalUnLock(); 484 return info.result; 485 } 486 info.token.resize(sizeof(UserAuthTokenHal)); 487 if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) { 488 IAM_LOGE("Failed to copy authToken"); 489 DestoryBuffer(scheduleResultBuffer); 490 GlobalUnLock(); 491 return RESULT_BAD_COPY; 492 } 493 DestoryBuffer(scheduleResultBuffer); 494 GlobalUnLock(); 495 return RESULT_SUCCESS; 496 } 497 498 // 取消认证 499 int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId) 500 { 501 IAM_LOGI("start"); 502 GlobalLock(); 503 uint32_t scheduleIdNum = 0; 504 int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum); 505 if (ret != RESULT_SUCCESS) { 506 IAM_LOGE("Failed to execute func"); 507 GlobalUnLock(); 508 return ret; 509 } 510 GlobalUnLock(); 511 return RESULT_SUCCESS; 512 } 513 ``` 514 515### 调测验证 516 517驱动开发完成后,通过[用户认证API接口](../../application-dev/reference/apis-user-authentication-kit/js-apis-useriam-userauth.md)开发HAP应用,基于RK3568平台验证。 518 5191.发起认证并获取认证结果的测试代码如下: 520 521```ts 522 // API version 10 523 import type {BusinessError} from '@ohos.base'; 524 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 525 526 // 设置认证参数 527 const authParam: userIAM_userAuth.AuthParam = { 528 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 529 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 530 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 531 }; 532 // 配置认证界面 533 const widgetParam: userIAM_userAuth.WidgetParam = { 534 title: '请进行身份认证', 535 }; 536 try { 537 // 获取认证对象 538 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 539 console.info('get userAuth instance success'); 540 // 订阅认证结果 541 userAuthInstance.on('result', { 542 onResult(result) { 543 console.info(`userAuthInstance callback result: ${JSON.stringify(result)}`); 544 // 可在认证结束或其他业务需要场景,取消订阅认证结果 545 userAuthInstance.off('result'); 546 } 547 }); 548 console.info('auth on success'); 549 userAuthInstance.start(); 550 console.info('auth start success'); 551 } catch (error) { 552 const err: BusinessError = error as BusinessError; 553 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 554 } 555``` 556 5572.取消认证的测试代码如下: 558 559```ts 560 // API version 10 561 import type {BusinessError} from '@ohos.base'; 562 import userIAM_userAuth from '@ohos.userIAM.userAuth'; 563 564 const authParam: userIAM_userAuth.AuthParam = { 565 challenge: new Uint8Array([49, 49, 49, 49, 49, 49]), 566 authType: [userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.UserAuthType.FACE], 567 authTrustLevel: userIAM_userAuth.AuthTrustLevel.ATL3, 568 }; 569 const widgetParam: userIAM_userAuth.WidgetParam = { 570 title: '请进行身份认证', 571 }; 572 try { 573 // 获取认证对象 574 let userAuthInstance = userIAM_userAuth.getUserAuthInstance(authParam, widgetParam); 575 console.info('get userAuth instance success'); 576 // 开始认证 577 userAuthInstance.start(); 578 console.info('auth start success'); 579 // 取消认证 580 userAuthInstance.cancel(); 581 console.info('auth cancel success'); 582 } catch (error) { 583 const err: BusinessError = error as BusinessError; 584 console.error(`auth catch error. Code is ${err?.code}, message is ${err?.message}`); 585 } 586``` 587