Skip to content

Commit 93000e5

Browse files
authored
Merge pull request wolfSSL#8467 from SparkiDev/kyber_improv_2
ML-KEM/Kyber: improvements
2 parents 539056e + 82b50f1 commit 93000e5

File tree

20 files changed

+6323
-4693
lines changed

20 files changed

+6323
-4693
lines changed

.github/workflows/pq-all.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
matrix:
1919
config: [
2020
# Add new configs here
21-
'--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-kyber=all,original --enable-lms --enable-xmss --enable-dilithium --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST"'
21+
'--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-kyber=yes,original --enable-lms --enable-xmss --enable-dilithium --enable-dual-alg-certs --disable-qt CPPFLAGS="-pedantic -DWOLFCRYPT_TEST_LINT -DNO_WOLFSSL_CIPHER_SUITE_TEST"'
2222
]
2323
name: make check
2424
if: github.repository_owner == 'wolfssl'

.wolfssl_known_macro_extras

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ WOLFSSL_KEIL
665665
WOLFSSL_KEIL_NET
666666
WOLFSSL_KYBER_INVNTT_UNROLL
667667
WOLFSSL_KYBER_NO_LARGE_CODE
668+
WOLFSSL_KYBER_NO_MALLOC
668669
WOLFSSL_KYBER_NTT_UNROLL
669670
WOLFSSL_LIB
670671
WOLFSSL_LMS_CACHE_BITS
@@ -800,6 +801,8 @@ WOLFSSL_TLS13_IGNORE_AEAD_LIMITS
800801
WOLFSSL_TLS13_MIDDLEBOX_COMPAT
801802
WOLFSSL_TLS13_SHA512
802803
WOLFSSL_TLS13_TICKET_BEFORE_FINISHED
804+
WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY
805+
WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
803806
WOLFSSL_TRACK_MEMORY_FULL
804807
WOLFSSL_TRAP_MALLOC_SZ
805808
WOLFSSL_UNALIGNED_64BIT_ACCESS

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2510,6 +2510,7 @@ if(WOLFSSL_EXAMPLES)
25102510
tests/api/test_ripemd.c
25112511
tests/api/test_hash.c
25122512
tests/api/test_ascon.c
2513+
tests/api/test_mlkem.c
25132514
tests/api/test_ocsp.c
25142515
tests/hash.c
25152516
tests/srp.c

configure.ac

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,13 +1405,19 @@ AC_ARG_ENABLE([kyber],
14051405

14061406
ENABLED_WC_KYBER=no
14071407
ENABLED_ML_KEM=unset
1408+
ENABLED_KYBER_MAKE_KEY=no
1409+
ENABLED_KYBER_ENCAPSULATE=no
1410+
ENABLED_KYBER_DECAPSULATE=no
14081411
for v in `echo $ENABLED_KYBER | tr "," " "`
14091412
do
14101413
case $v in
1411-
yes | all)
1414+
yes)
14121415
ENABLED_KYBER512=yes
14131416
ENABLED_KYBER768=yes
14141417
ENABLED_KYBER1024=yes
1418+
ENABLED_KYBER_MAKE_KEY=yes
1419+
ENABLED_KYBER_ENCAPSULATE=yes
1420+
ENABLED_KYBER_DECAPSULATE=yes
14151421
;;
14161422
no)
14171423
;;
@@ -1430,6 +1436,20 @@ do
14301436
1024)
14311437
ENABLED_KYBER1024=yes
14321438
;;
1439+
make)
1440+
ENABLED_KYBER_MAKE_KEY=yes
1441+
;;
1442+
encapsulate|enc)
1443+
ENABLED_KYBER_ENCAPSULATE=yes
1444+
;;
1445+
decapsulate|dec)
1446+
ENABLED_KYBER_DECAPSULATE=yes
1447+
;;
1448+
all)
1449+
ENABLED_KYBER_MAKE_KEY=yes
1450+
ENABLED_KYBER_ENCAPSULATE=yes
1451+
ENABLED_KYBER_DECAPSULATE=yes
1452+
;;
14331453
original)
14341454
ENABLED_ORIGINAL=yes
14351455
;;
@@ -1483,6 +1503,15 @@ then
14831503
else
14841504
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_NO_ML_KEM"
14851505
fi
1506+
if test "$ENABLED_KYBER_MAKE_KEY" = "no"; then
1507+
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KYBER_NO_MAKE_KEY"
1508+
fi
1509+
if test "$ENABLED_KYBER_ENCAPSULATE" = "no"; then
1510+
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KYBER_NO_ENCAPSULATE"
1511+
fi
1512+
if test "$ENABLED_KYBER_DECAPSULATE" = "no"; then
1513+
AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_KYBER_NO_DECAPSULATE"
1514+
fi
14861515

14871516
if test "$ENABLED_WC_KYBER" = "yes"
14881517
then

src/tls.c

Lines changed: 87 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8192,6 +8192,19 @@ static void findEccPqc(int *ecc, int *pqc, int group)
81928192
}
81938193
}
81948194

8195+
#if defined(WOLFSSL_MLKEM_CACHE_A) && \
8196+
!defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY)
8197+
/* Store KyberKey object rather than private key bytes in key share entry.
8198+
* Improves performance at cost of more dynamic memory being used. */
8199+
#define WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
8200+
#endif
8201+
#if defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY) && \
8202+
defined(WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ)
8203+
#error "Choose WOLFSSL_TLSX_PQC_MLKEM_STORE_PRIV_KEY or "
8204+
"WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ"
8205+
#endif
8206+
8207+
#ifndef WOLFSSL_KYBER_NO_MAKE_KEY
81958208
/* Create a key share entry using liboqs parameters group.
81968209
* Generates a key pair.
81978210
*
@@ -8203,13 +8216,17 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82038216
{
82048217
int ret = 0;
82058218
int type = 0;
8219+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
82068220
KyberKey kem[1];
8207-
byte* pubKey = NULL;
82088221
byte* privKey = NULL;
8222+
word32 privSz = 0;
8223+
#else
8224+
KyberKey* kem;
8225+
#endif
8226+
byte* pubKey = NULL;
82098227
KeyShareEntry *ecc_kse = NULL;
82108228
int oqs_group = 0;
82118229
int ecc_group = 0;
8212-
word32 privSz = 0;
82138230
word32 pubSz = 0;
82148231

82158232
/* This gets called twice. Once during parsing of the key share and once
@@ -8226,12 +8243,47 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82268243
ret = BAD_FUNC_ARG;
82278244
}
82288245

8246+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
8247+
if (ret == 0) {
8248+
ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
8249+
if (ret != 0) {
8250+
WOLFSSL_MSG("Failed to initialize Kyber Key.");
8251+
}
8252+
}
8253+
8254+
if (ret == 0) {
8255+
ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
8256+
}
8257+
if (ret == 0) {
8258+
ret = wc_KyberKey_PublicKeySize(kem, &pubSz);
8259+
}
8260+
8261+
if (ret == 0) {
8262+
privKey = (byte*)XMALLOC(privSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
8263+
if (privKey == NULL) {
8264+
WOLFSSL_MSG("privkey memory allocation failure");
8265+
ret = MEMORY_ERROR;
8266+
}
8267+
}
8268+
#else
8269+
if (ret == 0) {
8270+
kem = (KyberKey*)XMALLOC(sizeof(KyberKey), ssl->heap,
8271+
DYNAMIC_TYPE_PRIVATE_KEY);
8272+
if (kem == NULL) {
8273+
WOLFSSL_MSG("KEM memory allocation failure");
8274+
ret = MEMORY_ERROR;
8275+
}
8276+
}
82298277
if (ret == 0) {
82308278
ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
82318279
if (ret != 0) {
82328280
WOLFSSL_MSG("Failed to initialize Kyber Key.");
82338281
}
82348282
}
8283+
if (ret == 0) {
8284+
ret = wc_KyberKey_PublicKeySize(kem, &pubSz);
8285+
}
8286+
#endif
82358287

82368288
if (ret == 0) {
82378289
ecc_kse = (KeyShareEntry*)XMALLOC(sizeof(*ecc_kse), ssl->heap,
@@ -8244,11 +8296,6 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82448296

82458297
if (ret == 0) {
82468298
XMEMSET(ecc_kse, 0, sizeof(*ecc_kse));
8247-
8248-
ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
8249-
}
8250-
if (ret == 0) {
8251-
ret = wc_KyberKey_PublicKeySize(kem, &pubSz);
82528299
}
82538300

82548301
if (ret == 0 && ecc_group != 0) {
@@ -8266,14 +8313,6 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82668313
}
82678314
}
82688315

8269-
if (ret == 0) {
8270-
privKey = (byte*)XMALLOC(privSz, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
8271-
if (privKey == NULL) {
8272-
WOLFSSL_MSG("privkey memory allocation failure");
8273-
ret = MEMORY_ERROR;
8274-
}
8275-
}
8276-
82778316
if (ret == 0) {
82788317
ret = wc_KyberKey_MakeKey(kem, ssl->rng);
82798318
if (ret != 0) {
@@ -8284,9 +8323,11 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82848323
ret = wc_KyberKey_EncodePublicKey(kem, pubKey + ecc_kse->pubKeyLen,
82858324
pubSz);
82868325
}
8326+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
82878327
if (ret == 0) {
82888328
ret = wc_KyberKey_EncodePrivateKey(kem, privKey, privSz);
82898329
}
8330+
#endif
82908331
if (ret == 0) {
82918332
if (ecc_kse->pubKeyLen > 0)
82928333
XMEMCPY(pubKey, ecc_kse->pubKey, ecc_kse->pubKeyLen);
@@ -8298,9 +8339,15 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
82988339
* separately. That's because the ECC private key is not simply a
82998340
* buffer. Its is an ecc_key struct. Typically do not need the private
83008341
* key size, but will need to zero it out upon freeing. */
8342+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
83018343
kse->privKey = privKey;
83028344
privKey = NULL;
83038345
kse->privKeyLen = privSz;
8346+
#else
8347+
kse->privKey = (byte*)kem;
8348+
kem = NULL;
8349+
kse->privKeyLen = sizeof(KyberKey);
8350+
#endif
83048351

83058352
kse->key = ecc_kse->key;
83068353
ecc_kse->key = NULL;
@@ -8314,10 +8361,15 @@ static int TLSX_KeyShare_GenPqcKey(WOLFSSL *ssl, KeyShareEntry* kse)
83148361
wc_KyberKey_Free(kem);
83158362
TLSX_KeyShare_FreeAll(ecc_kse, ssl->heap);
83168363
XFREE(pubKey, ssl->heap, DYNAMIC_TYPE_PUBLIC_KEY);
8364+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
83178365
XFREE(privKey, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
8366+
#else
8367+
XFREE(kem, ssl->heap, DYNAMIC_TYPE_PRIVATE_KEY);
8368+
#endif
83188369

83198370
return ret;
83208371
}
8372+
#endif
83218373
#endif /* WOLFSSL_HAVE_KYBER */
83228374

83238375
/* Generate a secret/key using the key share entry.
@@ -8335,7 +8387,7 @@ int TLSX_KeyShare_GenKey(WOLFSSL *ssl, KeyShareEntry *kse)
83358387
ret = TLSX_KeyShare_GenX25519Key(ssl, kse);
83368388
else if (kse->group == WOLFSSL_ECC_X448)
83378389
ret = TLSX_KeyShare_GenX448Key(ssl, kse);
8338-
#ifdef WOLFSSL_HAVE_KYBER
8390+
#if defined(WOLFSSL_HAVE_KYBER) && !defined(WOLFSSL_KYBER_NO_MAKE_KEY)
83398391
else if (WOLFSSL_NAMED_GROUP_IS_PQC(kse->group))
83408392
ret = TLSX_KeyShare_GenPqcKey(ssl, kse);
83418393
#endif
@@ -8382,6 +8434,9 @@ static void TLSX_KeyShare_FreeAll(KeyShareEntry* list, void* heap)
83828434
current->pubKey = NULL;
83838435
if (current->privKey != NULL) {
83848436
ForceZero(current->privKey, current->privKeyLen);
8437+
#ifdef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
8438+
wc_KyberKey_Free((KyberKey*)current->privKey);
8439+
#endif
83858440
XFREE(current->privKey, heap, DYNAMIC_TYPE_PRIVATE_KEY);
83868441
current->privKey = NULL;
83878442
}
@@ -8920,7 +8975,7 @@ static int TLSX_KeyShare_ProcessEcc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
89208975
return ret;
89218976
}
89228977

8923-
#ifdef WOLFSSL_HAVE_KYBER
8978+
#if defined(WOLFSSL_HAVE_KYBER) && !defined(WOLFSSL_KYBER_NO_DECAPSULATE)
89248979
/* Process the Kyber key share extension on the client side.
89258980
*
89268981
* ssl The SSL/TLS object.
@@ -8931,14 +8986,18 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
89318986
{
89328987
int ret = 0;
89338988
int type;
8989+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
89348990
KyberKey kem[1];
8991+
word32 privSz = 0;
8992+
#else
8993+
KyberKey* kem;
8994+
#endif
89358995
byte* sharedSecret = NULL;
89368996
word32 sharedSecretLen = 0;
89378997
int oqs_group = 0;
89388998
int ecc_group = 0;
89398999
ecc_key eccpubkey;
89409000
word32 outlen = 0;
8941-
word32 privSz = 0;
89429001
word32 ctSz = 0;
89439002
word32 ssSz = 0;
89449003

@@ -8981,12 +9040,17 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
89819040
return BAD_FUNC_ARG;
89829041
}
89839042

9043+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
89849044
ret = wc_KyberKey_Init(type, kem, ssl->heap, ssl->devId);
89859045
if (ret != 0) {
89869046
wc_ecc_free(&eccpubkey);
89879047
WOLFSSL_MSG("Error creating Kyber KEM");
89889048
return MEMORY_E;
89899049
}
9050+
#else
9051+
kem = (KyberKey*)keyShareEntry->privKey;
9052+
keyShareEntry->privKey = NULL;
9053+
#endif
89909054

89919055
if (ret == 0) {
89929056
ret = wc_KyberKey_SharedSecretSize(kem, &ssSz);
@@ -9021,12 +9085,14 @@ static int TLSX_KeyShare_ProcessPqc(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
90219085
if (ret == 0) {
90229086
ret = wc_KyberKey_CipherTextSize(kem, &ctSz);
90239087
}
9088+
#ifndef WOLFSSL_TLSX_PQC_MLKEM_STORE_OBJ
90249089
if (ret == 0) {
90259090
ret = wc_KyberKey_PrivateKeySize(kem, &privSz);
90269091
}
90279092
if (ret == 0) {
90289093
ret = wc_KyberKey_DecodePrivateKey(kem, keyShareEntry->privKey, privSz);
90299094
}
9095+
#endif
90309096
if (ret == 0) {
90319097
ret = wc_KyberKey_Decapsulate(kem, sharedSecret + outlen,
90329098
keyShareEntry->ke + keyShareEntry->keLen - ctSz, ctSz);
@@ -9113,7 +9179,7 @@ static int TLSX_KeyShare_Process(WOLFSSL* ssl, KeyShareEntry* keyShareEntry)
91139179
ret = TLSX_KeyShare_ProcessX25519(ssl, keyShareEntry);
91149180
else if (keyShareEntry->group == WOLFSSL_ECC_X448)
91159181
ret = TLSX_KeyShare_ProcessX448(ssl, keyShareEntry);
9116-
#ifdef WOLFSSL_HAVE_KYBER
9182+
#if defined(WOLFSSL_HAVE_KYBER) && !defined(WOLFSSL_KYBER_NO_DECAPSULATE)
91179183
else if (WOLFSSL_NAMED_GROUP_IS_PQC(keyShareEntry->group))
91189184
ret = TLSX_KeyShare_ProcessPqc(ssl, keyShareEntry);
91199185
#endif
@@ -9437,7 +9503,7 @@ static int TLSX_KeyShare_New(KeyShareEntry** list, int group, void *heap,
94379503
return 0;
94389504
}
94399505

9440-
#ifdef WOLFSSL_HAVE_KYBER
9506+
#if defined(WOLFSSL_HAVE_KYBER) && !defined(WOLFSSL_KYBER_NO_ENCAPSULATE)
94419507
static int server_generate_pqc_ciphertext(WOLFSSL* ssl,
94429508
KeyShareEntry* keyShareEntry, byte* data, word16 len)
94439509
{
@@ -9643,7 +9709,7 @@ int TLSX_KeyShare_Use(const WOLFSSL* ssl, word16 group, word16 len, byte* data,
96439709
}
96449710

96459711

9646-
#ifdef WOLFSSL_HAVE_KYBER
9712+
#if defined(WOLFSSL_HAVE_KYBER) && !defined(WOLFSSL_KYBER_NO_ENCAPSULATE)
96479713
if (WOLFSSL_NAMED_GROUP_IS_PQC(group) &&
96489714
ssl->options.side == WOLFSSL_SERVER_END) {
96499715
ret = server_generate_pqc_ciphertext((WOLFSSL*)ssl, keyShareEntry, data,

0 commit comments

Comments
 (0)