subsys-security-huks-guide.md 46.7 KB
Newer Older
1
# 通用密钥库设备开发指导
scrawman's avatar
scrawman 已提交
2 3 4 5 6

## 概述

### 功能简介

7
OpenHarmony通用密钥库系统(英文全称:Open**H**armony **U**niversal **K**ey**S**tore,以下简称HUKS)是OpenHarmony提供的系统级的密钥管理系统服务,提供密钥的全生命周期管理能力,包括密钥生成、密钥存储、密钥使用、密钥销毁等功能,以及对存储在HUKS中的密钥提供合法性证明。在HUKS的分层架构中,处于最底层的HUKS核心层(HUKS Core)承载着密钥管理核心功能,一般运行在设备硬件安全环境中(比如TEE、安全芯片等)。由于不同厂商硬件安全环境不同,HUKS核心层的实现方式也不尽相同,为了保证服务层及应用层架构和接口的一致性,HUKS核心层定义了一套HDI接口(硬件设备统一接口),以保证HUKS服务层调用HUKS核心层的兼容。本文基于HUKS HDI接口,提供HUKS核心层功能的开发指导。
scrawman's avatar
scrawman 已提交
8

9
HUKS核心层需要支持以下功能:
10

11
1. 生成密钥
12

13
2. 外部导入密钥
14

15
3. 密钥操作(加密解密、签名验签、密钥派生、密钥协商、消息认证码等)
16

17
4. 密钥访问控制
18

19 20 21
5. 密钥证明

6. 芯片平台公钥导出
scrawman's avatar
scrawman 已提交
22

23
### 基本概念
scrawman's avatar
scrawman 已提交
24

25 26 27
- **HUKS Core**
  
  HUKS核心组件,承载HUKS的核心功能,包括密钥的密码学运算、明文密钥的加解密、密钥访问控制等。一般运行在设备的安全环境中(如TEE、安全芯片等,不同的厂商有所不同),保证密钥明文不出HUKS Core。
scrawman's avatar
scrawman 已提交
28

29 30
  
- **密钥会话** 
scrawman's avatar
scrawman 已提交
31

32
  应用通过指定密钥别名,给当前操作的密钥建立一个会话,HUKS为每个会话生成一个全局唯一的句柄值来索引该会话。它的作用是缓存密钥使用期间的信息,包括操作数据、密钥信息、访问控制属性等。密钥操作一般需要经过**建立会话、传入数据和参数、结束会话(中止会话)** 三个阶段。
scrawman's avatar
scrawman 已提交
33

34

35
- **可信执行环境(Trusted Execution Environment)**
scrawman's avatar
scrawman 已提交
36

37
  通过划分软件和硬件资源的方法构建一个安全区域,使得安全区域内部的程序和数据得到保护。这种划分会分隔出两个执行环境——可信执行环境和普通执行环境。每个执行环境有独立的内部数据通路和计算所需存储空间,保证可信执行环境里的信息不会向外泄露。普通执行环境的应用不能访问可信执行环境的资源,可信执行环境中的应用在没有授权的情况下也无法相互访问。
scrawman's avatar
scrawman 已提交
38

39

40 41
## 实现原理

42
HUKS采用分层架构,包含应用层、服务层、核心层(领域层),其中应用层主要对应用提供接口,服务层处理应用的密钥管理请求,进行密钥的密文管理、身份校验、密钥会话管理等,核心层提供密钥生成、密钥操作、密钥访问控制和密钥证明等核心功能。
43

44
**图1** HUKS分层架构图
45

46
![huks_architect](./figures/HUKS-architecture.png)
47

48
## 约束与限制
49

50
 - **密钥不出安全环境**
scrawman's avatar
scrawman 已提交
51

52
   HUKS的核心特点是密钥全生命周期明文不出HUKS Core,在有硬件条件的设备上,如有TEE(Trusted Execution Environment)或安全芯片的设备,HUKS Core运行在硬件安全环境中。即使REE(Rich Execution Environment)环境被攻破,也能确保密钥明文也不会泄露。因此,HUKS直通式HDI API所有函数接口密钥材料数据只能是密文格式。
53

54
- **系统级安全加密存储**
scrawman's avatar
scrawman 已提交
55

56
  必须基于设备根密钥加密业务密钥,在有条件的设备上,叠加用户口令加密保护密钥。
57

58
- **严格的访问控制**
scrawman's avatar
scrawman 已提交
59

60 61
  只有合法的业务才有权访问密钥,同时支持用户身份认证访问控制以支持业务的高安敏感场景下安全访问密钥的诉求。
- **密钥的合法性证明**
scrawman's avatar
scrawman 已提交
62

63
  业务提供硬件厂商级别的密钥的合法性证明,证明密钥没有被篡改,并确实存在于有硬件保护的HUKS Core中,以及拥有正确的密钥属性。
64 65

- **密钥材料格式** 
66
  
67
  导入/导出密钥时(包括密钥对、公钥、私钥),密钥材料的数据格式必须满足HUKS要求的格式,具体各个密码算法密钥材料见[密钥材料格式](../../application-dev/security/huks-appendix.md#密钥材料格式)
scrawman's avatar
scrawman 已提交
68

69
- **证书链格式** 
scrawman's avatar
scrawman 已提交
70

71
  AttestKey返回的证书链应该按照业务证书、设备证书、CA证书和根证书的顺序组装,在每项证书之前还需要加上证书的长度。证书链组装完成后添加整个证书链的长度组装成Blob格式。证书的具体格式如要自己实现应与服务器侧解析的格式相对应。
72

73
  ![CertChain格式图](figures/HUKS-CertChain.png)
74

75 76
- **KeyBlob格式**
  接口返回的密钥必须按照密钥存储态组装成KeyBlob,哪些接口需要遵循该限制请见[接口说明](#接口说明)
scrawman's avatar
scrawman 已提交
77

78
  ![KeyBlob格式图](figures/HUKS-KeyBlob.png)
scrawman's avatar
scrawman 已提交
79 80 81 82 83

## 开发指导

### 场景介绍

84
HUKS Core作为向应用提供密钥库能力的基础,包括密钥管理及密钥的密码学操作等功能。如果想要使用自己的实现替换HUKS Core,需要实现以下接口。
scrawman's avatar
scrawman 已提交
85 86 87 88 89 90 91

### 接口说明

**表1** 接口功能介绍

| 接口名                                                       | 功能介绍                                  | 约束与限制                     | 对应的js接口                                        |
| ------------------------------------------------------------ | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------ |
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
| [ModuleInit()](#moduleinit)                   | HUKS Core的初始化。                            |  无                           | 无 |
| [ModuleDestroy()](#moduledestroy)                   | HUKS Core的销毁。                            |  无                           | 无 |无                            | 无 |
| [GenerateKey()](#generatekey)                  | 根据密码算法参数,生成密钥,并返回密文材料。                                |  出参要遵循KeyBlob格式          |generateKey(keyAlias: string, options: HuksOptions)|
| [ImportKey()](#importkey)                     | 导入明文密钥,并返回密文材料。                            |  出参要遵循KeyBlob格式           | importKey(keyAlias: string, options: HuksOptions)|
| [ImportWrappedKey()](#importwrappedkey)        |导入加密密钥,并返回密文材料。                              |  出参要遵循KeyBlob格式          | importWrappedKey(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions)|
| [ExportPublicKey()](#exportpublickey)         | 导出密钥对中的公钥。                                 |无                             | exportKey(keyAlias: string, options: HuksOptions) |
| [Init()](#init)                              | 初始化密钥会话的接口,返回密钥会话句柄和令牌(可选)。                       |无                              | init(keyAlias: string, options: HuksOptions) |
| [Update()](#update)                           | 追加密钥操作数据。                     |签名验签时入参是原始数据          | update(handle: number, token?: Uint8Array, options: HuksOptions) |
| [Finish()](#finish)                           | 结束密钥会话                     |签名验签时入参是签名后数据        | finish(handle: number, options: HuksOptions) |
| [Abort()](#abort)                         | 取消密钥会话                               |无                             | abort(handle: number, options: HuksOptions) |
| [CheckKeyValidity()](#checkkeyvalidity)        | 校验密钥材料(密文)的完整性                              |无                            | 无 |
| [AttestKey()](#attestkey)        | 获取密钥证书。                              |出参要遵循密钥证书链格式                      | attestKey(keyAlias: string, options: HuksOptions)|
| [ExportChipsetPlatformPublicKey()](#exportchipsetplatformpublickey)        | 导出芯片平台级密钥对的公钥。     | 出参为ECC P256的x y轴值裸数据,各32字节                      | 无 |
| [UpgradeKey()](#upgradekey)        | 升级密钥文件。     | 无                      | 无 |
| [GenerateRandom()](#generaterandom)        | 生成安全随机数     | 无                      | 无 |
107 108 109 110
| [Encrypt()](#encrypt)        | 加密     | 无                      | 无 |
| [Decrypt()](#decrypt)        | 解密     | 无                      | 无 |
| [Sign()](#sign)        | 签名     | 无                      | 无 |
| [Verify()](#verify)        | 验签     | 无                      | 无 |
111 112 113
| [AgreeKey()](#agreekey)        | 密钥协商     | 无                      | 无 |
| [DeriveKey()](#derivekey)        | 密钥派生     | 无                      | 无 |
| [Mac()](#mac)        | 消息认证码     | 无                      | 无 |
scrawman's avatar
scrawman 已提交
114

115
- - -
scrawman's avatar
scrawman 已提交
116

117
#### ModuleInit
scrawman's avatar
scrawman 已提交
118 119 120

**接口描述**

121
HUKS Core的初始化,一般用于初始化全局变量,比如全局线程锁,算法库,用于访问控制的AuthToken Key和根密钥。
scrawman's avatar
scrawman 已提交
122 123

**接口原型**
124 125 126 127 128 129 130 131 132
<pre><code>int32_t ModuleInit(struct IHuks *self);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  </pre>
</details>
scrawman's avatar
scrawman 已提交
133 134 135 136

<details>
  <summary><strong>返回值</strong></summary>

137
  - HKS_SUCCESS:成功,值为0,下同
scrawman's avatar
scrawman 已提交
138

139
  - 其他:失败,值为负数,具体参考<a href="https://gitee.com/openharmony/security_huks/blob/master/interfaces/inner_api/huks_standard/main/include/hks_type.h">HksErrorCode枚举值定义</a>,下同
scrawman's avatar
scrawman 已提交
140 141
</details>

142
- - -
scrawman's avatar
scrawman 已提交
143

144 145

#### ModuleDestroy
scrawman's avatar
scrawman 已提交
146 147 148

**接口描述**

149
HUKS Core的销毁,一般用于释放全局变量,包括锁,销毁内存中的AuthToken Key和根密钥等。
scrawman's avatar
scrawman 已提交
150 151

**接口原型**
152 153 154 155 156 157 158 159 160
<pre><code>int32_t ModuleDestroy(struct IHuks *self);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  </pre>
</details>
scrawman's avatar
scrawman 已提交
161 162 163 164 165 166 167 168 169 170 171

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

172
#### GenerateKey
scrawman's avatar
scrawman 已提交
173 174 175

**接口描述**

176
根据密钥属性paramSet生成密钥。
scrawman's avatar
scrawman 已提交
177 178

**接口原型**
179 180
<pre><code>int32_t GenerateKey(struct IHuks *self, const struct HuksBlob *keyAlias, const struct HuksParamSet *paramSet,
    const struct HuksBlob *keyIn, struct HuksBlob *encKeyOut);</code></pre>
scrawman's avatar
scrawman 已提交
181 182 183 184

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
185 186 187 188
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *keyAlias</strong>
scrawman's avatar
scrawman 已提交
189 190 191
  将要生成的密钥的别名,要求:
  1. keyAlias != null
  2. keyAlias -> data != null
192
  3. keyAlias -> dataLen != 0
scrawman's avatar
scrawman 已提交
193
  <br></br>
194
  <strong>const struct HuksParamSet *paramSet</strong>
scrawman's avatar
scrawman 已提交
195 196
  要生成密钥的参数
  <br></br>
197 198
  <strong>const struct HuksBlob *keyIn</strong>
  可选,通过密钥协商或密钥派生生成密钥时,传原密钥材料
scrawman's avatar
scrawman 已提交
199
  <br></br>
200 201
  <strong>struct HuksBlob *encKeyOut</strong>
  出参,密钥密文材料,将密钥属性paramset和生成的密钥密文存放在这里,格式参考KeyBlob
scrawman's avatar
scrawman 已提交
202 203 204 205 206 207 208
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

209
  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
scrawman's avatar
scrawman 已提交
210

211
  2. keyOut请参照KeyBlob的结构。
scrawman's avatar
scrawman 已提交
212 213 214 215 216 217 218 219 220 221 222 223 224 225

</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

226
#### ImportKey
scrawman's avatar
scrawman 已提交
227 228 229 230 231 232

**接口描述**

导入明文密钥。

**接口原型**
233 234
<pre><code>int32_t ImportKey(struct IHuks *self, const struct HuksBlob *keyAlias, const struct HuksBlob *key,
    const struct HuksParamSet *paramSet, struct HuksBlob *encKeyOut);</code></pre>
scrawman's avatar
scrawman 已提交
235 236 237 238

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
239 240 241 242 243
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *keyAlias</strong>
  待导入的密钥的别名,要求:
scrawman's avatar
scrawman 已提交
244 245
  1. keyAlias != null
  2. keyAlias -> data != null
246
  3. keyAlias -> dataLen != 0
scrawman's avatar
scrawman 已提交
247
  <br></br>
248
  <strong>const struct HuksBlob *key</strong>
249
  待导入的密钥明文材料,密钥材料格式见<a href="https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-appendix.md#%E5%AF%86%E9%92%A5%E6%9D%90%E6%96%99%E6%A0%BC%E5%BC%8F">密钥材料格式</a>,要求:
scrawman's avatar
scrawman 已提交
250 251
  1. key != null
  2. key -> data != null
252
  3. key -> dataLen != 0
scrawman's avatar
scrawman 已提交
253
  <br></br>
254 255
  <strong>const struct HuksParamSet *paramSet</strong>
  待导入密钥的参数
scrawman's avatar
scrawman 已提交
256
  <br></br>
257 258
  <strong>struct HuksBlob *encKeyOut</strong>
  出参,密钥密文材料,将密钥属性paramset和生成的密钥密文存放在这里,格式参考KeyBlob
scrawman's avatar
scrawman 已提交
259 260 261 262 263 264 265
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

266
  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
scrawman's avatar
scrawman 已提交
267

268
  2. encKeyOut请参照KeyBlob的结构。
scrawman's avatar
scrawman 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282

</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

283
#### ImportWrappedKey
scrawman's avatar
scrawman 已提交
284 285 286 287 288 289

**接口描述**

导入加密密钥。

**接口原型**
290 291 292
<pre><code>int32_t ImportWrappedKey(struct IHuks *self, const struct HuksBlob *wrappingKeyAlias,
    const struct HuksBlob *wrappingEncKey, const struct HuksBlob *wrappedKeyData, const struct HuksParamSet *paramSet,
    struct HuksBlob *encKeyOut);</code></pre>
scrawman's avatar
scrawman 已提交
293 294 295 296

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
297 298
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
scrawman's avatar
scrawman 已提交
299
  <br></br>
300 301 302 303 304 305 306
  <strong>const struct HuksBlob *wrappingKeyAlias</strong>
  用于做加密导入的密钥的别名(非导入密钥本身的别名),要求:
  1. wrappingKeyAlias != null
  2. wrappingKeyAlias -> data != null
  3. wrappingKeyAlias -> dataLen != 0
  <br></br>
  <strong>const struct HuksBlob *wrappingEncKey</strong>
scrawman's avatar
scrawman 已提交
307
  要导入的密钥数据被加密时使用的密钥,要求:
308 309 310
  1. wrappingEncKey != null
  2. wrappingEncKey -> data != null
  3. wrappingEncKey -> dataLen != 0
scrawman's avatar
scrawman 已提交
311
  <br></br>
312
  <strong>const struct HuksBlob *wrappedKeyData</strong>
313
  要导入的密钥的密钥材料数据,格式参考<a href="https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-guidelines.md#%E5%8A%A0%E5%AF%86%E5%AF%BC%E5%85%A5">加密导入材料格式</a>,要求:
scrawman's avatar
scrawman 已提交
314 315
  1. wrappedKeyData != null
  2. wrappedKeyData -> data != null
316
  3. wrappedKeyData -> dataLen != 0
scrawman's avatar
scrawman 已提交
317
  <br></br>
318 319
  <strong>const struct HuksParamSet *paramSet</strong>
  待导入密钥的密钥属性
scrawman's avatar
scrawman 已提交
320
  <br></br>
321 322
  <strong>struct HuksBlob *encKeyOut</strong>
  导入密钥的密文材料,参考KeyBlob格式
scrawman's avatar
scrawman 已提交
323 324 325 326 327 328 329
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

330
  1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。
scrawman's avatar
scrawman 已提交
331

332
  2. encKeyOut请参照KeyBlob的结构。
scrawman's avatar
scrawman 已提交
333 334 335 336 337 338 339 340 341 342 343 344 345 346

</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

347
#### ExportPublicKey
scrawman's avatar
scrawman 已提交
348 349 350

**接口描述**

351
导出密钥对的公钥。
scrawman's avatar
scrawman 已提交
352 353

**接口原型**
354 355
<pre><code>int32_t ExportPublicKey(struct IHuks *self, const struct HuksBlob *encKey,
    const struct HuksParamSet *paramSet, struct HuksBlob *keyOut);</code></pre>
scrawman's avatar
scrawman 已提交
356 357 358 359

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
360 361 362 363 364 365 366 367
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  与要导出的公钥的密钥对材料,要求:
  1. encKey != null
  2. encKey -> data != null
  3. encKey -> dataLen != 0
scrawman's avatar
scrawman 已提交
368
  <br></br>
369 370
  <strong>const struct HuksParamSet *paramSet</strong>
  导出公钥的所需要的参数,默认为空
scrawman's avatar
scrawman 已提交
371
  <br></br>
372
  <strong>struct HuksBlob *keyOut</strong>
scrawman's avatar
scrawman 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387
  出参,存放导出的公钥
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

388
#### Init
scrawman's avatar
scrawman 已提交
389 390 391

**接口描述**

392
初始化密钥会话的接口,传入密钥材料密文,在HUKS Core进行解密,并生成密钥会话句柄和令牌(按需)
scrawman's avatar
scrawman 已提交
393 394

**接口原型**
395 396
<pre><code>int32_t Init(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
    struct HuksBlob *handle, struct HuksBlob *token);</code></pre>
scrawman's avatar
scrawman 已提交
397 398 399 400

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
401 402
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
scrawman's avatar
scrawman 已提交
403
  <br></br>
404 405 406 407 408
  <strong>const struct HuksBlob *encKey</strong>
  待操作密钥的密文材料,要求:
  1. encKey != null
  2. encKey -> data != null
  3. encKey -> dataLen != 0
scrawman's avatar
scrawman 已提交
409
  <br></br>
410 411
  <strong>const struct HuksParamSet *paramSet</strong>
  初始化密钥会话的参数
scrawman's avatar
scrawman 已提交
412
  <br></br>
413 414 415 416 417
  <strong>struct HuksBlob *handle</strong>
  出参,密钥会话的句柄,作为Update、Finish和Abort的入参,用于索引密钥会话
  <br></br>
  <strong>struct HuksBlob *token</strong>
  出参,存放密钥访问控制的认证令牌(按需)
scrawman's avatar
scrawman 已提交
418 419 420 421
  </pre>
</details>
<br></br>

422 423 424 425 426 427 428 429
<details>
  <summary><strong>约束与限制</strong></summary>

  1. 密钥会话操作函数,业务配合Update、Finish、Abort使用

</details>
<br></br>

scrawman's avatar
scrawman 已提交
430 431 432 433 434 435 436 437 438 439
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

440
#### Update
scrawman's avatar
scrawman 已提交
441 442 443

**接口描述**

444
追加密钥操作数据,如密码算法的要求需要对数据进行分段操作。
scrawman's avatar
scrawman 已提交
445 446

**接口原型**
447 448
<pre><code>int32_t Update(struct IHuks *self, const struct HuksBlob *handle, const struct HuksParamSet *paramSet,
    const struct HuksBlob *inData, struct HuksBlob *outData);</code></pre>
scrawman's avatar
scrawman 已提交
449 450 451 452

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
453 454 455 456 457
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *handle</strong>
  密钥会话的句柄
scrawman's avatar
scrawman 已提交
458
  <br></br>
459 460
  <strong> const struct HuksParamSet *paramSet</strong>
  追加操作的参数
scrawman's avatar
scrawman 已提交
461
  <br></br>
462 463
  <strong> const struct HuksBlob *inData</strong>
  追加操作的输入
scrawman's avatar
scrawman 已提交
464
  <br></br>
465 466
  <strong> struct HuksBlob *outData</strong>
  追加操作的结果
scrawman's avatar
scrawman 已提交
467 468 469 470 471 472 473
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

474 475 476
  1. 密钥会话操作函数,业务配合Init、Finish、Abort使用。

  2. 在进行签名验签时inData要传入原文数据。
scrawman's avatar
scrawman 已提交
477 478 479 480 481 482 483 484 485 486 487 488 489 490

</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

491
#### Finish
scrawman's avatar
scrawman 已提交
492 493 494

**接口描述**

495
结束密钥会话,操作最后一段数据并结束密钥会话。
scrawman's avatar
scrawman 已提交
496 497

**接口原型**
498 499
<pre><code>int32_t Finish(struct IHuks *self, const struct HuksBlob *handle, const struct HuksParamSet *paramSet,
    const struct HuksBlob *inData, struct HuksBlob *outData);</code></pre>
scrawman's avatar
scrawman 已提交
500 501 502 503

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
504 505 506 507 508
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *handle</strong>
  密钥会话的句柄
scrawman's avatar
scrawman 已提交
509
  <br></br>
510 511
  <strong>const struct HuksParamSet *paramSet</strong>
  最后一段操作的参数
scrawman's avatar
scrawman 已提交
512
  <br></br>
513 514
  <strong>const struct HuksBlob *inData</strong>
  最后一段操作的输入
scrawman's avatar
scrawman 已提交
515
  <br></br>
516 517
  <strong>struct HuksBlob *outData</strong>
  密钥操作的结果
scrawman's avatar
scrawman 已提交
518 519 520 521 522 523 524
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

525 526 527
  1. 密钥会话操作函数,业务配合Init、Update、Abort使用。

  2. 在进行验签时inData要传入需要验证的签名数据,通过返回结果表示验签是否成功。
scrawman's avatar
scrawman 已提交
528 529 530 531 532 533 534 535 536 537 538 539 540 541

</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

542
#### Abort
scrawman's avatar
scrawman 已提交
543 544 545

**接口描述**

546
取消密钥会话。当Init,Update和Finish操作中的任一阶段发生错误时,都要调用abort来终止密钥会话。
scrawman's avatar
scrawman 已提交
547 548

**接口原型**
549
<pre><code>int32_t Abort(struct IHuks *self, const struct HuksBlob *handle, const struct HuksParamSet *paramSet);</code></pre>
scrawman's avatar
scrawman 已提交
550 551 552 553

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
554 555
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
scrawman's avatar
scrawman 已提交
556
  <br></br>
557 558 559 560
  <strong>const struct HuksBlob *handle</strong>
  密钥会话的句柄
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
scrawman's avatar
scrawman 已提交
561 562 563 564 565
  Abort操作的参数
  </pre>
</details>
<br></br>

566 567 568 569 570 571 572 573
<details>
  <summary><strong>约束与限制</strong></summary>

  1. 密钥会话操作函数,业务配合Init、Update、Finish使用。

</details>
<br></br>

scrawman's avatar
scrawman 已提交
574 575 576 577 578 579 580 581 582 583
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

584
#### CheckKeyValidity
scrawman's avatar
scrawman 已提交
585 586 587 588 589 590

**接口描述**

获取密钥属性。

**接口原型**
591 592
<pre><code>int32_t CheckKeyValidity(struct IHuks *self, const struct HuksParamSet *paramSet,
    const struct HuksBlob *encKey);</code></pre>
scrawman's avatar
scrawman 已提交
593 594 595 596

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
597 598 599 600 601
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于校验密钥完整性接口的参数,默认传空
scrawman's avatar
scrawman 已提交
602
  <br></br>
603
  <strong>const struct HuksBlob *encKey</strong>
604
  待校验密钥完整性的密钥材料(密文)
scrawman's avatar
scrawman 已提交
605 606 607 608
  </pre>
</details>
<br></br>

609 610 611 612 613 614 615 616 617 618
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

619
#### AttestKey
620 621 622 623 624 625

**接口描述**

获取密钥证书。

**接口原型**
626 627
<pre><code>int32_t AttestKey(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
    struct HuksBlob *certChain);</code></pre>
628 629 630 631

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
632 633
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
634
  <br></br>
635 636
  <strong>const struct HuksBlob *encKey</strong>
  要获取证书的密钥对材料密文
637
  <br></br>
638 639 640 641
  <strong>const struct HuksParamSet *paramSet</strong>
  获取密钥证书操作的参数,如challenge等
  <br></br>
  <strong>struct HuksBlob *certChain</strong>
642
  出参,存放证书链,格式参考上述证书链格式
643 644 645 646 647 648 649
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

650
  1. certChain的格式需遵循[约束与限制第二点](#约束与限制)
651 652 653 654

</details>
<br></br>

655 656 657 658 659 660 661 662 663 664
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

665
#### ExportChipsetPlatformPublicKey
666 667 668 669 670 671

**接口描述**

导出芯片平台级密钥对的公钥。

**接口原型**
672 673
<pre><code>int32_t ExportChipsetPlatformPublicKey(struct IHuks *self, const struct HuksBlob *salt,
    enum HuksChipsetPlatformDecryptScene scene, struct HuksBlob *publicKey);</code></pre>
674 675 676 677

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
678 679 680 681
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *salt</strong>
682 683
  用来派生芯片平台密钥对时的派生因子
  <br></br>
684
  <strong>enum HuksChipsetPlatformDecryptScene scene</strong>
685 686
  业务预期进行芯片平台解密的场景
  <br></br>
687
  <strong>struct HuksBlob *publicKey</strong>
688 689 690 691 692 693 694 695
  出参为ECC P256的x y轴值裸数据,各32字节
  </pre>
</details>
<br></br>

<details>
  <summary><strong>约束与限制</strong></summary>

696
  1. 入参`salt`长度必须为16字节,且最后一个字节的内容会被忽略,将由huks内部根据入参`scene`进行修改填充。<br>
697
  当前huks的芯片平台级密钥对为软实现,硬编码了一对ECC-P256密钥对到代码中,`salt`值被忽略,即无论传入什么`salt`,派生出的密钥都是一样的。在真正基于硬件的芯片平台级密钥实现中,`salt`为用来派生密钥的派生因子,传入不同的`salt`会得到不同的密钥对。
698 699 700 701

</details>
<br></br>

702 703 704 705 706 707 708 709 710 711
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

712
#### UpgradeKey
713 714 715 716 717 718

**接口描述**

升级密钥文件。当密钥文件版本号小于最新版本号时,触发该升级能力。

**接口原型**
719 720
<pre><code>int32_t UpgradeKey(struct IHuks *self, const struct HuksBlob *encOldKey, const struct HuksParamSet *paramSet,
    struct HuksBlob *encNewKey);</code></pre>
721 722 723 724

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
725 726 727 728
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encOldKey</strong>
729 730
  待升级的密钥文件数据
  <br></br>
731
  <strong>const struct HuksParamSet *paramSet</strong>
732 733
  升级密钥文件数据的参数
  <br></br>
734
  <strong>struct HuksBlob *newKey</strong>
735 736 737 738 739
  出参,升级后的密钥文件数据
  </pre>
</details>
<br></br>

scrawman's avatar
scrawman 已提交
740 741 742 743 744 745 746 747 748 749
<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026
#### GenerateRandom

**接口描述**

生成安全随机数

**接口原型**
<pre><code>int32_t GenerateRandom(struct IHuks *self, const struct HuksParamSet *paramSet, struct HuksBlob *random);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  待生成安全随机数的参数,如长度
  <br></br>
  <strong>struct HuksBlob *random</strong>
  出参,随机数
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### Sign

**接口描述**

对数据进行签名

**接口原型**
<pre><code>int32_t Sign(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
    const struct HuksBlob *srcData, struct HuksBlob *signature);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  用于签名的密钥对材料(密文)
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于签名的参数,如摘要模式
  <br></br>
  <strong>const struct HuksBlob *srcData</strong>
  用于签名的数据
  <br></br>
  <strong>struct HuksBlob *signature</strong>
  出参,数据签名
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### Verify

**接口描述**

对数据签名进行验签

**接口原型**
<pre><code>int32_t Verify(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
    const struct HuksBlob *srcData, const struct HuksBlob *signature);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  用于验签的密钥对材料(密文)
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于验签的参数,如摘要模式
  <br></br>
  <strong>const struct HuksBlob *srcData</strong>
  待验签的数据
  <br></br>
  <strong>const struct HuksBlob *signature</strong>
  用于验签的签名
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### Encrypt

**接口描述**

对数据进行单次加密,相比密钥会话接口,该接口需满足一次调用即可完成加密操作

**接口原型**
<pre><code>int32_t Encrypt(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
     const struct HuksBlob *plainText, struct HuksBlob *cipherText);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  用于加密的密钥材料(密文)
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于加密的密钥参数,如密钥工作模式、填充模式等
  <br></br>
  <strong>const struct HuksBlob *plainText</strong>
  待加密的数据明文
  <br></br>
  <strong>const struct HuksBlob *cipherText</strong>
  加密后的数据密文
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### Decrypt

**接口描述**

对数据进行单次解密,相比密钥会话接口,该接口需要满足一次调用完成解密操作

**接口原型**
<pre><code>int32_t Decrypt(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
    const struct HuksBlob *cipherText, struct HuksBlob *plainText);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  用于解密的密钥材料(密文)
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于解密的密钥参数,如密钥工作模式、填充模式等
  <br></br>
  <strong>const struct HuksBlob *cipherText</strong>
  待解密的数据密文
  <br></br>
  <strong>const struct HuksBlob *plainText</strong>
  解密后的数据明文
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### AgreeKey

**接口描述**

对密钥进行协商,相比密钥会话接口,该接口需要满足一次调用完成密钥协商操作

**接口原型**
<pre><code>int32_t AgreeKey(struct IHuks *self, const struct HuksParamSet *paramSet,
    const struct HuksBlob *encPrivateKey, const struct HuksBlob *peerPublicKey, struct HuksBlob *agreedKey);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于协商的参数,如协商密钥的长度
  <br></br>
  <strong>const struct HuksBlob *encPrivateKey</strong>
  用于协商的密钥对材料(密文)
  <br></br>
  <strong>const struct HuksBlob *peerPublicKey</strong>
  用于协商密钥对公钥(明文)
  <br></br>
  <strong>struct HuksBlob *agreedKey</strong>
  出参,协商出的密钥明文
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

#### DeriveKey

**接口描述**

对密钥进行派生,相比密钥会话接口,该接口需要满足一次调用完成密钥派生操作

**接口原型**
<pre><code>int32_t DeriveKey(struct IHuks *self, const struct HuksParamSet *paramSet, const struct HuksBlob *encKdfKey,
     struct HuksBlob *derivedKey);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于密钥派生的参数,如派生密钥的长度
  <br></br>
  <strong>const struct HuksBlob *encKdfKey</strong>
  用于派生的密钥材料(密文)
  <br></br>
  <strong>struct HuksBlob *derivedKey</strong>
  出参,派生出的密钥(明文)
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -

1027
#### Mac
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066

**接口描述**

根据密钥生成消息认证码

**接口原型**
<pre><code>int32_t Mac(struct IHuks *self, const struct HuksBlob *encKey, const struct HuksParamSet *paramSet,
     const struct HuksBlob *srcData, struct HuksBlob *mac);</code></pre>

<details>
  <summary><strong>参数说明</strong></summary>
  <pre>
  <strong>struct IHuks *self</strong>
  HUKS HDI函数指针结构体指针
  <br></br>
  <strong>const struct HuksBlob *encKey</strong>
  用于生成消息认证码的密钥材料(密文)
  <br></br>
  <strong>const struct HuksParamSet *paramSet</strong>
  用于生成消息认证码的参数
  <br></br>
  <strong>const struct HuksBlob *srcData</strong>
  消息数据
  <br></br>
  <strong>struct HuksBlob *mac</strong>
  出参,消息认证码
  </pre>
</details>
<br></br>

<details>
  <summary><strong>返回值</strong></summary>

  - HKS_SUCCESS:成功

  - 其他:失败
</details>

- - -
scrawman's avatar
scrawman 已提交
1067 1068
### 开发步骤

1069 1070
#### 代码目录

W
wkyrong 已提交
1071
1. HDI接口的适配在以下目录中:
scrawman's avatar
scrawman 已提交
1072 1073

```undefined
1074
//drivers_peripheral/huks
scrawman's avatar
scrawman 已提交
1075
├── BUILD.gn # 编译脚本
1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087
├── hdi_service # 实现依赖,通过dloppen方式引用libhuks_engine_core_standard.z.so(软实现的HUKS Core,仅用于参考)
    ├── huks_sa_type.h # HUKS服务层的数据结构定义
    ├── huks_sa_hdi_struct.h # libhuks_engine_core_standard.z.so中函数指针结构体的定义
    ├── huks_hdi_template.h # HUKS服务层和HDI接口数据结构的转化适配
    ├── huks_hdi_service.c # HUKS直通式HDI服务层的接口实现
    └── huks_hdi_passthrough_adapter.c # HUKS直通式HDI服务层到软实现HUKS Core的适配层
└── test # HUKS HDI接口unittest和fuzztest
    ├── BUILD.gn # 编译脚本
    ├── fuzztest # fuzz测试
    └── unittest # 单元测试
```

W
wkyrong 已提交
1088
2. HUKS Core软实现的代码在以下目录中:
1089 1090 1091 1092 1093

```undefined
//base/security/huks/services/huks_standard/huks_engine
├── BUILD.gn # 编译脚本
├── core_dependency # HUKS Core依赖
1094
└── core # HUKS Core层的软实现
scrawman's avatar
scrawman 已提交
1095 1096 1097
    ├── BUILD.gn # 编译脚本
    ├── include 
    └── src
1098
        ├── hks_core_interfaces.c # HDI到HUKS Core的适配层
1099
        └── hks_core_service.c # HUKS Core详细实现
scrawman's avatar
scrawman 已提交
1100 1101
        └── ... #其他功能代码
```
W
wkyrong 已提交
1102
**注意事项!!!**
scrawman's avatar
scrawman 已提交
1103

W
wkyrong 已提交
1104
  <summary><strong>HUKS Core软实现中存在硬编码相关敏感数据,包括根密钥、访问控制用的AuthToken密钥、加密AuthToken用的密钥、证书相关等,如设备开发者使用了相关代码,一定要替换成自有实现</strong></summary>
W
wkyrong 已提交
1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120

  - **根密钥**

    用于加密HUKS业务密钥,一般由设备根密钥派生而来,HUKS Core软实现中硬编码在代码中,详细代码见<a href="https://gitee.com/openharmony/security_huks/blob/master/frameworks/huks_standard/main/crypto_engine/openssl/src/hks_openssl_get_main_key.c">hks_openssl_get_main_key.c</a>

 - **访问控制用于对AuthToken做HMAC的密钥**

   用于UserIAM对AuthToken进行HMAC,HUKS Core软实现中硬编码在代码中,值为"huks_default_user_auth_token_key",详细代码见<a href="https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_keyblob.c">hks_keyblob.c</a>

 - **访问控制用于对AuthToken敏感字段加密的密钥**

   用于UserIAM对AuthToken敏感字段进行加密的密钥,HUKS Core软实现中硬编码在代码中,值为"huks_default_user_auth_token_key",详细代码见<a href="https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_keyblob.c">hks_keyblob.c</a>

  - **根证书、设备CA、设备证书**

    用于密钥证明,一般由设备证书管理模块预置在硬件设备安全存储当中,HUKS Core软实现中硬编码在代码中,详细代码见<a href="https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/device_cert_manager/include/dcm_certs_and_key.h">dcm_certs_and_key.h</a>
1121

1122 1123
#### 适配样例

1124
下文以HUKS Core中的密钥会话Init\Update\Finish接口适配作为一个样例,介绍基本流程,仅供参考不可实际运行,实际可运行代码参考[HUKS源码目录](https://gitee.com/openharmony/security_huks)
scrawman's avatar
scrawman 已提交
1125

1126
1. 创建一个句柄,通过这个句柄在session中存储密钥操作相关的信息,使得外部可以通过这个句柄分多次进行同一密钥操作。
1127

1128
   ```c
scrawman's avatar
scrawman 已提交
1129

1130
   //密钥会话Init接口
scrawman's avatar
scrawman 已提交
1131

1132 1133
   int32_t HksCoreInit(const struct  HuksBlob *key, const struct HuksParamSet *paramSet, struct HuksBlob *handle,
    struct HuksBlob *token)
1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
   {
       HKS_LOG_D("HksCoreInit in Core start");
       uint32_t pur = 0;
       uint32_t alg = 0;
       //检查参数
       if (key == NULL || paramSet == NULL || handle == NULL || token == NULL) {
           HKS_LOG_E("the pointer param entered is invalid");
           return HKS_FAILURE;
        }

1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193
        if (handle->size < sizeof(uint64_t)) {
            HKS_LOG_E("handle size is too small, size : %u", handle->size);
            return HKS_ERROR_INSUFFICIENT_MEMORY;
        }
        //解密密钥文件
        struct HuksKeyNode *keyNode = HksCreateKeyNode(key, paramSet);
        if (keyNode == NULL || handle == NULL) {
            HKS_LOG_E("the pointer param entered is invalid");
            return HKS_ERROR_BAD_STATE;
        }
        //通过handle向session中存储信息,供Update/Finish使用。使得外部可以通过同个handle分多次进行同一密钥操作。
        handle->size = sizeof(uint64_t);
        (void)memcpy_s(handle->data, handle->size, &(keyNode->handle), handle->size);
        //从参数中提取出算法
        int32_t ret = GetPurposeAndAlgorithm(paramSet, &pur, &alg);
        if (ret != HKS_SUCCESS) {
            HksDeleteKeyNode(keyNode->handle);
            return ret;
        }
        //检查密钥参数
        ret = HksCoreSecureAccessInitParams(keyNode, paramSet, token);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("init secure access params failed");
            HksDeleteKeyNode(keyNode->handle);
            return ret;
        }
        //通过密钥使用目的获取对应的算法库处理函数  
        uint32_t i;
        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreInitHandler);
        for (i = 0; i < size; i++) {
           if (g_hksCoreInitHandler[i].pur == pur) {
               HKS_LOG_E("Core HksCoreInit [pur] = %d, pur = %d", g_hksCoreInitHandler[i].pur, pur);
               ret = g_hksCoreInitHandler[i].handler(keyNode, paramSet, alg);
               break;
        }
        }
        //异常结果检查
        if (ret != HKS_SUCCESS) {
            HksDeleteKeyNode(keyNode->handle);
            HKS_LOG_E("CoreInit failed, ret : %d", ret);
            return ret;
        }
    
        if (i == size) {
            HksDeleteKeyNode(keyNode->handle);
            HKS_LOG_E("don't found purpose, pur : %u", pur);
            return HKS_FAILURE;
        }
    
        HKS_LOG_D("HksCoreInit in Core end");
1194 1195 1196
        return ret;
    }
   ```
1197

1198 1199
2. 在执行密钥操作前通过句柄获得上下文信息,执行密钥操作时放入分片数据并取回密钥操作结果或者追加数据。
   
1200
    ```c
1201
    //密钥会话Update接口
1202 1203
    int32_t HksCoreUpdate(const struct HuksBlob *handle, const struct HuksParamSet *paramSet, const struct HuksBlob *inData,
        struct HuksBlob *outData)
1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
    {
        HKS_LOG_D("HksCoreUpdate in Core start");
        uint32_t pur = 0;
        uint32_t alg = 0;
        //检查参数
        if (handle == NULL || paramSet == NULL || inData == NULL) {
            HKS_LOG_E("the pointer param entered is invalid");
            return HKS_FAILURE;
        }
        
        uint64_t sessionId;
        struct HuksKeyNode *keyNode = NULL;
1216
        //根据handle获取本次密钥会话操作需要的上下文
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233
        int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
        if (ret != HKS_SUCCESS) {
            HKS_LOG_E("GetParamsForCoreUpdate failed");
            return ret;
        }
        //校验密钥参数
        ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
        if (ret != HKS_SUCCESS) {
            HksDeleteKeyNode(sessionId);
            HKS_LOG_E("HksCoreUpdate secure access verify failed");
            return ret;
        }
        //调用对应的算法库密钥处理函数
        uint32_t i;
        uint32_t size = HKS_ARRAY_SIZE(g_hksCoreUpdateHandler);
        for (i = 0; i < size; i++) {
            if (g_hksCoreUpdateHandler[i].pur == pur) {
1234
                struct HuksBlob appendInData = { 0, NULL };
1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
                ret = HksCoreAppendAuthInfoBeforeUpdate(keyNode, pur, paramSet, inData, &appendInData);
                if (ret != HKS_SUCCESS) {
                    HKS_LOG_E("before update: append auth info failed");
                    break;
                }
                ret = g_hksCoreUpdateHandler[i].handler(keyNode, paramSet,
                     appendInData.data == NULL ? inData : &appendInData, outData, alg);
                if (appendInData.data != NULL) {
                    HKS_FREE_BLOB(appendInData);
                }
                break;
            }
        }
        //异常结果检查
1249
        if (ret != HKS_SUCCESS) {
1250 1251 1252
            HksDeleteKeyNode(keyNode->handle);
            HKS_LOG_E("CoreUpdate failed, ret : %d", ret);
            return ret;
1253
        }
1254 1255 1256 1257 1258
        
        if (i == size) {
            HksDeleteKeyNode(sessionId);
            HKS_LOG_E("don't found purpose, pur : %u", pur);
            return HKS_FAILURE;
1259
        }
1260
        return ret;
1261
    }
1262
    ```
1263

1264
3. 结束密钥操作并取回结果,销毁句柄。
1265

1266
   ```c
1267
   //密钥会话Finish接口
1268 1269
   int32_t HksCoreFinish(const struct HuksBlob *handle, const struct HuksParamSet *paramSet, const struct HuksBlob *inData,
    struct HuksBlob *outData)
1270
   {
1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281
       HKS_LOG_D("HksCoreFinish in Core start");
       uint32_t pur = 0;
       uint32_t alg = 0;
       //检查参数
       if (handle == NULL || paramSet == NULL || inData == NULL) {
           HKS_LOG_E("the pointer param entered is invalid");
           return HKS_FAILURE;
       }
    
       uint64_t sessionId;
       struct HuksKeyNode *keyNode = NULL;
1282
       //根据handle获取本次密钥会话操作需要的上下文
1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
       int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg);
       if (ret != HKS_SUCCESS) {
           HKS_LOG_E("GetParamsForCoreUpdate failed");
           return ret;
       }
       //校验密钥参数
       ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet);
       if (ret != HKS_SUCCESS) {
           HksDeleteKeyNode(sessionId);
           HKS_LOG_E("HksCoreFinish secure access verify failed");
           return ret;
       }
       //调用对应的算法库密钥处理函数
       uint32_t i;
       uint32_t size = HKS_ARRAY_SIZE(g_hksCoreFinishHandler);
       for (i = 0; i < size; i++) {
           if (g_hksCoreFinishHandler[i].pur == pur) {
               uint32_t outDataBufferSize = (outData == NULL) ? 0 : outData->size;
1301
               struct HuksBlob appendInData = { 0, NULL };
1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316
               ret = HksCoreAppendAuthInfoBeforeFinish(keyNode, pur, paramSet, inData, &appendInData);
               if (ret != HKS_SUCCESS) {
                   HKS_LOG_E("before finish: append auth info failed");
                   break;
               }
               ret = g_hksCoreFinishHandler[i].handler(keyNode, paramSet,
                   appendInData.data == NULL ? inData : &appendInData, outData, alg);
               if (appendInData.data != NULL) {
                   HKS_FREE_BLOB(appendInData);
               }
               if (ret != HKS_SUCCESS) {
                   break;
               }
               //添加密钥操作结束标签
               ret = HksCoreAppendAuthInfoAfterFinish(keyNode, pur, paramSet, outDataBufferSize, outData);
1317 1318
               break;
           }
1319
       }
1320 1321 1322 1323 1324 1325 1326 1327
       if (i == size) {
           HKS_LOG_E("don't found purpose, pur : %d", pur);
           ret = HKS_FAILURE;
       }
       //删除对应的session
       HksDeleteKeyNode(sessionId);
       HKS_LOG_D("HksCoreFinish in Core end");
       return ret;
1328
   }
1329
   ```
scrawman's avatar
scrawman 已提交
1330 1331 1332

### 调测验证

1333 1334
开发完成后,通过[HUKS JS接口](https://gitee.com/openharmony/security_huks/blob/master/interfaces/kits/js/@ohos.security.huks.d.ts)开发JS应用来验证能力是否完备。

1335
对于每个HDI接口,[接口说明](#接口说明)都提供了对应的JS接口。可以通过调用JS接口组合来验证对应的HDI接口的能力,也可以通过完整的密钥操作来验证接口的能力。
1336

W
wkyrong 已提交
1337
JS测试代码示例如下(仅供参考),如果整个流程能够正常运行,代表HDI接口能力正常。更多的密钥操作类型和完整样例请见[huks-guidelines.md](../../application-dev/security/huks-guidelines.md)
scrawman's avatar
scrawman 已提交
1338

1339 1340
**AES生成密钥和加密**

1341
1. 引入HUKS模块
scrawman's avatar
scrawman 已提交
1342

1343
   ```js
1344 1345
   import huks from '@ohos.security.huks'
   ```
1346

1347
2. 使用generateKey接口生成密钥。
1348

1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445
   ```js
   var alias = 'testAlias';
   var properties = new Array();
   properties[0] = {
     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
     value: huks.HuksKeyAlg.HUKS_ALG_ECC
   };
   properties[1] = {
     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
     value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_224
   };
   properties[2] = {
     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
   };
   properties[3] = {
     tag: huks.HuksTag.HUKS_TAG_DIGEST,
     value: huks.HuksKeyDigest.HUKS_DIGEST_NONE
   };
   var options = {
     properties: properties
   }
   var resultA = huks.generateKey(alias, options);
   ```

3. 使用Init接口进行init操作。

   ```js
   var alias = 'test001'
   var properties = new Array();
   properties[0] = {
     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
     value: huks.HuksKeyAlg.HUKS_ALG_DH
   };
   properties[1] = {
     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
   };
   properties[2] = {
     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
   };
   var options = {
     properties: properties
   };
   huks.init(alias, options, function(err, data) {
       if (err.code !== 0) {
           console.log("test init err information: " + JSON.stringify(err));
       } else {
           console.log(`test init data: ${JSON.stringify(data)}`);
       }
   })
   ```
   
4. 使用Update接口进行update操作。

   ```js
   var properties = new Array();
   properties[0] = {
     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
     value: huks.HuksKeyAlg.HUKS_ALG_DH
   };
   properties[1] = {
     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
   };
   properties[2] = {
     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
   };
   var options = {
     properties: properties
   };
   var result = huks.update(handle, options)
   ```
   
5. 使用Finish接口进行finish操作。

   ```js
   var properties = new Array();
   properties[0] = {
     tag: huks.HuksTag.HUKS_TAG_ALGORITHM,
     value: huks.HuksKeyAlg.HUKS_ALG_DH
   };
   properties[1] = {
     tag: huks.HuksTag.HUKS_TAG_PURPOSE,
     value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE
   };
   properties[2] = {
     tag: huks.HuksTag.HUKS_TAG_KEY_SIZE,
     value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096
   };
   var options = {
     properties: properties
   };
   var result = huks.finish(handle, options) 
   ```