From 089e564ecff18ec08c4b68213070e256a7cbb395 Mon Sep 17 00:00:00 2001 From: mtf Date: Tue, 3 May 2022 18:03:03 +0800 Subject: [PATCH] add pinauth driver Signed-off-by: mtf --- .../driver/driver-peripherals-pinauth-des.md | 565 ++++++++++++++++++ ...1\345\212\250\344\272\244\344\272\222.png" | Bin 0 -> 29822 bytes ...1\346\236\266\346\236\204\345\233\276.png" | Bin 0 -> 16633 bytes 3 files changed, 565 insertions(+) create mode 100644 zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md create mode 100644 "zh-cn/device-dev/driver/figures/pin_auth\346\234\215\345\212\241\344\270\216\351\251\261\345\212\250\344\272\244\344\272\222.png" create mode 100644 "zh-cn/device-dev/driver/figures/\345\217\243\344\273\244\350\256\244\350\257\201\346\236\266\346\236\204\345\233\276.png" diff --git a/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md b/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md new file mode 100644 index 0000000000..277b3d8a8a --- /dev/null +++ b/zh-cn/device-dev/driver/driver-peripherals-pinauth-des.md @@ -0,0 +1,565 @@ +# Pin_auth + +## 概述 + +### 功能简介 + +口令认证是端侧设备不可或缺的一部分,为设备提供一种用户认证能力,可应用于设备解锁、支付、应用登录等身份认证场景。用户注册口令后,口令认证模块就可为设备提供密码解锁的功能,保证设备的安全使用。口令识别的整体架构如图1。 + +基于HDF(Hardware Driver Foundation)驱动框架开发的pin_auth驱动,pin_auth驱动模型屏蔽硬件差异,为上层用户IAM子系统基础框架和口令认证SA提供稳定的口令认证基础能力,包括口令认证执行器列表查询、执行器信息查询、指定模板防暴信息查询、用户认证和执行器间的模板信息对账,以及口令的录入、认证、删除。 + +**图1** 口令认证架构图 + +![image](figures/口令认证架构图.png "口令认证架构图") + +### 基本概念 +用户认证框架与各个基础认证服务(包含口令认证、人脸识别等)组成的身份认证系统,支持用户认证凭据设置、删除、认证等基础功能。 + +- 执行器 + + 执行器是能够提供数据采集、处理、存储及比对能力的模块,各基础认证服务提供执行器能力,被身份认证框架调度完成各项基础能力。 + +- 执行器安全等级 + + 执行器提供能力时运行环境所达到的安全级别,如操作运行在无访问控制安全等级低于操作运行硬件可信执行 环境的安全等级。 + +- 执行器角色 + + - ​ 全功能执行器:执行器可独立处理一次凭据注册和身份认证请求,即可提供用户认证数据采集、处理、储存及比对能力。 + + - ​ 采集器:执行器提供用户认证时的数据采集能力,需要和认证期配合完成用户认证。 + + - ​ 认证器:认证器提供用户认证是时数据处理,读取存储凭据模板信息并完成比对。 + +- 执行器类型 + + 同一种身份认证类型的不同认证方式会产生认证算法差异,设备器件差异也会导致算法差异,执行器根据支持的算法类型差异或对接的器件差异,会定义不同的执行器类型。 + +- 用户认证框架公钥 & 执行器公钥 + + 用户身份认证处理需要保证用户数据安全以及认证结果的准确性,用户认证框架于基础认证服务间的关键交互信息需要做数据完整性保护,各基础认证服务将提供的执行器能力对接到用户认证框架时,需要交互各自的公钥,其中: + + - 执行器通过用户认证框架公钥校验调度指令的准确性,如锁定一个口令模板,这种情况导致无法使用口令认证功能,属于敏感操作,需要确保指令准确,才可处理。 + + - 执行器公钥可被用户认证框架用于校验认证结果的准确性,同时用于执行器交互认证时的校验交互信息的完整性。 + + +- 口令认证凭据模板 + + 认证凭据是在用户设置认证凭据时由认证服务产生并存储,每个模板有一个ID。用于索引模板信息文件,再认证时读取模板信息并用于与当次认证过程中产生的认证数据做对比,完成身份认证。 + +- 执行器对账 + + 用户认证框架统一管理用户身份和凭据ID的映射关系,执行器对接到用户认证框架时,会读取用户身份认证框架内保存的该执行器的模板ID列表,执行器需要与自己维护的模板ID列表进行比对,并删除冗余信息。 + +### 运作机制 + +Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提供稳定的口令认证的基础能力,保证口令认证的功能可以正常运行。开发者可基于HDF框架对不同芯片进行各自驱动的开发以及HDI层接口的调用。 + +**图1** Pin_auth服务和pin_auth驱动接口 + +![image](figures/pin_auth服务与驱动交互.png "pin_auth服务与驱动交互") + +### 约束与限制 +口令认证的实现需要在TEE安全环境中实现,口令凭据等数据的保密信息需要在安全环境中存储。 +## 开发指导 + +### 场景介绍 +Pin_auth驱动的主要工作是为上层用户认证框架和Pin_auth服务提供稳定的口令认证基础能力,保证设备上口令认证功能可以正常运行。 + +### 接口说明 + +**表1** 接口功能介绍 + +| 接口名 | 功能介绍 | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| GetExecutorList(std::vector>& executorList) | 获取执行器列表。 | +| GetExecutorInfo(ExecutorInfo& info) | 获取执行器信息。 | +| GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | 获取指定templateId的模板信息。 | +| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey,
const std::vector& extraInfo) | 执行器注册成功后,获取用户认证框架的公钥信息;获取用户认证框架的template 列表用于对账。 | +| OnSetData(uint64_t scheduleId, uint64_t authSubType,
const std::vector &data) | 用于回调传pin码认证的子类型和脱敏数据。 | +| Enroll(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | pin码录入操作。 | +| Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector& extraInfo, const sptr& callbackObj) | pin码认证操作。 | +| Delete(uint64_t templateId) | 删除pin码模板。 | +| Cancel(uint64_t scheduleId) | 通过scheduleId取消指定操作。 | +| SendCommand(int32_t commandId, const std::vector& extraInfo,
const sptr& callbackObj) | pin码预留接口。 | + +**表2** 回调函数介绍 + +| 接口名 | 功能介绍 | +| ------------------------------------------------------------ | -------------------- | +| IExecutorCallback::OnResult(int32_t code, const std::vector& extraInfo) | 返回操作的最终结果。 | +| IExecutorCallback::OnGetData(uint64_t scheduleId, const std::vector& salt,
uint64_t authSubType)| 返回获取pin码数据信息。 | + +### 开发步骤 + +以下将基于pin_auth驱动框架,并以RK3568平台为例,介绍相关驱动开发的具体步骤。 + +1. 基于HDF驱动框架,按照驱动Driver Entry程序,完成pin_auth驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现。 + + ```c++ + // 通过自定义的HdfPinAuthInterfaceHost对象包含IoService对象和真正的HDI Service实现PinAuthInterfaceService对象 + struct HdfPinAuthInterfaceHost { + struct IDeviceIoService ioService; + OHOS::sptr stub; + }; + + // 服务接口调用响应接口 + static int32_t PinAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) + { + IAM_LOGI("start"); + auto *hdfPinAuthInterfaceHost = CONTAINER_OF(client->device->service, + struct HdfPinAuthInterfaceHost, ioService); + + OHOS::MessageParcel *dataParcel = nullptr; + OHOS::MessageParcel *replyParcel = nullptr; + OHOS::MessageOption option; + + if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { + IAM_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { + IAM_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return hdfPinAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); + } + + // 初始化接口 + static int HdfPinAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + std::shared_ptr pinHdi = + OHOS::UserIAM::Common::MakeShared(); + constexpr uint32_t SUCCESS = 0; + if (pinHdi == nullptr || pinHdi->Init() != SUCCESS) { + IAM_LOGE("Pin hal init failed"); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // PinAuth驱动对外提供的服务绑定到HDF框架 + static int HdfPinAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + auto *hdfPinAuthInterfaceHost = new (std::nothrow) HdfPinAuthInterfaceHost; + if (hdfPinAuthInterfaceHost == nullptr) { + IAM_LOGE("%{public}s: failed to create create HdfPinAuthInterfaceHost object", __func__); + return HDF_FAILURE; + } + + hdfPinAuthInterfaceHost->ioService.Dispatch = PinAuthInterfaceDriverDispatch; + hdfPinAuthInterfaceHost->ioService.Open = NULL; + hdfPinAuthInterfaceHost->ioService.Release = NULL; + + auto serviceImpl = IPinAuthInterface::Get(true); + if (serviceImpl == nullptr) { + IAM_LOGE("%{public}s: failed to get of implement service", __func__); + return HDF_FAILURE; + } + + hdfPinAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, + IPinAuthInterface::GetDescriptor()); + if (hdfPinAuthInterfaceHost->stub == nullptr) { + IAM_LOGE("%{public}s: failed to get stub object", __func__); + return HDF_FAILURE; + } + + deviceObject->service = &hdfPinAuthInterfaceHost->ioService; + IAM_LOGI("success"); + return HDF_SUCCESS; + } + + // 释放PinAuth驱动中的资源 + static void HdfPinAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + auto *hdfPinAuthInterfaceHost = CONTAINER_OF(deviceObject->service, + struct HdfPinAuthInterfaceHost, ioService); + delete hdfPinAuthInterfaceHost; + IAM_LOGI("success"); + } + + static struct HdfDriverEntry g_pinAuthInterfaceDriverEntry = { + .moduleVersion = 1, + .moduleName = "pinauth_interface_service", + .Bind = HdfPinAuthInterfaceDriverBind, + .Init = HdfPinAuthInterfaceDriverInit, + .Release = HdfPinAuthInterfaceDriverRelease, + }; + + // 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 + HDF_INIT(g_pinauthinterfaceDriverEntry); + ``` + + + +1. 完成获取执行器列表接口实现,向框架注册执行器。 + + ```c++ + // 执行器实现类 + class ExecutorImpl : public IExecutor, public NoCopyable { + public: + explicit ExecutorImpl(std::shared_ptr pinHdi); + virtual ~ExecutorImpl() {} + int32_t GetExecutorInfo(ExecutorInfo &info) override; + int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo &info) override; + int32_t OnRegisterFinish(const std::vector &templateIdList, + const std::vector &frameworkPublicKey, const std::vector &extraInfo) override; + int32_t OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector &data) override; + int32_t Enroll(uint64_t scheduleId, const std::vector &extraInfo, + const sptr &callbackObj) override; + int32_t Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector &extraInfo, + const sptr &callbackObj) override; + int32_t Delete(uint64_t templateId) override; + int32_t Cancel(uint64_t scheduleId) override; + int32_t SendCommand(int32_t commandId, const std::vector &extraInfo, + const sptr &callbackObj) override; + + private: + class ScheduleMap { + public: + uint32_t AddScheduleInfo(const uint64_t scheduleId, const uint32_t commandId, + const sptr callback, const uint64_t templateId, const std::vector salt); + uint32_t GetScheduleInfo(const uint64_t scheduleId, uint32_t &commandId, sptr &callback, + uint64_t &templateId, std::vector &salt); + uint32_t DeleteScheduleId(const uint64_t scheduleId); + + private: + struct ScheduleInfo { + uint32_t commandId; + sptr callback; + uint64_t templateId; + std::vector salt; + }; + + std::mutex mutex_; + std::map scheduleInfo_; + }; + + private: + uint32_t NewSalt(std::vector &salt); + void CallError(const sptr &callbackObj, const uint32_t errorCode); + std::shared_ptr pinHdi_; + ScheduleMap scheduleMap_; + }; + + // 获取执行器列表实现,创建执行器 (仅作示例) + int32_t PinAuthInterfaceService::GetExecutorList(std::vector> &executorList) + { + IAM_LOGI("start"); + std::shared_ptr pinHdi = + OHOS::UserIAM::Common::MakeShared(); + if (pinHdi == nullptr) { + IAM_LOGE("Generate pinHdi failed"); + return HDF_FAILURE; + } + sptr executor = new (std::nothrow) ExecutorImpl(pinHdi); + if (executor == nullptr) { + IAM_LOGE("Generate executor failed"); + return HDF_FAILURE; + } + executorList.push_back(executor); + IAM_LOGI("end"); + return HDF_SUCCESS; + } + ``` + + + +1. 完成执行器每个功能接口实现。 + + ```c++ + // 实现获取执行器信息接口(仅作示例) + int32_t ExecutorImpl::GetExecutorInfo(ExecutorInfo &info) + { + IAM_LOGI("start"); + constexpr unsigned short SENSOR_ID = 1; + info.sensorId = SENSOR_ID; + info.executorType = EXECUTOR_TYPE; + info.executorRole = ExecutorRole::ALL_IN_ONE; + info.authType = AuthType::PIN; + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + return HDF_FAILURE; + } + uint32_t eslRet = 0; + int32_t result = pinHdi_->GetExecutorInfo(info.publicKey, eslRet); + if (result != SUCCESS) { + IAM_LOGE("Get ExecutorInfo failed, fail code : %{public}d", result); + return result; + } + info.esl = static_cast(eslRet); + + return HDF_SUCCESS; + } + + // 实现获取指定templateId的模板信息接口 + int32_t ExecutorImpl::GetTemplateInfo(uint64_t templateId, TemplateInfo &info) + { + IAM_LOGI("start"); + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + return HDF_FAILURE; + } + OHOS::UserIAM::PinAuth::PinCredentialInfo infoRet = {}; + int32_t result = pinHdi_->QueryPinInfo(templateId, infoRet); + if (result != SUCCESS) { + IAM_LOGE("Get TemplateInfo failed, fail code : %{public}d", result); + return result; + } + /* subType is stored in extraInfo */ + info.extraInfo.resize(infoRet.subType); + if (memcpy_s(&(info.extraInfo[0]), sizeof(infoRet.subType), &(infoRet.subType), sizeof(infoRet.subType)) != EOK) { + IAM_LOGE("copy subType to extraInfo fail!"); + return HDF_FAILURE; + } + + info.executorType = EXECUTOR_TYPE; + info.remainTimes = infoRet.remainTimes; + info.freezingTime = infoRet.freezingTime; + + return HDF_SUCCESS; + } + + // 实现执行器注册成功后,获取用户认证框架的公钥信息、获取用户认证框架的template 列表接口,将公钥信息保持,template 列表用于和本地的template做对账 + int32_t ExecutorImpl::OnRegisterFinish(const std::vector &templateIdList, + const std::vector &frameworkPublicKey, const std::vector &extraInfo) + { + IAM_LOGI("start"); + static_cast(frameworkPublicKey); + static_cast(extraInfo); + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + return HDF_FAILURE; + } + int32_t result = pinHdi_->VerifyTemplateData(templateIdList); + if (result != SUCCESS) { + IAM_LOGE("Verify templateData failed"); + return result; + } + + return HDF_SUCCESS; + } + + // 实现口令录入接口 + int32_t ExecutorImpl::Enroll(uint64_t scheduleId, const std::vector &extraInfo, + const sptr &callbackObj) + { + IAM_LOGI("start"); + if (callbackObj == nullptr) { + IAM_LOGE("callbackObj is nullptr"); + return HDF_FAILURE; + } + static_cast(extraInfo); + std::vector salt; + if (NewSalt(salt) != HDF_SUCCESS) { + IAM_LOGE("new salt failed"); + CallError(callbackObj, HDF_FAILURE); + return HDF_FAILURE; + } + int32_t result = scheduleMap_.AddScheduleInfo(scheduleId, ENROLL_PIN, callbackObj, 0, salt); + if (result != HDF_SUCCESS) { + IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result); + CallError(callbackObj, HDF_FAILURE); + return result; + } + result = callbackObj->OnGetData(scheduleId, salt, 0); + if (result != SUCCESS) { + IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result); + // If the enroll fails, delete scheduleId of scheduleMap + if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { + IAM_LOGI("delete scheduleId failed"); + } + return result; + } + + return HDF_SUCCESS; + } + + //实现回调数据获取的接口 + int32_t ExecutorImpl::OnSetData(uint64_t scheduleId, uint64_t authSubType, const std::vector &data) + { + IAM_LOGI("start"); + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + return HDF_FAILURE; + } + std::vector resultTlv; + int32_t result = SUCCESS; + constexpr uint32_t INVALID_ID = 2; + uint32_t commandId = INVALID_ID; + sptr callback = nullptr; + uint64_t templateId = 0; + std::vector salt(0, 0); + if (scheduleMap_.GetScheduleInfo(scheduleId, commandId, callback, templateId, salt) != HDF_SUCCESS) { + IAM_LOGE("Get ScheduleInfo failed, fail code : %{public}d", result); + return HDF_FAILURE; + } + switch (commandId) { + case ENROLL_PIN: + result = pinHdi_->EnrollPin(scheduleId, authSubType, salt, data, resultTlv); + if (result != SUCCESS) { + IAM_LOGE("Enroll Pin failed, fail code : %{public}d", result); + } + break; + case AUTH_PIN: + result = pinHdi_->AuthPin(scheduleId, templateId, data, resultTlv); + if (result != SUCCESS) { + IAM_LOGE("Auth Pin failed, fail code : %{public}d", result); + } + break; + default: + IAM_LOGE("Error commandId"); + } + + if (callback->OnResult(result, resultTlv) != SUCCESS) { + IAM_LOGE("callbackObj Pin failed"); + } + // Delete scheduleId from the scheduleMap_ when the enroll and authentication are successful + if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { + IAM_LOGI("delete scheduleId failed"); + } + + return HDF_SUCCESS; + } + // 实现口令认证接口 + int32_t ExecutorImpl::Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector &extraInfo, + const sptr &callbackObj) + { + IAM_LOGI("start"); + if (callbackObj == nullptr) { + IAM_LOGE("callbackObj is nullptr"); + return HDF_FAILURE; + } + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + CallError(callbackObj, HDF_FAILURE); + return HDF_FAILURE; + } + static_cast(extraInfo); + std::vector salt; + int32_t result = pinHdi_->GetSalt(templateId, salt); + if (result != SUCCESS) { + IAM_LOGE("get salt failed, fail code : %{public}d", result); + CallError(callbackObj, HDF_FAILURE); + return result; + } + result = scheduleMap_.AddScheduleInfo(scheduleId, AUTH_PIN, callbackObj, templateId, salt); + if (result != HDF_SUCCESS) { + IAM_LOGE("Add scheduleInfo failed, fail code : %{public}d", result); + CallError(callbackObj, HDF_FAILURE); + return result; + } + result = callbackObj->OnGetData(scheduleId, salt, 0); + if (result != SUCCESS) { + IAM_LOGE("Authenticate Pin failed, fail code : %{public}d", result); + // If the authentication fails, delete scheduleId of scheduleMap + if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { + IAM_LOGI("delete scheduleId failed"); + } + return result; + } + + return HDF_SUCCESS; + } + + // 实现删除口令模板接口 + int32_t ExecutorImpl::Delete(uint64_t templateId) + { + IAM_LOGI("start"); + if (pinHdi_ == nullptr) { + IAM_LOGE("pinHdi_ is nullptr"); + return HDF_FAILURE; + } + int32_t result = pinHdi_->DeleteTemplate(templateId); + if (result != SUCCESS) { + IAM_LOGE("Verify templateData failed, fail code : %{public}d", result); + return result; + } + + return HDF_SUCCESS; + } + + // 实现通过scheduleId取消指定操作接口 + int32_t ExecutorImpl::Cancel(uint64_t scheduleId) + { + IAM_LOGI("start"); + if (scheduleMap_.DeleteScheduleId(scheduleId) != HDF_SUCCESS) { + IAM_LOGE("scheduleId is not found"); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // 口令预留接口 + int32_t ExecutorImpl::SendCommand(int32_t commandId, const std::vector &extraInfo, + const sptr &callbackObj) + { + IAM_LOGI("Extension interface, temporarily useless"); + static_cast(commandId); + static_cast(extraInfo); + static_cast(callbackObj); + return HDF_SUCCESS; + } + ``` + + +### 调测验证 +驱动开发完成后,通过[用户认证 API接口](../../application-dev/reference/apis/js-apis-useriam-userauth.md)开发JS应用,基于RK3568平台验证。认证和取消功能验证的JS测试代码如下: + +```js +// API version 8 +import userIAM_userAuth from '@ohos.userIAM.userAuth'; +let auth = new userIAM_userAuth.UserAuth(); + +export default { + getVersion() { + console.info("start get version"); + let version = this.auth.getVersion(); + console.info("auth version = " + version); + }, + + startAuth() { + console.info("start auth"); + this.auth.auth(null, userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.AuthTrustLevel.ATL3, { + onResult: (result, extraInfo) => { + try { + console.info("auth onResult result = " + result); + console.info("auth onResult extraInfo = " + JSON.stringify(extraInfo)); + if (result == 'SUCCESS') { + // 此处添加认证成功逻辑 + } else { + // 此处添加认证失败逻辑 + } + } catch (e) { + console.info("auth onResult error = " + e); + } + } + }); + }, + + cancelAuth() { + console.info("start cancel auth"); + // contextId通过auth接口获取 + let contextId = auth.auth(null, userIAM_userAuth.UserAuthType.PIN, userIAM_userAuth.AuthTrustLevel.ATL3, { + onResult: (result, extraInfo) => { + console.info("auth onResult result = " + result); + }, + + onAcquireInfo: (module, acquire, extraInfo) => { + console.info("auth onAcquireInfo module = " + module); + } + }); + let cancelCode = this.auth.cancel(contextId); + if (cancelCode == userIAM_userAuth.Result.SUCCESS) { + console.info("cancel auth success"); + } else { + console.error("cancel auth fail"); + } + } +} +``` diff --git "a/zh-cn/device-dev/driver/figures/pin_auth\346\234\215\345\212\241\344\270\216\351\251\261\345\212\250\344\272\244\344\272\222.png" "b/zh-cn/device-dev/driver/figures/pin_auth\346\234\215\345\212\241\344\270\216\351\251\261\345\212\250\344\272\244\344\272\222.png" new file mode 100644 index 0000000000000000000000000000000000000000..2d806ab0bfde6fa32b54d31df698c3276c8c0978 GIT binary patch literal 29822 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 literal 0 HcmV?d00001 diff --git "a/zh-cn/device-dev/driver/figures/\345\217\243\344\273\244\350\256\244\350\257\201\346\236\266\346\236\204\345\233\276.png" "b/zh-cn/device-dev/driver/figures/\345\217\243\344\273\244\350\256\244\350\257\201\346\236\266\346\236\204\345\233\276.png" new file mode 100644 index 0000000000000000000000000000000000000000..32dadac7d8488783c6b6af7d4586f43621ce1881 GIT binary patch literal 16633 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 Mrl(r2^5pgZ0d2A=*Z=?k literal 0 HcmV?d00001 -- GitLab