summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrédéric Desbiens <[email protected]>2026-05-28 09:29:10 -0400
committerGitHub <[email protected]>2026-05-28 09:29:10 -0400
commitde51ca2129a4e2822fa3937e1ffdafff2435aafc (patch)
tree7381adf54dc12a0ad9c3f08931ad959af0901324
parentd3688d073425e3854a8c90c26737f275fe546824 (diff)
Fixed issues in the PSK implementation (#386)
* Fixed server PSK identity selection for ECDHE-PSK * Fixed selected client PSK identity preservation Implemented logic to cache the PSK store entry selected by the server identity hint so ClientKeyExchange emits the matching identity when clients use the PSK store path. Cast the ECC supported-group test value to USHORT so the PSK identity regression builds cleanly with -Werror on Linux. Assisted-By: Codex (OpenAI GPT-5.5) <[email protected]>
-rw-r--r--nx_secure/src/nx_secure_generate_client_key_exchange.c46
-rw-r--r--nx_secure/src/nx_secure_generate_premaster_secret.c180
-rw-r--r--nx_secure/src/nx_secure_process_client_key_exchange.c55
-rw-r--r--test/cmake/nx_secure/regression/CMakeLists.txt1
-rw-r--r--test/regression/nx_secure_test/nx_secure_tls_psk_identity_test.c348
5 files changed, 611 insertions, 19 deletions
diff --git a/nx_secure/src/nx_secure_generate_client_key_exchange.c b/nx_secure/src/nx_secure_generate_client_key_exchange.c
index 0af26746..694694e4 100644
--- a/nx_secure/src/nx_secure_generate_client_key_exchange.c
+++ b/nx_secure/src/nx_secure_generate_client_key_exchange.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Codex gpt-5.5.
+
/**************************************************************************/
/**************************************************************************/
@@ -124,15 +126,40 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
{
data_size = (UINT)(1 + tls_key_material -> nx_secure_tls_new_key_material_data[0]);
- if ((data_size > sizeof(tls_key_material -> nx_secure_tls_new_key_material_data)) ||
- (data_size > buffer_length))
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+ if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
{
+ if ((tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size >
+ sizeof(tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id)) ||
+ (data_size > sizeof(tls_key_material -> nx_secure_tls_new_key_material_data)) ||
+ (((ULONG)data_size + 2u + tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size) > buffer_length))
+ {
- /* Packet buffer too small. */
- return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
+ /* Packet buffer too small. */
+ return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
+ }
+
+ data_buffer[0] = (UCHAR)((tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size & 0xFF00) >> 8);
+ data_buffer[1] = (UCHAR)(tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size & 0x00FF);
+ NX_SECURE_MEMCPY(&data_buffer[2], tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id,
+ tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size); /* Use case of memcpy is verified. */
+ NX_SECURE_MEMCPY(&data_buffer[2 + tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size],
+ tls_key_material -> nx_secure_tls_new_key_material_data, data_size); /* Use case of memcpy is verified. */
+ data_size += 2 + tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size;
}
+ else
+#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
+ {
+ if ((data_size > sizeof(tls_key_material -> nx_secure_tls_new_key_material_data)) ||
+ (data_size > buffer_length))
+ {
- NX_SECURE_MEMCPY(data_buffer, tls_key_material -> nx_secure_tls_new_key_material_data, data_size); /* Use case of memcpy is verified. */
+ /* Packet buffer too small. */
+ return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL);
+ }
+
+ NX_SECURE_MEMCPY(data_buffer, tls_key_material -> nx_secure_tls_new_key_material_data, data_size); /* Use case of memcpy is verified. */
+ }
}
else
#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
@@ -145,10 +172,10 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
/* Check for PSK ciphersuites. */
if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
{
- if ((tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint_size >
- sizeof(tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint)) ||
- (tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint_size >
- (buffer_length - 2)))
+ if ((tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size >
+ sizeof(tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id)) ||
+ ((buffer_length < 2u) || (tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size >
+ (buffer_length - 2u))))
{
/* Packet buffer too small. */
@@ -327,4 +354,3 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output;
return(NX_SECURE_TLS_SUCCESS);
}
-
diff --git a/nx_secure/src/nx_secure_generate_premaster_secret.c b/nx_secure/src/nx_secure_generate_premaster_secret.c
index dea98428..63f35692 100644
--- a/nx_secure/src/nx_secure_generate_premaster_secret.c
+++ b/nx_secure/src/nx_secure_generate_premaster_secret.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Codex gpt-5.5.
+
/**************************************************************************/
/**************************************************************************/
@@ -24,6 +26,141 @@
#include "nx_secure_tls.h"
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_secure_tls_psk_identity_lookup PORTABLE C */
+/* 6.x */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX Contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function searches the PSK store for an entry matching a peer */
+/* PSK identity. */
+/* */
+/* INPUT */
+/* */
+/* tls_credentials TLS credentials */
+/* psk_data Destination for PSK data */
+/* psk_length Destination for PSK length */
+/* psk_identity PSK identity data */
+/* identity_length PSK identity length */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Get TLS protection */
+/* tx_mutex_put Release TLS protection */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_secure_generate_premaster_secret Generate pre-master secret */
+/* */
+/**************************************************************************/
+static UINT _nx_secure_tls_psk_identity_lookup(NX_SECURE_TLS_CREDENTIALS *tls_credentials, UCHAR **psk_data, UINT *psk_length,
+ UCHAR *psk_identity, UINT identity_length)
+{
+UINT psk_list_size;
+UINT i;
+
+ /* Get the protection. */
+ tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
+
+ psk_list_size = tls_credentials -> nx_secure_tls_psk_count;
+
+ /* Loop through all PSKs, looking for a matching identity string. */
+ for (i = 0; i < psk_list_size; ++i)
+ {
+ if (identity_length == tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_id_size)
+ {
+ if (NX_SECURE_MEMCMP(tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_id,
+ psk_identity, identity_length) == 0)
+ {
+ *psk_data = tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_data;
+ *psk_length = tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_data_size;
+
+ /* Release the protection. */
+ tx_mutex_put(&_nx_secure_tls_protection);
+
+ return(NX_SUCCESS);
+ }
+ }
+ }
+
+ /* Release the protection. */
+ tx_mutex_put(&_nx_secure_tls_protection);
+
+ return(NX_SECURE_TLS_NO_MATCHING_PSK);
+}
+
+/**************************************************************************/
+/* */
+/* FUNCTION RELEASE */
+/* */
+/* _nx_secure_tls_client_psk_save PORTABLE C */
+/* 6.x */
+/* AUTHOR */
+/* */
+/* Eclipse ThreadX Contributors */
+/* */
+/* DESCRIPTION */
+/* */
+/* This function saves the PSK store entry selected by the server */
+/* identity hint so the client sends the matching identity in */
+/* ClientKeyExchange. */
+/* */
+/* INPUT */
+/* */
+/* tls_credentials TLS credentials */
+/* psk_store_index Selected PSK store index */
+/* */
+/* OUTPUT */
+/* */
+/* status Completion status */
+/* */
+/* CALLS */
+/* */
+/* tx_mutex_get Get TLS protection */
+/* tx_mutex_put Release TLS protection */
+/* */
+/* CALLED BY */
+/* */
+/* _nx_secure_generate_premaster_secret Generate pre-master secret */
+/* */
+/**************************************************************************/
+static UINT _nx_secure_tls_client_psk_save(NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT psk_store_index)
+{
+UINT status;
+
+ /* Get the protection. */
+ tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER);
+
+ if (psk_store_index < tls_credentials -> nx_secure_tls_psk_count)
+ {
+ NX_SECURE_MEMCPY(&tls_credentials -> nx_secure_tls_client_psk,
+ &tls_credentials -> nx_secure_tls_psk_store[psk_store_index],
+ sizeof(NX_SECURE_TLS_PSK_STORE)); /* Use case of memcpy is verified. */
+ status = NX_SUCCESS;
+ }
+ else
+ {
+ status = NX_SECURE_TLS_NO_MATCHING_PSK;
+ }
+
+ /* Release the protection. */
+ tx_mutex_put(&_nx_secure_tls_protection);
+
+ return(status);
+}
+#endif
+
/**************************************************************************/
/* */
/* FUNCTION RELEASE */
@@ -80,6 +217,7 @@ UINT status = NX_SECURE_TLS_SUCCESS;
UCHAR *psk_data;
UINT psk_length;
UINT index;
+UINT psk_store_index;
#endif
#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
NX_SECURE_X509_CERT *server_certificate;
@@ -125,9 +263,24 @@ UINT pre_master_secret_size;
containing the length of the PSK (in octets), and the PSK itself.
*/
- /* Client has to search for the PSK based on the identity hint. */
- status = _nx_secure_tls_psk_find(tls_credentials, &psk_data, &psk_length, tls_credentials -> nx_secure_tls_remote_psk_id,
- tls_credentials -> nx_secure_tls_remote_psk_id_size, NX_NULL);
+ if (session_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
+ {
+ /* Server searches for the PSK based on the identity requested by the client. */
+ status = _nx_secure_tls_psk_identity_lookup(tls_credentials, &psk_data, &psk_length,
+ tls_credentials -> nx_secure_tls_remote_psk_id,
+ tls_credentials -> nx_secure_tls_remote_psk_id_size);
+ }
+ else
+ {
+ /* Client has to search for the PSK based on the identity hint. */
+ status = _nx_secure_tls_psk_find(tls_credentials, &psk_data, &psk_length,
+ tls_credentials -> nx_secure_tls_remote_psk_id,
+ tls_credentials -> nx_secure_tls_remote_psk_id_size, &psk_store_index);
+ if (status == NX_SUCCESS)
+ {
+ status = _nx_secure_tls_client_psk_save(tls_credentials, psk_store_index);
+ }
+ }
if (status != NX_SUCCESS)
{
@@ -280,20 +433,32 @@ UINT pre_master_secret_size;
/* Now, using the identity as a key, find the PSK in our PSK store. */
if (session_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)
{
- /* Server just uses its PSK. */
- psk_data = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data;
- psk_length = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data_size;
+ /* Server searches for the PSK based on the identity requested by the client. */
+ status = _nx_secure_tls_psk_identity_lookup(tls_credentials, &psk_data, &psk_length,
+ tls_credentials -> nx_secure_tls_remote_psk_id,
+ tls_credentials -> nx_secure_tls_remote_psk_id_size);
+
+ if (status != NX_SUCCESS)
+ {
+ return(status);
+ }
}
else
{
/* Client has to search for the PSK based on the identity hint. */
status = _nx_secure_tls_psk_find(tls_credentials, &psk_data, &psk_length, tls_credentials -> nx_secure_tls_remote_psk_id,
- tls_credentials -> nx_secure_tls_remote_psk_id_size, NX_NULL);
+ tls_credentials -> nx_secure_tls_remote_psk_id_size, &psk_store_index);
if (status != NX_SUCCESS)
{
return(status);
}
+
+ status = _nx_secure_tls_client_psk_save(tls_credentials, psk_store_index);
+ if (status != NX_SUCCESS)
+ {
+ return(status);
+ }
}
/* From RFC 4279:
@@ -369,4 +534,3 @@ UINT pre_master_secret_size;
return(status);
}
-
diff --git a/nx_secure/src/nx_secure_process_client_key_exchange.c b/nx_secure/src/nx_secure_process_client_key_exchange.c
index 97fd37d6..5e608abc 100644
--- a/nx_secure/src/nx_secure_process_client_key_exchange.c
+++ b/nx_secure/src/nx_secure_process_client_key_exchange.c
@@ -9,6 +9,8 @@
* SPDX-License-Identifier: MIT
**************************************************************************/
+// Some portions generated by Codex gpt-5.5.
+
/**************************************************************************/
/**************************************************************************/
@@ -93,6 +95,10 @@ UINT _nx_secure_process_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO
USHORT length;
#endif
UINT status = NX_SECURE_TLS_UNEXPECTED_MESSAGE;
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+UINT psk_identity_length;
+UINT generate_psk_secret;
+#endif
#if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || !defined(NX_SECURE_DISABLE_X509)
const NX_CRYPTO_METHOD *public_cipher_method;
#endif
@@ -176,8 +182,37 @@ UINT private_key_length;
#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
/* Check for PSK ciphersuites and generate the pre-master-secret. */
+ generate_psk_secret = NX_FALSE;
if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK)
{
+ if (message_length < 2)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
+ psk_identity_length = (UINT)((packet_buffer[0] << 8) | packet_buffer[1]);
+ if ((psk_identity_length > NX_SECURE_TLS_MAX_PSK_ID_SIZE) ||
+ ((psk_identity_length + 2u) > message_length))
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
+ NX_SECURE_MEMCPY(tls_credentials -> nx_secure_tls_remote_psk_id, &packet_buffer[2], psk_identity_length); /* Use case of memcpy is verified. */
+ tls_credentials -> nx_secure_tls_remote_psk_id_size = psk_identity_length;
+ packet_buffer = &packet_buffer[2 + psk_identity_length];
+ message_length -= psk_identity_length + 2u;
+ generate_psk_secret = NX_TRUE;
+
+#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
+ if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
+ {
+ generate_psk_secret = NX_FALSE;
+ }
+#endif
+ }
+
+ if (generate_psk_secret == NX_TRUE)
+ {
status = _nx_secure_generate_premaster_secret(ciphersuite, protocol_version, tls_key_material, tls_credentials,
NX_SECURE_TLS_SESSION_TYPE_SERVER, received_remote_credentials,
public_cipher_metadata, public_cipher_metadata_size, tls_ecc_curves);
@@ -193,6 +228,11 @@ UINT private_key_length;
if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH ||
ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)
{
+ if (message_length < 1)
+ {
+ return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH);
+ }
+
length = packet_buffer[0];
if ((UINT)length + 1 > message_length)
@@ -334,6 +374,20 @@ UINT private_key_length;
return(status);
}
}
+
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+ if ((ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) &&
+ (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE))
+ {
+ status = _nx_secure_generate_premaster_secret(ciphersuite, protocol_version, tls_key_material, tls_credentials,
+ NX_SECURE_TLS_SESSION_TYPE_SERVER, received_remote_credentials,
+ public_cipher_metadata, public_cipher_metadata_size, tls_ecc_curves);
+ if (status != NX_SUCCESS)
+ {
+ return(status);
+ }
+ }
+#endif
}
else
#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE && !NX_SECURE_DISABLE_X509 */
@@ -579,4 +633,3 @@ UINT private_key_length;
return(status);
}
-
diff --git a/test/cmake/nx_secure/regression/CMakeLists.txt b/test/cmake/nx_secure/regression/CMakeLists.txt
index d14c1a99..f6b5f070 100644
--- a/test/cmake/nx_secure/regression/CMakeLists.txt
+++ b/test/cmake/nx_secure/regression/CMakeLists.txt
@@ -13,6 +13,7 @@ set(nx_secure_test_cases
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_finished_hash_generate_coverage_test.c
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_generate_keys_coverage_test.c
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_generate_premaster_secret_coverage_test.c
+ ${SOURCE_DIR}/nx_secure_test/nx_secure_tls_psk_identity_test.c
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_handshake_hash_init_coverage_test.c
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_ecc_generate_keys_coverage_test.c
${SOURCE_DIR}/nx_secure_test/nx_secure_tls_session_renegotiate_coverage_test.c
diff --git a/test/regression/nx_secure_test/nx_secure_tls_psk_identity_test.c b/test/regression/nx_secure_test/nx_secure_tls_psk_identity_test.c
new file mode 100644
index 00000000..6e297ec0
--- /dev/null
+++ b/test/regression/nx_secure_test/nx_secure_tls_psk_identity_test.c
@@ -0,0 +1,348 @@
+/***************************************************************************
+ * Copyright (C) 2026 Eclipse ThreadX contributors
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the MIT License which is available at
+ * https://opensource.org/licenses/MIT.
+ *
+ * AI Disclosure: This file was largely AI-generated by Codex gpt-5.5.
+ * The AI-generated portions may be considered public domain (CC0-1.0)
+ * and not subject to the project's licence. The human contributor has
+ * reviewed and verified that the code is correct.
+ *
+ * SPDX-License-Identifier: MIT and CC0-1.0
+ **************************************************************************/
+
+#include <stdio.h>
+#include <string.h>
+
+#include "nx_secure_tls.h"
+#include "nx_crypto.h"
+#include "tls_test_utility.h"
+
+extern void test_control_return(UINT status);
+
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+static UCHAR psk_one[] = {0x11};
+static UCHAR psk_two[] = {0x22, 0x33, 0x44};
+static UCHAR psk_id_one[] = "first";
+static UCHAR psk_id_two[] = "second";
+static UCHAR psk_hint[] = "hint";
+static UCHAR ecdhe_public_key[] = {0xAA, 0xBB, 0xCC};
+static UCHAR ecdhe_shared_secret[] = {0x55, 0x66, 0x77, 0x88};
+
+static NX_CRYPTO_METHOD crypto_method_test_null =
+{
+ NX_CRYPTO_ENCRYPTION_NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL
+};
+
+static NX_CRYPTO_METHOD crypto_method_test_psk =
+{
+ NX_CRYPTO_KEY_EXCHANGE_PSK,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL
+};
+
+static NX_SECURE_TLS_CIPHERSUITE_INFO psk_ciphersuite =
+{
+ TLS_PSK_WITH_AES_128_CBC_SHA256,
+ &crypto_method_test_null,
+ &crypto_method_test_psk,
+ &crypto_method_test_null,
+ 0,
+ 0,
+ &crypto_method_test_null,
+ 0,
+ &crypto_method_test_null
+};
+
+/* Store two PSKs so the tests can verify that the requested identity selects a non-zero store entry. */
+static VOID psk_credentials_setup(NX_SECURE_TLS_CREDENTIALS *credentials)
+{
+
+ memset(credentials, 0, sizeof(NX_SECURE_TLS_CREDENTIALS));
+
+ credentials -> nx_secure_tls_psk_count = 2;
+
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data, psk_one, sizeof(psk_one));
+ credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_data_size = sizeof(psk_one);
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id, psk_id_one, sizeof(psk_id_one) - 1u);
+ credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_size = sizeof(psk_id_one) - 1u;
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint, psk_hint, sizeof(psk_hint) - 1u);
+ credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint_size = sizeof(psk_hint) - 1u;
+
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_data, psk_two, sizeof(psk_two));
+ credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_data_size = sizeof(psk_two);
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_id, psk_id_two, sizeof(psk_id_two) - 1u);
+ credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_id_size = sizeof(psk_id_two) - 1u;
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_id_hint, psk_hint, sizeof(psk_hint) - 1u);
+ credentials -> nx_secure_tls_psk_store[1].nx_secure_tls_psk_id_hint_size = sizeof(psk_hint) - 1u;
+
+ NX_SECURE_MEMCPY(credentials -> nx_secure_tls_remote_psk_id, psk_id_two, sizeof(psk_id_two) - 1u);
+ credentials -> nx_secure_tls_remote_psk_id_size = sizeof(psk_id_two) - 1u;
+}
+
+/* Validate that a plain PSK premaster uses the client-requested PSK identity. */
+static VOID plain_psk_identity_test(VOID)
+{
+NX_SECURE_TLS_CREDENTIALS credentials;
+NX_SECURE_TLS_KEY_MATERIAL key_material;
+USHORT received_remote_credentials = NX_FALSE;
+UINT status;
+
+ psk_credentials_setup(&credentials);
+ memset(&key_material, 0, sizeof(key_material));
+
+ status = _nx_secure_generate_premaster_secret(&psk_ciphersuite, NX_SECURE_TLS_VERSION_TLS_1_2,
+ &key_material, &credentials,
+ NX_SECURE_TLS_SESSION_TYPE_SERVER,
+ &received_remote_credentials,
+ NX_NULL, 0, NX_NULL);
+ EXPECT_EQ(NX_SECURE_TLS_SUCCESS, status);
+ EXPECT_EQ(NX_TRUE, received_remote_credentials);
+ EXPECT_EQ((UINT)(2u + sizeof(psk_two) + 2u + sizeof(psk_two)), key_material.nx_secure_tls_pre_master_secret_size);
+ EXPECT_EQ(0, key_material.nx_secure_tls_pre_master_secret[0]);
+ EXPECT_EQ(sizeof(psk_two), key_material.nx_secure_tls_pre_master_secret[1]);
+ EXPECT_EQ(0, NX_SECURE_MEMCMP(&key_material.nx_secure_tls_pre_master_secret[2u + sizeof(psk_two) + 2u], psk_two, sizeof(psk_two)));
+
+ NX_SECURE_MEMCPY(credentials.nx_secure_tls_remote_psk_id, psk_hint, sizeof(psk_hint) - 1u);
+ credentials.nx_secure_tls_remote_psk_id_size = sizeof(psk_hint) - 1u;
+ status = _nx_secure_generate_premaster_secret(&psk_ciphersuite, NX_SECURE_TLS_VERSION_TLS_1_2,
+ &key_material, &credentials,
+ NX_SECURE_TLS_SESSION_TYPE_SERVER,
+ &received_remote_credentials,
+ NX_NULL, 0, NX_NULL);
+ EXPECT_EQ(NX_SECURE_TLS_NO_MATCHING_PSK, status);
+}
+
+/* Validate ClientKeyExchange PSK identity bounds checking for plain PSK. */
+static VOID plain_psk_client_key_exchange_length_test(VOID)
+{
+NX_SECURE_TLS_CREDENTIALS credentials;
+NX_SECURE_TLS_KEY_MATERIAL key_material;
+USHORT received_remote_credentials = NX_FALSE;
+UCHAR truncated_identity[] = {0x00, 0x06, 's', 'e'};
+UINT status;
+
+ psk_credentials_setup(&credentials);
+ memset(&key_material, 0, sizeof(key_material));
+
+ status = _nx_secure_process_client_key_exchange(&psk_ciphersuite, NX_SECURE_TLS_VERSION_TLS_1_2,
+ truncated_identity, sizeof(truncated_identity),
+ &received_remote_credentials, &key_material, &credentials,
+ NX_NULL, 0, NX_NULL, 0, NX_NULL);
+ EXPECT_EQ(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH, status);
+}
+
+#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE
+#ifndef NX_SECURE_DISABLE_X509
+static UINT test_ecdhe_operation(UINT op, VOID *handler, NX_CRYPTO_METHOD *method,
+ UCHAR *key, NX_CRYPTO_KEY_SIZE key_size_in_bits,
+ UCHAR *input, ULONG input_length_in_byte,
+ UCHAR *iv_ptr, UCHAR *output, ULONG output_length_in_byte,
+ VOID *crypto_metadata, ULONG crypto_metadata_size,
+ VOID *packet_ptr,
+ VOID (*nx_crypto_hw_process_callback)(VOID *packet_ptr, UINT status))
+{
+NX_CRYPTO_EXTENDED_OUTPUT *extended_output;
+
+ NX_PARAMETER_NOT_USED(handler);
+ NX_PARAMETER_NOT_USED(method);
+ NX_PARAMETER_NOT_USED(key);
+ NX_PARAMETER_NOT_USED(key_size_in_bits);
+ NX_PARAMETER_NOT_USED(iv_ptr);
+ NX_PARAMETER_NOT_USED(output_length_in_byte);
+ NX_PARAMETER_NOT_USED(crypto_metadata);
+ NX_PARAMETER_NOT_USED(crypto_metadata_size);
+ NX_PARAMETER_NOT_USED(packet_ptr);
+ NX_PARAMETER_NOT_USED(nx_crypto_hw_process_callback);
+
+ if ((op == NX_CRYPTO_EC_CURVE_SET) || (op == NX_CRYPTO_DH_KEY_PAIR_IMPORT))
+ {
+ return(NX_CRYPTO_SUCCESS);
+ }
+
+ if (op == NX_CRYPTO_DH_CALCULATE)
+ {
+ if ((input_length_in_byte != sizeof(ecdhe_public_key)) ||
+ (NX_SECURE_MEMCMP(input, ecdhe_public_key, sizeof(ecdhe_public_key)) != 0))
+ {
+ return(NX_CRYPTO_NOT_SUCCESSFUL);
+ }
+
+ extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output;
+ if (extended_output -> nx_crypto_extended_output_length_in_byte < sizeof(ecdhe_shared_secret))
+ {
+ return(NX_CRYPTO_NOT_SUCCESSFUL);
+ }
+
+ NX_SECURE_MEMCPY(extended_output -> nx_crypto_extended_output_data, ecdhe_shared_secret, sizeof(ecdhe_shared_secret));
+ extended_output -> nx_crypto_extended_output_actual_size = sizeof(ecdhe_shared_secret);
+ return(NX_CRYPTO_SUCCESS);
+ }
+
+ return(NX_CRYPTO_NOT_SUCCESSFUL);
+}
+
+static NX_CRYPTO_METHOD crypto_method_test_ecdhe =
+{
+ NX_CRYPTO_KEY_EXCHANGE_ECDHE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL,
+ test_ecdhe_operation
+};
+
+static NX_CRYPTO_METHOD crypto_method_test_curve =
+{
+ NX_CRYPTO_EC_SECP256R1,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL,
+ NX_CRYPTO_NULL
+};
+
+static NX_SECURE_TLS_CIPHERSUITE_INFO ecdhe_psk_ciphersuite =
+{
+ TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA,
+ &crypto_method_test_ecdhe,
+ &crypto_method_test_psk,
+ &crypto_method_test_null,
+ 0,
+ 0,
+ &crypto_method_test_null,
+ 0,
+ &crypto_method_test_null
+};
+
+/* Validate that ECDHE-PSK parses identity before public key and appends the selected PSK. */
+static VOID ecdhe_psk_client_key_exchange_test(VOID)
+{
+NX_SECURE_TLS_CREDENTIALS credentials;
+NX_SECURE_TLS_KEY_MATERIAL key_material;
+NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data;
+NX_SECURE_TLS_ECC ecc;
+const NX_CRYPTO_METHOD *curves[1];
+USHORT groups[1];
+USHORT received_remote_credentials = NX_FALSE;
+UCHAR client_key_exchange[2u + sizeof(psk_id_two) - 1u + 1u + sizeof(ecdhe_public_key)];
+UINT offset;
+UINT status;
+
+ psk_credentials_setup(&credentials);
+ memset(&key_material, 0, sizeof(key_material));
+
+ ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)key_material.nx_secure_tls_new_key_material_data;
+ ecdhe_data -> nx_secure_tls_ecdhe_named_curve = NX_CRYPTO_EC_SECP256R1;
+ ecdhe_data -> nx_secure_tls_ecdhe_private_key[0] = 1;
+ ecdhe_data -> nx_secure_tls_ecdhe_private_key_length = 1;
+
+ groups[0] = (USHORT)NX_CRYPTO_EC_SECP256R1;
+ curves[0] = &crypto_method_test_curve;
+ ecc.nx_secure_tls_ecc_supported_groups = groups;
+ ecc.nx_secure_tls_ecc_supported_groups_count = 1;
+ ecc.nx_secure_tls_ecc_curves = curves;
+
+ offset = 0;
+ client_key_exchange[offset++] = 0;
+ client_key_exchange[offset++] = (UCHAR)(sizeof(psk_id_two) - 1u);
+ NX_SECURE_MEMCPY(&client_key_exchange[offset], psk_id_two, sizeof(psk_id_two) - 1u);
+ offset += sizeof(psk_id_two) - 1u;
+ client_key_exchange[offset++] = sizeof(ecdhe_public_key);
+ NX_SECURE_MEMCPY(&client_key_exchange[offset], ecdhe_public_key, sizeof(ecdhe_public_key));
+ offset += sizeof(ecdhe_public_key);
+
+ status = _nx_secure_process_client_key_exchange(&ecdhe_psk_ciphersuite, NX_SECURE_TLS_VERSION_TLS_1_2,
+ client_key_exchange, offset,
+ &received_remote_credentials, &key_material, &credentials,
+ NX_NULL, 0, NX_NULL, 0, &ecc);
+ EXPECT_EQ(NX_SECURE_TLS_SUCCESS, status);
+ EXPECT_EQ(NX_TRUE, received_remote_credentials);
+ EXPECT_EQ((UINT)(2u + sizeof(ecdhe_shared_secret) + 2u + sizeof(psk_two)), key_material.nx_secure_tls_pre_master_secret_size);
+ EXPECT_EQ(sizeof(ecdhe_shared_secret), key_material.nx_secure_tls_pre_master_secret[1]);
+ EXPECT_EQ(0, NX_SECURE_MEMCMP(&key_material.nx_secure_tls_pre_master_secret[2], ecdhe_shared_secret, sizeof(ecdhe_shared_secret)));
+ EXPECT_EQ(sizeof(psk_two), key_material.nx_secure_tls_pre_master_secret[2u + sizeof(ecdhe_shared_secret) + 1u]);
+ EXPECT_EQ(0, NX_SECURE_MEMCMP(&key_material.nx_secure_tls_pre_master_secret[2u + sizeof(ecdhe_shared_secret) + 2u], psk_two, sizeof(psk_two)));
+}
+
+/* Validate that ECDHE-PSK client messages include the PSK identity before the EC public key. */
+static VOID ecdhe_psk_client_key_exchange_generate_test(VOID)
+{
+NX_SECURE_TLS_CREDENTIALS credentials;
+NX_SECURE_TLS_KEY_MATERIAL key_material;
+UCHAR output[32];
+ULONG output_size = 0;
+UINT status;
+
+ memset(&credentials, 0, sizeof(credentials));
+ memset(&key_material, 0, sizeof(key_material));
+ NX_SECURE_MEMCPY(credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id, psk_id_two, sizeof(psk_id_two) - 1u);
+ credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_size = sizeof(psk_id_two) - 1u;
+ key_material.nx_secure_tls_new_key_material_data[0] = sizeof(ecdhe_public_key);
+ NX_SECURE_MEMCPY(&key_material.nx_secure_tls_new_key_material_data[1], ecdhe_public_key, sizeof(ecdhe_public_key));
+
+ status = _nx_secure_generate_client_key_exchange(&ecdhe_psk_ciphersuite, &key_material, &credentials,
+ output, sizeof(output), &output_size,
+ NX_NULL, 0, NX_NULL, 0);
+ EXPECT_EQ(NX_SECURE_TLS_SUCCESS, status);
+ EXPECT_EQ((ULONG)(2u + sizeof(psk_id_two) - 1u + 1u + sizeof(ecdhe_public_key)), output_size);
+ EXPECT_EQ(0, output[0]);
+ EXPECT_EQ(sizeof(psk_id_two) - 1u, output[1]);
+ EXPECT_EQ(0, NX_SECURE_MEMCMP(&output[2], psk_id_two, sizeof(psk_id_two) - 1u));
+ EXPECT_EQ(sizeof(ecdhe_public_key), output[2u + sizeof(psk_id_two) - 1u]);
+ EXPECT_EQ(0, NX_SECURE_MEMCMP(&output[2u + sizeof(psk_id_two)], ecdhe_public_key, sizeof(ecdhe_public_key)));
+}
+#endif /* NX_SECURE_DISABLE_X509 */
+#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */
+#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */
+
+#ifdef CTEST
+void test_application_define(void *first_unused_memory);
+void test_application_define(void *first_unused_memory)
+#else
+void nx_secure_tls_psk_identity_test_application_define(void *first_unused_memory)
+#endif
+{
+
+ NX_PARAMETER_NOT_USED(first_unused_memory);
+
+ printf("NetX Secure Test: TLS PSK Identity Test...............................");
+
+#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES
+ nx_system_initialize();
+ nx_secure_tls_initialize();
+ plain_psk_identity_test();
+ plain_psk_client_key_exchange_length_test();
+#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_DISABLE_X509)
+ ecdhe_psk_client_key_exchange_test();
+ ecdhe_psk_client_key_exchange_generate_test();
+#endif
+ printf("SUCCESS!\n");
+#else
+ printf("N/A\n");
+#endif
+
+ test_control_return(0);
+}