• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Development on HUKS
2
3## Overview
4
5### Introduction
6
7OpenHarmony Universal KeyStore (HUKS) provides system-level key management capabilities, ensuring secure management and use of keys throughout their entire lifecycle (generation, storage, use, and destruction). The environment where a key is stored and used is of the most importance to key security. For example, a key in plaintext must be used in a secure environment, such as a Trusted Execution Environment (TEE) or a security chip.
8
9This document describes how to adapt Hardware Device Interface (HDI) APIs for secure key storage and use environment based on the OpenHarmony HUKS architecture and how to verify these APIs.
10
11HUKS supports key lifecycle management, which covers the following:
12
131. Generation and import of the key
14
152. Storage of the key
16
173. Use of the key (including encryption and decryption, signing and verification, key derivation and agreement, hash, and key access control)
18
194. Destruction of the key
20
21### Basic Concepts
22
23- HUKS Service
24
25  An independent OpenHarmony service that supports key management. It belongs to the huks_service process. Instead of handling key calculation, the HUKS Service depends on the HUKS Core to provide services for the upper layer.
26
27- HUKS Core
28
29  A functional module that provides the key management service. This module must run in a secure environment, and the keys in plaintext must be kept inside the HUKS Core module throughout the lifecycle.
30
31- TEE
32
33  A secure area created by isolating software and hardware resources to protect the applications and data in the secure area from unauthorized access. This isolation mechanism yields two execution environments: TEE and Rich Execution Environment (REE). Each execution environment has independent internal data path and memory, protecting the data inside the TEEs from being disclosed. The applications in an REE cannot access resources in a TEE. The applications in a TEE cannot access resources in another TEE without authorization.
34
35- Init-Update-Finish
36
37   **Init**: initializes data for a key operation.
38
39   **Update**: operates data by segment and returns the result, or appends data.
40
41   **Finish**: stops operating data by segment or appending data, and returns the result.
42
43### Working Principles
44
45The following uses the key generation process as an example to describe the communication between the HUKS Service and HUKS Core. Other key operations are similar.
46The upper-layer application invokes the HUKS Service through the key management SDK. The HUKS Service invokes the HUKS Core, which invokes the key management module to generate a key. The HUKS Core uses a work key derived from the root key to encrypt the generated key and sends the encrypted key to the HUKS Service. The HUKS Service stores the encrypted key in a file.
47
48![](figures/HUKS-GenerateKey1.png)
49
50### Constraints
51
52* HUKS must be implemented in a TEE for security purposes.
53
54* The certificate chain returned by **HuksHdiAttestKey** must be in the sequence of the application certificate, device certificate, CA certificate, and root certificate, with the certificate length added before each certificate. The certificate chain and its length are assembled in the binary large object (BLOB) format. If you want to define the certificate format, the format must be the same as that parsed by the server.
55
56![CertChain format](figures/HUKS-CertChain.png)
57
58* The key returned by the API must be assembled into a **KeyBlob** based on the key storage status. For details about the APIs that must comply with this constraint, see [Available APIs](#available-apis).
59
60   The **KeyBlob** stores both the key and its attributes. The figure below shows the **KeyBlob** structure. For details about how to construct a **KeyBlob**, see [hks_keyblob.c/HksBuildKeyBlob](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_keyblob.c).
61
62![KeyBlob format](figures/HUKS-KeyBlob.png)
63
64## Development Guidelines
65
66### When to Use
67
68The HUKS Core provides KeyStore (KS) capabilities for applications, including key management and key cryptography operations. If you want to replace the HUKS Core with your own implementation, you need to implement the following APIs:
69
70### Available APIs
71
72**Table 1** Available APIs
73
74| API                                                      | Description                                 | Constraints                    | Corresponding JS API                                       |
75| ------------------------------------------------------------ | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------ |
76| [HuksHdiModuleInit()](#hukshdimoduleinit)                   | Initializes the HUKS Core.                           |  –                          | –|
77| [HuksHdiRefresh()](#hukshdirefresh)                          | Refreshes the root key.                             |  –                           | –|
78| [HuksHdiGenerateKey()](#hukshdigeneratekey)                  | Generates a key.                               |  The key generated must be in the **KeyBlob** format.         |generateKey(keyAlias: string, options: HuksOptions)|
79| [HuksHdiImportKey()](#hukshdiimportkey)                     | Import a key in plaintext.                           |  The output parameter must be in the **KeyBlob** format.          | importKey(keyAlias: string, options: HuksOptions)|
80| [HuksHdiImportWrappedKey()](#hukshdiimportwrappedkey)        |Import an encrypted key.                             |  The output parameter must be in the **KeyBlob** format.         | importWrappedKey(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions)|
81| [HuksHdiExportPublicKey()](#hukshdiexportpublickey)         | Exports a public key.                                |–                            | exportKey(keyAlias: string, options: HuksOptions) |
82| [HuksHdiInit()](#hukshdiinit)                              | Initializes data for a key operation. This API is of the Init-Update-Final model.                      |–                             | init(keyAlias: string, options: HuksOptions) |
83| [HuksHdiUpdate()](#hukshdiupdate)                           | Operates data by segment or appends data for the key operation. This API is of the Init-Update-Final model.                    |The input parameter for signing and signature verification must be the raw data.         | update(handle: number, token?: Uint8Array, options: HuksOptions) |
84| [HuksHdiFinish()](#hukshdifinish)                           | Finishes the key operation. This API is of the Init-Update-Final model.                    |The input parameter for signing and signature verification must be the signed data.       | finish(handle: number, options: HuksOptions) |
85| [HuksHdiAbort()](#hukshdiabort)                         | Aborts Init-Update-Finish.                              |–                            | abort(handle: number, options: HuksOptions) |
86| [HuksHdiGetKeyProperties()](#hukshdigetkeyproperties)        | Obtains key properties.                             |–                           | getKeyProperties(keyAlias: string, options: HuksOptions)|
87| [HuksHdiAttestKey()](#hukshdiattestkey)        | Obtain the key certificate.                             |The output parameter must be in the **certChain** format.                     | attestKey(keyAlias: string, options: HuksOptions)|
88
89- - -
90
91#### HuksHdiModuleInit
92
93**API description**
94
95Initializes the HUKS Core, including the lock, encryption algorithm library, authtoken key, and root key.
96
97**Prototype**
98<pre><code>int32_t HuksHdiModuleInit();</code></pre>
99<details>
100  <summary><strong>Return value</strong></summary>
101
102  - **HKS_SUCCESS**: The operation is successful.
103
104  - Other value: The operation failed.
105</details>
106
107- - -
108
109#### HuksHdiRefresh
110
111**API description**
112
113Refreshes the root key.
114
115**Prototype**
116<pre><code>int32_t HuksHdiRefresh();</code></pre>
117<details>
118  <summary><strong>Return value</strong></summary>
119
120  - **HKS_SUCCESS**: The operation is successful.
121
122  - Other value: The operation failed.
123</details>
124
125- - -
126
127#### HuksHdiGenerateKey
128
129**API description**
130
131Generates a key based on **paramSet**.
132
133**Prototype**
134<pre><code>int32_t HuksHdiGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, const struct HksBlob *keyIn, struct HksBlob *keyOut);</code></pre>
135<details>
136  <summary><strong>Parameters</strong></summary>
137  <pre>
138  <strong>const struct HksBlob *keyAlias</strong>
139  Pointer to the alias of the key to generate. The value must meet the following requirements:
140  1. keyAlias != null
141  2. keyAlias -> data != null
142  3. keyAlias -> size != 0
143  <br></br>
144  <strong>const struct HksParamSet *paramSet</strong>
145  Pointer to the parameters for generating the key.
146  <br></br>
147  <strong>const struct HksBlob *keyIn</strong>
148  This parameter is used in key agreement.
149  <br></br>
150  <strong>struct HksBlob *keyOut</strong>
151  Pointer to the output parameter, which holds **paramSet** and the key generated.
152  </pre>
153</details>
154<br></br>
155
156<details>
157  <summary><strong>Constraints</strong></summary>
158
159  1. Check parameters in the API. For example, check for null pointers and whether the key algorithm is supported.
160
161  2. **keyOut** must be in the **KeyBlob** format.
162
163</details>
164<br></br>
165
166<details>
167  <summary><strong>Return value</strong></summary>
168
169  - **HKS_SUCCESS**: The operation is successful.
170
171  - Other value: The operation failed.
172</details>
173
174- - -
175
176#### HuksHdiImportKey
177
178**API description**
179
180Imports a key in plaintext.
181
182**Prototype**
183<pre><code>int32_t HuksHdiImportKey(const struct HksBlob *keyAlias, const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
184<details>
185  <summary><strong>Parameters</strong></summary>
186  <pre>
187  <strong>const struct HksBlob *msg</strong>
188  Pointer to the alias of the key to import. The value must meet the following requirements:
189  1. keyAlias != null
190  2. keyAlias -> data != null
191  3. keyAlias -> size != 0
192  <br></br>
193  <strong>const struct HksBlob *key</strong>
194  Pointer to the key to import. The value must meet the following requirements:
195  1. key != null
196  2. key -> data != null
197  3. key -> size != 0
198  <br></br>
199  <strong>const struct HksParamSet *paramSet</strong>
200  Pointer to the parameters for importing the key.
201  <br></br>
202  <strong>struct HksBlob *keyOut</strong>
203  Pointer to the output parameter, which holds **paramSet** and the key.
204  <br></br>
205  </pre>
206</details>
207<br></br>
208
209<details>
210  <summary><strong>Constraints</strong></summary>
211
212  1. Check parameters in the API. For example, check for null pointers and whether the key algorithm is supported.
213
214  2. **keyOut** must be in the **KeyBlob** format.
215
216</details>
217<br></br>
218
219<details>
220  <summary><strong>Return value</strong></summary>
221
222  - **HKS_SUCCESS**: The operation is successful.
223
224  - Other value: The operation failed.
225</details>
226
227- - -
228
229#### HuksHdiImportWrappedKey
230
231**API description**
232
233Imports an encrypted key.
234
235**Prototype**
236<pre><code>int32_t HuksHdiImportWrappedKey(const struct HksBlob *keyAlias, const struct HksBlob *wrappingUsedkey, const struct HksBlob *wrappedKeyData, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
237<details>
238  <summary><strong>Parameters</strong></summary>
239  <pre>
240  <strong>const struct HksBlob *KeyAlias</strong>
241  Pointer to the alias of the key to import. The value must meet the following requirements:
242  1. keyAlias != null
243  2. keyAlias -> data != null
244  3. keyAlias -> size != 0
245  <br></br>
246  <strong>const struct HksBlob *key</strong>
247  Pointer to the key used to encrypt the key to import. The value must meet the following requirements:
248  1. wrappingUsedkey != null
249  2. wrappingUsedkey -> data != null
250  3. wrappingUsedkey -> size != 0
251  <br></br>
252  <strong>const struct HksBlob *wrappedKeyData</strong>
253  Pointer to the encrypted data of the key to import. The value must meet the following requirements:
254  1. wrappedKeyData != null
255  2. wrappedKeyData -> data != null
256  3. wrappedKeyData -> size != 0
257  <br></br>
258  <strong>const struct HksParamSet *paramSet</strong>
259  Pointer to the parameters for importing the key.
260  <br></br>
261  <strong>struct HksBlob *keyOut</strong>
262  Pointer to the output parameter, which holds **paramSet** and the key imported.
263  </pre>
264</details>
265<br></br>
266
267<details>
268  <summary><strong>Constraints</strong></summary>
269
270  1. Check parameters in the API. For example, check for null pointers and whether the key algorithm is supported.
271
272  2. **keyOut** must be in the **KeyBlob** format.
273
274</details>
275<br></br>
276
277<details>
278  <summary><strong>Return value</strong></summary>
279
280  - **HKS_SUCCESS**: The operation is successful.
281
282  - Other value: The operation failed.
283</details>
284
285- - -
286
287#### HuksHdiExportPublicKey
288
289**API description**
290
291Exports a public key.
292
293**Prototype**
294<pre><code>int32_t HuksHdiExportPublicKey(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre>
295<details>
296  <summary><strong>Parameters</strong></summary>
297  <pre>
298  <strong>const struct HksBlob *key</strong>
299  Pointer to the private key corresponding to the public key to export. The value must meet the following requirements:
300  1. key != null
301  2. key -> data != null
302  3. key -> size != 0
303  <br></br>
304  <strong>const struct HksParamSet *paramSet</strong>
305  Pointer to the parameter set, which is empty.
306  <br></br>
307  <strong>struct HksBlob *keyOut</strong>
308  Pointer to the output parameter, which holds the public key exported.
309  </pre>
310</details>
311<br></br>
312
313<details>
314  <summary><strong>Return value</strong></summary>
315
316  - **HKS_SUCCESS**: The operation is successful.
317
318  - Other value: The operation failed.
319</details>
320
321- - -
322
323#### HuksHdiInit
324
325**API description**
326
327Initializes data for a key operation. This API is of the Init-Update-Final model.
328
329**Prototype**
330<pre><code>int32_t HuksHdiInit(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle, struct HksBlob *token);</code></pre>
331<details>
332  <summary><strong>Parameters</strong></summary>
333  <pre>
334  <strong>const struct HksBlob *key</strong>
335  Pointer to the key, on which the **Init** operation is to perform. The value must meet the following requirements:
336  1. key != null
337  2. key -> data != null
338  3. key -> size != 0
339  <br></br>
340  <strong>const struct HksParamSet *paramSet</strong>
341  Pointer to the parameters of the **Init** operation.
342  <br></br>
343  <strong>struct HksBlob *handle</strong>
344  Pointer to the handle of Init-Update-Finish.
345  <br></br>
346  <strong>struct HksBlob *token</strong>
347  Pointer to the challenge used for secure access control.
348  </pre>
349</details>
350<br></br>
351
352<details>
353  <summary><strong>Return value</strong></summary>
354
355  - **HKS_SUCCESS**: The operation is successful.
356
357  - Other value: The operation failed.
358</details>
359
360- - -
361
362#### HuksHdiUpdate
363
364**API description**
365
366Operates data by segment or appends data for the key operation. This API is of the Init-Update-Final model.
367
368**Prototype**
369<pre><code>int32_t HuksHdiUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre>
370<details>
371  <summary><strong>Parameters</strong></summary>
372  <pre>
373  <strong>const struct HksBlob *handle</strong>
374  Pointer to the handle of Init-Update-Finish.
375  <br></br>
376  <strong> const struct HksParamSet *paramSet</strong>
377  Pointer to the parameters of the **Update** operation.
378  <br></br>
379  <strong> const struct HksBlob *inData</strong>
380  Pointer to the input of the **Update** operation.
381  <br></br>
382  <strong> struct HksBlob *outData</strong>
383  Pointer to the result of the **Update** operation.
384  </pre>
385</details>
386<br></br>
387
388<details>
389  <summary><strong>Constraints</strong></summary>
390
391  1. **inData** must pass in the raw data when signing and signature verification are performed.
392
393</details>
394<br></br>
395
396<details>
397  <summary><strong>Return value</strong></summary>
398
399  - **HKS_SUCCESS**: The operation is successful.
400
401  - Other value: The operation failed.
402</details>
403
404- - -
405
406#### HuksHdiFinish
407
408**API description**
409
410Finishes the key operation. This API is of the Init-Update-Final model.
411
412**Prototype**
413<pre><code>int32_t HuksHdiFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre>
414<details>
415  <summary><strong>Parameters</strong></summary>
416  <pre>
417  <strong>const struct HksBlob *handle</strong>
418  Pointer to the handle of Init-Update-Finish.
419  <br></br>
420  <strong>const struct HksParamSet *paramSet</strong>
421  Pointer to the parameters of the **Finish** operation.
422  <br></br>
423  <strong>const struct HksBlob *inData</strong>
424  Pointer to the input of the **Finish** operation.
425  <br></br>
426  <strong>struct HksBlob *outData</strong>
427  Pointer to the result of the **Finish** operation.
428  </pre>
429</details>
430<br></br>
431
432<details>
433  <summary><strong>Constraints</strong></summary>
434
435  1. In signing and signature verification, **inData** must pass in the signature data to be verified. The return value indicates whether the operation is successful.
436
437</details>
438<br></br>
439
440<details>
441  <summary><strong>Return value</strong></summary>
442
443  - **HKS_SUCCESS**: The operation is successful.
444
445  - Other value: The operation failed.
446</details>
447
448- - -
449
450#### HuksHdiAbort
451
452**API description**
453
454Aborts Init-Update-Finish. When an error occurs in any of the **Init**, **Update**, and **Finish** operations, call this API to terminate the use of the key.
455
456**Prototype**
457<pre><code>int32_t HuksHdiAbort(const struct HksBlob *handle, const struct HksParamSet *paramSet);</code></pre>
458<details>
459  <summary><strong>Parameters</strong></summary>
460  <pre>
461  <strong>const struct HksBlob *handle</strong>
462  Pointer to the handle of Init-Update-Finish.
463  <br></br>
464  <strong>const struct HksParamSet *paramSet</strong>
465  Pointer to the parameters of the **Abort** operation.
466  </pre>
467</details>
468<br></br>
469
470<details>
471  <summary><strong>Return value</strong></summary>
472
473  - **HKS_SUCCESS**: The operation is successful.
474
475  - Other value: The operation failed.
476</details>
477
478- - -
479
480#### HuksHdiGetKeyProperties
481
482**API description**
483
484Obtains key properties.
485
486**Prototype**
487<pre><code>int32_t HuksHdiGetKeyProperties(const struct HksParamSet *paramSet, const struct HksBlob *key);</code></pre>
488<details>
489  <summary><strong>Parameters</strong></summary>
490  <pre>
491  <strong>const struct HksParamSet *paramSet</strong>
492  Pointer to the parameter set, which is empty.
493  <br></br>
494  <strong>const struct HksBlob *key</strong>
495  Pointer to the target key.
496  </pre>
497</details>
498<br></br>
499
500<details>
501  <summary><strong>Return value</strong></summary>
502
503  - **HKS_SUCCESS**: The operation is successful.
504
505  - Other value: The operation failed.
506</details>
507
508- - -
509
510#### HuksHdiAttestKey
511
512**API description**
513
514Obtains the key certificate.
515
516**Prototype**
517<pre><code>int32_t (*HuksHdiAttestKey)(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *certChain);</code></pre>
518<details>
519  <summary><strong>Parameters</strong></summary>
520  <pre>
521  <strong>const struct HksBlob *key</strong>
522  Pointer to the target key.
523  <br></br>
524  <strong>const struct HksParamSet *paramSet</strong>
525  Pointer to the parameters for the operation.
526  <br></br>
527  <strong>struct HksBlob *certChain</strong>
528  Pointer to the output parameter, which holds the certificate obtained.
529  </pre>
530</details>
531<br></br>
532
533<details>
534  <summary><strong>Constraints</strong></summary>
535
536  1. **certChain** must comply with the certificate chain described in [Constraints](#constraints).
537
538</details>
539<br></br>
540
541<details>
542  <summary><strong>Return value</strong></summary>
543
544  - **HKS_SUCCESS**: The operation is successful.
545
546  - Other value: The operation failed.
547</details>
548
549- - -
550
551### Development Procedure
552
553The directory structure is as follows:
554
555```undefined
556// base/security/user_auth/services/huks_standard/huks_engine/main
557├── BUILD.gn # Build script
558├── core_dependency # Dependencies of the implementation
559└── core # Software implementation of the HUKS Core
560    ├── BUILD.gn # Build script
561    ├── include
562    └── src
563        ├── hks_core_interfaces.c # Adaptation of the HDI to the HUKS Core
564        └── hks_core_service.c # Specific implementation
565        └── ... # Other function code
566```
567
568Init-Update-Finish must be used to implement HUKS Core APIs. The following provides the development procedure of Init-Update-Finish and sample code of the HUKS Core. You can refer to the following code to implement all HDI APIs.
569
570For the code of other HUKS Core APIs, see [hks_core_service.c](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_core_service.c).
571
5721. Create a handle to enable the information about the operations on a key to be stored in a session. With this handle, multiple operations on the same key can be performed.
573
574   ```c
575
576   // Implement Init().
577
578   int32_t HksCoreInit(const struct  HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle,
579    struct HksBlob *token)
580   {
581       HKS_LOG_D("HksCoreInit in Core start");
582       uint32_t pur = 0;
583       uint32_t alg = 0;
584       // Check parameters.
585       if (key == NULL || paramSet == NULL || handle == NULL || token == NULL) {
586           HKS_LOG_E("the pointer param entered is invalid");
587           return HKS_FAILURE;
588        }
589
590        if (handle->size < sizeof(uint64_t)) {
591            HKS_LOG_E("handle size is too small, size : %u", handle->size);
592            return HKS_ERROR_INSUFFICIENT_MEMORY;
593        }
594        // Decrypt the key file.
595        struct HuksKeyNode *keyNode = HksCreateKeyNode(key, paramSet);
596        if (keyNode == NULL || handle == NULL) {
597            HKS_LOG_E("the pointer param entered is invalid");
598            return HKS_ERROR_BAD_STATE;
599        }
600        // Store information in a session based on the handle. The information stored can be used for the Update and Finish operations on the key.
601        handle->size = sizeof(uint64_t);
602        (void)memcpy_s(handle->data, handle->size, &(keyNode->handle), handle->size);
603        // Obtain the algorithm from the parameters.
604        int32_t ret = GetPurposeAndAlgorithm(paramSet, &pur, &alg);
605        if (ret != HKS_SUCCESS) {
606            HksDeleteKeyNode(keyNode->handle);
607            return ret;
608        }
609        // Check the key parameters.
610        ret = HksCoreSecureAccessInitParams(keyNode, paramSet, token);
611        if (ret != HKS_SUCCESS) {
612            HKS_LOG_E("init secure access params failed");
613            HksDeleteKeyNode(keyNode->handle);
614            return ret;
615        }
616        // Obtain the initialization handler from the algorithm library based on the usage of the key.
617        uint32_t i;
618        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreInitHandler);
619        for (i = 0; i < size; i++) {
620           if (g_hksCoreInitHandler[i].pur == pur) {
621               HKS_LOG_E("Core HksCoreInit [pur] = %d, pur = %d", g_hksCoreInitHandler[i].pur, pur);
622               ret = g_hksCoreInitHandler[i].handler(keyNode, paramSet, alg);
623               break;
624        }
625        }
626        // Check exception results.
627        if (ret != HKS_SUCCESS) {
628            HksDeleteKeyNode(keyNode->handle);
629            HKS_LOG_E("CoreInit failed, ret : %d", ret);
630            return ret;
631        }
632
633        if (i == size) {
634            HksDeleteKeyNode(keyNode->handle);
635            HKS_LOG_E("don't found purpose, pur : %u", pur);
636            return HKS_FAILURE;
637        }
638
639        HKS_LOG_D("HksCoreInit in Core end");
640        return ret;
641    }
642   ```
643
6442. Obtain the context based on the handle, and pass in data slices to obtain the operation result or append data.
645
646    ```c
647    // Implement Update().
648    int32_t HksCoreUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData,
649        struct HksBlob *outData)
650    {
651        HKS_LOG_D("HksCoreUpdate in Core start");
652        uint32_t pur = 0;
653        uint32_t alg = 0;
654        // Check parameters.
655        if (handle == NULL || paramSet == NULL || inData == NULL) {
656            HKS_LOG_E("the pointer param entered is invalid");
657            return HKS_FAILURE;
658        }
659
660        uint64_t sessionId;
661        struct HuksKeyNode *keyNode = NULL;
662        // Obtain the context based on the handle.
663        int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
664        if (ret != HKS_SUCCESS) {
665            HKS_LOG_E("GetParamsForCoreUpdate failed");
666            return ret;
667        }
668        // Verify key parameters.
669        ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
670        if (ret != HKS_SUCCESS) {
671            HksDeleteKeyNode(sessionId);
672            HKS_LOG_E("HksCoreUpdate secure access verify failed");
673            return ret;
674        }
675        // Call the key handler from the corresponding algorithm library.
676        uint32_t i;
677        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreUpdateHandler);
678        for (i = 0; i < size; i++) {
679            if (g_hksCoreUpdateHandler[i].pur == pur) {
680                struct HksBlob appendInData = { 0, NULL };
681                ret = HksCoreAppendAuthInfoBeforeUpdate(keyNode, pur, paramSet, inData, &appendInData);
682                if (ret != HKS_SUCCESS) {
683                    HKS_LOG_E("before update: append auth info failed");
684                    break;
685                }
686                ret = g_hksCoreUpdateHandler[i].handler(keyNode, paramSet,
687                     appendInData.data == NULL ? inData : &appendInData, outData, alg);
688                if (appendInData.data != NULL) {
689                    HKS_FREE_BLOB(appendInData);
690                }
691                break;
692            }
693        }
694        // Check exception results.
695        if (ret != HKS_SUCCESS) {
696            HksDeleteKeyNode(keyNode->handle);
697            HKS_LOG_E("CoreUpdate failed, ret : %d", ret);
698            return ret;
699        }
700
701        if (i == size) {
702            HksDeleteKeyNode(sessionId);
703            HKS_LOG_E("don't found purpose, pur : %u", pur);
704            return HKS_FAILURE;
705        }
706        return ret;
707    }
708    ```
709
7103. Finish the key operation to obtain the result, and destroy the handle.
711
712   ```c
713   // Implement Finish().
714   int32_t HksCoreFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData,
715    struct HksBlob *outData)
716   {
717       HKS_LOG_D("HksCoreFinish in Core start");
718       uint32_t pur = 0;
719       uint32_t alg = 0;
720       // Check parameters.
721       if (handle == NULL || paramSet == NULL || inData == NULL) {
722           HKS_LOG_E("the pointer param entered is invalid");
723           return HKS_FAILURE;
724       }
725
726       uint64_t sessionId;
727       struct HuksKeyNode *keyNode = NULL;
728       // Obtain the context based on the handle.
729       int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
730       if (ret != HKS_SUCCESS) {
731           HKS_LOG_E("GetParamsForCoreUpdate failed");
732           return ret;
733       }
734       // Verify key parameters.
735       ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
736       if (ret != HKS_SUCCESS) {
737           HksDeleteKeyNode(sessionId);
738           HKS_LOG_E("HksCoreFinish secure access verify failed");
739           return ret;
740       }
741       // Call the key handler from the corresponding algorithm library.
742       uint32_t i;
743       uint32_t size = HKS_ARRAY_SIZE(g_hksCoreFinishHandler);
744       for (i = 0; i < size; i++) {
745           if (g_hksCoreFinishHandler[i].pur == pur) {
746               uint32_t outDataBufferSize = (outData == NULL) ? 0 : outData->size;
747               struct HksBlob appendInData = { 0, NULL };
748               ret = HksCoreAppendAuthInfoBeforeFinish(keyNode, pur, paramSet, inData, &appendInData);
749               if (ret != HKS_SUCCESS) {
750                   HKS_LOG_E("before finish: append auth info failed");
751                   break;
752               }
753               ret = g_hksCoreFinishHandler[i].handler(keyNode, paramSet,
754                   appendInData.data == NULL ? inData : &appendInData, outData, alg);
755               if (appendInData.data != NULL) {
756                   HKS_FREE_BLOB(appendInData);
757               }
758               if (ret != HKS_SUCCESS) {
759                   break;
760               }
761               // Append the end label of the key operation.
762               ret = HksCoreAppendAuthInfoAfterFinish(keyNode, pur, paramSet, outDataBufferSize, outData);
763               break;
764           }
765       }
766       if (i == size) {
767           HKS_LOG_E("don't found purpose, pur : %d", pur);
768           ret = HKS_FAILURE;
769       }
770       // Delete the session.
771       HksDeleteKeyNode(sessionId);
772       HKS_LOG_D("HksCoreFinish in Core end");
773       return ret;
774   }
775   ```
776
777### Verification
778
779Use the [HUKS JS APIs](https://gitee.com/openharmony/security_huks/blob/master/interfaces/kits/js/@ohos.security.huks.d.ts) to develop a JavaScript application to verify HUKS capabilities.
780
781The JS API corresponding to each HDI API is provided in [Available APIs](#available-apis). You can invoke the JS APIs to verify the capabilities of the corresponding HDI APIs or perform complete key operations to verify the capabilities of the APIs.
782
783The JS test code is as follows. If the entire process is successful, the HDI APIs are functioning. For more information about key operations, see [HUKS Development](../../application-dev/security/huks-guidelines.md).
784
785**Generating and Encrypting an AES Key**
786
7871. Import the HUKS module.
788
789   ```js
790   import huks from '@ohos.security.huks'
791   ```
792
7932. Call **generateKey()** to generate a key.
794
795   ```js
796   var alias = 'testAlias';
797   var properties = new Array();
798   properties[0] = {
799     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
800     value: huks.HuksKeyAlg.HUKS_ALG_ECC
801   };
802   properties[1] = {
803     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
804     value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_224
805   };
806   properties[2] = {
807     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
808     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
809   };
810   properties[3] = {
811     tag: huks.HuksTag.HUKS_TAG_DIGEST,
812     value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
813   };
814   var options = {
815     properties: properties
816   }
817   var resultA = huks.generateKey(alias, options);
818   ```
819
8203. Call **Init()** to perform initialization.
821
822   ```js
823   var alias = 'test001'
824   var properties = new Array();
825   properties[0] = {
826     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
827     value: huks.HuksKeyAlg.HUKS_ALG_DH
828   };
829   properties[1] = {
830     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
831     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
832   };
833   properties[2] = {
834     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
835     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
836   };
837   var options = {
838     properties: properties
839   };
840   huks.init(alias, options, function(err, data) {
841       if (err.code !== 0) {
842           console.log("test init err information: " + JSON.stringify(err));
843       } else {
844           console.log(`test init data: ${JSON.stringify(data)}`);
845       }
846   })
847   ```
848
8494. Call **update()** to perform the **Update** operation.
850
851   ```js
852   var properties = new Array();
853   properties[0] = {
854     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
855     value: huks.HuksKeyAlg.HUKS_ALG_DH
856   };
857   properties[1] = {
858     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
859     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
860   };
861   properties[2] = {
862     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
863     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
864   };
865   var options = {
866     properties: properties
867   };
868   var result = huks.update(handle, options)
869   ```
870
8715. Call **finish()** to finish the operation.
872
873   ```js
874   var properties = new Array();
875   properties[0] = {
876     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
877     value: huks.HuksKeyAlg.HUKS_ALG_DH
878   };
879   properties[1] = {
880     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
881     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
882   };
883   properties[2] = {
884     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
885     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
886   };
887   var options = {
888     properties: properties
889   };
890   var result = huks.finish(handle, options)
891   ```
892