diff options
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); +} |
