@@ -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)
94419507static 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