1# Pin_auth 2 3## 概述 4 5### 功能简介 6 7口令认证是端侧设备不可或缺的一部分,为设备提供一种用户认证能力,可应用于设备解锁、支付、应用登录等身份认证场景。用户注册口令后,口令认证模块就可为设备提供密码解锁的功能,保证设备的安全使用。口令识别的整体架构如图1。 8 9基于HDF(Hardware Driver Foundation)驱动框架开发的Pin_auth驱动,Pin_auth驱动模型屏蔽硬件差异,为上层用户IAM子系统基础框架和口令认证SA提供稳定的口令认证基础能力,包括口令认证执行器列表查询、执行器信息查询、指定模板防暴信息查询、用户认证和执行器间的模板信息对账,以及口令的录入、认证、删除。 10 11**图1** 口令认证架构图 12 13 14 15### 基本概念 16用户认证框架与各个基础认证服务(包含口令认证、人脸识别等)组成的身份认证系统,支持用户认证凭据设置、删除、认证等基础功能。 17 18- 执行器 19 20 执行器是能够提供数据采集、处理、存储及比对能力的模块,各基础认证服务提供执行器能力,被身份认证框架调度完成各项基础能力。 21 22- 执行器安全等级 23 24 执行器提供能力时所在运行环境达到的安全级别。 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 认证凭据是在用户设置认证凭据时由认证服务产生并存储,每个模板有一个ID,用于索引模板信息文件,在认证时读取模板信息并用于与当次认证过程中产生的认证数据做对比,完成身份认证。 50 51- 执行器对账 52 53 用户认证框架统一管理用户身份和凭据ID的映射关系,执行器对接到用户认证框架时,会读取用户身份认证框架内保存的该执行器的模板ID列表,执行器需要与自己维护的模板ID列表进行比对,并删除冗余信息。 54 55- IDL接口 56 57 接口定义语言(Interface Definition Language)通过IDL编译器编译后,能够生成与编程语言相关的文件:客户端桩文件,服务器框架文件。本文主要是通过IDL接口生成的客户端和服务端来实现Pin_auth服务和驱动的通信,详细使用方法可参考[IDL简介](https://gitee.com/openharmony/ability_idl_tool/blob/master/README.md)。 58 59- IPC通信 60 61 IPC(Inter Process Communication),进程间通信是指两个进程的数据之间产生交互,详细原理可参考[IPC通信简介](https://gitee.com/openharmony/communication_ipc/blob/master/README_zh.md)。 62 63- HDI 64 65 HDI(Hardware Device Interface),硬件设备接口,位于基础系统服务层和设备驱动层之间,是提供给硬件系统服务开发者使用的、统一的硬件设备功能抽象接口,其目的是为系统服务屏蔽底层硬件设备差异,具体可参考[HDI规范](../../design/hdi-design-specifications.md)。 66 67### 运作机制 68 69Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提供稳定的口令认证的基础能力,保证口令认证的功能可以正常运行。开发者可基于HDF框架对不同芯片进行各自驱动的开发以及HDI层接口的调用。 70 71**图2** Pin_auth服务和pin_auth驱动接口 72 73 74 75### 约束与限制 76口令认证的实现需要在TEE安全环境中实现,口令凭据等数据的加密信息需要在安全环境中存储。 77## 开发指导 78 79### 场景介绍 80Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提供稳定的口令认证基础能力,保证设备上口令认证功能可以正常运行。 81 82### 接口说明 83 84注:以下接口列举的为IDL接口描述生成的对应C++语言函数接口,接口声明见idl文件(/drivers/interface/pin_auth)。 85在本文中,口令凭据的录入、认证和删除相关的HDI接口如表1所示,表2中的回调函数分别用于口令执行器返回操作结果给框架和获取用户输入的口令信息。 86 87**表1** 接口功能介绍 88 89| 接口名称 | 功能介绍 | 90| ------------------------------- | ------------------------------------------- | 91| GetExecutorList(std::vector\<sptr\<V1_0::IExecutor>>& executorList) | 获取V1_0执行器列表。 | 92| GetExecutorListV1_1(std::vector\<sptr\<V1_1::IExecutor>>& executorList) | 获取V1_1版本执行器列表。 | 93| GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | 获取指定templateId的模板信息。 | 94| OnRegisterFinish(const std::vector\<uint64_t>& templateIdList,<br/>const std::vector\<uint8_t>& frameworkPublicKey,<br/>const std::vector\<uint8_t>& extraInfo) | 执行器注册成功后,获取用户认证框架的公钥信息;获取用户认证框架的template 列表用于对账。 | 95| OnSetData(uint64_t scheduleId, uint64_t authSubType, <br/>const std::vector\<uint8_t> &data) | 回调函数,返回用户录入的口令子类型和录入的口令脱敏数据。 | 96| Enroll(uint64_t scheduleId, const std::vector\<uint8_t>& extraInfo,<br/>const sptr\<IExecutorCallback>& callbackObj) | 录入pin码。 | 97| Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector\<uint8_t>& extraInfo, const sptr\<IExecutorCallback>& callbackObj) | pin码认证。 | 98| Delete(uint64_t templateId) | 删除pin码模板。 | 99| Cancel(uint64_t scheduleId) | 通过scheduleId取消指定操作。 | 100| SendCommand(int32_t commandId, const std::vector\<uint8_t>& extraInfo,<br/>const sptr\<IExecutorCallback>& callbackObj) | 预留接口。 | 101| GetProperty(const std::vector\<uint64_t>& templateIdList,<br/>const std::vector\<GetPropertyType>& propertyTypes, Property& property) | 获取执行器属性信息。 | 102 103 104**表2** 回调函数介绍 105 106| 接口名称 | 功能介绍 | 107| ------------------------------------------------------------ | -------------------- | 108| IExecutorCallback::OnResult(int32_t code, const std::vector\<uint8_t>& extraInfo) | 返回操作的最终结果。 | 109| IExecutorCallback::OnGetData(uint64_t scheduleId, const std::vector\<uint8_t>& salt,<br/> uint64_t authSubType)| 返回获取pin码数据信息。 | 110 111### 开发步骤 112 113以RK3568平台为例,我们提供了Pin_auth驱动DEMO实例,以下是目录结构及各部分功能简介。 114 115```text 116// drivers/peripheral/pin_auth 117├── BUILD.gn # 编译脚本 118├── bundle.json # 组件描述文件 119├── test # 测试用例 120└── hdi_service # Pin_auth驱动实现 121 ├── BUILD.gn # 编译脚本 122 ├── adaptor # 相关算法实现 123 ├── common # 公共接口实现 124 ├── database # 数据库实现 125 ├── main # 口令相关功能实现入口 126 └── service # Pin_auth驱动实现入口 127 ├── inc # 头文件 128 └── src # 源文件 129 ├── executor_impl.cpp # 认证、录入等功能接口实现 130 ├── pin_auth_interface_driver.cpp # Pin_auth驱动入口 131 └── pin_auth_interface_service.cpp # 获取执行器列表接口实现 132``` 133 134下面结合DEMO实例介绍驱动开发的具体步骤。 135 1361. 基于HDF驱动框架,按照驱动Driver Entry程序,完成pin_auth驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现,详细代码参见[pin_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/pin_auth_interface_driver.cpp)文件。 137 138 ```c++ 139 // 通过自定义的HdfPinAuthInterfaceHost对象包含IoService对象和真正的HDI Service实现PinAuthInterfaceService对象 140 struct HdfPinAuthInterfaceHost { 141 struct IDeviceIoService ioService; 142 OHOS::sptr<OHOS::IRemoteObject> stub; 143 }; 144 145 // 服务接口调用响应接口 146 static int32_t PinAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) 147 { 148 IAM_LOGI("start"); 149 auto *hdfPinAuthInterfaceHost = CONTAINER_OF(client->device->service, 150 struct HdfPinAuthInterfaceHost, ioService); 151 152 OHOS::MessageParcel *dataParcel = nullptr; 153 OHOS::MessageParcel *replyParcel = nullptr; 154 OHOS::MessageOption option; 155 156 if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { 157 IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); 158 return HDF_ERR_INVALID_PARAM; 159 } 160 if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { 161 IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); 162 return HDF_ERR_INVALID_PARAM; 163 } 164 165 return hdfPinAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); 166 } 167 168 // 初始化接口 169 static int HdfPinAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) 170 { 171 IAM_LOGI("start"); 172 std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi = 173 OHOS::UserIAM::Common::MakeShared<OHOS::UserIAM::PinAuth::PinAuth>(); 174 constexpr uint32_t SUCCESS = 0; 175 if (pinHdi == nullptr || pinHdi->Init() != SUCCESS) { 176 IAM_LOGE("Pin hal init failed"); 177 return HDF_FAILURE; 178 } 179 return HDF_SUCCESS; 180 } 181 182 // PinAuth驱动对外提供的服务绑定到HDF框架 183 static int HdfPinAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) 184 { 185 IAM_LOGI("start"); 186 auto *hdfPinAuthInterfaceHost = new (std::nothrow) HdfPinAuthInterfaceHost; 187 if (hdfPinAuthInterfaceHost == nullptr) { 188 IAM_LOGE("%{public}s: failed to create create HdfPinAuthInterfaceHost object", __func__); 189 return HDF_FAILURE; 190 } 191 192 hdfPinAuthInterfaceHost->ioService.Dispatch = PinAuthInterfaceDriverDispatch; 193 hdfPinAuthInterfaceHost->ioService.Open = NULL; 194 hdfPinAuthInterfaceHost->ioService.Release = NULL; 195 196 auto serviceImpl = IPinAuthInterface::Get(true); 197 if (serviceImpl == nullptr) { 198 IAM_LOGE("%{public}s: failed to get of implement service", __func__); 199 return HDF_FAILURE; 200 } 201 202 hdfPinAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, 203 IPinAuthInterface::GetDescriptor()); 204 if (hdfPinAuthInterfaceHost->stub == nullptr) { 205 IAM_LOGE("%{public}s: failed to get stub object", __func__); 206 return HDF_FAILURE; 207 } 208 209 deviceObject->service = &hdfPinAuthInterfaceHost->ioService; 210 IAM_LOGI("success"); 211 return HDF_SUCCESS; 212 } 213 214 // 释放PinAuth驱动中的资源 215 static void HdfPinAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) 216 { 217 IAM_LOGI("start"); 218 auto *hdfPinAuthInterfaceHost = CONTAINER_OF(deviceObject->service, 219 struct HdfPinAuthInterfaceHost, ioService); 220 delete hdfPinAuthInterfaceHost; 221 IAM_LOGI("success"); 222 } 223 224 static struct HdfDriverEntry g_pinAuthInterfaceDriverEntry = { 225 .moduleVersion = 1, 226 .moduleName = "pinauth_interface_service", 227 .Bind = HdfPinAuthInterfaceDriverBind, 228 .Init = HdfPinAuthInterfaceDriverInit, 229 .Release = HdfPinAuthInterfaceDriverRelease, 230 }; 231 232 // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 233 HDF_INIT(g_pinauthinterfaceDriverEntry); 234 ``` 235 236 237 2381. 完成获取执行器列表接口实现,详细代码参见[pin_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/pin_auth_interface_service.cpp)文件。 239 240 ```c++ 241 // 执行器实现类 242 class ExecutorImpl : public V1_1::IExecutor, public NoCopyable { 243 public: 244 explicit ExecutorImpl(std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi); 245 virtual ~ExecutorImpl() {} 246 int32_t GetExecutorInfo(ExecutorInfo &info) override; 247 int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo &info) override; 248 int32_t OnRegisterFinish(const std::vector<uint64_t> &templateIdList, 249 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) override; 250 int32_t OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data) override; 251 int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, 252 const sptr<IExecutorCallback> &callbackObj) override; 253 int32_t Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo, 254 const sptr<IExecutorCallback> &callbackObj) override; 255 int32_t Delete(uint64_t templateId) override; 256 int32_t Cancel(uint64_t scheduleId) override; 257 int32_t SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo, 258 const sptr<IExecutorCallback> &callbackObj) override; 259 int32_t GetProperty(const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, 260 Property &property) override; 261 262 private: 263 class ScheduleMap { 264 public: 265 uint32_t AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId, 266 const sptr<IExecutorCallback> callback, const uint64_t templateId, const std::vector<uint8_t> salt); 267 uint32_t GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId, sptr<IExecutorCallback> &callback, 268 uint64_t &templateId, std::vector<uint8_t> &salt); 269 uint32_t DeleteScheduleId(const uint64_t scheduleId); 270 271 private: 272 struct ScheduleInfo { 273 uint32_t commandId; 274 sptr<IExecutorCallback> callback; 275 uint64_t templateId; 276 std::vector<uint8_t> salt; 277 }; 278 279 std::mutex mutex_; 280 std::map<uint64_t, struct ScheduleInfo> scheduleInfo_; 281 }; 282 283 private: 284 uint32_t NewSalt(std::vector<uint8_t> &salt); 285 void CallError(const sptr<IExecutorCallback> &callbackObj, const uint32_t errorCode); 286 std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi_; 287 ScheduleMap scheduleMap_; 288 }; 289 290 // 获取V1_1执行器列表实现,创建执行器(仅作示例) 291 int32_t PinAuthInterfaceService::GetExecutorListV1_1(std::vector<sptr<V1_1::IExecutor>> &executorList) 292 { 293 IAM_LOGI("start"); 294 std::shared_ptr<OHOS::UserIAM::PinAuth::PinAuth> pinHdi = 295 OHOS::UserIAM::Common::MakeShared<OHOS::UserIAM::PinAuth::PinAuth>(); 296 if (pinHdi == nullptr) { 297 IAM_LOGE("Generate pinHdi failed"); 298 return HDF_FAILURE; 299 } 300 sptr<IExecutor> executor = new (std::nothrow) ExecutorImpl(pinHdi); 301 if (executor == nullptr) { 302 IAM_LOGE("Generate executor failed"); 303 return HDF_FAILURE; 304 } 305 executorList.push_back(executor); 306 IAM_LOGI("end"); 307 return HDF_SUCCESS; 308 } 309 310 // 获取V1_0执行器列表实现,使用V1_1版本执行器实现V1_0版本执行器的功能 311 int32_t PinAuthInterfaceService::GetExecutorList(std::vector<sptr<V1_0::IExecutor>> &executorList) 312 { 313 std::vector<sptr<V1_1::IExecutor>> executorListV1_1; 314 int32_t result = GetExecutorListV1_1(executorListV1_1); 315 for (auto &executor : executorListV1_1) { 316 executorList.push_back(executor); 317 } 318 return result; 319 } 320 ``` 321 322 323 3241. 完成执行器每个功能接口实现,详细代码参见[executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/service/src/executor_impl.cpp)文件。 325 326 ```c++ 327 // 实现获取执行器信息接口(仅作示例) 328 int32_t ExecutorImpl::GetExecutorInfo(ExecutorInfo &info) 329 { 330 IAM_LOGI("start"); 331 constexpr unsigned short SENSOR_ID = 1; 332 info.sensorId = SENSOR_ID; 333 info.executorType = EXECUTOR_TYPE; 334 info.executorRole = ExecutorRole::ALL_IN_ONE; 335 info.authType = AuthType::PIN; 336 if (pinHdi_ == nullptr) { 337 IAM_LOGE("pinHdi_ is nullptr"); 338 return HDF_FAILURE; 339 } 340 uint32_t eslRet = 0; 341 int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet); 342 if (result != SUCCESS) { 343 IAM_LOGE("Get ExecutorInfo failed, fail code : %{public}d", result); 344 return result; 345 } 346 info.esl = static_cast<ExecutorSecureLevel>(eslRet); 347 348 return HDF_SUCCESS; 349 } 350 351 // 实现获取指定templateId的模板信息接口 352 int32_t ExecutorImpl::GetTemplateInfo(uint64_t templateId, TemplateInfo &info) 353 { 354 IAM_LOGI("start"); 355 if (pinHdi_ == nullptr) { 356 IAM_LOGE("pinHdi_ is nullptr"); 357 return HDF_FAILURE; 358 } 359 OHOS::UserIAM::PinAuth::PinCredentialInfo infoRet = {}; 360 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet); 361 if (result != SUCCESS) { 362 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result); 363 return result; 364 } 365 /* subType is stored in extraInfo */ 366 info.extraInfo.resize(infoRet.subType); 367 if (memcpy_s(&(info.extraInfo[0]), sizeof(infoRet.subType), &(infoRet.subType), sizeof(infoRet.subType)) != EOK) { 368 IAM_LOGE("copy subType to extraInfo fail!"); 369 return HDF_FAILURE; 370 } 371 372 info.executorType = EXECUTOR_TYPE; 373 info.remainAttempts = infoRet.remainTimes; 374 info.lockoutDuration = infoRet.freezingTime; 375 376 return HDF_SUCCESS; 377 } 378 379 // 实现执行器注册成功后,获取用户认证框架的公钥信息、获取用户认证框架的template 列表接口,将公钥信息保存,template列表用于和本地的template做对账 380 int32_t ExecutorImpl::OnRegisterFinish(const std::vector<uint64_t> &templateIdList, 381 const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo) 382 { 383 IAM_LOGI("start"); 384 static_cast<void>(frameworkPublicKey); 385 static_cast<void>(extraInfo); 386 if (pinHdi_ == nullptr) { 387 IAM_LOGE("pinHdi_ is nullptr"); 388 return HDF_FAILURE; 389 } 390 int32_t result = pinHdi_->VerifyTemplateData(templateIdList); 391 if (result != SUCCESS) { 392 IAM_LOGE("Verify templateData failed"); 393 return result; 394 } 395 396 return HDF_SUCCESS; 397 } 398 399 // 实现口令录入接口 400 int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector<uint8_t> &extraInfo, 401 const sptr<IExecutorCallback> &callbackObj) 402 { 403 IAM_LOGI("start"); 404 if (callbackObj == nullptr) { 405 IAM_LOGE("callbackObj is nullptr"); 406 return HDF_FAILURE; 407 } 408 static_cast<void>(extraInfo); 409 std::vector<uint8_t> salt; 410 if (NewSalt(salt) != HDF_SUCCESS) { 411 IAM_LOGE("new salt failed"); 412 CallError(callbackObj, HDF_FAILURE); 413 return HDF_FAILURE; 414 } 415 int32_t result = scheduleMap_.AddScheduleInfo(scheduleId, ENROLL_PIN, callbackObj, 0, salt); 416 if (result != HDF_SUCCESS) { 417 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result); 418 CallError(callbackObj, HDF_FAILURE); 419 return result; 420 } 421 result = callbackObj->OnGetData(scheduleId, salt, 0); 422 if (result != SUCCESS) { 423 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result); 424 // If the enroll fails, delete scheduleId of scheduleMap 425 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { 426 IAM_LOGI("delete scheduleId failed"); 427 } 428 return result; 429 } 430 431 return HDF_SUCCESS; 432 } 433 434 // 实现回调数据获取的接口 435 int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector<uint8_t> &data) 436 { 437 IAM_LOGI("start"); 438 if (pinHdi_ == nullptr) { 439 IAM_LOGE("pinHdi_ is nullptr"); 440 return HDF_FAILURE; 441 } 442 std::vector<uint8_t> resultTlv; 443 int32_t result = SUCCESS; 444 constexpr uint32_t INVALID_ID = 2; 445 uint32_t commandId = INVALID_ID; 446 sptr<IExecutorCallback> callback = nullptr; 447 uint64_t templateId = 0; 448 std::vector<uint8_t> salt(0, 0); 449 if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, salt) != HDF_SUCCESS) { 450 IAM_LOGE("Get ScheduleInfo failed, fail code : %{public}d", result); 451 return HDF_FAILURE; 452 } 453 switch (commandId) { 454 case ENROLL_PIN: 455 result = pinHdi_->EnrollPin(scheduleId, authSubType, salt, data, resultTlv); 456 if (result != SUCCESS) { 457 IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result); 458 } 459 break; 460 case AUTH_PIN: 461 result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv); 462 if (result != SUCCESS) { 463 IAM_LOGE("Auth Pin failed, fail code : %{public}d", result); 464 } 465 break; 466 default: 467 IAM_LOGE("Error commandId"); 468 } 469 470 if (callback->OnResult(result, resultTlv) != SUCCESS) { 471 IAM_LOGE("callbackObj Pin failed"); 472 } 473 // Delete scheduleId from the scheduleMap_ when the enroll and authentication are successful 474 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { 475 IAM_LOGI("delete scheduleId failed"); 476 } 477 478 return HDF_SUCCESS; 479 } 480 // 实现口令认证接口 481 int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t> &extraInfo, 482 const sptr<IExecutorCallback> &callbackObj) 483 { 484 IAM_LOGI("start"); 485 if (callbackObj == nullptr) { 486 IAM_LOGE("callbackObj is nullptr"); 487 return HDF_FAILURE; 488 } 489 if (pinHdi_ == nullptr) { 490 IAM_LOGE("pinHdi_ is nullptr"); 491 CallError(callbackObj, HDF_FAILURE); 492 return HDF_FAILURE; 493 } 494 static_cast<void>(extraInfo); 495 std::vector<uint8_t> salt; 496 int32_t result = pinHdi_->GetSalt(templateId, salt); 497 if (result != SUCCESS) { 498 IAM_LOGE("get salt failed, fail code : %{public}d", result); 499 CallError(callbackObj, HDF_FAILURE); 500 return result; 501 } 502 result = scheduleMap_.AddScheduleInfo(scheduleId, AUTH_PIN, callbackObj, templateId, salt); 503 if (result != HDF_SUCCESS) { 504 IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result); 505 CallError(callbackObj, HDF_FAILURE); 506 return result; 507 } 508 result = callbackObj->OnGetData(scheduleId, salt, 0); 509 if (result != SUCCESS) { 510 IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result); 511 // If the authentication fails, delete scheduleId of scheduleMap 512 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { 513 IAM_LOGI("delete scheduleId failed"); 514 } 515 return result; 516 } 517 518 return HDF_SUCCESS; 519 } 520 521 // 实现删除口令模板接口 522 int32_t ExecutorImpl::Delete(uint64_t templateId) 523 { 524 IAM_LOGI("start"); 525 if (pinHdi_ == nullptr) { 526 IAM_LOGE("pinHdi_ is nullptr"); 527 return HDF_FAILURE; 528 } 529 int32_t result = pinHdi_->DeleteTemplate(templateId); 530 if (result != SUCCESS) { 531 IAM_LOGE("Verify templateData failed, fail code : %{public}d", result); 532 return result; 533 } 534 535 return HDF_SUCCESS; 536 } 537 538 // 实现通过scheduleId取消指定操作接口 539 int32_t ExecutorImpl::Cancel(uint64_t scheduleId) 540 { 541 IAM_LOGI("start"); 542 if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { 543 IAM_LOGE("scheduleId is not found"); 544 return HDF_FAILURE; 545 } 546 return HDF_SUCCESS; 547 } 548 549 // 口令预留接口 550 int32_t ExecutorImpl::SendCommand(int32_t commandId, const std::vector<uint8_t> &extraInfo, 551 const sptr<IExecutorCallback> &callbackObj) 552 { 553 IAM_LOGI("Extension interface, temporarily useless"); 554 static_cast<void>(commandId); 555 static_cast<void>(extraInfo); 556 static_cast<void>(callbackObj); 557 return HDF_SUCCESS; 558 } 559 560 // 获取执行器属性信息接口 561 int32_t ExecutorImpl::GetProperty( 562 const std::vector<uint64_t> &templateIdList, const std::vector<GetPropertyType> &propertyTypes, Property &property) 563 { 564 IAM_LOGI("start"); 565 if (pinHdi_ == nullptr) { 566 IAM_LOGE("pinHdi_ is nullptr"); 567 return HDF_FAILURE; 568 } 569 570 if (templateIdList.size() != 1) { 571 IAM_LOGE("templateIdList size is not 1"); 572 return HDF_FAILURE; 573 } 574 575 uint64_t templateId = templateIdList[0]; 576 OHOS::UserIam::PinAuth::PinCredentialInfo infoRet = {}; 577 int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet); 578 if (result != SUCCESS) { 579 IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result); 580 return HDF_FAILURE; 581 } 582 583 property.authSubType = infoRet.subType; 584 property.remainAttempts = infoRet.remainTimes; 585 property.lockoutDuration = infoRet.freezingTime; 586 return HDF_SUCCESS; 587 } 588 ``` 589 590 591### 调测验证 592驱动开发完成后,可基于RK3568平台验证, 通过设备的设置和锁屏功能验证口令认证功能是否正常,测试步骤如下: 593 5941. 点击设备的 “ 设置 > 生物识别和密码 > 锁屏密码" 后,录入锁屏密码。 5952. 按设备电源键进行锁屏,再次按设备的电源键进行解锁,输入锁屏密码进行解锁验证,至此就完成了口令的录入和认证功能。 5963. 进入设置中的生物识别和密码,点击关闭锁屏密码或者更改锁屏密码,来验证口令的删除和更新功能是否正常。 5974. 在步骤1完成后,进行步骤2的输入锁屏密码时,输入错误密码达到一定的次数来验证,防暴力破解能力是否正常(例如:连续输入5次错误密码,设备将被冻结60s)。 598