From f16dfa24252356006f867cb98131d0b877880701 Mon Sep 17 00:00:00 2001 From: Annie_wang Date: Mon, 30 May 2022 15:47:03 +0800 Subject: [PATCH] update docs Signed-off-by: Annie_wang --- .../apis/js-apis-data-preferences.md | 85 ++- .../reference/apis/js-apis-data-storage.md | 6 +- .../reference/apis/js-apis-system-storage.md | 2 +- .../driver-peripherals-face_auth-des.md | 483 +++++++++++++++ .../driver/driver-peripherals-pinauth-des.md | 45 +- .../driver-peripherals-user-auth-des.md | 558 ++++++++++++++++++ .../driver/figures/face_auth_architecture.png | Bin 0 -> 12451 bytes ...ce_auth_service_and_driver_interaction.png | Bin 0 -> 15151 bytes .../driver/figures/pin_auth_architecture.png | Bin 15812 -> 16301 bytes .../driver/figures/process-of-using-pin.png | Bin 0 -> 11848 bytes .../driver/figures/user_auth_architecture.png | Bin 0 -> 20580 bytes .../user_auth_service_and_driver_api.png | Bin 0 -> 29891 bytes 12 files changed, 1131 insertions(+), 48 deletions(-) create mode 100644 en/device-dev/driver/driver-peripherals-face_auth-des.md create mode 100644 en/device-dev/driver/driver-peripherals-user-auth-des.md create mode 100644 en/device-dev/driver/figures/face_auth_architecture.png create mode 100644 en/device-dev/driver/figures/face_auth_service_and_driver_interaction.png create mode 100644 en/device-dev/driver/figures/process-of-using-pin.png create mode 100644 en/device-dev/driver/figures/user_auth_architecture.png create mode 100644 en/device-dev/driver/figures/user_auth_service_and_driver_api.png diff --git a/en/application-dev/reference/apis/js-apis-data-preferences.md b/en/application-dev/reference/apis/js-apis-data-preferences.md index 1010a20849..1c44c61279 100644 --- a/en/application-dev/reference/apis/js-apis-data-preferences.md +++ b/en/application-dev/reference/apis/js-apis-data-preferences.md @@ -1,6 +1,6 @@ # Preferences -Preferences provide capabilities for processing data in the form of key-value (KV) pairs and supports lightweight data persistence, modification, and query. In KV pairs, keys are of the string type, and values can be of the number, string, or Boolean type. +Preferences provide capabilities for processing data in the form of key-value (KV) pairs and support lightweight data persistence, modification, and query. In KV pairs, keys are of the string type, and values can be of the number, string, or Boolean type. > **NOTE**
@@ -19,8 +19,8 @@ import data_preferences from '@ohos.data.preferences'; | Name| Type| Readable| Writable| Description| | -------- | -------- | -------- | -------- | -------- | -| MAX_KEY_LENGTH | string | Yes| No| Maximum length of a key. It is 80 bytes.| -| MAX_VALUE_LENGTH | string | Yes| No| Maximum length of a value. It is 8192 bytes.| +| MAX_KEY_LENGTH | string | Yes| No| Maximum length of a key. It must be less than 80 bytes.| +| MAX_VALUE_LENGTH | string | Yes| No| Maximum length of a value. It must be less than 8192 bytes.| ## data_preferences.getPreferences @@ -262,6 +262,56 @@ promise.then((value) => { }) ``` +### getAll + +getAll(callback: AsyncCallback<Object>): void; + +Obtains the **Object** instance that contains all values. + +**System capability**: SystemCapability.DistributedDataManager.Preferences.Core + +Parameters + | Name| Type| Mandatory| Description| + | -------- | -------- | -------- | -------- | + | callback | AsyncCallback<Object> | Yes| Callback used to return the **Object** instance that contains all values.| + +**Example** +```ts +preferences.get.getAll(function (err, value) { + if (err) { + console.info("getAll failed, err: " + err) + return + } + let keys = Object.keys(value) + console.info('getAll keys = ' + keys) + console.info("getAll object = " + JSON.stringify(value)) +}); +``` + +### getAll + +getAll(): Promise<Object> + +Obtains the **Object** instance that contains all values. + +**System capability**: SystemCapability.DistributedDataManager.Preferences.Core + +**Return value** + | Type| Description| + | -------- | -------- | + | Promise<Object> | Promise used to return the **Object** instance that contains all values.| + +**Example** +```ts +let promise = preferences.getAll() +promise.then((value) => { + let keys = Object.keys(value) + console.info('getAll keys = ' + keys) + console.info("getAll object = " + JSON.stringify(value)) +}).catch((err) => { + console.info("getAll failed, err: " + err) +}) +``` ### put @@ -289,7 +339,6 @@ preferences.put('startup', 'auto', function (err) { }) ``` - ### put put(key: string, value: ValueType): Promise<void> @@ -322,7 +371,7 @@ promise.then(() => { ### has -has(key: string, callback: AsyncCallback<boolean>): boolean +has(key: string, callback: AsyncCallback<boolean>): void Checks whether this **Preferences** instance contains data with a given key. This API uses an asynchronous callback to return the result. @@ -332,12 +381,8 @@ Checks whether this **Preferences** instance contains data with a given key. Thi | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | key | string | Yes| Key of the data to check. It cannot be empty.| - | callback | AsyncCallback<boolean> | Yes| Callback used to return the result.| + | callback | AsyncCallback<boolean> | Yes| Callback used to return the result. It returns **true** if the **Preferences** instance contains data with the given key and returns **false** otherwise.| -**Return value** - | Type| Description| - | -------- | -------- | - | boolean | Returns **true** if the **Preferences** instance contains data with the specified key; returns **false** otherwise.| **Example** ```ts @@ -371,7 +416,7 @@ Checks whether this **Preferences** instance contains data with a given key. Thi **Return value** | Type| Description| | -------- | -------- | - | Promise<boolean> | Promise used to return the result.| + | Promise<boolean> | Promise used to return the result. It returns **true** if the **Preferences** instance contains data with the given key and returns **false** otherwise.| **Example** ```ts @@ -550,10 +595,10 @@ Subscribes to data changes. When the value of the subscribed key changes, a call **System capability**: SystemCapability.DistributedDataManager.Preferences.Core **Parameters** - | Name| Type| Description| - | -------- | -------- | -------- | - | type | string | Event type. The value **change** indicates data change events.| - | callback | Callback<{ key : string }> | Callback used to return data changes.| + | Name| Type|Mandatory| Description| + | -------- | -------- | -------- |-------- | + | type | string | Yes| Event type. The value **change** indicates data change events.| + | callback | Callback<{ key : string }> | Yes| Callback used to return data changes.| **Example** ```ts @@ -584,17 +629,17 @@ preferences.put('startup', 'auto', function (err) { ### off('change') -off(type: 'change', callback: Callback<{ key : string }>): void +off(type: 'change', callback?: Callback<{ key : string }>): void Unsubscribes from data changes. **System capability**: SystemCapability.DistributedDataManager.Preferences.Core **Parameters** - | Name| Type| Description| - | -------- | -------- | -------- | - | type | string | Event type. The value **change** indicates data change events.| - | callback | Callback<{ key : string }> | Callback used to return data changes.| + | Name| Type| Mandatory| Description| + | -------- | -------- | -------- |-------- | + | type | string| Yes| Event type. The value **change** indicates data change events.| + | callback | Callback<{ key : string }> | No| Callback used to return data changes. If this parameter is left empty, all callbacks for data changes will be canceled.| **Example** ```ts diff --git a/en/application-dev/reference/apis/js-apis-data-storage.md b/en/application-dev/reference/apis/js-apis-data-storage.md index 63ae9d95bc..6cdfcf94fd 100644 --- a/en/application-dev/reference/apis/js-apis-data-storage.md +++ b/en/application-dev/reference/apis/js-apis-data-storage.md @@ -22,15 +22,15 @@ import dataStorage from '@ohos.data.storage'; | Name| Type| Readable| Writable| Description| | -------- | -------- | -------- | -------- | -------- | -| MAX_KEY_LENGTH | string | Yes| No| Maximum length of a key. It is 80 bytes.| -| MAX_VALUE_LENGTH | string | Yes| No| Maximum length of a value. It is 8192 bytes.| +| MAX_KEY_LENGTH | string | Yes| No| Maximum length of a key. It must be less than 80 bytes.| +| MAX_VALUE_LENGTH | string | Yes| No| Maximum length of a value. It must be less than 8192 bytes.| ## dataStorage.getStorageSync getStorageSync(path: string): Storage -Reads the specified file and load its data to the **Storage** instance for data operations. +Reads the specified file and loads its data to the **Storage** instance for data operations. **System capability**: SystemCapability.DistributedDataManager.Preferences.Core diff --git a/en/application-dev/reference/apis/js-apis-system-storage.md b/en/application-dev/reference/apis/js-apis-system-storage.md index 37e8dc5de7..ffa96a8e8e 100644 --- a/en/application-dev/reference/apis/js-apis-system-storage.md +++ b/en/application-dev/reference/apis/js-apis-system-storage.md @@ -68,7 +68,7 @@ Sets the value in the cache based on the specified key. | Name| Type| Mandatory| Description| | -------- | -------- | -------- | -------- | | key | string | Yes| Key of the data to set.| -| value | string | Yes| New value to set. The maximum length is 128 bytes.| +| value | string | Yes| New value to set. The length must be less than 128 bytes.| | success | Function | No| Called when **storage.set()** is successful.| | fail | Function | No| Called when **storage.set()** fails. In the callback, **data** indicates the error information, and **code** indicates the error code.| | complete | Function | No| Called when **storage.set()** is complete.| diff --git a/en/device-dev/driver/driver-peripherals-face_auth-des.md b/en/device-dev/driver/driver-peripherals-face_auth-des.md new file mode 100644 index 0000000000..741648b3d5 --- /dev/null +++ b/en/device-dev/driver/driver-peripherals-face_auth-des.md @@ -0,0 +1,483 @@ +# Face_auth + +## Overview + +### Function + +Facial authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. It uses biometric recognition technologies to identify individuals based on facial characteristics. A camera is used to collect images or video streams that contain human faces, and automatically detect, track, and recognize human faces. Facial authentication is also called facial recognition or face recognition. The figure below shows the architecture of facial authentication. + +The face authentication driver (Face_auth) driver is developed based on the Hardware Driver Foundation (HDF) driver framework. It shields hardware differences and provides stable facial authentication capabilities for the user authentication framework (User_auth) and Face_auth service. The facial authentication capabilities include obtaining facial recognition executor list, executor information, and template information by template ID, comparing face image template information of the executor and that of User_auth, enrolling or deleting face templates, and performing facial authentication. + +**Figure 1** Facial authentication architecture + +![image](figures/face_auth_architecture.png "Facial authentication architecture") + +### Basic Concepts + +The identity authentication consists of User_auth and basic authentication services (including PIN authentication and facial authentication). It supports basic functions such as setting and deleting user credentials and performing authentication. The system supports user identity authentication and provides data collection, processing, storage, and comparison capabilities. +- Executor + + 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. + +- Executor security level + + Certain security level is required for the execution environment of an executor. For example, the executor security level is low for an operation performed without access control and high for an operation performed in a Trusted Execution Environment (TEE). + +- Executor role + + - 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. + + - Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication. + + - Authenticator: only processes data, obtains the stored credential template, and compares it with the authentication information generated. + +- Executor type + + 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. + +- User_auth public key & executor public key + + 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. + + 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. + + User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. + +- Facial authentication credential template + + 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. + +- Data verification by the executor + + 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. + +### Working Principles + +The Face_auth driver provides basic facial authentication capabilities for the User_auth framework and Face_auth service to ensure successful facial authentication. +You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. + +**Figure 2** Face_auth service and Face_auth driver interaction + +![image](figures/face_auth_service_and_driver_interaction.png "Face_auth service and Face_auth driver interaction") + +### Constraints + +- To implement facial authentication, the device must have a camera with a face image pixel greater than 100x100. +- TEE must be available, and facial feature information must be encrypted and stored in a TEE. +- The face matching accuracy varies with people with similar looks and children whose facial features keep changing. If you are concerned about this, consider using other authentication modes. + +## Development Guidelines + +### When to Use + +The Face_auth driver provides basic facial authentication capabilities for the User_auth framework and Face_auth service to ensure successful facial authentication. + +### Available APIs + +**Table 1** Available APIs + +| API | Description | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| GetExecutorList(std::vector>& executorList) | Obtains the executor list. | +| GetExecutorInfo(ExecutorInfo& info) | Obtain the executor information, including the executor type, executor role, authentication type, security level, and executor public key.| +| GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | Obtains information about a face image template based on the specified template ID. | +| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey, const std::vector& extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully.| +| Enroll(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | Enrolls a face image template. | +| Authenticate(uint64_t scheduleId, const std::vector& templateIdList,
const std::vector& extraInfo, const sptr& callbackObj) | Performs facial authentication. | +| Identify(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | Performs face identification. | +| Delete(const std::vector& templateIdList) | Deletes a face image template. | +| Cancel(uint64_t scheduleId) | Cancels a face enrolling, authentication, or identification operation based on the **scheduleId**. | +| SendCommand(int32_t commandId, const std::vector& extraInfo,
const sptr& callbackObj) | Sends commands to the Face_auth service. | + +**Table 2** Callbacks + +| API | Description | +| ------------------------------------------------------------ | ------------------------ | +| IExecutorCallback::OnResult(int32_t code, const std::vector& extraInfo) | Called to return the operation result. | +| IExecutorCallback::OnAcquireInfo(int32_t code, const std::vector& extraInfo) | Called to return the interaction information about the operation process.| + +### How to Develop + +The following uses the Hi3516DV300 platform as an example to demonstrate how to develop the Face_auth driver.
The directory structure is as follows: + +```undefined +// drivers/peripheral/face_auth +├── BUILD.gn # Build script +├── bundle.json # Module description file +└── hdi_service # Face_auth driver implementation + ├── BUILD.gn # Build script + ├── include # Header files + └── src + ├── executor_impl.cpp # Implementation of authentication and enrollment APIs + ├── face_auth_interface_driver.cpp # Face_auth driver entry + └── face_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list +``` + +The development procedure is as follows: + +1. Develop the Face_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [face_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_driver.cpp). + + ```c++ + // Create the IRemoteObject object by using the custom HdfFaceAuthInterfaceHost object, which consists of the IoService object and HDI service. + struct HdfFaceAuthInterfaceHost { + struct IDeviceIoService ioService; + OHOS::sptr stub; + }; + + // Enable the IPC service to call the response API. + static int32_t FaceAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, + struct HdfSBuf *reply) + { + IAM_LOGI("start"); + auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(client->device->service, + struct HdfFaceAuthInterfaceHost, 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 hdfFaceAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); + } + + // Initialize the HdfFaceAuthInterfaceDriver object. + int HdfFaceAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + return HDF_SUCCESS; + } + + // Bind the service provided by the Face_auth driver to the HDF. + int HdfFaceAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + auto *hdfFaceAuthInterfaceHost = new (std::nothrow) HdfFaceAuthInterfaceHost; + if (hdfFaceAuthInterfaceHost == nullptr) { + IAM_LOGE("%{public}s: failed to create create HdfFaceAuthInterfaceHost object", __func__); + return HDF_FAILURE; + } + + hdfFaceAuthInterfaceHost->ioService.Dispatch = FaceAuthInterfaceDriverDispatch; + hdfFaceAuthInterfaceHost->ioService.Open = NULL; + hdfFaceAuthInterfaceHost->ioService.Release = NULL; + + auto serviceImpl = IFaceAuthInterface::Get(true); + if (serviceImpl == nullptr) { + IAM_LOGE("%{public}s: Failed to implement the service", __func__); + return HDF_FAILURE; + } + + hdfFaceAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, + IFaceAuthInterface::GetDescriptor()); + if (hdfFaceAuthInterfaceHost->stub == nullptr) { + IAM_LOGE("%{public}s: Failed to get stub object", __func__); + return HDF_FAILURE; + } + + deviceObject->service = &hdfFaceAuthInterfaceHost->ioService; + IAM_LOGI("success"); + return HDF_SUCCESS; + } + + // Release resources of the Face_auth driver. + void HdfFaceAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) + { + IAM_LOGI("start"); + auto *hdfFaceAuthInterfaceHost = CONTAINER_OF(deviceObject->service, + struct HdfFaceAuthInterfaceHost, ioService); + delete hdfFaceAuthInterfaceHost; + IAM_LOGI("success"); + } + + // Register the entry data structure object of the Face_auth driver. + struct HdfDriverEntry g_faceAuthInterfaceDriverEntry = { + .moduleVersion = 1, + .moduleName = "faceauth_interface_service", + .Bind = HdfFaceAuthInterfaceDriverBind, + .Init = HdfFaceAuthInterfaceDriverInit, + .Release = HdfFaceAuthInterfaceDriverRelease, + }; + + // 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. + HDF_INIT(g_faceAuthInterfaceDriverEntry); + ``` + +2. Implement the API for obtaining the executor list. For details about the code, see [face_auth_interface_service.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/face_auth_interface_service.cpp). + + ```c++ + // Executor implementation class + class ExecutorImpl : public IExecutor { + public: + ExecutorImpl(struct ExecutorInfo executorInfo); + virtual ~ExecutorImpl() {} + + private: + struct ExecutorInfo executorInfo_; // Executor information + }; + + static constexpr uint16_t SENSOR_ID = 123; // Executor sensor ID + static constexpr uint32_t EXECUTOR_TYPE = 123; // Executor type + static constexpr size_t PUBLIC_KEY_LEN = 32; //32-byte public key of the executor + + // Create an HDI service object. + extern "C" IFaceAuthInterface *FaceAuthInterfaceImplGetInstance(void) + { + auto faceAuthInterfaceService = new (std::nothrow) FaceAuthInterfaceService(); + if (faceAuthInterfaceService == nullptr) { + IAM_LOGE("faceAuthInterfaceService is nullptr"); + return nullptr; + } + return faceAuthInterfaceService; + } + + // Obtain the executor list and create an executor. + int32_t GetExecutorList(std::vector>& executorList) + { + IAM_LOGI("interface mock start"); + executorList.clear(); + struct ExecutorInfo executorInfoExample = { + .sensorId = SENSOR_ID, + .executorType = EXECUTOR_TYPE, + .executorRole = ExecutorRole::ALL_IN_ONE, + .authType = AuthType::FACE, + .esl = ExecutorSecureLevel::ESL0, // Executor security level, which ranges from ESL0 to ESL3 (highest). + .publicKey = std::vector(PUBLIC_KEY_LEN, 0), // 32-byte public key, using the Ed25519 algorithm. + .extraInfo = {}, + }; + auto executor = new (std::nothrow) ExecutorImpl(executorInfoExample); + if (executor == nullptr) { + IAM_LOGE("executor is nullptr"); + return HDF_FAILURE; + } + executorList.push_back(sptr(executor)); + IAM_LOGI("interface mock success"); + return HDF_SUCCESS; + } + ``` + +3. Implement each function of the executor. For details about the code, see [executor_impl.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/face_auth/hdi_service/src/executor_impl.cpp). + + ```c++ + // Obtain the executor information. + int32_t GetExecutorInfo(ExecutorInfo& info) + { + IAM_LOGI("interface mock start"); + info = executorInfo_; + IAM_LOGI("get executor information success"); + return HDF_SUCCESS; + } + + // Obtain template information based on templateId. + int32_t GetTemplateInfo(uint64_t templateId, TemplateInfo& info) + { + IAM_LOGI("interface mock start"); + static_cast(templateId); + info = {0}; + IAM_LOGI("get template information success"); + return HDF_SUCCESS; + } + + // 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. + int32_t OnRegisterFinish(const std::vector& templateIdList, + const std::vector& frameworkPublicKey, const std::vector& extraInfo) + { + IAM_LOGI("interface mock start"); + static_cast(templateIdList); + static_cast(extraInfo); + static_cast(frameworkPublicKey); + IAM_LOGI("register finish"); + return HDF_SUCCESS; + } + + // Enroll face image. + int32_t Enroll(uint64_t scheduleId, const std::vector& extraInfo, + const sptr& callbackObj) + { + IAM_LOGI("interface mock start"); + static_cast(scheduleId); + static_cast(extraInfo); + IAM_LOGI("enroll, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); + int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // Start facial authentication. + int32_t Authenticate(uint64_t scheduleId, const std::vector& templateIdList, + const std::vector& extraInfo, const sptr& callbackObj) + { + IAM_LOGI("interface mock start"); + static_cast(scheduleId); + static_cast(templateIdList); + static_cast(extraInfo); + IAM_LOGI("authenticate, result is %{public}d", ResultCode::NOT_ENROLLED); + int32_t ret = callbackObj->OnResult(ResultCode::NOT_ENROLLED, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // Perform face recognition. + int32_t Identify(uint64_t scheduleId, const std::vector& extraInfo, + const sptr& callbackObj) + { + IAM_LOGI("interface mock start"); + static_cast(scheduleId); + static_cast(extraInfo); + IAM_LOGI("identify, result is %{public}d", ResultCode::OPERATION_NOT_SUPPORT); + int32_t ret = callbackObj->OnResult(ResultCode::OPERATION_NOT_SUPPORT, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + return HDF_SUCCESS; + } + + // Delete the face image template. + int32_t Delete(const std::vector& templateIdList) + { + IAM_LOGI("interface mock start"); + static_cast(templateIdList); + IAM_LOGI("delete success"); + return HDF_SUCCESS; + } + + // Cancel the operation based on the specified scheduleId. + int32_t Cancel(uint64_t scheduleId) + { + IAM_LOGI("interface mock start"); + static_cast(scheduleId); + IAM_LOGI("cancel success"); + return HDF_SUCCESS; + } + + // Send template freezing or unlocking command from the Face_auth service to the Face_auth driver. + int32_t SendCommand(int32_t commandId, const std::vector& extraInfo, + const sptr& callbackObj) + { + IAM_LOGI("interface mock start"); + static_cast(extraInfo); + int32_t ret; + switch (commandId) { + case LOCK_TEMPLATE: + IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); + ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + break; + case UNLOCK_TEMPLATE: + IAM_LOGI("unlock template, result is %{public}d", ResultCode::SUCCESS); + ret = callbackObj->OnResult(ResultCode::SUCCESS, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + break; + default: + IAM_LOGD("not support CommandId : %{public}d", commandId); + ret = callbackObj->OnResult(ResultCode::GENERAL_ERROR, {}); + if (ret != ResultCode::SUCCESS) { + IAM_LOGE("callback result is %{public}d", ret); + return HDF_FAILURE; + } + } + return HDF_SUCCESS; + } + ``` + +4. Modify **serviceName2Config** in the **face_auth_service.cpp** file if you need to add a driver or modify driver information. + + ```c++ + // base/user_iam/face_auth/services/src/face_auth_service.cpp + void FaceAuthService::StartDriverManager() + { + IAM_LOGI("start"); + // Service name and ID of the driver to add or modify. The driver service name and ID must be globally unique. + const std::map serviceName2Config = { + {"face_auth_interface_service", {1, std::make_shared()}}, + }; + UserIAM::UserAuth::IDriverManager::GetInstance().Start(serviceName2Config); + } + ``` + +### Verification + +Use the [User Authentication APIs](../../application-dev/reference/apis/js-apis-useriam-userauth.md) to develop a JavaScript application and verify the application on the Hi3516DV300 platform. The sample code for verifying the authentication and authentication cancellation is as follows: + +```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.FACE, userIAM_userAuth.AuthTrustLevel.ATL1, { + onResult: (result, extraInfo) => { + try { + console.info("auth onResult result = " + result); + console.info("auth onResult extraInfo = " + JSON.stringify(extraInfo)); + if (result == 'SUCCESS') { + // Add the logic to be executed when the authentication is successful. + } else { + // Add the logic to be executed when the authentication fails. + } + } catch (e) { + console.info("auth onResult error = " + e); + } + }, + + onAcquireInfo: (module, acquire, extraInfo) => { + try { + console.info("auth onAcquireInfo module = " + module); + console.info("auth onAcquireInfo acquire = " + acquire); + console.info("auth onAcquireInfo extraInfo = " + JSON.stringify(extraInfo)); + } catch (e) { + console.info("auth onAcquireInfo error = " + e); + } + } + }); + }, + + cancelAuth() { + console.info("start cancel auth"); + // Obtain contextId using auth(). + let contextId = auth.auth(null, userIAM_userAuth.UserAuthType.FACE, userIAM_userAuth.AuthTrustLevel.ATL1, { + 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/en/device-dev/driver/driver-peripherals-pinauth-des.md b/en/device-dev/driver/driver-peripherals-pinauth-des.md index 22a619ae00..0d2bc41747 100644 --- a/en/device-dev/driver/driver-peripherals-pinauth-des.md +++ b/en/device-dev/driver/driver-peripherals-pinauth-des.md @@ -4,20 +4,20 @@ ### Function -Personal Identification Number (PIN) authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. After a user registers a PIN, the PIN authentication (pin_auth) module unlocks the device only when a correct PIN is entered. The figure below shows the architecture of PIN authentication. +Personal Identification Number (PIN) authentication provides user authentication capabilities in identity authentication scenarios, such as device unlocking, payment, and app logins. After a user registers a PIN, the PIN authentication (Pin_auth) module unlocks the device only when a correct PIN is entered. The figure below shows the architecture of PIN authentication. -The pin_auth driver is developed based on the Hardware Driver Foundation (HDF). The pin_auth driver model shields hardware differences and provides stable PIN authentication capabilities for the user IAM framework(UserIAM) and PIN authentication system ability (SA). The PIN authentication capabilities include obtaining the PIN authentication executor list, executor information, and anti-brute force information of the specified template, comparing the template list of the executor and that of UserIAM, enrolling or deleting PINs, and performing PIN authentication. +The Pin_auth driver is developed based on the Hardware Driver Foundation (HDF). The Pin_auth driver model shields hardware differences and provides stable PIN authentication capabilities for the user User_auth framework (User_auth) and PIN authentication system ability (SA). The PIN authentication capabilities include obtaining the PIN authentication executor list, executor information, and anti-brute force information of the specified template, comparing the template ID list of the executor and that of User_auth, enrolling or deleting PINs, and performing PIN authentication. **Figure 1** PIN authentication architecture ![image](figures/pin_auth_architecture.png "PIN authentication architecture") ### Basic Concepts -The identity authentication consists of UserIAM and basic authentication services (including PIN authentication and facial recognition). It supports basic functions such as setting and deleting user credentials, and performing authentication. +The identity authentication consists of User_auth and basic authentication services (including PIN authentication and facial recognition). It supports basic functions such as setting and deleting user credentials and performing authentication. - Executor - The executor collects, processes, stores, and compares data for authentication. Each authentication service provides the executor capabilities, which are scheduled by UserIAM to implement basic capabilities. + 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. - Executor security level @@ -35,13 +35,13 @@ The identity authentication consists of UserIAM and basic authentication service 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. -- UserIAM public key & executor public key +- User_auth public key & executor public key - To ensure user data security and authentication result accuracy, measures must be taken to protect the integrity of the key information exchanged between UserIAM and basic authentication services. Public keys must be exchanged when the executor provided by a basic authentication service interworks with UserIAM. + 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. - - The executor uses the UserIAM public key to verify the scheduling instruction. + - The executor uses the User_auth public key to verify scheduling instructions. - - UserIAM uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. + - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. - PIN authentication credential template @@ -50,22 +50,22 @@ The identity authentication consists of UserIAM and basic authentication service - Data verification by the executor - UserIAM manages the mappings between user identities and credential IDs in a unified manner. When connecting to UserIAM, the executor obtains the template ID list from UserIAM, and updates its template ID list based on the obtained template ID list. + 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. ### Working Principles -The pin_auth driver provides basic capabilities of PIN authentication for the upper-layer UserIAM and pin_auth service to ensure successful PIN authentication. You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. +The Pin_auth driver provides basic PIN authentication capabilities for the upper-layer User_auth and Pin_auth service to ensure successful PIN authentication. You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. **Figure 2** Pin_auth service and pin_auth driver APIs -![image](figures/pin_auth_service_and_driver_interaction.png "interaction between the pin_auth service and driver") +![image](figures/pin_auth_service_and_driver_interaction.png "interaction between the Pin_auth service and driver") ### Constraints PIN authentication must be implemented in a TEE, and the confidential information, such as PINs and credentials, must be stored in a TEE. ## Development Guidelines ### When to Use -The pin_auth driver provides basic PIN authentication capabilities for the UserIAM and pin_auth service to ensure successful PIN authentication. +The Pin_auth driver provides basic PIN authentication capabilities for the User_auth and Pin_auth service to ensure successful PIN authentication. ### Available APIs @@ -76,7 +76,7 @@ The pin_auth driver provides basic PIN authentication capabilities for the UserI | GetExecutorList(std::vector>& executorList) | Obtains the executor list. | | GetExecutorInfo(ExecutorInfo& info) | Obtains information about an executor. | | GetTemplateInfo(uint64_t templateId, TemplateInfo& info) | Obtains information about a template. | -| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey,
const std::vector& extraInfo) | Obtains the public key and template list from UserIAM after the executor is registered successfully.| +| OnRegisterFinish(const std::vector& templateIdList,
const std::vector& frameworkPublicKey,
const std::vector& extraInfo) | Obtains the public key and template ID list from User_auth after the executor is registered successfully.| | OnSetData(uint64_t scheduleId, uint64_t authSubType,
const std::vector &data) | Called to return the subtype and anonymized data of PIN authentication. | | Enroll(uint64_t scheduleId, const std::vector& extraInfo,
const sptr& callbackObj) | Enrolls a PIN. | | Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector& extraInfo, const sptr& callbackObj) | Starts PIN authentication. | @@ -93,7 +93,7 @@ The pin_auth driver provides basic PIN authentication capabilities for the UserI ### How to Develop -The following uses the RK3568 platform as an example to demonstrate how to develop the pin_auth driver.
The directory structure is as follows: +The following uses the RK3568 platform as an example to demonstrate how to develop the Pin_auth driver.
The directory structure is as follows: ``` // drivers/peripheral/pin_auth @@ -104,13 +104,13 @@ The following uses the RK3568 platform as an example to demonstrate how to devel ├── inc # Header files └── src ├── executor_impl.cpp # Implementation of authentication and enrollment APIs - ── pin_auth_interface_driver.cpp # Pin_auth driver entry + ├── pin_auth_interface_driver.cpp # Pin_auth driver entry └── pin_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list ``` The development procedure is as follows: -1. Develop the pin_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [pin_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/pin_auth/hdi_service/src/pin_auth_interface_driver.cpp). +1. Develop the Pin_auth driver based on the HDF. The **Bind()**, **Init()**, **Release()**, and **Dispatch()** functions are used. For details about the code, see [pin_auth_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/Pin_auth/hdi_service/src/pin_auth_interface_driver.cpp). ```c++ // Create the PinAuthInterfaceService object by using the custom HdfPinAuthInterfaceHost object, which consists of the IoService object and HDI service. @@ -156,7 +156,7 @@ The development procedure is as follows: return HDF_SUCCESS; } - // Bind the service provided by the pin_auth driver to the HDF. + // Bind the service provided by the Pin_auth driver to the HDF. static int HdfPinAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) { IAM_LOGI("start"); @@ -188,7 +188,7 @@ The development procedure is as follows: return HDF_SUCCESS; } - // Release resources of the pin_auth driver. + // Release resources of the Pin_auth driver. static void HdfPinAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) { IAM_LOGI("start"); @@ -340,7 +340,7 @@ The development procedure is as follows: return HDF_SUCCESS; } - // After the executor is successfully registered, obtain the public key and template ID list from UserIAM and save the public key obtained. The executor compares its template ID list with the template ID list obtained and updates its template ID list. + // After the executor is successfully registered, obtain the public key and template ID list from User_auth and save the public key obtained. The executor compares its template ID list with the template ID list obtained and updates its template ID list. int32_t ExecutorImpl::OnRegisterFinish(const std::vector &templateIdList, const std::vector &frameworkPublicKey, const std::vector &extraInfo) { @@ -526,9 +526,8 @@ The development procedure is as follows: ### Verification Verify whether PIN authentication can be successfully performed on the RK3568 platform as follows: -1. Set a PIN. - - Touch **Settings** > **Biometrics & passwords** > **Password**, and enter your password. +1. Set a PIN.
+ Touch **Settings** > **Biometrics & passwords** > **Password**, and enter your password. 2. Verify PIN authentication. @@ -549,5 +548,3 @@ Verify whether PIN authentication can be successfully performed on the RK3568 pl 1) Touch **Settings** > **Biometrics & passwords** > **Password**. 2) Touch **Change screen lock password** and set the new password. - - diff --git a/en/device-dev/driver/driver-peripherals-user-auth-des.md b/en/device-dev/driver/driver-peripherals-user-auth-des.md new file mode 100644 index 0000000000..90b42987be --- /dev/null +++ b/en/device-dev/driver/driver-peripherals-user-auth-des.md @@ -0,0 +1,558 @@ +# User_auth + +## Overview + +### Function + +User 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. + +The 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 authentication executor information management. + +**Figure 1** User authentication architecture + +![image](figures/user_auth_architecture.png "User authentication architecture") + +### Basic Concepts +The 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. + +- Authentication credential information + + 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. + +- Authentication credential template + + The authentication credential template is generated and stored by the authentication service when a user sets the authentication credential. The template information needs to be compared with the authentication data generated during authentication to complete identity authentication. Each template has an ID to index a set of template information files. + +- Executor + + 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. + +- Executor role + + - ​ 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. + + - ​ Collector: only collects data during user authentication. It needs to work with the authenticator to complete user authentication. + + - ​ Authenticator: processes data, obtains the stored credential template, and compares it with the authentication information generated. + +- Executor type + + 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. + +- Executor security level + + Certain security level is required for the execution environment of an executor. For example, the executor security level is low for an operation performed without access control and high for an operation performed in a Trusted Execution Environment (TEE). + +- User_auth public key & executor public key + + 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. + + - 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. + + - User_auth uses the executor public key to verify the authentication result accuracy and the integrity of the information exchanged with the executor. + + +- Authentication result trust level + + The trust level of the authentication result varies, depending on the authentication mode and the security level of the authentication execution environment. + +- Authentication scheme + + An authentication scheme contains information about the authentication mode, trust level of the authentication result, executor, and credential. + +- Scheduling information + + 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. + +- SA + + SAs are loaded by the System Ability Manager service to provide basic system capabilities for the OpenHarmony system. + +- Kit + + The kit provides basic application programming interfaces (APIs) for third-party applications. + +- Inner API + + Inner API is an API provided by OpenHarmony for system applications. + +### Working Principles + +The User_auth driver shields the differences of security devices and environments. It provides unified interface for the User_auth service to implement management of authentication executors and credentials as well as authentication scheme generation. +You can develop drivers to call Hardware Device Interface (HDI) APIs based on the HDF and the chip you use. + +**Figure 2** User_auth service and User_auth driver APIs + +![image](figures/user_auth_service_and_driver_api.png "interaction between the uin_auth service and driver") + +### Constraints + +The User_auth driver must be implemented in a TEE to ensure secure storage of user credential information and trustworthiness of user authentication results. + +## Development Guidelines + +### When to Use + +The User_auth driver provides stable user credential management, authentication session management, and executor information management capabilities for the User_auth service to ensure successful PIN authentication and biometric recognition on devices. + +### Available APIs + +**Table 1** Available APIs + +| API | Description | +| ------------------------------------------------------------ | ------------------------------------------------------------ | +| Init() | Initializes cached information. | +| AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index, std::vector& publicKey,
std::vector& templateIds) | Adds an executor to obtain the authentication capability. | +| DeleteExecutor(uint64_t index) | Deletes an executor. | +| OpenSession(int32_t userId, std::vector& challenge) | Opens a session for authentication credential management. | +| CloseSession(int32_t userId) | Closes a session for authentication credential management. | +| BeginEnrollment(int32_t userId, const std::vector& authToken, const EnrollParam& param,
ScheduleInfo& info) | Enrolls the user authentication credential. If a user has enrolled a PIN, the new PIN enrolled will replace the old PIN.| +| UpdateEnrollmentResult(int32_t userId, const std::vector& scheduleResult, uint64_t& credentialId,
CredentialInfo& oldInfo) | Updates the data to complete this enrollment. | +| CancelEnrollment(int32_t userId) | Cancels an enrollment operation. | +| DeleteCredential(int32_t userId, uint64_t credentialId, const std::vector& authToken,
CredentialInfo& info) | Deletes credential information based on the specified **credentialId**. | +| DeleteUser(int32_t userId, const std::vector& authToken,
std::vector& deletedInfos) | Deletes a user PIN from User_auth. | +| EnforceDeleteUser(int32_t userId, std::vector& deletedInfos) | Forcibly deletes a user. This API will be called when a user is deleted from the system. | +| GetCredential(int32_t userId, AuthType authType, std::vector& infos) | Obtains user credential information by authentication type. | +| GetSecureInfo(int32_t userId, uint64_t& secureUid, std::vector& infos) | Obtains the secure user ID and the enrolled tag ID of each authentication type. | +| BeginAuthentication(uint64_t contextId, const AuthSolution& param,
std::vector& scheduleInfos) | Starts an authentication to generate the authentication scheme and scheduling information. | +| UpdateAuthenticationResult(uint64_t contextId, const std::vector& scheduleResult,
AuthResultInfo& info) | Updates the authentication result to evaluate the authentication scheme. | +| CancelAuthentication(uint64_t contextId) | Cancels an authentication. | +| BeginIdentification(uint64_t contextId, AuthType authType, const std::vector& challenge,
uint32_t executorId, ScheduleInfo& scheduleInfo) | Starts an identification to generate the identification scheme and scheduling information. | +| UpdateIdentificationResult(uint64_t contextId, const std::vector& scheduleResult,
IdentifyResultInfo& info) | Updates the identification result to evaluate the identification scheme. | +| CancelIdentification(uint64_t contextId) | Cancel an identification. | +| GetAuthTrustLevel(int32_t userId, AuthType authType, uint32_t& authTrustLevel) | Obtains the authentication trust level of the specified authentication type. | +| GetValidSolution(int32_t userId, const std::vector& authTypes, uint32_t authTrustLevel,
std::vector& validTypes) | Obtains the valid authentication scheme based on the authentication trust level for a user. | + +### How to Develop + +The following uses the Hi3516DV300 platform as an example to demonstrate how to develop the User_auth driver.
The directory structure is as follows: + +```undefined +// drivers/peripheral/user_auth +├── BUILD.gn # Build script +├── bundle.json # Module description file +└── hdi_service # User_auth driver implementation + ├── BUILD.gn # Build script + ├── module # Implementation of functionalities + └── service + ├── user_auth_interface_driver.cpp # User_auth driver entry + └── user_auth_interface_service.cpp # Implementation of the APIs for obtaining the executor list +``` + +The development procedure is as follows: + +1. 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). + + ```c++ + // Create the IRemoteObject object by using the custom HdfUserAuthInterfaceHost object, which consists of the IoService object and HDI service. + struct HdfUserAuthInterfaceHost { + struct IDeviceIoService ioService; + OHOS::sptr stub; + }; + + // Enable the IPC service to call the response API. + static int32_t UserAuthInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, + struct HdfSBuf *reply) + { + auto *hdfUserAuthInterfaceHost = CONTAINER_OF(client->device->service, struct HdfUserAuthInterfaceHost, ioService); + + OHOS::MessageParcel *dataParcel = nullptr; + OHOS::MessageParcel *replyParcel = nullptr; + OHOS::MessageOption option; + + if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s:invalid data sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s:invalid reply sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return hdfUserAuthInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); + } + + // Initialize the HdfUserAuthInterfaceDriver object. + int HdfUserAuthInterfaceDriverInit(struct HdfDeviceObject *deviceObject) + { + HDF_LOGI("HdfUserAuthInterfaceDriverInit enter"); + OHOS::UserIAM::Common::Init(); + return HDF_SUCCESS; + } + + // Bind the service provided by the User_auth driver to the HDF. + int HdfUserAuthInterfaceDriverBind(struct HdfDeviceObject *deviceObject) + { + HDF_LOGI("HdfUserAuthInterfaceDriverBind enter"); + + auto *hdfUserAuthInterfaceHost = new (std::nothrow) HdfUserAuthInterfaceHost; + if (hdfUserAuthInterfaceHost == nullptr) { + HDF_LOGE("%{public}s: failed to create create HdfUserAuthInterfaceHost object", __func__); + return HDF_FAILURE; + } + + hdfUserAuthInterfaceHost->ioService.Dispatch = UserAuthInterfaceDriverDispatch; + hdfUserAuthInterfaceHost->ioService.Open = NULL; + hdfUserAuthInterfaceHost->ioService.Release = NULL; + + auto serviceImpl = IUserAuthInterface::Get(true); + if (serviceImpl == nullptr) { + HDF_LOGE("%{public}s: failed to get of implement service", __func__); + return HDF_FAILURE; + } + + hdfUserAuthInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, + IUserAuthInterface::GetDescriptor()); + if (hdfUserAuthInterfaceHost->stub == nullptr) { + HDF_LOGE("%{public}s: failed to get stub object", __func__); + return HDF_FAILURE; + } + + deviceObject->service = &hdfUserAuthInterfaceHost->ioService; + return HDF_SUCCESS; + } + + // Release resources of the User_auth driver. + void HdfUserAuthInterfaceDriverRelease(struct HdfDeviceObject *deviceObject){ + HDF_LOGI("HdfUserAuthInterfaceDriverRelease enter"); + auto *hdfUserAuthInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfUserAuthInterfaceHost, ioService); + delete hdfUserAuthInterfaceHost; + } + + // Register the User_auth driver entry data structure object. + struct HdfDriverEntry g_userAuthInterfaceDriverEntry = { + .moduleVersion = 1, + .moduleName = "user_auth_device_driver", + .Bind = HdfUserAuthInterfaceDriverBind, + .Init = HdfUserAuthInterfaceDriverInit, + .Release = HdfUserAuthInterfaceDriverRelease, + }; + + // 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. + #ifndef __cplusplus + extern "C" { + #endif + HDF_INIT(g_userAuthInterfaceDriverEntry); + #ifndef __cplusplus + } + #endif + ``` + +2. 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). + + ```c++ + // Add an executor. + int32_t UserAuthInterfaceService::AddExecutor(const ExecutorRegisterInfo& info, uint64_t& index, + std::vector& publicKey, std::vector& templateIds) + { + GlobalLock(); + ExecutorInfoHal executorInfoHal; + CopyExecutorInfo(info, executorInfoHal); + int32_t ret = RegisterExecutor(&executorInfoHal, &index); + GlobalUnLock(); + return ret; + } + + // Delete the executor. + int32_t UserAuthInterfaceService::DeleteExecutor(uint64_t index) + { + return UnRegisterExecutor(index); + } + ``` + +3. 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). + + ```c++ + // Open a session for authentication credential management. + int32_t UserAuthInterfaceService::OpenSession(int32_t userId, std::vector& challenge) + { + GlobalLock(); + uint64_t challengeU64 = 0; + int32_t ret = OpenEditSession(userId, &challengeU64); + challenge.resize(sizeof(uint64_t)); + if (memcpy_s(&challenge[0], challenge.size(), &challengeU64, sizeof(uint64_t)) != EOK) { + IAM_LOGE("challengeU64 copy failed"); + return RESULT_BAD_COPY; + } + GlobalUnLock(); + return ret; + } + + // Close the session for authentication credential management. + int32_t UserAuthInterfaceService::CloseSession(int32_t userId) + { + GlobalLock(); + int32_t ret = CloseEditSession(); + GlobalUnLock(); + return ret; + } + + // Start an authentication to generate enrollment and scheduling information. + int32_t UserAuthInterfaceService::BeginEnrollment(int32_t userId, const std::vector& authToken, + const EnrollParam& param, ScheduleInfo& info) + { + IAM_LOGI("start"); + GlobalLock(); + if (authToken.size() != sizeof(UserAuthTokenHal) && param.authType != PIN) { + IAM_LOGE("authToken len is invalid"); + GlobalUnLock(); + return RESULT_BAD_PARAM; + } + PermissionCheckParam checkParam; + if (authToken.size() == sizeof(UserAuthTokenHal) && + memcpy_s(checkParam.token, AUTH_TOKEN_LEN, &authToken[0], authToken.size()) != EOK) { + GlobalUnLock(); + return RESULT_BAD_COPY; + } + checkParam.authType = param.authType; + checkParam.userId = userId; + checkParam.authSubType = (uint64_t)param.executorType; + CoAuthSchedule scheduleInfo; + int32_t ret = CheckEnrollPermission(checkParam, &scheduleInfo.scheduleId); + if (ret != RESULT_SUCCESS) { + IAM_LOGE("check permission failed"); + GlobalUnLock(); + return ret; + } + ret = GetCoAuthSchedule(&scheduleInfo); + if (ret != RESULT_SUCCESS) { + IAM_LOGE("get schedule info failed"); + GlobalUnLock(); + return ret; + } + if (!CopyScheduleInfo(&scheduleInfo, &info)) { + IAM_LOGE("copy schedule info failed"); + ret = RESULT_BAD_COPY; + } + GlobalUnLock(); + return ret; + } + + // Cancel the enrollment operation. + int32_t UserAuthInterfaceService::CancelEnrollment(int32_t userId) + { + IAM_LOGI("start"); + BreakOffCoauthSchedule(userId); + return RESULT_SUCCESS; + } + + // Update the enrolled credential information. + int32_t UserAuthInterfaceService::UpdateEnrollmentResult(int32_t userId, const std::vector& scheduleResult, + uint64_t& credentialId, CredentialInfo& oldInfo) + { + IAM_LOGI("start"); + GlobalLock(); + if (scheduleResult.size() == 0) { + IAM_LOGE("enrollToken is invalid"); + GlobalUnLock(); + return RESULT_BAD_PARAM; + } + Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); + if (scheduleResultBuffer == nullptr) { + IAM_LOGE("scheduleTokenBuffer is null"); + GlobalUnLock(); + return RESULT_NO_MEMORY; + } + bool isUpdate; + int32_t ret = GetIsUpdate(&isUpdate); + if (ret != RESULT_SUCCESS) { + IAM_LOGE("get isUpdate failed"); + return ret; + } + if (isUpdate) { + CredentialInfoHal oldCredentialHal; + ret = UpdateCredentialFunc(scheduleResultBuffer, &credentialId, &oldCredentialHal); + oldInfo.authType = static_cast(oldCredentialHal.authType); + oldInfo.credentialId = oldCredentialHal.credentialId; + oldInfo.templateId = oldCredentialHal.templateId; + oldInfo.executorType = static_cast(oldCredentialHal.authSubType); + oldInfo.executorId = 0; + oldInfo.index = 0; + } else { + ret = AddCredentialFunc(scheduleResultBuffer, &credentialId); + } + DestoryBuffer(scheduleResultBuffer); + GlobalUnLock(); + return ret; + } + ``` + +4. 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). + + ```c++ + // Create an HDI service object. + extern "C" IUserAuthInterface *UserAuthInterfaceImplGetInstance(void) + { + auto userAuthInterfaceService = new (std::nothrow) UserAuthInterfaceService(); + if (userAuthInterfaceService == nullptr) { + IAM_LOGE("userAuthInterfaceService is nullptr"); + return nullptr; + } + return userAuthInterfaceService; + } + + // Start an authentication to generate the authentication scheme and scheduling information. + int32_t UserAuthInterfaceService::BeginAuthentication(uint64_t contextId, const AuthSolution& param, + std::vector& infos) + { + IAM_LOGI("start"); + if (param.challenge.size() != sizeof(uint64_t)) { + IAM_LOGE("challenge copy failed"); + return RESULT_BAD_PARAM; + } + GlobalLock(); + CoAuthSchedule *schedulesGet = nullptr; + uint32_t scheduleIdNum = 0; + AuthSolutionHal solutionIn; + solutionIn.contextId = contextId; + solutionIn.userId = param.userId; + solutionIn.authType = static_cast(param.authType); + solutionIn.authTrustLevel = param.authTrustLevel; + if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), ¶m.challenge[0], + param.challenge.size()) != EOK) { + IAM_LOGE("challenge copy failed"); + GlobalUnLock(); + return RESULT_BAD_COPY; + } + int32_t ret = GenerateSolutionFunc(solutionIn, &schedulesGet, &scheduleIdNum); + if (ret != RESULT_SUCCESS) { + IAM_LOGE("generate solution failed"); + GlobalUnLock(); + return ret; + } + for (uint32_t i = 0; i < scheduleIdNum; i++) { + ScheduleInfo temp; + if (!CopyScheduleInfo(schedulesGet + i, &temp)) { + infos.clear(); + ret = RESULT_GENERAL_ERROR; + break; + } + infos.push_back(temp); + } + free(schedulesGet); + GlobalUnLock(); + return ret; + } + + // Update the authentication result to evaluate the authentication scheme. + int32_t UserAuthInterfaceService::UpdateAuthenticationResult(uint64_t contextId, + const std::vector& scheduleResult, AuthResultInfo& info) + { + IAM_LOGI("start"); + GlobalLock(); + if (scheduleResult.size() == 0) { + IAM_LOGE("param is invalid"); + info.result = RESULT_BAD_PARAM; + GlobalUnLock(); + return RESULT_BAD_PARAM; + } + Buffer *scheduleResultBuffer = CreateBufferByData(&scheduleResult[0], scheduleResult.size()); + if (scheduleResultBuffer == nullptr) { + IAM_LOGE("scheduleTokenBuffer is null"); + info.result = RESULT_GENERAL_ERROR; + GlobalUnLock(); + return RESULT_NO_MEMORY; + } + UserAuthTokenHal authTokenHal; + info.result = RequestAuthResultFunc(contextId, scheduleResultBuffer, &authTokenHal); + if (info.result != RESULT_SUCCESS) { + IAM_LOGE("execute func failed"); + DestoryBuffer(scheduleResultBuffer); + GlobalUnLock(); + return info.result; + } + info.token.resize(sizeof(UserAuthTokenHal)); + if (memcpy_s(&info.token[0], info.token.size(), &authTokenHal, sizeof(authTokenHal)) != EOK) { + IAM_LOGE("copy authToken failed"); + DestoryBuffer(scheduleResultBuffer); + GlobalUnLock(); + return RESULT_BAD_COPY; + } + DestoryBuffer(scheduleResultBuffer); + GlobalUnLock(); + return RESULT_SUCCESS; + } + + // Cancel the authentication. + int32_t UserAuthInterfaceService::CancelAuthentication(uint64_t contextId) + { + IAM_LOGI("start"); + GlobalLock(); + uint32_t scheduleIdNum = 0; + int32_t ret = CancelContextFunc(contextId, nullptr, &scheduleIdNum); + if (ret != RESULT_SUCCESS) { + IAM_LOGE("execute func failed"); + GlobalUnLock(); + return ret; + } + GlobalUnLock(); + return RESULT_SUCCESS; + } + ``` + +### Verification + +Use the [User Authentication APIs](../../application-dev/reference/apis/js-apis-useriam-userauth.md) to develop a JavaScript application and verify the application on the Hi3516DV300 platform. The sample code for verifying the authentication and authentication cancellation is as follows: + +```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.FACE, userIAM_userAuth.AuthTrustLevel.ATL1, { + onResult: (result, extraInfo) => { + try { + console.info("auth onResult result = " + result); + console.info("auth onResult extraInfo = " + JSON.stringify(extraInfo)); + if (result == 'SUCCESS') { + // Add the logic to be executed when the authentication is successful. + } else { + // Add the logic to be executed when the authentication fails. + } + } catch (e) { + console.info("auth onResult error = " + e); + } + }, + + onAcquireInfo: (module, acquire, extraInfo) => { + try { + console.info("auth onAcquireInfo module = " + module); + console.info("auth onAcquireInfo acquire = " + acquire); + console.info("auth onAcquireInfo extraInfo = " + JSON.stringify(extraInfo)); + } catch (e) { + console.info("auth onAcquireInfo error = " + e); + } + } + }); + }, + + cancelAuth() { + console.info("start cancel auth"); + // Obtain contextId using auth(). + let contextId = auth.auth(null, userIAM_userAuth.UserAuthType.FACE, userIAM_userAuth.AuthTrustLevel.ATL1, { + 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/en/device-dev/driver/figures/face_auth_architecture.png b/en/device-dev/driver/figures/face_auth_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..d8f01c87f052fe547f0e1a8e41619aa37b1e435a GIT binary patch literal 12451 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 literal 0 HcmV?d00001 diff --git a/en/device-dev/driver/figures/face_auth_service_and_driver_interaction.png b/en/device-dev/driver/figures/face_auth_service_and_driver_interaction.png new file mode 100644 index 0000000000000000000000000000000000000000..f8ee14264d63f1a3912be533595f2444aac1bb84 GIT binary patch literal 15151 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 literal 0 HcmV?d00001 diff --git a/en/device-dev/driver/figures/pin_auth_architecture.png b/en/device-dev/driver/figures/pin_auth_architecture.png index aeba4a173a2e26cbdaa9c5a1aabe0220ef7b2a59..6aab7cfafd6adf4be20b926448da9d03c9b0d8d5 100644 GIT binary patch literal 16301 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%0A}UL2yJ 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 F{|`5EoSOgu literal 15812 zcmdVBnTHNC@sOLy$mlcN^Rtf_re+AW48>@DMC`aQEQu4#C|az~JuicJ8O{ zs`s3F{(E8W&kYU^qvziTK7k2?6b?>UPYx`u z>1}kh^2S?pr&aXy#KNkY-hx_87ZE2BOROmS-A8;WIdyE!+qu`H6AHZnoS; z(r9bg`PVK!uid1v^C4nkW2+^-RSU!cwuI(;zy|S+WD*q0AWPH)27|@B{?LLzs5lT7 z;Q!y*+{2*IZ^2m#U@+c0G(!+5o67Y6i9^to#aop~Y8J@Xmr7KSg5c?BVr;?&NF{a5 zIXJKXAm@*#Jr=&Cng9NA8ci_)up_Qj**{Jr zWec#VZbHZ2$ClJVsFu5HPxK33K~|s@L)Z~yDrGtKxndZ-xsg@MK8^(FjufKys zHF|nYgG|3Uce4iF7O5KI0q2UM8KRdyx)VNME(!>pZlNuU&>9vwI`C*WydJ31q+|DQ z$ifK>*wGjnYb3i-YF9T@0Q+`tB#_KE9k5B~Uv?&#hcXE2mLz;tVDSv)gTu`Xc^?Nc z@A)G#U$@I(3mYr63zKysYJ&f<(e(1i25pZt)QEkflGA=LbOqxlIuaV`Pv|0qfJ}7d zS2;DP)pQT3uqY4F1ATNa2`}Q*nUgHLn);m9mCzr@{Et~p)golGk zy@hdmPdPH^$!rg4pcP>!I(`h2i48LQ@2G1b8vW8@mbKRBdS=5OaYdISaMJCZcy+vn zd6gXBZ+;+zy$>gu^pQA?XF9XIbAQolhl_BH%)KtHb3d-O(BXG&`(Eh${KDjy;yCU? zC)eLEmYoZe!LTW<+vhzOG7)#Q&~5kI*UGaC2}e9|P$jHi!9@;*S5>W+U!bnTH<1abm0(a3)K>(; zQfsc-h5tRo)~>c_nZWdr)X!}7u(UJjBoOK(qu3evc!e*-QHP^H=O5f`XZG- zZa54i3&AzZYj5UMsB|*cT|Iv%26x&^7wWP+1b6@W*1FU#arA4Ih^>%y^9cEDQN?;I zA>ZzF_-4-h>E7dZZ-eV6X?uS;(wXjK4~`mUpCM80kF{5JXb~M%n9sref$?Dn95eD7 ziW)sf#4#@j`1D86c-n#kLK7~&s;9X2E$3y2pWH`CXt)s-sTWw%p_*nFeH>(jGBnv@ zj+Sim&iO<5d!fC*t$R<-wvFquPe#3{A7I`@nEI!yV@HMZWZ$r99+F^;BZVu{9afL=Un>DN9)$x@aak_8gll@1!OfETv)*c#vhbp0Zh4S!^P) zuUucuG#oyAoo=2K&@iJ`_G0t|$7jty^x?GJ&l1kNH6d}&Vu8WXHT)a5!QTv6u`IyD z@>iWq9V$J4ehz(gZ{}Lo*}T)=t@ZvEDs zk!y6gX$q($_P9L_Ofs=<7p&TARkznYDUVdBa+wl!KG`F`-P}@|*EvBo9Ng!k=4hit zx>V`=4i6eZrlX=m!@_(M+TavAg(7*cQe`oN7Y&l zm8(86I`dl2?8Go=#`4!vkIIc8;p8L~_7@A>-$&!)&6C0Mj7$(6(>uZ3>*&DSH2RQo ztb?0(+iY!H>h{R#xNDwaJ@P|x7}S>`NJG_W3bD}XQ=f3V52=QeVt?r&lL;3|e8+wm znlcl~0f`AWgocBI%qnx;W06G7*hxwj%$41R_NlnMli2*VS+*2PgoD3vUFUj7^5RFX zFnMl9fmc=!#M3jpH1C8+VmIhsI+-vL#;1Q3*I_fu*SMj8w&MOUalGCbia zI})^y>hRRni z%TL|sjJoL#D&T32{~}#Utf%p7F)(;LD60fJb!+nOn<$Lr7=bfD8G0E3EDk%9!Da%U z)dWhT+QFyfw4xTP0@Gto0jzAX0qmexc=*_mo(6{bGEd8bp{MtEG%tTJC`-f}77G20 zpt70&=s@fER6L9?pb3N9Ly3*UV=#0OCC%}7&gK&C9yw)5?rR83tP#6AH=E5P)}g33 zYNkDdjAR^nmepC`dHRg7kC+wSSElwwXNP@9GJfqSyB=#=0S?8LZ_rDKPVVHFm5q)I zC%w~!zfTRE2dK-=N{rb#5~gVEl`qN#7B^*v8RLh)w<4S{vey$-*iAJ#0`6)KunBRG z7okx1(5#Z!;zdsHvmkgv@&fVZMjL-l*tN+J;CKqgFu^pESF4 zoG97vd}(M#hr!_L&8(J1&Qh=O-v(5$5$1E-2M2^|Xama{%mSy{y%W(~)$gBI#@ zdm$S2%w*tceh7=r*uJ|-UnDV~?mK1?zd||^Dl6e1Lvv;Swguq zjEyU}*oWOTFV4?ZH8g^HBM8m^{1P9k9vF}%&!|xVPeT$|Y^1g8TwGlCW=aUVy1TIn z2q3}1uPu$V+t3U^lY$Tyk2gM}mi&5U+Ca0g+5a~sqdu$Q;bg_+3n6ik% zR2iI$2w~X=6C~p8zDmr~-NBd~lCZEMq^_S2n{0d!lSnG1#b+3(qxJ0Wxz4ETg0)(xhPh9e5#0z0avI#r8>GOw=>PVTN`@|@<>n0~%a?w%g`bph zCo9&|%NC&nO=3tUxo5xjS&$MtmT36+gGrT+gSR`O15j`PKPtpXVSGC$j zJ=SSZtkVv-gV5i=!s9>u@s&?)@#UjtjJOWSnff6_VJ3DA3|?g8+d;tvMXk7v3m2A` z_W_$wYDq|;LKyTiD&hYWo`zj3qPAQlGqhkZ(45hEdmh~~?fE0m9Wy+PP=wLZ(V-Rt zmR;b$NQ5F;&Xe{R5znK=ke@$^TAr?#_&i{Ej_psLmq$y4Z{EE5Dd55QjtUBIvvYFT9TvHI`uj`taj^GsC6l-~o!7;dJ?0GM2Ygew?Fd-fA6@e{fnVSR zo=V&6!v!MIfEEGdJkguu<`b&~1@JpIcR7v0!NH#*{=Rm#pLf%}K*GX?jY{BLFW~7~ z_P<#Ta@p$3*0D!>KB5;j1&+ww+_Q|T)jj&;Sd~?LjFys83RCw7^mzy6^Qq{kPlYm$ zjx0YOZbEDGqzpgX#04s2Z&>w6htf>jOXM~vfw%kq%s{(0dalDys?Mi44p#$T(HC#q zaAFu@P@rO0=tY|luu@oE#ZwFW4;*43<9wFN4$L%aIJ#GBI3CJE!G%`@?!e3!wB^9^ zm1vzrCxV1>ggN8%Z@;H4dZ4!SV2g5!HPf3NN^%Sz55}E*mH~w5d(Kfl*HWaV8#3vg zuec44U6$Ub4X+PNU1}Y#Yaq z9%J#^-_EOt5w3lV8N?0UBD^sOErhCiFo7m%Fmh4sm(2G5yZW!URB{~=vK;KtM@x@yj4sEP7}b7jz0;1VeLzP8C# z$wo#5KVpzKcGJ4Xb&?WNd{gUw*mPH-iOww7nZt^u08Zn+?#%5=-$TU#LaQc?8Auv1 zM3ay1PbMIhOp@LGw@MZuhJ+-Wa={LM6A5^oyJ6cV<}{*jc0^|4{F^b6pfvGe&^?3y zb@uun>qdu=@oe)7sYh5nd+f9R160?`pZdD!!qCivVpD?i%q&mfMBL|56~WPGY+U}v z?ZmnD*RmIu5dyZ_7ow(=bsH+e(rT;-=LXoN4=!Hy`Z2J(3y{#?Vzf14A{&+}> zFFHE6POp&jX?Ee?CMMkG9>aFLJ=960i)+B(6=KPxmcb6CVVOl#`eOZQ8z~l}^jU%y z4rlrinJ3l0BobKmIKl)ANdL=sKHo2G|hz22^pNEs^T?j-Tdiva4#1ckX7*?8e`1VY`lbi+3L=IQ1tU@EDUB+Ym8GG22amejMx&%rSo>v=yWDBCX6&J7_|Bk8heku2nQE@*_$oHUcrGXn*HqNX=ICSk@9(hrw5;?L5HZ zqVk1F`R<%tY)7HUN{~!-r+CpgJu^n>T$9G*J+_)k$DbLAm;uAu3Qy}gFG|?hEBh;< zJeg=squApWYe5HKJTQfP{(WBAFJE;pV_Cl>xo)&Gl8$}4tOga+AlDhp!RAM&Cs@=N(A@Z++}^>Js6TaLC@Y-`wi+ImPPvO zx2b>C%li9xtpLo>pS(lW5ZUivNo`-%9SMgyG)J4Lw)4H~l_>)JxfpMkNH{$Q&&P)g zyR)Mk?w?*S7Lm&P=mn(?J+0{1W4`D~>7;oNu6_5AD zXzs=r6EMRn^37ier|B>5(Ttd;Zao`_q2CBsd+L4Y>Y)Wlt{jr0Z$GacfY*FY(f^f3 ztI)}Q!f=lyN}7z{^|faxx&Omu$e_if;VC2}7&Q{43 zA>y(Bd0u1O9smsw?^^E+N?4MFpqZ}!58bEP3&r|3YnNyN%>d*4U-}4TBOjx$h4$h=oiQq3zkGhR5p1uZSon{88?m z)WbJgA}rXYnV}g$z|MPq2N=CSlr2o!nKa6%07UtJh5FP(izfIvsv5+KdOKI zhW7US1ifXGyW~H=oJ(0`Gw=n`62E+5NK3&KTkGuGhq;z|yb(j)$j!;dO#V z-Rto*icqf065}USOH0e!Ey@>YER9StfYQ+alC+!~H8r(7XBnUsld!O30gP5k<99O*-H_!iI%!mV?f= z`b*q^M)d*sKk}0u!Ms0OOPWRD{rmR=V`I{~x<5Ho{)d?(CqCiL93x~e9#xF2xsBT! z1n`&q^GTwOjwLWcanD7CUFOLL1_wLqj+UzY?pzhq_^_1=Bn?Y&H#3(%ZJ&L>uI>Lb zqpMMaPG3U$Z<-|&QA21(q4shsp$LYgoK47Nc39PJrr4EByDLT>k4@ArrSHXIg{XDk zQ@s~Kjm6G_0rMU(T}dBi7q7Iw@EI9b;TtEAe;qZI(e!4B%*RsOFCyLlBGmGo^1URq z@UlmxHJ~9yzqHV)(ro+Bs`sbAGYx+3fj^a`J(&N4$27wtt6}ZWYtrxNz%&Q&mBBg`MC3M=Rv4To$w0M|?eV(T8SgK8PfTZf6{;<1%l*zfNn1a($zW>lhhf19c z`X5!!UFmk>@>uulHFm7&?Ukg)caC@B!BOJDF-`FM(T^q7i)o(#SK>3JU(`(IN!ONW za`5{&17m7g@O{r8^zVKT0UEdPZGzfCh?uL96WutbwZr0?<;5|V3U!sk1UvWAq|aN8 zIGQ@Vn`@Mf#P5S}W|*O}PJBHaV#w_ko!93%1CO0-Xt;tJsVMq_2uZJf)@RHR&1jSc z+Dy@4W50iGcF6s^YHWa7K4WI6E2EPLR*Qm0zC;=4ONtzBq8wJkzmZ?N-q_+U4*};Y z02EFxtX6{dGdvnC2p9)>ZttQ8vB>eGp{HzQqK5PsBe!zYlT1LeWPuAp?o+kiE(|M# zvSByT?M!okCRrhlzrd@myzjsdA?>lfHGt$bzUy@A5% zpwDp}Gih~`y>*c<<%zo7e|2ZK#!n6lB zDv$sv)BjP z@dvw#(k_~?X{-5io*hJfSp{_Qyt}(s4=FSG2U;-$e@!#z4&)q=ZhXr!Uin~v!6HOW zzEkC_>f|l7zY$d!rIlatv^L8NlNaK!uCBH5*LMFB&?zf8E4=uz7z(pJ9_`u+kQQ%N z_7Yh7WLFz@XUWgz;7dQ#a=^|r+CI1S+;h-sBm{9?RHXtg>|b2(r2coaLLOS^AD2}= z6=PB3sDC;@XRPK@hjA_6n?Y|_@TRfhmBZAd=E;TocoJDr3uvXe-F*>5NNbkokKMd^ z-uyjUOI`AvE6eH`8QLs-UYK5k)5l$esYOv~#tbrzWr1JJ-+{+qdvG0ZddVGr)u0i- zgc<+mONWvy=_;v`_CNXulPxaVD?gqWSrVm?MHq{+5d-A}USXF|z$S;Vq${bQ7>0I- z_2m;x&+=|*D&=^$c>->*2Xi`W=zN)UaPov83#wXd78H%Q#7_1EQ2j8TtP-P@qKhfr zZ3Y9LFeH61%oXXgEW)UM$k{4>Xd_m*4R#IA=f8F$=ZVRL z)uJXxAJp1Ti1OFCkVI1hXw9;_rpshwfX4Wm_iFo9e$7%KkIS;d&uSJ6KDGq8XCBgJ z+0_W1_UnjrSI2m5o;{TJ|2~lEc4X^fC@~;tf{**G-T2wz)4$|u^{dvVf198knUxax zc;ajF0}%%U;rQjO^M()snr3NIlGKDDnK!>3H*=yAbnCC+&X3zLIGvPbpoNY*7jc!rEHpxSd@kZ8QW$24DjfpDNBXqQVlWS&MB$VSnOT-z7Q~B5!&=z;c8%!SV{NR z)6WFLPtyDavUp5I&1fsHc*;)Vvwq7>zBlKlcv%le8;p71$o|wP*_rY>-|C{{NbOxm z$3V1#5j@CUgo3u)s!-6mx0+8%4ByHn0UbvYzx;N;=t;H7hxM9L06orI#xjocv%PEp zMvn-AM-)%#y*siQNFr9?otoii7d_l-Xk--hJdHZ?`o%_LlMXoZAY{6myzqfPipPIb)H>paA^Ynq07X7nxaWOn6T}_iY$2PhBLrXwYt_3rF?2@2hO? z+-6>URd#DGEp28@ZL1zcJXOeXg1R|mTsbvfeDB_YHGN?CQ5Ku9Q{35QGbuyKx6%f) zq?n^EBs#h1SoqF2`={1>NQ9C}%YcUxR}hj`>e$m3RN%Y~cF@1w3-&8xW@f&fYu7ei zZm1#>7El^FD8W?VVWOu6n_gCmY+Ae57dZ;Ey9WVO>4>(%@~*^qrv;w8wql6!CiCPO zS2XZaP3U>v{C1`yu#AiMApDj-=|s{iU;#tBK@QW?9zlb$DB>7pWh>tiQ zyW(=HcGC+0@4)jx{i^R<0F>4L?u>1W@~-tMN0sqaK7a6OE(yIOfE848`v z_gk@{3bVcXI{rh&4U|*4XVJ|D8T@C!ryrss2rFp>|4| zU<>OV-=+`Y-=c#H)oh-E2NC2QpW=hZwItQeHp-Yao0&U1jf{eEa>f%aD%MqGz#KQN z{g}Xb1H?1K4>|jT8hor$yM3nyJgP&l`i>elJ}~@lxmiJ z4VX;1;Z_9s?ju@}rS6`GF(`NDD4}DNMZ(ce!;gJ(=j1lnN~VI@&bM5*vE}HwXJe!| zk6>H*#@-4A4QQ#Fkx}&Rt+!%^5b>O$7deQAhCSfXdwYAEikcc;OG^uuI4#_;n6Q(l zFyFLH?%u+rOu11%;vuIL1O>%w6<$b4i%aQixX4!JGu0qg#cm_#9$5-X(&trh8%*AfjgMvpu zu=#Ye*1y>s5gQ*L{P^hiFAN!~9vM*t+ya<<8}*SEdeR5N*dJf@_(jh0fm(ri6r-Cs zj#ryTEjx8u6&Z0O4LqRBv^)oRRwgwyEB$Fbm1hi=F^^=4H?pD!Ph>yc9~Z0F89fc1 zz&pixl@=r4PL}Xd0RN-Qo`;5!5p`l>0vZ;kHl~qq;Tj$lr8TQ@(+R8FomV@a!8j<( zR_qD0ruAgeN=CdZ62Z4c7B57sc;2%A)sQVFG)#5w)$!-eINjfHj0>l|=Q)$6-y84|2{>S8AB2wF5B`e>UGJ3KXt#Lc1DFf-&-FjM%KIy}{i zYv@H^kf>#Iv7do`F1pNXtCqezkPGAjW3VC6^B zs9DicS>8ym-O%30Obzq+DXVI=c>T!9Squ$Ah38g>Ac*{V{8y#Mx4XrihXSJmUYC^z z@fmMP)0c}p{d;K#G-N({EZPT%tFw7!oqTe*Iuj5&8p_1mhF;d`{&xD9_@74W4lPgC zF{%1ob}|+q-q~P|G5-w7I~LKux+ESS-F|8u!?A5{Kg>43`;6f|8Qw1*bWmkb02}Dk zHbO@JIQTI;jc(@JdtqKpb>qe#7HJ2rxmFs+X+QnKRqwFGvmEen(XK7tXZx}8?(*M}MrPYrY&n5rj|}V&P%-YbGI<2o z4jq+Rdn{m+dfrMGb)JO(j1>;l>ES^i#YgQ#&utwQ?HTUu@+`e&Z9?@Vwy^!_eIznb zE##WPy^n?5I|^9yzsaz!gxx*GYpO|Kre!Io6;|$yFqA90B$Q<3p%VU*Z&Omsu;VD9e_&pCe2tCcT_7^v_XaFelPTeY;>GBIMzbiDh~`GIcX zeo!t*t}V%xgU@uq1&^|HDTGNHvm;?2;Xm*JWV-UUA0aK}6yH3=Gmh<5+l_wuFTEz? zR}Xpd-9RW^@`KZ=RVplVQp+b%CKMXHsQ^U%TIQ#Y^O&JiQ7K9g&t&B1d?m4;LexY{N7 zwY9ZC0xhkjg@5ST%wepdku$=}&0X{_)FpfXc1h)R>cdqL`dVGh5e$KB&R3cLt6NZ1 zL?a;~IX$cy-+Xy$e<^STQd^Z$VE3)QC`nh>YMeS`ObRfN6Dwy3g*`po(6F;(7Znx# zkGBS3zyRzzE0m%OicK?3>+p9ZIcS)*-5{OjpDh7c$cuIrQqs~84(O1>O%`b007BKK~$Uh%t0$R~KT~uE^ zL<>@PxpXCrbt;+ptJ+qfsj`i@D*EC_e%$^Nu>5(g)%$!-#h07+AjFSyI|=#p+YNX- z45&{j8IATwRx!VM-kJ|=K=nXZ`tDTe=-Ij%BGA*>H(RF9{^^tojf_u~KU7C$J5$r$ zf(VJe-+cPdJD~LU%K#A10zMA0q>dzg3CZb=ma*y8y|8?OV5RYgO|vekS{kn&n6$up z@$vSy<||pJOt!mwyMq*$Z7{hlEY+nuLDJLziaK>q;8T9D|2RSx!( zZ@-D6yz%7;X#^W5YlJ+Sq0&59>mf7n32SF9z2lKTnJ8(IkXm|) zQhUVb_ER{A9+w5k&-rP@`-JoBv_;!7qRz)N#K)hi}w}K8gowAHP z5cr@m6Qx^!Cs=yx&5L73b7trAhxXx4t{q_O+ZaO8o(T;P-BU3-mV>#sqn^!85EQoX z^olps-iJk6D4ZdHr`JZ@YSsmuW_-h(`}XO=&V&oTz2!wfEv!ExuY3jG3-xOpGkJCL z0+lDS@v*?S-j`+ybI48i31!n8t2nil@Jk52Dv~Tk^`WRc3Bp4!l-!2saM>^xlb`K< zk4e|5_?tq9Pkm=oSFn_bgE*znY8rt^UTZuUG)UKwm3`HZpSCTw@J=o8k=M=(Bo8g= z^DsL{ip*65)?c^Hd#XMWHlU8w$^8TlPECO40w3}Jp=T%2E>Su>HF)wPOeK4qW8xuuAB5Xm zQ&S_?7%@*?T{0LpjMUTliOb}qQ==T8FsL(ffXGL?cR|IJGbE&oEa1A+n0lj17Pds_ zzcVdJ(b}cg>jeP}0K_M?k~n@T3nzRBYWEa!CC_zZXB?ad6Qkcc9TkF2^Wl*sDdeYVkBXMI zJzAtX08QdH05;7NP}v2teem>Ap2=~S!C4K;u;9@2zj+w0ajIq-ahm*}DeC*JbYIo1 zK4_X*&*-%Uo(Vi>y*?1B;o4C|OXL;>?Qd|yv?ob~7!!pTLzra=OSjo$cJt0I@NUR$ zn%<0i&6mzZttB}|Dvb!s5#%?k&#B7J8hSxr3dPZRf z1)oXR5^YW%fc7;ub;V6?FMCoRQOZ0TWqnQ^OXr#PNuoaj)haJ#63lC#6<@cK5lPywo^K6FR4u*xFxk#Lp=|6%r%zh<_$* zg&Pnj7Tt-7ha4!#q~Rlq1r)1Lg+GoN1#@|%hQD$dUjPV_)(6Rja-SiwowZ=oeS0^; z;^rL!Z!=0`FN|l*EH|S6>{zFcD$s_6G5$)SCo2drk+~;59+>0r916@9m*+iy4cJ~^ zRh!z1@okmtvZZ5{jI0&&*M_&42@H6omUx;ba!b;>AYR6g+uZX*HLvCb0VjJoK|)6x zttiJCoyV;H(frd~BrL=0$(>iuSeCQI3Ag^n|JJTeD@pi)P?2Z!OR3w7XX^jYGmbv; zzov`Xb;ZrlF=|frGpIV$TiE_ECrX#-Ez~YQXI}UDLnfW=Nk6n}+gd-fcKw7M%2J27 z-Jo92EVKgO=v>Y;?^nF4U1W1qynTsHv6LGr*5r!|)E3h)=I`0d3;&R5}!&!kU-P}AEVe(pYR~3 z!Gn&qed^%;Rs2bfnz1*q#G)}-aHXJvE2m6!&f3-v^;mZZ3TIYRO$HCXrj5y3O1JlZ zWiFf|XgGxy|71f-Vtm*#Ca-V>g~V&-7V(Zpkp*9>>B9|L&8w+Ez0sC^L|OBSGlOhI z1R?tQg93}GbN&xR&$kslt&iwT%Stx1Ouft84K(_X(Yp>R@|i*Pjwpxf}ld3f+;orEKX|gfcKD z#|dpk%n)_d?dY5GKbt<}&^a>YwY{Hpt*^izBcYd?>(MHsEI(@XfaoMY8U7?8NL4nD zXrL|bg@P;9q65Xu1M_W2X6$siM*f)7G%xnVoynf96dB++zjj0y@OsHVxTN7X^WJJP z;0}gtO?V8m6?jz6@f|)#9dJ<->U21y@s2$Rt-NJ>Jd3G(Qu%b?)>?+9@>299R_wMx z@rBzu#Vg3CxgTrlGU=~L$U;xJ#FAdNcYKZqrEpZZ#Xs(#TFp;w|~#BX!h z!FR6CAQfzB&S#@@^x4v-h|IP0uVLoMMRqLFe+fv>Un+6@@4=gc%amOv&i+Nh9#N_} z*vK(+o1!o0Zy;AEQEPvdv;l__5UrD($u%P%vwxZH+2-mW*G~^qH>IjPsT_7sb7B}_ zh)`_pkxJgE(^XV&@5U3I$Qk?p+#c;z=l!%y?n5m!Il&Fouw#UTq+n5!el@3uscJ2~ z&iUH>t=s~yc@fqmt?PjCPi7_kpg3byLLdv57M=h&hhZ&{WbN>og6=GnOi^kvjxg#w z`Wdvf(TRu4Sh!n zIJ=Y&4h>m9`%IsuVu1G%sBS`!RS0HBYkwFfNfVlhToV-{9+ayBAgrJI`EpIanf&Ep zob@co<>|~xlqB@o-)uwk-g~E$#tWTr?3Y2h91l|xrBE2*>f)P~uo%cf;h9H0ffyq++({*?oo~SRaE$|yKno=K zPQZx{MKwe2B3?pbyK&CuRVt)i&Cu+f83;+&Q%h9jSu^fMgGRqtzf{5JrMCB0Q2z9r zV2#{R&~DjzP}v+#NA9)0<5Je)?K-y5k)zsnoU!M~b~59VMw9Ep>_h8W-{$jR{wHT> z{?)1yu2!!XpCO#q2+~tEdZBH9QT6FjxZiRfU~^k{A0;k*{Diq`*os?Ipw!`CZ@l0j zitBlnTc#bV{^VMK#pg2udKi!#m8R%WWdh0swlVB>3M{?vR#;tt@+V3o58_GnA6SIA zES}Y58>RHFm6{$7xETJ%2*a~Mg?67h(>40cX3Ms)aPjjUrNF*GHSTwN<<-^`KJ9=u z($78PIrO#@W;Hd7GsJgbKMKouMk%BU0p2nG+}^;7cysrQ**mHL0|wO@uWFPL|csi)ZLFcaX-YdAS6 LWpKHK$+!OxyaC!tEdhdZyqT;|Py&JmHYXpRZ5(1+1 zDuhVyAPF5pNeGEdTr9mk;80ic?%mp87gnGHUWv8gPs8&Nf<8nP9_%S8hFoS z@&Ge@Mi*)qN(+3^j`chb99({IrvZT;F@1ypCuJ&V;4Yp?oCWS0^#05&8*mu8HUa#+ z`KOl_z=>(tKfCDuOy-j|n&z#}!t72gm4rah9<5|69U2~!S4Hd@K>EPY45w*n0=Mm_ zwP=oiboaRE{us192mvPXul}q5VtzSJYZVhov(K&1p-}3k)C}`cQB7w)Zi6-6s>cN} zDM91WW%Quimp?*0wbnK^x~ET$q2jog2~u`*+aWS?)q=WHtKEqR5j%>vI-O;8V;-lO zo=O0>(+!^h$WE?(sR(EoJj*6s;QM~<+qXF2>iu4JZyRjfa%$V+lL0MyWXBOXC2Akx z1gYcY5IQ&N7lB=fEzU+ly_a3My8Vr0I7%96Ki58dVQ}A?=q*D`PO_P1A^8Xy)2q=@ zXh5O&(R4AQlQ21P@u3WE)O=EKFw!P`UN8<}#v<=@-|*MSeT{%yH(XxXA+ESQL=HXI zp+mQKZ+}}Ukk`=ao*b8|CZ<@{^7)*?h`sGH<2e7|!2Bbkly&-k(@QO;sG^o6QI5pT zX95-|#n?Kc-h=(Hk7VJA3yUKv$x8BjVS>}S7c>HaY4mb$>WI#RV&ZMZR$iK;Qc~Cs zm(o2lnoE@k`xskQx_SXb6H36F9A$YWx;r470WCXBYK%ipPb9c6{~~)^So0HN1iaXO z*WS3gyovp=dlzQFVhPnv_m)S^7A)^aPK@?{5cIHgiLdK}AWn|xSrzX!Sv2yv^|3(N z^V=r33F#*MoaX%3g?B2!7^2=t=t1ndOD}{`S<&2`1`O;VKk#-~d5U`{?s$3fWcFyc z=8>WBlsc&{L^^HFr-5?NByaLo2Zbik_l47w7oWR!>KcVCa3xIJs&1;W$Y%-`R=It; zK1UE96q+{3+B{B*=gKh27K9V&-4z7R6f3A zn4WMeYmF6YCrt0&3K8}}gqF!w{mhYiey~XWy@71@RH~mrTLnWNvwkjXN2$lOOkEB^ zLcW2|0sC;ga(sV_w&z>mdG|1w}h*$_7@uuW5zv$)Vcg1ohIa5 zD7E(-bl6uHHkwq1(I_vpkP2#&=4BQ}b$A9H;~fJb-Sc(P!J;b@F~xXWB7#8qDH(a= zUV#yN>nVs>yfois9XX+-V$%=RilpP%9 z%f$G2A`XXp_uSY6E5LPAbI1m|NG^Eky<$8)9A^1TV~Wv|BiDd8UW#(fjQr+y|D7kv zj=QJq?%cV<^6IXwr{_Qq%?$mA3EFl;7Z(?UnqgQ8&sS&b*&4}~y>GUJ^d5K|BPa%l z1)yPzdsa*(`B=8Hdmj}Hc%ZL83~)W*1m$dfO934WJoMGv{Ng*w;&}^*RLY{jfd4{B z{4e4Z5b#`1Pf2WpeNNpJ{Ne2FUHB3zOPX70V+|qDoIT~?mW)Ap^bQYl{Pa_T`gNYL zurT`zAf=o|Hf0*lE52y^N1HnX9gog8WB)|7{%@xCmvBLECQ(-@QTbYP^9)fXyATv7 z@>^I5R-Hz31UeDclme?g3P5lM6zcY_Ec@Tz=wF6}=2U+Z_pV`Ot&%j<*RS_ z%vB4<)NEU|jC7O5Jq`SO4gH*rQk~JL$qpFk8T<$L=TDz_c=WTUwYWE$^x1@R$0LjY zXxU`-L}_|TUT^h+Hbd;x*bJ{&tEY9II^7`KYg#8LgxyLjZvuHrzqFWn6R@|6@b&fW zSXjvGzvHgDuJhW`3d=XCA}(|#IWki7iwwKaS*Heo5S}Q)4Y(FH7{lAJj=w=7vILfY zD4F1R=p=67q=V>WQK>gP)aWD)%R7wQo$h%-eb{A&%mW}(lx%x#GdLJi=c%8w4G6v*W9$iw>nKioA8Y=m*g~B7_wS zF*yJAA=J*D(k)-j7YMP`g^!rU#vcN!)DHzl>(L`aExuyct4l)rYBNWcSLRxFi%X6i zkB_fPDzlC3&q=|5^uj&f-wKHr2~8i1)%Pp1RRZO-oJBqB|MtF^j`n%lg^-XCojUjR zxCS)Zaf#gA?Pj8BH!@u-)%%7mVH#}?ZO9c3Y;se4A+i}Z#3NG{F$xh!UV$RO4>osG zjtocCHb3KsTDIywWg1&KjGv-zD{CaPC;mz_S->bo{BTsx(BNfeF?gx|yt;Z*Or|ee za>*S#ir0tNnM4woPKNYszpesE`ulwHTGtw&8_u$2WztRs${rp_`QQV+GiT29WSk*N z^MRExB1F0t0dAN5zK+rUA(b+%dfcFVh9tHqd@#;T5AFsoakDblaKp3jEq10G)tL?~ z&fUyRiUejKr!H-!3?L@ay*lql__~@#r4MGRbsXi9UsHn{20fepzS%V*%sB%{Iqf05 z0r#4kJ_roSP__K9qoIMGP7|y}b7HB7UqjW{?B~6?f07tVPY8Cq|2^lCZAOs%Z31g1 zQo4D8KHU`n{ts}AQNI-JZ+8%p;D`Qbx=q4V67oYG^@Xpw6gnQ#9J)QV>2EP zch0Z(W`3R^;if}>=JrDL@1hjaWQP-u>A}&Bzc4W|J-E&i-_oKYPX7!%;C=q;rItqn zC`b({fkWPf!?kAY^muM!v4_}+iWulUJ&=AM<-DsngZpw){&!Sr`c5T1g?c{2k16iw z-g8W{fPTEw{g`){kKz}a`FEom;!_KzjuWLQ_6(baoJAxEMR2b)j(tJ zeIzUocg2|L3!OtagX5XR{XR^LyW1+147!r&JS{K&4Pn8MK!Y2?)2Tqv-CpQzl1Cis z*NQ|KHcNDCj>XflzPy}ZFBXBXvLF04C~!JEADo0w;6)Y= z^S$b>+#YHX62ms}&4<{VYp!>+X{h>7z7;xrN?0alP8_DSS6LbLg$p8;E8UW2lH&38 zmVK}(L#s(Yp*rS*EPFx@EOp8T!@S~sVXQz+1~hXD;N+FTw|is~@tCQOvv6TPh$?m! zN>@AcK>VGmQKQMnr=n(>x4J)>M#3^Lmz-sP=^l11YQZUvK@m8a5S* zWMs}G)Kz?RSb;6$Bs}0!6)U6yePYdi*Kp07A=bPv^JhSzKoof61ya0t_H^Dz>Joua zvP-Ho82qvAu{jon~ommTAUOw9AWLD@q)PSWDv6~Ik9^b8ZSpd7%xVwEEbEWc2y(?Z>i1|A{Q7| zP}&_{qV*?DNx2#JJ6e@{QNQQi1ntZPwJsBe>%=HN~)K=kO5LXG7(`)_DCm zE^TVqM)G%L`;;zYLJW0tzV>yCf8$Ka`AEF#Gd%J0D*RVroYI+u%-O!)ygoluR|4up9 zbN(93Llhk)Q#Yuc8CTx@?y3f{1hW6HGY?iq%Fzfm)7X%rqAB4%Sa(&twMd}B(mKLR z4bfiyeD}~|wbv38f%2H{3fjOpIMX!iet)Ir+x5~%*dn{XW6q;#UUGsfLCs2YJNfv) z2JZ8bQ(`jFT9VHNsZV^Bk(4FU*AdnY5u3<5AsJbBZwI*Z+Gxq5o)RQRVFl#r`-`Oy z;+>4zHkBi_uIqIEGStUl=R}m|7fT;I_6)+h>JmI+r5}L>OHh&3SsfY0E&;2*_}T-w z@SHHb#=OIc1_i&M?*f6pfP+TJU$kx{_UY;5;Kn_^p0aZymlkO3NkOzxWP3{7(zdxV zA~)cT2C9*59lo~rR+{=~!u&QRC&PHd%{USm<2!dewN8hrO#iLA;_iv1DgQ7>u^A81 z;|_UreF&m*0!7ya)iHND_4-YKu0jDVspvkP71NQBpiOjELR}?WA*=6`yF#z8I?_tU*Qoc4YaDteI&AmKo zL^%L;2n<_ev^UixVW8&W=%~&U|10B#3u!W-qh~1=AUfYi1G8z*Tl(+thCx6lJbzUQ z_~-BEUlZ-3o8>-7nJj#-%it8ExH#QakCUU$!fm_*T+|@qG7#muG^=l*n+6%3Lne)! z|I<1|>|;-k;dUn{)K)E;c9U-SLGn@R$u79p(5~bHio8St;DVryK>-NVZgtFUh2W*q zRLYSJ8aUpGW8ykCT@-ZkWlz_>ObmFYe;UuV#j9_!i#THhK+5x>dSErUC6Ub?`g@tT zgT=N2YkSC1u!EqM1@!snNKbno@Wv@JHUD`X_vj^ed=IoARQZ|z@OuT;yuFe}Lo z<-b=^F`clUgJ6y7`uv%1B_oP8l z&u!JGGA=(805&kP3F73>hZIE=Ma8x)9A?8i6qdUcE@P}swmqDu0#laEjHwm;4%7^n zl^^!akQ9|pvLQ^qCpdfRX-xuBBv2#NRa6mbkjzZR z=GSn%sGrcr{#0X@LeLFPPEIiynLuCeR4h{+oMX5~Ry1WQW~su5ouPts(d?$bTZx+k z(hCU-0vE2z+Dj*^2+DrA8>6Lex%5=2#AZ0@ zG~Q(KUEQGD?-Fc{maR(WS+PW`+S21^wWLff?S&*He72h<&_}aA(+i4Nw{x$ro3?6d zhmo(Z2Xfmublo&6$eI@McCcxq==)Sra`$V#$O^*7e@jqVnTJIcu?kr- z#|;Flhv`Rg`!K4z9tsqIYp=n)2~M3SZ0@@VgX^;H~oiQ*Pw*KCA)*pQJ*U z9gGR49yYHZ5W-dTK)BnVUpagw1cLV=Dq&v7eN}8(_ZCBeg)*PLh)-#8D1vj z)_P^yK9TB~O--$Zi#<&)?muNGg6eH3wuFyQ-F|AW9y)(DDQVqNE6XFj;DA<1dgF(T zzTIj9r^|zNF{Ol=7098$j!vuQ7Retxow`g2FP+Ba$!_m=pCU!%2OvaWy}4v4gi%_= z4UX0lGXqQfgd~=XkhNdYmI0&4DVn`5LrY8|LzWii_=^nwT&{?$c-nqYhtayC9qYJp z|78bTiV>O9j1S9;#KSVbuPpF3_Yx1r)KOek*ifpYx%c6?-iV)J%o9A!Ycxa}Jr&X5 zUsa+o)vkGnpJHEGmFJKDCNSzxZ;?OYvo(Wf#inRX8I+JY0>2WA{ehR)XRK7wfAXmW z5-+t8QoA=>3s@FMyG=V=CKWHsCgpe?ltf7M=+nvT{5_{`?nF9YVM5T6@Oy8^M)LEA z{WBliWHojkKP={V80QPX3klA{U^j#>A`*7ic(c+p>iiq7NhRM0Gc+7lFXT zWF3zbaa*zst{)AaPt#aTZL?xEd8IIfee!#fnC856c{FLkMVw5&N3eQr*1zK7>sYak z`If$gDb5JJamf7AHgHXsHN#D$`#x-(a5vpx<0~f@Y0QfKLC9h_Olq`z`Y{2j%DKGo zfga8o7f`d7b5;zaD5vBo>GN_Gohz+vm7S4|f$U zD(ZbTzcp3n3pY^+oZ69$%pcUz3fFzAt}|B>)VcH z#9n%3;63}HTGedqwKb7`_0Bz#zt>1N#$Q$(EMe?9aSIcAAvethNoh-9kfz?SO+J(( z!7|&Yhu=h~sf0}Z@N!GQ)9JeX1%9zBmwNrKyc^1$rs-*8bTHq&mD9JNoB^Xqi<2L;(PNKgHTVKNKIy5YzD!4)32!^~}<$v^#J zEA-7$ktaKmNAuw5hCLeW0S-yKZF8~{WM3j?6k!1(4Sn-GKl6wL7%CTH-Om9t{oi@u z|DYZHPmJ^bgNuGVSQzTR{=?aye?EW>EDL}Z&NmwLNQ1Hmq}K0Sr@<(I)13}jO&`}F zOcI7O(VOZQf;@^{HYV?WkQ{#&FE{^_e zP*d0iMhi69m$(Y?iUD=;tI9WH4&q4nk}_VKwdbgFGJkdGC!c!8{9RbT8!<-2BPmJ?{uv3e z8>DVe%U^DZYrf#`{guIV%lcgGXIn_+txHcK1V35VV!gcpGcJY6B(+ygbwT4)ub^T( z3o)qyp-UwhHI;EMk$f3-=38zHLttX;?^eF&($i2VDxwj;=q7Xz?`6JZ{o1uZO_sp6 zD!LzT2Pi!&S01n!W_+A2@+I*#a?OILKZIjK-SZ4VnLy_WUXC2Qh^D0N3t7x2NBZzy7}z z^n)n(hdAHnvc)*Cs{~YYeQxd@f_O=V8Xs8Fzt%eFnms<*zP|{#Gi)Z*=Fv@Mtb82g zusAAqZ((O!2wL5rzH4C(A*Yh)Y2D5y2ik`CZ}p?%|ZX$CoU=uhKtqDw~?J4m{X= z%gD(1Mn*BNXKiP61bVM2U5l=~miZ1(YDxxug??)jL-PvT=P~KmZo`QNCk(6>%O2zD z_C46$K&#bYUe;bY+RR&t zm0N_(DV?ZPXg_F@%%y8gsk@41LZN%?$n)zRA6+el@8;T*<6dNbIoxe3ONXsi-0BV+ zE9#d|8a-3_3AY<
tA@gW1h63> zR!$I=AK>{NyJialg7XE(FpOtx33d#=@ib?|>_p6gv+j}-x&~%hWFm%8edpcN7S3oTmijj1AAAhtiH z_zt0ft(^rF0}R_7KNh{;b=WO(UF>gtW?tv|!fmCkbIJAz=`3wWORMbX5Xy{28e$x^VCC+|;;+L>?2o#{=j< z55xV%xw!;ioi+y5#dQr;$%*p%POyQJ4Ka4!AU7s2)QSgb_b@q#SJ2H~uvegZSnco+ zX^8iS%d5H)e#2tjRis-%l*QFMEnYYE`%mprnnOU(WVr!!>WLwe0CNj)hNQ>h8mewF z>%avRRvx8aOzz0n4&0UI46n6y&oQ~d(p@FVk@$Wm9?f9zU+FSXm)r);=f|cYpH>)V zlVsQuHfvs1UoSO1Oe+-*B(4~L+cdpZvsRhHQr`a`x{QQXzY`)zpi04ofM_hP%@#Hg z!cKe)(R=%0MjG8MPTWP0bS9asD}t1%--A~fH#e%ZIwxPBlCu-VuKB&aZ%4|#^I)!| z$DgWlV~%ICvebKTmtBSuod%zOEx4Q){6lp2(YvfBz8$ElSV+U&H?VrX7A=IP_w1Cn zwar-Ky)NC(kr$`l#J-Dx?X7@(}mZD+*BjP>O0%68N>bucb zxNnEa$+lM=Sh(Ldbgv^h%o-V zZ7$-|>Ik$E5IeQm*Xu+a#3420$Ca^p4I)Z8L2JNEqSfhC=Qom>kW<`UAuGHr64}FL z>b?%^3kyV&6n|~^x@qZ9!mqGa197;oy^><_Taznb`1{BX6Jq@V9X*Ku>xjjEGz76$ zFS2a(Gdq{#LmIy8K7wBrec`u5|E}lZQk9Mdpye#I*ws{o29(X0ScZ&lG`gEAefq$e z5SvL`l5EmslKW`$^-%l%LtR1xtW|Kc93$4v@F}nQ+wri5VN=?V2xGs&c3&PZ4dD#Q zNcnqq6RTl64SL*u+MK60=KmnCbR$8E$B)|g2&DdY5op};?Op?#8WmRD8o0 zW>%*`pc>_F$TQjx6YtmoD<|g)&@=GYxZ<=M2kjG}?GOJ**dIZ8|8B3;^8wY||G0_y j4+8wR7v19CKB2+7aMHE#iaG-0gC5+|xm%(7=*7PQ%!>*< literal 0 HcmV?d00001 diff --git a/en/device-dev/driver/figures/user_auth_architecture.png b/en/device-dev/driver/figures/user_auth_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..08dfa16e0015682b20f51767dbdcb4da299842fc GIT binary patch literal 20580 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 E0nLCG5&!@I literal 0 HcmV?d00001 -- GitLab