From d1d1e689ea6b0fdb300b44787e868b5f1c541695 Mon Sep 17 00:00:00 2001 From: Dev10-sys Date: Thu, 22 Oct 2026 11:34:28 +0530 Subject: [PATCH] Initialized remote certificates and optional extension fields (#473) The documented API contract for nx_secure_tls_remote_certificate_allocate states that caller passes an uninitialized NX_SECURE_X509_CERT structure instance. However, nx_secure_tls_remote_certificate_allocate only assigned the raw buffer pointers and user allocation flag without clearing the certificate structure first. In addition, _nx_secure_x509_certificate_parse did not clear optional fields (extensions data and unique identifiers) when parsing certificates where those blocks are absent, such as X.509 v1 or v2 certificates or reused structures. When an uninitialized or non-zeroed certificate was allocated, nx_secure_x509_extensions_data and nx_secure_x509_extensions_data_length retained uninitialized memory. During certificate verification of self-signed certificates or issuer chains, _nx_secure_x509_key_usage_extension_parse called _nx_secure_x509_extension_find, which attempted to parse ASN.1 TLV blocks from the stale pointer in _nx_secure_x509_asn1_tlv_block_parse, triggering a BusFault/segmentation fault. This fix zeroes the certificate structure in _nx_secure_tls_remote_certificate_allocate before populating fields, explicitly initializes optional extension and identifier fields to NULL and zero in _nx_secure_x509_certificate_parse, and guards _nx_secure_x509_extension_find against NULL or zero-length extension data. A test case in nx_secure_x509_parse_test verifies clean handling for certificates without extensions and non-zeroed initial memory. Signed-off-by: Dev10-sys --- ...x_secure_tls_remote_certificate_allocate.c | 5 ++- nx_secure/src/nx_secure_x509.c | 8 ++++ nx_secure/src/nx_secure_x509_extension_find.c | 6 +++ .../nx_secure_x509_parse_test.c | 37 +++++++++++++++++++ 4 files changed, 55 insertions(+), 1 deletion(-) diff --git a/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c b/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c index a61a36068..38ff6f961 100644 --- a/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c +++ b/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c @@ -85,11 +85,14 @@ UINT status; tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); + /* Clear the certificate structure. */ + NX_SECURE_MEMSET(certificate, 0, sizeof(NX_SECURE_X509_CERT)); + certificate -> nx_secure_x509_certificate_raw_data = raw_certificate_buffer; certificate -> nx_secure_x509_certificate_raw_buffer_size = buffer_size; /* This certificate was allocated by the user application and not by TLS. */ - certificate->nx_secure_x509_user_allocated_cert = NX_TRUE; + certificate -> nx_secure_x509_user_allocated_cert = NX_TRUE; /* Add the certificate to the TLS session credentials X509 store. */ status = _nx_secure_x509_store_certificate_add(certificate, &tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, diff --git a/nx_secure/src/nx_secure_x509.c b/nx_secure/src/nx_secure_x509.c index e7f46f9a3..eb447b7d3 100644 --- a/nx_secure/src/nx_secure_x509.c +++ b/nx_secure/src/nx_secure_x509.c @@ -165,6 +165,14 @@ UINT status; return(NX_CRYPTO_PTR_ERROR); } + /* Initialize optional fields to NULL/0. */ + cert -> nx_secure_x509_issuer_identifier = NX_CRYPTO_NULL; + cert -> nx_secure_x509_issuer_identifier_length = 0; + cert -> nx_secure_x509_subject_identifier = NX_CRYPTO_NULL; + cert -> nx_secure_x509_subject_identifier_length = 0; + cert -> nx_secure_x509_extensions_data = NX_CRYPTO_NULL; + cert -> nx_secure_x509_extensions_data_length = 0; + /* Parse a TLV block and get information to continue parsing. */ status = _nx_secure_x509_asn1_tlv_block_parse(buffer, (ULONG *)&length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); diff --git a/nx_secure/src/nx_secure_x509_extension_find.c b/nx_secure/src/nx_secure_x509_extension_find.c index 64c458718..43db18c40 100644 --- a/nx_secure/src/nx_secure_x509_extension_find.c +++ b/nx_secure/src/nx_secure_x509_extension_find.c @@ -98,6 +98,12 @@ UINT found_extension = NX_CRYPTO_FALSE; current_buffer = certificate -> nx_secure_x509_extensions_data; extensions_sequence_length = certificate -> nx_secure_x509_extensions_data_length; + /* Make sure extensions data is present. */ + if (current_buffer == NX_CRYPTO_NULL || extensions_sequence_length == 0) + { + return(NX_SECURE_X509_EXTENSION_NOT_FOUND); + } + /* Keep looping until we run out of data to parse. */ while (extensions_sequence_length > 0) { diff --git a/test/regression/nx_secure_test/nx_secure_x509_parse_test.c b/test/regression/nx_secure_test/nx_secure_x509_parse_test.c index c6e21289c..22bc61c43 100644 --- a/test/regression/nx_secure_test/nx_secure_x509_parse_test.c +++ b/test/regression/nx_secure_test/nx_secure_x509_parse_test.c @@ -6398,6 +6398,10 @@ TEST(NX_SECURE_X509, X509_version_1_test) NX_SECURE_X509_CERT certificate; NX_SECURE_X509_DISTINGUISHED_NAME expected_name; UINT status; +#ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK +USHORT key_usage_bitfield = 0; +#endif +UINT bytes_processed; memset(&certificate, 0, sizeof(certificate)); @@ -6447,6 +6451,39 @@ UINT status; EXPECT_EQ(NX_SECURE_TLS_X509_TYPE_RSA_MD5, certificate.nx_secure_x509_signature_algorithm); EXPECT_EQ(NX_SECURE_X509_VERSION_1, certificate.nx_secure_x509_version); + + EXPECT_TRUE(certificate.nx_secure_x509_extensions_data == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_extensions_data_length); + EXPECT_TRUE(certificate.nx_secure_x509_issuer_identifier == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_issuer_identifier_length); + EXPECT_TRUE(certificate.nx_secure_x509_subject_identifier == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_subject_identifier_length); + +#ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK + status = _nx_secure_x509_key_usage_extension_parse(&certificate, &key_usage_bitfield); + EXPECT_EQ(NX_SECURE_X509_EXTENSION_NOT_FOUND, status); +#endif + + /* Test that _nx_secure_x509_certificate_parse clears stale optional fields when re-parsing. */ + certificate.nx_secure_x509_extensions_data = (const UCHAR *)"stale_extension"; + certificate.nx_secure_x509_extensions_data_length = 0x1234; + certificate.nx_secure_x509_issuer_identifier = (const UCHAR *)"stale_issuer"; + certificate.nx_secure_x509_issuer_identifier_length = 0x5678; + certificate.nx_secure_x509_subject_identifier = (const UCHAR *)"stale_subject"; + certificate.nx_secure_x509_subject_identifier_length = 0x9ABC; + + status = _nx_secure_x509_certificate_parse(x509_version_1_ca_cert_der, x509_version_1_ca_cert_der_len, &bytes_processed, &certificate); + EXPECT_EQ(0, status); + EXPECT_TRUE(certificate.nx_secure_x509_extensions_data == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_extensions_data_length); + EXPECT_TRUE(certificate.nx_secure_x509_issuer_identifier == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_issuer_identifier_length); + EXPECT_TRUE(certificate.nx_secure_x509_subject_identifier == NX_CRYPTO_NULL); + EXPECT_EQ(0, certificate.nx_secure_x509_subject_identifier_length); +#ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK + status = _nx_secure_x509_key_usage_extension_parse(&certificate, &key_usage_bitfield); + EXPECT_EQ(NX_SECURE_X509_EXTENSION_NOT_FOUND, status); +#endif } TEST(NX_SECURE_X509, RSA_parse_test)