summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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);
+}