• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_HYBRIDKEM
18 
19 #include "securec.h"
20 #include "bsl_sal.h"
21 #include "sal_atomic.h"
22 #include "eal_pkey_local.h"
23 #include "crypt_eal_pkey.h"
24 #include "crypt_utils.h"
25 #include "crypt_hybridkem_local.h"
26 #include "crypt_hybridkem.h"
27 #include "crypt_ecdh.h"
28 #include "crypt_curve25519.h"
29 #include "crypt_mlkem.h"
30 
31 typedef struct {
32     int32_t hybrId;
33     int32_t pkeyParam;
34     int32_t kemParam;
35     int32_t pkeyAlg;
36     int32_t kemAlg;
37 } HybridKemIdList;
38 
39 static const HybridKemIdList HYBRID_KEY_LIST[] = {
40     {CRYPT_HYBRID_X25519_MLKEM512, 0, CRYPT_KEM_TYPE_MLKEM_512, CRYPT_PKEY_X25519, CRYPT_PKEY_ML_KEM},
41     {CRYPT_HYBRID_X25519_MLKEM768, 0, CRYPT_KEM_TYPE_MLKEM_768, CRYPT_PKEY_X25519, CRYPT_PKEY_ML_KEM},
42     {CRYPT_HYBRID_X25519_MLKEM1024, 0, CRYPT_KEM_TYPE_MLKEM_1024, CRYPT_PKEY_X25519, CRYPT_PKEY_ML_KEM},
43 
44     {CRYPT_HYBRID_ECDH_NISTP256_MLKEM512, CRYPT_ECC_NISTP256, CRYPT_KEM_TYPE_MLKEM_512,
45      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
46     {CRYPT_HYBRID_ECDH_NISTP256_MLKEM768, CRYPT_ECC_NISTP256, CRYPT_KEM_TYPE_MLKEM_768,
47      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
48     {CRYPT_HYBRID_ECDH_NISTP256_MLKEM1024, CRYPT_ECC_NISTP256, CRYPT_KEM_TYPE_MLKEM_1024,
49      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
50     {CRYPT_HYBRID_ECDH_NISTP384_MLKEM512, CRYPT_ECC_NISTP384, CRYPT_KEM_TYPE_MLKEM_512,
51      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
52     {CRYPT_HYBRID_ECDH_NISTP384_MLKEM768, CRYPT_ECC_NISTP384, CRYPT_KEM_TYPE_MLKEM_768,
53      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
54     {CRYPT_HYBRID_ECDH_NISTP384_MLKEM1024, CRYPT_ECC_NISTP384, CRYPT_KEM_TYPE_MLKEM_1024,
55      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
56     {CRYPT_HYBRID_ECDH_NISTP521_MLKEM512, CRYPT_ECC_NISTP521, CRYPT_KEM_TYPE_MLKEM_512,
57      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
58     {CRYPT_HYBRID_ECDH_NISTP521_MLKEM768, CRYPT_ECC_NISTP521, CRYPT_KEM_TYPE_MLKEM_768,
59      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
60     {CRYPT_HYBRID_ECDH_NISTP521_MLKEM1024, CRYPT_ECC_NISTP521, CRYPT_KEM_TYPE_MLKEM_1024,
61      CRYPT_PKEY_ECDH, CRYPT_PKEY_ML_KEM},
62 };
63 
HybridGetCurveIdAndKemId(int32_t hybrId,const HybridKemIdList ** algInfo)64 static int32_t HybridGetCurveIdAndKemId(int32_t hybrId, const HybridKemIdList **algInfo)
65 {
66     for (uint32_t i = 0; i < (sizeof(HYBRID_KEY_LIST) / sizeof(HYBRID_KEY_LIST[0])); i++) {
67         if (HYBRID_KEY_LIST[i].hybrId == hybrId) {
68             *algInfo = &HYBRID_KEY_LIST[i];
69             return CRYPT_SUCCESS;
70         }
71     }
72     return CRYPT_ERR_ALGID;
73 }
74 
CRYPT_HYBRID_KEM_NewCtx(void)75 CRYPT_HybridKemCtx *CRYPT_HYBRID_KEM_NewCtx(void)
76 {
77     CRYPT_HybridKemCtx *hybridKey = BSL_SAL_Calloc(sizeof(CRYPT_HybridKemCtx), 1);
78     if (hybridKey == NULL) {
79         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
80         return NULL;
81     }
82     BSL_SAL_ReferencesInit(&(hybridKey->references));
83     return hybridKey;
84 }
85 
CRYPT_HYBRID_KEM_NewCtxEx(void * libCtx)86 CRYPT_HybridKemCtx *CRYPT_HYBRID_KEM_NewCtxEx(void *libCtx)
87 {
88     CRYPT_HybridKemCtx *hybridKey = CRYPT_HYBRID_KEM_NewCtx();
89     if (hybridKey == NULL) {
90         return NULL;
91 
92     }
93     hybridKey->libCtx = libCtx;
94     return hybridKey;
95 }
96 
CRYPT_HYBRID_KEM_FreeCtx(CRYPT_HybridKemCtx * hybridKey)97 void CRYPT_HYBRID_KEM_FreeCtx(CRYPT_HybridKemCtx *hybridKey)
98 {
99     if (hybridKey == NULL) {
100         return;
101     }
102     int ref = 0;
103     BSL_SAL_AtomicDownReferences(&(hybridKey->references), &ref);
104     if (ref > 0) {
105         return;
106     }
107     BSL_SAL_ReferencesFree(&(hybridKey->references));
108     if (hybridKey->pKeyMethod != NULL && hybridKey->pKeyMethod->freeCtx != NULL) {
109         hybridKey->pKeyMethod->freeCtx(hybridKey->pkeyCtx);
110     }
111     if (hybridKey->kemMethod != NULL && hybridKey->kemMethod->freeCtx != NULL) {
112         hybridKey->kemMethod->freeCtx(hybridKey->kemCtx);
113     }
114     BSL_SAL_FREE(hybridKey);
115 }
116 
CRYPT_HybridNewPkeyCtx(CRYPT_HybridKemCtx * ctx,int32_t algId)117 static void *CRYPT_HybridNewPkeyCtx(CRYPT_HybridKemCtx *ctx, int32_t algId)
118 {
119     void *pkeyCtx = NULL;
120 #ifdef HITLS_CRYPTO_PROVIDER
121     if (algId == CRYPT_PKEY_X25519) {
122         pkeyCtx = CRYPT_X25519_NewCtxEx(ctx->libCtx);
123     } else {
124         pkeyCtx = CRYPT_ECDH_NewCtxEx(ctx->libCtx);
125     }
126 #else
127     (void) ctx;
128     if (algId == CRYPT_PKEY_X25519) {
129         pkeyCtx = CRYPT_X25519_NewCtx();
130     } else {
131         pkeyCtx = CRYPT_ECDH_NewCtx();
132     }
133 #endif
134     return pkeyCtx;
135 }
136 
CRYPT_HybridNewKemCtx(CRYPT_HybridKemCtx * ctx,int32_t algId)137 static void *CRYPT_HybridNewKemCtx(CRYPT_HybridKemCtx *ctx, int32_t algId)
138 {
139     (void) algId;
140     void *kemCtx = NULL;
141 #ifdef HITLS_CRYPTO_PROVIDER
142     kemCtx = CRYPT_ML_KEM_NewCtxEx(ctx->libCtx);
143 #else
144     (void) ctx;
145     kemCtx = CRYPT_ML_KEM_NewCtx();
146 #endif
147     return kemCtx;
148 }
149 
CRYPT_HybridSetKeyType(CRYPT_HybridKemCtx * ctx,int32_t val)150 static int32_t CRYPT_HybridSetKeyType(CRYPT_HybridKemCtx *ctx, int32_t val)
151 {
152     int32_t ret;
153     const HybridKemIdList *algInfo = NULL;
154     RETURN_RET_IF((ctx->pkeyCtx != NULL || ctx->kemCtx != NULL), CRYPT_INVALID_ARG);
155     RETURN_RET_IF_ERR(HybridGetCurveIdAndKemId(val, &algInfo), ret);
156 
157     const EAL_PkeyMethod *pKeyMethod = CRYPT_EAL_PkeyFindMethod(algInfo->pkeyAlg);
158     const EAL_PkeyMethod *kemMethod = CRYPT_EAL_PkeyFindMethod(algInfo->kemAlg);
159     RETURN_RET_IF((pKeyMethod == NULL || kemMethod == NULL), CRYPT_NOT_SUPPORT);
160 
161     ctx->pkeyCtx = CRYPT_HybridNewPkeyCtx(ctx, algInfo->pkeyAlg);
162     RETURN_RET_IF(ctx->pkeyCtx == NULL, CRYPT_MEM_ALLOC_FAIL);
163     ctx->kemCtx = CRYPT_HybridNewKemCtx(ctx, algInfo->kemAlg);
164     if (ctx->kemCtx == NULL) {
165         pKeyMethod->freeCtx(ctx->pkeyCtx);
166         ctx->pkeyCtx = NULL;
167         return CRYPT_MEM_ALLOC_FAIL;
168     }
169     ctx->pKeyMethod = pKeyMethod;
170     ctx->kemMethod = kemMethod;
171 
172     int32_t kemType = algInfo->kemParam;
173     int32_t curveId = algInfo->pkeyParam;
174     GOTO_ERR_IF_EX(ctx->kemMethod->ctrl(ctx->kemCtx, CRYPT_CTRL_SET_PARA_BY_ID, &kemType, sizeof(kemType)), ret);
175     if (curveId == 0) {  // For X25519, the curve ID does not need to be set.
176         return CRYPT_SUCCESS;
177     }
178     GOTO_ERR_IF_EX(ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_SET_PARA_BY_ID, &curveId, sizeof(curveId)), ret);
179     return CRYPT_SUCCESS;
180 ERR:
181     pKeyMethod->freeCtx(ctx->pkeyCtx);
182     ctx->pkeyCtx = NULL;
183     kemMethod->freeCtx(ctx->kemCtx);
184     ctx->kemCtx = NULL;
185     return ret;
186 }
187 
CRYPT_HybridGetEncapsKeyLen(const CRYPT_HybridKemCtx * ctx,uint32_t * pubLen,uint32_t * ekLen)188 static int32_t CRYPT_HybridGetEncapsKeyLen(const CRYPT_HybridKemCtx *ctx, uint32_t *pubLen, uint32_t *ekLen)
189 {
190     int32_t ret;
191     uint32_t val;
192     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->kemMethod == NULL), CRYPT_NULL_INPUT);
193     RETURN_RET_IF_ERR(ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_GET_PUBKEY_LEN, &val, sizeof(val)), ret);
194     *pubLen = val;
195 
196     RETURN_RET_IF_ERR(ctx->kemMethod->ctrl(ctx->kemCtx, CRYPT_CTRL_GET_PUBKEY_LEN, &val, sizeof(val)), ret);
197     *ekLen = val;
198     return CRYPT_SUCCESS;
199 }
200 
CRYPT_HybridGetDecapsKeyLen(const CRYPT_HybridKemCtx * ctx,uint32_t * prvLen,uint32_t * dkLen)201 static int32_t CRYPT_HybridGetDecapsKeyLen(const CRYPT_HybridKemCtx *ctx, uint32_t *prvLen, uint32_t *dkLen)
202 {
203     int32_t ret;
204     uint32_t val;
205     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->kemMethod == NULL), CRYPT_NULL_INPUT);
206     RETURN_RET_IF_ERR(ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_GET_PRVKEY_LEN, &val, sizeof(val)), ret);
207     *prvLen = val;
208 
209     RETURN_RET_IF_ERR(ctx->kemMethod->ctrl(ctx->kemCtx, CRYPT_CTRL_GET_PRVKEY_LEN, &val, sizeof(val)), ret);
210     *dkLen = val;
211     return CRYPT_SUCCESS;
212 }
213 
CRYPT_HybridGetCipherTextLen(const CRYPT_HybridKemCtx * ctx,uint32_t * pubLen,uint32_t * ctLen)214 static int32_t CRYPT_HybridGetCipherTextLen(const CRYPT_HybridKemCtx *ctx, uint32_t *pubLen, uint32_t *ctLen)
215 {
216     int32_t ret;
217     uint32_t val;
218     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->kemMethod == NULL), CRYPT_NULL_INPUT);
219     RETURN_RET_IF_ERR(ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_GET_PUBKEY_LEN, &val, sizeof(val)), ret);
220     *pubLen = val;
221 
222     RETURN_RET_IF_ERR(ctx->kemMethod->ctrl(ctx->kemCtx, CRYPT_CTRL_GET_CIPHERTEXT_LEN, &val, sizeof(val)), ret);
223     *ctLen = val;
224     return CRYPT_SUCCESS;
225 }
226 
CRYPT_HybridGetShareKeyLen(const CRYPT_HybridKemCtx * ctx,uint32_t * pkeyLen,uint32_t * kemLen)227 static int32_t CRYPT_HybridGetShareKeyLen(const CRYPT_HybridKemCtx *ctx, uint32_t *pkeyLen, uint32_t *kemLen)
228 {
229     int32_t ret;
230     uint32_t val;
231     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->kemMethod == NULL), CRYPT_NULL_INPUT);
232     RETURN_RET_IF_ERR(ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_GET_SHARED_KEY_LEN, &val, sizeof(val)), ret);
233     *pkeyLen = val;
234     RETURN_RET_IF_ERR(ctx->kemMethod->ctrl(ctx->kemCtx, CRYPT_CTRL_GET_SHARED_KEY_LEN, &val, sizeof(val)), ret);
235     *kemLen = val;
236     return CRYPT_SUCCESS;
237 }
238 
CRYPT_HybridSetEccPointFormit(const CRYPT_HybridKemCtx * ctx,void * val,uint32_t len)239 static int32_t CRYPT_HybridSetEccPointFormit(const CRYPT_HybridKemCtx *ctx, void *val, uint32_t len)
240 {
241     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->pkeyCtx == NULL), CRYPT_INVALID_ARG);
242     return ctx->pKeyMethod->ctrl(ctx->pkeyCtx, CRYPT_CTRL_SET_ECC_POINT_FORMAT, val, len);
243 }
244 
CRYPT_HYBRID_KEM_KeyCtrl(CRYPT_HybridKemCtx * ctx,int32_t opt,void * val,uint32_t len)245 int32_t CRYPT_HYBRID_KEM_KeyCtrl(CRYPT_HybridKemCtx *ctx, int32_t opt, void *val, uint32_t len)
246 {
247     int32_t ret;
248     RETURN_RET_IF(ctx == NULL || val == NULL, CRYPT_NULL_INPUT);
249     RETURN_RET_IF(len != sizeof(uint32_t), CRYPT_INVALID_ARG);
250     uint32_t pkeyLen = 0;
251     uint32_t kemLen = 0;
252     switch (opt) {
253         case CRYPT_CTRL_SET_PARA_BY_ID:
254             return CRYPT_HybridSetKeyType(ctx, *(int32_t *)val);
255         case CRYPT_CTRL_GET_PUBKEY_LEN:
256             ret = CRYPT_HybridGetEncapsKeyLen(ctx, &pkeyLen, &kemLen);
257             break;
258         case CRYPT_CTRL_GET_PRVKEY_LEN:
259             ret = CRYPT_HybridGetDecapsKeyLen(ctx, &pkeyLen, &kemLen);
260             break;
261         case CRYPT_CTRL_GET_CIPHERTEXT_LEN:
262             ret = CRYPT_HybridGetCipherTextLen(ctx, &pkeyLen, &kemLen);
263             break;
264         case CRYPT_CTRL_GET_SHARED_KEY_LEN:
265             ret = CRYPT_HybridGetShareKeyLen(ctx, &pkeyLen, &kemLen);
266             break;
267         case CRYPT_CTRL_SET_ECC_POINT_FORMAT:
268             return CRYPT_HybridSetEccPointFormit(ctx, val, len);
269         default:
270             BSL_ERR_PUSH_ERROR(CRYPT_NOT_SUPPORT);
271             return CRYPT_NOT_SUPPORT;
272     }
273     RETURN_RET_IF(ret != CRYPT_SUCCESS, ret);
274     *(uint32_t *)val = pkeyLen + kemLen;
275     return CRYPT_SUCCESS;
276 }
277 
CRYPT_HYBRID_KEM_GenKey(CRYPT_HybridKemCtx * ctx)278 int32_t CRYPT_HYBRID_KEM_GenKey(CRYPT_HybridKemCtx *ctx)
279 {
280     int32_t ret;
281     RETURN_RET_IF(ctx == NULL, CRYPT_NULL_INPUT);
282     RETURN_RET_IF((ctx->pKeyMethod == NULL || ctx->kemMethod == NULL), CRYPT_NULL_INPUT);
283     RETURN_RET_IF_ERR(ctx->pKeyMethod->gen(ctx->pkeyCtx), ret);
284     return ctx->kemMethod->gen(ctx->kemCtx);
285 }
286 
287 /*
288  * According of <Post-quantum hybrid ECDHE-MLKEM Key Agreement for TLSv1.3>, when MLKEM and X25519 are mixed,
289  * the key of MLKEM is before the key of X25519.
290  * Protocol link: www.ietf.org/archive/id/draft-kwiatkowski-tls-ecdhe-mlkem-03.html#name-negotiated-groups
291 */
CRYPT_HybridGetKeyPtr(const CRYPT_HybridKemCtx * ctx,const BSL_Param * input,BSL_Param * pkeyData,BSL_Param * kemData)292 static int32_t CRYPT_HybridGetKeyPtr(const CRYPT_HybridKemCtx *ctx, const BSL_Param *input, BSL_Param *pkeyData,
293     BSL_Param *kemData)
294 {
295     RETURN_RET_IF(input->valueLen < (pkeyData->valueLen + kemData->valueLen), CRYPT_INVALID_ARG);
296     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
297         kemData->value = input->value;
298         pkeyData->value = input->value + kemData->valueLen;
299     } else {
300         pkeyData->value = input->value;
301         kemData->value = input->value + pkeyData->valueLen;
302     }
303     return CRYPT_SUCCESS;
304 }
305 
306 // Get the local public Key and kem encapsulation key.
CRYPT_HYBRID_KEM_GetEncapsKey(const CRYPT_HybridKemCtx * ctx,BSL_Param * param)307 int32_t CRYPT_HYBRID_KEM_GetEncapsKey(const CRYPT_HybridKemCtx *ctx, BSL_Param *param)
308 {
309     int32_t ret;
310     RETURN_RET_IF((ctx == NULL), CRYPT_NULL_INPUT);
311     BSL_Param *pub = BSL_PARAM_FindParam(param, CRYPT_PARAM_HYBRID_PUBKEY);
312     if (pub == NULL) {
313         pub = BSL_PARAM_FindParam(param, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
314     }
315     RETURN_RET_IF(pub == NULL || pub->value == NULL, CRYPT_NULL_INPUT);
316 
317     BSL_Param pubKey[2] = {{CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
318     BSL_Param kemEK[2] = {{CRYPT_PARAM_ML_KEM_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
319     RETURN_RET_IF_ERR(CRYPT_HybridGetEncapsKeyLen(ctx, &(pubKey[0].valueLen), &(kemEK[0].valueLen)), ret);
320     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, pub, pubKey, kemEK), ret);
321 
322     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
323         pubKey[0].key = CRYPT_PARAM_CURVE25519_PUBKEY;
324     }
325     RETURN_RET_IF_ERR(ctx->pKeyMethod->getPub(ctx->pkeyCtx, pubKey), ret);
326     RETURN_RET_IF_ERR(ctx->kemMethod->getPub(ctx->kemCtx, kemEK), ret);
327     pub->useLen = pubKey[0].useLen + kemEK[0].useLen;
328     return CRYPT_SUCCESS;
329 }
330 
CRYPT_HYBRID_KEM_GetDecapsKey(const CRYPT_HybridKemCtx * ctx,BSL_Param * param)331 int32_t CRYPT_HYBRID_KEM_GetDecapsKey(const CRYPT_HybridKemCtx *ctx, BSL_Param *param)
332 {
333     int32_t ret;
334     RETURN_RET_IF((ctx == NULL), CRYPT_NULL_INPUT);
335     BSL_Param *prv = BSL_PARAM_FindParam(param, CRYPT_PARAM_HYBRID_PRVKEY);
336     RETURN_RET_IF(prv == NULL || prv->value == NULL, CRYPT_NULL_INPUT);
337 
338     BSL_Param prvKey[2] = {{CRYPT_PARAM_EC_PRVKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
339     BSL_Param kemDK[2] = {{CRYPT_PARAM_ML_KEM_PRVKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
340     RETURN_RET_IF_ERR(CRYPT_HybridGetDecapsKeyLen(ctx, &prvKey[0].valueLen, &kemDK[0].valueLen), ret);
341     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, prv, prvKey, kemDK), ret);
342 
343     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
344         prvKey[0].key = CRYPT_PARAM_CURVE25519_PRVKEY;
345     }
346     RETURN_RET_IF_ERR(ctx->pKeyMethod->getPrv(ctx->pkeyCtx, prvKey), ret);
347     RETURN_RET_IF_ERR(ctx->kemMethod->getPrv(ctx->kemCtx, kemDK), ret);
348     prv->useLen = prvKey[0].useLen + kemDK[0].useLen;
349     return CRYPT_SUCCESS;
350 }
351 
352 // Set the public key and kem encapsulation key.
CRYPT_HYBRID_KEM_SetEncapsKey(CRYPT_HybridKemCtx * ctx,const BSL_Param * param)353 int32_t CRYPT_HYBRID_KEM_SetEncapsKey(CRYPT_HybridKemCtx *ctx, const BSL_Param *param)
354 {
355     int32_t ret;
356     RETURN_RET_IF((ctx == NULL || param == NULL), CRYPT_NULL_INPUT);
357     const BSL_Param *pub = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_HYBRID_PUBKEY);
358     if (pub == NULL) {
359         pub = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
360     }
361     RETURN_RET_IF(pub == NULL || pub->value == NULL, CRYPT_NULL_INPUT);
362     BSL_Param pubKey[2] = {{CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
363     BSL_Param kemEK[2] = {{CRYPT_PARAM_ML_KEM_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
364     RETURN_RET_IF_ERR(CRYPT_HybridGetEncapsKeyLen(ctx, &pubKey[0].valueLen, &kemEK[0].valueLen), ret);
365     RETURN_RET_IF(pub->valueLen < kemEK[0].valueLen, CRYPT_INVALID_ARG);
366     pubKey[0].valueLen = pub->valueLen - kemEK[0].valueLen;
367     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, pub, pubKey, kemEK), ret);
368 
369     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
370         pubKey[0].key = CRYPT_PARAM_CURVE25519_PUBKEY;
371     }
372     RETURN_RET_IF_ERR(ctx->kemMethod->setPub(ctx->kemCtx, kemEK), ret);
373     return ctx->pKeyMethod->setPub(ctx->pkeyCtx, pubKey);
374 }
375 
CRYPT_HYBRID_KEM_SetDecapsKey(CRYPT_HybridKemCtx * ctx,const BSL_Param * param)376 int32_t CRYPT_HYBRID_KEM_SetDecapsKey(CRYPT_HybridKemCtx *ctx, const BSL_Param *param)
377 {
378     int32_t ret;
379     RETURN_RET_IF((ctx == NULL || param == NULL), CRYPT_NULL_INPUT);
380     const BSL_Param *prv = BSL_PARAM_FindConstParam(param, CRYPT_PARAM_HYBRID_PRVKEY);
381     RETURN_RET_IF(prv == NULL || prv->value == NULL, CRYPT_NULL_INPUT);
382     BSL_Param prvKey[2] = {{CRYPT_PARAM_EC_PRVKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
383     BSL_Param kemDK[2] = {{CRYPT_PARAM_ML_KEM_PRVKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
384     RETURN_RET_IF_ERR(CRYPT_HybridGetDecapsKeyLen(ctx, &(prvKey[0].valueLen), &(kemDK[0].valueLen)), ret);
385     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, prv, prvKey, kemDK), ret);
386 
387     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
388         prvKey[0].key = CRYPT_PARAM_CURVE25519_PRVKEY;
389     }
390     RETURN_RET_IF_ERR(ctx->kemMethod->setPrv(ctx->kemCtx, kemDK), ret);
391     return ctx->pKeyMethod->setPrv(ctx->pkeyCtx, prvKey);
392 }
393 
CRYPT_HYBRID_KEM_Encaps(const CRYPT_HybridKemCtx * ctx,uint8_t * cipher,uint32_t * cipherLen,uint8_t * sharekey,uint32_t * shareLen)394 int32_t CRYPT_HYBRID_KEM_Encaps(const CRYPT_HybridKemCtx *ctx, uint8_t *cipher, uint32_t *cipherLen,
395     uint8_t *sharekey, uint32_t *shareLen)
396 {
397     int32_t ret;
398     RETURN_RET_IF((ctx == NULL || cipher == NULL || cipherLen == NULL || sharekey == NULL || shareLen == NULL),
399         CRYPT_NULL_INPUT);
400 
401     BSL_Param kemCT = { 0 };
402     BSL_Param pubKey[2] = {{CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
403     BSL_Param cipherData = { 0 };
404     cipherData.value = cipher;
405     cipherData.valueLen = *cipherLen;
406     RETURN_RET_IF_ERR(CRYPT_HybridGetCipherTextLen(ctx, &(pubKey[0].valueLen), &(kemCT.valueLen)), ret);
407     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, &cipherData, pubKey, &kemCT), ret);
408 
409     void *tmpKey = ctx->pKeyMethod->dupCtx(ctx->pkeyCtx);
410     RETURN_RET_IF(tmpKey == NULL, CRYPT_MEM_ALLOC_FAIL);
411     GOTO_ERR_IF(ctx->pKeyMethod->gen(tmpKey), ret);
412     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
413         pubKey[0].key = CRYPT_PARAM_CURVE25519_PUBKEY;
414     }
415     GOTO_ERR_IF(ctx->pKeyMethod->getPub(tmpKey, pubKey), ret);
416 
417     BSL_Param kemSK = { 0 };
418     BSL_Param pkeyShared = { 0 };
419     BSL_Param shareData = { 0 };
420     shareData.value = sharekey;
421     shareData.valueLen = *shareLen;
422     GOTO_ERR_IF(CRYPT_HybridGetShareKeyLen(ctx, &pkeyShared.valueLen, &kemSK.valueLen), ret);
423     GOTO_ERR_IF(CRYPT_HybridGetKeyPtr(ctx, &shareData, &pkeyShared, &kemSK), ret);
424     GOTO_ERR_IF(ctx->pKeyMethod->computeShareKey(tmpKey, ctx->pkeyCtx, pkeyShared.value, &pkeyShared.valueLen), ret);
425 
426     GOTO_ERR_IF(ctx->kemMethod->encaps(ctx->kemCtx, kemCT.value, &kemCT.valueLen, kemSK.value, &kemSK.valueLen), ret);
427     *shareLen = pkeyShared.valueLen + kemSK.valueLen;
428     *cipherLen = pubKey[0].valueLen + kemCT.valueLen;
429 
430 ERR:
431     ctx->pKeyMethod->freeCtx(tmpKey);
432     return ret;
433 }
434 
CRYPT_HYBRID_KEM_Decaps(const CRYPT_HybridKemCtx * ctx,uint8_t * cipher,uint32_t cipherLen,uint8_t * sharekey,uint32_t * shareLen)435 int32_t CRYPT_HYBRID_KEM_Decaps(const CRYPT_HybridKemCtx *ctx, uint8_t *cipher, uint32_t cipherLen,
436     uint8_t *sharekey, uint32_t *shareLen)
437 {
438     int32_t ret;
439     RETURN_RET_IF((ctx == NULL || cipher == NULL || sharekey == NULL || shareLen == NULL), CRYPT_NULL_INPUT);
440 
441     BSL_Param cipherData = { 0 };
442     cipherData.value = cipher;
443     cipherData.valueLen = cipherLen;
444     BSL_Param kemCT = { 0 };
445     BSL_Param pubKey[2] = {{CRYPT_PARAM_EC_PUBKEY, BSL_PARAM_TYPE_OCTETS, NULL, 0, 0}, BSL_PARAM_END};
446     RETURN_RET_IF_ERR(CRYPT_HybridGetCipherTextLen(ctx, &pubKey[0].valueLen, &kemCT.valueLen), ret);
447     RETURN_RET_IF_ERR(CRYPT_HybridGetKeyPtr(ctx, &cipherData, pubKey, &kemCT), ret);
448 
449     void *tmpKey = ctx->pKeyMethod->dupCtx(ctx->pkeyCtx);
450     RETURN_RET_IF(tmpKey == NULL, CRYPT_MEM_ALLOC_FAIL);
451     if (ctx->pKeyMethod->id == CRYPT_PKEY_X25519) {
452         pubKey[0].key = CRYPT_PARAM_CURVE25519_PUBKEY;
453     }
454     GOTO_ERR_IF(ctx->pKeyMethod->setPub(tmpKey, pubKey), ret);
455 
456     BSL_Param pkeyShared = { 0 };
457     BSL_Param kemSK = { 0 };
458     BSL_Param shareData = { 0 };
459     shareData.value = sharekey;
460     shareData.valueLen = *shareLen;
461     GOTO_ERR_IF(CRYPT_HybridGetShareKeyLen(ctx, &pkeyShared.valueLen, &kemSK.valueLen), ret);
462     GOTO_ERR_IF(CRYPT_HybridGetKeyPtr(ctx, &shareData, &pkeyShared, &kemSK), ret);
463     GOTO_ERR_IF(ctx->pKeyMethod->computeShareKey(ctx->pkeyCtx, tmpKey, pkeyShared.value, &pkeyShared.valueLen), ret);
464 
465     GOTO_ERR_IF(ctx->kemMethod->decaps(ctx->kemCtx, kemCT.value, kemCT.valueLen, kemSK.value, &kemSK.valueLen), ret);
466     *shareLen = pkeyShared.valueLen + kemSK.valueLen;
467 ERR:
468     ctx->pKeyMethod->freeCtx(tmpKey);
469     return ret;
470 }
471 
472 #endif