Skip to content

Commit deb4cc1

Browse files
committed
ML-KEM fixes
* DTLS 1.3 cookie and CH frag handling * static memory handling * Fix memory leak in TLS server PQC handling in case of ECH * Make sure hybrids are actually tested in testsuite
1 parent 156db7d commit deb4cc1

9 files changed

Lines changed: 151 additions & 33 deletions

File tree

examples/client/client.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,18 @@ static void SetKeyShare(WOLFSSL* ssl, int onlyKeyShare, int useX25519,
557557
else {
558558
err_sys("unable to use post-quantum KEM");
559559
}
560+
561+
#ifdef WOLFSSL_DTLS13
562+
if (wolfSSL_dtls(ssl)) {
563+
/* When the KeyShare is too large for an unfragmented
564+
* ClientHello, DTLS sends an empty KeyShare extension to
565+
* use the Hello Retry Request to enable fragmentation.
566+
* In order to enforce our desired PQC algorithm in the
567+
* second ClientHello, we need to set it as the only one
568+
* allowed in the SupportedGroups extension. */
569+
setGroups = 1;
570+
}
571+
#endif /* WOLFSSL_DTLS13 */
560572
}
561573
}
562574
#endif
@@ -2299,8 +2311,8 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args)
22992311

23002312

23012313
#ifdef WOLFSSL_STATIC_MEMORY
2302-
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
2303-
|| defined(SESSION_CERTS)
2314+
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) || \
2315+
defined(SESSION_CERTS) || defined(WOLFSSL_HAVE_MLKEM)
23042316
/* big enough to handle most cases including session certs */
23052317
byte memory[320000];
23062318
#else

examples/server/server.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1763,8 +1763,8 @@ THREAD_RETURN WOLFSSL_THREAD server_test(void* args)
17631763
/* Note: Actual memory used is much less, this is the entire buffer buckets,
17641764
* which is partitioned into pools of common sizes. To adjust the buckets
17651765
* sizes see WOLFMEM_BUCKETS in memory.h */
1766-
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) \
1767-
|| defined(SESSION_CERTS)
1766+
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) || \
1767+
defined(SESSION_CERTS) || defined(WOLFSSL_HAVE_MLKEM)
17681768
/* big enough to handle most cases including session certs */
17691769
#if !defined(WOLFSSL_NO_CLIENT_AUTH) && \
17701770
((defined(HAVE_ED25519) && !defined(NO_ED25519_CLIENT_AUTH)) || \

src/internal.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,6 +2251,26 @@ int InitSSL_Side(WOLFSSL* ssl, word16 side)
22512251
WOLFSSL_MSG("DTLS Cookie Secret error");
22522252
return ret;
22532253
}
2254+
#if defined(WOLFSSL_DTLS13)
2255+
if (IsAtLeastTLSv1_3(ssl->version)) {
2256+
#if defined(WOLFSSL_SEND_HRR_COOKIE)
2257+
ret = wolfSSL_send_hrr_cookie(ssl, NULL, 0);
2258+
if (ret != WOLFSSL_SUCCESS) {
2259+
WOLFSSL_MSG("DTLS1.3 Cookie secret error");
2260+
return ret;
2261+
}
2262+
#endif /* WOLFSSL_SEND_HRR_COOKIE */
2263+
#if defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM)
2264+
/* Allow fragmentation of the second ClientHello due to the
2265+
* large PQC key share. */
2266+
ret = wolfSSL_dtls13_allow_ch_frag(ssl, 1);
2267+
if (ret != WOLFSSL_SUCCESS) {
2268+
WOLFSSL_MSG("DTLS1.3 CH frag error");
2269+
return ret;
2270+
}
2271+
#endif /* WOLFSSL_DTLS_CH_FRAG && WOLFSSL_HAVE_MLKEM */
2272+
}
2273+
#endif /* WOLFSSL_DTLS13 */
22542274
}
22552275
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
22562276

@@ -8006,15 +8026,26 @@ int InitSSL(WOLFSSL* ssl, WOLFSSL_CTX* ctx, int writeDup)
80068026
WOLFSSL_MSG("DTLS Cookie Secret error");
80078027
return ret;
80088028
}
8009-
#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
8029+
#if defined(WOLFSSL_DTLS13)
80108030
if (IsAtLeastTLSv1_3(ssl->version)) {
8031+
#if defined(WOLFSSL_SEND_HRR_COOKIE)
80118032
ret = wolfSSL_send_hrr_cookie(ssl, NULL, 0);
80128033
if (ret != WOLFSSL_SUCCESS) {
80138034
WOLFSSL_MSG("DTLS1.3 Cookie secret error");
80148035
return ret;
80158036
}
8037+
#endif /* WOLFSSL_SEND_HRR_COOKIE */
8038+
#if defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM)
8039+
/* Allow fragmentation of the second ClientHello due to the
8040+
* large PQC key share. */
8041+
ret = wolfSSL_dtls13_allow_ch_frag(ssl, 1);
8042+
if (ret != WOLFSSL_SUCCESS) {
8043+
WOLFSSL_MSG("DTLS1.3 CH frag error");
8044+
return ret;
8045+
}
8046+
#endif /* WOLFSSL_DTLS_CH_FRAG && WOLFSSL_HAVE_MLKEM */
80168047
}
8017-
#endif /* WOLFSSL_DTLS13 && WOLFSSL_SEND_HRR_COOKIE */
8048+
#endif /* WOLFSSL_DTLS13 */
80188049
}
80198050
#endif /* WOLFSSL_DTLS && !NO_WOLFSSL_SERVER */
80208051

src/tls.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10531,6 +10531,7 @@ static int TLSX_KeyShare_HandlePqcKeyServer(WOLFSSL* ssl,
1053110531
keyShareEntry->ke = NULL;
1053210532
keyShareEntry->keLen = 0;
1053310533

10534+
XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1053410535
keyShareEntry->pubKey = ciphertext;
1053510536
keyShareEntry->pubKeyLen = ctSz;
1053610537
ciphertext = NULL;
@@ -10767,6 +10768,7 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl,
1076710768
XMEMCPY(ciphertext + ecc_kse->pubKeyLen, pqc_kse->pubKey, ctSz);
1076810769
}
1076910770

10771+
XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1077010772
keyShareEntry->pubKey = ciphertext;
1077110773
keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen + ctSz;
1077210774
ciphertext = NULL;
@@ -10856,13 +10858,20 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data,
1085610858
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE)
1085710859
if (ssl->options.side == WOLFSSL_SERVER_END &&
1085810860
WOLFSSL_NAMED_GROUP_IS_PQC(group)) {
10859-
ret = TLSX_KeyShare_HandlePqcKeyServer((WOLFSSL*)ssl,
10860-
keyShareEntry,
10861-
data, len,
10862-
ssl->arrays->preMasterSecret,
10863-
&ssl->arrays->preMasterSz);
10864-
if (ret != 0)
10865-
return ret;
10861+
if (TLSX_IsGroupSupported(group)) {
10862+
ret = TLSX_KeyShare_HandlePqcKeyServer((WOLFSSL*)ssl,
10863+
keyShareEntry,
10864+
data, len,
10865+
ssl->arrays->preMasterSecret,
10866+
&ssl->arrays->preMasterSz);
10867+
if (ret != 0)
10868+
return ret;
10869+
}
10870+
else {
10871+
XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10872+
keyShareEntry->ke = NULL;
10873+
keyShareEntry->keLen = 0;
10874+
}
1086610875
}
1086710876
else if (ssl->options.side == WOLFSSL_SERVER_END &&
1086810877
WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group)) {

tests/api.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@
259259
#endif
260260

261261
#if defined(WOLFSSL_STATIC_MEMORY) && !defined(WOLFCRYPT_ONLY)
262-
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) || defined(SESSION_CERTS)
262+
#if (defined(HAVE_ECC) && !defined(ALT_ECC_SIZE)) || \
263+
defined(SESSION_CERTS) || defined(WOLFSSL_HAVE_MLKEM)
263264
#ifdef OPENSSL_EXTRA
264265
#define TEST_TLS_STATIC_MEMSZ (400000)
265266
#else
@@ -31980,7 +31981,7 @@ static int test_dtls13_frag_ch_pq(void)
3198031981
{
3198131982
EXPECT_DECLS;
3198231983
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
31983-
&& defined(WOLFSSL_DTLS_CH_FRAG) && defined(HAVE_LIBOQS)
31984+
&& defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM)
3198431985
WOLFSSL_CTX *ctx_c = NULL;
3198531986
WOLFSSL_CTX *ctx_s = NULL;
3198631987
WOLFSSL *ssl_c = NULL;

tests/suites.c

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ static int IsKyberLevelAvailable(const char* line)
180180
begin += 6;
181181
end = XSTRSTR(begin, " ");
182182

183-
#ifndef WOLFSSL_NO_ML_KEM
183+
#ifndef WOLFSSL_NO_ML_KEM
184184
if ((size_t)end - (size_t)begin == 10) {
185185
#ifndef WOLFSSL_NO_ML_KEM_512
186186
if (XSTRNCMP(begin, "ML_KEM_512", 10) == 0) {
@@ -200,8 +200,64 @@ static int IsKyberLevelAvailable(const char* line)
200200
}
201201
}
202202
#endif
203-
#endif
204-
#ifdef WOLFSSL_MLKEM_KYBER
203+
#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC)
204+
if ((size_t)end - (size_t)begin == 17) {
205+
if (XSTRNCMP(begin, "SecP256r1MLKEM768", 17) == 0) {
206+
available = 1;
207+
}
208+
}
209+
#endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_ECC */
210+
#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE25519)
211+
if ((size_t)end - (size_t)begin == 14) {
212+
if (XSTRNCMP(begin, "X25519MLKEM768", 14) == 0) {
213+
available = 1;
214+
}
215+
}
216+
#endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_CURVE25519 */
217+
#if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC384)
218+
if ((size_t)end - (size_t)begin == 18) {
219+
if (XSTRNCMP(begin, "SecP384r1MLKEM1024", 18) == 0) {
220+
available = 1;
221+
}
222+
}
223+
#endif /* !WOLFSSL_NO_ML_KEM_1024 && HAVE_ECC384 */
224+
#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_ECC)
225+
if ((size_t)end - (size_t)begin == 17) {
226+
if (XSTRNCMP(begin, "SecP256r1MLKEM512", 17) == 0) {
227+
available = 1;
228+
}
229+
}
230+
#endif /* !WOLFSSL_NO_ML_KEM_512 && HAVE_ECC */
231+
#if !defined(WOLFSSL_NO_ML_KEM_512) && defined(HAVE_CURVE25519)
232+
if ((size_t)end - (size_t)begin == 14) {
233+
if (XSTRNCMP(begin, "X25519MLKEM512", 14) == 0) {
234+
available = 1;
235+
}
236+
}
237+
#endif /* !WOLFSSL_NO_ML_KEM_512 && HAVE_CURVE25519 */
238+
#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_ECC384)
239+
if ((size_t)end - (size_t)begin == 17) {
240+
if (XSTRNCMP(begin, "SecP384r1MLKEM768", 17) == 0) {
241+
available = 1;
242+
}
243+
}
244+
#endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_ECC384 */
245+
#if !defined(WOLFSSL_NO_ML_KEM_768) && defined(HAVE_CURVE448)
246+
if ((size_t)end - (size_t)begin == 12) {
247+
if (XSTRNCMP(begin, "X448MLKEM768", 12) == 0) {
248+
available = 1;
249+
}
250+
}
251+
#endif /* !WOLFSSL_NO_ML_KEM_768 && HAVE_CURVE448 */
252+
#if !defined(WOLFSSL_NO_ML_KEM_1024) && defined(HAVE_ECC521)
253+
if ((size_t)end - (size_t)begin == 18) {
254+
if (XSTRNCMP(begin, "SecP521r1MLKEM1024", 18) == 0) {
255+
available = 1;
256+
}
257+
}
258+
#endif /* !WOLFSSL_NO_ML_KEM_1024 */
259+
#endif /* !WOLFSSL_NO_ML_KEM */
260+
#ifdef WOLFSSL_MLKEM_KYBER
205261
if ((size_t)end - (size_t)begin == 12) {
206262
#ifndef WOLFSSL_NO_KYBER512
207263
if (XSTRNCMP(begin, "KYBER_LEVEL1", 12) == 0) {
@@ -219,7 +275,8 @@ static int IsKyberLevelAvailable(const char* line)
219275
}
220276
#endif
221277
}
222-
#endif
278+
#endif /* WOLFSSL_MLKEM_KYBER */
279+
(void) end;
223280
}
224281

225282
#if defined(WOLFSSL_MLKEM_NO_MAKE_KEY) || \
@@ -910,7 +967,7 @@ int SuiteTest(int argc, char** argv)
910967
char* myArgv[3];
911968

912969
#ifdef WOLFSSL_STATIC_MEMORY
913-
byte memory[200000];
970+
byte memory[320000];
914971
#endif
915972

916973
printf(" Begin Cipher Suite Tests\n");

wolfssl/ssl.h

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4750,16 +4750,15 @@ enum {
47504750
WOLFSSL_P256_KYBER_LEVEL3 = 25498,
47514751
#endif /* WOLFSSL_MLKEM_KYBER */
47524752
#ifndef WOLFSSL_NO_ML_KEM
4753-
/* Taken from draft-connolly-tls-mlkem-key-agreement, see:
4754-
* https://github.com/dconnolly/draft-connolly-tls-mlkem-key-agreement/
4753+
/* Taken from draft-ietf-tls-mlkem, see:
4754+
* https://datatracker.ietf.org/doc/draft-ietf-tls-mlkem/07/
47554755
*/
47564756
WOLFSSL_ML_KEM_512 = 512,
47574757
WOLFSSL_ML_KEM_768 = 513,
47584758
WOLFSSL_ML_KEM_1024 = 514,
47594759

4760-
/* Taken from draft-kwiatkowski-tls-ecdhe-mlkem. see:
4761-
* https://github.com/post-quantum-cryptography/
4762-
* draft-kwiatkowski-tls-ecdhe-mlkem/
4760+
/* Taken from draft-ietf-tls-ecdhe-mlkem. see:
4761+
* https://datatracker.ietf.org/doc/draft-ietf-tls-ecdhe-mlkem/04/
47634762
*/
47644763
WOLFSSL_SECP256R1MLKEM768 = 4587,
47654764
WOLFSSL_X25519MLKEM768 = 4588,

wolfssl/wolfcrypt/memory.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,25 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf,
175175
#define WOLFMEM_BUCKETS 64,128,256,512,1024,8192,32768,\
176176
65536,LARGEST_MEM_BUCKET
177177
#endif
178+
#elif defined(WOLFSSL_HAVE_MLKEM)
179+
/* extra storage in structs for multiple attributes and order */
180+
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,4096,8192,\
181+
LARGEST_MEM_BUCKET
178182
#else
179183
/* default size of chunks of memory to separate into */
180184
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\
181185
LARGEST_MEM_BUCKET
182186
#endif
183187
#elif defined(OPENSSL_EXTRA)
184-
/* extra storage in structs for multiple attributes and order */
185-
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,\
186-
LARGEST_MEM_BUCKET
188+
#ifdef WOLFSSL_HAVE_MLKEM
189+
/* extra storage in structs for multiple attributes and order */
190+
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,4096,8192,\
191+
LARGEST_MEM_BUCKET
192+
#else
193+
/* extra storage in structs for multiple attributes and order */
194+
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3360,4480,\
195+
LARGEST_MEM_BUCKET
196+
#endif
187197
#elif defined(WOLFSSL_CERT_EXT)
188198
#define WOLFMEM_BUCKETS 64,128,256,512,1024,2432,3456,4544,\
189199
LARGEST_MEM_BUCKET
@@ -204,7 +214,7 @@ WOLFSSL_API int wolfSSL_GetAllocators(wolfSSL_Malloc_cb* mf,
204214
#define WOLFMEM_DIST 30,10,8,15,8,10,8,5,1
205215
#endif
206216
#elif !defined(WOLFSSL_STATIC_MEMORY_SMALL)
207-
#define WOLFMEM_DIST 49,10,6,14,5,6,9,1,1
217+
#define WOLFMEM_DIST 49,10,6,14,5,6,14,1,1
208218
#else
209219
/* Low resource and not RSA */
210220
#define WOLFMEM_DIST 29, 7,6, 9,4,4,0,0,0

wolfssl/wolfcrypt/settings.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4549,10 +4549,9 @@ extern void uITRON4_free(void *p) ;
45494549
#define WOLFSSL_DILITHIUM_VERIFY_NO_MALLOC
45504550
#endif
45514551

4552-
#if defined(HAVE_PQC) && defined(WOLFSSL_DTLS13) && \
4553-
!defined(WOLFSSL_DTLS_CH_FRAG)
4554-
#warning "Using DTLS 1.3 + pqc without WOLFSSL_DTLS_CH_FRAG will probably" \
4555-
"fail.Use --enable-dtls-frag-ch to enable it."
4552+
#if defined(HAVE_PQC) && defined(WOLFSSL_HAVE_MLKEM) && \
4553+
defined(WOLFSSL_DTLS13) && !defined(WOLFSSL_DTLS_CH_FRAG)
4554+
#define WOLFSSL_DTLS_CH_FRAG
45564555
#endif
45574556
#if !defined(WOLFSSL_DTLS13) && defined(WOLFSSL_DTLS_CH_FRAG)
45584557
#error "WOLFSSL_DTLS_CH_FRAG only works with DTLS 1.3"

0 commit comments

Comments
 (0)