1 /*
2 * Copyright (c) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #define HUKS_DISABLE_LOG_AT_FILE_TO_REDUCE_ROM_SIZE
16
17 #ifdef HKS_CONFIG_FILE
18 #include HKS_CONFIG_FILE
19 #else
20 #include "hks_config.h"
21 #endif
22
23 #include "hks_client_service_adapter.h"
24
25 #include <mbedtls/bignum.h>
26 #include <mbedtls/ecp.h>
27 #include <mbedtls/pk.h>
28 #include <mbedtls/rsa.h>
29 #include <securec.h>
30
31 #include "hks_log.h"
32 #include "hks_mbedtls_common.h"
33 #include "hks_mbedtls_ecc.h"
34 #include "hks_mem.h"
35 #include "hks_template.h"
36
37 #ifdef _CUT_AUTHENTICATE_
38 #undef HKS_SUPPORT_HASH_C
39 #undef HKS_SUPPORT_RSA_C
40 #undef HKS_SUPPORT_ECC_C
41 #undef HKS_SUPPORT_X25519_C
42 #undef HKS_SUPPORT_ED25519_C
43 #undef HKS_SUPPORT_KDF_PBKDF2
44 #endif /* _CUT_AUTHENTICATE_ */
45
46 #if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C)
PkCtxToX509(mbedtls_pk_context * ctx,struct HksBlob * x509Key)47 static int32_t PkCtxToX509(mbedtls_pk_context *ctx, struct HksBlob *x509Key)
48 {
49 uint8_t *tmpBuf = (uint8_t *)HksMalloc(MAX_KEY_SIZE);
50 HKS_IF_NULL_RETURN(tmpBuf, HKS_ERROR_MALLOC_FAIL)
51
52 int32_t ret = HKS_SUCCESS;
53 do {
54 int32_t x509Size = mbedtls_pk_write_pubkey_der(ctx, tmpBuf, MAX_KEY_SIZE);
55 if (x509Size < HKS_MBEDTLS_SUCCESS) {
56 HKS_LOG_E("public key to x509 write der failed! mbedtls ret = 0x%" LOG_PUBLIC "X", x509Size);
57 ret = x509Size;
58 break;
59 }
60
61 uint8_t *x509KeyData = (uint8_t *)HksMalloc(x509Size);
62 if (x509KeyData == NULL) {
63 HKS_LOG_E("Malloc x509 key data failed!");
64 ret = HKS_ERROR_MALLOC_FAIL;
65 break;
66 }
67
68 /* mbedtls_pk_write_pubkey_der use little-endian for storage */
69 if (memcpy_s(x509KeyData, x509Size, tmpBuf + MAX_KEY_SIZE - x509Size, x509Size) != EOK) {
70 HKS_LOG_E("public key to x509 memcpy to x509key failed!");
71 HKS_FREE(x509KeyData);
72 ret = HKS_ERROR_INSUFFICIENT_MEMORY;
73 break;
74 }
75
76 x509Key->size = x509Size;
77 x509Key->data = x509KeyData;
78 } while (0);
79
80 HKS_FREE(tmpBuf);
81 return ret;
82 }
83
84 #ifdef HKS_SUPPORT_RSA_C
InitRsaPkCtx(const struct HksBlob * mod,const struct HksBlob * e,mbedtls_pk_context * ctx)85 static int32_t InitRsaPkCtx(const struct HksBlob *mod, const struct HksBlob *e, mbedtls_pk_context *ctx)
86 {
87 int32_t ret = mbedtls_pk_setup(ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_RSA));
88 if (ret != HKS_MBEDTLS_SUCCESS) {
89 HKS_LOG_E("Mbedtls setup pk context failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
90 return ret;
91 }
92
93 mbedtls_mpi mpiN;
94 mbedtls_mpi mpiE;
95
96 mbedtls_mpi_init(&mpiN);
97 mbedtls_mpi_init(&mpiE);
98
99 do {
100 ret = mbedtls_mpi_read_binary(&mpiN, mod->data, mod->size);
101 if (ret != HKS_MBEDTLS_SUCCESS) {
102 HKS_LOG_E("Hks init rsa pk context read N failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
103 break;
104 }
105
106 ret = mbedtls_mpi_read_binary(&mpiE, e->data, e->size);
107 if (ret != HKS_MBEDTLS_SUCCESS) {
108 HKS_LOG_E("Hks init rsa pk context read E failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
109 break;
110 }
111
112 mbedtls_rsa_context *rsaCtx = mbedtls_pk_rsa(*ctx);
113 ret = mbedtls_rsa_import(rsaCtx, &mpiN, NULL, NULL, NULL, &mpiE);
114 if (ret != HKS_MBEDTLS_SUCCESS) {
115 HKS_LOG_E("Hks init rsa pk context import rsa context failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
116 break;
117 }
118
119 ret = mbedtls_rsa_complete(rsaCtx);
120 if (ret != HKS_MBEDTLS_SUCCESS) {
121 HKS_LOG_E("Hks init rsa pk context complete rsa context failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
122 }
123 } while (0);
124
125 mbedtls_mpi_free(&mpiN);
126 mbedtls_mpi_free(&mpiE);
127 return ret;
128 }
129
RsaToX509PublicKey(const struct HksBlob * mod,const struct HksBlob * e,struct HksBlob * x509Key)130 static int32_t RsaToX509PublicKey(const struct HksBlob *mod, const struct HksBlob *e, struct HksBlob *x509Key)
131 {
132 mbedtls_pk_context ctx;
133 mbedtls_pk_init(&ctx);
134
135 int32_t ret;
136 do {
137 ret = InitRsaPkCtx(mod, e, &ctx);
138 HKS_IF_NOT_SUCC_BREAK(ret)
139
140 ret = PkCtxToX509(&ctx, x509Key);
141 HKS_IF_NOT_SUCC_LOGE(ret, "Pk context to rsa x509 failed! ret = 0x%" LOG_PUBLIC "X", ret)
142 } while (0);
143
144 mbedtls_pk_free(&ctx);
145 return ret;
146 }
147 #endif
148
149 #ifdef HKS_SUPPORT_ECC_C
InitEccPkCtx(uint32_t keySize,const struct HksBlob * x,const struct HksBlob * y,mbedtls_pk_context * ctx)150 static int32_t InitEccPkCtx(uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y,
151 mbedtls_pk_context *ctx)
152 {
153 int32_t ret = mbedtls_pk_setup(ctx, mbedtls_pk_info_from_type(MBEDTLS_PK_ECKEY));
154 if (ret != HKS_MBEDTLS_SUCCESS) {
155 HKS_LOG_E("Mbedtls setup pk context failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
156 return ret;
157 }
158
159 mbedtls_ecp_group_id grp_id;
160 ret = GetEccGroupId(keySize, &grp_id);
161 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Get ecc group id failed! ret = 0x%" LOG_PUBLIC "X", ret)
162
163 mbedtls_ecp_keypair *pubKey = mbedtls_pk_ec(*ctx);
164 ret = mbedtls_ecp_group_load(&(pubKey->MBEDTLS_PRIVATE(grp)), grp_id);
165 if (ret != HKS_MBEDTLS_SUCCESS) {
166 HKS_LOG_E("Hks init ecc pk context load group failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
167 return ret;
168 }
169
170 ret = mbedtls_mpi_read_binary(&(pubKey->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)), x->data, x->size);
171 if (ret != HKS_MBEDTLS_SUCCESS) {
172 HKS_LOG_E("Hks init ecc pk context read X failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
173 return ret;
174 }
175
176 ret = mbedtls_mpi_read_binary(&(pubKey->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)), y->data, y->size);
177 if (ret != HKS_MBEDTLS_SUCCESS) {
178 HKS_LOG_E("Hks init ecc pk context read Y failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
179 return ret;
180 }
181
182 /* Z = 1, X and Y are its standard (affine) coordinates */
183 ret = mbedtls_mpi_lset(&(pubKey->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z)), 1);
184 if (ret != HKS_MBEDTLS_SUCCESS) {
185 HKS_LOG_E("Hks init ecc pk context set Z failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
186 return ret;
187 }
188
189 return HKS_SUCCESS;
190 }
191
EccToX509PublicKey(uint32_t keySize,const struct HksBlob * x,const struct HksBlob * y,struct HksBlob * x509Key)192 static int32_t EccToX509PublicKey(uint32_t keySize, const struct HksBlob *x, const struct HksBlob *y,
193 struct HksBlob *x509Key)
194 {
195 mbedtls_pk_context ctx;
196 mbedtls_pk_init(&ctx);
197
198 int32_t ret;
199 do {
200 ret = InitEccPkCtx(keySize, x, y, &ctx);
201 HKS_IF_NOT_SUCC_BREAK(ret)
202
203 ret = PkCtxToX509(&ctx, x509Key);
204 HKS_IF_NOT_SUCC_LOGE(ret, "Pk context to ecc x509 failed! ret = 0x%" LOG_PUBLIC "X", ret)
205 } while (0);
206
207 mbedtls_pk_free(&ctx);
208 return ret;
209 }
210 #endif
211 #endif
212
213 #if defined(HKS_SUPPORT_X25519_C) || defined(HKS_SUPPORT_ED25519_C)
Curve25519ToX509PublicKey(const struct HksBlob * publicKey,struct HksBlob * x509Key)214 static int32_t Curve25519ToX509PublicKey(const struct HksBlob *publicKey, struct HksBlob *x509Key)
215 {
216 if (publicKey->size != HKS_KEY_BYTES(HKS_CURVE25519_KEY_SIZE_256)) {
217 HKS_LOG_E("Invalid public key size! key size = 0x%" LOG_PUBLIC "X", publicKey->size);
218 return HKS_ERROR_INVALID_ARGUMENT;
219 }
220
221 x509Key->data = (uint8_t *)HksMalloc(publicKey->size);
222 HKS_IF_NULL_LOGE_RETURN(x509Key->data, HKS_ERROR_MALLOC_FAIL,
223 "X25519/Ed25519 to x509 public key malloc x509 key data failed!")
224
225 if (memcpy_s(x509Key->data, publicKey->size, publicKey->data, publicKey->size) != EOK) {
226 HKS_LOG_E("X25519/Ed25519 to x509 public key memcpy to x509 key data failed!");
227 HKS_FREE(x509Key->data);
228 return HKS_ERROR_INSUFFICIENT_MEMORY;
229 }
230 x509Key->size = publicKey->size;
231
232 return HKS_SUCCESS;
233 }
234 #endif
235
TranslateToX509PublicKey(const struct HksBlob * publicKey,struct HksBlob * x509Key)236 int32_t TranslateToX509PublicKey(const struct HksBlob *publicKey, struct HksBlob *x509Key)
237 {
238 #if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C) || defined(HKS_SUPPORT_X25519_C) || \
239 defined(HKS_SUPPORT_ED25519_C)
240 if ((publicKey == NULL) || (publicKey->data == NULL) || (publicKey->size == 0) || (x509Key == NULL)) {
241 HKS_LOG_E("translate to x509 public key invalid args");
242 return HKS_ERROR_INVALID_ARGUMENT;
243 }
244
245 if (publicKey->size < sizeof(struct HksPubKeyInfo)) {
246 HKS_LOG_E("translate to x509 public key invalid publicKey size");
247 return HKS_ERROR_INVALID_ARGUMENT;
248 }
249
250 struct HksPubKeyInfo *publicKeyInfo = (struct HksPubKeyInfo *)publicKey->data;
251 uint32_t offset = sizeof(struct HksPubKeyInfo);
252 if ((publicKey->size - offset) < publicKeyInfo->nOrXSize) {
253 HKS_LOG_E("translate to x509 public key invalid nOrXSize size");
254 return HKS_ERROR_INVALID_ARGUMENT;
255 }
256
257 struct HksBlob material1 = { publicKeyInfo->nOrXSize, publicKey->data + offset };
258 offset += publicKeyInfo->nOrXSize;
259 if ((publicKey->size - offset) < publicKeyInfo->eOrYSize) {
260 HKS_LOG_E("translate to x509 public key invalid eOrYSize size");
261 return HKS_ERROR_INVALID_ARGUMENT;
262 }
263
264 #if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C)
265 struct HksBlob material2 = { publicKeyInfo->eOrYSize, publicKey->data + offset };
266 #endif
267 switch (publicKeyInfo->keyAlg) {
268 #ifdef HKS_SUPPORT_RSA_C
269 case HKS_ALG_RSA:
270 return RsaToX509PublicKey(&material1, &material2, x509Key);
271 #endif
272 #ifdef HKS_SUPPORT_ECC_C
273 case HKS_ALG_ECC:
274 return EccToX509PublicKey(publicKeyInfo->keySize, &material1, &material2, x509Key);
275 #endif
276 #if defined(HKS_SUPPORT_X25519_C) || defined(HKS_SUPPORT_ED25519_C)
277 case HKS_ALG_X25519:
278 case HKS_ALG_ED25519:
279 return Curve25519ToX509PublicKey(&material1, x509Key);
280 #endif
281 default:
282 HKS_LOG_E("Unsupport alg type! type = 0x%" LOG_PUBLIC "X", publicKeyInfo->keyAlg);
283 return HKS_ERROR_INVALID_ARGUMENT;
284 }
285 #else
286 (void)publicKey;
287 (void)x509Key;
288 return HKS_ERROR_NOT_SUPPORTED;
289 #endif
290 }
291
292 #if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C)
293 #ifdef HKS_SUPPORT_RSA_C
CheckRsaCtx(const mbedtls_rsa_context * rsaCtx)294 static int32_t CheckRsaCtx(const mbedtls_rsa_context *rsaCtx)
295 {
296 uint32_t maxKeyByteLen = HKS_RSA_KEY_SIZE_4096 / HKS_BITS_PER_BYTE;
297 if (rsaCtx->MBEDTLS_PRIVATE(len) > maxKeyByteLen) {
298 HKS_LOG_E("Invalid mbedtls rsa context's len! len = 0x%" LOG_PUBLIC "zu", rsaCtx->MBEDTLS_PRIVATE(len));
299 return HKS_ERROR_INVALID_ARGUMENT;
300 }
301
302 return HKS_SUCCESS;
303 }
304
X509PublicKeyToRsa(mbedtls_rsa_context * rsaCtx,struct HksBlob * rsaPublicKey)305 static int32_t X509PublicKeyToRsa(mbedtls_rsa_context *rsaCtx, struct HksBlob *rsaPublicKey)
306 {
307 int32_t ret = CheckRsaCtx(rsaCtx);
308 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Check rsa ctx failed! ret = 0x%" LOG_PUBLIC "X", ret)
309
310 uint32_t nSize = rsaCtx->MBEDTLS_PRIVATE(len);
311 uint32_t eSize = rsaCtx->MBEDTLS_PRIVATE(len);
312
313 uint32_t totalSize = sizeof(struct HksPubKeyInfo) + nSize + eSize;
314 uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
315 HKS_IF_NULL_LOGE_RETURN(keyBuffer, HKS_ERROR_MALLOC_FAIL,
316 "X509 public key to rsa malloc keyBuffer failed!")
317
318 struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
319 pubKeyInfo->keyAlg = HKS_ALG_RSA;
320 pubKeyInfo->keySize = rsaCtx->MBEDTLS_PRIVATE(len) * HKS_BITS_PER_BYTE;
321 pubKeyInfo->nOrXSize = nSize;
322 pubKeyInfo->eOrYSize = eSize;
323 pubKeyInfo->placeHolder = 0;
324
325 ret = mbedtls_mpi_write_binary(&rsaCtx->MBEDTLS_PRIVATE(N), keyBuffer + sizeof(struct HksPubKeyInfo), nSize);
326 if (ret != HKS_MBEDTLS_SUCCESS) {
327 HKS_LOG_E("X509 public key to rsa write N failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
328 HKS_FREE(keyBuffer);
329 return ret;
330 }
331
332 ret = mbedtls_mpi_write_binary(&rsaCtx->MBEDTLS_PRIVATE(E),
333 keyBuffer + sizeof(struct HksPubKeyInfo) + nSize, eSize);
334 if (ret != HKS_MBEDTLS_SUCCESS) {
335 HKS_LOG_E("X509 public key to rsa write E failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
336 HKS_FREE(keyBuffer);
337 return ret;
338 }
339
340 rsaPublicKey->data = keyBuffer;
341 rsaPublicKey->size = totalSize;
342
343 return HKS_SUCCESS;
344 }
345 #endif
346
347 #ifdef HKS_SUPPORT_ECC_C
CheckEccXySize(const uint32_t xSize,const uint32_t ySize)348 static int32_t CheckEccXySize(const uint32_t xSize, const uint32_t ySize)
349 {
350 uint32_t maxKeyByteLen = HKS_ECC_KEY_SIZE_521 / HKS_BITS_PER_BYTE;
351 if ((xSize > maxKeyByteLen) || (ySize > maxKeyByteLen)) {
352 HKS_LOG_E("Invalid ecc public key size! xSize = 0x%" LOG_PUBLIC "X, ySize = 0x%" LOG_PUBLIC "X", xSize, ySize);
353 return HKS_ERROR_INVALID_ARGUMENT;
354 }
355
356 return HKS_SUCCESS;
357 }
358
X509PublicKeyToEcc(mbedtls_ecp_keypair * pubKey,struct HksBlob * eccPublicKey)359 static int32_t X509PublicKeyToEcc(mbedtls_ecp_keypair *pubKey, struct HksBlob *eccPublicKey)
360 {
361 /* When converting from X509 to internal format, the first byte needs to be filled with 0 */
362 uint32_t xSize = mbedtls_mpi_size(&(pubKey->MBEDTLS_PRIVATE(grp).P));
363 uint32_t ySize = mbedtls_mpi_size(&(pubKey->MBEDTLS_PRIVATE(grp).P));
364
365 int32_t ret = CheckEccXySize(xSize, ySize);
366 HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "Check ecc public key size failed! ret = 0x%" LOG_PUBLIC "X", ret)
367
368 uint32_t totalSize = sizeof(struct HksPubKeyInfo) + xSize + ySize;
369 uint8_t *keyBuffer = (uint8_t *)HksMalloc(totalSize);
370 HKS_IF_NULL_LOGE_RETURN(keyBuffer, HKS_ERROR_MALLOC_FAIL,
371 "X509 public key to ecc malloc keyBuffer failed!")
372
373 if (mbedtls_mpi_size(&(pubKey->MBEDTLS_PRIVATE(grp).P)) > UINT32_MAX / HKS_BITS_PER_BYTE) {
374 HKS_FREE(keyBuffer);
375 HKS_LOG_E("invalid param, the size is :%" LOG_PUBLIC "zu", mbedtls_mpi_size(&(pubKey->MBEDTLS_PRIVATE(grp).P)));
376 return HKS_ERROR_INVALID_ARGUMENT;
377 }
378
379 struct HksPubKeyInfo *pubKeyInfo = (struct HksPubKeyInfo *)keyBuffer;
380 pubKeyInfo->keyAlg = HKS_ALG_ECC;
381 pubKeyInfo->keySize = mbedtls_mpi_size(&(pubKey->MBEDTLS_PRIVATE(grp).P)) * HKS_BITS_PER_BYTE;
382 pubKeyInfo->nOrXSize = xSize;
383 pubKeyInfo->eOrYSize = ySize;
384 pubKeyInfo->placeHolder = 0;
385
386 ret = mbedtls_mpi_write_binary(&(pubKey->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X)),
387 keyBuffer + sizeof(struct HksPubKeyInfo), xSize);
388 if (ret != HKS_MBEDTLS_SUCCESS) {
389 HKS_LOG_E("X509 public key to ecc write X failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
390 HKS_FREE(keyBuffer);
391 return ret;
392 }
393
394 ret = mbedtls_mpi_write_binary(&(pubKey->MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y)),
395 keyBuffer + sizeof(struct HksPubKeyInfo) + xSize, ySize);
396 if (ret != HKS_MBEDTLS_SUCCESS) {
397 HKS_LOG_E("X509 public key to ecc write Y failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
398 HKS_FREE(keyBuffer);
399 return ret;
400 }
401
402 eccPublicKey->data = keyBuffer;
403 eccPublicKey->size = totalSize;
404
405 return HKS_SUCCESS;
406 }
407 #endif
408 #endif
409
TranslateFromX509PublicKey(const uint32_t alg,const struct HksBlob * x509Key,struct HksBlob * publicKey)410 int32_t TranslateFromX509PublicKey(const uint32_t alg, const struct HksBlob *x509Key, struct HksBlob *publicKey)
411 {
412 (void)alg;
413 #if defined(HKS_SUPPORT_RSA_C) || defined(HKS_SUPPORT_ECC_C)
414 mbedtls_pk_context ctx;
415 mbedtls_pk_init(&ctx);
416
417 int32_t ret = mbedtls_pk_parse_public_key(&ctx, x509Key->data, x509Key->size);
418 if (ret != HKS_MBEDTLS_SUCCESS) {
419 mbedtls_pk_free(&ctx);
420 return HKS_ERROR_INVALID_ARGUMENT;
421 }
422
423 /* 1: if the context can do operations on the given type. */
424 if (mbedtls_pk_can_do(&ctx, MBEDTLS_PK_RSA) == 1) {
425 #ifdef HKS_SUPPORT_RSA_C
426 ret = X509PublicKeyToRsa(mbedtls_pk_rsa(ctx), publicKey);
427 #else
428 ret = HKS_ERROR_INVALID_ALGORITHM;
429 #endif
430 } else if (mbedtls_pk_can_do(&ctx, MBEDTLS_PK_ECKEY) == 1) {
431 #ifdef HKS_SUPPORT_ECC_C
432 ret = X509PublicKeyToEcc(mbedtls_pk_ec(ctx), publicKey);
433 #else
434 ret = HKS_ERROR_INVALID_ALGORITHM;
435 #endif
436 } else {
437 HKS_LOG_E("Unsupport alg type!");
438 ret = HKS_ERROR_INVALID_ARGUMENT;
439 }
440
441 mbedtls_pk_free(&ctx);
442 return ret;
443 #else
444 (void)publicKey;
445 (void)x509Key;
446 return HKS_ERROR_NOT_SUPPORTED;
447 #endif
448 }
449
450