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