1# OpenHarmony通用密钥库开发指导 2 3## 概述 4 5### 功能简介 6 7HUKS(OpenHarmony Universal KeyStore)提供系统级的密钥管理能力,实现密钥全生命周期(生成、存储、使用、销毁)的管理和安全使用,满足生态应用和上层业务的诉求。其中,密钥的安全存储和安全使用环境是密钥安全最重要的约束,如对明文密钥的存储和使用不能出现在非安全环境中,需要保证在安全环境中使用(比如TEE,安全芯片等);本文档介绍了开发者在OpenHarmony HUKS架构的基础上适配安全存储和安全使用环境的步骤,以及如何去验证适配是否正确,以保证API接口的兼容。 8 9HUKS支持密钥全生命周期管理,包括以下特性: 10 111. 密钥生成/导入 12 132. 密钥存储 14 153. 密钥使用(加解密、签名验签、密钥派生、密钥协商、哈希、密钥访问控制等) 16 174. 密钥销毁 18 19### 基本概念 20 21- 服务层(HUKS Service) 22 23 承载密钥管理功能的一个独立的OpenHarmony Service附属于huks_service进程,HUKS Service并不直接处理密钥运算,依赖HUKS Core为上层提供服务。 24 25- 核心层(HUKS CORE) 26 27 提供密钥管理服务的核心功能模块,需要保证该模块处于安全环境中且密钥全生命周期明文不出HUKS Core模块。 28 29- 可信执行环境(Trusted Execution Environment) 30 31 通过划分软件和硬件资源的方法构建一个安全区域,使得安全区域内部的程序和数据得到保护。这种划分会分隔出两个执行环境——可信执行环境和普通执行环境。每个执行环境有独立的内部数据通路和计算所需存储空间,保证可信执行环境里的信息不会向外泄露。普通执行环境的应用不能访问可信执行环境的资源,可信执行环境中的应用在没有授权的情况下也无法相互访问。 32 33- 三段式(Init-Update-Finish) 34 35 Init:初始化密钥操作数据。 36 37 Update:分段操作数据并返回结果,或追加数据。 38 39 Finish:结束分段操作或追加数据,返回结果。 40 41### 实现原理 42 43以密钥的生成为例介绍HUKS Service与HUKS Core的通信过程,其他密钥操作类似: 44上层应用通过密钥管理SDK调用到HUKS Service,HUKS Service再调用HUKS Core,HUKS Core会调用密钥管理模块生成密钥。之后HUKS Core使用基于RootKey派生的加密密钥对生成的密钥加密再传给Service侧,Service侧再以文件形式存储加密后的密钥。 45 46![HUKS密钥生成流程图](figures/HUKS-GenerateKey1.png) 47 48### 约束与限制 49 50* HUKS的实现需要在可信执行环境中实现,保证密钥管理和操作的可信可靠。 51 52* HuksHdiAttestKey返回的证书链应该按照业务证书、设备证书、CA证书和根证书的顺序组装,在每项证书之前还需要加上证书的长度。证书链组装完成后添加整个证书链的长度组装成Blob格式。证书的具体格式如要自己实现应与服务器侧解析的格式相对应。 53 54![CertChain格式图](figures/HUKS-CertChain.png) 55 56* 接口返回的密钥必须按照密钥存储态组装成KeyBlob,哪些接口需要遵循该限制请见[接口说明](#接口说明)。 57 58 KeyBlob存储密钥的同时存储它的属性,结构见下图。构造KeyBlob的示例请参见[hks_keyblob.c/HksBuildKeyBlob](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_keyblob.c)。 59 60![KeyBlob格式图](figures/HUKS-KeyBlob.png) 61 62## 开发指导 63 64### 场景介绍 65 66HUKS Core作为向应用提供密钥库能力的基础,包括密钥管理及密钥的密码学操作等功能。如果想要使用自己的实现替换HUKS Core,需要实现以下接口。 67 68### 接口说明 69 70**表1** 接口功能介绍 71 72| 接口名 | 功能介绍 | 约束与限制 | 对应的js接口 | 73| ------------------------------------------------------------ | ---------------------------------------- | ----------------------------- | ------------------------------------------------------------ | 74| [HuksHdiModuleInit()](#hukshdimoduleinit) | HUKS Core的初始化。 | 无 | 无 | 75| [HuksHdiRefresh()](#hukshdirefresh) | 刷新根密钥。 | 无 | 无 | 76| [HuksHdiGenerateKey()](#hukshdigeneratekey) | 生成密钥。 | 出参要遵循KeyBlob格式 |generateKey(keyAlias: string, options: HuksOptions)| 77| [HuksHdiImportKey()](#hukshdiimportkey) | 导入明文密钥。 | 出参要遵循KeyBlob格式 | importKey(keyAlias: string, options: HuksOptions)| 78| [HuksHdiImportWrappedKey()](#hukshdiimportwrappedkey) |导入加密密钥。 | 出参要遵循KeyBlob格式 | importWrappedKey(keyAlias: string, wrappingKeyAlias: string, options: HuksOptions)| 79| [HuksHdiExportPublicKey()](#hukshdiexportpublickey) | 导出公钥。 |无 | exportKey(keyAlias: string, options: HuksOptions) | 80| [HuksHdiInit()](#hukshdiinit) | 三段式中的Init接口。 |无 | init(keyAlias: string, options: HuksOptions) | 81| [HuksHdiUpdate()](#hukshdiupdate) | 三段式中的Update接口。 |签名验签时入参是原始数据 | update(handle: number, token?: Uint8Array, options: HuksOptions) | 82| [HuksHdiFinish()](#hukshdifinish) | 三段式中的Finish接口。 |签名验签时入参是签名后数据 | finish(handle: number, options: HuksOptions) | 83| [HuksHdiAbort()](#hukshdiabort) | 终止三段式。 |无 | abort(handle: number, options: HuksOptions) | 84| [HuksHdiGetKeyProperties()](#hukshdigetkeyproperties) | 获取密钥属性。 |无 | getKeyProperties(keyAlias: string, options: HuksOptions)| 85| [HuksHdiAttestKey()](#hukshdiattestkey) | 获取密钥证书。 |出参要遵循certChain格式 | attestKey(keyAlias: string, options: HuksOptions)| 86 87- - - 88 89#### HuksHdiModuleInit 90 91**接口描述** 92 93HUKS Core的初始化,包括锁,加密算法库,authtoken key和根密钥。 94 95**接口原型** 96<pre><code>int32_t HuksHdiModuleInit();</code></pre> 97 98<details> 99 <summary><strong>返回值</strong></summary> 100 101 - HKS_SUCCESS:成功 102 103 - 其他:失败 104</details> 105 106- - - 107 108#### HuksHdiRefresh 109 110**接口描述** 111 112刷新根密钥。 113 114**接口原型** 115<pre><code>int32_t HuksHdiRefresh();</code></pre> 116 117<details> 118 <summary><strong>返回值</strong></summary> 119 120 - HKS_SUCCESS:成功 121 122 - 其他:失败 123</details> 124 125- - - 126 127#### HuksHdiGenerateKey 128 129**接口描述** 130 131根据paramSet生成密钥。 132 133**接口原型** 134<pre><code>int32_t HuksHdiGenerateKey(const struct HksBlob *keyAlias, const struct HksParamSet *paramSet, const struct HksBlob *keyIn, struct HksBlob *keyOut);</code></pre> 135 136<details> 137 <summary><strong>参数说明</strong></summary> 138 <pre> 139 <strong>const struct HksBlob *keyAlias</strong> 140 将要生成的密钥的别名,要求: 141 1. keyAlias != null 142 2. keyAlias -> data != null 143 3. keyAlias -> size != 0 144 <br></br> 145 <strong>const struct HksParamSet *paramSet</strong> 146 要生成密钥的参数 147 <br></br> 148 <strong>const struct HksBlob *keyIn</strong> 149 在agree key时使用 150 <br></br> 151 <strong>struct HksBlob *keyOut</strong> 152 出参,将paramset和生成的密钥存放在这里 153 </pre> 154</details> 155<br></br> 156 157<details> 158 <summary><strong>约束与限制</strong></summary> 159 160 1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。 161 162 2. keyOut请参照KeyBlob的结构。 163 164</details> 165<br></br> 166 167<details> 168 <summary><strong>返回值</strong></summary> 169 170 - HKS_SUCCESS:成功 171 172 - 其他:失败 173</details> 174 175- - - 176 177#### HuksHdiImportKey 178 179**接口描述** 180 181导入明文密钥。 182 183**接口原型** 184<pre><code>int32_t HuksHdiImportKey(const struct HksBlob *keyAlias, const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre> 185 186<details> 187 <summary><strong>参数说明</strong></summary> 188 <pre> 189 <strong>const struct HksBlob *msg</strong> 190 将要导入的密钥的别名,要求: 191 1. keyAlias != null 192 2. keyAlias -> data != null 193 3. keyAlias -> size != 0 194 <br></br> 195 <strong>const struct HksBlob *key</strong> 196 要导入的密钥,要求: 197 1. key != null 198 2. key -> data != null 199 3. key -> size != 0 200 <br></br> 201 <strong>const struct HksParamSet *paramSet</strong> 202 导入密钥的参数 203 <br></br> 204 <strong>struct HksBlob *keyOut</strong> 205 出参,将paramset和生成的密钥存放在这里 206 <br></br> 207 </pre> 208</details> 209<br></br> 210 211<details> 212 <summary><strong>约束与限制</strong></summary> 213 214 1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。 215 216 2. keyOut请参照KeyBlob的结构。 217 218</details> 219<br></br> 220 221<details> 222 <summary><strong>返回值</strong></summary> 223 224 - HKS_SUCCESS:成功 225 226 - 其他:失败 227</details> 228 229- - - 230 231#### HuksHdiImportWrappedKey 232 233**接口描述** 234 235导入加密密钥。 236 237**接口原型** 238<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> 239 240<details> 241 <summary><strong>参数说明</strong></summary> 242 <pre> 243 <strong>const struct HksBlob *KeyAlias</strong> 244 将要导入的密钥的别名,要求: 245 1. keyAlias != null 246 2. keyAlias -> data != null 247 3. keyAlias -> size != 0 248 <br></br> 249 <strong>const struct HksBlob *key</strong> 250 要导入的密钥数据被加密时使用的密钥,要求: 251 1. wrappingUsedkey != null 252 2. wrappingUsedkey -> data != null 253 3. wrappingUsedkey -> size != 0 254 <br></br> 255 <strong>const struct HksBlob *wrappedKeyData</strong> 256 要导入的密钥的加密数据,要求: 257 1. wrappedKeyData != null 258 2. wrappedKeyData -> data != null 259 3. wrappedKeyData -> size != 0 260 <br></br> 261 <strong>const struct HksParamSet *paramSet</strong> 262 导入密钥的参数 263 <br></br> 264 <strong>struct HksBlob *keyOut</strong> 265 出参,将paramset和生成的密钥存放在这里 266 </pre> 267</details> 268<br></br> 269 270<details> 271 <summary><strong>约束与限制</strong></summary> 272 273 1. 请在接口内检查上述参数是否符合要求,如是否是空指针、密钥算法是否支持等。 274 275 2. keyOut请参照KeyBlob的结构。 276 277</details> 278<br></br> 279 280<details> 281 <summary><strong>返回值</strong></summary> 282 283 - HKS_SUCCESS:成功 284 285 - 其他:失败 286</details> 287 288- - - 289 290#### HuksHdiExportPublicKey 291 292**接口描述** 293 294导出公钥。 295 296**接口原型** 297<pre><code>int32_t HuksHdiExportPublicKey(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *keyOut);</code></pre> 298 299<details> 300 <summary><strong>参数说明</strong></summary> 301 <pre> 302 <strong>const struct HksBlob *key</strong> 303 与要导出的公钥对应的私钥,要求: 304 1. key != null 305 2. key -> data != null 306 3. key -> size != 0 307 <br></br> 308 <strong>const struct HksParamSet *paramSet</strong> 309 空参数 310 <br></br> 311 <strong>struct HksBlob *keyOut</strong> 312 出参,存放导出的公钥 313 </pre> 314</details> 315<br></br> 316 317<details> 318 <summary><strong>返回值</strong></summary> 319 320 - HKS_SUCCESS:成功 321 322 - 其他:失败 323</details> 324 325- - - 326 327#### HuksHdiInit 328 329**接口描述** 330 331三段式中的Init接口。 332 333**接口原型** 334<pre><code>int32_t HuksHdiInit(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle, struct HksBlob *token);</code></pre> 335 336<details> 337 <summary><strong>参数说明</strong></summary> 338 <pre> 339 <strong>const struct HksBlob *key</strong> 340 Init操作的密钥,要求: 341 1. key != null 342 2. key -> data != null 343 3. key -> size != 0 344 <br></br> 345 <strong>const struct HksParamSet *paramSet</strong> 346 Init操作的参数 347 <br></br> 348 <strong>struct HksBlob *handle</strong> 349 三段式的句柄 350 <br></br> 351 <strong>struct HksBlob *token</strong> 352 存放安全访问控制的challenge 353 </pre> 354</details> 355<br></br> 356 357<details> 358 <summary><strong>返回值</strong></summary> 359 360 - HKS_SUCCESS:成功 361 362 - 其他:失败 363</details> 364 365- - - 366 367#### HuksHdiUpdate 368 369**接口描述** 370 371三段式中的Update接口。 372 373**接口原型** 374<pre><code>int32_t HuksHdiUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre> 375 376<details> 377 <summary><strong>参数说明</strong></summary> 378 <pre> 379 <strong>const struct HksBlob *handle</strong> 380 三段式的句柄 381 <br></br> 382 <strong> const struct HksParamSet *paramSet</strong> 383 Update操作的参数 384 <br></br> 385 <strong> const struct HksBlob *inData</strong> 386 Update操作的输入 387 <br></br> 388 <strong> struct HksBlob *outData</strong> 389 Update操作的结果 390 </pre> 391</details> 392<br></br> 393 394<details> 395 <summary><strong>约束与限制</strong></summary> 396 397 1. 在进行签名验签时inData要传入原文数据。 398 399</details> 400<br></br> 401 402<details> 403 <summary><strong>返回值</strong></summary> 404 405 - HKS_SUCCESS:成功 406 407 - 其他:失败 408</details> 409 410- - - 411 412#### HuksHdiFinish 413 414**接口描述** 415 416三段式中的Finish接口。 417 418**接口原型** 419<pre><code>int32_t HuksHdiFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, struct HksBlob *outData);</code></pre> 420 421<details> 422 <summary><strong>参数说明</strong></summary> 423 <pre> 424 <strong>const struct HksBlob *handle</strong> 425 三段式的句柄 426 <br></br> 427 <strong>const struct HksParamSet *paramSet</strong> 428 Finish操作的参数 429 <br></br> 430 <strong>const struct HksBlob *inData</strong> 431 Finish操作的输入 432 <br></br> 433 <strong>struct HksBlob *outData</strong> 434 Finish操作的结果 435 </pre> 436</details> 437<br></br> 438 439<details> 440 <summary><strong>约束与限制</strong></summary> 441 442 1. 在进行签名验签时inData要传入需要验证的签名数据,通过返回结果表示验签是否成功。 443 444</details> 445<br></br> 446 447<details> 448 <summary><strong>返回值</strong></summary> 449 450 - HKS_SUCCESS:成功 451 452 - 其他:失败 453</details> 454 455- - - 456 457#### HuksHdiAbort 458 459**接口描述** 460 461终止三段式。当Init,Update和Finish操作中的任一阶段发生错误时,都要调用abort来终止密钥的使用。 462 463**接口原型** 464<pre><code>int32_t HuksHdiAbort(const struct HksBlob *handle, const struct HksParamSet *paramSet);</code></pre> 465 466<details> 467 <summary><strong>参数说明</strong></summary> 468 <pre> 469 <strong>const struct HksBlob *handle</strong> 470 三段式的句柄 471 <br></br> 472 <strong>const struct HksParamSet *paramSet</strong> 473 Abort操作的参数 474 </pre> 475</details> 476<br></br> 477 478<details> 479 <summary><strong>返回值</strong></summary> 480 481 - HKS_SUCCESS:成功 482 483 - 其他:失败 484</details> 485 486- - - 487 488#### HuksHdiGetKeyProperties 489 490**接口描述** 491 492获取密钥属性。 493 494**接口原型** 495<pre><code>int32_t HuksHdiGetKeyProperties(const struct HksParamSet *paramSet, const struct HksBlob *key);</code></pre> 496 497<details> 498 <summary><strong>参数说明</strong></summary> 499 <pre> 500 <strong>const struct HksParamSet *paramSet</strong> 501 空对象 502 <br></br> 503 <strong>const struct HksBlob *key</strong> 504 要获取属性的密钥 505 </pre> 506</details> 507<br></br> 508 509<details> 510 <summary><strong>返回值</strong></summary> 511 512 - HKS_SUCCESS:成功 513 514 - 其他:失败 515</details> 516 517- - - 518 519#### HuksHdiAttestKey 520 521**接口描述** 522 523获取密钥证书。 524 525**接口原型** 526<pre><code>int32_t (*HuksHdiAttestKey)(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *certChain);</code></pre> 527 528<details> 529 <summary><strong>参数说明</strong></summary> 530 <pre> 531 <strong>const struct HksBlob *key</strong> 532 要获取证书的密钥 533 <br></br> 534 <strong>const struct HksParamSet *paramSet</strong> 535 获取证书操作的参数 536 <br></br> 537 <strong>struct HksBlob *certChain</strong> 538 出参,存放证书 539 </pre> 540</details> 541<br></br> 542 543<details> 544 <summary><strong>约束与限制</strong></summary> 545 546 1. certChain的格式需遵循[约束与限制第二点](#约束与限制)。 547 548</details> 549<br></br> 550 551<details> 552 <summary><strong>返回值</strong></summary> 553 554 - HKS_SUCCESS:成功 555 556 - 其他:失败 557</details> 558 559- - - 560 561### 开发步骤 562 563HDI接口到HUKS Core的适配在以下目录中: 564 565```undefined 566// base/security/user_auth/services/huks_standard/huks_engine/main 567├── BUILD.gn # 编译脚本 568├── core_dependency # 实现依赖 569└── core # HUKS Core层的软实现 570 ├── BUILD.gn # 编译脚本 571 ├── include 572 └── src 573 ├── hks_core_interfaces.c # HDI到HUKS Core的适配层 574 └── hks_core_service.c # 具体实现 575 └── ... #其他功能代码 576``` 577 578关于HUKS Core接口的具体实现,开发者必须采用三段式。以下是三段式的开发步骤以及HUKS CORE的代码示例,开发者应参考以下代码实现所有的Hdi接口。 579 580其他HUKS Core接口的代码可以参考[hks_core_service.c](https://gitee.com/openharmony/security_huks/blob/master/services/huks_standard/huks_engine/main/core/src/hks_core_service.c)文件。 581 5821. 创建一个句柄,通过这个句柄在session中存储密钥操作相关的信息,使得外部可以通过这个句柄分多次进行同一密钥操作。 583 584 ```c 585 586 //三段式Init接口 587 588 int32_t HksCoreInit(const struct HksBlob *key, const struct HksParamSet *paramSet, struct HksBlob *handle, 589 struct HksBlob *token) 590 { 591 HKS_LOG_D("HksCoreInit in Core start"); 592 uint32_t pur = 0; 593 uint32_t alg = 0; 594 //检查参数 595 if (key == NULL || paramSet == NULL || handle == NULL || token == NULL) { 596 HKS_LOG_E("the pointer param entered is invalid"); 597 return HKS_FAILURE; 598 } 599 600 if (handle->size < sizeof(uint64_t)) { 601 HKS_LOG_E("handle size is too small, size : %u", handle->size); 602 return HKS_ERROR_INSUFFICIENT_MEMORY; 603 } 604 //解密密钥文件 605 struct HuksKeyNode *keyNode = HksCreateKeyNode(key, paramSet); 606 if (keyNode == NULL || handle == NULL) { 607 HKS_LOG_E("the pointer param entered is invalid"); 608 return HKS_ERROR_BAD_STATE; 609 } 610 //通过handle向session中存储信息,供Update/Finish使用。使得外部可以通过同个handle分多次进行同一密钥操作。 611 handle->size = sizeof(uint64_t); 612 (void)memcpy_s(handle->data, handle->size, &(keyNode->handle), handle->size); 613 //从参数中提取出算法 614 int32_t ret = GetPurposeAndAlgorithm(paramSet, &pur, &alg); 615 if (ret != HKS_SUCCESS) { 616 HksDeleteKeyNode(keyNode->handle); 617 return ret; 618 } 619 //检查密钥参数 620 ret = HksCoreSecureAccessInitParams(keyNode, paramSet, token); 621 if (ret != HKS_SUCCESS) { 622 HKS_LOG_E("init secure access params failed"); 623 HksDeleteKeyNode(keyNode->handle); 624 return ret; 625 } 626 //通过密钥使用目的获取对应的算法库处理函数 627 uint32_t i; 628 uint32_t size = HKS_ARRAY_SIZE(g_hksCoreInitHandler); 629 for (i = 0; i < size; i++) { 630 if (g_hksCoreInitHandler[i].pur == pur) { 631 HKS_LOG_E("Core HksCoreInit [pur] = %d, pur = %d", g_hksCoreInitHandler[i].pur, pur); 632 ret = g_hksCoreInitHandler[i].handler(keyNode, paramSet, alg); 633 break; 634 } 635 } 636 //异常结果检查 637 if (ret != HKS_SUCCESS) { 638 HksDeleteKeyNode(keyNode->handle); 639 HKS_LOG_E("CoreInit failed, ret : %d", ret); 640 return ret; 641 } 642 643 if (i == size) { 644 HksDeleteKeyNode(keyNode->handle); 645 HKS_LOG_E("don't found purpose, pur : %u", pur); 646 return HKS_FAILURE; 647 } 648 649 HKS_LOG_D("HksCoreInit in Core end"); 650 return ret; 651 } 652 ``` 653 6542. 在执行密钥操作前通过句柄获得上下文信息,执行密钥操作时放入分片数据并取回密钥操作结果或者追加数据。 655 656 ```c 657 //三段式Update接口 658 int32_t HksCoreUpdate(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, 659 struct HksBlob *outData) 660 { 661 HKS_LOG_D("HksCoreUpdate in Core start"); 662 uint32_t pur = 0; 663 uint32_t alg = 0; 664 //检查参数 665 if (handle == NULL || paramSet == NULL || inData == NULL) { 666 HKS_LOG_E("the pointer param entered is invalid"); 667 return HKS_FAILURE; 668 } 669 670 uint64_t sessionId; 671 struct HuksKeyNode *keyNode = NULL; 672 //根据handle获取本次三段式操作需要的上下文 673 int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg); 674 if (ret != HKS_SUCCESS) { 675 HKS_LOG_E("GetParamsForCoreUpdate failed"); 676 return ret; 677 } 678 //校验密钥参数 679 ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet); 680 if (ret != HKS_SUCCESS) { 681 HksDeleteKeyNode(sessionId); 682 HKS_LOG_E("HksCoreUpdate secure access verify failed"); 683 return ret; 684 } 685 //调用对应的算法库密钥处理函数 686 uint32_t i; 687 uint32_t size = HKS_ARRAY_SIZE(g_hksCoreUpdateHandler); 688 for (i = 0; i < size; i++) { 689 if (g_hksCoreUpdateHandler[i].pur == pur) { 690 struct HksBlob appendInData = { 0, NULL }; 691 ret = HksCoreAppendAuthInfoBeforeUpdate(keyNode, pur, paramSet, inData, &appendInData); 692 if (ret != HKS_SUCCESS) { 693 HKS_LOG_E("before update: append auth info failed"); 694 break; 695 } 696 ret = g_hksCoreUpdateHandler[i].handler(keyNode, paramSet, 697 appendInData.data == NULL ? inData : &appendInData, outData, alg); 698 if (appendInData.data != NULL) { 699 HKS_FREE_BLOB(appendInData); 700 } 701 break; 702 } 703 } 704 //异常结果检查 705 if (ret != HKS_SUCCESS) { 706 HksDeleteKeyNode(keyNode->handle); 707 HKS_LOG_E("CoreUpdate failed, ret : %d", ret); 708 return ret; 709 } 710 711 if (i == size) { 712 HksDeleteKeyNode(sessionId); 713 HKS_LOG_E("don't found purpose, pur : %u", pur); 714 return HKS_FAILURE; 715 } 716 return ret; 717 } 718 ``` 719 7203. 结束密钥操作并取回结果,销毁句柄。 721 722 ```c 723 //三段式Finish接口 724 int32_t HksCoreFinish(const struct HksBlob *handle, const struct HksParamSet *paramSet, const struct HksBlob *inData, 725 struct HksBlob *outData) 726 { 727 HKS_LOG_D("HksCoreFinish in Core start"); 728 uint32_t pur = 0; 729 uint32_t alg = 0; 730 //检查参数 731 if (handle == NULL || paramSet == NULL || inData == NULL) { 732 HKS_LOG_E("the pointer param entered is invalid"); 733 return HKS_FAILURE; 734 } 735 736 uint64_t sessionId; 737 struct HuksKeyNode *keyNode = NULL; 738 //根据handle获取本次三段式操作需要的上下文 739 int32_t ret = GetParamsForUpdateAndFinish(handle, &sessionId, &keyNode, &pur, &alg); 740 if (ret != HKS_SUCCESS) { 741 HKS_LOG_E("GetParamsForCoreUpdate failed"); 742 return ret; 743 } 744 //校验密钥参数 745 ret = HksCoreSecureAccessVerifyParams(keyNode, paramSet); 746 if (ret != HKS_SUCCESS) { 747 HksDeleteKeyNode(sessionId); 748 HKS_LOG_E("HksCoreFinish secure access verify failed"); 749 return ret; 750 } 751 //调用对应的算法库密钥处理函数 752 uint32_t i; 753 uint32_t size = HKS_ARRAY_SIZE(g_hksCoreFinishHandler); 754 for (i = 0; i < size; i++) { 755 if (g_hksCoreFinishHandler[i].pur == pur) { 756 uint32_t outDataBufferSize = (outData == NULL) ? 0 : outData->size; 757 struct HksBlob appendInData = { 0, NULL }; 758 ret = HksCoreAppendAuthInfoBeforeFinish(keyNode, pur, paramSet, inData, &appendInData); 759 if (ret != HKS_SUCCESS) { 760 HKS_LOG_E("before finish: append auth info failed"); 761 break; 762 } 763 ret = g_hksCoreFinishHandler[i].handler(keyNode, paramSet, 764 appendInData.data == NULL ? inData : &appendInData, outData, alg); 765 if (appendInData.data != NULL) { 766 HKS_FREE_BLOB(appendInData); 767 } 768 if (ret != HKS_SUCCESS) { 769 break; 770 } 771 //添加密钥操作结束标签 772 ret = HksCoreAppendAuthInfoAfterFinish(keyNode, pur, paramSet, outDataBufferSize, outData); 773 break; 774 } 775 } 776 if (i == size) { 777 HKS_LOG_E("don't found purpose, pur : %d", pur); 778 ret = HKS_FAILURE; 779 } 780 //删除对应的session 781 HksDeleteKeyNode(sessionId); 782 HKS_LOG_D("HksCoreFinish in Core end"); 783 return ret; 784 } 785 ``` 786 787### 调测验证 788 789开发完成后,通过[HUKS JS接口](https://gitee.com/openharmony/security_huks/blob/master/interfaces/kits/js/@ohos.security.huks.d.ts)开发JS应用来验证能力是否完备。 790 791对于每个HDI接口,[接口说明](#接口说明)都提供了对应的JS接口。可以通过调用JS接口组合来验证对应的HDI接口的能力,也可以通过完整的密钥操作来验证接口的能力。 792 793JS测试代码示例如下,如果整个流程能够正常运行,代表HDI接口能力正常。更多的密钥操作类型请见[huks-guidelines.md](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/security/huks-guidelines.md)。 794 795**AES生成密钥和加密** 796 7971. 引入HUKS模块 798 799 ```js 800 import huks from '@ohos.security.huks' 801 ``` 802 8032. 使用generateKey接口生成密钥。 804 805 ```js 806 var alias = 'testAlias'; 807 var properties = new Array(); 808 properties[0] = { 809 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 810 value: huks.HuksKeyAlg.HUKS_ALG_ECC 811 }; 812 properties[1] = { 813 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 814 value: huks.HuksKeySize.HUKS_ECC_KEY_SIZE_224 815 }; 816 properties[2] = { 817 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 818 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 819 }; 820 properties[3] = { 821 tag: huks.HuksTag.HUKS_TAG_DIGEST, 822 value: huks.HuksKeyDigest.HUKS_DIGEST_NONE 823 }; 824 var options = { 825 properties: properties 826 } 827 var resultA = huks.generateKey(alias, options); 828 ``` 829 8303. 使用Init接口进行init操作。 831 832 ```js 833 var alias = 'test001' 834 var properties = new Array(); 835 properties[0] = { 836 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 837 value: huks.HuksKeyAlg.HUKS_ALG_DH 838 }; 839 properties[1] = { 840 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 841 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 842 }; 843 properties[2] = { 844 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 845 value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096 846 }; 847 var options = { 848 properties: properties 849 }; 850 huks.init(alias, options, function(err, data) { 851 if (err.code !== 0) { 852 console.log("test init err information: " + JSON.stringify(err)); 853 } else { 854 console.log(`test init data: ${JSON.stringify(data)}`); 855 } 856 }) 857 ``` 858 8594. 使用Update接口进行update操作。 860 861 ```js 862 var properties = new Array(); 863 properties[0] = { 864 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 865 value: huks.HuksKeyAlg.HUKS_ALG_DH 866 }; 867 properties[1] = { 868 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 869 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 870 }; 871 properties[2] = { 872 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 873 value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096 874 }; 875 var options = { 876 properties: properties 877 }; 878 var result = huks.update(handle, options) 879 ``` 880 8815. 使用Finish接口进行finish操作。 882 883 ```js 884 var properties = new Array(); 885 properties[0] = { 886 tag: huks.HuksTag.HUKS_TAG_ALGORITHM, 887 value: huks.HuksKeyAlg.HUKS_ALG_DH 888 }; 889 properties[1] = { 890 tag: huks.HuksTag.HUKS_TAG_PURPOSE, 891 value: huks.HuksKeyPurpose.HUKS_KEY_PURPOSE_AGREE 892 }; 893 properties[2] = { 894 tag: huks.HuksTag.HUKS_TAG_KEY_SIZE, 895 value: huks.HuksKeySize.HUKS_DH_KEY_SIZE_4096 896 }; 897 var options = { 898 properties: properties 899 }; 900 var result = huks.finish(handle, options) 901 ```