未验证 提交 46f26369 编写于 作者: O openharmony_ci 提交者: Gitee

!4655 #I59IW8完成,请审批

Merge pull request !4655 from Annie_wang/OpenHarmony-3.2-Beta1
# 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**<br/>
......@@ -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&lt;Object&gt;): void;
Obtains the **Object** instance that contains all KV pairs.
**System capability**: SystemCapability.DistributedDataManager.Preferences.Core
Parameters
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- | -------- |
| callback | AsyncCallback&lt;Object&gt; | Yes| Callback used to return the **Object** instance that contains all KV pairs. |
**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&lt;Object&gt;
Obtains the **Object** instance that contains all KV pairs.
**System capability**: SystemCapability.DistributedDataManager.Preferences.Core
**Return value**
| Type| Description|
| -------- | -------- |
| Promise&lt;Object&gt; | Promise used to return the **Object** instance that contains all KV pairs. |
**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&lt;void&gt;
......@@ -322,7 +371,7 @@ promise.then(() => {
### has
has(key: string, callback: AsyncCallback&lt;boolean&gt;): boolean
has(key: string, callback: AsyncCallback&lt;boolean&gt;): 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&lt;boolean&gt; | Yes| Callback used to return the result.|
| callback | AsyncCallback&lt;boolean&gt; | 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&lt;boolean&gt; | Promise used to return the result.|
| Promise&lt;boolean&gt; | 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&lt;{ key : string }&gt; | Callback used to return data changes.|
| Name| Type|Mandatory| Description|
| -------- | -------- | -------- |-------- |
| type | string | Yes| Event type. The value **change** indicates data change events.|
| callback | Callback&lt;{ key : string }&gt; | 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&lt;{ key : string }&gt;): void
off(type: 'change', callback?: Callback&lt;{ key : string }&gt;): 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&lt;{ key : string }&gt; | Callback used to return data changes.|
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- |-------- |
| type | string| Yes| Event type. The value **change** indicates data change events.|
| callback | Callback&lt;{ key : string }&gt; | No| Callback used to return data changes. If this parameter is left empty, all callbacks for data changes will be canceled.|
**Example**
```ts
......
......@@ -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
......
......@@ -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.|
......
......@@ -43,12 +43,15 @@
- [UART](driver-platform-uart-des.md)
- [Watchdog](driver-platform-watchdog-des.md)
- Peripheral Driver Usage
- [Audio](driver-peripherals-audio-des.md)
- [Camera](driver-peripherals-camera-des.md)
- [Face_auth](driver-peripherals-face_auth-des.md)
- [LCD](driver-peripherals-lcd-des.md)
- [Touchscreen](driver-peripherals-touch-des.md)
- [Light](driver-peripherals-light-des.md)
- [Pin_auth](driver-peripherals-pinauth-des.md)
- [Sensor](driver-peripherals-sensor-des.md)
- [WLAN](driver-peripherals-external-des.md)
- [Audio](driver-peripherals-audio-des.md)
- [Touchscreen](driver-peripherals-touch-des.md)
- [USB](driver-peripherals-usb-des.md)
- [Camera](driver-peripherals-camera-des.md)
- [User_auth](driver-peripherals-user-auth-des.md)
- [Vibrator](driver-peripherals-vibrator-des.md)
- [Light](driver-peripherals-light-des.md)
- [WLAN](driver-peripherals-external-des.md)
# 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<sptr<IExecutor>>& 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<uint64_t>& templateIdList,<br> const std::vector<uint8_t>& frameworkPublicKey, const std::vector<uint8_t>& 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<uint8_t>& extraInfo,<br> const sptr<IExecutorCallback>& callbackObj) | Enrolls a face image template. |
| Authenticate(uint64_t scheduleId, const std::vector<uint64_t>& templateIdList,<br> const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& callbackObj) | Performs facial authentication. |
| Identify(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo,<br> const sptr<IExecutorCallback>& callbackObj) | Performs face identification. |
| Delete(const std::vector<uint64_t>& 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<uint8_t>& extraInfo,<br> const sptr<IExecutorCallback>& callbackObj) | Sends commands to the Face_auth service. |
**Table 2** Callbacks
| API | Description |
| ------------------------------------------------------------ | ------------------------ |
| IExecutorCallback::OnResult(int32_t code, const std::vector<uint8_t>& extraInfo) | Called to return the operation result. |
| IExecutorCallback::OnAcquireInfo(int32_t code, const std::vector<uint8_t>& 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. <br/>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<OHOS::IRemoteObject> 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<sptr<IExecutor>>& 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<uint8_t>(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<IExecutor>(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<void>(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<uint64_t>& templateIdList,
const std::vector<uint8_t>& frameworkPublicKey, const std::vector<uint8_t>& extraInfo)
{
IAM_LOGI("interface mock start");
static_cast<void>(templateIdList);
static_cast<void>(extraInfo);
static_cast<void>(frameworkPublicKey);
IAM_LOGI("register finish");
return HDF_SUCCESS;
}
// Enroll face image.
int32_t Enroll(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo,
const sptr<IExecutorCallback>& callbackObj)
{
IAM_LOGI("interface mock start");
static_cast<void>(scheduleId);
static_cast<void>(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<uint64_t>& templateIdList,
const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& callbackObj)
{
IAM_LOGI("interface mock start");
static_cast<void>(scheduleId);
static_cast<void>(templateIdList);
static_cast<void>(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<uint8_t>& extraInfo,
const sptr<IExecutorCallback>& callbackObj)
{
IAM_LOGI("interface mock start");
static_cast<void>(scheduleId);
static_cast<void>(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<uint64_t>& templateIdList)
{
IAM_LOGI("interface mock start");
static_cast<void>(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<void>(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<uint8_t>& extraInfo,
const sptr<IExecutorCallback>& callbackObj)
{
IAM_LOGI("interface mock start");
static_cast<void>(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<std::string, UserAuth::ServiceConfig> serviceName2Config = {
{"face_auth_interface_service", {1, std::make_shared<FaceAuthDriverHdi>()}},
};
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");
}
}
}
```
......@@ -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<sptr<IExecutor>>& 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<uint64_t>& templateIdList,<br>const std::vector<uint8_t>& frameworkPublicKey,<br>const std::vector<uint8_t>& extraInfo) | Obtains the public key and template list from UserIAM after the executor is registered successfully.|
| OnRegisterFinish(const std::vector<uint64_t>& templateIdList,<br>const std::vector<uint8_t>& frameworkPublicKey,<br>const std::vector<uint8_t>& 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, <br>const std::vector<uint8_t> &data) | Called to return the subtype and anonymized data of PIN authentication. |
| Enroll(uint64_t scheduleId, const std::vector<uint8_t>& extraInfo,<br>const sptr<IExecutorCallback>& callbackObj) | Enrolls a PIN. |
| Authenticate(uint64_t scheduleId, uint64_t templateId, const std::vector<uint8_t>& extraInfo, const sptr<IExecutorCallback>& 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. <br/>The directory structure is as follows:
The following uses the RK3568 platform as an example to demonstrate how to develop the Pin_auth driver. <br/>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<uint64_t> &templateIdList,
const std::vector<uint8_t> &frameworkPublicKey, const std::vector<uint8_t> &extraInfo)
{
......@@ -526,8 +526,7 @@ 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.
1. Set a PIN.<br/>
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.
# 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<uint8_t>& publicKey,<br> std::vector<uint64_t>& templateIds) | Adds an executor to obtain the authentication capability. |
| DeleteExecutor(uint64_t index) | Deletes an executor. |
| OpenSession(int32_t userId, std::vector<uint8_t>& 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<uint8_t>& authToken, const EnrollParam& param,<br> 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<uint8_t>& scheduleResult, uint64_t& credentialId,<br> 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<uint8_t>& authToken,<br> CredentialInfo& info) | Deletes credential information based on the specified **credentialId**. |
| DeleteUser(int32_t userId, const std::vector<uint8_t>& authToken,<br> std::vector<CredentialInfo>& deletedInfos) | Deletes a user PIN from User_auth. |
| EnforceDeleteUser(int32_t userId, std::vector<CredentialInfo>& deletedInfos) | Forcibly deletes a user. This API will be called when a user is deleted from the system. |
| GetCredential(int32_t userId, AuthType authType, std::vector<CredentialInfo>& infos) | Obtains user credential information by authentication type. |
| GetSecureInfo(int32_t userId, uint64_t& secureUid, std::vector<EnrolledInfo>& infos) | Obtains the secure user ID and the enrolled tag ID of each authentication type. |
| BeginAuthentication(uint64_t contextId, const AuthSolution& param,<br> std::vector<ScheduleInfo>& scheduleInfos) | Starts an authentication to generate the authentication scheme and scheduling information. |
| UpdateAuthenticationResult(uint64_t contextId, const std::vector<uint8_t>& scheduleResult,<br> 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<int8_t>& challenge,<br> uint32_t executorId, ScheduleInfo& scheduleInfo) | Starts an identification to generate the identification scheme and scheduling information. |
| UpdateIdentificationResult(uint64_t contextId, const std::vector<uint8_t>& scheduleResult,<br> 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<AuthType>& authTypes, uint32_t authTrustLevel,<br> std::vector<AuthType>& 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. <br/>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<OHOS::IRemoteObject> 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<uint8_t>& publicKey, std::vector<uint64_t>& 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<uint8_t>& 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<uint8_t>& 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<uint8_t>& 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<AuthType>(oldCredentialHal.authType);
oldInfo.credentialId = oldCredentialHal.credentialId;
oldInfo.templateId = oldCredentialHal.templateId;
oldInfo.executorType = static_cast<uint32_t>(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<ScheduleInfo>& 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<uint32_t>(param.authType);
solutionIn.authTrustLevel = param.authTrustLevel;
if (memcpy_s(&solutionIn.challenge, sizeof(uint64_t), &param.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<uint8_t>& 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");
}
}
}
```
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册