Skip to content

Commit a51b40b

Browse files
authored
Merge pull request #9968 from Frauschi/mlkem_fixes
ML-KEM fixes
2 parents e023c17 + 10b9873 commit a51b40b

12 files changed

Lines changed: 252 additions & 71 deletions

File tree

.github/workflows/pq-all.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ jobs:
2727
'--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem --enable-lms --enable-xmss --enable-slhdsa --enable-dilithium --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ"',
2828
'--disable-intelasm --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem,small --enable-lms=yes,small --enable-xmss=yes,small --enable-slhdsa=yes,small --enable-dilithium=yes,small --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_MLKEM_MAKEKEY_SMALL_MEM -DWOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM -DWOLFSSL_MLKEM_NO_LARGE_CODE -DWOLFSSL_DILITHIUM_SIGN_SMALL_MEM -DWOLFSSL_DILITHIUM_VERIFY_SMALL_MEM -DWOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM -DWOLFSSL_DILITHIUM_NO_LARGE_CODE"',
2929
'--disable-intelasm --enable-smallstack --enable-smallstackcache --enable-all --enable-testcert --enable-acert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-quic --with-sys-crypto-policy --enable-experimental --enable-mlkem=yes,kyber,ml-kem,small --enable-lms=yes,small --enable-xmss=yes,small --enable-slhdsa=yes,small --enable-dilithium=yes,small --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE -DWOLFSSL_MLKEM_MAKEKEY_SMALL_MEM -DWOLFSSL_MLKEM_ENCAPSULATE_SMALL_MEM -DWOLFSSL_MLKEM_NO_LARGE_CODE -DWOLFSSL_DILITHIUM_SIGN_SMALL_MEM -DWOLFSSL_DILITHIUM_VERIFY_SMALL_MEM -DWOLFSSL_DILITHIUM_MAKE_KEY_SMALL_MEM -DWOLFSSL_DILITHIUM_NO_LARGE_CODE"',
30+
'--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,512 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
31+
'--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,768 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
32+
'--enable-intelasm --enable-sp-asm --enable-all --enable-testcert --enable-dtls13 --enable-dtls-mtu --enable-dtls-frag-ch --enable-dtlscid --enable-mlkem=make,enc,dec,1024 --disable-qt CPPFLAGS="-pedantic -Wdeclaration-after-statement -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST -DTEST_LIBWOLFSSL_SOURCES_INCLUSION_SEQUENCE"',
3033
]
3134
name: make check
3235
if: github.repository_owner == 'wolfssl'

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: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10534,6 +10534,7 @@ static int TLSX_KeyShare_HandlePqcKeyServer(WOLFSSL* ssl,
1053410534
keyShareEntry->ke = NULL;
1053510535
keyShareEntry->keLen = 0;
1053610536

10537+
XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1053710538
keyShareEntry->pubKey = ciphertext;
1053810539
keyShareEntry->pubKeyLen = ctSz;
1053910540
ciphertext = NULL;
@@ -10770,6 +10771,7 @@ static int TLSX_KeyShare_HandlePqcHybridKeyServer(WOLFSSL* ssl,
1077010771
XMEMCPY(ciphertext + ecc_kse->pubKeyLen, pqc_kse->pubKey, ctSz);
1077110772
}
1077210773

10774+
XFREE(keyShareEntry->pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
1077310775
keyShareEntry->pubKey = ciphertext;
1077410776
keyShareEntry->pubKeyLen = ecc_kse->pubKeyLen + ctSz;
1077510777
ciphertext = NULL;
@@ -10859,21 +10861,35 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data,
1085910861
#if defined(WOLFSSL_HAVE_MLKEM) && !defined(WOLFSSL_MLKEM_NO_ENCAPSULATE)
1086010862
if (ssl->options.side == WOLFSSL_SERVER_END &&
1086110863
WOLFSSL_NAMED_GROUP_IS_PQC(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;
10864+
if (TLSX_IsGroupSupported(group)) {
10865+
ret = TLSX_KeyShare_HandlePqcKeyServer((WOLFSSL*)ssl,
10866+
keyShareEntry,
10867+
data, len,
10868+
ssl->arrays->preMasterSecret,
10869+
&ssl->arrays->preMasterSz);
10870+
if (ret != 0)
10871+
return ret;
10872+
}
10873+
else {
10874+
XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10875+
keyShareEntry->ke = NULL;
10876+
keyShareEntry->keLen = 0;
10877+
}
1086910878
}
1087010879
else if (ssl->options.side == WOLFSSL_SERVER_END &&
1087110880
WOLFSSL_NAMED_GROUP_IS_PQC_HYBRID(group)) {
10872-
ret = TLSX_KeyShare_HandlePqcHybridKeyServer((WOLFSSL*)ssl,
10873-
keyShareEntry,
10874-
data, len);
10875-
if (ret != 0)
10876-
return ret;
10881+
if (TLSX_IsGroupSupported(group)) {
10882+
ret = TLSX_KeyShare_HandlePqcHybridKeyServer((WOLFSSL*)ssl,
10883+
keyShareEntry,
10884+
data, len);
10885+
if (ret != 0)
10886+
return ret;
10887+
}
10888+
else {
10889+
XFREE(keyShareEntry->ke, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
10890+
keyShareEntry->ke = NULL;
10891+
keyShareEntry->keLen = 0;
10892+
}
1087710893
}
1087810894
else
1087910895
#endif

tests/api.c

Lines changed: 24 additions & 10 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
@@ -32014,7 +32015,7 @@ static int test_dtls13_frag_ch_pq(void)
3201432015
{
3201532016
EXPECT_DECLS;
3201632017
#if defined(HAVE_MANUAL_MEMIO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS13) \
32017-
&& defined(WOLFSSL_DTLS_CH_FRAG) && defined(HAVE_LIBOQS)
32018+
&& defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_HAVE_MLKEM)
3201832019
WOLFSSL_CTX *ctx_c = NULL;
3201932020
WOLFSSL_CTX *ctx_s = NULL;
3202032021
WOLFSSL *ssl_c = NULL;
@@ -32023,10 +32024,28 @@ static int test_dtls13_frag_ch_pq(void)
3202332024
const char *test_str = "test";
3202432025
int test_str_size;
3202532026
byte buf[255];
32026-
#ifdef WOLFSSL_MLKEM_KYBER
32027+
#if defined(WOLFSSL_MLKEM_KYBER)
32028+
#if !defined(WOLFSSL_NO_KYBER1024)
3202732029
int group = WOLFSSL_KYBER_LEVEL5;
32030+
const char *group_name = "KYBER_LEVEL5";
32031+
#elif !defined(WOLFSSL_NO_KYBER768)
32032+
int group = WOLFSSL_KYBER_LEVEL3;
32033+
const char *group_name = "KYBER_LEVEL3";
32034+
#else
32035+
int group = WOLFSSL_KYBER_LEVEL1;
32036+
const char *group_name = "KYBER_LEVEL1";
32037+
#endif
3202832038
#else
32039+
#if !defined(WOLFSSL_NO_ML_KEM_1024)
3202932040
int group = WOLFSSL_ML_KEM_1024;
32041+
const char *group_name = "ML_KEM_1024";
32042+
#elif !defined(WOLFSSL_NO_ML_KEM_768)
32043+
int group = WOLFSSL_ML_KEM_768;
32044+
const char *group_name = "ML_KEM_768";
32045+
#else
32046+
int group = WOLFSSL_ML_KEM_512;
32047+
const char *group_name = "ML_KEM_512";
32048+
#endif
3203032049
#endif
3203132050

3203232051
XMEMSET(&test_ctx, 0, sizeof(test_ctx));
@@ -32037,13 +32056,8 @@ static int test_dtls13_frag_ch_pq(void)
3203732056
ExpectIntEQ(wolfSSL_UseKeyShare(ssl_c, group), WOLFSSL_SUCCESS);
3203832057
ExpectIntEQ(wolfSSL_dtls13_allow_ch_frag(ssl_s, 1), WOLFSSL_SUCCESS);
3203932058
ExpectIntEQ(test_memio_do_handshake(ssl_c, ssl_s, 10, NULL), 0);
32040-
#ifdef WOLFSSL_MLKEM_KYBER
32041-
ExpectStrEQ(wolfSSL_get_curve_name(ssl_c), "KYBER_LEVEL5");
32042-
ExpectStrEQ(wolfSSL_get_curve_name(ssl_s), "KYBER_LEVEL5");
32043-
#else
32044-
ExpectStrEQ(wolfSSL_get_curve_name(ssl_c), "ML_KEM_1024");
32045-
ExpectStrEQ(wolfSSL_get_curve_name(ssl_s), "ML_KEM_1024");
32046-
#endif
32059+
ExpectStrEQ(wolfSSL_get_curve_name(ssl_c), group_name);
32060+
ExpectStrEQ(wolfSSL_get_curve_name(ssl_s), group_name);
3204732061
test_str_size = XSTRLEN("test") + 1;
3204832062
ExpectIntEQ(wolfSSL_write(ssl_c, test_str, test_str_size), test_str_size);
3204932063
ExpectIntEQ(wolfSSL_read(ssl_s, buf, sizeof(buf)), test_str_size);

tests/api/test_tls13.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,15 @@ int test_tls13_apis(void)
149149
":P256_KYBER_LEVEL1"
150150
#elif !defined(WOLFSSL_NO_KYBER768)
151151
":P256_KYBER_LEVEL3"
152-
#else
152+
#elif !defined(WOLFSSL_NO_KYBER1024)
153153
":P256_KYBER_LEVEL5"
154154
#endif
155155
#else
156-
#ifndef WOLFSSL_NO_KYBER512
156+
#ifndef WOLFSSL_NO_ML_KEM_512
157157
":SecP256r1MLKEM512"
158-
#elif !defined(WOLFSSL_NO_KYBER768)
158+
#elif !defined(WOLFSSL_NO_ML_KEM_768)
159159
":SecP384r1MLKEM768"
160-
#else
160+
#elif !defined(WOLFSSL_NO_ML_KEM_1024)
161161
":SecP521r1MLKEM1024"
162162
#endif
163163
#endif
@@ -173,15 +173,15 @@ int test_tls13_apis(void)
173173
":KYBER_LEVEL1"
174174
#elif !defined(WOLFSSL_NO_KYBER768)
175175
":KYBER_LEVEL3"
176-
#else
176+
#elif !defined(WOLFSSL_NO_KYBER1024)
177177
":KYBER_LEVEL5"
178178
#endif
179179
#else
180-
#ifndef WOLFSSL_NO_KYBER512
180+
#ifndef WOLFSSL_NO_ML_KEM_512
181181
":ML_KEM_512"
182-
#elif !defined(WOLFSSL_NO_KYBER768)
182+
#elif !defined(WOLFSSL_NO_ML_KEM_768)
183183
":ML_KEM_768"
184-
#else
184+
#elif !defined(WOLFSSL_NO_ML_KEM_1024)
185185
":ML_KEM_1024"
186186
#endif
187187
#endif

0 commit comments

Comments
 (0)