1 /*
2 * This file is part of the openHiTLS project.
3 *
4 * openHiTLS is licensed under the Mulan PSL v2.
5 * You can use this software according to the terms and conditions of the Mulan PSL v2.
6 * You may obtain a copy of Mulan PSL v2 at:
7 *
8 * http://license.coscl.org.cn/MulanPSL2
9 *
10 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13 * See the Mulan PSL v2 for more details.
14 */
15
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_KEY_DECODE
18
19 #include "crypt_ecc.h"
20 #ifdef HITLS_CRYPTO_ECDSA
21 #include "crypt_ecdsa.h"
22 #endif
23 #ifdef HITLS_CRYPTO_SM2
24 #include "crypt_sm2.h"
25 #endif
26 #ifdef HITLS_CRYPTO_ED25519
27 #include "crypt_curve25519.h"
28 #endif
29 #include "crypt_params_key.h"
30 #include "bsl_asn1.h"
31 #include "bsl_params.h"
32 #include "bsl_obj_internal.h"
33 #include "bsl_err_internal.h"
34 #include "crypt_errno.h"
35 #include "crypt_encode_decode_local.h"
36 #include "crypt_encode_decode_key.h"
37
38 #if defined(HITLS_CRYPTO_ECDSA) || defined(HITLS_CRYPTO_SM2)
39 typedef struct {
40 int32_t version;
41 BSL_ASN1_Buffer param;
42 BSL_ASN1_Buffer prikey;
43 BSL_ASN1_Buffer pubkey;
44 } CRYPT_DECODE_EccPrikeyInfo;
45
GetParaId(uint8_t * octs,uint32_t octsLen)46 static int32_t GetParaId(uint8_t *octs, uint32_t octsLen)
47 {
48 BslOidString oidStr = {octsLen, (char *)octs, 0};
49 BslCid cid = BSL_OBJ_GetCID(&oidStr);
50 if (cid == BSL_CID_UNKNOWN) {
51 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
52 return CRYPT_PKEY_PARAID_MAX;
53 }
54 return (int32_t)cid;
55 }
56
ParsePrikeyAsn1Info(uint8_t * buff,uint32_t buffLen,BSL_ASN1_Buffer * pk8AlgoParam,CRYPT_DECODE_EccPrikeyInfo * eccPrvInfo)57 static int32_t ParsePrikeyAsn1Info(uint8_t *buff, uint32_t buffLen, BSL_ASN1_Buffer *pk8AlgoParam,
58 CRYPT_DECODE_EccPrikeyInfo *eccPrvInfo)
59 {
60 BSL_ASN1_Buffer asn1[CRYPT_ECPRIKEY_PUBKEY_IDX + 1] = {0};
61 int32_t ret = CRYPT_DECODE_PrikeyAsn1Buff(buff, buffLen, asn1, CRYPT_ECPRIKEY_PUBKEY_IDX + 1);
62 if (ret != CRYPT_SUCCESS) {
63 BSL_ERR_PUSH_ERROR(ret);
64 return ret;
65 }
66 int32_t version;
67 BSL_ASN1_Buffer *prikey = &asn1[CRYPT_ECPRIKEY_PRIKEY_IDX]; // the ECC OID
68 BSL_ASN1_Buffer *ecParamOid = &asn1[CRYPT_ECPRIKEY_PARAM_IDX]; // the parameters OID
69 BSL_ASN1_Buffer *pubkey = &asn1[CRYPT_ECPRIKEY_PUBKEY_IDX]; // the ECC OID
70 BSL_ASN1_Buffer *param = pk8AlgoParam;
71 if (ecParamOid->len != 0) {
72 // has a valid Algorithm param
73 param = ecParamOid;
74 } else {
75 if (param == NULL) {
76 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
77 return CRYPT_NULL_INPUT;
78 }
79 if (param->len == 0) {
80 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_PKCS8_INVALID_ALGO_PARAM);
81 return CRYPT_DECODE_PKCS8_INVALID_ALGO_PARAM;
82 }
83 }
84 if (pubkey->len == 0) {
85 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ASN1_BUFF_FAILED);
86 return CRYPT_DECODE_ASN1_BUFF_FAILED;
87 }
88
89 ret = BSL_ASN1_DecodePrimitiveItem(&asn1[CRYPT_ECPRIKEY_VERSION_IDX], &version);
90 if (ret != CRYPT_SUCCESS) {
91 BSL_ERR_PUSH_ERROR(ret);
92 return ret;
93 }
94 eccPrvInfo->version = version;
95 eccPrvInfo->param = *param;
96 eccPrvInfo->prikey = *prikey;
97 eccPrvInfo->pubkey = *pubkey;
98 return CRYPT_SUCCESS;
99 }
100
101 #endif // HITLS_CRYPTO_ECDSA || HITLS_CRYPTO_SM2
102
103 #ifdef HITLS_CRYPTO_ECDSA
104 // ecdh is not considered, and it will be improved in the future
EccKeyNew(BSL_ASN1_Buffer * ecParamOid,void ** ecKey)105 static int32_t EccKeyNew(BSL_ASN1_Buffer *ecParamOid, void **ecKey)
106 {
107 int32_t paraId = GetParaId(ecParamOid->buff, ecParamOid->len);
108 if (!IsEcdsaEcParaId(paraId)) {
109 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
110 }
111 CRYPT_ECDSA_Ctx *key = CRYPT_ECDSA_NewCtx();
112 if (key == NULL) {
113 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
114 return CRYPT_MEM_ALLOC_FAIL;
115 }
116
117 int32_t ret = ECC_SetPara(key, ECC_NewPara(paraId));
118 if (ret != CRYPT_SUCCESS) {
119 ECC_FreeCtx(key);
120 BSL_ERR_PUSH_ERROR(ret);
121 return ret;
122 }
123 *ecKey = (void *)key;
124 return CRYPT_SUCCESS;
125 }
126
CRYPT_ECC_ParseSubPubkeyAsn1Buff(uint8_t * buff,uint32_t buffLen,void ** pubKey,bool isComplete)127 int32_t CRYPT_ECC_ParseSubPubkeyAsn1Buff(uint8_t *buff, uint32_t buffLen, void **pubKey, bool isComplete)
128 {
129 if (buff == NULL || buffLen == 0 || pubKey == NULL) {
130 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
131 return CRYPT_NULL_INPUT;
132 }
133 CRYPT_DECODE_SubPubkeyInfo subPubkeyInfo = {0};
134 void *pctx = NULL;
135 int32_t ret = CRYPT_DECODE_SubPubkey(buff, buffLen, NULL, &subPubkeyInfo, isComplete);
136 if (ret != CRYPT_SUCCESS) {
137 BSL_ERR_PUSH_ERROR(ret);
138 return ret;
139 }
140 if (subPubkeyInfo.keyType != BSL_CID_EC_PUBLICKEY) {
141 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
142 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
143 }
144 ret = EccKeyNew(&subPubkeyInfo.keyParam, &pctx);
145 if (ret != CRYPT_SUCCESS) {
146 BSL_ERR_PUSH_ERROR(ret);
147 return ret;
148 }
149 BSL_Param pubParam[2] = {
150 {CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, subPubkeyInfo.pubKey.buff,
151 subPubkeyInfo.pubKey.len, 0},
152 BSL_PARAM_END
153 };
154 ret = ECC_PkeySetPubKey(pctx, pubParam);
155 if (ret != CRYPT_SUCCESS) {
156 BSL_ERR_PUSH_ERROR(ret);
157 ECC_FreeCtx(pctx);
158 return ret;
159 }
160 *pubKey = (void *)pctx;
161 return ret;
162 }
163
CRYPT_ECC_ParsePrikeyAsn1Buff(uint8_t * buffer,uint32_t bufferLen,BSL_ASN1_Buffer * pk8AlgoParam,void ** ecPriKey)164 int32_t CRYPT_ECC_ParsePrikeyAsn1Buff(uint8_t *buffer, uint32_t bufferLen, BSL_ASN1_Buffer *pk8AlgoParam,
165 void **ecPriKey)
166 {
167 if (buffer == NULL || bufferLen == 0 || ecPriKey == NULL) {
168 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
169 return CRYPT_NULL_INPUT;
170 }
171
172 CRYPT_DECODE_EccPrikeyInfo eccPrvInfo = {0};
173 int32_t ret = ParsePrikeyAsn1Info(buffer, bufferLen, pk8AlgoParam, &eccPrvInfo);
174 if (ret != CRYPT_SUCCESS) {
175 BSL_ERR_PUSH_ERROR(ret);
176 return ret;
177 }
178 void *pctx = NULL;
179 ret = EccKeyNew(&eccPrvInfo.param, &pctx);
180 if (ret != CRYPT_SUCCESS) {
181 BSL_ERR_PUSH_ERROR(ret);
182 return ret;
183 }
184 BSL_Param pubParam[2] = {
185 {CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, (eccPrvInfo.pubkey.buff + 1),
186 eccPrvInfo.pubkey.len - 1, 0},
187 BSL_PARAM_END
188 };
189 ret = ECC_PkeySetPubKey(pctx, pubParam);
190 if (ret != CRYPT_SUCCESS) {
191 BSL_ERR_PUSH_ERROR(ret);
192 goto ERR;
193 }
194 BSL_Param prvParam[2] = {
195 {CRYPT_PARAM_EC_PRVKEY, BSL_PARAM_TYPE_OCTETS, eccPrvInfo.prikey.buff, eccPrvInfo.prikey.len, 0},
196 BSL_PARAM_END
197 };
198 ret = ECC_PkeySetPrvKey(pctx, prvParam);
199 if (ret != CRYPT_SUCCESS) {
200 BSL_ERR_PUSH_ERROR(ret);
201 goto ERR;
202 }
203 *ecPriKey = pctx;
204 return ret;
205 ERR:
206 ECC_FreeCtx(pctx);
207 return ret;
208 }
209
CRYPT_ECC_ParsePkcs8Key(uint8_t * buff,uint32_t buffLen,void ** ecdsaPriKey)210 int32_t CRYPT_ECC_ParsePkcs8Key(uint8_t *buff, uint32_t buffLen, void **ecdsaPriKey)
211 {
212 CRYPT_ENCODE_DECODE_Pk8PrikeyInfo pk8PrikeyInfo = {0};
213 int32_t ret = CRYPT_DECODE_Pkcs8Info(buff, buffLen, NULL, &pk8PrikeyInfo);
214 if (ret != CRYPT_SUCCESS) {
215 BSL_ERR_PUSH_ERROR(ret);
216 return ret;
217 }
218 if (pk8PrikeyInfo.keyType != BSL_CID_EC_PUBLICKEY) {
219 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
220 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
221 }
222 ret = CRYPT_ECC_ParsePrikeyAsn1Buff(pk8PrikeyInfo.pkeyRawKey, pk8PrikeyInfo.pkeyRawKeyLen, &pk8PrikeyInfo.keyParam,
223 ecdsaPriKey);
224 if (ret != CRYPT_SUCCESS) {
225 BSL_ERR_PUSH_ERROR(ret);
226 }
227 return ret;
228 }
229 #endif // HITLS_CRYPTO_ECDSA
230 #ifdef HITLS_CRYPTO_SM2
Sm2KeyNew(BSL_ASN1_Buffer * ecParamOid,CRYPT_SM2_Ctx ** ecKey)231 static int32_t Sm2KeyNew(BSL_ASN1_Buffer *ecParamOid, CRYPT_SM2_Ctx **ecKey)
232 {
233 CRYPT_SM2_Ctx *key = NULL;
234 int32_t paraId = GetParaId(ecParamOid->buff, ecParamOid->len);
235 if (paraId != CRYPT_ECC_SM2) {
236 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
237 }
238 key = CRYPT_SM2_NewCtx();
239 if (key == NULL) {
240 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
241 return CRYPT_MEM_ALLOC_FAIL;
242 }
243 *ecKey = key;
244 return CRYPT_SUCCESS;
245 }
246
CRYPT_SM2_ParseSubPubkeyAsn1Buff(uint8_t * buff,uint32_t buffLen,CRYPT_SM2_Ctx ** pubKey,bool isComplete)247 int32_t CRYPT_SM2_ParseSubPubkeyAsn1Buff(uint8_t *buff, uint32_t buffLen, CRYPT_SM2_Ctx **pubKey, bool isComplete)
248 {
249 if (buff == NULL || buffLen == 0 || pubKey == NULL) {
250 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
251 return CRYPT_NULL_INPUT;
252 }
253 CRYPT_DECODE_SubPubkeyInfo subPubkeyInfo = {0};
254 CRYPT_SM2_Ctx *pctx = NULL;
255 int32_t ret = CRYPT_DECODE_SubPubkey(buff, buffLen, NULL, &subPubkeyInfo, isComplete);
256 if (ret != CRYPT_SUCCESS) {
257 BSL_ERR_PUSH_ERROR(ret);
258 return ret;
259 }
260 if (subPubkeyInfo.keyType != BSL_CID_EC_PUBLICKEY && subPubkeyInfo.keyType != BSL_CID_SM2PRIME256) {
261 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
262 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
263 }
264 ret = Sm2KeyNew(&subPubkeyInfo.keyParam, &pctx);
265 if (ret != CRYPT_SUCCESS) {
266 BSL_ERR_PUSH_ERROR(ret);
267 return ret;
268 }
269 BSL_Param pubParam[2] = {
270 {CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, subPubkeyInfo.pubKey.buff,
271 subPubkeyInfo.pubKey.len, 0},
272 BSL_PARAM_END
273 };
274 ret = CRYPT_SM2_SetPubKey(pctx, pubParam);
275 if (ret != CRYPT_SUCCESS) {
276 BSL_ERR_PUSH_ERROR(ret);
277 CRYPT_SM2_FreeCtx(pctx);
278 return ret;
279 }
280 *pubKey = pctx;
281 return ret;
282 }
283
CRYPT_SM2_ParsePrikeyAsn1Buff(uint8_t * buffer,uint32_t bufferLen,BSL_ASN1_Buffer * pk8AlgoParam,CRYPT_SM2_Ctx ** sm2PriKey)284 int32_t CRYPT_SM2_ParsePrikeyAsn1Buff(uint8_t *buffer, uint32_t bufferLen, BSL_ASN1_Buffer *pk8AlgoParam,
285 CRYPT_SM2_Ctx **sm2PriKey)
286 {
287 CRYPT_DECODE_EccPrikeyInfo eccPrvInfo = {0};
288 int32_t ret = ParsePrikeyAsn1Info(buffer, bufferLen, pk8AlgoParam, &eccPrvInfo);
289 if (ret != CRYPT_SUCCESS) {
290 BSL_ERR_PUSH_ERROR(ret);
291 return ret;
292 }
293 CRYPT_SM2_Ctx *pctx = NULL;
294 ret = Sm2KeyNew(&eccPrvInfo.param, &pctx);
295 if (ret != CRYPT_SUCCESS) {
296 BSL_ERR_PUSH_ERROR(ret);
297 return ret;
298 }
299 BSL_Param pubParam[2] = {
300 {CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, eccPrvInfo.pubkey.buff + 1,
301 eccPrvInfo.pubkey.len - 1, 0},
302 BSL_PARAM_END
303 };
304 ret = CRYPT_SM2_SetPubKey(pctx, pubParam);
305 if (ret != CRYPT_SUCCESS) {
306 BSL_ERR_PUSH_ERROR(ret);
307 goto ERR;
308 }
309 BSL_Param prvParam[2] = {
310 {CRYPT_PARAM_EC_PRVKEY, BSL_PARAM_TYPE_OCTETS, eccPrvInfo.prikey.buff, eccPrvInfo.prikey.len, 0},
311 BSL_PARAM_END
312 };
313 ret = CRYPT_SM2_SetPrvKey(pctx, prvParam);
314 if (ret != CRYPT_SUCCESS) {
315 BSL_ERR_PUSH_ERROR(ret);
316 goto ERR;
317 }
318 *sm2PriKey = pctx;
319 return ret;
320 ERR:
321 CRYPT_SM2_FreeCtx(pctx);
322 return ret;
323 }
324
CRYPT_SM2_ParsePkcs8Key(uint8_t * buff,uint32_t buffLen,CRYPT_SM2_Ctx ** sm2PriKey)325 int32_t CRYPT_SM2_ParsePkcs8Key(uint8_t *buff, uint32_t buffLen, CRYPT_SM2_Ctx **sm2PriKey)
326 {
327 CRYPT_ENCODE_DECODE_Pk8PrikeyInfo pk8PrikeyInfo = {0};
328 int32_t ret = CRYPT_DECODE_Pkcs8Info(buff, buffLen, NULL, &pk8PrikeyInfo);
329 if (ret != CRYPT_SUCCESS) {
330 BSL_ERR_PUSH_ERROR(ret);
331 return ret;
332 }
333 if (pk8PrikeyInfo.keyType != BSL_CID_EC_PUBLICKEY) {
334 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
335 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
336 }
337 ret = CRYPT_SM2_ParsePrikeyAsn1Buff(pk8PrikeyInfo.pkeyRawKey, pk8PrikeyInfo.pkeyRawKeyLen, &pk8PrikeyInfo.keyParam,
338 sm2PriKey);
339 if (ret != CRYPT_SUCCESS) {
340 BSL_ERR_PUSH_ERROR(ret);
341 }
342 return ret;
343 }
344 #endif // HITLS_CRYPTO_SM2
345
346 #ifdef HITLS_CRYPTO_ED25519
ParseEd25519PrikeyAsn1Buff(uint8_t * buffer,uint32_t bufferLen,CRYPT_CURVE25519_Ctx ** ed25519PriKey)347 static int32_t ParseEd25519PrikeyAsn1Buff(uint8_t *buffer, uint32_t bufferLen, CRYPT_CURVE25519_Ctx **ed25519PriKey)
348 {
349 uint8_t *tmpBuff = buffer;
350 uint32_t tmpBuffLen = bufferLen;
351
352 int32_t ret = BSL_ASN1_DecodeTagLen(BSL_ASN1_TAG_OCTETSTRING, &tmpBuff, &tmpBuffLen, &tmpBuffLen);
353 if (ret != BSL_SUCCESS) {
354 BSL_ERR_PUSH_ERROR(ret);
355 return ret;
356 }
357
358 CRYPT_CURVE25519_Ctx *pctx = CRYPT_ED25519_NewCtx();
359 if (pctx == NULL) {
360 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
361 return CRYPT_MEM_ALLOC_FAIL;
362 }
363 BSL_Param prvParam[2] = {
364 {CRYPT_PARAM_CURVE25519_PRVKEY, BSL_PARAM_TYPE_OCTETS, tmpBuff, tmpBuffLen, 0},
365 BSL_PARAM_END
366 };
367 ret = CRYPT_CURVE25519_SetPrvKey(pctx, prvParam);
368 if (ret != CRYPT_SUCCESS) {
369 CRYPT_CURVE25519_FreeCtx(pctx);
370 BSL_ERR_PUSH_ERROR(ret);
371 return ret;
372 }
373 *ed25519PriKey = pctx;
374 return CRYPT_SUCCESS;
375 }
376
CRYPT_ED25519_ParsePkcs8Key(uint8_t * buffer,uint32_t bufferLen,CRYPT_CURVE25519_Ctx ** ed25519PriKey)377 int32_t CRYPT_ED25519_ParsePkcs8Key(uint8_t *buffer, uint32_t bufferLen, CRYPT_CURVE25519_Ctx **ed25519PriKey)
378 {
379 CRYPT_ENCODE_DECODE_Pk8PrikeyInfo pk8PrikeyInfo = {0};
380 int32_t ret = CRYPT_DECODE_Pkcs8Info(buffer, bufferLen, NULL, &pk8PrikeyInfo);
381 if (ret != CRYPT_SUCCESS) {
382 BSL_ERR_PUSH_ERROR(ret);
383 return ret;
384 }
385 if (pk8PrikeyInfo.keyType != BSL_CID_ED25519) {
386 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
387 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
388 }
389 return ParseEd25519PrikeyAsn1Buff(pk8PrikeyInfo.pkeyRawKey, pk8PrikeyInfo.pkeyRawKeyLen, ed25519PriKey);
390 }
391
CRYPT_ED25519_ParseSubPubkeyAsn1Buff(uint8_t * buff,uint32_t buffLen,CRYPT_CURVE25519_Ctx ** pubKey,bool isComplete)392 int32_t CRYPT_ED25519_ParseSubPubkeyAsn1Buff(uint8_t *buff, uint32_t buffLen, CRYPT_CURVE25519_Ctx **pubKey,
393 bool isComplete)
394 {
395 if (buff == NULL || buffLen == 0 || pubKey == NULL) {
396 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
397 return CRYPT_NULL_INPUT;
398 }
399 CRYPT_DECODE_SubPubkeyInfo subPubkeyInfo = {0};
400 int32_t ret = CRYPT_DECODE_SubPubkey(buff, buffLen, NULL, &subPubkeyInfo, isComplete);
401 if (ret != CRYPT_SUCCESS) {
402 BSL_ERR_PUSH_ERROR(ret);
403 return ret;
404 }
405 if (subPubkeyInfo.keyType != BSL_CID_ED25519) {
406 BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH);
407 return CRYPT_DECODE_ERR_KEY_TYPE_NOT_MATCH;
408 }
409 CRYPT_CURVE25519_Ctx *pctx = CRYPT_ED25519_NewCtx();
410 if (pctx == NULL) {
411 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
412 return CRYPT_MEM_ALLOC_FAIL;
413 }
414 BSL_Param pubParam[2] = {
415 {CRYPT_PARAM_CURVE25519_PUBKEY, BSL_PARAM_TYPE_OCTETS, subPubkeyInfo.pubKey.buff, subPubkeyInfo.pubKey.len, 0},
416 BSL_PARAM_END
417 };
418 ret = CRYPT_CURVE25519_SetPubKey(pctx, pubParam);
419 if (ret != CRYPT_SUCCESS) {
420 BSL_ERR_PUSH_ERROR(ret);
421 CRYPT_CURVE25519_FreeCtx(pctx);
422 return ret;
423 }
424 *pubKey = pctx;
425 return ret;
426
427 }
428 #endif // HITLS_CRYPTO_ED25519
429 #endif // HITLS_CRYPTO_KEY_DECODE
430