@@ -22,7 +22,6 @@ Observe the following permission management principles:
- When an application is started for the first time, avoid frequently displaying dialog boxes to request multiple permissions. Allow the application to apply for the permission only when it needs to use the corresponding service function.
- If a user rejects to grant a permission, the user can still use functions irrelevant to this permission and can register and access the application.
- Provide no more message if a user rejects the authorization required by a function. Provide onscreen instructions to direct the user to grant the permission in **Settings** if the user triggers this function again or needs to use this function.
- All the permissions for applications must come from the [Application Permission List](permission-list.md). Custom permissions are not allowed currently.
## Permission Workflows
...
...
@@ -54,6 +53,7 @@ The figure below illustrates the process.
3. A low-APL application can have a high-level permission by using the Access Control List (ACL). For details, see [ACL](#acl).
### Verifying a Permission
To protect sensitive data and eliminate security threats on core abilities, you can use the permissions in the [Application Permission List](permission-list.md) to protect an API from unauthorized calling. Each time before the API is called, a verification is performed to check whether the caller has the required permission.
The API can be called only after the permission verification is successful.
...
...
@@ -130,7 +130,7 @@ The permissions available to applications vary with the APL. The permission leve
-**system_core**
The **system_core** permission allows access to core resources of the OS. These resources are underlying core services of the system. If these resources are corrupted, the OS cannot run properly.
The **system_core** permissions are not available to third-party applications.
## Permission Types
...
...
@@ -153,6 +153,14 @@ Permissions can be classified into the following types based on the authorizatio
The user_grant permission list must also be presented on the details page of each application in the application market.
### Permission Groups and Permissions
To minimize the number of pop-up permission windows and optimize interaction experience, the logically related user_grant permissions are combined to form multiple permission groups.
The permissions of the same permission group are displayed in the same dialog box for user authorization. A permission in a permission group is called a sub-permission of the group.
The relationship between a permission group and its permissions is not fixed. The permission group to which a permission belongs may change. For details about the permission groups supported by the system, see [Application Permission Group List](permission-group-list.md).
### Authorization Processes
As described in [Permission Workflows](permission-workflows), you need to first apply for the required permissions for your application.
...
...
@@ -163,14 +171,14 @@ As described in [Permission Workflows](permission-workflows), you need to first
- Authorizing a permission
- The system_grant permission is pre-granted when the application is installed.
- For a user_grant permission, you need to trigger user authorization through a dialog box during the running of the application. For details, see [Requesting User Authorization](#requesting-user-authorization).
- The system_grant permission is pre-granted when the application is installed.
- For a user_grant permission, you need to trigger user authorization through a dialog box during the running of the application. For details, see [Requesting User Authorization](#requesting-user-authorization).
### Requesting User Authorization
The procedure is as follows:
1. In the configuration file, declare the permissions required by your application. For details, see [Permission Application Guide](accesstoken-guidelines.md).
1. In the configuration file, declare the permissions required by your application. For details, see [Declaring Permissions in the Configuration File](accesstoken-guidelines.md#declaring-permissions-in-the configuration-file).
2. Associate the target object in the application with the required permission. This allows the users to know the operations that need user authorization.
...
...
@@ -178,10 +186,10 @@ The procedure is as follows:
4. Check the user authorization result. Allow the subsequent operations only after the user has granted the permission to the application successfully.
**Caution**
**CAUTION**
- Each time before the operation that requires the target permission is performed, the application must check whether the permission is available.
- To check whether a user has granted a permission to your application, use [checkAccessToken()](../reference/apis/js-apis-abilityAccessCtrl.md#checkaccesstoken9). This API returns [PERMISSION_GRANTED](../reference/apis/js-apis-abilityAccessCtrl.md) or [PERMISSION_DENIED](../reference/apis/js-apis-abilityAccessCtrl.md). For details about the sample code, see [Permission Application Guide](accesstoken-guidelines.md).
- To check whether a user has granted a permission to your application, use [checkAccessToken()](../reference/apis/js-apis-abilityAccessCtrl.md#checkaccesstoken9). This API returns [PERMISSION_GRANTED](../reference/apis/js-apis-abilityAccessCtrl.md) or [PERMISSION_DENIED](../reference/apis/js-apis-abilityAccessCtrl.md). For details about the sample code, see [Requesting User Authorization](accesstoken-guidelines.md#requesting-user-authorization).
- Users must be able to understand and control the authorization of user_grant permissions. For a user_grant permission, the application must proactively call an API to dynamically request user authorization. Then, the system displays a dialog box asking the user to grant the permission. The user then determines whether to grant the permission.
- The user may revoke the permission authorization at any time. Therefore, each time before an API associated with a user_grant permission is called, the application must check whether the permission is available.
@@ -18,7 +18,7 @@ Use [huks.generateKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-
>
> The key alias cannot exceed 64 bytes.
**Sample code**
**Sample Code**
```ts
/*
...
...
@@ -106,7 +106,7 @@ Use [huks.importKeyItem(keyAlias,options,callback)](../reference/apis/js-apis-hu
2. Encapsulate the key material and key property set.<br>The key material must comply with [HUKS key material formats](./huks-appendix.md#key-material-formats). The **inData** value of [HuksOptions](../reference/apis/js-apis-huks.md#huksoptions) must be in the Uint8Array format. Encapsulate key properties in [HuksParam](../reference/apis/js-apis-huks.md#huksparam), and use a **HuksParam** array to assign values to the **properties** field. The key properties must contain [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg), [HuksKeySize](../reference/apis/js-apis-huks.md#hukskeysize), and [HuksKeyPurpose](../reference/apis/js-apis-huks.md#hukskeypurpose).
3. Import the key.
**Sample code**
**Sample Code**
```ts
/*
...
...
@@ -166,7 +166,7 @@ try {
Check whether the key exists. If yes, the key is imported successfully.
**Sample code**
**Sample Code**
```ts
importhuksfrom'@ohos.security.huks';
...
...
@@ -247,7 +247,7 @@ The following example presents the development involving HUKS APIs (using the EC
5. Import the encapsulated key material.
6. Delete the key used for secure import.
**Sample code**
**Sample Code**
```ts
/*
...
...
@@ -586,7 +586,7 @@ async function ImportWrappedKeyNormalTest() {
Check whether the key exists. If yes, the key is imported successfully.
**Sample code**
**Sample Code**
```ts
importhuksfrom'@ohos.security.huks';
...
...
@@ -632,15 +632,9 @@ To ensure data confidentiality and integrity, you may need to encrypt or decrypt
The HUKS operates data based on key sessions. The general process is as follows:
1. (Mandatory) Use [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9) to initialize a key session.
You need to pass in the key alias and key operation parameters to initialize a key session, and obtain the session handle. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD. If access control is set for the key, other parameters are required. For details, see [Key Access Control](#key-access-control).
1. (Mandatory) Use [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9) to initialize a key session.<br>You need to pass in the key alias and key operation parameters to initialize a key session, and obtain the session handle. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD. If access control is set for the key, other parameters are required. For details, see [Key Access Control](#key-access-control).
2. (Optional) Use [huks.updateSession()](../reference/apis/js-apis-huks.md#huksupdatesession9) to pass in data by segment. Perform this step only if the data exceeds 100 KB or the cryptographic algorithm requires operations by data segment. Otherwise, skip this step.
3. (Mandatory) Use [huks.finishSession()](../reference/apis/js-apis-huks.md#huksfinishsession9) to complete the key session operation.
Pass in the last data segment and complete the key session operation. If an error occurs during the process or the data passed in is not required, use [huks.abortSession()](../reference/apis/js-apis-huks.md#huksabortsession9) to abort the session.
3. (Mandatory) Use [huks.finishSession()](../reference/apis/js-apis-huks.md#huksfinishsession9) to complete the key session operation.<br>Pass in the last data segment and complete the key session operation. If an error occurs during the process or the data passed in is not required, use [huks.abortSession()](../reference/apis/js-apis-huks.md#huksabortsession9) to abort the session.
### Encryption and Decryption
...
...
@@ -873,28 +867,6 @@ struct Index {
.margin({top:10})
}
Row(){
Text('Encryption or decryption result').fontSize(20).margin({left:2,top:10})
}
Row(){
TextInput({placeholder:'Encryption and decryption result',controller:this.controller})
@@ -1671,7 +1643,7 @@ In addition to user identity authentication, the HUKS provides the following mod
- Invalidate the key when the screen lock password is cleared.<br>This mode takes effect only when a screen lock password has been set. If the screen lock password is cleared, the key becomes invalid permanently. The key will not be invalidated if the screen lock password is modified. This mode applies to user-related data protection or access based on screen lock passwords.
- Invalidate the key when new biometric enrollments are added.<br>This mode takes effect only when at least one biometric feature (such as fingerprint) has been enrolled. The key becomes invalid permanently once a new biometric feature is enrolled. The key will not be invalidated if the biometric feature is deleted. This mode applies to scenarios, such as password-free login or payment.
To ensure the validity of the user authentication result, the HUKS supports challenge verification. Before user identity authentication, obtain the challenge (in [HuksSessionHandle](../reference/apis/js-apis-huks.md#hukssessionhandle9) returned by [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9)) from the HUKS and pass in the challenge in [userIAM_userAuth.getAuthInstance](../reference/apis/js-apis-useriam-userauth.md#authinstance9). The challenge of the authentication token is then verified during key operations.
To ensure the validity of the user authentication result, the HUKS supports challenge verification. Before user identity authentication, obtain the challenge (in [HuksSessionHandle](../reference/apis/js-apis-huks.md#hukssessionhandle9) returned by [huks.initSession()](../reference/apis/js-apis-huks.md#huksinitsession9)) from the HUKS and pass in the challenge in **userIAM_userAuth.getAuthInstance**. The challenge of the authentication token is then verified during key operations.
**How to Develop**
...
...
@@ -1685,34 +1657,38 @@ When a key is generated or imported, [HuksUserAuthType](../reference/apis/js-api
| HUKS_USER_AUTH_TYPE_FINGERPRINT |0x0001 | Fingerprint authentication, which can be enabled with facial authentication and PIN authentication at the same time. |
| HUKS_USER_AUTH_TYPE_FACE |0x0002 | Facial authentication, whch can be enabled with fingerprint authentication and PIN authentication at the same time.|
| HUKS_USER_AUTH_TYPE_PIN |0x0004 | PIN authentication, which can be enabled with fingerprint authentication and facial authenticationat the same time.|
| HUKS_USER_AUTH_TYPE_FINGERPRINT | 0x0001 | Fingerprint authentication, which can be enabled with facial authentication and PIN authentication at the same time. |
| HUKS_USER_AUTH_TYPE_FACE | 0x0002 | Facial authentication, whch can be enabled with fingerprint authentication and PIN authentication at the same time. |
| HUKS_USER_AUTH_TYPE_PIN | 0x0004 | PIN authentication, which can be enabled with fingerprint authentication and facial authenticationat the same time. |
| HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD | 1 | Invalidates the key after the screen lock password is cleared. |
| HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL | 2 | Invalidates the key after a biometric enrollment is added. The user authentication types must include the biometric authentication.|
| HUKS_AUTH_ACCESS_INVALID_CLEAR_PASSWORD | 1 | Invalidates the key after the screen lock password is cleared. |
| HUKS_AUTH_ACCESS_INVALID_NEW_BIO_ENROLL | 2 | Invalidates the key after a biometric enrollment is added. The user authentication types must include the biometric authentication. |
| HUKS_CHALLENGE_TYPE_NORMAL | 0 | Normal challenge, which requires an independent user authentication for each use of the key. |
| HUKS_CHALLENGE_TYPE_CUSTOM | 1 | Custom challenge, which supports only one user authentication for multiple keys. |
| HUKS_CHALLENGE_TYPE_NONE | 2 | No challenge is required during user authentication. |
| | | |
> **NOTICE**
>
> - The three challenge types are mutually exclusive.
> - If the challenge type is **HUKS_CHALLENGE_TYPE_NONE**, no challenge is required. However, the key can be accessed within a specified time period (set by **HUKS_TAG_AUTH_TIMEOUT**) after a successful authentication. The maximum value of **HUKS_TAG_AUTH_TIMEOUT** is 60 seconds.
> If the challenge type is **HUKS_CHALLENGE_TYPE_NONE**, no challenge is required. However, the key can be accessed within a specified time period (set by **HUKS_TAG_AUTH_TIMEOUT**) after a successful authentication. The maximum value of **HUKS_TAG_AUTH_TIMEOUT** is 60 seconds.
To use a key, initialize the key session, and determine whether a challenge is required based on the challenge type specified when the key is generated or imported.
|initSession(keyAlias: string, options: HuksOptions, callback: AsyncCallback\<HuksSessionHandle>) : void| Initializes the key session and obtains the challenge.|
...
...
@@ -2090,23 +2066,23 @@ To use a key, initialize the key session, and determine whether a challenge is r
### Refined User Identity Authentication
As an extension of the Key Access Control, the refined access control allows secondary user identity authentication (biometric authentication and lock screen password) to be performed for key access in one or more scenarios, such as encryption, decryption, signing, signature verification, key agreement, and key derivation. For example, a service needs to use a HUKS key to encrypt the account password information. In this scenario, identity authentication is not required in encryption but required in decryption. To achieve this purpose, you can use the refined user identity authentication feature provided by the HUKS.
As an extension to [Key Access Control](#key-access-control), the refined access control allows secondary user identity authentication (biometric authentication and lock screen password) to be performed for key access in one or more scenarios, such as encryption, decryption, signing, signature verification, key agreement, and key derivation. For example, a service needs to use a HUKS key to encrypt the account password information. In this scenario, identity authentication is not required in encryption but required in decryption. To achieve this purpose, you can use the refined user identity authentication feature provided by the HUKS.
**How to Develop**
1. Specify [**HUKS_TAG_KEY_AUTH_PURPOSE**](../reference/apis/js-apis-huks.md#hukstag) in key generation to allow user identity authentication to be performed when a specific algorithm is used.
1. Specify [HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag) in key generation to allow refined user identity authentication to be performed when a specific algorithm is used.
2. The **HUKS_TAG_KEY_AUTH_PURPOSE** does not need to be specified for the key usage process. The development process is the same as that of the user identity authentication process.
**Available APIs**
You can use the [**HUKS_TAG_KEY_AUTH_PURPOSE**](../reference/apis/js-apis-huks.md#hukstag) tag to specify the scenarios, for which the refined user identity authentication is performed. The value range of this tag is [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg).
You can use the [HUKS_TAG_KEY_AUTH_PURPOSE](../reference/apis/js-apis-huks.md#hukstag) tag to specify the scenarios, for which the refined user identity authentication is performed. The value range of this tag is [HuksKeyAlg](../reference/apis/js-apis-huks.md#hukskeyalg).
|HUKS_TAG_KEY_AUTH_PURPOSE| Purpose of the user identity authentication, that is, perform the user identity authentication when a specific algorithm is used.|
**NOTE**
**NOTICE**
- If [**HuksUserAuthType**](../reference/apis/js-apis-huks.md#huksuserauthtype9) is not specified, no user identity authentication is performed by default. In this case, the setting of **HUKS_TAG_KEY_AUTH_PURPOSE** is invalid by default. If **HuksUserAuthType** is specified and **HUKS_TAG_KEY_AUTH_PURPOSE** is not specified, user identity authentication will still be performed by default before the key is used with the algorithm that is specified in the key generation process.
- If the AES or SM4 symmetric algorithm is used for encryption and decryption, only the CBC mode supports refined user identity authentication.
...
...
@@ -2726,8 +2702,9 @@ async function AttestKeyTest() {
**security.huks.d.ts** is not imported. To solve the problem, add **import huks from '@ohos.security.huks'**.
### Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'?
**finishSession()** is supported from API version 9. Update the SDK version or use the latest **security.huks.d.ts** file.
### Property 'finishSession' does not exist on type 'typeof huks'. Did you mean 'finish'?
**finishSession()** is supported from API version 9. Update the SDK version or use the latest **security.huks.d.ts** file.
The OpenHarmony Universal KeyStore (HUKS) provides full lifecycle management capability for keys. The keys managed by the HUKS can be imported by an application or generated by calling the HUKS APIs. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key.
With the Native APIs provided by the HUKS, you can:
* Generate a key.
* Import an external key to the HUKS.
* Encrypt and decrypt data by using a key.
* Generate a digital signature and verify a signature.
* Generate a shared secrete through key agreement.
* Derive a key.
* Provide key attestation.
## Available APIs
### APIs for Key Use
| API| Description|
| -------- | -------- |
| [OH_Huks_GetSdkVersion](../reference/native-apis/_huks_key_api.md#oh_huks_getsdkversion)(struct[OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md) \*sdkVersion) | Obtains the current HUKS SDK version. |
| [OH_Huks_GetKeyItemParamSet](../reference/native-apis/_huks_key_api.md#oh_huks_getkeyitemparamset)(const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSetIn, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSetOut) | Obtains the parameter set of a key. |
| [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession)(const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*keyAlias, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSet, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*handle, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*token) | Initializes the key session to obtain a handle (mandatory) and a challenge value (optional). |
| [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession)(const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*handle, const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSet, const struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*inData, struct [OH_Huks_Blob](../reference/native-apis/_o_h___huks___blob.md)\*outData) | Adds data by segment for the key operation, performs the related key operation, and outputs the processed data. |
| [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset)(struct[OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Initializes a parameter set. |
| [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams)(struct[OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md)\*params, uint32_t paramCnt) | Adds parameters to a parameter set. |
| [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset)(struct[OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Builds a formal parameter set. |
| [OH_Huks_FreeParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freeparamset)(struct[OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*\*paramSet) | Destroys a parameter set. |
| [OH_Huks_CopyParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_copyparamset)(const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*fromParamSet, uint32_t fromParamSetSize, struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*\*paramSet) | Copies a parameter set (deep copy). |
| [OH_Huks_GetParam](../reference/native-apis/_huks_param_set_api.md#oh_huks_getparam)(const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSet, uint32_t tag, struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md)\*\*param) | Obtains parameters from a parameter set. |
| [OH_Huks_FreshParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_freshparamset)(struct[OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md) \*paramSet, bool isCopy) | Refreshes data of the **Blob** type in a parameter set. |
| [OH_Huks_IsParamSetTagValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsettagvalid)(const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSet) | Checks whether the parameters in a parameter set are valid. |
| [OH_Huks_IsParamSetValid](../reference/native-apis/_huks_param_set_api.md#oh_huks_isparamsetvalid)(const struct [OH_Huks_ParamSet](../reference/native-apis/_o_h___huks___param_set.md)\*paramSet, uint32_t size) | Checks whether a parameter set is of the valid size. |
| [OH_Huks_CheckParamMatch](../reference/native-apis/_huks_param_set_api.md#oh_huks_checkparammatch)(const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md)\*baseParam, const struct [OH_Huks_Param](../reference/native-apis/_o_h___huks___param.md)\*param) | Compares whether two parameters are the same. |
## How to Develop
### Key Generation
The HUKS provides the capability of randomly generating keys for services. For a key generated by the HUKS, the plaintext will never be exposed outside throughout the lifecycle. No one can obtain the key in plaintext. Even the service itself can call APIs provided by the HUKS to perform operations on the key and obtain the operation result, but cannot access the key.
**How to Develop**
Use [OH_Huks_GenerateKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_generatekeyitem) to generate a key. You need to pass in **keyAlias** and **paramSetIn**.
1. Set the key alias.
2. Initialize the key parameter set. Use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain the [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose).
3. Pass in the key alias and key parameter set to generate a key.
> **NOTE**
>
> The key alias cannot exceed 64 bytes.
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
A key generated outside the HUKS (for example, generated through key agreement or by a server) can be imported to the HUKS for management. The HUKS supports import of keys in plaintext. However, if a key is imported in plaintext, the key is exposed in the Rich Execution Environment (REE) memory. This type of import applies to lightweight devices or security-insensitive services. For security-sensitive services, use the secure import feature provided by the HUKS. Secure import allows the keys generated for services to be transferred to the HUKS through an end-to-end encrypted transmission channel.
Once a key is imported to the HUKS, its plaintext will not be exposed outside the HUKS throughout the lifecycle of the key.
#### Importing a Key in Plaintext
Use [OH_Huks_ImportKeyItem](../reference/native-apis/_huks_key_api.md#oh_huks_importkeyitem) to import a key in plaintext. You need to pass in the key alias and **paramSetIn**, which must contain the key material and key property set.
1. Set the key alias.
2. Encapsulate the key material and key property set. The key material must comply with the HUKS key material formats (huks-appendix.md#key-material-formats) and assign a value to the key field. In addition, use [OH_Huks_InitParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_initparamset), [OH_Huks_AddParams](../reference/native-apis/_huks_param_set_api.md#oh_huks_addparams), and [OH_Huks_BuildParamSet](../reference/native-apis/_huks_param_set_api.md#oh_huks_buildparamset) to construct **paramSet**, which must contain [OH_Huks_KeyAlg](../reference/native-apis/_huks_type_api.md#oh_huks_keyalg), [OH_Huks_KeySize](../reference/native-apis/_huks_type_api.md#oh_huks_keysize), and [OH_Huks_KeyPurpose](../reference/native-apis/_huks_type_api.md#oh_huks_keypurpose).
3. Import the key.
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
Compared with import of a key in plaintext, the import of a wrapped key involves more complex key material and operations. The following figure illustrates the basic development process.
**Figure 2** Development process for importing a wrapped key
During the development process, you need to use the APIs for key generation, export, import, and deletion in sequence.
>**NOTE**<br>The public key plaintext material returned by **exportKeyItem()** is encapsulated in X.509 format, and the key material to be imported by **importWrappedKeyItem()** must be encapsulated in **Length<sub>Data</sub>-Data** format. Specifically, the application needs to encapsulate the wrapped key material in sequence according to the sequence in the following table.
The following example provides the development involving HUKS APIs (using the ECDH key agreement suite). The operations performed by the service are not included. In the following example, a key is imported from device A to device B.
1. Convert the key to be imported from device A into the key material in HUKS format **To_Import_Key**.
2. Generate an asymmetric key pair **Caller_Key** for device A.
3. Generate an asymmetric key pair **Wrapping_Key**, with key purpose of **unwrap**, for device B.
4. Generate a symmetric key **Caller_Kek** for device A.
5. Export the public key material from the asymmetric key pairs of devices A and B.
6. Use the private key of **Caller_Key** (device A) and the public key of **Wrapping_Key** (device B) to perform key agreement, and obtain an **Agree_Key**.
7. Use the **Caller_Kek** to encrypt the **To_Import_Key** of device A and generate **To_Import_Key_Enc**.
8. Use **Agree_Key** to encrypt the **Caller_Kek** of device A and generate **Caller_Kek_Enc**.
9. Send the public key of **Caller_Key**, **Caller_Kek_Enc**, and **To_Import_Key_Enc** from device A to device B.
10. Encapsulate and encrypt the key materials to be imported to device B.
11. Import the encrypted key material to device B.
12. Delete the keys, which are used for encrypting the key to import, from devices A and B.
**C++ Code Example**
```C++
#include "napi/native_api.h"
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <algorithm>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
ret = OH_Huks_BuildParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
return ret;
}
/**
* Securely import a key from device A to the HUKS of device B.
* wrappingKey is a key pair of device B.
* callerKey is a key pair of device A.
* callerAgreeKey is generated through key agreement based on the private key of the key pair of device A and the public key of device B .
{.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller
{.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time
{.tag = OH_HUKS_TAG_IV, .blob = {.size = WRAPPED_KEY_IV_SIZE, .data = (uint8_t *)WRAPPED_KEY_IV }}}; // this is a test value, for real use the iv should be different every time
{.tag = OH_HUKS_TAG_ASSOCIATED_DATA, .blob = {.size = AAD_SIZE, .data = (uint8_t *)AAD}}, // this is a test value, for real use the aad should be info associated with caller
{.tag = OH_HUKS_TAG_NONCE, .blob = {.size = NONCE_SIZE, .data = (uint8_t *)NONCE}}}; // this is a test value, for real use the nonce should be different every time
{.tag = OH_HUKS_TAG_IV, .blob = {.size = IV_SIZE, .data = (uint8_t *)IV}}}; // this is a test value, for real use the iv should be different every time
* Securely import a key from remote device A to local device B.
*
* 1. Prepare the key material to be imported on device A. In this example, g_importedAes256PlainKey is used as an example.
*/
/**
* 2. Generate an asymmetric key pair Caller_Key for device A.
*/
ret = GenerateAndExportCallerPublicKey(params, &callerSelfPublicKey);
if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
break;
}
/**
* 3. Generate an asymmetric key pair Wrapping_Key with the key purpose of unwrap for device B.
*/
ret = GenerateAndExportHuksPublicKey(params, &huksPublicKey);
if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
break;
}
/**
* 4. Generate a symmetric key Caller_Kek for device A.
* 5. Export the public key material from the asymmetric key pairs of devices A and B. In this example, the public key is stored in callerSelfPublicKey and huksPublicKey as variables.
* 6. Devices A and B perform key agreement and obtain an Agree_Key based on the private key of the Caller_Key (device A) and the public key of Wrapping_Key (device B).
*/
ret = ImportKekAndAgreeSharedSecret(params, &huksPublicKey, &outSharedKey);
if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
break;
}
/**
* 7. Use Caller_Kek to encrypt To_Import_Key of device A and generate the To_Import_Key_Enc.
* 8. Use Agree_Key to encrypt Caller_Kek of device A and generate the Caller_Kek_Enc.
*/
ret = EncryptImportedPlainKeyAndKek(params, &plainCipherText, &kekCipherText);
if (ret.errorCode != (int32_t)OH_HUKS_SUCCESS) {
break;
}
/**
* 9. Send the public key of Caller_Key, Caller_Kek_Enc, and To_Import_Key_Enc from device A to device B. In this example, keys are stored in callerSelfPublicKey, plainCipherText, and kekCipherText as variables.
*/
/**
* 10. Encapsulate and encrypt the key materials to be imported to device B.
* 11. Import the encrypted key material to device B.
* 12. Delete the keys, used for encrypting the key to import, from devices A and B.
*/
ret = ImportWrappedKey(params, &plainCipherText, &kekCipherText, &callerSelfPublicKey, &wrappedKeyData);
To ensure data confidentiality and integrity, you may need to encrypt or decrypt data, generate or verify a signature, perform key agreement, and derive a key. The following describes common key operations.
**General Development Process**
The HUKS operates data based on key sessions. The general process is as follows:
1. Initialize a key session using [OH_Huks_InitSession](../reference/native-apis/_huks_key_api.md#oh_huks_initsession).<br>You need to pass in the key alias and key operation parameters. After the initialization, a session handle is returned. The key operation parameters must contain the parameters required by the cipher algorithm, including the cipher algorithm, key size, key purpose, working mode, padding mode, hash mode, IV, nonce, and AAD.
2. Update data by segment using [OH_Huks_UpdateSession](../reference/native-apis/_huks_key_api.md#oh_huks_updatesession) to pass in data by segment.<br>In key agreement, key derivation, and signature verification, you need to use this API to perform algorithm operations. In other cases, for example, the data exceeds 100 KB or the cryptographic algorithm requires data operations by segment, you can use this API to pass in data by segment.
3. Finish the key session using [OH_Huks_FinishSession](../reference/native-apis/_huks_key_api.md#oh_huks_finishsession).<br>Operate the last segment of data and end the key session. If an error occurs during this process or the key operation data is not required, use [OH_Huks_AbortSession](../reference/native-apis/_huks_key_api.md#oh_huks_abortsession) to abort the session. This step is mandatory.
#### Encryption and Decryption
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
ret = OH_Huks_BuildParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
return ret;
}
static const uint32_t IV_SIZE = 16;
static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key agreement. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks.
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
ret = OH_Huks_BuildParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
OH_Huks_FreeParamSet(paramSet);
return ret;
}
return ret;
}
static const uint32_t IV_SIZE = 16;
static uint8_t IV[IV_SIZE] = { 0 }; // this is a test value, for real use the iv should be different every time
You are advised to pass in [HuksKeyStorageType](../reference/apis/js-apis-huks.md#hukskeystoragetype) to specify the storage type in key derivation. From API version 10, only **HUKS_STORAGE_ONLY_USED_IN_HUKS** or **HUKS_STORAGE_KEY_EXPORT_ALLOWED** can be used. If **HuksKeyStorageType** is not passed in, the key can be stored or exported by default, which poses security risks.
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
The HUKS provides attestation for the public keys of asymmetric key pairs. The HUKS can issue a certificate for the public key of an asymmetric key pair stored in the HUKS using the public key infrastructure (PKI) certificate chain technology. The certificate can prove the validity of the public key. The service can use the root CA certificate provided by the OpenHarmony to verify the key certificate issued by the HUKS level by level to ensure that the public key and private key in the certificate are from a trusted hardware device and stored in the HUKS.
**How to Develop**
1. Pass in the key alias and the attribute tag of the key to be attested.
2. Generate an X.509 certificate chain, which consists of the root CA certificate, device CA certificate, device certificate, and key certificate in sequence, for the application.
3. Send the certificate chain to a trusted server. The server parses and verifies the validity of the certificate chain and whether a single certificate is revoked.
**C++ Code Example**
```C++
#include "huks/native_huks_api.h"
#include "huks/native_huks_param.h"
#include <string.h>
OH_Huks_Result InitParamSet(
struct OH_Huks_ParamSet **paramSet,
const struct OH_Huks_Param *params,
uint32_t paramCount)
{
OH_Huks_Result ret = OH_Huks_InitParamSet(paramSet);
if (ret.errorCode != OH_HUKS_SUCCESS) {
return ret;
}
ret = OH_Huks_AddParams(*paramSet, params, paramCount);
Before applying for permissions for your application, understand [permission groups and permissions](accesstoken-overview.md#permission-groups-and-permissions).
The following lists the permission groups supported currently. For details about the permissions, see the [Application Permission List](permission-list.md).