diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..8dc87bcc --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,35 @@ +--- +name: Bug report +about: Create a report to help us improve Azure RTOS. +title: '' +labels: bug +assignees: '' + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +Please also mention any information which could help others to understand +the problem you're facing: +- What target device are you using? +- Which version of Azure RTOS? +- What toolchain and environment? +- What have you tried to diagnose or workaround this issue? + +**To Reproduce** +Steps to reproduce the behavior: +1. Build my project in IAR Workbench. +1. See error + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Impact** +What impact does this issue have on your progress (e.g., annoyance, showstopper) + +**Logs and console output** +If applicable, add console logs or other types of debug information like Wireshark capture as `.zip` file. + +**Additional context** +Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..0221c220 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea or enhancement to existing feature for Azure RTOS. +title: '' +labels: feature +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. diff --git a/.github/ISSUE_TEMPLATE/hardware-or-architecture-support.md b/.github/ISSUE_TEMPLATE/hardware-or-architecture-support.md new file mode 100644 index 00000000..8ecbd34e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/hardware-or-architecture-support.md @@ -0,0 +1,19 @@ +--- +name: Hardware or architecture support +about: Suggest adding hardware or new architecture support. +title: '' +labels: hardware +assignees: '' + +--- + +**Is this request related to a particular hardware platform, SoC, board? Please describe.** +Describe in details the hardware support being requested and why this support benefits Azure RTOS. + +**Describe why you are asking for this support?** +Describe why you are asking for this support. + +If this is a new board or SoC, please state whether you are willing to maintain the Azure RTOS support together with you. + +**Additional context** +Add any other context or graphics (drag-and-drop an image) about the hardware here. diff --git a/CMakeLists.txt b/CMakeLists.txt index 68d3c8be..527cf996 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,12 @@ cmake_minimum_required(VERSION 3.0.0 FATAL_ERROR) # Set up the project project(netxduo - VERSION 6.0.0 LANGUAGES C ASM ) option(NXD_ENABLE_FILE_SERVERS "Includes a dependency on FileX to support 'server' protocol handlers" ON) +option(NXD_ENABLE_AZURE_IOT "Enable Azure IoT" OFF) +option(NX_AZURE_DISABLE_IOT_SECURITY_MODULE "Disable Azure IoT Security Module" OFF) if(NOT DEFINED THREADX_ARCH) message(FATAL_ERROR "Error: THREADX_ARCH not defined") @@ -39,7 +40,11 @@ endif() set(CUSTOM_INC_DIR ${CMAKE_CURRENT_BINARY_DIR}/custom_inc) # Pick up the port specific stuff first -add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}) +if(DEFINED NETXDUO_CUSTOM_PORT) + add_subdirectory(${NETXDUO_CUSTOM_PORT} netxduo_port) +else() + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}) +endif() # Then the common files add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/common) @@ -51,6 +56,9 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/addons) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/crypto_libraries) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/nx_secure) +# Utility components +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/utility) + # If the user provided an override, copy it to the custom directory if (NOT NX_USER_FILE) message(STATUS "Using default nx_user.h file") diff --git a/LICENSED-HARDWARE.txt b/LICENSED-HARDWARE.txt index ca64a50f..006731c6 100644 --- a/LICENSED-HARDWARE.txt +++ b/LICENSED-HARDWARE.txt @@ -1,6 +1,6 @@ LICENSED HARDWARE LIST -Last Updated: 2020-12-15 +Last Updated: 2021-04-01 Microsoft has entered into OEM Agreements with manufacturers of the following microprocessors and microcontrollers (the “hardware”) to enable those @@ -29,12 +29,15 @@ Microchip: NXP: - NXP i.MX RT10xx series crossover MCUs + i.MX RT10xx and RT116x/7x series crossover MCUs + LPC5500 series + Renesas: Synergy Platform RX Family of MCUs + RA Family of MCUs RZ Family of MPUs -------------------------------------------------------------------------------- diff --git a/README.md b/README.md index 5e2579a4..479e9ea6 100755 --- a/README.md +++ b/README.md @@ -2,98 +2,127 @@ This advanced, industrial-grade TCP/IP network stack is designed specifically for deeply embedded real-time and IoT applications. Azure RTOS NetX Duo is a dual IPv4 and IPv6 network stack, while Azure RTOS NetX is the original IPv4 network stack, essentially a subset of Azure RTOS NetX Duo. -## Documentation +Here are the key features and modules of NetX Duo: -Documentation for this library can be found here: http://docs.microsoft.com/azure/rtos/netx-duo +![NetX Duo Key Features](./docs/netx-duo-features.png) +## Getting Started -## Cloning the repo +Azure RTOS NetX Duo as part of Azure RTOS has been integrated to the semiconductor's SDKs and development environment. You can develop using the tools of choice from [STMicro](https://www.st.com/content/st_com/en/campaigns/x-cube-azrtos-azure-rtos-stm32.html), [NXP](https://www.nxp.com/design/software/embedded-software/azure-rtos-for-nxp-microcontrollers:AZURE-RTOS), [Renesas](https://github.com/renesas/azure-rtos) and [Microchip](https://mu.microchip.com/get-started-simplifying-your-iot-design-with-azure-rtos). -```bash -$ git clone https://github.com/azure-rtos/netxduo.git -$ git submodule update --init -``` +We also provide [getting started guide](https://github.com/azure-rtos/getting-started) and [samples](https://github.com/azure-rtos/samples) using hero development boards from semiconductors you can build and test with. -# Repository Structure and Usage +See [Overview of Azure RTOS NetX Duo](https://learn.microsoft.com/azure/rtos/netx-duo/overview-netx-duo) for the high-level overview, and all documentation and APIs can be found in: [Azure RTOS NetX Duo documentation](https://learn.microsoft.com/azure/rtos/netx-duo/). -## Branches & Releases +Also there is dedicated [learning path of Azure RTOS NetX Duo](https://learn.microsoft.com/training/paths/azure-rtos-netx-duo/) for learning systematically. -The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. +## Repository Structure and Usage -## Releases +### Directory layout -Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.1-rel`. + . + ├── addons # NetX Duo addon modules for protocols and connectivity + ├── cmake # CMakeList files for building the project + ├── common # Core NetX Duo files + ├── crypto_libraries # NetX Crypto files + ├── nx_secure # NetX Secure files + ├── ports # Architecture and compiler specific files + ├── samples # Sample codes + ├── utility # Test cases and utilities (e.g. iperf) + ├── LICENSE.txt # License terms + ├── LICENSE-HARDWARE.txt # Licensed hardware from semiconductors + ├── CONTRIBUTING.md # Contribution guidance + └── SECURITY.md # Microsoft repo security guidance -## Directory layout +### Branches & Releases -``` -- addons - - auto_ip, BSD, azure_iot, dhcp, cloud, dns, ftp, http, mdns, mqtt, nat, pop3, ppp, pppoe, smtp, sntp, telnet, tftp, web -- cmake -- common - - inc - - src -- crypto_libraries - - inc - - src -- nx_secure - - inc - - src -- ports - - cortex_m0/gnu - - inc - - src - - cortex_m3/gnu - - inc - - src - - cortex_m4/gnu - - inc - - src - - cortex_m7/gnu - - inc - - src -- samples -``` +The master branch has the most recent code with all new features and bug fixes. It does not represent the latest General Availability (GA) release of the library. Each official release (preview or GA) will be tagged to mark the commit and push it into the Github releases tab, e.g. `v6.2-rel`. -# Azure IoT +## Protocols and connectivity -NetX Duo includes [Azure IoT Middleware for Azure RTOS](https://github.com/azure-rtos/netxduo/tree/master/addons/azure_iot), a platform specific library that acts as a binding layer between the Azure RTOS and the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c/tree/master/sdk/docs/iot). +Protocols and connectivity support are provided as addon modules within NetX Duo in `addons` folder. Some key modules are: [**azure_iot**](https://github.com/azure-rtos/netxduo/tree/master/addons/azure_iot), [**dhcp**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-dhcp-client/chapter1), [**dns**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-dns/chapter1), [**ftp**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-dns/chapter1), [**http**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-http/chapter1), [**mqtt**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-mqtt/chapter1), [**pop3**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-pop3-client/chapter1), [**lwm2m**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-lwm2m/chapter1), [**ppp**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-ppp/chapter1), [**sntp**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-sntp-client/chapter1), and [**web**](https://learn.microsoft.com/azure/rtos/netx-duo/netx-duo-web-http/chapter1). For a full list of NetX Duo addons, you can find in the same [Azure RTOS NetX Duo documentation](https://learn.microsoft.com/azure/rtos/netx-duo/). -Additional APIs supporting Azure IoT Plug and Play can be found on the [feature/iot_pnp](https://github.com/azure-rtos/netxduo/tree/v6.1_beta.1) branch, with sample projects in the [Beta Release](https://github.com/azure-rtos/netxduo/releases/tag/v6.1_beta.1). +### Samples -# Security +We provide sample codes about how to use various addons in the [`samples`](./samples/) folder. -Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying -MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device -fully meets the evolving security requirements associated with its specific use case. +### Azure IoT Middleware for Azure RTOS -## Azure Defender for IoT security module +[Azure IoT Middleware for Azure RTOS](https://github.com/azure-rtos/netxduo/tree/master/addons/azure_iot) (a.k.a IoT Middleware) is a platform specific library that acts as a binding layer between the Azure RTOS and the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c). It simplifies building device application that connects to Azure IoT services. -The Azure Defender for IoT security module provides a comprehensive security solution for Azure RTOS devices. Azure RTOS now ships with the Defender for IoT security module built-in and provides coverage for common threats and potential malicious activities. The security module is part of the Azure IoT Middleware for Azure RTOS (addons/azure_iot/). As the device connects to Azure IoT hub, Defender for IoT collectors gather network connectivity information and sends it to the Defender for IoT service for analysis. For details on how the security module works and the type of information it collects, refer to [Azure Defender for IoT security module](https://github.com/azure-rtos/netxduo/tree/v6.1_rel/addons/azure_iot/docs#azure-defender-for-iot-module) section in the Azure IoT document. +The IoT Middleware also includes built-in support for: -# Licensing +- **[Device Update for IoT Hub](https://learn.microsoft.com/azure/iot-hub-device-update/device-update-azure-real-time-operating-system)**: an Azure service for IoT devices to enable the over-the-air (OTA) updates easily. +- **[Microsoft Defender for IoT](https://learn.microsoft.com/azure/defender-for-iot/device-builders/iot-security-azure-rtos)**: an Azure service makes IoT devices visibility into security posture management and threat detection, and integrates with other Microsoft tools for unified security management. -License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all -definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined -in the LICENSED-HARDWARE.txt file. If you are using hardware not defined in the LICENSED-HARDWARE.txt file or have -licensing questions in general, please contact Microsoft directly at https://azure-rtos.ms-iot-contact.com/ +## Component dependencies -# Contribution, feedback, issues, and professional support +The main components of Azure RTOS are each provided in their own repository, but there are dependencies between them, as shown in the following graph. This is important to understand when setting up your builds. -If you encounter any bugs, have suggestions for new features, or if you would like to become an active contributor to -this project, please follow the instructions provided in the contribution guideline for the corresponding repo. +![dependency graph](docs/deps.png) -For basic support, click Issues in the command bar or post a question to [Stack Overflow](http://stackoverflow.com/questions/tagged/azure-rtos+threadx) using the `threadx` and `azure-rtos` tags. +> You will have to take the dependency graph above into account when building anything other than ThreadX itself. -Professional support plans (https://azure.microsoft.com/en-us/support/options/) are available from Microsoft. +### Building and using the library -# Additional Resources +Instruction for building the NetX Duo as static library using Arm GNU Toolchain and CMake. If you are using toolchain and IDE from semiconductor, you might follow its own instructions to use Azure RTOS components as explained in the [Getting Started](#getting-started) section. -The following are references to additional Azure RTOS and Azure IoT in general: -| | | -|---|---| -| Azure RTOS Website: | https://azure.microsoft.com/en-us/services/rtos/ | -| Azure RTOS Sales Questions: | https://azure-rtos.ms-iot-contact.com/ | -| Microsoft Q/A for Azure IoT: | https://docs.microsoft.com/en-us/answers/products/azure?product=iot | -| Internet of Things Show: | https://aka.ms/iotshow | -| IoT Tech Community: | https://aka.ms/iottechcommunity | +1. Install the following tools: + + * [CMake](https://cmake.org/download/) version 3.0 or later + * [Arm GNU Toolchain for arm-none-eabi](https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads) + * [Ninja](https://ninja-build.org/) + +1. Build the [ThreadX library](https://github.com/azure-rtos/threadx#building-and-using-the-library) as the dependency. + +1. Cloning the repo. NetX Duo has a couple of dependencies that are included as submodules. + + ```bash + $ git clone --recursive https://github.com/azure-rtos/netxduo.git + ``` + +1. Define the features and addons you need in `nx_user.h` and build together with the component source code. You can refer to [`nx_user_sample.h`](https://github.com/azure-rtos/netxduo/blob/master/common/inc/nx_user_sample.h) as an example. + +1. Building as a static library + + Each component of Azure RTOS comes with a composable CMake-based build system that supports many different MCUs and host systems. Integrating any of these components into your device app code is as simple as adding a git submodule and then including it in your build using the CMake `add_subdirectory()`. + + While the typical usage pattern is to include NetX Duo into your device code source tree to be built & linked with your code, you can compile this project as a standalone static library to confirm your build is set up correctly. + + An example of building the library for Cortex-M4: + + ```bash + $ cmake -Bbuild -GNinja -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_m4.cmake . + + $ cmake --build ./build + ``` + +## Professional support + +[Professional support plans](https://azure.microsoft.com/support/options/) are available from Microsoft. For community support and others, see the [Resources](#resources) section below. + +## Licensing + +License terms for using Azure RTOS are defined in the LICENSE.txt file of this repo. Please refer to this file for all definitive licensing information. No additional license fees are required for deploying Azure RTOS on hardware defined in the [LICENSED-HARDWARE.txt](./LICENSED-HARDWARE.txt) file. If you are using hardware not listed in the file or having licensing questions in general, please contact Microsoft directly at https://aka.ms/azrtos-license. + +## Resources + +The following are references to additional Azure RTOS resources: + +- **Product introduction and white papers**: https://azure.com/rtos +- **General technical questions**: https://aka.ms/QnA/azure-rtos +- **Product issues and bugs, or feature requests**: https://github.com/azure-rtos/netxduo/issues +- **Licensing and sales questions**: https://aka.ms/azrtos-license +- **Product roadmap and support policy**: https://aka.ms/azrtos/lts +- **Blogs and videos**: http://msiotblog.com and https://aka.ms/iotshow +- **Azure RTOS TraceX Installer**: https://aka.ms/azrtos-tracex-installer + +You can also check [previous questions](https://stackoverflow.com/questions/tagged/azure-rtos+netxduo) or ask new ones on StackOverflow using the `azure-rtos` and `netxduo` tags. + +## Security + +Azure RTOS provides OEMs with components to secure communication and to create code and data isolation using underlying MCU/MPU hardware protection mechanisms. It is ultimately the responsibility of the device builder to ensure the device fully meets the evolving security requirements associated with its specific use case. + +## Contribution + +Please follow the instructions provided in the [CONTRIBUTING.md](./CONTRIBUTING.md) for the corresponding repository. diff --git a/addons/BSD/nxd_bsd.c b/addons/BSD/nxd_bsd.c index 62589931..84fe6e61 100644 --- a/addons/BSD/nxd_bsd.c +++ b/addons/BSD/nxd_bsd.c @@ -93,7 +93,7 @@ TX_BLOCK_POOL nx_bsd_socket_block_pool; /* Define the memory area for the socket block pool... use TCP socket size, since it is the larger. */ -static UCHAR nx_bsd_socket_pool_memory[NX_BSD_MAX_SOCKETS*(sizeof(NX_TCP_SOCKET)+sizeof(VOID *))]; +static ULONG nx_bsd_socket_pool_memory[NX_BSD_MAX_SOCKETS * (sizeof(NX_TCP_SOCKET) + sizeof(VOID *)) / sizeof(ULONG)]; /* Define the block pool that will be used to dynamically allocate addrinfo struct. */ @@ -104,8 +104,8 @@ TX_BLOCK_POOL nx_bsd_addrinfo_block_pool; * Every address may be mapped to 3 socktypes, SOCK_STREAM, SOCK_DGRAM and SOCK_RAW, * 3 blocks for addrinfo) + 1 block for IP adddress = 4 blocks */ -static UCHAR nx_bsd_addrinfo_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM)* 4 - *(sizeof(struct addrinfo) + sizeof(VOID *))]; +static ULONG nx_bsd_addrinfo_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * 4 + *(sizeof(struct addrinfo) + sizeof(VOID *)) / sizeof(ULONG)]; #ifdef NX_BSD_ENABLE_DNS @@ -117,8 +117,8 @@ extern NX_DNS *_nx_dns_instance_ptr; TX_BLOCK_POOL nx_bsd_cname_block_pool; /* Here we just support a CNAME per IP address. */ -static UCHAR nx_bsd_cname_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * - (NX_DNS_NAME_MAX + 1)]; +static ULONG nx_bsd_cname_pool_memory[(NX_BSD_IPV4_ADDR_MAX_NUM + NX_BSD_IPV6_ADDR_MAX_NUM) * + (NX_DNS_NAME_MAX + 1) / sizeof(ULONG)]; #endif /* NX_DNS_ENABLE_EXTENDED_RR_TYPES */ #endif /* NX_BSD_ENABLE_DNS */ @@ -8599,7 +8599,7 @@ INT i; /* FUNCTION RELEASE */ /* */ /* nx_bsd_raw_packet_filter PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8639,6 +8639,10 @@ INT i; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed NULL pointer access */ +/* for raw socket, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ static UINT nx_bsd_raw_packet_filter(NX_IP *ip_ptr, ULONG protocol, NX_PACKET *packet_ptr) @@ -8653,6 +8657,13 @@ NX_BSD_SOCKET * bsd_socket_ptr; /* Search the bound sockets in this index for particular protocol. */ bsd_socket_ptr = nx_bsd_socket_raw_protocol_table[index]; + /* Was a BSD socket with this protocol found? */ + if (bsd_socket_ptr == NX_NULL) + { + /* No, let NetX Duo continue processing the packet. */ + return 1; + } + do { /* Determine if the protocol is matched. */ @@ -8726,7 +8737,7 @@ NX_BSD_SOCKET * bsd_socket_ptr; /* Was a BSD socket with this protocol found? */ if (bsd_socket_ptr == nx_bsd_socket_raw_protocol_table[index]) { - /* No, let NetX Duo know it can discard the packet. */ + /* No, let NetX Duo continue processing the packet. */ return 1; } @@ -13566,7 +13577,7 @@ UINT index = 0; /* FUNCTION RELEASE */ /* */ /* getaddrinfo PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13627,6 +13638,9 @@ UINT index = 0; /* verified memcpy use cases, */ /* fixed compiler errors, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ INT getaddrinfo(const CHAR *node, const CHAR *service, const struct addrinfo *hints, struct addrinfo **res) @@ -13761,7 +13775,7 @@ static struct addrinfo default_hints = {0, AF_UNSPEC, 0, 0, 0, NX_NULL, NX_NULL, /* Service is a decimal port number string, and has been converted to a numeric port successfully. */ /* Convert port from host byte order to network byte order. */ - port = htons(port); + port = htons((USHORT)port); } else { diff --git a/addons/BSD/nxd_bsd.h b/addons/BSD/nxd_bsd.h index ae2cd65b..ba4ef7a3 100644 --- a/addons/BSD/nxd_bsd.h +++ b/addons/BSD/nxd_bsd.h @@ -25,7 +25,7 @@ /* BSD DEFINITIONS RELEASE */ /* */ /* nxd_bsd.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -43,6 +43,13 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* defined IP protocols for */ +/* ICMP, IGMP and ICMPv6, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -59,7 +66,9 @@ extern "C" { #endif +#ifndef __CCRX__ #include "time.h" +#endif /* __CCRX__ */ /* Bring in the necessary NetX include file. */ #include "nx_api.h" @@ -188,8 +197,11 @@ extern "C" { #define SOCK_STREAM 1 /* TCP Socket */ #define SOCK_DGRAM 2 /* UDP Socket */ #define SOCK_RAW 3 /* Raw socket */ +#define IPPROTO_ICMP 1 /* ICMP used with socket type SOCK_RAW */ +#define IPPROTO_IGMP 2 /* IGMP used with socket type SOCK_RAW */ #define IPPROTO_TCP 6 /* TCP Socket */ #define IPPROTO_UDP 17 /* TCP Socket */ +#define IPPROTO_ICMPV6 58 /* ICMPv6 used with socket type SOCK_RAW */ #define IPPROTO_RAW 255 /* Raw Socket */ /* Define supported flags for 'send' and 'recv'. */ @@ -496,13 +508,18 @@ extern "C" { /* Define data types used in structure timeval. */ -typedef LONG suseconds_t; +#ifdef __CCRX__ +typedef LONG time_t; +#endif /* __CCRX__ */ +typedef LONG suseconds_t; +#ifndef __SES_ARM struct timeval { time_t tv_sec; /* Seconds */ suseconds_t tv_usec; /* Microseconds */ }; +#endif /* __SES_ARM */ struct sockaddr_storage { diff --git a/addons/CMakeLists.txt b/addons/CMakeLists.txt index cfe60389..37aae089 100644 --- a/addons/CMakeLists.txt +++ b/addons/CMakeLists.txt @@ -14,6 +14,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/ftp/nxd_ftp_server.c ${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_client.c ${CMAKE_CURRENT_LIST_DIR}/http/nxd_http_server.c + ${CMAKE_CURRENT_LIST_DIR}/lwm2m/nx_lwm2m_client.c ${CMAKE_CURRENT_LIST_DIR}/mdns/nxd_mdns.c ${CMAKE_CURRENT_LIST_DIR}/mqtt/nxd_mqtt_client.c ${CMAKE_CURRENT_LIST_DIR}/nat/nx_nat.c @@ -21,6 +22,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/ppp/nx_ppp.c ${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_client.c ${CMAKE_CURRENT_LIST_DIR}/pppoe/nx_pppoe_server.c + ${CMAKE_CURRENT_LIST_DIR}/ptp/nxd_ptp_client.c ${CMAKE_CURRENT_LIST_DIR}/smtp/nxd_smtp_client.c ${CMAKE_CURRENT_LIST_DIR}/snmp/nx_des.c ${CMAKE_CURRENT_LIST_DIR}/snmp/nx_sha1.c @@ -33,6 +35,7 @@ set(SOURCES ${CMAKE_CURRENT_LIST_DIR}/web/nx_tcpserver.c ${CMAKE_CURRENT_LIST_DIR}/web/nx_web_http_client.c ${CMAKE_CURRENT_LIST_DIR}/web/nx_web_http_server.c + ${CMAKE_CURRENT_LIST_DIR}/websocket/nx_websocket_client.c # {{END_TARGET_SOURCES}} ) @@ -49,9 +52,12 @@ if(NXD_ENABLE_AZURE_IOT) list(APPEND SOURCES ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_hub_client.c + ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_hub_client_properties.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_json_reader.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_json_writer.c ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_provisioning_client.c + ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_adu_agent.c + ${CMAKE_CURRENT_LIST_DIR}/azure_iot/nx_azure_iot_adu_root_key.c ) set(ENV{AZ_SDK_C_NO_SAMPLES} TRUE) set(NX_AZURE_DISABLE_IOT_SECURITY_MODULE OFF CACHE BOOL "Disable Azure IoT Security Module (default is OFF)") @@ -84,16 +90,19 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/dns ${CMAKE_CURRENT_LIST_DIR}/ftp ${CMAKE_CURRENT_LIST_DIR}/http + ${CMAKE_CURRENT_LIST_DIR}/lwm2m ${CMAKE_CURRENT_LIST_DIR}/mdns ${CMAKE_CURRENT_LIST_DIR}/mqtt ${CMAKE_CURRENT_LIST_DIR}/nat ${CMAKE_CURRENT_LIST_DIR}/pop3 ${CMAKE_CURRENT_LIST_DIR}/ppp ${CMAKE_CURRENT_LIST_DIR}/pppoe + ${CMAKE_CURRENT_LIST_DIR}/ptp ${CMAKE_CURRENT_LIST_DIR}/smtp ${CMAKE_CURRENT_LIST_DIR}/snmp ${CMAKE_CURRENT_LIST_DIR}/sntp ${CMAKE_CURRENT_LIST_DIR}/telnet ${CMAKE_CURRENT_LIST_DIR}/tftp ${CMAKE_CURRENT_LIST_DIR}/web + ${CMAKE_CURRENT_LIST_DIR}/websocket ) diff --git a/addons/auto_ip/nx_auto_ip.c b/addons/auto_ip/nx_auto_ip.c index 9ec35bb3..3420dc7a 100644 --- a/addons/auto_ip/nx_auto_ip.c +++ b/addons/auto_ip/nx_auto_ip.c @@ -24,14 +24,17 @@ /* Force error checking to be disabled in this module */ +#include "tx_port.h" #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif +#endif /* Include necessary system files. */ @@ -858,7 +861,7 @@ NX_IP *ip_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_auto_ip_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -898,6 +901,9 @@ NX_IP *ip_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ VOID _nx_auto_ip_thread_entry(ULONG auto_ip_ptr_info) @@ -1079,7 +1085,7 @@ ULONG host_ip_address; { #ifdef NX_AUTO_IP_DEBUG - printf("AutoIP %s, CONFLICT for: %d,%d,%d,%d\n", auto_ip_ptr -> nx_auto_ip_name, + printf("AutoIP %s, CONFLICT for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name, (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF), @@ -1097,7 +1103,7 @@ ULONG host_ip_address; is ours! */ #ifdef NX_AUTO_IP_DEBUG - printf("AutoIP %s, RESOLVED for: %d,%d,%d,%d\n", auto_ip_ptr -> nx_auto_ip_name, + printf("AutoIP %s, RESOLVED for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name, (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF), @@ -1145,7 +1151,7 @@ ULONG host_ip_address; { #ifdef NX_AUTO_IP_DEBUG - printf("AutoIP %s, CONFLICT for: %d,%d,%d,%d\n", auto_ip_ptr -> nx_auto_ip_name, + printf("AutoIP %s, CONFLICT for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name, (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF), @@ -1174,7 +1180,7 @@ ULONG host_ip_address; auto_ip_ptr -> nx_auto_ip_defend_count++; #ifdef NX_AUTO_IP_DEBUG - printf("AutoIP %s, DEFEND for: %d,%d,%d,%d\n", auto_ip_ptr -> nx_auto_ip_name, + printf("AutoIP %s, DEFEND for: %lu,%lu,%lu,%lu\n", auto_ip_ptr -> nx_auto_ip_name, (auto_ip_ptr -> nx_auto_ip_current_local_address >> 24), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 16 & 0xFF), (auto_ip_ptr -> nx_auto_ip_current_local_address >> 8 & 0xFF), diff --git a/addons/auto_ip/nx_auto_ip.h b/addons/auto_ip/nx_auto_ip.h index a49d30df..16b31ee3 100644 --- a/addons/auto_ip/nx_auto_ip.h +++ b/addons/auto_ip/nx_auto_ip.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_auto_ip.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -60,6 +63,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the AutoIP ID that is used to mark the AutoIP structure as created. */ diff --git a/addons/azure_iot/README.md b/addons/azure_iot/README.md new file mode 100644 index 00000000..a14c44a6 --- /dev/null +++ b/addons/azure_iot/README.md @@ -0,0 +1,112 @@ +# Azure IoT Middleware for Azure RTOS + +Azure IoT Middleware for Azure RTOS is a platform specific library that acts as a binding layer between the Azure RTOS and the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c). Goals of this layer are following: + +* Expose smart client interfaces (IoTHub_Client, DeviceProvisioning_Client) for the customers, to be consumed in their application. +* Orchestrate the interaction between Embedded C SDK and platform. +* Provide Azure RTOS platform initialization. +* [IoT Plug and Play](https://learn.microsoft.com/azure/iot-develop/overview-iot-plug-and-play) support. +* Security capabilities. +* Resource limitation aware. +* Protocol support. + +## Getting Started + +See the following samples on how to get started on development boards with Azure IoT Middleware for Azure RTOS: + +Manufacturer | Device | Samples | +| --- | --- | --- | +| STMicroelectronics | [STM32F746GDISCOVERY](https://www.st.com/en/evaluation-tools/32f746gdiscovery.html) | [IAR](https://aka.ms/azrtos-sample/f746g-iar) • [STM32Cube](https://aka.ms/azrtos-sample/f746g-cubeide) +| STMicroelectronics | [B-L4S5I-IOT01](https://www.st.com/en/evaluation-tools/b-l4s5i-iot01a.html) / [B-L475E-IOT01](https://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/STMicroelectronics/STM32L4_L4%2B) • [IAR](https://aka.ms/azrtos-sample/l4s5-iar) • [STM32Cube](https://aka.ms/azrtos-sample/l4s5-cubeide) +| NXP | [MIMXRT1060-EVK](https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/mimxrt1060-evk-i-mx-rt1060-evaluation-kit:MIMXRT1060-EVK) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/NXP/MIMXRT1060-EVK) • [IAR](https://aka.ms/azrtos-sample/rt1060-iar) • [MCUXpresso](https://aka.ms/azrtos-sample/rt1060-mcuxpresso) +| Renesas | [RX65N-RSK-2MB](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rx65n-2mb-starter-kit-plus-renesas-starter-kit-rx65n-2mb) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/Renesas/RSK_RX65N_2MB) • [IAR](https://aka.ms/azrtos-samples/rx65n-rsk-2mb-iar) • [E2Studio CCRX](https://aka.ms/azrtos-samples/rx65n-rsk-2mb-ccrx) • [E2Studio GNURX](https://aka.ms/azrtos-samples/rx65n-rsk-2mb-gnurx) +| Renesas | [RX65N-Cloud-Kit](https://www.renesas.com/us/en/products/microcontrollers-microprocessors/rx-32-bit-performance-efficiency-mcus/rx65n-cloud-kit-renesas-rx65n-cloud-kit) | [E2Studio CCRX](https://aka.ms/azrtos-samples/rx65n-ck-ccrx) • [E2Studio GNURX](https://aka.ms/azrtos-samples/rx65n-ck-gnurx) +| Microchip | [ATSAME54-XPRO](https://www.microchip.com/developmenttools/productdetails/atsame54-xpro) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/Microchip/ATSAME54-XPRO) • [IAR](https://aka.ms/azrtos-sample/e54-iar) • [MPLAB](https://aka.ms/azrtos-sample/e54-mplab) +| MXCHIP | [AZ3166](https://aka.ms/iot-devkit) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/MXChip/AZ3166) + +## Building + +The Azure IoT Middleware for Azure RTOS is built as part of the NetX Duo. Make sure you have defined the following macros in the `CMakeLists.txt` or `nx_user.h` when building it: + +Module | Macros | +| --- | --- | +| Azure IoT Middleware for Azure RTOS | `NX_ENABLE_EXTENDED_NOTIFY_SUPPORT`
`NX_SECURE_ENABLE`
`NXD_MQTT_CLOUD_ENABLE` +| Azure Defender for IoT security module | `NX_ENABLE_IP_PACKET_FILTER` + +Follow [`nx_user_sample.h`](https://github.com/azure-rtos/netxduo/blob/master/common/inc/nx_user_sample.h) to see how to define these macros in the NetX user header file. + +## Features + +Azure IoT Middleware for Azure RTOS stays as an addon module for the Azure RTOS NetX Duo. It facilitates the MQTT and TLS stacks that are also as part of NetX Duo addons. + +![diagram](./docs/img/diagram.png) + +### Basic features + +* Connect to Azure IoT Hub via MQTT. +* Support of IoT Hub primitive data format: [device to cloud (D2C) message](https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-d2c-guidance), [Device Twins](https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-device-twins) and [Direct methods](https://learn.microsoft.com/azure/iot-hub/iot-hub-devguide-direct-methods). +* Support of IoT Plug and Play data format: Telemetry, Properties and Commands. +* Authentication: SAS Token and X.509 client certificate. +* JSON parsers. + +### Device Update for IoT Hub + +[Device Update for IoT Hub](https://learn.microsoft.com/azure/iot-hub-device-update/understand-device-update) is an Azure service that enables you to deploy over-the-air updates (OTA) for your IoT devices. The [Device Update for IoT Hub agent](https://learn.microsoft.com/azure/iot-hub-device-update/device-update-azure-real-time-operating-system) in the IoT Middleware provides simple APIs for device builders to integrate the OTA capability easily. + +See the [samples](https://github.com/azure-rtos/samples) of semiconductor's hero development boards with detailed guides to learn configure, build and deploy the over-the-air (OTA) updates to the devices. + +### Microsoft Defender for IoT + +[Microsoft Defender for IoT](https://learn.microsoft.com/azure/defender-for-iot/device-builders/overview) provides a comprehensive security solution for Azure RTOS devices. The built-in [IoT Security Module](https://learn.microsoft.com/azure/defender-for-iot/device-builders/iot-security-azure-rtos) in IoT Middleware is enabled by default to detect common threats and potential malicious activities. + +#### Opt-out + +To disable (opt-out) the module for your application, you can choose one of these two options: +* Define `NX_AZURE_DISABLE_IOT_SECURITY_MODULE` in NetX Duo header file such as `nx_user.h` when building the project. +* Call [`UINT nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr)`](https://docs.microsoft.com/azure/defender-for-iot/azure-rtos-security-module-api#disable-azure-iot-security-module) in your application code. + +#### Data collection + +By enabling the module, it analyzes inbound and outbound network activity on IPv4 and IPv6 with supported protocols of **TCP**, **UDP** and **ICMP**. And with below data collected: + +* Local and remote address / port +* Bytes in / out + +#### Footprint + +IoT Security Module leverages existing Azure RTOS resources, and sends security messages in the background, without interfering with the user application, using the same connection to the IoT Hub. + +The extra resource it will take on device and connection: + +**Memory Footprint** (using default config - 4 unique monitored connection in IPv4 in an hour): +Toolchain | RAM | ROM | +| --- | --- | --- | +| IAR Embedded Workbench (iccarm) | 4Kb | 10Kb +| GNU ARM Embedded Toolchain (arm-gcc) | 4Kb | 13Kb + +**Additional Connection**: +Connection Type | RAM | Network | +| --- | --- | --- | +| IPv4 | 52bytes | 36bytes +| IPv6 | 200bytes | 60bytes + +So the total additional connection traffic will be: +*Total (in bytes) = Metadata (e.g. 300 bytes) + IPv4 Connections * 36 + IPv6 Connections * 60* + +## APIs + +* [nx_azure_iot](./docs/azure_rtos_iot.md) +* [nx_azure_iot_hub_client](./docs/azure_rtos_iot_hub_client.md) +* [nx_azure_iot_hub_client_properties](./docs/azure_rtos_iot_hub_client_properties.md) +* [nx_azure_iot_provisioning_client](./docs/azure_rtos_iot_provisioning_client.md) +* [nx_azure_iot_json](./docs/azure_rtos_iot_json.md) +* [nx_azure_iot_adu_agent](./docs/azure_rtos_iot_adu_agent.md) +* [nx_azure_iot_security_module](../azure_iot_security_module/docs/nx_azure_iot_security_module.md) + +## Need Help? + +Find support channels in the [Resources](https://github.com/azure-rtos/netxduo#resources) list. + +## Licensing + +View [Licensing](https://github.com/azure-rtos/netxduo#licensing) of Azure RTOS NetX Duo. diff --git a/addons/azure_iot/azure-sdk-for-c b/addons/azure_iot/azure-sdk-for-c index 5e9d7b96..0400c341 160000 --- a/addons/azure_iot/azure-sdk-for-c +++ b/addons/azure_iot/azure-sdk-for-c @@ -1 +1 @@ -Subproject commit 5e9d7b96dbd98ce7125e4beed385959a32b4c6c1 +Subproject commit 0400c341743e7c87595f11e56c7f14302277ee56 diff --git a/addons/azure_iot/azure_iot_security_module/CMakeLists.txt b/addons/azure_iot/azure_iot_security_module/CMakeLists.txt index d6dd1907..5df94ab3 100644 --- a/addons/azure_iot/azure_iot_security_module/CMakeLists.txt +++ b/addons/azure_iot/azure_iot_security_module/CMakeLists.txt @@ -6,47 +6,65 @@ project(${PROJECT_NAME}) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") -# reslove logger log level -set(LOG_LEVELS NOTSET DEBUG INFO WARNING ERROR FATAL) -set(log_level NOTSET CACHE STRING "log_level: ${log_level} (default is NOTSET)") -set_property(CACHE log_level PROPERTY STRINGS NOTSET DEBUG INFO WARNING ERROR FATAL) -list(FIND LOG_LEVELS ${log_level} log_level_index) -if(log_level_index EQUAL -1) - message(FATAL_ERROR "log_level must be one of ${LOG_LEVELS}") -else() - add_definitions(-DLOG_LEVEL=${log_level_index}) +include(${CMAKE_CURRENT_LIST_DIR}/iot-security-module-core/configs/functions.cmake) + +# `IOT_SECURITY_MODULE_DIST_TARGET` A Compile flag that specifies the name of the distribution +# to be built, the value needs to be one of the *.dist file names (excluding extension) +# in 'netxduo/addons/azure_iot/azure_iot_security_module/configs' directory. +# The relevant 'asc_config.h' header file will then be generated with the property values +# specified in the chosen distribution. +if(NOT DEFINED IOT_SECURITY_MODULE_DIST_TARGET) + message("Target Distribution Undefined, setting default 'RTOS_BASE'") + set(IOT_SECURITY_MODULE_DIST_TARGET RTOS_BASE) endif() -# collector options -set(collector_heartbeat_enabled ON CACHE BOOL "Enable the heartbeat collector") -set(collector_network_activity_enabled ON CACHE BOOL "Enable the network activity collector") -set(collector_system_information_enabled ON CACHE BOOL "Enable the system information collector") +CONF_INC_CLEAN() + +include_directories(${CMAKE_CURRENT_LIST_DIR}/inc/configs/${IOT_SECURITY_MODULE_DIST_TARGET}) + +CONF_LOG_LEVEL() + +CONF_CREATE_DIST( + ${IOT_SECURITY_MODULE_DIST_TARGET} + ${CMAKE_CURRENT_LIST_DIR}/iot-security-module-core/configs/ + ${CMAKE_CURRENT_LIST_DIR}/configs/ + ${CMAKE_CURRENT_LIST_DIR}/inc/configs/${IOT_SECURITY_MODULE_DIST_TARGET}/asc_config.h + __ASC_CONFIG_H__ + ON + ON + ) + +if (DEFINED asc_config_h_only) + if (${asc_config_h_only}) + message("asc_config_h_only is ${asc_config_h_only} - configuration finished") + return() + endif() +endif() # Azure IoT Security Module core if(UNIX) set(build_as_32 ON CACHE BOOL "build as 32 bit") endif() -set(serializer_custom_allocator ON CACHE BOOL "") -set(run_unittests OFF) -set(run_coverage OFF) + add_subdirectory(iot-security-module-core) # FlatBUffers target_include_directories(flatccrt PRIVATE ${CMAKE_CURRENT_LIST_DIR}/inc + ${CMAKE_CURRENT_LIST_DIR}/inc/configs/${IOT_SECURITY_MODULE_DIST_TARGET} ) # Define our target library and an alias for consumers add_library(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/nx_azure_iot_security_module.c - $<$:${CMAKE_CURRENT_LIST_DIR}/src/collectors/collector_network_activity.c> - $<$:${CMAKE_CURRENT_LIST_DIR}/src/collectors/collector_system_information.c> + $<$:${CMAKE_CURRENT_LIST_DIR}/src/collectors/collector_network_activity.c> + $<$:${CMAKE_CURRENT_LIST_DIR}/src/collectors/collector_system_information.c> ${CMAKE_CURRENT_LIST_DIR}/src/model/objects/object_network_activity_ext.c ${CMAKE_CURRENT_LIST_DIR}/src/utils/irand.c ${CMAKE_CURRENT_LIST_DIR}/src/utils/itime.c - ${CMAKE_CURRENT_LIST_DIR}/src/utils/iuuid.c ${CMAKE_CURRENT_LIST_DIR}/src/utils/os_utils.c + ${CMAKE_CURRENT_LIST_DIR}/src/utils/ievent_loop.c ) add_library("azrtos::${PROJECT_NAME}" ALIAS ${PROJECT_NAME}) @@ -55,6 +73,7 @@ target_include_directories(${PROJECT_NAME} ${AZURE_IOT_SECURITY_MODULE} ${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}/inc + ${CMAKE_CURRENT_LIST_DIR}/inc/configs/${IOT_SECURITY_MODULE_DIST_TARGET} ) @@ -72,6 +91,7 @@ target_link_libraries(asc_security_core target_include_directories(asc_security_core PRIVATE inc + ${CMAKE_CURRENT_LIST_DIR}/inc/configs/${IOT_SECURITY_MODULE_DIST_TARGET} ) # Define any required dependencies between this library and others diff --git a/addons/azure_iot/azure_iot_security_module/configs/L4_BASE.dist b/addons/azure_iot/azure_iot_security_module/configs/L4_BASE.dist new file mode 100644 index 00000000..151c6a4f --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/configs/L4_BASE.dist @@ -0,0 +1,7 @@ +# set default configuration from specific parent dist +CONF_DEFINE_BASE(${g_plat_config_path} RTOS_BASE.dist) + +# DIST: overwrite configuration for specific distribution + +set(ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED ON) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY OFF) diff --git a/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE.dist b/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE.dist new file mode 100644 index 00000000..1dfc3ef5 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE.dist @@ -0,0 +1,35 @@ +# set default configuration from specific parent dist +CONF_DEFINE_BASE(${g_core_config_path} base_dist.cmake) + +# DIST: overwrite configuration for specific distribution +set(SECURITY_MODULE_VERSION_MAJOR 3) +set(SECURITY_MODULE_VERSION_MINOR 5) +set(SECURITY_MODULE_VERSION_PATCH 4) + +set(ASC_COMPONENT_CONFIGURATION OFF) + +set(ASC_COLLECTOR_HEARTBEAT_ENABLED ON) +set(ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED ON) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED ON) + +set(ASC_COMPONENT_SECURITY_MODULE ON) + +set(ASC_COMPONENT_CORE_SUPPORTS_RESTART OFF) +set(ASC_NOTIFIERS_OBJECT_POOL_ENTRIES 2) +set(ASC_LOG_TIMESTAMP_DEFAULT OFF) + +set(ASC_BEST_EFFORT_EVENT_LOOP ON) +set(ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME 3) +set(ASC_SECURITY_MODULE_PENDING_TIME 60*5) + +set(ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY ON) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 64) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 64) + +if(ASC_COMPONENT_CORE_SUPPORTS_RESTART) +set(ASC_BE_TIMERS_OBJECT_POOL_ENTRIES 3) +else() +set(ASC_BE_TIMERS_OBJECT_POOL_ENTRIES 2) +endif() +set(FLATCC_NO_ASSERT OFF) +set(FLATCC_ASSERT NX_ASSERT) \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE_UT.dist b/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE_UT.dist new file mode 100644 index 00000000..caedf490 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/configs/RTOS_BASE_UT.dist @@ -0,0 +1,16 @@ +# set default configuration from specific parent dist +CONF_DEFINE_BASE(${g_plat_config_path} RTOS_BASE.dist) + +# DIST: overwrite configuration for specific distribution +set(ASC_FIRST_FORCE_COLLECTION_INTERVAL 2) +set(ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES 1) +set(ASC_SECURITY_MODULE_MAX_HUB_DEVICES 128) +set(ASC_FLATCC_JSON_PRINTER_OVERWRITE ON) +if (NOT DEFINED log_level_cmdline) + set(ASC_LOG_LEVEL 0) +endif() +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 4) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 4) +set(run_unittests ON CACHE BOOL "set run_unittests to ON to run unittests (default is OFF)") +set(run_coverage ON CACHE BOOL "set run_unittests to ON to run unittests (default is OFF)") +set(FLATCC_ASSERT 0) \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/configs/asc_config.h.in b/addons/azure_iot/azure_iot_security_module/configs/asc_config.h.in new file mode 100644 index 00000000..97ae5790 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/configs/asc_config.h.in @@ -0,0 +1,37 @@ + +/************************ +* Platform configuration +*************************/ +#ifdef FLATCC_ASSERT +#undef FLATCC_ASSERT +#endif + +#ifndef __ASC_CONFIG_EXCLUDE_PORT__H__ +#include "tx_port.h" +#include "nx_port.h" +#include "nx_api.h" + +/* Flat buffer serializer platform */ +#cmakedefine FLATCC_ASSERT @FLATCC_ASSERT@ + +#endif /* __ASC_CONFIG_EXCLUDE_PORT__H__ */ + +/* Security Module pending time, in seconds */ +#cmakedefine ASC_SECURITY_MODULE_PENDING_TIME @ASC_SECURITY_MODULE_PENDING_TIME@ +#cmakedefine ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME @ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME@ +#cmakedefine ASC_SECURITY_MODULE_MAX_HUB_DEVICES @ASC_SECURITY_MODULE_MAX_HUB_DEVICES@ +#ifndef ASC_SECURITY_MODULE_MAX_HUB_DEVICES +#define ASC_SECURITY_MODULE_MAX_HUB_DEVICES 64 +#endif + +/* Collector network activity. */ +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_TCP_DISABLED +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_UDP_DISABLED +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY + +/* The maximum number of IPv4 network events to store in memory. */ +#ifdef NX_DISABLE_IPV6 +#undef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.h b/addons/azure_iot/azure_iot_security_module/configs/license similarity index 71% rename from addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.h rename to addons/azure_iot/azure_iot_security_module/configs/license index 0592c9fc..639866c2 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.h +++ b/addons/azure_iot/azure_iot_security_module/configs/license @@ -9,13 +9,3 @@ /* */ /**************************************************************************/ -#ifndef CUSTOM_BUILDER_ALLOCATOR_H -#define CUSTOM_BUILDER_ALLOCATOR_H - -#include "flatcc/flatcc_builder.h" - -int serializer_custom_allocator(void *alloc_context, flatcc_iovec_t *b, size_t request, int zero_fill, int alloc_type); - -void serializer_custom_allocator_reset(); - -#endif /* CUSTOM_BUILDER_ALLOCATOR_H */ diff --git a/addons/azure_iot/azure_iot_security_module/docs/nx_azure_iot_security_module.md b/addons/azure_iot/azure_iot_security_module/docs/nx_azure_iot_security_module.md new file mode 100644 index 00000000..06e1b51b --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/docs/nx_azure_iot_security_module.md @@ -0,0 +1,70 @@ +# Azure RTOS IoT Security Module API + +## Azure IoT Security Module + +**nx_azure_iot_security_module_enable** +*** +
Enable Azure IoT Security Module
+ +**Prototype** +```c +UINT nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr); +``` +**Description** + +

This routine enables the Azure IoT Security Module subsystem. An internal state machine manage security events collection and sends them to Azure IoT Hub. Only one NX_AZURE_IOT_SECURITY_MODULE instance exists at most and needed to manage data collection.

+ +**Parameters** +| Name | Description | +| - |:-| +| nx_azure_iot_ptr [in] | A pointer to a `NX_AZURE_IOT` | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully enabled Azure IoT Security Module. +* NX_AZURE_IOT_FAILURE Fail to enable Azure IoT Security Module due to internal error. +* NX_AZURE_IOT_INVALID_PARAMETER Security module requires valid #NX_AZURE_IOT instance. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_security_module_disable** +*** +
Disable Azure IoT Security Module
+ +**Prototype** +```c +UINT nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr); +``` +**Description** + +

This routine disables the Azure IoT Security Module subsystem.

+ +**Parameters** + +| Name | Description | +| - |:-| +| nx_azure_iot_ptr [in] | A pointer to a `NX_AZURE_IOT`, if NULL the singleton instance will be disabled. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if Azure IoT Security Module has been disabled successfully. +* NX_AZURE_IOT_INVALID_PARAMETER Azure IoT Hub instance differ than the singleton composite instance. +* NX_AZURE_IOT_FAILURE Fail to disable Azure IoT Security Module due to internal error. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
diff --git a/addons/azure_iot/azure_iot_security_module/inc/asc_port.h b/addons/azure_iot/azure_iot_security_module/inc/asc_port.h deleted file mode 100644 index dbb66a77..00000000 --- a/addons/azure_iot/azure_iot_security_module/inc/asc_port.h +++ /dev/null @@ -1,69 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef ASC_PORT_H -#define ASC_PORT_H - -#include "nx_api.h" -#include "asc_security_core/version.h" - -/* Security Module ID - A unique identifier of the device. */ -#ifndef ASC_SECURITY_MODULE_ID -#define ASC_SECURITY_MODULE_ID "iot_security_module" -#endif - -/* Security Module pending time, in seconds */ -#ifndef ASC_SECURITY_MODULE_PENDING_TIME -#define ASC_SECURITY_MODULE_PENDING_TIME (60 * 5) -#endif - -/* Collection intervals, in seconds. */ -#ifndef ASC_HIGH_PRIORITY_INTERVAL -#define ASC_HIGH_PRIORITY_INTERVAL 10 -#endif -#ifndef ASC_MEDIUM_PRIORITY_INTERVAL -#define ASC_MEDIUM_PRIORITY_INTERVAL 30 -#endif -#ifndef ASC_LOW_PRIORITY_INTERVAL -#define ASC_LOW_PRIORITY_INTERVAL 60 -#endif - -/* Enable Collectors */ -#define COLLECTOR_HEARTBEAT_ENABLED -#define COLLECTOR_SYSTEM_INFORMATION_ENABLED -#define COLLECTOR_NETWORK_ACTIVITY_ENABLED - -/* Collector network activity. */ -/* #define ASC_COLLECTOR_NETWORK_ACTIVITY_TCP_DISABLED */ -/* #define ASC_COLLECTOR_NETWORK_ACTIVITY_UDP_DISABLED */ -/* #define ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED */ -#define ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY - -/* The maximum number of IPv4 network events to store in memory. */ -#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE -#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 4 -#endif -/* The maximum number of IPv6 network events to store in memory. */ -#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE -#ifdef NX_DISABLE_IPV6 -#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 -#else -#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 4 -#endif /* NX_DISABLE_IPV6 */ -#endif - - -/* Serializer custom allocator uses static memory instead of heap memory. Desired behaviour in Azure RTOS devices. */ -#ifndef ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR -#define ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR -#endif - -#endif /* ASC_PORT_H */ diff --git a/addons/azure_iot/azure_iot_security_module/inc/asc_version.h b/addons/azure_iot/azure_iot_security_module/inc/asc_version.h deleted file mode 100644 index 78b70b3c..00000000 --- a/addons/azure_iot/azure_iot_security_module/inc/asc_version.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef SECURITY_MODULE_VERSION_MAJOR -#define SECURITY_MODULE_VERSION_MAJOR 2 -#endif - -#ifndef SECURITY_MODULE_VERSION_MINOR -#define SECURITY_MODULE_VERSION_MINOR 0 -#endif - -#ifndef SECURITY_MODULE_VERSION_PATCH -#define SECURITY_MODULE_VERSION_PATCH 3 -#endif diff --git a/addons/azure_iot/azure_iot_security_module/inc/configs/L4_BASE/asc_config.h b/addons/azure_iot/azure_iot_security_module/inc/configs/L4_BASE/asc_config.h new file mode 100644 index 00000000..87384977 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/inc/configs/L4_BASE/asc_config.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Distribution L4_BASE */ +#ifndef __ASC_CONFIG_H__ +#define __ASC_CONFIG_H__ + +/******************** +* Core configuration +*********************/ +/* Based on 2022.07.19-3.5.3 core tag */ + +/* ID and version */ +#define ASC_SECURITY_MODULE_ID "defender-iot-micro-agent" +#define SECURITY_MODULE_VERSION_MAJOR 3 +#define SECURITY_MODULE_VERSION_MINOR 5 +#define SECURITY_MODULE_VERSION_PATCH 4 +#ifndef SECURITY_MODULE_VERSION_MAJOR +#define SECURITY_MODULE_VERSION_MAJOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_MINOR +#define SECURITY_MODULE_VERSION_MINOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_PATCH +#define SECURITY_MODULE_VERSION_PATCH 0 +#endif + +/* Collectors definitions */ +/* #undef ASC_DYNAMIC_COLLECTORS_MAX */ +#ifndef ASC_DYNAMIC_COLLECTORS_MAX +#define ASC_DYNAMIC_COLLECTORS_MAX 0 +#endif +#define ASC_COLLECTOR_HEARTBEAT_ENABLED + +/* #undef ASC_COLLECTOR_BASELINE_ENABLED */ +/* #undef ASC_BASELINE_REPORT_POOL_ENTRIES */ + +/* #undef ASC_COLLECTOR_LOG_ENABLED */ +/* #undef ASC_LOG_REPORT_POOL_ENTRIES */ + +#define ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 64 +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 64 +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 0 +#endif +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +/* #undef ASC_COLLECTOR_PROCESS_ENABLED */ +/* #undef ASC_COLLECTOR_PROCESS_SEND_EMPTY_EVENTS */ +/* #undef ASC_COLLECTOR_PROCESS_IN_CACHE */ +#ifndef ASC_COLLECTOR_PROCESS_IN_CACHE +#define ASC_COLLECTOR_PROCESS_IN_CACHE 0 +#endif + +#define ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + +/* #undef ASC_COLLECTOR_LISTENING_PORTS_ENABLED */ + +/* Components definitions */ +/* #undef ASC_DYNAMIC_FACTORY_ENABLED */ +/* #undef ASC_DYNAMIC_FACTORY_PATH */ +/* #undef ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET */ +/* #undef ASC_DYNAMIC_COMPONENTS_MAX */ +#ifndef ASC_DYNAMIC_COMPONENTS_MAX +#define ASC_DYNAMIC_COMPONENTS_MAX 0 +#endif + +/* #undef ASC_COMPONENT_COMMAND_EXECUTOR */ +/* #undef ASC_OPERATIONS_POOL_ENTRIES */ + +/* #undef ASC_COMPONENT_CONFIGURATION */ +/* #undef ASC_COMPONENT_CONFIGURATION_PLAT */ + +#define ASC_COMPONENT_SECURITY_MODULE + +/* Collection definitions */ +#define ASC_FIRST_COLLECTION_INTERVAL 30 +#define ASC_HIGH_PRIORITY_INTERVAL 10 +#define ASC_MEDIUM_PRIORITY_INTERVAL 30 +#define ASC_LOW_PRIORITY_INTERVAL 60 + +/* Dynamic/Static memory */ +/* #undef ASC_DYNAMIC_MEMORY_ENABLED */ + +/* ROM reduce */ +/* #undef ASC_COMPONENT_CORE_SUPPORTS_RESTART */ +/* #undef ASC_COLLECTORS_INFO_SUPPORT */ +/* #undef ASC_LINKED_LIST_NODE_SUPPORT */ + +/* Log */ +// Highest compiled log level +/* #undef ASC_LOG_LEVEL */ +/* #undef ASC_TIME_H_SUPPORT */ +/* #undef ASC_LOG_TIMESTAMP_DEFAULT */ + +/* Notifier definitions */ +#define ASC_NOTIFIERS_OBJECT_POOL_ENTRIES 2 + +/* Event loop best effort */ +#define ASC_BEST_EFFORT_EVENT_LOOP +#define ASC_BE_TIMERS_OBJECT_POOL_ENTRIES 2 + +/* Flat buffer serializer */ +#define ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +/* #undef ASC_FLATCC_JSON_PRINTER_OVERWRITE */ +#define ASC_EMITTER_PAGE_CACHE_SIZE 1 +/* #undef FLATCC_NO_ASSERT */ +/* FLATCC_ASSERT might be redefined in platform area */ +#define FLATCC_ASSERT NX_ASSERT +#define FLATCC_USE_GENERIC_ALIGNED_ALLOC +/* #undef FLATCC_EMITTER_PAGE_SIZE */ + +/* Tests definitions */ +// Set ASC_FIRST_FORCE_COLLECTION_INTERVAL to '-1' to force immediatly collecting +/* #undef ASC_FIRST_FORCE_COLLECTION_INTERVAL */ +/* #undef ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES */ +/* #undef ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES */ +/* #undef ASC_EXTRA_COMPONENTS_COUNT */ +#ifndef ASC_EXTRA_COMPONENTS_COUNT +#define ASC_EXTRA_COMPONENTS_COUNT 0 +#endif +/* #undef ASC_EXTRA_COLLECTORS_COUNT */ +#ifndef ASC_EXTRA_COLLECTORS_COUNT +#define ASC_EXTRA_COLLECTORS_COUNT 0 +#endif + +#define LOOP_ASSERT_FAIL for (;;) { } +#define LOOP_ASSERT(s) if (!(s)) {LOOP_ASSERT_FAIL} + +/************************ +* Platform configuration +*************************/ +#ifdef FLATCC_ASSERT +#undef FLATCC_ASSERT +#endif + +#ifndef __ASC_CONFIG_EXCLUDE_PORT__H__ +#include "tx_port.h" +#include "nx_port.h" +#include "nx_api.h" + +/* Flat buffer serializer platform */ +#define FLATCC_ASSERT NX_ASSERT + +#endif /* __ASC_CONFIG_EXCLUDE_PORT__H__ */ + +/* Security Module pending time, in seconds */ +#define ASC_SECURITY_MODULE_PENDING_TIME 60*5 +#define ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME 3 +/* #undef ASC_SECURITY_MODULE_MAX_HUB_DEVICES */ +#ifndef ASC_SECURITY_MODULE_MAX_HUB_DEVICES +#define ASC_SECURITY_MODULE_MAX_HUB_DEVICES 64 +#endif + +/* Collector network activity. */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_TCP_DISABLED */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_UDP_DISABLED */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY */ + +/* The maximum number of IPv4 network events to store in memory. */ +#ifdef NX_DISABLE_IPV6 +#undef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +#endif /* __ASC_CONFIG_H__ */ + +#ifdef __cplusplus +} +#endif diff --git a/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE/asc_config.h b/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE/asc_config.h new file mode 100644 index 00000000..de0fdc6f --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE/asc_config.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Distribution RTOS_BASE */ +#ifndef __ASC_CONFIG_H__ +#define __ASC_CONFIG_H__ + +/******************** +* Core configuration +*********************/ +/* Based on 2022.07.19-3.5.3 core tag */ + +/* ID and version */ +#define ASC_SECURITY_MODULE_ID "defender-iot-micro-agent" +#define SECURITY_MODULE_VERSION_MAJOR 3 +#define SECURITY_MODULE_VERSION_MINOR 5 +#define SECURITY_MODULE_VERSION_PATCH 4 +#ifndef SECURITY_MODULE_VERSION_MAJOR +#define SECURITY_MODULE_VERSION_MAJOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_MINOR +#define SECURITY_MODULE_VERSION_MINOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_PATCH +#define SECURITY_MODULE_VERSION_PATCH 0 +#endif + +/* Collectors definitions */ +/* #undef ASC_DYNAMIC_COLLECTORS_MAX */ +#ifndef ASC_DYNAMIC_COLLECTORS_MAX +#define ASC_DYNAMIC_COLLECTORS_MAX 0 +#endif +#define ASC_COLLECTOR_HEARTBEAT_ENABLED + +/* #undef ASC_COLLECTOR_BASELINE_ENABLED */ +/* #undef ASC_BASELINE_REPORT_POOL_ENTRIES */ + +/* #undef ASC_COLLECTOR_LOG_ENABLED */ +/* #undef ASC_LOG_REPORT_POOL_ENTRIES */ + +#define ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 64 +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 64 +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 0 +#endif +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +/* #undef ASC_COLLECTOR_PROCESS_ENABLED */ +/* #undef ASC_COLLECTOR_PROCESS_SEND_EMPTY_EVENTS */ +/* #undef ASC_COLLECTOR_PROCESS_IN_CACHE */ +#ifndef ASC_COLLECTOR_PROCESS_IN_CACHE +#define ASC_COLLECTOR_PROCESS_IN_CACHE 0 +#endif + +#define ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + +/* #undef ASC_COLLECTOR_LISTENING_PORTS_ENABLED */ + +/* Components definitions */ +/* #undef ASC_DYNAMIC_FACTORY_ENABLED */ +/* #undef ASC_DYNAMIC_FACTORY_PATH */ +/* #undef ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET */ +/* #undef ASC_DYNAMIC_COMPONENTS_MAX */ +#ifndef ASC_DYNAMIC_COMPONENTS_MAX +#define ASC_DYNAMIC_COMPONENTS_MAX 0 +#endif + +/* #undef ASC_COMPONENT_COMMAND_EXECUTOR */ +/* #undef ASC_OPERATIONS_POOL_ENTRIES */ + +/* #undef ASC_COMPONENT_CONFIGURATION */ +/* #undef ASC_COMPONENT_CONFIGURATION_PLAT */ + +#define ASC_COMPONENT_SECURITY_MODULE + +/* Collection definitions */ +#define ASC_FIRST_COLLECTION_INTERVAL 30 +#define ASC_HIGH_PRIORITY_INTERVAL 10 +#define ASC_MEDIUM_PRIORITY_INTERVAL 30 +#define ASC_LOW_PRIORITY_INTERVAL 60 + +/* Dynamic/Static memory */ +/* #undef ASC_DYNAMIC_MEMORY_ENABLED */ + +/* ROM reduce */ +/* #undef ASC_COMPONENT_CORE_SUPPORTS_RESTART */ +/* #undef ASC_COLLECTORS_INFO_SUPPORT */ +/* #undef ASC_LINKED_LIST_NODE_SUPPORT */ + +/* Log */ +// Highest compiled log level +/* #undef ASC_LOG_LEVEL */ +/* #undef ASC_TIME_H_SUPPORT */ +/* #undef ASC_LOG_TIMESTAMP_DEFAULT */ + +/* Notifier definitions */ +#define ASC_NOTIFIERS_OBJECT_POOL_ENTRIES 2 + +/* Event loop best effort */ +#define ASC_BEST_EFFORT_EVENT_LOOP +#define ASC_BE_TIMERS_OBJECT_POOL_ENTRIES 2 + +/* Flat buffer serializer */ +#define ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +/* #undef ASC_FLATCC_JSON_PRINTER_OVERWRITE */ +#define ASC_EMITTER_PAGE_CACHE_SIZE 1 +/* #undef FLATCC_NO_ASSERT */ +/* FLATCC_ASSERT might be redefined in platform area */ +#define FLATCC_ASSERT NX_ASSERT +#define FLATCC_USE_GENERIC_ALIGNED_ALLOC +/* #undef FLATCC_EMITTER_PAGE_SIZE */ + +/* Tests definitions */ +// Set ASC_FIRST_FORCE_COLLECTION_INTERVAL to '-1' to force immediatly collecting +/* #undef ASC_FIRST_FORCE_COLLECTION_INTERVAL */ +/* #undef ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES */ +/* #undef ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES */ +/* #undef ASC_EXTRA_COMPONENTS_COUNT */ +#ifndef ASC_EXTRA_COMPONENTS_COUNT +#define ASC_EXTRA_COMPONENTS_COUNT 0 +#endif +/* #undef ASC_EXTRA_COLLECTORS_COUNT */ +#ifndef ASC_EXTRA_COLLECTORS_COUNT +#define ASC_EXTRA_COLLECTORS_COUNT 0 +#endif + +#define LOOP_ASSERT_FAIL for (;;) { } +#define LOOP_ASSERT(s) if (!(s)) {LOOP_ASSERT_FAIL} + +/************************ +* Platform configuration +*************************/ +#ifdef FLATCC_ASSERT +#undef FLATCC_ASSERT +#endif + +#ifndef __ASC_CONFIG_EXCLUDE_PORT__H__ +#include "tx_port.h" +#include "nx_port.h" +#include "nx_api.h" + +/* Flat buffer serializer platform */ +#define FLATCC_ASSERT NX_ASSERT + +#endif /* __ASC_CONFIG_EXCLUDE_PORT__H__ */ + +/* Security Module pending time, in seconds */ +#define ASC_SECURITY_MODULE_PENDING_TIME 60*5 +#define ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME 3 +/* #undef ASC_SECURITY_MODULE_MAX_HUB_DEVICES */ +#ifndef ASC_SECURITY_MODULE_MAX_HUB_DEVICES +#define ASC_SECURITY_MODULE_MAX_HUB_DEVICES 64 +#endif + +/* Collector network activity. */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_TCP_DISABLED */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_UDP_DISABLED */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY + +/* The maximum number of IPv4 network events to store in memory. */ +#ifdef NX_DISABLE_IPV6 +#undef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +#endif /* __ASC_CONFIG_H__ */ + +#ifdef __cplusplus +} +#endif diff --git a/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE_UT/asc_config.h b/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE_UT/asc_config.h new file mode 100644 index 00000000..8fdaa8db --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/inc/configs/RTOS_BASE_UT/asc_config.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Distribution RTOS_BASE_UT */ +#ifndef __ASC_CONFIG_H__ +#define __ASC_CONFIG_H__ + +/******************** +* Core configuration +*********************/ +/* Based on 2022.07.19-3.5.3 core tag */ + +/* ID and version */ +#define ASC_SECURITY_MODULE_ID "defender-iot-micro-agent" +#define SECURITY_MODULE_VERSION_MAJOR 3 +#define SECURITY_MODULE_VERSION_MINOR 5 +#define SECURITY_MODULE_VERSION_PATCH 4 +#ifndef SECURITY_MODULE_VERSION_MAJOR +#define SECURITY_MODULE_VERSION_MAJOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_MINOR +#define SECURITY_MODULE_VERSION_MINOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_PATCH +#define SECURITY_MODULE_VERSION_PATCH 0 +#endif + +/* Collectors definitions */ +/* #undef ASC_DYNAMIC_COLLECTORS_MAX */ +#ifndef ASC_DYNAMIC_COLLECTORS_MAX +#define ASC_DYNAMIC_COLLECTORS_MAX 0 +#endif +#define ASC_COLLECTOR_HEARTBEAT_ENABLED + +/* #undef ASC_COLLECTOR_BASELINE_ENABLED */ +/* #undef ASC_BASELINE_REPORT_POOL_ENTRIES */ + +/* #undef ASC_COLLECTOR_LOG_ENABLED */ +/* #undef ASC_LOG_REPORT_POOL_ENTRIES */ + +#define ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 4 +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 4 +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 0 +#endif +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +/* #undef ASC_COLLECTOR_PROCESS_ENABLED */ +/* #undef ASC_COLLECTOR_PROCESS_SEND_EMPTY_EVENTS */ +/* #undef ASC_COLLECTOR_PROCESS_IN_CACHE */ +#ifndef ASC_COLLECTOR_PROCESS_IN_CACHE +#define ASC_COLLECTOR_PROCESS_IN_CACHE 0 +#endif + +#define ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + +/* #undef ASC_COLLECTOR_LISTENING_PORTS_ENABLED */ + +/* Components definitions */ +/* #undef ASC_DYNAMIC_FACTORY_ENABLED */ +/* #undef ASC_DYNAMIC_FACTORY_PATH */ +/* #undef ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET */ +/* #undef ASC_DYNAMIC_COMPONENTS_MAX */ +#ifndef ASC_DYNAMIC_COMPONENTS_MAX +#define ASC_DYNAMIC_COMPONENTS_MAX 0 +#endif + +/* #undef ASC_COMPONENT_COMMAND_EXECUTOR */ +/* #undef ASC_OPERATIONS_POOL_ENTRIES */ + +/* #undef ASC_COMPONENT_CONFIGURATION */ +/* #undef ASC_COMPONENT_CONFIGURATION_PLAT */ + +#define ASC_COMPONENT_SECURITY_MODULE + +/* Collection definitions */ +#define ASC_FIRST_COLLECTION_INTERVAL 30 +#define ASC_HIGH_PRIORITY_INTERVAL 10 +#define ASC_MEDIUM_PRIORITY_INTERVAL 30 +#define ASC_LOW_PRIORITY_INTERVAL 60 + +/* Dynamic/Static memory */ +/* #undef ASC_DYNAMIC_MEMORY_ENABLED */ + +/* ROM reduce */ +/* #undef ASC_COMPONENT_CORE_SUPPORTS_RESTART */ +/* #undef ASC_COLLECTORS_INFO_SUPPORT */ +/* #undef ASC_LINKED_LIST_NODE_SUPPORT */ + +/* Log */ +// Highest compiled log level +/* #undef ASC_LOG_LEVEL */ +/* #undef ASC_TIME_H_SUPPORT */ +/* #undef ASC_LOG_TIMESTAMP_DEFAULT */ + +/* Notifier definitions */ +#define ASC_NOTIFIERS_OBJECT_POOL_ENTRIES 2 + +/* Event loop best effort */ +#define ASC_BEST_EFFORT_EVENT_LOOP +#define ASC_BE_TIMERS_OBJECT_POOL_ENTRIES 2 + +/* Flat buffer serializer */ +#define ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +#define ASC_FLATCC_JSON_PRINTER_OVERWRITE +#define ASC_EMITTER_PAGE_CACHE_SIZE 1 +/* #undef FLATCC_NO_ASSERT */ +/* FLATCC_ASSERT might be redefined in platform area */ +/* #undef FLATCC_ASSERT */ +#define FLATCC_USE_GENERIC_ALIGNED_ALLOC +/* #undef FLATCC_EMITTER_PAGE_SIZE */ + +/* Tests definitions */ +// Set ASC_FIRST_FORCE_COLLECTION_INTERVAL to '-1' to force immediatly collecting +#define ASC_FIRST_FORCE_COLLECTION_INTERVAL 2 +/* #undef ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES */ +#define ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES 1 +/* #undef ASC_EXTRA_COMPONENTS_COUNT */ +#ifndef ASC_EXTRA_COMPONENTS_COUNT +#define ASC_EXTRA_COMPONENTS_COUNT 0 +#endif +/* #undef ASC_EXTRA_COLLECTORS_COUNT */ +#ifndef ASC_EXTRA_COLLECTORS_COUNT +#define ASC_EXTRA_COLLECTORS_COUNT 0 +#endif + +#define LOOP_ASSERT_FAIL for (;;) { } +#define LOOP_ASSERT(s) if (!(s)) {LOOP_ASSERT_FAIL} + +/************************ +* Platform configuration +*************************/ +#ifdef FLATCC_ASSERT +#undef FLATCC_ASSERT +#endif + +#ifndef __ASC_CONFIG_EXCLUDE_PORT__H__ +#include "tx_port.h" +#include "nx_port.h" +#include "nx_api.h" + +/* Flat buffer serializer platform */ +/* #undef FLATCC_ASSERT */ + +#endif /* __ASC_CONFIG_EXCLUDE_PORT__H__ */ + +/* Security Module pending time, in seconds */ +#define ASC_SECURITY_MODULE_PENDING_TIME 60*5 +#define ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME 3 +#define ASC_SECURITY_MODULE_MAX_HUB_DEVICES 128 +#ifndef ASC_SECURITY_MODULE_MAX_HUB_DEVICES +#define ASC_SECURITY_MODULE_MAX_HUB_DEVICES 64 +#endif + +/* Collector network activity. */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_TCP_DISABLED */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_UDP_DISABLED */ +/* #undef ASC_COLLECTOR_NETWORK_ACTIVITY_ICMP_DISABLED */ +#define ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY + +/* The maximum number of IPv4 network events to store in memory. */ +#ifdef NX_DISABLE_IPV6 +#undef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +#endif /* __ASC_CONFIG_H__ */ + +#ifdef __cplusplus +} +#endif diff --git a/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/model/objects/object_network_activity_ext.h b/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/model/objects/object_network_activity_ext.h index 4a8b11f8..4252b2ee 100644 --- a/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/model/objects/object_network_activity_ext.h +++ b/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/model/objects/object_network_activity_ext.h @@ -12,11 +12,12 @@ #ifndef OBJECT_NETWORK_ACTIVITY_EXT_H #define OBJECT_NETWORK_ACTIVITY_EXT_H +#include + #ifdef __cplusplus extern "C" { #endif -#include "asc_security_core/configuration.h" #include "asc_security_core/utils/collection/hashset.h" #include "asc_security_core/model/objects/network_activity.h" diff --git a/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/mti.h b/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/mti.h index 11511647..63a99629 100644 --- a/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/mti.h +++ b/addons/azure_iot/azure_iot_security_module/inc/iot_security_module/mti.h @@ -9,6 +9,8 @@ /* */ /**************************************************************************/ +#include + #ifndef MTI_RTOS_H #define MTI_RTOS_H diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/CMakeLists.txt b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/CMakeLists.txt index 4fe194de..a1417981 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/CMakeLists.txt +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/CMakeLists.txt @@ -1,138 +1,134 @@ -cmake_minimum_required(VERSION 3.13) - -set(TARGET_NAME "asc_security_core") -project(${TARGET_NAME}) - - -set(build_pedantic ON CACHE BOOL "use -Wpedantic flag in compilation") - -# Include the common build rules for the security module core -include(cmake-modules/asc_security_coreBuild.cmake) -include(cmake-modules/asc_security_core_build_rules.cmake) - -# the following variables are project-wide and can be used with cmake-gui -set(run_unittests OFF CACHE BOOL "set run_unittests to ON to run unittests (default is OFF)") -set(run_coverage OFF CACHE BOOL "set run_coverage to ON to gather coverage info (default is OFF)") -set(use_dynamic_memory OFF CACHE BOOL "use the stack memory instead of using heap memory") -set(disable_asc_port OFF CACHE BOOL "explicitly disable ASC_PORT include") -set(serializer_custom_allocator OFF CACHE BOOL "Use custom allocator for flatcc") -set(build_json_printer OFF CACHE BOOL "Build the json printer") - -# collector options -set(collector_force_first_interval 0 CACHE STRING "Force first collector interval") -set(collector_heartbeat_enabled ON CACHE BOOL "Enable the heartbeat collector") -set(collector_network_activity_enabled OFF CACHE BOOL "Enable the network activity collector") -set(collector_system_information_enabled OFF CACHE BOOL "Enable the system information collector") -set(collector_listening_ports_enabled OFF CACHE BOOL "Enable the listening ports collector") -set(collector_baseline_enabled OFF CACHE BOOL "Enable the baseline collector") -set(build_as_32 OFF CACHE BOOL "build as 32 bit") - -# components options -set(component_command_executor_enabled OFF CACHE BOOL "Enable the command executor component") -set(best_effort_event_loop_enabled OFF CACHE BOOL "Compile best effort event loop") - -# reslove logger log level -set(LOG_LEVELS NOTSET DEBUG INFO WARNING ERROR FATAL) -set(log_level NOTSET CACHE STRING "log_level: ${log_level} (default is NOTSET)") -set_property(CACHE log_level PROPERTY STRINGS NOTSET DEBUG INFO WARNING ERROR FATAL) -list(FIND LOG_LEVELS ${log_level} log_level_index) -if(log_level_index EQUAL -1) - message(FATAL_ERROR "log_level must be one of ${LOG_LEVELS}") -endif() - -list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules") - -if(${collector_force_first_interval}) - message("Forcing first collection interval to ${collector_force_first_interval}") - add_definitions( - -DASC_FIRST_FORCE_COLLECTION_INTERVAL=${collector_force_first_interval} - ) -endif() - -if(${run_unittests}) - FILE(REMOVE ${CMAKE_BINARY_DIR}/valgrind_targets.lst) - - set(disable_asc_port ON) - set(collector_heartbeat_enabled ON) - set(component_command_executor_enabled ON) - set(best_effort_event_loop_enabled ON) - - if (${run_coverage}) - include(asc_security_coreCodeCoverage) - include(asc_security_coreCreateCodeCoverageTargets) - include(asc_security_coreCheckAndIncludeCodeCov) - endif () -endif() - -add_library(${TARGET_NAME} STATIC - # componets - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/command_executor.c> - - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/collectors/collector_heartbeat.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/collectors/baseline.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/baseline.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/model/objects/object_baseline_ext.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/heartbeat.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/listening_ports.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/network_activity.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/system_information.c> - - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/extensions/custom_builder_allocator.c> - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/extensions/page_allocator.c> - - src/collector_collection_factory.c - src/collector_collection_internal.c - src/collector_collection.c - src/collectors_info.c - src/core.c - src/logger.c - src/model/collector.c - src/model/security_message.c - src/serializer/serializer_private.c - src/serializer/serializer.c - src/utils/notifier.c - $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/utils/event_loop_be.c> - src/utils/string_utils.c -) - -target_compile_definitions(${TARGET_NAME} PUBLIC - LOG_LEVEL=${log_level_index} - - $<$:DISABLE_ASC_PORT> - $<$:DYNAMIC_MEMORY_ENABLED> - $<$:ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR> - - $<$:CONFIG_COMPONENT_COMMAND_EXECUTOR> -) - -target_include_directories(${TARGET_NAME} PUBLIC inc) - -add_subdirectory(deps) -target_link_libraries(${TARGET_NAME} PRIVATE - flatccrt -) -target_include_directories(flatccrt PRIVATE inc) - -if(${serializer_custom_allocator}) - target_link_libraries(flatccrt PRIVATE asc_security_core) - target_sources(flatccrt PRIVATE src/serializer/extensions/custom_emitter.c) - target_include_directories(flatccrt PRIVATE deps/flatcc/src/runtime) -endif() - -if (${run_unittests}) - enable_testing() - include(CTest) - - add_definitions( - -DEXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES=10 - -DEXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES=1 - # we have 7 test collectors - -DEXTRA_COLLECTORS_OBJECT_POOL_COUNT=7 - ) - - add_subdirectory(tests) - -endif () - -setTargetCompileOptions(${TARGET_NAME}) -compileTargetAsC99(${TARGET_NAME}) +cmake_minimum_required(VERSION 3.13) + +set(TARGET_NAME "asc_security_core") +project(${TARGET_NAME}) + +# Include the common build rules for the security module core +include(cmake-modules/asc_security_coreBuild.cmake) +include(cmake-modules/asc_security_core_build_rules.cmake) + +include(configs/functions.cmake) + +CONF_LOG_LEVEL() + +CONF_INC_CLEAN() + +if(DEFINED dist_test) + include_directories(${CMAKE_SOURCE_DIR}/inc/configs/${dist_test}) + CONF_CREATE_DIST( + ${dist_test} + ${CMAKE_SOURCE_DIR}/configs/test/ + ${CMAKE_SOURCE_DIR}/configs/test/plat/ + ${CMAKE_SOURCE_DIR}/inc/configs/${dist_test}/asc_config_test.h + __ASC_CONFIG_TEST_H__ + OFF + ON + ) +endif() + +if(NOT DEFINED IOT_SECURITY_MODULE_DIST_TARGET AND NOT DEFINED DEFENDER_IOT_MICRO_AGENT_DIST_CORE) + message(FATAL_ERROR "Target Distribution Undefined") +endif() + +if(DEFINED DEFENDER_IOT_MICRO_AGENT_DIST_CORE) + include_directories(${CMAKE_SOURCE_DIR}/inc/configs/${DEFENDER_IOT_MICRO_AGENT_DIST_CORE}) + CONF_CREATE_DIST( + ${DEFENDER_IOT_MICRO_AGENT_DIST_CORE} + ${CMAKE_SOURCE_DIR}/configs/ + ${CMAKE_SOURCE_DIR}/configs/ + ${CMAKE_SOURCE_DIR}/inc/configs/${DEFENDER_IOT_MICRO_AGENT_DIST_CORE}/asc_config.h + __ASC_CONFIG_H__ + ON + OFF + ) +endif() + +if (DEFINED asc_config_h_only) + if (${asc_config_h_only}) + message("asc_config_h_only is ${asc_config_h_only} - configuration finished") + return() + endif() +endif() + +set(build_pedantic ON CACHE BOOL "use -Wpedantic flag in compilation") + +# the following variables are project-wide and can be used with cmake-gui +set(build_as_32 OFF CACHE BOOL "build as 32 bit") + +list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake-modules") + +if(${run_core_unittests}) + FILE(REMOVE ${CMAKE_BINARY_DIR}/valgrind_targets.lst) + + if (${run_core_coverage}) + include(asc_security_coreCodeCoverage) + include(asc_security_coreCreateCodeCoverageTargets) + include(asc_security_coreCheckAndIncludeCodeCov) + endif () +endif() + +add_library(${TARGET_NAME} STATIC + # components + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/cli_plat.c> + + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/command_executor.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/configuration.c> + + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/collectors/collector_heartbeat.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/collectors/baseline.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/baseline.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/model/objects/object_baseline_ext.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/log.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/heartbeat.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/process.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/listening_ports.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/network_activity.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/system_information.c> + + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/extensions/custom_builder_allocator.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/serializer/extensions/page_allocator.c> + + src/components_factory.c + src/components_manager.c + src/collector_collection.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/collectors_info.c> + src/core.c + src/logger.c + src/model/collector.c + src/model/security_message.c + src/serializer/serializer_private.c + src/serializer/serializer.c + src/utils/iconv.c + src/utils/notifier.c + src/utils/uuid.c + src/utils/collection/bit_vector.c + src/utils/collection/stack.c + src/utils/collection/list.c + src/utils/collection/hashtable.c + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/utils/collection/linked_list_node.c> + $,src/object_pool_dynamic.c,src/object_pool_static.c> + $<$:${CMAKE_CURRENT_SOURCE_DIR}/src/utils/event_loop_be.c> + src/utils/string_utils.c +) + +target_include_directories(${TARGET_NAME} PUBLIC inc) + +add_subdirectory(deps) +target_link_libraries(${TARGET_NAME} PRIVATE + flatccrt +) + +if(${ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR}) + target_link_libraries(flatccrt PRIVATE asc_security_core) + target_include_directories(flatccrt PRIVATE deps/flatcc/src/runtime) +endif() + +if (${run_core_unittests}) + enable_testing() + include(CTest) + add_subdirectory(tests) + +endif () + +setTargetCompileOptions(${TARGET_NAME}) +compileTargetAsC99(${TARGET_NAME}) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_coreBuild.cmake b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_coreBuild.cmake index c1957acc..0d79a56c 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_coreBuild.cmake +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_coreBuild.cmake @@ -51,12 +51,12 @@ function(setTargetCompileOptions target) "-Wfloat-equal" "-Wmissing-declarations" "-Wno-unused-parameter" - "-Wno-cast-function-type" + "-Wjump-misses-init" ) if(${build_pedantic}) message(STATUS "Using '-Wpedantic' flag for compilation as warning only for target ${target}") - target_compile_options(${target} PRIVATE "-Wno-error=pedantic" "-Wpedantic" "-Wshadow") + target_compile_options(${target} PRIVATE "-Wpedantic" "-Wshadow") #Temopary hack target_compile_options(${target} PRIVATE "-Wno-error=overlength-strings") endif() diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_core_build_rules.cmake b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_core_build_rules.cmake index 7c1e3608..c81db82a 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_core_build_rules.cmake +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/cmake-modules/asc_security_core_build_rules.cmake @@ -54,3 +54,68 @@ function(usePermissiveRulesForSamplesAndTests) endif() endfunction() +function(add_exec_target _TARGET_NAME) + + set(one_value_arguments + ) + + set(multi_value_arguments + SOURCES + COMPILE_OPTIONS + MOCK_FUNCTIONS + PRIVATE_ACCESS + LINK_TARGETS + ) + + cmake_parse_arguments(_add_exec_target + "" + "${one_value_arguments}" + "${multi_value_arguments}" + ${ARGN} + ) + + if (NOT DEFINED _add_exec_target_SOURCES) + message(FATAL_ERROR "No sources provided for target ${_TARGET_NAME}") + endif() + + add_executable(${_TARGET_NAME} ${_add_exec_target_SOURCES}) + + if (DEFINED _add_exec_target_COMPILE_OPTIONS) + target_compile_options(${_TARGET_NAME} + PRIVATE ${_add_exec_target_COMPILE_OPTIONS} + ) + endif() + + if (DEFINED _add_exec_target_LINK_TARGETS) + target_link_libraries(${_TARGET_NAME} + PRIVATE + ${_add_exec_target_LINK_TARGETS} + ) + endif() + + if (DEFINED _add_exec_target_MOCK_FUNCTIONS) + set(functions "") + foreach(function ${_add_exec_target_MOCK_FUNCTIONS}) + set(functions "${functions} -Wl,--wrap=${function}") + endforeach() + + set_target_properties(${_TARGET_NAME} + PROPERTIES LINK_FLAGS + ${functions} + ) + + # Used for apply mocks in Azure RTOS + get_target_property(libs ${_TARGET_NAME} LINK_LIBRARIES) + foreach(function ${_add_exec_target_MOCK_FUNCTIONS}) + list(INSERT libs 0 + -Wl,-wrap,${function} + ) + endforeach() + set_target_properties(${TARGET_NAME} PROPERTIES LINK_LIBRARIES "${libs}") + endif() + + setTargetCompileOptions(${TARGET_NAME}) + compileTargetAsC99(${_TARGET_NAME}) + +endfunction (add_exec_target) + diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/asc_config.h.in b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/asc_config.h.in new file mode 100644 index 00000000..96c46284 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/asc_config.h.in @@ -0,0 +1,125 @@ +/******************** +* Core configuration +*********************/ +/* Based on 2022.07.19-3.5.3 core tag */ + +/* ID and version */ +#cmakedefine ASC_SECURITY_MODULE_ID "@ASC_SECURITY_MODULE_ID@" +#cmakedefine SECURITY_MODULE_VERSION_MAJOR @SECURITY_MODULE_VERSION_MAJOR@ +#cmakedefine SECURITY_MODULE_VERSION_MINOR @SECURITY_MODULE_VERSION_MINOR@ +#cmakedefine SECURITY_MODULE_VERSION_PATCH @SECURITY_MODULE_VERSION_PATCH@ +#ifndef SECURITY_MODULE_VERSION_MAJOR +#define SECURITY_MODULE_VERSION_MAJOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_MINOR +#define SECURITY_MODULE_VERSION_MINOR 0 +#endif +#ifndef SECURITY_MODULE_VERSION_PATCH +#define SECURITY_MODULE_VERSION_PATCH 0 +#endif + +/* Collectors definitions */ +#cmakedefine ASC_DYNAMIC_COLLECTORS_MAX @ASC_DYNAMIC_COLLECTORS_MAX@ +#ifndef ASC_DYNAMIC_COLLECTORS_MAX +#define ASC_DYNAMIC_COLLECTORS_MAX 0 +#endif +#cmakedefine ASC_COLLECTOR_HEARTBEAT_ENABLED + +#cmakedefine ASC_COLLECTOR_BASELINE_ENABLED +#cmakedefine ASC_BASELINE_REPORT_POOL_ENTRIES @ASC_BASELINE_REPORT_POOL_ENTRIES@ + +#cmakedefine ASC_COLLECTOR_LOG_ENABLED +#cmakedefine ASC_LOG_REPORT_POOL_ENTRIES @ASC_LOG_REPORT_POOL_ENTRIES@ + +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE @ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE@ +#cmakedefine ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE @ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE@ +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 0 +#endif +#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE +#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0 +#endif + +#cmakedefine ASC_COLLECTOR_PROCESS_ENABLED +#cmakedefine ASC_COLLECTOR_PROCESS_SEND_EMPTY_EVENTS +#cmakedefine ASC_COLLECTOR_PROCESS_IN_CACHE @ASC_COLLECTOR_PROCESS_IN_CACHE@ +#ifndef ASC_COLLECTOR_PROCESS_IN_CACHE +#define ASC_COLLECTOR_PROCESS_IN_CACHE 0 +#endif + +#cmakedefine ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + +#cmakedefine ASC_COLLECTOR_LISTENING_PORTS_ENABLED + +/* Components definitions */ +#cmakedefine ASC_DYNAMIC_FACTORY_ENABLED +#cmakedefine ASC_DYNAMIC_FACTORY_PATH "@ASC_DYNAMIC_FACTORY_PATH@" +#cmakedefine ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET +#cmakedefine ASC_DYNAMIC_COMPONENTS_MAX @ASC_DYNAMIC_COMPONENTS_MAX@ +#ifndef ASC_DYNAMIC_COMPONENTS_MAX +#define ASC_DYNAMIC_COMPONENTS_MAX 0 +#endif + +#cmakedefine ASC_COMPONENT_COMMAND_EXECUTOR +#cmakedefine ASC_OPERATIONS_POOL_ENTRIES @ASC_OPERATIONS_POOL_ENTRIES@ + +#cmakedefine ASC_COMPONENT_CONFIGURATION +#cmakedefine ASC_COMPONENT_CONFIGURATION_PLAT + +#cmakedefine ASC_COMPONENT_SECURITY_MODULE + +/* Collection definitions */ +#cmakedefine ASC_FIRST_COLLECTION_INTERVAL @ASC_FIRST_COLLECTION_INTERVAL@ +#cmakedefine ASC_HIGH_PRIORITY_INTERVAL @ASC_HIGH_PRIORITY_INTERVAL@ +#cmakedefine ASC_MEDIUM_PRIORITY_INTERVAL @ASC_MEDIUM_PRIORITY_INTERVAL@ +#cmakedefine ASC_LOW_PRIORITY_INTERVAL @ASC_LOW_PRIORITY_INTERVAL@ + +/* Dynamic/Static memory */ +#cmakedefine ASC_DYNAMIC_MEMORY_ENABLED + +/* ROM reduce */ +#cmakedefine ASC_COMPONENT_CORE_SUPPORTS_RESTART +#cmakedefine ASC_COLLECTORS_INFO_SUPPORT +#cmakedefine ASC_LINKED_LIST_NODE_SUPPORT + +/* Log */ +// Highest compiled log level +#cmakedefine ASC_LOG_LEVEL @ASC_LOG_LEVEL@ +#cmakedefine ASC_TIME_H_SUPPORT +#cmakedefine ASC_LOG_TIMESTAMP_DEFAULT + +/* Notifier definitions */ +#cmakedefine ASC_NOTIFIERS_OBJECT_POOL_ENTRIES @ASC_NOTIFIERS_OBJECT_POOL_ENTRIES@ + +/* Event loop best effort */ +#cmakedefine ASC_BEST_EFFORT_EVENT_LOOP +#cmakedefine ASC_BE_TIMERS_OBJECT_POOL_ENTRIES @ASC_BE_TIMERS_OBJECT_POOL_ENTRIES@ + +/* Flat buffer serializer */ +#cmakedefine ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +#cmakedefine ASC_FLATCC_JSON_PRINTER_OVERWRITE +#cmakedefine ASC_EMITTER_PAGE_CACHE_SIZE @ASC_EMITTER_PAGE_CACHE_SIZE@ +#cmakedefine FLATCC_NO_ASSERT +/* FLATCC_ASSERT might be redefined in platform area */ +#cmakedefine FLATCC_ASSERT @FLATCC_ASSERT@ +#cmakedefine FLATCC_USE_GENERIC_ALIGNED_ALLOC +#cmakedefine FLATCC_EMITTER_PAGE_SIZE @FLATCC_EMITTER_PAGE_SIZE@ + +/* Tests definitions */ +// Set ASC_FIRST_FORCE_COLLECTION_INTERVAL to '-1' to force immediatly collecting +#cmakedefine ASC_FIRST_FORCE_COLLECTION_INTERVAL @ASC_FIRST_FORCE_COLLECTION_INTERVAL@ +#cmakedefine ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES @ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES@ +#cmakedefine ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES @ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES@ +#cmakedefine ASC_EXTRA_COMPONENTS_COUNT @ASC_EXTRA_COMPONENTS_COUNT@ +#ifndef ASC_EXTRA_COMPONENTS_COUNT +#define ASC_EXTRA_COMPONENTS_COUNT 0 +#endif +#cmakedefine ASC_EXTRA_COLLECTORS_COUNT @ASC_EXTRA_COLLECTORS_COUNT@ +#ifndef ASC_EXTRA_COLLECTORS_COUNT +#define ASC_EXTRA_COLLECTORS_COUNT 0 +#endif + +#define LOOP_ASSERT_FAIL for (\;\;) { } +#define LOOP_ASSERT(s) if (!(s)) {LOOP_ASSERT_FAIL} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/base_dist.cmake b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/base_dist.cmake new file mode 100644 index 00000000..9a6a3a72 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/base_dist.cmake @@ -0,0 +1,37 @@ +set(ASC_SECURITY_MODULE_ID "defender-iot-micro-agent") +set(ASC_FIRST_COLLECTION_INTERVAL 30) +set(ASC_HIGH_PRIORITY_INTERVAL 10) +set(ASC_MEDIUM_PRIORITY_INTERVAL 30) +set(ASC_LOW_PRIORITY_INTERVAL 60) + +set(ASC_COLLECTOR_HEARTBEAT_ENABLED ON) +set(ASC_COLLECTOR_BASELINE_ENABLED OFF) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED OFF) +set(ASC_COLLECTOR_PROCESS_ENABLED OFF) +set(ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED OFF) +set(ASC_COLLECTOR_LISTENING_PORTS_ENABLED OFF) + +set(ASC_COMPONENT_COMMAND_EXECUTOR OFF) +set(ASC_COMPONENT_CONFIGURATION OFF) +set(ASC_COMPONENT_SECURITY_MODULE OFF) + +set(ASC_OPERATIONS_POOL_ENTRIES 50) +set(ASC_BASELINE_REPORT_POOL_ENTRIES 100) +set(ASC_LOG_REPORT_POOL_ENTRIES 100) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 64) +set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 64) +set(ASC_COLLECTOR_PROCESS_IN_CACHE 32) + +set(ASC_DYNAMIC_MEMORY_ENABLED OFF) + +set(ASC_BEST_EFFORT_EVENT_LOOP OFF) + +set(ASC_LOG_TIMESTAMP_DEFAULT ON) + +set(run_core_unittests OFF) +set(run_core_coverage OFF) +set(build_json_printer OFF) +set(FLATCC_NO_ASSERT OFF) +set(FLATCC_USE_GENERIC_ALIGNED_ALLOC ON) +set(ASC_FLATCC_JSON_PRINTER_OVERWRITE OFF) +set(ASC_COMPONENT_CORE_SUPPORTS_RESTART ON) \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/depends_configuration.cmake b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/depends_configuration.cmake new file mode 100644 index 00000000..a4b67b4a --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/depends_configuration.cmake @@ -0,0 +1,47 @@ +if(NOT ASC_COMPONENT_CONFIGURATION) + set(ASC_COMPONENT_CONFIGURATION_PLAT OFF) +endif() + +if(NOT ASC_COMPONENT_COMMAND_EXECUTOR) + set(ASC_OPERATIONS_POOL_ENTRIES 0) + set(ASC_COMPONENT_CONFIGURATION_PLAT OFF) +endif() + +if(NOT ASC_COLLECTOR_BASELINE_ENABLED) + set(ASC_BASELINE_REPORT_POOL_ENTRIES 0) + set(ASC_COMPONENT_BASELINE_PLAT OFF) +endif() + +if(NOT ASC_COLLECTOR_LOG_ENABLED) + set(ASC_LOG_REPORT_POOL_ENTRIES 0) +endif() + +if(NOT ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED) + set(ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS OFF) + set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 0) + set(ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 0) +endif() + +if(NOT ASC_COLLECTOR_PROCESS_ENABLED) + set(ASC_COLLECTOR_PROCESS_SEND_EMPTY_EVENTS OFF) + set(ASC_COLLECTOR_PROCESS_IN_CACHE 0) + set(ASC_COLLECTOR_PROCESS_MODE_AGGREGATED_DISABLE OFF) +endif() + +if(NOT ASC_DYNAMIC_FACTORY_ENABLED) + set(ASC_DYNAMIC_COMPONENTS_MAX 0) + set(ASC_DYNAMIC_COLLECTORS_MAX 0) + set(ASC_DYNAMIC_FACTORY_PATH OFF) + set(ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET OFF) +endif() + +if(FLATCC_NO_ASSERT) + set(FLATCC_ASSERT OFF) +endif() + +if(NOT ASC_DYNAMIC_MEMORY_ENABLED) + set(ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR ON) + set(ASC_EMITTER_PAGE_CACHE_SIZE 1) +else() + set(FLATCC_EMITTER_PAGE_SIZE 14016) +endif() diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/functions.cmake b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/functions.cmake new file mode 100644 index 00000000..904d82de --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/configs/functions.cmake @@ -0,0 +1,102 @@ +macro(CONF_DEPENDS_OPTIONS __core_config_dir) + # include default depends configuration + include(${__core_config_dir}depends_configuration.cmake) +endmacro() + +macro(CONF_DEFINE_BASE __config_path __base) + # include default configuration from specific base dist + include(${__config_path}${__base}) +endmacro() + +macro(CONF_IN_FILE_OPEN __core_config_dir __plat_config_dir __dist __path __ifdef __cpp) + FILE(REMOVE ${__path}) + if(NOT "${__core_config_dir}" STREQUAL "${__plat_config_dir}") + file(READ ${__plat_config_dir}/license __license_body) + else() + file(READ ${__core_config_dir}/license __license_body) + endif() + FILE(APPEND ${__path} ${__license_body}) + if (${__cpp}) + FILE(APPEND ${__path} "\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n") + endif() + + FILE(APPEND ${__path} "/* Distribution ") + FILE(APPEND ${__path} ${__dist} " */") + FILE(APPEND ${__path} \n) + FILE(APPEND ${__path} "#ifndef " ${__ifdef}\n) + FILE(APPEND ${__path} "#define " ${__ifdef}\n\n) +endmacro() + +macro(CONF_IN_FILE_BODY __core_config_dir __plat_config_dir __path) + file(READ ${__core_config_dir}/asc_config.h.in __cfg_body) + FILE(APPEND ${__path} ${__cfg_body}) + if(NOT "${__core_config_dir}" STREQUAL "${__plat_config_dir}") + message("Merging platform asc_config.h.in") + file(READ ${__plat_config_dir}/asc_config.h.in __cfg_body) + FILE(APPEND ${__path} ${__cfg_body}) + endif() + set(__cfg_body "") +endmacro() + +macro(CONF_IN_FILE_CLOSE __path __def __cpp) + FILE(APPEND ${__path} \n) + FILE(APPEND ${__path} "#endif /* ${__def} */") + if (${__cpp}) + FILE(APPEND ${__path} "\n\n#ifdef __cplusplus\n}\n#endif") + endif() +endmacro() + +macro(CONF_IN_CREATE __core_config_dir __plat_config_dir __dist __path __ifdef __cpp) + CONF_IN_FILE_OPEN(${__core_config_dir} ${__plat_config_dir} ${__dist} ${__path} ${__ifdef} ${__cpp}) + CONF_IN_FILE_BODY(${__core_config_dir} ${__plat_config_dir} ${__path}) + CONF_IN_FILE_CLOSE(${__path} ${__ifdef} ${__cpp}) +endmacro() + +macro(CONF_CREATE_DIST __dist __core_config_dir __plat_config_dir __output __ifdef __check_dist __cpp) + if (${__check_dist}) + if (EXISTS ${CMAKE_BINARY_DIR}/built_dist.conf) + FILE(READ ${CMAKE_BINARY_DIR}/built_dist.conf _stored_dist) + if(DEFINED _stored_dist) + if ((NOT (${_stored_dist} STREQUAL "")) AND (NOT (${_stored_dist} STREQUAL ${__dist}))) + message(FATAL_ERROR "Stored dist '${_stored_dist}' is not equal to current dist '${__dist}' - perform rebuild") + endif() + endif() + endif() + endif() + message("Seting distribution " ${__config_dir}${__dist}) + set(g_core_config_path ${__core_config_dir}) + set(g_plat_config_path ${__plat_config_dir}) + + # configure target dist + include(${__plat_config_dir}${__dist}.dist) + + # set depends from ${__core_config_dir}depends_configuration.cmake + CONF_DEPENDS_OPTIONS(${__core_config_dir}) + + # create asc_config.h.in.tmp for target dist + CONF_IN_CREATE(${__core_config_dir} ${__plat_config_dir} ${__dist} ${CMAKE_BINARY_DIR}/asc_config.h.in.tmp ${__ifdef} ${__cpp}) + configure_file(${CMAKE_BINARY_DIR}/asc_config.h.in.tmp ${__output} @ONLY) + + # store current dist + if (${__check_dist}) + FILE(WRITE ${CMAKE_BINARY_DIR}/built_dist.conf ${__dist}) + endif() + + # clean up + FILE(REMOVE ${CMAKE_BINARY_DIR}/asc_config.h.in.tmp) +endmacro() + +macro(CONF_LOG_LEVEL) + if(NOT DEFINED log_level) + set(log_level NOTSET) + endif() + set(LOG_LEVELS NOTSET FATAL ERROR WARNING INFO DEBUG) + list(FIND LOG_LEVELS ${log_level} log_level_index) + if(log_level_index EQUAL -1) + message(FATAL_ERROR "log_level must be one of ${LOG_LEVELS}") + endif() + set(ASC_LOG_LEVEL ${log_level_index}) +endmacro() + +macro(CONF_INC_CLEAN) +endmacro() \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/CMakeLists.txt b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/CMakeLists.txt index d6c5c108..ef172e14 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/CMakeLists.txt +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/CMakeLists.txt @@ -7,16 +7,11 @@ set(build_as_32 OFF CACHE BOOL "build as 32 bit") # Build flatcc runtime library add_library(flatccrt STATIC - $<$>:${CMAKE_CURRENT_SOURCE_DIR}/flatcc/src/runtime/emitter.c> - + flatcc/src/runtime/emitter.c flatcc/src/runtime/builder.c flatcc/src/runtime/refmap.c ) -target_compile_definitions(flatccrt PUBLIC - FLATCC_NO_ASSERT - $<$>:FLATCC_EMITTER_PAGE_SIZE=14016> -) target_include_directories(flatccrt PUBLIC flatcc/include) target_compile_options(flatccrt @@ -24,7 +19,7 @@ target_compile_options(flatccrt $<$:-m32> ) -if(${run_unittests} OR ${build_json_printer}) +if(${run_core_unittests} OR ${build_json_printer}) add_library(flatccrt_json STATIC flatcc/src/runtime/json_printer.c ) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_alloc.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_alloc.h index af6b79fc..06ca4a0b 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_alloc.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_alloc.h @@ -45,16 +45,16 @@ extern "C" { #include +#include /* ASC Disable memory allocation usage */ +#ifdef ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR #define FLATCC_ALLOC(n) NULL #define FLATCC_FREE(p) NULL #define FLATCC_REALLOC(p,n) NULL #define FLATCC_CALLOC(nm,n) NULL #define FLATCC_ALIGNED_ALLOC(a,n) NULL #define FLATCC_ALIGNED_FREE(p) NULL -#ifndef FLATCC_USE_GENERIC_ALIGNED_ALLOC -#define FLATCC_USE_GENERIC_ALIGNED_ALLOC -#endif +#endif /* ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR */ #ifndef FLATCC_ALLOC #define FLATCC_ALLOC(n) malloc(n) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_assert.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_assert.h index 3db3e7b0..7e9ccd3b 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_assert.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_assert.h @@ -1,5 +1,6 @@ #ifndef FLATCC_ASSERT_H #define FLATCC_ASSERT_H +#include #ifdef __cplusplus extern "C" { @@ -31,6 +32,13 @@ extern "C" { #define FLATCC_ASSERT(x) ((void)0) /* Grisu3 is used for floating point conversion in JSON processing. */ #define GRISU3_NO_ASSERT +#define __SET_ASSERT__ +#define __ASSERT_VAL__ +#define __ASSERT_REASON__ +#else +extern int __SET_ASSERT__; +extern int __ASSERT_VAL__; +extern const char *__ASSERT_REASON__; #endif #ifndef FLATCC_ASSERT diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_emitter.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_emitter.h index 6216c516..69026e4e 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_emitter.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_emitter.h @@ -5,6 +5,9 @@ extern "C" { #endif +#ifdef ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +#include "asc_security_core/serializer/page_allocator.h" +#endif /* * Default implementation of a flatbuilder emitter. * @@ -16,6 +19,8 @@ extern "C" { #include #include +#include + #include "flatcc/flatcc_types.h" #include "flatcc/flatcc_iov.h" #include "flatcc/flatcc_alloc.h" diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_endian.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_endian.h index 0592f313..c07b7bce 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_endian.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/flatcc_endian.h @@ -97,11 +97,11 @@ extern "C" { /* flatcc/portable/pendian.h sets LITTLE/BIG flags if possible, and always defines le16toh. */ #ifndef flatbuffers_is_native_pe -#if defined(__LITTLE_ENDIAN__) || FLATBUFFERS_LITTLEENDIAN +#if (__LITTLE_ENDIAN__==1) || FLATBUFFERS_LITTLEENDIAN #undef FLATBUFFERS_LITTLEENDIAN #define FLATBUFFERS_LITTLEENDIAN 1 #define flatbuffers_is_native_pe() (FLATBUFFERS_PROTOCOL_IS_LE) -#elif defined(__BIG_ENDIAN__) || (defined(FLATBUFFERS_LITTLEENDIAN) && !FLATBUFFERS_LITTLEENDIAN) +#elif (__BIG_ENDIAN__==1) || (defined(FLATBUFFERS_LITTLEENDIAN) && !FLATBUFFERS_LITTLEENDIAN) #undef FLATBUFFERS_LITTLEENDIAN #define FLATBUFFERS_LITTLEENDIAN 0 #define flatbuffers_is_native_pe() (FLATBUFFERS_PROTOCOL_IS_BE) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian.h index 122ba8e2..3b174ba0 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian.h @@ -131,7 +131,7 @@ extern "C" { /* Assume it goes for all. */ #if !defined(le16toh) -#if defined(__LITTLE_ENDIAN__) +#if (__LITTLE_ENDIAN__==1) #define le16toh(v) (v) #define le32toh(v) (v) @@ -149,7 +149,7 @@ extern "C" { #define htobe32(v) bswap32(v) #define htobe64(v) bswap64(v) -#elif defined(__BIG_ENDIAN__) +#elif (__BIG_ENDIAN__==1) #define le16toh(v) bswap16(v) #define le32toh(v) bswap32(v) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian_detect.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian_detect.h index 1dd62c04..5b8bf054 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian_detect.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pendian_detect.h @@ -33,11 +33,11 @@ extern "C" { #ifdef __BYTE_ORDER__ -#if defined(__LITTLE_ENDIAN__) && __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ +#if (__LITTLE_ENDIAN__ == 1) && __BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__ #error __LITTLE_ENDIAN__ inconsistent with __BYTE_ORDER__ #endif -#if defined(__BIG_ENDIAN__) && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ +#if (__BIG_ENDIAN__ == 1) && __BYTE_ORDER__ != __ORDER_BIG_ENDIAN__ #error __BIG_ENDIAN__ inconsistent with __BYTE_ORDER__ #endif @@ -45,7 +45,7 @@ extern "C" { #if \ - defined(__LITTLE_ENDIAN__) || \ + (__LITTLE_ENDIAN__ == 1) || \ (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) || \ defined(__ARMEL__) || defined(__THUMBEL__) || \ defined(__AARCH64EL__) || \ @@ -57,20 +57,20 @@ extern "C" { defined(_M_IA64) || defined(_M_ALPHA) || \ defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || \ defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ - defined(__bfin__) + defined(__bfin__) || defined(__LIT) #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__ #endif #if \ - defined (__BIG_ENDIAN__) || \ + (__BIG_ENDIAN__ == 1) || \ (defined(__BYTE_ORDER) && __BYTE_ORDER == __ORDER_BIG_ENDIAN) || \ defined(__ARMEB__) || defined(THUMBEB__) || defined (__AARCH64EB__) || \ defined(_MIPSEB) || defined(__MIPSEB) || defined(__MIPSEB__) || \ defined(__sparc) || defined(__sparc__) || \ defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || \ - defined(__hpux) || defined(__hppa) || defined(__s390__) + defined(__hpux) || defined(__hppa) || defined(__s390__) || defined(__BIG) #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ @@ -107,7 +107,7 @@ extern "C" { #endif #endif /* __BYTE_ORDER__ */ -#if defined(__LITTLE_ENDIAN__) && defined(__BIG_ENDIAN__) +#if (__LITTLE_ENDIAN__ == 1) && (__BIG_ENDIAN__ == 1) #error conflicting definitions of __LITTLE_ENDIAN__ and __BIG_ENDIAN__ #endif diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdalign.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdalign.h index 207ecfc5..65e51a48 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdalign.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdalign.h @@ -124,7 +124,9 @@ extern "C" { #define _Alignas(t) __declspec (align(t)) #define _Alignof(t) __alignof(t) - +#elif defined(__CCRX__) +#define alignas(t) +#define alignof(t) #else #error please update pstdalign.h with support for current compiler and library #endif diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdint.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdint.h index 14444aa7..844662f0 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdint.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/include/flatcc/portable/pstdint.h @@ -190,7 +190,9 @@ #include #include +#if !defined(__CCRX__) #include +#endif /* * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/builder.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/builder.c index d77f1830..7ea58f19 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/builder.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/builder.c @@ -18,7 +18,13 @@ #include "flatcc/flatcc_builder.h" #include "flatcc/flatcc_emitter.h" +#include "flatcc/flatcc_assert.h" +#ifndef FLATCC_NO_ASSERT +int __SET_ASSERT__ = 0; +int __ASSERT_VAL__ = 0; +const char *__ASSERT_REASON__ = ""; +#endif /* * `check` is designed to handle incorrect use errors that can be * ignored in production of a tested product. @@ -314,7 +320,7 @@ static inline void *reserve_buffer(flatcc_builder_t *B, int alloc_type, size_t u if (used + need > buf->iov_len) { if (B->alloc(B->alloc_context, buf, used + need, zero_init, alloc_type)) { - check(0, "memory allocation failed"); + check(__SET_ASSERT__, "memory allocation failed"); return 0; } } @@ -664,11 +670,11 @@ static inline flatcc_builder_ref_t emit_front(flatcc_builder_t *B, iov_state_t * (iov->len > 16 && iov->len - 16 > FLATBUFFERS_UOFFSET_MAX) || #endif ref >= B->emit_start) { - check(0, "buffer too large to represent"); + check(__SET_ASSERT__, "buffer too large to represent"); return 0; } if (B->emit(B->emit_context, iov->iov, iov->count, ref, iov->len)) { - check(0, "emitter rejected buffer content"); + check(__SET_ASSERT__, "emitter rejected buffer content"); return 0; } return B->emit_start = ref; @@ -690,11 +696,11 @@ static inline flatcc_builder_ref_t emit_back(flatcc_builder_t *B, iov_state_t *i * separately. */ if (B->emit_end < ref) { - check(0, "buffer too large to represent"); + check(__SET_ASSERT__, "buffer too large to represent"); return 0; } if (B->emit(B->emit_context, iov->iov, iov->count, ref, iov->len)) { - check(0, "emitter rejected buffer content"); + check(__SET_ASSERT__, "emitter rejected buffer content"); return 0; } /* @@ -719,7 +725,7 @@ static int align_to_block(flatcc_builder_t *B, uint16_t *align, uint16_t block_a init_iov(); push_iov(_pad, end_pad); if (0 == emit_back(B, &iov)) { - check(0, "emitter rejected buffer content"); + check(__SET_ASSERT__, "emitter rejected buffer content"); return -1; } } @@ -789,7 +795,7 @@ flatcc_builder_ref_t flatcc_builder_create_buffer(flatcc_builder_t *B, } write_uoffset(&object_offset, (uoffset_t)object_ref - buffer_base); if (0 == (buffer_ref = emit_front(B, &iov))) { - check(0, "emitter rejected buffer content"); + check(__SET_ASSERT__, "emitter rejected buffer content"); return 0; } return buffer_ref; @@ -1482,7 +1488,7 @@ static flatcc_builder_ref_t _create_offset_vector_direct(flatcc_builder_t *B, if (types) { check(types[i] == 0, "union vector cannot have null element without type NONE"); } else { - check(0, "offset vector cannot have null element"); + check(__SET_ASSERT__, "offset vector cannot have null element"); } } } @@ -1729,7 +1735,6 @@ flatcc_builder_ref_t flatcc_builder_create_string(flatcc_builder_t *B, const cha uoffset_t s_pad; uoffset_t length_prefix; iov_state_t iov; - //int size_exceeded = (uint64_t)len > (uint64_t)max_string_len; #if max_string_len < UINT32_MAX if (len > max_string_len) { @@ -1812,7 +1817,7 @@ void *flatcc_builder_table_add(flatcc_builder_t *B, int id, size_t size, uint16_ } #else if (B->vs[id] != 0) { - check(0, "table field already set"); + check(__SET_ASSERT__, "table field already set"); return 0; } #endif @@ -1847,7 +1852,7 @@ flatcc_builder_ref_t *flatcc_builder_table_add_offset(flatcc_builder_t *B, int i } #else if (B->vs[id] != 0) { - check(0, "table field already set"); + check(__SET_ASSERT__, "table field already set"); return 0; } #endif @@ -1972,11 +1977,11 @@ void *flatcc_builder_finalize_buffer(flatcc_builder_t *B, size_t *size_out) buffer = FLATCC_BUILDER_ALLOC(size); if (!buffer) { - check(0, "failed to allocated memory for finalized buffer"); + check(__SET_ASSERT__, "failed to allocated memory for finalized buffer"); goto done; } if (!flatcc_builder_copy_buffer(B, buffer, size)) { - check(0, "default emitter declined to copy buffer"); + check(__SET_ASSERT__, "default emitter declined to copy buffer"); FLATCC_BUILDER_FREE(buffer); buffer = 0; } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_emitter.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/emitter.c similarity index 89% rename from addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_emitter.c rename to addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/emitter.c index e443dbff..fe89d234 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_emitter.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/emitter.c @@ -1,27 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - - - - +#include -#include "page_allocator.h" +#include #ifdef ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR +#include "asc_security_core/serializer/page_allocator.h" + #define FLATCC_EMITTER_ALLOC serializer_page_alloc #define FLATCC_EMITTER_FREE serializer_page_free -#endif /* ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR */ - -/* flatcc/src/runtime/emitter.c */ -#include +#endif #include "flatcc/flatcc_rtconfig.h" #include "flatcc/flatcc_emitter.h" @@ -290,5 +276,3 @@ void *flatcc_emitter_copy_buffer(flatcc_emitter_t *E, void *buf, size_t size) memcpy(buf, p->page, FLATCC_EMITTER_PAGE_SIZE - E->back_left); return buf; } - - diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/refmap.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/refmap.c index a2497f02..e346dad5 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/refmap.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/deps/flatcc/src/runtime/refmap.c @@ -102,7 +102,7 @@ int flatcc_refmap_resize(flatcc_refmap_t *refmap, size_t count) refmap->table = _flatcc_refmap_calloc(buckets, sizeof(refmap->table[0])); if (refmap->table == 0) { refmap->table = T_old; - FLATCC_ASSERT(0); /* out of memory */ + FLATCC_ASSERT(__SET_ASSERT__); /* out of memory */ return -1; } } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/asc_result.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/asc_result.h index 9835be01..fb290e0c 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/asc_result.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/asc_result.h @@ -1,16 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef ASC_RESULT_H #define ASC_RESULT_H +#include typedef enum { ASC_RESULT_OK = 0, diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector.h index f9f53863..4ac97c76 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector.h @@ -1,13 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef COLLECTOR_H #define COLLECTOR_H @@ -15,18 +15,15 @@ #include #include -#include "asc_security_core/utils/itime.h" +#include + #include "asc_security_core/asc_result.h" -#include "asc_security_core/collector_enums.h" +#include "asc_security_core/component_info.h" + #include "asc_security_core/object_pool.h" #include "asc_security_core/serializer.h" -#include "asc_security_core/utils/collection/linked_list.h" -#ifndef EXTRA_COLLECTORS_OBJECT_POOL_COUNT -#define COLLECTOR_OBJECT_POOL_COUNT COLLECTOR_TYPE_COUNT -#else -#define COLLECTOR_OBJECT_POOL_COUNT (COLLECTOR_TYPE_COUNT + EXTRA_COLLECTORS_OBJECT_POOL_COUNT) -#endif +#define COLLECTOR_OBJECT_POOL_COUNT COLLECTORS_COUNT typedef struct collector_internal_t collector_internal_t; @@ -51,20 +48,19 @@ typedef asc_result_t (*collector_init_function_t)(collector_internal_t *collecto */ typedef asc_result_t (*collector_serialize_function_t)(collector_internal_t *collector_internal_ptr, serializer_t *serializer); -/** - * @brief Function which used in order to free a specific collector. - * - * @param collector_internal_ptr A handle to the collector internal to deinitialize. - */ -typedef void (*collector_deinit_function_t)(collector_internal_t *collector_internal_ptr); +typedef enum { + COLLECTOR_PRIORITY_HIGH = 0, + COLLECTOR_PRIORITY_MEDIUM = 1, + COLLECTOR_PRIORITY_LOW = 2, + COLLECTOR_PRIORITY_COUNT = 3 +} collector_priority_t; struct collector_internal_t { - collector_type_t type; + collector_enum_t type; collector_priority_t priority; + unsigned long interval; collector_serialize_function_t collect_function; - collector_deinit_function_t deinit_function; - void *state; }; @@ -80,10 +76,11 @@ typedef enum { * */ typedef struct collector_t { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct collector_t); /*@{*/ - bool enabled; /**< Indicates if the collector is enabled. */ + bool disabled; /**< Indicates if the collector is disabled. */ collector_status_t status; unsigned int failure_count; /*@}*/ @@ -92,34 +89,29 @@ typedef struct collector_t { * @name Timestamps */ /*@{*/ - uint32_t last_collected_timestamp; - uint32_t last_sent_timestamp; + unsigned long last_collected_timestamp; + unsigned long last_sent_timestamp; /*@}*/ collector_internal_t internal; } collector_t; OBJECT_POOL_DECLARATIONS(collector_t) -LINKED_LIST_DECLARATIONS(collector_t) - /** - * @brief Initialize a Collector + * @brief Default allocate and initialize collector * - * @param init_function The initialization function of the collector internal + * @param id The component ID provided by component manager on init function + * @param type The collector type + * @param priority The collector priority + * @param event_queue_max_size The event queue max capacity + * @param collect_function The collect function of the collector + * @param interval The interval of sending security messages + * @param state The initial state value * - * @return collector ptr + * @return ASC_RESULT_OK on success, corresponding error code otherwise. */ -collector_t *collector_init(collector_init_function_t init_function); - - -/** - * @brief Deinitialize Collector - * - * @param collector_ptr collector ptr - */ -void collector_deinit(collector_t *collector_ptr); - +asc_result_t collector_default_create(component_id_t id, collector_enum_t type, collector_priority_t priority, collector_serialize_function_t collect_function, unsigned long interval, void *state); /** * @brief Collector priority getter @@ -130,7 +122,6 @@ void collector_deinit(collector_t *collector_ptr); */ collector_priority_t collector_get_priority(collector_t *collector_ptr); - /** * @brief Collector last collected timestamp getter * @@ -138,8 +129,7 @@ collector_priority_t collector_get_priority(collector_t *collector_ptr); * * @return Collector last collected timestamp */ -uint32_t collector_get_last_collected_timestamp(collector_t *collector_ptr); - +unsigned long collector_get_last_collected_timestamp(collector_t *collector_ptr); /** * @brief Collector last collected timestamp setter @@ -147,10 +137,9 @@ uint32_t collector_get_last_collected_timestamp(collector_t *collector_ptr); * @param collector_ptr collector_t* * @param last_collected_timestamp the timestamp * - * @return ASC_RESULT_OK on success, ASC_RESULT_EXCEPTION otherwise + * @return ASC_RESULT_OK on success, corresponding error code otherwise. */ -asc_result_t collector_set_last_collected_timestamp(collector_t *collector_ptr, uint32_t last_collected_timestamp); - +asc_result_t collector_set_last_collected_timestamp(collector_t *collector_ptr, unsigned long last_collected_timestamp); /** * @brief Serialize the events in the collector @@ -164,5 +153,58 @@ asc_result_t collector_set_last_collected_timestamp(collector_t *collector_ptr, */ asc_result_t collector_serialize_events(collector_t *collector, serializer_t *serializer); +/** + * @brief Default collector subscribe to core function + * + * @param id The component ID provided by component manager + * + * @return ASC_RESULT_OK on success, ASC_RESULT_MEMORY_EXCEPTION otherwise + */ +asc_result_t collector_default_subscribe(component_id_t id); + +/** + * @brief Default collector unsubscribe from core function + * + * @param id The component ID provided by component manager + * + * @return ASC_RESULT_OK on success, ASC_RESULT_MEMORY_EXCEPTION otherwise + */ +asc_result_t collector_default_unsubscribe(component_id_t id); + +/** + * @brief Default collector deinit function + * + * @param id The component ID provided by component manager + * + * @return ASC_RESULT_OK on success, ASC_RESULT_MEMORY_EXCEPTION otherwise + */ +asc_result_t collector_default_deinit(component_id_t id); + +/** + * @brief Default collector start function + * + * @param id The component ID provided by component manager + * + * @return ASC_RESULT_OK + */ +asc_result_t collector_default_start(component_id_t id); +/** + * @brief Default collector stop function + * + * @param id The component ID provided by component manager + * + * @return ASC_RESULT_OK + */ +asc_result_t collector_default_stop(component_id_t id); + +#define COLLECTOR_OPS_DEFINITIONS(__ops, __init, __deinit, __subscribe, __unsubscribe, __start, __stop) \ +static component_ops_t _ops##__ops = { \ + .init = __init, \ + .deinit = __deinit, \ + .subscribe = __subscribe, \ + .unsubscribe = __unsubscribe, \ + .start = __start, \ + .stop = __stop, \ +} #endif /* COLLECTOR_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection.h index f60ca828..a2683b4f 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection.h @@ -1,21 +1,24 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef IOTSECURITY_COLLECTOR_COLLECTION_H #define IOTSECURITY_COLLECTOR_COLLECTION_H #include + +#include + #include "asc_security_core/asc_result.h" #include "asc_security_core/collector.h" -#include "asc_security_core/utils/collection/linked_list.h" +#include "asc_security_core/utils/collection/list.h" typedef struct priority_collectors priority_collectors_t; typedef struct collector_collection collector_collection_t; @@ -26,7 +29,7 @@ typedef struct collector_collection collector_collection_t; * * @return A @c collector_collection_t* representing the newly created collector collection. */ -collector_collection_t *collector_collection_init(); +collector_collection_t *collector_collection_init(void); /** @@ -36,6 +39,24 @@ collector_collection_t *collector_collection_init(); */ void collector_collection_deinit(collector_collection_t *collector_collection_ptr); +/** + * @brief Register collector to collector_collection + * + * @param collector_collection_ptr the collector colleciton + * @param collector_ptr a @c collector_t* collector handle + * @param random_collect_offset a random start collection offset + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. + */ +asc_result_t collector_collection_register(collector_collection_t *collector_collection_ptr, collector_t *collector_ptr, unsigned long collect_offset); + +/** + * @brief Unregister collector from collector_collection + * + * @param collector_collection_ptr the collector colleciton + * @param collector_ptr a @c collector_t* collector handle + */ +void collector_collection_unregister(collector_collection_t *collector_collection_ptr, collector_t *collector_ptr); /** * @brief Return CollectorCollection specific priority collection @@ -76,7 +97,7 @@ priority_collectors_t *collector_collection_get_next_priority(collector_collecti * * @return A @c collector_t* collector handle with the same type */ -collector_t *collector_collection_get_collector_by_priority(collector_collection_t *collector_collection_ptr, collector_type_t type); +collector_t *collector_collection_get_collector_by_priority(collector_collection_t *collector_collection_ptr, collector_enum_t type); /** @@ -85,38 +106,16 @@ collector_t *collector_collection_get_collector_by_priority(collector_collection * @param action_function a predicate to call to for each collector * @param context caller context */ -void collector_collection_foreach(collector_collection_t *collector_collection_ptr, linked_list_collector_t_action action_function, void *context); - - -/** - * @brief returns the interval in seconds of the priority collection - * - * @param priority_collectors_ptr the priority collection - * - * @return A @c uint32_t which stands for the interval in seconds of the priority collection - */ -uint32_t priority_collectors_get_interval(priority_collectors_t *priority_collectors_ptr); - - -/** - * @brief priority collectors interval setter - * - * @param priority_collectors_ptr priority collectors ptr - * @param interval interval in seconds - * - * @return asc_result_t - */ -asc_result_t priority_collectors_set_interval(priority_collectors_t *priority_collectors_ptr, uint32_t interval); - +void collector_collection_foreach(collector_collection_t *collector_collection_ptr, void(*action_function)(collector_t *collector, void *context), void *context); /** * @brief returns the list of collectors of the priority collection * * @param priority_collectors_ptr the priority collection * - * @return A @c linked_list_collector_t which stands for the list of collectors of the priority collection + * @return A @c linked_list_t which stands for the list of collectors of the priority collection */ -linked_list_collector_t_handle priority_collectors_get_list(priority_collectors_t *priority_collectors_ptr); +linked_list_t *priority_collectors_get_list(priority_collectors_t *priority_collectors_ptr); /** diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_factory.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_factory.h deleted file mode 100644 index c476fb24..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_factory.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef IOTSECURITY_COLLECTOR_COLLECTION_FACTORY_H -#define IOTSECURITY_COLLECTOR_COLLECTION_FACTORY_H - - -#include -#include "asc_security_core/collector_collection.h" -#include "asc_security_core/asc_result.h" - -/** - * @brief Initialize an collector_init_function_t array with init functions of enabled collectors - * - * @param init_array out param -given array to populate - * @param init_array_size array size - * - * @return An @c asc_result_t indicating the status of the call. - */ -asc_result_t collector_collection_factory_get_initialization_array(collector_init_function_t **init_array, uint32_t *init_array_size); - -#endif /* IOTSECURITY_COLLECTOR_COLLECTION_FACTORY_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_internal.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_internal.h deleted file mode 100644 index 7d38a301..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_collection_internal.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef IOTSECURITY_COLLECTOR_COLLECTION_INTERNAL_H -#define IOTSECURITY_COLLECTOR_COLLECTION_INTERNAL_H - -#include -#include "asc_security_core/collector_collection.h" -#include "asc_security_core/asc_result.h" - -/** - * @brief Initialize startup time for each collector in the collection - * - * @param collector_collection collector collection - * - * @return An @c asc_result_t indicating the status of the call. - */ -asc_result_t collector_collection_internal_init_startup_time(collector_collection_t *collector_collection_ptr); - -#endif /* IOTSECURITY_COLLECTOR_COLLECTION_INTERNAL_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_enums.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_enums.h deleted file mode 100644 index ed6fe513..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collector_enums.h +++ /dev/null @@ -1,55 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _COLLECTOR_ENUMS_H_ -#define _COLLECTOR_ENUMS_H_ - -#include - -#include "asc_security_core/configuration.h" - -#define COLLECTOR_NAME_SYSTEM_INFORMATION "SystemInformation" -#define COLLECTOR_NAME_NETWORK_ACTIVITY "NetworkActivity" -#define COLLECTOR_NAME_LISTENING_PORTS "ListeningPorts" -#define COLLECTOR_NAME_HEARTBEAT "Heartbeat" -#define COLLECTOR_NAME_BASELINE "Baseline" - -typedef enum { -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED - COLLECTOR_TYPE_SYSTEM_INFORMATION, -#endif -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED - COLLECTOR_TYPE_NETWORK_ACTIVITY, -#endif -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED - COLLECTOR_TYPE_LISTENING_PORTS, -#endif -#ifdef COLLECTOR_HEARTBEAT_ENABLED - COLLECTOR_TYPE_HEARTBEAT, -#endif -#ifdef COLLECTOR_BASELINE_ENABLED - COLLECTOR_TYPE_BASELINE, -#endif - COLLECTOR_TYPE_COUNT -} collector_type_t; - -extern const char *g_collector_names[COLLECTOR_TYPE_COUNT]; - -typedef enum { - COLLECTOR_PRIORITY_HIGH = 0, - COLLECTOR_PRIORITY_MEDIUM = 1, - COLLECTOR_PRIORITY_LOW = 2, - COLLECTOR_PRIORITY_COUNT = 3 -} collector_priority_t; - -extern const uint32_t g_collector_collections_intervals[COLLECTOR_PRIORITY_COUNT]; - -#endif /* _COLLECTOR_ENUMS_H_ */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/heartbeat.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/heartbeat.h deleted file mode 100644 index a5a9e076..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/heartbeat.h +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _HEARTBEAT_INFORMATION_H -#define _HEARTBEAT_INFORMATION_H - -#include "asc_security_core/collector.h" - -/** - * @brief Initialize Heartbeat Collector - * - * @param collector_internal_ptr A handle to the collector internal to initialize. - * - * @return ASC_RESULT_OK on success - */ -asc_result_t collector_heartbeat_init(collector_internal_t *collector_internal_ptr); - -#endif /* _HEARTBEAT_INFORMATION_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/network_activity.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/network_activity.h deleted file mode 100644 index 8be732be..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/network_activity.h +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _COLLECTOR_NETWORK_ACTIVITY_H -#define _COLLECTOR_NETWORK_ACTIVITY_H - -#include "asc_security_core/collector.h" - -/** - * @brief Initialize NetworkActivity Collector - * - * @param collector_internal_ptr A handle to the collector internal to initialize. - * - * @return ASC_RESULT_OK on success - */ -asc_result_t collector_network_activity_init(collector_internal_t *collector_internal_ptr); - -#endif /* _COLLECTOR_NETWORK_ACTIVITY_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/system_information.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/system_information.h deleted file mode 100644 index 6eb0f888..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors/system_information.h +++ /dev/null @@ -1,26 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _COLLECTOR_SYSTEM_INFORMATION_H -#define _COLLECTOR_SYSTEM_INFORMATION_H - -#include "asc_security_core/collector.h" - -/** - * @brief Initialize SystemInformation Collector - * - * @param collector_internal_ptr A handle to the collector internal to initialize. - * - * @return ASC_RESULT_OK on success - */ -asc_result_t collector_system_information_init(collector_internal_t *collector_internal_ptr); - -#endif /* _COLLECTOR_SYSTEM_INFORMATION_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_headers.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_headers.h deleted file mode 100644 index 5906076d..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_headers.h +++ /dev/null @@ -1,38 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _COLLECTORS_HEADERS_H -#define _COLLECTORS_HEADERS_H - -#include "asc_security_core/configuration.h" - -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED -#include "asc_security_core/collectors/system_information.h" -#endif - -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED -#include "asc_security_core/collectors/listening_ports.h" -#endif - -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED -#include "asc_security_core/collectors/network_activity.h" -#endif - -#ifdef COLLECTOR_HEARTBEAT_ENABLED -#include "asc_security_core/collectors/heartbeat.h" -#endif - -#ifdef COLLECTOR_BASELINE_ENABLED -#include "asc_security_core/collectors/baseline.h" -#endif - -#endif /* _COLLECTORS_HEADERS_H */ - diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_info.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_info.h index e84d4ba6..f1e400ce 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_info.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/collectors_info.h @@ -1,26 +1,25 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef _COLLECTORS_INFO_H_ #define _COLLECTORS_INFO_H_ #include -#ifndef EXTRA_COLLECTORS_OBJECT_POOL_COUNT -#define COLLECTORS_INFO_SIZE COLLECTOR_TYPE_COUNT -#else -#define COLLECTORS_INFO_SIZE (COLLECTOR_TYPE_COUNT + EXTRA_COLLECTORS_OBJECT_POOL_COUNT) -#endif +#include + +#define COLLECTORS_INFO_SIZE COLLECTORS_COUNT + typedef struct { - uint32_t interval; + unsigned long interval; } collector_info_t; typedef intptr_t collectors_info_t; @@ -29,7 +28,7 @@ typedef intptr_t collectors_info_t; * * @return Collectors info data struct handler */ -collectors_info_t *collectors_info_init(); +collectors_info_t *collectors_info_init(void); /** * @brief Deinitialize collectors info module diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_id.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_id.h new file mode 100644 index 00000000..cc123560 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_id.h @@ -0,0 +1,50 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENT_ID_H__ +#define __COMPONENT_ID_H__ +#include + +#include "asc_security_core/components_factory_type.h" + +static component_id_t __auto_generated_self_id = 0; + +/** + * @brief Get self ID of specific component. + * Can be called after COMPONENTS_FACTORY_DEFINITION() only. + * + * @return A @c component_id_t component ID. + */ +static inline component_id_t components_manager_get_self_id() +{ + return __auto_generated_self_id; +} + +/** + * @brief Set self ID of specific component. + * Can be called instead COMPONENTS_FACTORY_DEFINITION(). + * + * @param component Component enumerator + * + */ +static inline void components_manager_set_self_id(int component) +{ + __auto_generated_self_id = g_component_factory[component].component.info.id; +} + +/** + * @brief Reset static self ID in specific file. + */ +static inline void components_manager_reset_self_id() +{ + __auto_generated_self_id = 0; +} +#endif \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_info.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_info.h new file mode 100644 index 00000000..1218e9c2 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/component_info.h @@ -0,0 +1,123 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENT_INFO_H__ +#define __COMPONENT_INFO_H__ + +#include + +#include + +#include "asc_security_core/asc_result.h" + +#include "asc_security_core/components_factory_enum.h" +#include "asc_security_core/utils/collection/bit_vector.h" + +BIT_VECTOR_DECLARATIONS(component_owners_t, COMPONENTS_COUNT) + +/** + * @brief Type definition of component ID. + */ +typedef uintptr_t component_id_t; + +/** + * @brief Type definition of life cycle management functions: init(), deinit(), start(), stop(). + */ +typedef asc_result_t (*lcm_func_t)(component_id_t id); + +/** + * @brief State enumerator of built-in component. + */ +typedef enum { + COMPONENT_UNLOADED = 0, + COMPONENT_LOADED, + COMPONENT_FAIL, + COMPONENT_INITIALIZED, + COMPONENT_RUNNING, + COMPONENT_STOPED, + COMPONENT_SUBSCRIBED, + COMPONENT_UNSUBSCRIBED, + COMPONENT_UNDEFINED +} component_state_enum_t; + +/** + * @brief Struct of component internal info. + */ +typedef struct { +/* The current component's state from component_state_enum_t */ + component_state_enum_t state; + +/* The last component's result (like erno but for each component) */ + asc_result_t last_result; + +/* The component's ID */ + component_id_t id; + +/* The component's name */ + const char *name; + +/* The component's enumerator */ + int enumerator; + +/* The component's internal context */ + void *ctx; + +/* The component's external context */ + uintptr_t ext_ctx; + +/* Disable auto start configuration */ + bool auto_start_disable; + +/* The bit vector of component's owners - who started and stopped it */ + bit_vector_component_owners_t owners; + +/* The log level */ + unsigned int log_level; + +} component_info_t; + +/** + * @brief Struct of component's operations. + */ +typedef struct { +/* The 'init()' function is for internal allocations and subscriptions. Don't use here API from another components, + * don't set timers, don't send notifications etc. + */ + lcm_func_t init; + +/* The 'subscribe()' is place to registrate and subscribe to APIs from another components. */ + lcm_func_t subscribe; + +/* The 'start()' is place to set timers, send notifications and start the component's logic. */ + lcm_func_t start; + +/* The 'deinit()' function is for free internal memory. Don't use here API from another components, + * don't set/delete timers, don't send notifications etc. + */ + lcm_func_t deinit; + +/* The 'unsubscribe()' is place to unregistrate and unsubscribe from APIs from another components. */ + lcm_func_t unsubscribe; + +/* The 'stop()' is place to delete timers, send notifications and finalize all running sequence of component. */ + lcm_func_t stop; + +} component_ops_t; + +/** + * @brief Struct of component's. + */ +typedef struct { + component_info_t info; + component_ops_t *ops; +} component_t; + +#endif \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory.h new file mode 100644 index 00000000..a9757951 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory.h @@ -0,0 +1,46 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENTS_FACTORY_H__ +#define __COMPONENTS_FACTORY_H__ + +#include +#include + +#include + +#include "asc_security_core/logger.h" +#include "asc_security_core/utils/string_utils.h" +#include "asc_security_core/components_factory_type.h" +#include "asc_security_core/component_id.h" + +/** + * @brief Macros for generating load and get_id functions for built-in components. + * + * @param _component Component generated name from @c component_enum_t and @c collector_enum_t + */ +/* Add this declaration in inc/asc_security_core/components_factory_enum.h. */ +#define COMPONENTS_FACTORY_DECLARATION(_component) \ +extern component_load_function_t components_factory_##_component##_load_ptr; + +#define COMPONENTS_FACTORY_DEFINITION(_component, _ops) \ +asc_result_t components_factory_##_component##_load(void);\ +asc_result_t components_factory_##_component##_load(void) { \ + asc_result_t result = components_factory_set(#_component, _component, _ops, false); \ + __auto_generated_self_id = g_component_factory[_component].component.info.id; \ + return result; \ +} \ +component_load_function_t components_factory_##_component##_load_ptr = components_factory_##_component##_load; + +/* Add this macro in src/components_factory.c */ +#define COMPONENTS_FACTORY_LOAD(_component) &components_factory_##_component##_load_ptr + +#endif // __COMPONENTS_FACTORY_H__ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_declarations.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_declarations.h new file mode 100644 index 00000000..e7abe905 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_declarations.h @@ -0,0 +1,64 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENTS_FACTORY_DECLARATIONS_H__ +#define __COMPONENTS_FACTORY_DECLARATIONS_H__ +#include + +#include "asc_security_core/components_factory.h" + +COMPONENTS_FACTORY_DECLARATION(ManagerCore) +#ifdef ASC_COMPONENT_SECURITY_MODULE + COMPONENTS_FACTORY_DECLARATION(SecurityModule) +#endif +COMPONENTS_FACTORY_DECLARATION(CollectorsCore) +COMPONENTS_FACTORY_DECLARATION(Logger) +#ifdef ASC_COMPONENT_CONFIGURATION + COMPONENTS_FACTORY_DECLARATION(Configuration) +#endif +#ifdef ASC_COMPONENT_CONFIGURATION_PLAT + COMPONENTS_FACTORY_DECLARATION(ConfigurationPlatform) +#endif +#ifdef ASC_COMPONENT_COMMAND_EXECUTOR_PLAT + COMPONENTS_FACTORY_DECLARATION(CommandExecutorPlatform) +#endif +#ifdef ASC_COLLECTOR_HEARTBEAT_ENABLED + COMPONENTS_FACTORY_DECLARATION(Heartbeat) +#endif +#ifdef ASC_COLLECTOR_BASELINE_ENABLED + COMPONENTS_FACTORY_DECLARATION(Baseline) +#endif +#ifdef ASC_COMPONENT_BASELINE_PLAT + COMPONENTS_FACTORY_DECLARATION(BaselinePlatform) +#endif +#ifdef ASC_COMPONENT_IPC_PLAT + COMPONENTS_FACTORY_DECLARATION(IpcPlatform) +#endif +#ifdef ASC_COMPONENT_CLI_PLAT + #ifdef ASC_COMPONENT_DEMO_CLI_PLAT + COMPONENTS_FACTORY_DECLARATION(CliDemoPlatform) + #endif + COMPONENTS_FACTORY_DECLARATION(CliPlatform) +#endif +#ifdef ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + COMPONENTS_FACTORY_DECLARATION(SystemInformation) +#endif +#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED + COMPONENTS_FACTORY_DECLARATION(NetworkActivity) +#endif +#ifdef ASC_COLLECTOR_LISTENING_PORTS_ENABLED + COMPONENTS_FACTORY_DECLARATION(ListeningPorts) +#endif +#ifdef ASC_COLLECTOR_PROCESS_ENABLED + COMPONENTS_FACTORY_DECLARATION(Process) +#endif + +#endif // __COMPONENTS_FACTORY_DECLARATIONS_H__ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_enum.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_enum.h new file mode 100644 index 00000000..04976b26 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_enum.h @@ -0,0 +1,125 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENTS_FACTORY_ENUM_H__ +#define __COMPONENTS_FACTORY_ENUM_H__ +#include + +typedef enum { +#ifdef ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + SystemInformation, +#endif +#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED + NetworkActivity, +#endif +#ifdef ASC_COLLECTOR_LISTENING_PORTS_ENABLED + ListeningPorts, +#endif +#ifdef ASC_COLLECTOR_HEARTBEAT_ENABLED + Heartbeat, +#endif +#ifdef ASC_COLLECTOR_BASELINE_ENABLED + Baseline, +#endif +#ifdef ASC_COLLECTOR_PROCESS_ENABLED + Process, +#endif + __COLLECTOR_COUNT // Must be last +} collector_enum_t; + +#define COLLECTORS_COUNT (__COLLECTOR_COUNT + ASC_EXTRA_COLLECTORS_COUNT + ASC_DYNAMIC_COLLECTORS_MAX) + +/** + * @brief Factory enumerator of all built-in component. + * Components factory has following struct: + * FACTORY_ARRAY[__COLLECTOR_COUNT, ASC_EXTRA_COLLECTORS_COUNT, ASC_DYNAMIC_COLLECTORS_MAX, __COMPONENT_COUNT, ASC_EXTRA_COMPONENTS_COUNT, ASC_DYNAMIC_COMPONENTS_MAX] + * COLLECTORS_COUNT + * |________________________________________________________________________| + * COMPONENTS_COUNT + * |___________________________________________________________________________________________________________________________________________________| + */ +/** + * @brief Factory enumerator of collectors. This enumerator comes first in component enum. + * + * : + * : 0 + * CollectorN1 + * CollectorNx + * : __COLLECTOR_COUNT + * : + * : __COLLECTOR_COUNT + * CollectorExtraN1 + * CollectorExtraNx + * : __COLLECTOR_COUNT + ASC_EXTRA_COLLECTORS_COUNT + * : + * : __COLLECTOR_COUNT + ASC_DYNAMIC_COLLECTORS_MAX + * CollectorDynamicN1 + * CollectorDynamicNx + * : COLLECTORS_COUNT = __COLLECTOR_COUNT + ASC_DYNAMIC_COLLECTORS_MAX + ASC_DYNAMIC_COLLECTORS_MAX + * : + * : COLLECTORS_COUNT + * ComponentN1 + * ComponentNx + * : __COMPONENT_COUNT + * : + * : __COMPONENT_COUNT + * ComponentExtraN1 + * ComponentExtraNx + * : + * : __COMPONENT_COUNT + ASC_EXTRA_COMPONENTS_COUNT + * ComponentDynamicN1 + * ComponentDynamicNx + * : COMPONENTS_COUNT = __COMPONENT_COUNT + ASC_EXTRA_COMPONENTS_COUNT + ASC_DYNAMIC_COMPONENTS_MAX + * + * Each component should be defined in 5 places: + * in @c component_enum_t or @c collector_enum_t enum: ComponentName or CollectorName + * The enum must contain the following characters only: [a-zA-Z0-9]* + * in inc/asc_security_core/components_factory_declarations.h: @c COMPONENTS_FACTORY_DECLARATION(ComponentName) + * in src/component_factory.c:component_load_function_array[]: @c COMPONENTS_FACTORY_LOAD(ComponentName); + * in component's code: @c COMPONENTS_FACTORY_DEFINITION(ComponentName, &ops) + * in compilation enviroments: @c -DComponentName + * + * @param _component Component generated name from @c component_enum_t + */ +typedef enum { + ManagerCore = COLLECTORS_COUNT, //first and always exists +#ifdef ASC_COMPONENT_SECURITY_MODULE + SecurityModule, +#endif + CollectorsCore, +#ifdef ASC_COMPONENT_CONFIGURATION + Configuration, +#endif +#ifdef ASC_COMPONENT_CONFIGURATION_PLAT + ConfigurationPlatform, +#endif +#ifdef ASC_COMPONENT_COMMAND_EXECUTOR_PLAT + CommandExecutorPlatform, +#endif +#ifdef ASC_COMPONENT_BASELINE_PLAT + BaselinePlatform, +#endif +#ifdef ASC_COMPONENT_IPC_PLAT + IpcPlatform, +#endif +#ifdef ASC_COMPONENT_CLI_PLAT + CliPlatform, + #ifdef ASC_COMPONENT_DEMO_CLI_PLAT + CliDemoPlatform, + #endif +#endif + Logger, + __COMPONENT_COUNT // Must be last +} component_enum_t; + +#define COMPONENTS_COUNT (__COMPONENT_COUNT + ASC_EXTRA_COMPONENTS_COUNT + ASC_DYNAMIC_COMPONENTS_MAX) + +#endif // __COMPONENTS_FACTORY_ENUM_H__ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_type.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_type.h new file mode 100644 index 00000000..3328cdc2 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_factory_type.h @@ -0,0 +1,140 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENTS_FACTORY__TYPE_H__ +#define __COMPONENTS_FACTORY__TYPE_H__ + +#include + +#include + +#include "asc_security_core/asc_result.h" +#include "asc_security_core/component_info.h" + +/** + * @brief Factory load the component function prototype. + */ +typedef asc_result_t (*component_load_function_t)(void); + +/** + * @brief Struct of factory entry. + */ +typedef struct { + component_t component; +} components_factory_t; + +/** + * @brief Factory global array. + */ +extern components_factory_t g_component_factory[]; + +/** + * @brief Get array of component load functions. + * + * @return An @c component_load_function_t array of component load functions. + */ +component_load_function_t **components_factory_get_load_array(void); + +/** + * @brief Factory unload - clean built-in components data from @c g_component_factory . + * + * @return none. + */ +void components_factory_unload(void); + +/** + * @brief Factory unload - clean built-in component with specified index from @c g_component_factory . + * + * @param index A component's index. + * + * @return none. + */ +void component_factory_unload(int index); + +/** + * @brief Generate ID for component with specified index. + * + * @param index A component's index. + * + * @return A component's ID. + */ +component_id_t components_factory_create_id(int index); + +/** + * @brief Insert component with specified index to @c g_component_factory . + * + * @param name A component's name. + * @param index A component's index. + * @param ops A component's LCM ops. + * @param auto_disable Is componet auto disable to run. + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. + */ +asc_result_t components_factory_set(const char *name, int index, component_ops_t *ops, bool auto_disable); + +/** + * @brief Dynamic loading API . + */ +#ifdef ASC_DYNAMIC_FACTORY_ENABLED +/** + * @brief Insert dynamic loaded collector with specified index to @c g_component_factory . + * + * @param name A collector's name. + * @param index A collector's index. + * @param ops A collector's LCM ops. + * @param auto_disable Is collector auto disable to run. + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. + */ +asc_result_t components_factory_set_dynamic_collector(const char *name, int index, component_ops_t *ops, bool auto_disable); + +/** + * @brief Insert dynamic loaded component with specified index to @c g_component_factory . + * + * @param name A component's name. + * @param index A component's index. + * @param ops A component's LCM ops. + * @param auto_disable Is componet auto disable to run. + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. + */ +asc_result_t components_factory_set_dynamic_component(const char *name, int index, component_ops_t *ops, bool auto_disable); + +/** + * @brief Dynamic loading of all existing collectors and componets to @c g_component_factory . + * + * @param __path A directory of dynamic stuff - if NULL taken from components_factory_dynamic_path_set() and ASC_DYNAMIC_FACTORY_PATH. + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. + */ +asc_result_t components_factory_load_dynamic(const char *__path); + +/** + * @brief Unload all dynamic loaded entries from @c g_component_factory . + * + * @return none. + */ +void components_factory_unload_dynamic(void); + + +#ifdef ASC_DYNAMIC_FACTORY_PATH_RUNTIME_SET +/** + * @brief Overwrite default path to dynamic stuff. + * + * @param __path A directory of dynamic stuff. + * + * @return none. + */ +void components_factory_dynamic_path_set(const char *__path); +#endif +#endif // ASC_DYNAMIC_FACTORY_ENABLED + +#endif // __COMPONENTS_FACTORY__TYPE_H__ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_manager.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_manager.h new file mode 100644 index 00000000..ad903928 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/components_manager.h @@ -0,0 +1,176 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __COMPONENTS_MANAGER_H__ +#define __COMPONENTS_MANAGER_H__ +#include + +#include "asc_security_core/asc_result.h" +#include "asc_security_core/components_factory.h" + +/** + * @brief Call init and start function of all declarated built-in components. + * + * @return A @c asc_result_t result. + */ +asc_result_t components_manager_init(void); + +/** + * @brief Set global context. + * + * @param ctx Global Context + * + * @return none. + */ +void components_manager_global_context_set(uintptr_t ctx); + +/** + * @brief Get global context. + * + * @return The global context. + */ +uintptr_t components_manager_global_context_get(void); + +/** + * @brief Call stop and deinit function of all declarated built-in components. + * + * @return A @c asc_result_t result. + */ +asc_result_t components_manager_deinit(void); + +/** + * @brief Get internal component struct by it's ID. + * + * @param id Component ID provided by component manager on init function + * + * @return A @c component_t* representing component. + */ +component_t *components_manager_get_component(component_id_t id); + +/** + * @brief Get internal info of specific component by it's ID. + * + * @param id Component ID provided by component manager on init function + * + * @return A @c component_info_t* representing internal component info. + */ +component_info_t *components_manager_get_info(component_id_t id); + +/** + * @brief Get user component context by it's ID. Avoid using __components_manager_get_ctx() - use private components_manager_get_self_ctx() macro + * + * @param id Component ID provided by component manager on init function + * + * @return A @c void* user context. + */ +void *__components_manager_get_ctx(component_id_t id); +#define components_manager_get_self_ctx() __components_manager_get_ctx(components_manager_get_self_id()) + +/** + * @brief Set user component context by it's ID. Avoid using __components_manager_set_ctx() - use private components_manager_set_self_ctx() macro + * + * @param id Component ID provided by component manager on init function + * + * @param ctx User context to store + * + * @return none. + */ +void __components_manager_set_ctx(component_id_t id, void *ctx); +#define components_manager_set_self_ctx(_ctx) __components_manager_set_ctx(components_manager_get_self_id(), _ctx) + +/** + * @brief Get last result of component. + * + * @param id Component ID provided by component manager on init function + * + * @return A @c asc_result_t result. + */ +asc_result_t components_manager_get_last_result(component_id_t id); + +/** + * @brief Get name of component. + * + * @param id Component ID provided by component manager on init function + * + * @return A component name. + */ +const char *components_manager_get_name(component_id_t id); + +/** + * @brief Set log level to specified component. + * + * @param id Component ID provided by component manager on init function + * @param set Requested log level, if (-1) - reset to default 'ASC_LOG_LEVEL' + * + * @return true on seccess, otherwise false.. + */ +bool components_manager_set_log_level(component_id_t id, int set); + +/** + * @brief Get log level to specified component. + * + * @param id Component ID provided by component manager on init function + * + * @return log level. + */ +unsigned int components_manager_get_log_level(component_id_t id); + +/** + * @brief Set log level to all components. + * + * @param set Requested log level, if (-1) - reset to default 'ASC_LOG_LEVEL' + * + * @return true on seccess, otherwise false.. + */ +bool components_manager_set_log_level_all(int set); + +/** + * @brief Get ID of specific component by it's generated name. + * + * @param name Component name in string format + * @paran len The length of the name + * + * @return A @c component_id_t component ID. + */ +component_id_t components_manager_get_id_by_name(const char *name, size_t len); + +/** + * @brief Get ID of specific component by it's generated name. + * + * @param _component Component generated name from @c component_enum_t or @c collector_enum_t + * + * @return A @c component_id_t component ID. + */ +#define components_manager_get_id(_component) (g_component_factory[_component].component.info.id) + +/** + * @brief Start component. + * + * @param id Component ID provided by component manager on init function + * @param owner_id Component ID that asked the action + * + * @return A @c asc_result_t result. + */ +asc_result_t components_manager_start(component_id_t id, component_id_t owner_id); + +/** + * @brief Stop component. + * + * @param id Component ID provided by component manager on init function + * @param owner_id Component ID that asked the action + * @param ignore_self_owner If component has only self owner stop it + * @param force Force stop and clean owners + * + * @return A @c asc_result_t result. + */ +asc_result_t components_manager_stop(component_id_t id, component_id_t owner_id, bool ignore_self_owner, bool force); + +#endif //__COMPONENTS_MANAGER_H__ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/configuration.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/configuration.h deleted file mode 100644 index 45f6903d..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/configuration.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef CONFIGURATION_H -#define CONFIGURATION_H - -#include "asc_security_core/version.h" - -#ifndef DISABLE_ASC_PORT -#include "asc_port.h" -#else -#include "asc_security_core/no_platform/asc_port.h" -#endif /* DISABLE_ASC_PORT */ - -// Security Module ID - A unique identifier of the device -#ifndef ASC_SECURITY_MODULE_ID -#define ASC_SECURITY_MODULE_ID "iot_security_module" -#endif - -// First collection interval in seconds -#ifndef ASC_FIRST_COLLECTION_INTERVAL -#define ASC_FIRST_COLLECTION_INTERVAL 10 -#endif - -// Collection interval for high priority events, in seconds -#ifndef ASC_HIGH_PRIORITY_INTERVAL -#define ASC_HIGH_PRIORITY_INTERVAL 10 -#endif - -// Collection interval for medium priority events, in seconds -#ifndef ASC_MEDIUM_PRIORITY_INTERVAL -#define ASC_MEDIUM_PRIORITY_INTERVAL 30 -#endif - -// Collection interval for low priority events, in seconds -#ifndef ASC_LOW_PRIORITY_INTERVAL -#define ASC_LOW_PRIORITY_INTERVAL 60 -#endif - -// The maximum number of IPv4 network events to store in memory -#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE -#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE 64 -#endif - -// The maximum number of IPv6 network events to store in memory -#ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE -#define ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE 64 -#endif - -// Send empty Network Activity events -// #define ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS - -// The size of flatcc emitter page cache, when using custom allocator -#ifndef EMITTER_PAGE_CACHE_SIZE -#define EMITTER_PAGE_CACHE_SIZE 1 -#endif - -#endif /* CONFIGURATION_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/core.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/core.h index 9a2921ab..96b8d97b 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/core.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/core.h @@ -1,91 +1,86 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef CORE_H #define CORE_H +#include +#include + +#include + #include "asc_security_core/asc_result.h" #include "asc_security_core/collector_collection.h" #include "asc_security_core/model/security_message.h" - +#define CORE_NEAREST_TIMER_UNSET_VAL LONG_MAX /** - * @struct core_t + * @brief Get a security message from the core. * + * @param core_ptr The core ptr + * @param security_message_ptr The message buffer to write into + * + * @return ASC_RESULT_OK on success, + * ASC_RESULT_EMPTY when there are no events to send, in that case message_ptr remains unchanged, + * ASC_RESULT_EXCEPTION otherwise. */ -typedef struct core { - COLLECTION_INTERFACE(struct core); - - const char *security_module_id; - uint32_t security_module_version; - collector_collection_t *collector_collection_ptr; - - uint8_t *message_buffer; - size_t message_buffer_size; -#ifdef DYNAMIC_MEMORY_ENABLED - bool message_allocated; -#endif - bool message_empty; - - serializer_t *serializer; -} core_t; - +asc_result_t core_message_get(security_message_t* security_message_ptr); /** - * @brief Initialize a new core + * @brief Deinit the last security message. * - * @return A new core + * @return ASC_RESULT_OK on success, + * ASC_RESULT_EXCEPTION otherwise. */ -core_t *core_init(); +asc_result_t core_message_deinit(void); /** - * @brief Deinitialize a core + * @brief Register collector to core * - * @param core_ptr The core to deinit + * @param collector_ptr A @c collector_t* collector handle + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. */ -void core_deinit(core_t *core_ptr); +asc_result_t core_collector_register(collector_t *collector_ptr); /** - * @brief Collect events from all of the registered collectors. + * @brief Unregister collector from collector_collection * - * @param core_ptr the core ptr - * - * @return ASC_RESULT_OK on success, - * ASC_RESULT_EMPTY when there are no events to send, - * ASC_RESULT_EXCEPTION otherwise. + * @param collector_ptr A @c collector_t* collector handle + * + * @return ASC_RESULT_OK on success, corresponding error code otherwise. */ -asc_result_t core_collect(core_t *core_ptr); +asc_result_t core_collector_unregister(collector_t *collector_ptr); /** - * @brief Get a security message from the core. + * @brief Get random generated collection start time, what is generating on startup of system to avoid sending message + * from many devices simultaneously. * - * @param core_ptr The core ptr - * @param security_message_ptr The message buffer to write into - * - * @return ASC_RESULT_OK on success, - * ASC_RESULT_EMPTY when there are no events to send, in that case message_ptr remains unchanged, - * ASC_RESULT_EXCEPTION otherwise. + * @return init_random_collect_offset value. */ -asc_result_t core_message_get(core_t* core_ptr, security_message_t* security_message_ptr); - +unsigned long core_get_init_random_collect_offset(void); /** - * @brief Deinit the last security message. + * @brief Get current (last set) collect time. * - * @param core_ptr the core ptr + * @return nearest_collect_time value. In case of unset timer the CORE_NEAREST_TIMER_UNSET_VAL=LONG_MAX will be returned. + */ +unsigned long core_get_nearest_collect_time(void); + +/** + * @brief Get collectors collections that registered to core * - * @return ASC_RESULT_OK on success, - * ASC_RESULT_EXCEPTION otherwise. + * @return Pointer to collector collection @c collector_collection_t . */ -asc_result_t core_message_deinit(core_t *core_ptr); +collector_collection_t *core_get_collector_collection(void); #endif /* CORE_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/logger.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/logger.h index 2f79b441..ac0ea9c0 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/logger.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/logger.h @@ -1,73 +1,88 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef LOGGER_H #define LOGGER_H -#include "asc_security_core/utils/macros.h" +#include +#include +#include +#include -#define LOG_LEVEL_NOTSET 0 -#define LOG_LEVEL_DEBUG 1 -#define LOG_LEVEL_INFO 2 -#define LOG_LEVEL_WARN 3 -#define LOG_LEVEL_ERROR 4 -#define LOG_LEVEL_FATAL 5 +#include +#define LOG_LEVEL_NOTSET 0 +#define LOG_LEVEL_FATAL 1 +#define LOG_LEVEL_ERROR 2 +#define LOG_LEVEL_WARN 3 +#define LOG_LEVEL_INFO 4 +#define LOG_LEVEL_DEBUG 5 -#if LOG_LEVEL == LOG_LEVEL_NOTSET +#ifndef ASC_LOG_LEVEL +#define ASC_LOG_LEVEL LOG_LEVEL_NOTSET +#endif + +#if ASC_LOG_LEVEL == LOG_LEVEL_NOTSET #define log_debug(...) #define log_info(...) #define log_warn(...) #define log_error(...) #define log_fatal(...) + #define logger_set_system_log_level(_l) + #define logger_set_timestamp(_s) + #define logger_get_system_log_level() (LOG_LEVEL_NOTSET) #else - #include - #include - #include - #include + #include "asc_security_core/utils/macros.h" + #include "asc_security_core/component_id.h" #define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILE__) - #define MDC_FORMAT "%s [%s/%s:%d] " - bool logger_init(); - void logger_deinit(); - void logger_log(const char *level, const char *filename, const char *func, int line, const char *fmt, ...) ATTRIBUTE_FORMAT(5, 6); + bool logger_log(component_id_t id, unsigned int level, const char *filename, const char *func, int line, const char *fmt, ...) ATTRIBUTE_FORMAT(6, 7); +/** + * @brief Set system log level - highest priority. + * + * @param set Requested log level, if (-1) - reset to default 'ASC_LOG_LEVEL' + * + * @return true on seccess, otherwise false. + */ + bool logger_set_system_log_level(int set); + void logger_set_timestamp(bool set); + int logger_get_system_log_level(void); - // define log by severity according to LOG_LEVEL - #if LOG_LEVEL > LOG_LEVEL_DEBUG + // define log by severity according to ASC_LOG_LEVEL + #if ASC_LOG_LEVEL < LOG_LEVEL_DEBUG #define log_debug(...) #else - #define log_debug(...) logger_log("DEBUG", __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) + #define log_debug(...) logger_log(components_manager_get_self_id(), LOG_LEVEL_DEBUG, __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) #endif - #if LOG_LEVEL > LOG_LEVEL_INFO + #if ASC_LOG_LEVEL < LOG_LEVEL_INFO #define log_info(...) #else - #define log_info(...) logger_log("INFO", __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) + #define log_info(...) logger_log(components_manager_get_self_id(), LOG_LEVEL_INFO, __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) #endif - #if LOG_LEVEL > LOG_LEVEL_WARN + #if ASC_LOG_LEVEL < LOG_LEVEL_WARN #define log_warn(...) #else - #define log_warn(...) logger_log("WARN", __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) + #define log_warn(...) logger_log(components_manager_get_self_id(), LOG_LEVEL_WARN, __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) #endif - #if LOG_LEVEL > LOG_LEVEL_ERROR + #if ASC_LOG_LEVEL < LOG_LEVEL_ERROR #define log_error(...) #else - #define log_error(...) logger_log("ERROR", __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) + #define log_error(...) logger_log(components_manager_get_self_id(), LOG_LEVEL_ERROR, __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) #endif - #if LOG_LEVEL > LOG_LEVEL_FATAL + #if ASC_LOG_LEVEL < LOG_LEVEL_FATAL #define log_fatal(...) #else - #define log_fatal(...) logger_log("FATAL", __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) + #define log_fatal(...) logger_log(components_manager_get_self_id(), LOG_LEVEL_FATAL, __FILENAME__, __func__, __LINE__, ##__VA_ARGS__) #endif #endif - -#endif //LOGGER_H \ No newline at end of file +#endif //LOGGER_H diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/mti.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/mti.h index e076d446..3c497a63 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/mti.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/mti.h @@ -1,17 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef _MTI_H_ #define _MTI_H_ - +#include /** * @brief Create Message Type Indicator in format "X.Y-E-S-T", * where "Major.Minor-Encoding-Source-Type". All fields are numeric @@ -19,7 +19,7 @@ #define MTI_NAME "mti" #define SCHEMA_MAJOR_VER "2" -#define SCHEMA_MINOR_VER "0" +#define SCHEMA_MINOR_VER "3" #define JSON_ENCODING "0" #define FLAT_BUFFERS "1" diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/network_activity.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/network_activity.h index 196b3d1d..99602774 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/network_activity.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/network_activity.h @@ -1,19 +1,21 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECT_NETWORK_ACTIVITY_H #define OBJECT_NETWORK_ACTIVITY_H #include +#include + #include "asc_security_core/model/objects/transport_protocol.h" #include "asc_security_core/utils/collection/collection.h" @@ -27,16 +29,18 @@ typedef struct { typedef struct network_activity_ipv4_t { - network_activity_common_t common; + /* This macro must be first in object */ COLLECTION_INTERFACE(struct network_activity_ipv4_t); + network_activity_common_t common; uint32_t local_address; uint32_t remote_address; } network_activity_ipv4_t; typedef struct network_activity_ipv6_t { - network_activity_common_t common; + /* This macro must be first in object */ COLLECTION_INTERFACE(struct network_activity_ipv6_t); + network_activity_common_t common; uint32_t local_address[4]; uint32_t remote_address[4]; } network_activity_ipv6_t; diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/objects.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/objects.h index 53b7e278..b24eec48 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/objects.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/objects.h @@ -1,34 +1,41 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECTS_H #define OBJECTS_H +#include -#include "asc_security_core/configuration.h" +#ifdef ASC_COLLECTOR_LOG_ENABLED +#include "asc_security_core/model/objects/log.h" +#endif -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED +#ifdef ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED #include "asc_security_core/model/objects/system_information.h" #endif -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED +#ifdef ASC_COLLECTOR_LISTENING_PORTS_ENABLED #include "asc_security_core/model/objects/listening_ports.h" #endif -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED +#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED #include "asc_security_core/model/objects/network_activity.h" #endif -#ifdef COLLECTOR_BASELINE_ENABLED +#ifdef ASC_COLLECTOR_BASELINE_ENABLED #include "asc_security_core/model/objects/baseline.h" #include "asc_security_core/model/objects/object_baseline_ext.h" #endif +#ifdef ASC_COLLECTOR_PROCESS_ENABLED +#include "asc_security_core/model/objects/process.h" +#endif + #endif /* OBJECTS_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/system_information.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/system_information.h index 536bcaff..4ac54bf3 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/system_information.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/system_information.h @@ -1,22 +1,25 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECT_SYSTEM_INFORMATION_H #define OBJECT_SYSTEM_INFORMATION_H #include +#include + #include "asc_security_core/utils/collection/collection.h" typedef struct system_information_t { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct system_information_t); char* os_info; diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/transport_protocol.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/transport_protocol.h index 8f816e7a..d7a542df 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/transport_protocol.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/objects/transport_protocol.h @@ -1,16 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef TRANSPORT_PROTOCOL_H #define TRANSPORT_PROTOCOL_H +#include typedef enum { TRANSPORT_PROTOCOL_TCP, diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_parser.h new file mode 100644 index 00000000..c7a49d58 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_parser.h @@ -0,0 +1,424 @@ +#ifndef BASELINE_JSON_PARSER_H +#define BASELINE_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_Result_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); +static const char *AzureIoTSecurity_Severity_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); +static const char *AzureIoTSecurity_BaselineCheck_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *AzureIoTSecurity_Baseline_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *baseline_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *baseline_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *baseline_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_Result_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_sign, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x4641494c00000000) { /* branch "FAIL" */ + if ((w & 0xffffffffff000000) == 0x4552524f52000000) { /* "ERROR" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 5, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "ERROR" */ + return unmatched; + } /* "ERROR" */ + } else { /* branch "FAIL" */ + if ((w & 0xffffffff00000000) == 0x5041535300000000) { /* "PASS" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "PASS" */ + if ((w & 0xffffffff00000000) == 0x4641494c00000000) { /* "FAIL" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(1), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "FAIL" */ + return unmatched; + } /* "FAIL" */ + } /* "PASS" */ + } /* branch "FAIL" */ + return buf; +} + +static const char *AzureIoTSecurity_Severity_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_sign, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x494d504f5254414e) { /* branch "IMPORTAN" */ + if (w == 0x435249544943414c) { /* "CRITICAL" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 8, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "CRITICAL" */ + return unmatched; + } /* "CRITICAL" */ + } else { /* branch "IMPORTAN" */ + if (w < 0x494e464f524d4154) { /* branch "INFORMAT" */ + if (w == 0x494d504f5254414e) { /* descend "IMPORTAN" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x5400000000000000) { /* "T" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 1, aggregate); + if (buf != mark) { + *value = UINT64_C(1), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "T" */ + return unmatched; + } /* "T" */ + } else { /* descend "IMPORTAN" */ + return unmatched; + } /* descend "IMPORTAN" */ + } else { /* branch "INFORMAT" */ + if (w == 0x494e464f524d4154) { /* descend "INFORMAT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffff000000) == 0x494f4e414c000000) { /* "IONAL" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 5, aggregate); + if (buf != mark) { + *value = UINT64_C(3), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "IONAL" */ + return unmatched; + } /* "IONAL" */ + } else { /* descend "INFORMAT" */ + if ((w & 0xffffffffffffff00) == 0x5741524e494e4700) { /* "WARNING" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 7, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "WARNING" */ + return unmatched; + } /* "WARNING" */ + } /* descend "INFORMAT" */ + } /* branch "INFORMAT" */ + } /* branch "IMPORTAN" */ + return buf; +} + +static const char *AzureIoTSecurity_BaselineCheck_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 6)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x6964000000000000) { /* branch "id" */ + if (w == 0x6465736372697074) { /* descend "descript" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffff0000000000) == 0x696f6e0000000000) { /* "ion" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 3); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 3))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "ion" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "ion" */ + } else { /* descend "descript" */ + if ((w & 0xffffffffff000000) == 0x6572726f72000000) { /* "error" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 2))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "error" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "error" */ + } /* descend "descript" */ + } else { /* branch "id" */ + if (w < 0x72656d6564696174) { /* branch "remediat" */ + if ((w & 0xffff000000000000) == 0x6964000000000000) { /* "id" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "id" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "id" */ + } else { /* branch "remediat" */ + if (w < 0x726573756c740000) { /* branch "result" */ + if (w == 0x72656d6564696174) { /* descend "remediat" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffff0000000000) == 0x696f6e0000000000) { /* "ion" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 3); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 5))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "ion" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "ion" */ + } else { /* descend "remediat" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "remediat" */ + } else { /* branch "result" */ + if (w == 0x7365766572697479) { /* "severity" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 8); + if (mark != buf) { + int8_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + AzureIoTSecurity_Severity_parse_json_enum, + baseline_local_AzureIoTSecurity_json_parser_enum, + baseline_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_int8(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_int8(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 4, 1, 1))) goto failed; + flatbuffers_int8_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "severity" */ + if ((w & 0xffffffffffff0000) == 0x726573756c740000) { /* "result" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6); + if (mark != buf) { + int8_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + AzureIoTSecurity_Result_parse_json_enum, + baseline_local_AzureIoTSecurity_json_parser_enum, + baseline_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_int8(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_int8(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 1, 1, 1))) goto failed; + flatbuffers_int8_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "result" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "result" */ + } /* "severity" */ + } /* branch "result" */ + } /* branch "remediat" */ + } /* branch "id" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!flatcc_builder_check_required_field(ctx->ctx, 0) + ) { + buf = flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_required); + goto failed; + } + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_BaselineCheck_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_BaselineCheck_parse_json_table); +} + +static const char *AzureIoTSecurity_Baseline_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 1)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x626173656c696e65) { /* descend "baseline" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffffff00) == 0x5f636865636b7300) { /* "_checks" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7); + if (mark != buf) { + if (flatcc_builder_start_offset_vector(ctx->ctx)) goto failed; + buf = flatcc_json_parser_array_start(ctx, buf, end, &more); + while (more) { + buf = AzureIoTSecurity_BaselineCheck_parse_json_table(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_extend_offset_vector(ctx->ctx, 1))) goto failed; + *pref = ref; + buf = flatcc_json_parser_array_end(ctx, buf, end, &more); + } + ref = flatcc_builder_end_offset_vector(ctx->ctx); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "_checks" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "_checks" */ + } else { /* descend "baseline" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "baseline" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_Baseline_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_Baseline_parse_json_table); +} + +static const char *baseline_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *baseline_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365766572697479) { /* "Severity" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Severity" */ + if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Result" */ + return unmatched; + } /* "Result" */ + } /* "Severity" */ + return buf; +} + +static const char *baseline_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); + if (buf != mark) { + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + goto pfguard1; + } + } else { /* ".Result" */ + goto pfguard1; + } /* ".Result" */ + goto endpfguard1; +pfguard1: + if (w == 0x2e53657665726974) { /* descend ".Severit" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "y" */ + return unmatched; + } /* "y" */ + } else { /* descend ".Severit" */ + return unmatched; + } /* descend ".Severit" */ +endpfguard1: + (void)0; + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* BASELINE_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_printer.h new file mode 100644 index 00000000..76ec854c --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/baseline_json_printer.h @@ -0,0 +1,61 @@ +#ifndef BASELINE_JSON_PRINTER_H +#define BASELINE_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#include "flatcc/flatcc_prologue.h" + +static void AzureIoTSecurity_BaselineCheck_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); +static void AzureIoTSecurity_Baseline_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); + +static void AzureIoTSecurity_Result_print_json_enum(flatcc_json_printer_t *ctx, int8_t v) +{ + + switch (v) { + case 0: flatcc_json_printer_enum(ctx, "PASS", 4); break; + case 1: flatcc_json_printer_enum(ctx, "FAIL", 4); break; + case 2: flatcc_json_printer_enum(ctx, "ERROR", 5); break; + default: flatcc_json_printer_int8(ctx, v); break; + } +} + +static void AzureIoTSecurity_Severity_print_json_enum(flatcc_json_printer_t *ctx, int8_t v) +{ + + switch (v) { + case 0: flatcc_json_printer_enum(ctx, "CRITICAL", 8); break; + case 1: flatcc_json_printer_enum(ctx, "IMPORTANT", 9); break; + case 2: flatcc_json_printer_enum(ctx, "WARNING", 7); break; + case 3: flatcc_json_printer_enum(ctx, "INFORMATIONAL", 13); break; + default: flatcc_json_printer_int8(ctx, v); break; + } +} + +static void AzureIoTSecurity_BaselineCheck_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_string_field(ctx, td, 0, "id", 2); + flatcc_json_printer_int8_enum_field(ctx, td, 1, "result", 6, 0, AzureIoTSecurity_Result_print_json_enum); + flatcc_json_printer_string_field(ctx, td, 2, "error", 5); + flatcc_json_printer_string_field(ctx, td, 3, "description", 11); + flatcc_json_printer_int8_enum_field(ctx, td, 4, "severity", 8, 0, AzureIoTSecurity_Severity_print_json_enum); + flatcc_json_printer_string_field(ctx, td, 5, "remediation", 11); +} + +static inline int AzureIoTSecurity_BaselineCheck_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_BaselineCheck_print_json_table); +} + +static void AzureIoTSecurity_Baseline_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_table_vector_field(ctx, td, 0, "baseline_checks", 15, AzureIoTSecurity_BaselineCheck_print_json_table); +} + +static inline int AzureIoTSecurity_Baseline_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_Baseline_print_json_table); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* BASELINE_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_builder.h index 776f7e13..a947d0a0 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_builder.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_builder.h @@ -42,6 +42,8 @@ __flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event __flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event_payload, AzureIoTSecurity_Payload, ListeningPorts, AzureIoTSecurity_ListeningPorts) __flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event_payload, AzureIoTSecurity_Payload, Heartbeat, AzureIoTSecurity_Heartbeat) __flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event_payload, AzureIoTSecurity_Payload, Baseline, AzureIoTSecurity_Baseline) +__flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event_payload, AzureIoTSecurity_Payload, Process, AzureIoTSecurity_Process) +__flatbuffers_build_union_table_value_field(flatbuffers_, AzureIoTSecurity_Event_payload, AzureIoTSecurity_Payload, Log, AzureIoTSecurity_Log) static inline AzureIoTSecurity_Event_ref_t AzureIoTSecurity_Event_create(flatbuffers_builder_t *B __AzureIoTSecurity_Event_formal_args) { diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_json_parser.h index 85ad1f60..07271041 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_json_parser.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/event_json_parser.h @@ -175,7 +175,7 @@ static const char *event_local_AzureIoTSecurity_json_parser_enum(flatcc_json_par uint64_t w; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w < 0x50726f6365737345) { /* branch "ProcessE" */ if ((w & 0xffffffffffffff00) == 0x5061796c6f616400) { /* "Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { @@ -184,42 +184,70 @@ static const char *event_local_AzureIoTSecurity_json_parser_enum(flatcc_json_par return unmatched; } } else { /* "Payload" */ - return unmatched; - } /* "Payload" */ - } else { /* branch "Protocol" */ - if (w < 0x526573756c740000) { /* branch "Result" */ - if (w == 0x50726f746f636f6c) { /* "Protocol" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if ((w & 0xffffffffff000000) == 0x4c6576656c000000) { /* "Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 5); if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Protocol" */ + } else { /* "Level" */ return unmatched; - } /* "Protocol" */ - } else { /* branch "Result" */ - if (w == 0x5365766572697479) { /* "Severity" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); - if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + } /* "Level" */ + } /* "Payload" */ + } else { /* branch "ProcessE" */ + if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x76656e7454797065) { /* "ventType" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "ventType" */ return unmatched; - } - } else { /* "Severity" */ - if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + } /* "ventType" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + } else { /* branch "Protocol" */ + if (w < 0x526573756c740000) { /* branch "Result" */ + if (w == 0x50726f746f636f6c) { /* "Protocol" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Result" */ + } else { /* "Protocol" */ return unmatched; - } /* "Result" */ - } /* "Severity" */ - } /* branch "Result" */ - } /* branch "Protocol" */ + } /* "Protocol" */ + } else { /* branch "Result" */ + if (w == 0x5365766572697479) { /* "Severity" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Severity" */ + if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Result" */ + return unmatched; + } /* "Result" */ + } /* "Severity" */ + } /* branch "Result" */ + } /* branch "Protocol" */ + } /* branch "ProcessE" */ return buf; } @@ -237,7 +265,7 @@ static const char *event_global_json_parser_enum(flatcc_json_parser_t *ctx, cons if (w == 0x5365637572697479) { /* descend "Security" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w < 0x2e50726f63657373) { /* branch ".Process" */ if (w == 0x2e5061796c6f6164) { /* ".Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { @@ -246,59 +274,93 @@ static const char *event_global_json_parser_enum(flatcc_json_parser_t *ctx, cons return unmatched; } } else { /* ".Payload" */ - return unmatched; + if ((w & 0xffffffffffff0000) == 0x2e4c6576656c0000) { /* ".Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* ".Level" */ + return unmatched; + } /* ".Level" */ } /* ".Payload" */ - } else { /* branch ".Protoco" */ - if (w < 0x2e526573756c7400) { /* branch ".Result" */ - if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + } else { /* branch ".Process" */ + if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w == 0x2e50726f63657373) { /* descend ".Process" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); - if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + if (w == 0x4576656e74547970) { /* descend "EventTyp" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "e" */ return unmatched; - } - } else { /* "l" */ + } /* "e" */ + } else { /* descend "EventTyp" */ return unmatched; - } /* "l" */ - } else { /* descend ".Protoco" */ + } /* descend "EventTyp" */ + } else { /* descend ".Process" */ return unmatched; - } /* descend ".Protoco" */ - } else { /* branch ".Result" */ - if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); - if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { - goto pfguard1; - } - } else { /* ".Result" */ - goto pfguard1; - } /* ".Result" */ - goto endpfguard1; -pfguard1: - if (w == 0x2e53657665726974) { /* descend ".Severit" */ - buf += 8; - w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + } /* descend ".Process" */ + } else { /* branch ".Protoco" */ + if (w < 0x2e526573756c7400) { /* branch ".Result" */ + if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "l" */ + return unmatched; + } /* "l" */ + } else { /* descend ".Protoco" */ + return unmatched; + } /* descend ".Protoco" */ + } else { /* branch ".Result" */ + if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { - return unmatched; + goto pfguard1; } - } else { /* "y" */ + } else { /* ".Result" */ + goto pfguard1; + } /* ".Result" */ + goto endpfguard1; +pfguard1: + if (w == 0x2e53657665726974) { /* descend ".Severit" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "y" */ + return unmatched; + } /* "y" */ + } else { /* descend ".Severit" */ return unmatched; - } /* "y" */ - } else { /* descend ".Severit" */ - return unmatched; - } /* descend ".Severit" */ + } /* descend ".Severit" */ endpfguard1: - (void)0; - } /* branch ".Result" */ - } /* branch ".Protoco" */ + (void)0; + } /* branch ".Result" */ + } /* branch ".Protoco" */ + } /* branch ".Process" */ } else { /* descend "Security" */ return unmatched; } /* descend "Security" */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/flatbuffers_common_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/flatbuffers_common_reader.h index 2f4b5784..5f6f64df 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/flatbuffers_common_reader.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/flatbuffers_common_reader.h @@ -3,11 +3,8 @@ /* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ -#ifndef FLATCC_NO_ASSERT -#define FLATCC_NO_ASSERT -#endif - /* Common FlatBuffers read functionality for C. */ + #include "flatcc/flatcc_prologue.h" #include "flatcc/flatcc_flatbuffers.h" @@ -17,7 +14,7 @@ #define __flatbuffers_read_vt(ID, offset, t)\ flatbuffers_voffset_t offset = 0;\ { flatbuffers_voffset_t id__tmp, *vt__tmp;\ - FLATCC_ASSERT(t != 0 && "null pointer table access");\ + FLATCC_ASSERT((0 != (__ASSERT_VAL__ = (t != 0))) && (NULL != (__ASSERT_REASON__ = "null pointer table access")));\ id__tmp = ID;\ vt__tmp = (flatbuffers_voffset_t *)((uint8_t *)(t) -\ __flatbuffers_soffset_read_from_pe(t));\ @@ -54,7 +51,7 @@ __flatbuffers_define_scan_by_scalar_field(N, NK, T) if (offset__tmp) {\ return (T)((uint8_t *)(t) + offset__tmp);\ }\ - FLATCC_ASSERT(!(r) && "required field missing");\ + FLATCC_ASSERT((0 != (__ASSERT_VAL__ = !(r))) && (NULL != (__ASSERT_REASON__ = "required field missing")));\ return 0;\ } #define __flatbuffers_offset_field(T, ID, t, r, adjust)\ @@ -67,7 +64,7 @@ __flatbuffers_define_scan_by_scalar_field(N, NK, T) return (T)((uint8_t *)(elem__tmp) + adjust +\ __flatbuffers_uoffset_read_from_pe(elem__tmp));\ }\ - FLATCC_ASSERT(!(r) && "required field missing");\ + FLATCC_ASSERT((0 != (__ASSERT_VAL__ = !(r))) && (NULL != (__ASSERT_REASON__ = "required field missing")));\ return 0;\ } #define __flatbuffers_vector_field(T, ID, t, r) __flatbuffers_offset_field(T, ID, t, r, sizeof(flatbuffers_uoffset_t)) @@ -107,14 +104,14 @@ __flatbuffers_define_scan_by_string_field(N, NK) static inline size_t flatbuffers_vec_len(const void *vec) __flatbuffers_vec_len(vec) #define __flatbuffers_scalar_vec_at(N, vec, i)\ -{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range");\ +{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && (NULL != (__ASSERT_REASON__ = "index out of range")));\ return __flatbuffers_read_scalar(N, &(vec)[i]); } #define __flatbuffers_struct_vec_at(vec, i)\ -{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range"); return (vec) + (i); } +{ FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && (NULL != (__ASSERT_REASON__ = "index out of range"))); return (vec) + (i); } /* `adjust` skips past the header for string vectors. */ #define __flatbuffers_offset_vec_at(T, vec, i, adjust)\ { const flatbuffers_uoffset_t *elem__tmp = (vec) + (i);\ - FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && "index out of range");\ + FLATCC_ASSERT(flatbuffers_vec_len(vec) > (i) && (NULL != (__ASSERT_REASON__ = "index out of range")));\ return (T)((uint8_t *)(elem__tmp) + (size_t)__flatbuffers_uoffset_read_from_pe(elem__tmp) + (adjust)); } #define __flatbuffers_define_scalar_vec_len(N)\ static inline size_t N ## _vec_len(N ##_vec_t vec__tmp)\ @@ -194,7 +191,7 @@ static inline size_t T ## _union_vec_len(T ## _union_vec_t uv__tmp)\ { return NS ## vec_len(uv__tmp.type); }\ static inline T ## _union_t T ## _union_vec_at(T ## _union_vec_t uv__tmp, size_t i__tmp)\ { T ## _union_t u__tmp = { 0, 0 }; size_t n__tmp = NS ## vec_len(uv__tmp.type);\ - FLATCC_ASSERT(n__tmp > (i__tmp) && "index out of range"); u__tmp.type = uv__tmp.type[i__tmp];\ + FLATCC_ASSERT(n__tmp > (i__tmp) && (NULL != (__ASSERT_REASON__ = "index out of range"))); u__tmp.type = uv__tmp.type[i__tmp];\ /* Unknown type is treated as NONE for schema evolution. */\ if (u__tmp.type == 0) return u__tmp;\ u__tmp.value = NS ## generic_vec_at(uv__tmp.value, i__tmp); return u__tmp; }\ @@ -220,7 +217,7 @@ static inline T ## _union_vec_t N ## _ ## NK ## _union(N ## _table_t t__tmp)\ { T ## _union_vec_t uv__tmp; uv__tmp.type = N ## _ ## NK ## _type_get(t__tmp);\ uv__tmp.value = N ## _ ## NK(t__tmp);\ FLATCC_ASSERT(NS ## vec_len(uv__tmp.type) == NS ## vec_len(uv__tmp.value)\ - && "union vector type length mismatch"); return uv__tmp; } + && (NULL != (__ASSERT_REASON__ = "union vector type length mismatch"))); return uv__tmp; } #include static const size_t flatbuffers_not_found = (size_t)-1; static const size_t flatbuffers_end = (size_t)-1; diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_parser.h new file mode 100644 index 00000000..7204f173 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_parser.h @@ -0,0 +1,427 @@ +#ifndef LISTENING_PORTS_JSON_PARSER_H +#define LISTENING_PORTS_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#ifndef PROTOCOL_JSON_PARSER_H +#include "protocol_json_parser.h" +#endif +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_ListeningPortsCommon_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base); +static const char *AzureIoTSecurity_ListeningPortsCommon_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *AzureIoTSecurity_ListeningPortsV4_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base); +static const char *AzureIoTSecurity_ListeningPortsV4_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *AzureIoTSecurity_ListeningPortsV6_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base); +static const char *AzureIoTSecurity_ListeningPortsV6_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *AzureIoTSecurity_ListeningPorts_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *listening_ports_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *listening_ports_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *listening_ports_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_ListeningPortsCommon_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base) +{ + int more; + flatcc_builder_ref_t ref; + void *pval; + const char *mark; + uint64_t w; + + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x6c6f63616c5f706f) { /* descend "local_po" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x7274000000000000) { /* "rt" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + uint16_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + listening_ports_local_AzureIoTSecurity_json_parser_enum, + listening_ports_global_json_parser_enum, 0 }; + pval = (void *)((size_t)struct_base + 0); + buf = flatcc_json_parser_uint16(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint16(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + flatbuffers_uint16_write_to_pe(pval, val); + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "rt" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "rt" */ + } else { /* descend "local_po" */ + if (w == 0x70726f746f636f6c) { /* "protocol" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 8); + if (mark != buf) { + int8_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + AzureIoTSecurity_Protocol_parse_json_enum, + listening_ports_local_AzureIoTSecurity_json_parser_enum, + listening_ports_global_json_parser_enum, 0 }; + pval = (void *)((size_t)struct_base + 2); + buf = flatcc_json_parser_int8(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_int8(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + flatbuffers_int8_write_to_pe(pval, val); + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "protocol" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "protocol" */ + } /* descend "local_po" */ + buf = flatcc_json_parser_object_end(ctx, buf, end , &more); + } + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static const char *AzureIoTSecurity_ListeningPortsCommon_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + void *pval; + + *result = 0; + if (!(pval = flatcc_builder_start_struct(ctx->ctx, 4, 2))) goto failed; + buf = AzureIoTSecurity_ListeningPortsCommon_parse_json_struct_inline(ctx, buf, end, pval); + if (buf == end || !(*result = flatcc_builder_end_struct(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_ListeningPortsCommon_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_struct_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_ListeningPortsCommon_parse_json_struct); +} + +static const char *AzureIoTSecurity_ListeningPortsV4_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base) +{ + int more; + flatcc_builder_ref_t ref; + void *pval; + const char *mark; + uint64_t w; + + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffff0000) == 0x636f6d6d6f6e0000) { /* "common" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6); + if (mark != buf) { + pval = (void *)((size_t)struct_base + 4); + buf = AzureIoTSecurity_ListeningPortsCommon_parse_json_struct_inline(ctx, buf, end, pval); + } else { + goto pfguard1; + } + } else { /* "common" */ + goto pfguard1; + } /* "common" */ + goto endpfguard1; +pfguard1: + if (w == 0x6c6f63616c5f6164) { /* descend "local_ad" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffff000000) == 0x6472657373000000) { /* "dress" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + listening_ports_local_AzureIoTSecurity_json_parser_enum, + listening_ports_global_json_parser_enum, 0 }; + pval = (void *)((size_t)struct_base + 0); + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + flatbuffers_uint32_write_to_pe(pval, val); + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "dress" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "dress" */ + } else { /* descend "local_ad" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "local_ad" */ +endpfguard1: + (void)0; + buf = flatcc_json_parser_object_end(ctx, buf, end , &more); + } + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static const char *AzureIoTSecurity_ListeningPortsV4_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + void *pval; + + *result = 0; + if (!(pval = flatcc_builder_start_struct(ctx->ctx, 8, 4))) goto failed; + buf = AzureIoTSecurity_ListeningPortsV4_parse_json_struct_inline(ctx, buf, end, pval); + if (buf == end || !(*result = flatcc_builder_end_struct(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_ListeningPortsV4_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_struct_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_ListeningPortsV4_parse_json_struct); +} + +static const char *AzureIoTSecurity_ListeningPortsV6_parse_json_struct_inline(flatcc_json_parser_t *ctx, const char *buf, const char *end, void *struct_base) +{ + int more; + flatcc_builder_ref_t ref; + void *pval; + const char *mark; + uint64_t w; + + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffff0000) == 0x636f6d6d6f6e0000) { /* "common" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 6); + if (mark != buf) { + pval = (void *)((size_t)struct_base + 16); + buf = AzureIoTSecurity_ListeningPortsCommon_parse_json_struct_inline(ctx, buf, end, pval); + } else { + goto pfguard1; + } + } else { /* "common" */ + goto pfguard1; + } /* "common" */ + goto endpfguard1; +pfguard1: + if (w == 0x6c6f63616c5f6164) { /* descend "local_ad" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffff000000) == 0x6472657373000000) { /* "dress" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5); + if (mark != buf) { + size_t count = 4; + uint32_t *base = (uint32_t *)((size_t)struct_base + 0); + buf = flatcc_json_parser_array_start(ctx, buf, end, &more); + while (more) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + listening_ports_local_AzureIoTSecurity_json_parser_enum, + listening_ports_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (count) { + flatbuffers_uint32_write_to_pe(base, val); + --count; + ++base; + } else if (!(ctx->flags & flatcc_json_parser_f_skip_array_overflow)) { + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_array_overflow); + } + buf = flatcc_json_parser_array_end(ctx, buf, end, &more); + } + if (count) { + if (ctx->flags & flatcc_json_parser_f_reject_array_underflow) { + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_array_underflow); + } + memset(base, 0, count * sizeof(*base)); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "dress" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "dress" */ + } else { /* descend "local_ad" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "local_ad" */ +endpfguard1: + (void)0; + buf = flatcc_json_parser_object_end(ctx, buf, end , &more); + } + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static const char *AzureIoTSecurity_ListeningPortsV6_parse_json_struct(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + void *pval; + + *result = 0; + if (!(pval = flatcc_builder_start_struct(ctx->ctx, 20, 4))) goto failed; + buf = AzureIoTSecurity_ListeningPortsV6_parse_json_struct_inline(ctx, buf, end, pval); + if (buf == end || !(*result = flatcc_builder_end_struct(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_ListeningPortsV6_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_struct_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_ListeningPortsV6_parse_json_struct); +} + +static const char *AzureIoTSecurity_ListeningPorts_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 2)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x697076345f706f72) { /* descend "ipv4_por" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x7473000000000000) { /* "ts" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + if (flatcc_builder_start_vector(ctx->ctx, 8, 4, UINT64_C(536870911))) goto failed; + buf = flatcc_json_parser_array_start(ctx, buf, end, &more); + while (more) { + if (!(pval = flatcc_builder_extend_vector(ctx->ctx, 1))) goto failed; + buf = AzureIoTSecurity_ListeningPortsV4_parse_json_struct_inline(ctx, buf, end, pval); + buf = flatcc_json_parser_array_end(ctx, buf, end, &more); + } + ref = flatcc_builder_end_vector(ctx->ctx); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "ts" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "ts" */ + } else { /* descend "ipv4_por" */ + if (w == 0x697076365f706f72) { /* descend "ipv6_por" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x7473000000000000) { /* "ts" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + if (flatcc_builder_start_vector(ctx->ctx, 20, 4, UINT64_C(214748364))) goto failed; + buf = flatcc_json_parser_array_start(ctx, buf, end, &more); + while (more) { + if (!(pval = flatcc_builder_extend_vector(ctx->ctx, 1))) goto failed; + buf = AzureIoTSecurity_ListeningPortsV6_parse_json_struct_inline(ctx, buf, end, pval); + buf = flatcc_json_parser_array_end(ctx, buf, end, &more); + } + ref = flatcc_builder_end_vector(ctx->ctx); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 1))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "ts" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "ts" */ + } else { /* descend "ipv6_por" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "ipv6_por" */ + } /* descend "ipv4_por" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_ListeningPorts_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_ListeningPorts_parse_json_table); +} + +static const char *listening_ports_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *listening_ports_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x50726f746f636f6c) { /* "Protocol" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Protocol" */ + return unmatched; + } /* "Protocol" */ + return buf; +} + +static const char *listening_ports_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "l" */ + return unmatched; + } /* "l" */ + } else { /* descend ".Protoco" */ + return unmatched; + } /* descend ".Protoco" */ + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* LISTENING_PORTS_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_printer.h new file mode 100644 index 00000000..83556521 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/listening_ports_json_printer.h @@ -0,0 +1,62 @@ +#ifndef LISTENING_PORTS_JSON_PRINTER_H +#define LISTENING_PORTS_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#ifndef PROTOCOL_JSON_PRINTER_H +#include "protocol_json_printer.h" +#endif +#include "flatcc/flatcc_prologue.h" + +static void AzureIoTSecurity_ListeningPortsCommon_print_json_struct(flatcc_json_printer_t *ctx, const void *p); +static void AzureIoTSecurity_ListeningPortsV4_print_json_struct(flatcc_json_printer_t *ctx, const void *p); +static void AzureIoTSecurity_ListeningPortsV6_print_json_struct(flatcc_json_printer_t *ctx, const void *p); +static void AzureIoTSecurity_ListeningPorts_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); + +static void AzureIoTSecurity_ListeningPortsCommon_print_json_struct(flatcc_json_printer_t *ctx, const void *p) +{ + flatcc_json_printer_uint16_struct_field(ctx, 0, p, 0, "local_port", 10); + flatcc_json_printer_int8_enum_struct_field(ctx, 1, p, 2, "protocol", 8, AzureIoTSecurity_Protocol_print_json_enum); +} + +static inline int AzureIoTSecurity_ListeningPortsCommon_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_struct_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_ListeningPortsCommon_print_json_struct); +} + +static void AzureIoTSecurity_ListeningPortsV4_print_json_struct(flatcc_json_printer_t *ctx, const void *p) +{ + flatcc_json_printer_uint32_struct_field(ctx, 0, p, 0, "local_address", 13); + flatcc_json_printer_embedded_struct_field(ctx, 1, p, 4, "common", 6, AzureIoTSecurity_ListeningPortsCommon_print_json_struct); +} + +static inline int AzureIoTSecurity_ListeningPortsV4_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_struct_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_ListeningPortsV4_print_json_struct); +} + +static void AzureIoTSecurity_ListeningPortsV6_print_json_struct(flatcc_json_printer_t *ctx, const void *p) +{ + flatcc_json_printer_uint32_array_struct_field(ctx, 0, p, 0, "local_address", 13, 4); + flatcc_json_printer_embedded_struct_field(ctx, 1, p, 16, "common", 6, AzureIoTSecurity_ListeningPortsCommon_print_json_struct); +} + +static inline int AzureIoTSecurity_ListeningPortsV6_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_struct_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_ListeningPortsV6_print_json_struct); +} + +static void AzureIoTSecurity_ListeningPorts_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_struct_vector_field(ctx, td, 0, "ipv4_ports", 10, 8, AzureIoTSecurity_ListeningPortsV4_print_json_struct); + flatcc_json_printer_struct_vector_field(ctx, td, 1, "ipv6_ports", 10, 20, AzureIoTSecurity_ListeningPortsV6_print_json_struct); +} + +static inline int AzureIoTSecurity_ListeningPorts_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_ListeningPorts_print_json_table); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* LISTENING_PORTS_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_builder.h new file mode 100644 index 00000000..9043392f --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_builder.h @@ -0,0 +1,101 @@ +#ifndef LOG_BUILDER_H +#define LOG_BUILDER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef LOG_READER_H +#include "log_reader.h" +#endif +#ifndef FLATBUFFERS_COMMON_BUILDER_H +#include "flatbuffers_common_builder.h" +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + +#define __AzureIoTSecurity_Level_formal_args , AzureIoTSecurity_Level_enum_t v0 +#define __AzureIoTSecurity_Level_call_args , v0 +__flatbuffers_build_scalar(flatbuffers_, AzureIoTSecurity_Level, AzureIoTSecurity_Level_enum_t) + +static const flatbuffers_voffset_t __AzureIoTSecurity_Record_required[] = { 0, 4, 0 }; +typedef flatbuffers_ref_t AzureIoTSecurity_Record_ref_t; +static AzureIoTSecurity_Record_ref_t AzureIoTSecurity_Record_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Record_table_t t); +__flatbuffers_build_table(flatbuffers_, AzureIoTSecurity_Record, 5) + +static const flatbuffers_voffset_t __AzureIoTSecurity_Log_required[] = { 0 }; +typedef flatbuffers_ref_t AzureIoTSecurity_Log_ref_t; +static AzureIoTSecurity_Log_ref_t AzureIoTSecurity_Log_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Log_table_t t); +__flatbuffers_build_table(flatbuffers_, AzureIoTSecurity_Log, 1) + +#define __AzureIoTSecurity_Record_formal_args ,\ + flatbuffers_string_ref_t v0, AzureIoTSecurity_Level_enum_t v1, uint64_t v2, uint32_t v3, flatbuffers_string_ref_t v4 +#define __AzureIoTSecurity_Record_call_args ,\ + v0, v1, v2, v3, v4 +static inline AzureIoTSecurity_Record_ref_t AzureIoTSecurity_Record_create(flatbuffers_builder_t *B __AzureIoTSecurity_Record_formal_args); +__flatbuffers_build_table_prolog(flatbuffers_, AzureIoTSecurity_Record, AzureIoTSecurity_Record_file_identifier, AzureIoTSecurity_Record_type_identifier) + +#define __AzureIoTSecurity_Log_formal_args , AzureIoTSecurity_Record_vec_ref_t v0 +#define __AzureIoTSecurity_Log_call_args , v0 +static inline AzureIoTSecurity_Log_ref_t AzureIoTSecurity_Log_create(flatbuffers_builder_t *B __AzureIoTSecurity_Log_formal_args); +__flatbuffers_build_table_prolog(flatbuffers_, AzureIoTSecurity_Log, AzureIoTSecurity_Log_file_identifier, AzureIoTSecurity_Log_type_identifier) + +__flatbuffers_build_string_field(0, flatbuffers_, AzureIoTSecurity_Record_message, AzureIoTSecurity_Record) +__flatbuffers_build_scalar_field(1, flatbuffers_, AzureIoTSecurity_Record_level, AzureIoTSecurity_Level, AzureIoTSecurity_Level_enum_t, 1, 1, INT8_C(0), AzureIoTSecurity_Record) +__flatbuffers_build_scalar_field(2, flatbuffers_, AzureIoTSecurity_Record_timestamp, flatbuffers_uint64, uint64_t, 8, 8, UINT64_C(0), AzureIoTSecurity_Record) +__flatbuffers_build_scalar_field(3, flatbuffers_, AzureIoTSecurity_Record_line, flatbuffers_uint32, uint32_t, 4, 4, UINT32_C(0), AzureIoTSecurity_Record) +__flatbuffers_build_string_field(4, flatbuffers_, AzureIoTSecurity_Record_filename, AzureIoTSecurity_Record) + +static inline AzureIoTSecurity_Record_ref_t AzureIoTSecurity_Record_create(flatbuffers_builder_t *B __AzureIoTSecurity_Record_formal_args) +{ + if (AzureIoTSecurity_Record_start(B) + || AzureIoTSecurity_Record_timestamp_add(B, v2) + || AzureIoTSecurity_Record_message_add(B, v0) + || AzureIoTSecurity_Record_line_add(B, v3) + || AzureIoTSecurity_Record_filename_add(B, v4) + || AzureIoTSecurity_Record_level_add(B, v1)) { + return 0; + } + return AzureIoTSecurity_Record_end(B); +} + +static AzureIoTSecurity_Record_ref_t AzureIoTSecurity_Record_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Record_table_t t) +{ + __flatbuffers_memoize_begin(B, t); + if (AzureIoTSecurity_Record_start(B) + || AzureIoTSecurity_Record_timestamp_pick(B, t) + || AzureIoTSecurity_Record_message_pick(B, t) + || AzureIoTSecurity_Record_line_pick(B, t) + || AzureIoTSecurity_Record_filename_pick(B, t) + || AzureIoTSecurity_Record_level_pick(B, t)) { + return 0; + } + __flatbuffers_memoize_end(B, t, AzureIoTSecurity_Record_end(B)); +} + +__flatbuffers_build_table_vector_field(0, flatbuffers_, AzureIoTSecurity_Log_logs, AzureIoTSecurity_Record, AzureIoTSecurity_Log) + +static inline AzureIoTSecurity_Log_ref_t AzureIoTSecurity_Log_create(flatbuffers_builder_t *B __AzureIoTSecurity_Log_formal_args) +{ + if (AzureIoTSecurity_Log_start(B) + || AzureIoTSecurity_Log_logs_add(B, v0)) { + return 0; + } + return AzureIoTSecurity_Log_end(B); +} + +static AzureIoTSecurity_Log_ref_t AzureIoTSecurity_Log_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Log_table_t t) +{ + __flatbuffers_memoize_begin(B, t); + if (AzureIoTSecurity_Log_start(B) + || AzureIoTSecurity_Log_logs_pick(B, t)) { + return 0; + } + __flatbuffers_memoize_end(B, t, AzureIoTSecurity_Log_end(B)); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* LOG_BUILDER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_parser.h new file mode 100644 index 00000000..b52ba74e --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_parser.h @@ -0,0 +1,348 @@ +#ifndef LOG_JSON_PARSER_H +#define LOG_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_Level_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); +static const char *AzureIoTSecurity_Record_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *AzureIoTSecurity_Log_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *log_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *log_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *log_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_Level_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_sign, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x464154414c000000) { /* branch "FATAL" */ + if ((w & 0xffffffffff000000) == 0x4552524f52000000) { /* "ERROR" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 5, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "ERROR" */ + if ((w & 0xffffffffff000000) == 0x4445425547000000) { /* "DEBUG" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 5, aggregate); + if (buf != mark) { + *value = UINT64_C(5), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "DEBUG" */ + return unmatched; + } /* "DEBUG" */ + } /* "ERROR" */ + } else { /* branch "FATAL" */ + if (w < 0x494e464f00000000) { /* branch "INFO" */ + if ((w & 0xffffffffff000000) == 0x464154414c000000) { /* "FATAL" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 5, aggregate); + if (buf != mark) { + *value = UINT64_C(1), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "FATAL" */ + return unmatched; + } /* "FATAL" */ + } else { /* branch "INFO" */ + if (w < 0x4e4f545345540000) { /* branch "NOTSET" */ + if ((w & 0xffffffff00000000) == 0x494e464f00000000) { /* "INFO" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(4), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "INFO" */ + return unmatched; + } /* "INFO" */ + } else { /* branch "NOTSET" */ + if ((w & 0xffffffff00000000) == 0x5741524e00000000) { /* "WARN" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(3), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "WARN" */ + if ((w & 0xffffffffffff0000) == 0x4e4f545345540000) { /* "NOTSET" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 6, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "NOTSET" */ + return unmatched; + } /* "NOTSET" */ + } /* "WARN" */ + } /* branch "NOTSET" */ + } /* branch "INFO" */ + } /* branch "FATAL" */ + return buf; +} + +static const char *AzureIoTSecurity_Record_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 5)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x6c696e6500000000) { /* branch "line" */ + if ((w & 0xffffffffff000000) == 0x6c6576656c000000) { /* "level" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 5); + if (mark != buf) { + int8_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + AzureIoTSecurity_Level_parse_json_enum, + log_local_AzureIoTSecurity_json_parser_enum, + log_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_int8(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_int8(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 1, 1, 1))) goto failed; + flatbuffers_int8_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "level" */ + if (w == 0x66696c656e616d65) { /* "filename" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 8); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 4))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "filename" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "filename" */ + } /* "level" */ + } else { /* branch "line" */ + if (w < 0x6d65737361676500) { /* branch "message" */ + if ((w & 0xffffffff00000000) == 0x6c696e6500000000) { /* "line" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 4); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + log_local_AzureIoTSecurity_json_parser_enum, + log_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 3, 4, 4))) goto failed; + flatbuffers_uint32_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "line" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "line" */ + } else { /* branch "message" */ + if ((w & 0xffffffffffffff00) == 0x6d65737361676500) { /* "message" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + goto pfguard1; + } + } else { /* "message" */ + goto pfguard1; + } /* "message" */ + goto endpfguard1; +pfguard1: + if (w == 0x74696d657374616d) { /* descend "timestam" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7000000000000000) { /* "p" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1); + if (mark != buf) { + uint64_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + log_local_AzureIoTSecurity_json_parser_enum, + log_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint64(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint64(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 2, 8, 8))) goto failed; + flatbuffers_uint64_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "p" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "p" */ + } else { /* descend "timestam" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "timestam" */ +endpfguard1: + (void)0; + } /* branch "message" */ + } /* branch "line" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!flatcc_builder_check_required_field(ctx->ctx, 4) + || !flatcc_builder_check_required_field(ctx->ctx, 0) + ) { + buf = flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_required); + goto failed; + } + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_Record_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_Record_parse_json_table); +} + +static const char *AzureIoTSecurity_Log_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 1)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffff00000000) == 0x6c6f677300000000) { /* "logs" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 4); + if (mark != buf) { + if (flatcc_builder_start_offset_vector(ctx->ctx)) goto failed; + buf = flatcc_json_parser_array_start(ctx, buf, end, &more); + while (more) { + buf = AzureIoTSecurity_Record_parse_json_table(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_extend_offset_vector(ctx->ctx, 1))) goto failed; + *pref = ref; + buf = flatcc_json_parser_array_end(ctx, buf, end, &more); + } + ref = flatcc_builder_end_offset_vector(ctx->ctx); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "logs" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "logs" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_Log_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_Log_parse_json_table); +} + +static const char *log_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *log_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffff000000) == 0x4c6576656c000000) { /* "Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 5); + if (buf != mark) { + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Level" */ + return unmatched; + } /* "Level" */ + return buf; +} + +static const char *log_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffff0000) == 0x2e4c6576656c0000) { /* ".Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* ".Level" */ + return unmatched; + } /* ".Level" */ + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* LOG_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_printer.h new file mode 100644 index 00000000..0c0eacba --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_json_printer.h @@ -0,0 +1,51 @@ +#ifndef LOG_JSON_PRINTER_H +#define LOG_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#include "flatcc/flatcc_prologue.h" + +static void AzureIoTSecurity_Record_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); +static void AzureIoTSecurity_Log_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); + +static void AzureIoTSecurity_Level_print_json_enum(flatcc_json_printer_t *ctx, int8_t v) +{ + + switch (v) { + case 0: flatcc_json_printer_enum(ctx, "NOTSET", 6); break; + case 1: flatcc_json_printer_enum(ctx, "FATAL", 5); break; + case 2: flatcc_json_printer_enum(ctx, "ERROR", 5); break; + case 3: flatcc_json_printer_enum(ctx, "WARN", 4); break; + case 4: flatcc_json_printer_enum(ctx, "INFO", 4); break; + case 5: flatcc_json_printer_enum(ctx, "DEBUG", 5); break; + default: flatcc_json_printer_int8(ctx, v); break; + } +} + +static void AzureIoTSecurity_Record_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_string_field(ctx, td, 0, "message", 7); + flatcc_json_printer_int8_enum_field(ctx, td, 1, "level", 5, 0, AzureIoTSecurity_Level_print_json_enum); + flatcc_json_printer_uint64_field(ctx, td, 2, "timestamp", 9, 0); + flatcc_json_printer_uint32_field(ctx, td, 3, "line", 4, 0); + flatcc_json_printer_string_field(ctx, td, 4, "filename", 8); +} + +static inline int AzureIoTSecurity_Record_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_Record_print_json_table); +} + +static void AzureIoTSecurity_Log_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_table_vector_field(ctx, td, 0, "logs", 4, AzureIoTSecurity_Record_print_json_table); +} + +static inline int AzureIoTSecurity_Log_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_Log_print_json_table); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* LOG_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_reader.h new file mode 100644 index 00000000..045c7ce5 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/log_reader.h @@ -0,0 +1,116 @@ +#ifndef LOG_READER_H +#define LOG_READER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef FLATBUFFERS_COMMON_READER_H +#include "flatbuffers_common_reader.h" +#endif +#include "flatcc/flatcc_flatbuffers.h" +#ifndef __alignas_is_defined +#include +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + + +typedef const struct AzureIoTSecurity_Record_table *AzureIoTSecurity_Record_table_t; +typedef struct AzureIoTSecurity_Record_table *AzureIoTSecurity_Record_mutable_table_t; +typedef const flatbuffers_uoffset_t *AzureIoTSecurity_Record_vec_t; +typedef flatbuffers_uoffset_t *AzureIoTSecurity_Record_mutable_vec_t; +typedef const struct AzureIoTSecurity_Log_table *AzureIoTSecurity_Log_table_t; +typedef struct AzureIoTSecurity_Log_table *AzureIoTSecurity_Log_mutable_table_t; +typedef const flatbuffers_uoffset_t *AzureIoTSecurity_Log_vec_t; +typedef flatbuffers_uoffset_t *AzureIoTSecurity_Log_mutable_vec_t; +#ifndef AzureIoTSecurity_Record_file_identifier +#define AzureIoTSecurity_Record_file_identifier flatbuffers_identifier +#endif +/* deprecated, use AzureIoTSecurity_Record_file_identifier */ +#ifndef AzureIoTSecurity_Record_identifier +#define AzureIoTSecurity_Record_identifier flatbuffers_identifier +#endif +#define AzureIoTSecurity_Record_type_hash ((flatbuffers_thash_t)0xb5e0a8b5) +#define AzureIoTSecurity_Record_type_identifier "\xb5\xa8\xe0\xb5" +#ifndef AzureIoTSecurity_Log_file_identifier +#define AzureIoTSecurity_Log_file_identifier flatbuffers_identifier +#endif +/* deprecated, use AzureIoTSecurity_Log_file_identifier */ +#ifndef AzureIoTSecurity_Log_identifier +#define AzureIoTSecurity_Log_identifier flatbuffers_identifier +#endif +#define AzureIoTSecurity_Log_type_hash ((flatbuffers_thash_t)0x4ee428f2) +#define AzureIoTSecurity_Log_type_identifier "\xf2\x28\xe4\x4e" + +typedef int8_t AzureIoTSecurity_Level_enum_t; +__flatbuffers_define_integer_type(AzureIoTSecurity_Level, AzureIoTSecurity_Level_enum_t, 8) +#define AzureIoTSecurity_Level_NOTSET ((AzureIoTSecurity_Level_enum_t)INT8_C(0)) +#define AzureIoTSecurity_Level_FATAL ((AzureIoTSecurity_Level_enum_t)INT8_C(1)) +#define AzureIoTSecurity_Level_ERROR ((AzureIoTSecurity_Level_enum_t)INT8_C(2)) +#define AzureIoTSecurity_Level_WARN ((AzureIoTSecurity_Level_enum_t)INT8_C(3)) +#define AzureIoTSecurity_Level_INFO ((AzureIoTSecurity_Level_enum_t)INT8_C(4)) +#define AzureIoTSecurity_Level_DEBUG ((AzureIoTSecurity_Level_enum_t)INT8_C(5)) + +static inline const char *AzureIoTSecurity_Level_name(AzureIoTSecurity_Level_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_Level_NOTSET: return "NOTSET"; + case AzureIoTSecurity_Level_FATAL: return "FATAL"; + case AzureIoTSecurity_Level_ERROR: return "ERROR"; + case AzureIoTSecurity_Level_WARN: return "WARN"; + case AzureIoTSecurity_Level_INFO: return "INFO"; + case AzureIoTSecurity_Level_DEBUG: return "DEBUG"; + default: return ""; + } +} + +static inline int AzureIoTSecurity_Level_is_known_value(AzureIoTSecurity_Level_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_Level_NOTSET: return 1; + case AzureIoTSecurity_Level_FATAL: return 1; + case AzureIoTSecurity_Level_ERROR: return 1; + case AzureIoTSecurity_Level_WARN: return 1; + case AzureIoTSecurity_Level_INFO: return 1; + case AzureIoTSecurity_Level_DEBUG: return 1; + default: return 0; + } +} + + + +struct AzureIoTSecurity_Record_table { uint8_t unused__; }; + +static inline size_t AzureIoTSecurity_Record_vec_len(AzureIoTSecurity_Record_vec_t vec) +__flatbuffers_vec_len(vec) +static inline AzureIoTSecurity_Record_table_t AzureIoTSecurity_Record_vec_at(AzureIoTSecurity_Record_vec_t vec, size_t i) +__flatbuffers_offset_vec_at(AzureIoTSecurity_Record_table_t, vec, i, 0) +__flatbuffers_table_as_root(AzureIoTSecurity_Record) + +/** The formatted log message */ +__flatbuffers_define_string_field(0, AzureIoTSecurity_Record, message, 1) +/** The level of the record defined in Level enum */ +__flatbuffers_define_scalar_field(1, AzureIoTSecurity_Record, level, AzureIoTSecurity_Level, AzureIoTSecurity_Level_enum_t, INT8_C(0)) +__flatbuffers_define_scalar_field(2, AzureIoTSecurity_Record, timestamp, flatbuffers_uint64, uint64_t, UINT64_C(0)) +/** The line number from which this record was written */ +__flatbuffers_define_scalar_field(3, AzureIoTSecurity_Record, line, flatbuffers_uint32, uint32_t, UINT32_C(0)) +/** The file name from which this record was written */ +__flatbuffers_define_string_field(4, AzureIoTSecurity_Record, filename, 1) + +struct AzureIoTSecurity_Log_table { uint8_t unused__; }; + +static inline size_t AzureIoTSecurity_Log_vec_len(AzureIoTSecurity_Log_vec_t vec) +__flatbuffers_vec_len(vec) +static inline AzureIoTSecurity_Log_table_t AzureIoTSecurity_Log_vec_at(AzureIoTSecurity_Log_vec_t vec, size_t i) +__flatbuffers_offset_vec_at(AzureIoTSecurity_Log_table_t, vec, i, 0) +__flatbuffers_table_as_root(AzureIoTSecurity_Log) + +__flatbuffers_define_vector_field(0, AzureIoTSecurity_Log, logs, AzureIoTSecurity_Record_vec_t, 0) + + +#include "flatcc/flatcc_epilogue.h" +#endif /* LOG_READER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/message_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/message_json_parser.h index e8985527..dd118fa9 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/message_json_parser.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/message_json_parser.h @@ -167,7 +167,7 @@ static const char *message_local_AzureIoTSecurity_json_parser_enum(flatcc_json_p uint64_t w; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w < 0x50726f6365737345) { /* branch "ProcessE" */ if ((w & 0xffffffffffffff00) == 0x5061796c6f616400) { /* "Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { @@ -176,42 +176,70 @@ static const char *message_local_AzureIoTSecurity_json_parser_enum(flatcc_json_p return unmatched; } } else { /* "Payload" */ - return unmatched; - } /* "Payload" */ - } else { /* branch "Protocol" */ - if (w < 0x526573756c740000) { /* branch "Result" */ - if (w == 0x50726f746f636f6c) { /* "Protocol" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if ((w & 0xffffffffff000000) == 0x4c6576656c000000) { /* "Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 5); if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Protocol" */ + } else { /* "Level" */ return unmatched; - } /* "Protocol" */ - } else { /* branch "Result" */ - if (w == 0x5365766572697479) { /* "Severity" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); - if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + } /* "Level" */ + } /* "Payload" */ + } else { /* branch "ProcessE" */ + if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x76656e7454797065) { /* "ventType" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "ventType" */ return unmatched; - } - } else { /* "Severity" */ - if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + } /* "ventType" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + } else { /* branch "Protocol" */ + if (w < 0x526573756c740000) { /* branch "Result" */ + if (w == 0x50726f746f636f6c) { /* "Protocol" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Result" */ + } else { /* "Protocol" */ return unmatched; - } /* "Result" */ - } /* "Severity" */ - } /* branch "Result" */ - } /* branch "Protocol" */ + } /* "Protocol" */ + } else { /* branch "Result" */ + if (w == 0x5365766572697479) { /* "Severity" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Severity" */ + if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Result" */ + return unmatched; + } /* "Result" */ + } /* "Severity" */ + } /* branch "Result" */ + } /* branch "Protocol" */ + } /* branch "ProcessE" */ return buf; } @@ -229,7 +257,7 @@ static const char *message_global_json_parser_enum(flatcc_json_parser_t *ctx, co if (w == 0x5365637572697479) { /* descend "Security" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w < 0x2e50726f63657373) { /* branch ".Process" */ if (w == 0x2e5061796c6f6164) { /* ".Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { @@ -238,59 +266,93 @@ static const char *message_global_json_parser_enum(flatcc_json_parser_t *ctx, co return unmatched; } } else { /* ".Payload" */ - return unmatched; + if ((w & 0xffffffffffff0000) == 0x2e4c6576656c0000) { /* ".Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* ".Level" */ + return unmatched; + } /* ".Level" */ } /* ".Payload" */ - } else { /* branch ".Protoco" */ - if (w < 0x2e526573756c7400) { /* branch ".Result" */ - if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + } else { /* branch ".Process" */ + if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w == 0x2e50726f63657373) { /* descend ".Process" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); - if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + if (w == 0x4576656e74547970) { /* descend "EventTyp" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "e" */ return unmatched; - } - } else { /* "l" */ + } /* "e" */ + } else { /* descend "EventTyp" */ return unmatched; - } /* "l" */ - } else { /* descend ".Protoco" */ + } /* descend "EventTyp" */ + } else { /* descend ".Process" */ return unmatched; - } /* descend ".Protoco" */ - } else { /* branch ".Result" */ - if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); - if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { - goto pfguard1; - } - } else { /* ".Result" */ - goto pfguard1; - } /* ".Result" */ - goto endpfguard1; -pfguard1: - if (w == 0x2e53657665726974) { /* descend ".Severit" */ - buf += 8; - w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + } /* descend ".Process" */ + } else { /* branch ".Protoco" */ + if (w < 0x2e526573756c7400) { /* branch ".Result" */ + if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "l" */ + return unmatched; + } /* "l" */ + } else { /* descend ".Protoco" */ + return unmatched; + } /* descend ".Protoco" */ + } else { /* branch ".Result" */ + if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { - return unmatched; + goto pfguard1; } - } else { /* "y" */ + } else { /* ".Result" */ + goto pfguard1; + } /* ".Result" */ + goto endpfguard1; +pfguard1: + if (w == 0x2e53657665726974) { /* descend ".Severit" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "y" */ + return unmatched; + } /* "y" */ + } else { /* descend ".Severit" */ return unmatched; - } /* "y" */ - } else { /* descend ".Severit" */ - return unmatched; - } /* descend ".Severit" */ + } /* descend ".Severit" */ endpfguard1: - (void)0; - } /* branch ".Result" */ - } /* branch ".Protoco" */ + (void)0; + } /* branch ".Result" */ + } /* branch ".Protoco" */ + } /* branch ".Process" */ } else { /* descend "Security" */ return unmatched; } /* descend "Security" */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_builder.h index eb55fca3..de956439 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_builder.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_builder.h @@ -9,6 +9,12 @@ #ifndef FLATBUFFERS_COMMON_BUILDER_H #include "flatbuffers_common_builder.h" #endif +#ifndef LOG_BUILDER_H +#include "log_builder.h" +#endif +#ifndef PROCESS_BUILDER_H +#include "process_builder.h" +#endif #ifndef BASELINE_BUILDER_H #include "baseline_builder.h" #endif @@ -48,6 +54,10 @@ static inline AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_as_H { AzureIoTSecurity_Payload_union_ref_t uref; uref.type = AzureIoTSecurity_Payload_Heartbeat; uref.value = ref; return uref; } static inline AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_as_Baseline(AzureIoTSecurity_Baseline_ref_t ref) { AzureIoTSecurity_Payload_union_ref_t uref; uref.type = AzureIoTSecurity_Payload_Baseline; uref.value = ref; return uref; } +static inline AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_as_Process(AzureIoTSecurity_Process_ref_t ref) +{ AzureIoTSecurity_Payload_union_ref_t uref; uref.type = AzureIoTSecurity_Payload_Process; uref.value = ref; return uref; } +static inline AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_as_Log(AzureIoTSecurity_Log_ref_t ref) +{ AzureIoTSecurity_Payload_union_ref_t uref; uref.type = AzureIoTSecurity_Payload_Log; uref.value = ref; return uref; } __flatbuffers_build_union_vector(flatbuffers_, AzureIoTSecurity_Payload) static AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Payload_union_t u) @@ -58,6 +68,8 @@ static AzureIoTSecurity_Payload_union_ref_t AzureIoTSecurity_Payload_clone(flatb case 3: return AzureIoTSecurity_Payload_as_ListeningPorts(AzureIoTSecurity_ListeningPorts_clone(B, (AzureIoTSecurity_ListeningPorts_table_t)u.value)); case 4: return AzureIoTSecurity_Payload_as_Heartbeat(AzureIoTSecurity_Heartbeat_clone(B, (AzureIoTSecurity_Heartbeat_table_t)u.value)); case 5: return AzureIoTSecurity_Payload_as_Baseline(AzureIoTSecurity_Baseline_clone(B, (AzureIoTSecurity_Baseline_table_t)u.value)); + case 6: return AzureIoTSecurity_Payload_as_Process(AzureIoTSecurity_Process_clone(B, (AzureIoTSecurity_Process_table_t)u.value)); + case 7: return AzureIoTSecurity_Payload_as_Log(AzureIoTSecurity_Log_clone(B, (AzureIoTSecurity_Log_table_t)u.value)); default: return AzureIoTSecurity_Payload_as_NONE(); } } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_parser.h index a61c12ba..ecaa0bf6 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_parser.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_parser.h @@ -4,6 +4,12 @@ /* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ #include "flatcc/flatcc_json_parser.h" +#ifndef LOG_JSON_PARSER_H +#include "log_json_parser.h" +#endif +#ifndef PROCESS_JSON_PARSER_H +#include "process_json_parser.h" +#endif #ifndef BASELINE_JSON_PARSER_H #include "baseline_json_parser.h" #endif @@ -54,6 +60,12 @@ static const char *AzureIoTSecurity_Payload_parse_json_union(flatcc_json_parser_ case 5: /* Baseline */ buf = AzureIoTSecurity_Baseline_parse_json_table(ctx, buf, end, result); break; + case 6: /* Process */ + buf = AzureIoTSecurity_Process_parse_json_table(ctx, buf, end, result); + break; + case 7: /* Log */ + buf = AzureIoTSecurity_Log_parse_json_table(ctx, buf, end, result); + break; default: if (!(ctx->flags & flatcc_json_parser_f_skip_unknown)) { return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_unknown_union); @@ -77,6 +89,8 @@ static int AzureIoTSecurity_Payload_json_union_accept_type(uint8_t type) case 3: return 1; /* ListeningPorts */ case 4: return 1; /* Heartbeat */ case 5: return 1; /* Baseline */ + case 6: return 1; /* Process */ + case 7: return 1; /* Log */ default: return 0; } } @@ -89,68 +103,74 @@ static const char *AzureIoTSecurity_Payload_parse_json_enum(flatcc_json_parser_t uint64_t w; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x4c697374656e696e) { /* branch "Listenin" */ - if (w == 0x426173656c696e65) { /* "Baseline" */ - buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 8, aggregate); - if (buf != mark) { - *value = UINT64_C(5), *value_sign = 0; - } else { - goto pfguard1; - } - } else { /* "Baseline" */ - goto pfguard1; - } /* "Baseline" */ - goto endpfguard1; -pfguard1: - if (w == 0x4865617274626561) { /* descend "Heartbea" */ - buf += 8; - w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x7400000000000000) { /* "t" */ - buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 1, aggregate); + if (w < 0x4c6f670000000000) { /* branch "Log" */ + if (w < 0x4865617274626561) { /* branch "Heartbea" */ + if (w == 0x426173656c696e65) { /* "Baseline" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 8, aggregate); if (buf != mark) { - *value = UINT64_C(4), *value_sign = 0; + *value = UINT64_C(5), *value_sign = 0; } else { return unmatched; } - } else { /* "t" */ + } else { /* "Baseline" */ return unmatched; - } /* "t" */ - } else { /* descend "Heartbea" */ - return unmatched; - } /* descend "Heartbea" */ -endpfguard1: - (void)0; - } else { /* branch "Listenin" */ - if (w < 0x4e4f4e4500000000) { /* branch "NONE" */ - if (w == 0x4c697374656e696e) { /* descend "Listenin" */ + } /* "Baseline" */ + } else { /* branch "Heartbea" */ + if (w == 0x4865617274626561) { /* descend "Heartbea" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xffffffffffff0000) == 0x67506f7274730000) { /* "gPorts" */ - buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 6, aggregate); + if ((w & 0xff00000000000000) == 0x7400000000000000) { /* "t" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 1, aggregate); if (buf != mark) { - *value = UINT64_C(3), *value_sign = 0; + *value = UINT64_C(4), *value_sign = 0; } else { return unmatched; } - } else { /* "gPorts" */ + } else { /* "t" */ return unmatched; - } /* "gPorts" */ - } else { /* descend "Listenin" */ - return unmatched; - } /* descend "Listenin" */ - } else { /* branch "NONE" */ - if (w < 0x4e6574776f726b41) { /* branch "NetworkA" */ - if ((w & 0xffffffff00000000) == 0x4e4f4e4500000000) { /* "NONE" */ - buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + } /* "t" */ + } else { /* descend "Heartbea" */ + if (w == 0x4c697374656e696e) { /* descend "Listenin" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffffff0000) == 0x67506f7274730000) { /* "gPorts" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 6, aggregate); + if (buf != mark) { + *value = UINT64_C(3), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "gPorts" */ + return unmatched; + } /* "gPorts" */ + } else { /* descend "Listenin" */ + return unmatched; + } /* descend "Listenin" */ + } /* descend "Heartbea" */ + } /* branch "Heartbea" */ + } else { /* branch "Log" */ + if (w < 0x4e6574776f726b41) { /* branch "NetworkA" */ + if ((w & 0xffffffff00000000) == 0x4e4f4e4500000000) { /* "NONE" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "NONE" */ + if ((w & 0xffffff0000000000) == 0x4c6f670000000000) { /* "Log" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 3, aggregate); if (buf != mark) { - *value = UINT64_C(0), *value_sign = 0; + *value = UINT64_C(7), *value_sign = 0; } else { return unmatched; } - } else { /* "NONE" */ + } else { /* "Log" */ return unmatched; - } /* "NONE" */ - } else { /* branch "NetworkA" */ + } /* "Log" */ + } /* "NONE" */ + } else { /* branch "NetworkA" */ + if (w < 0x50726f6365737300) { /* branch "Process" */ if (w == 0x4e6574776f726b41) { /* descend "NetworkA" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); @@ -165,32 +185,48 @@ static const char *AzureIoTSecurity_Payload_parse_json_enum(flatcc_json_parser_t return unmatched; } /* "ctivity" */ } else { /* descend "NetworkA" */ - if (w == 0x53797374656d496e) { /* descend "SystemIn" */ + return unmatched; + } /* descend "NetworkA" */ + } else { /* branch "Process" */ + if ((w & 0xffffffffffffff00) == 0x50726f6365737300) { /* "Process" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 7, aggregate); + if (buf != mark) { + *value = UINT64_C(6), *value_sign = 0; + } else { + goto pfguard1; + } + } else { /* "Process" */ + goto pfguard1; + } /* "Process" */ + goto endpfguard1; +pfguard1: + if (w == 0x53797374656d496e) { /* descend "SystemIn" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x666f726d6174696f) { /* descend "formatio" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if (w == 0x666f726d6174696f) { /* descend "formatio" */ - buf += 8; - w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x6e00000000000000) { /* "n" */ - buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 1, aggregate); - if (buf != mark) { - *value = UINT64_C(2), *value_sign = 0; - } else { - return unmatched; - } - } else { /* "n" */ + if ((w & 0xff00000000000000) == 0x6e00000000000000) { /* "n" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 1, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { return unmatched; - } /* "n" */ - } else { /* descend "formatio" */ + } + } else { /* "n" */ return unmatched; - } /* descend "formatio" */ - } else { /* descend "SystemIn" */ + } /* "n" */ + } else { /* descend "formatio" */ return unmatched; - } /* descend "SystemIn" */ - } /* descend "NetworkA" */ - } /* branch "NetworkA" */ - } /* branch "NONE" */ - } /* branch "Listenin" */ + } /* descend "formatio" */ + } else { /* descend "SystemIn" */ + return unmatched; + } /* descend "SystemIn" */ +endpfguard1: + (void)0; + } /* branch "Process" */ + } /* branch "NetworkA" */ + } /* branch "Log" */ return buf; } @@ -209,7 +245,7 @@ static const char *payload_local_AzureIoTSecurity_json_parser_enum(flatcc_json_p uint64_t w; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w < 0x50726f6365737345) { /* branch "ProcessE" */ if ((w & 0xffffffffffffff00) == 0x5061796c6f616400) { /* "Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { @@ -218,42 +254,70 @@ static const char *payload_local_AzureIoTSecurity_json_parser_enum(flatcc_json_p return unmatched; } } else { /* "Payload" */ - return unmatched; - } /* "Payload" */ - } else { /* branch "Protocol" */ - if (w < 0x526573756c740000) { /* branch "Result" */ - if (w == 0x50726f746f636f6c) { /* "Protocol" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if ((w & 0xffffffffff000000) == 0x4c6576656c000000) { /* "Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 5); if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Protocol" */ + } else { /* "Level" */ return unmatched; - } /* "Protocol" */ - } else { /* branch "Result" */ - if (w == 0x5365766572697479) { /* "Severity" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); - if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + } /* "Level" */ + } /* "Payload" */ + } else { /* branch "ProcessE" */ + if (w < 0x50726f746f636f6c) { /* branch "Protocol" */ + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x76656e7454797065) { /* "ventType" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "ventType" */ return unmatched; - } - } else { /* "Severity" */ - if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + } /* "ventType" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + } else { /* branch "Protocol" */ + if (w < 0x526573756c740000) { /* branch "Result" */ + if (w == 0x50726f746f636f6c) { /* "Protocol" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { return unmatched; } - } else { /* "Result" */ + } else { /* "Protocol" */ return unmatched; - } /* "Result" */ - } /* "Severity" */ - } /* branch "Result" */ - } /* branch "Protocol" */ + } /* "Protocol" */ + } else { /* branch "Result" */ + if (w == 0x5365766572697479) { /* "Severity" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Severity" */ + if ((w & 0xffffffffffff0000) == 0x526573756c740000) { /* "Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Result" */ + return unmatched; + } /* "Result" */ + } /* "Severity" */ + } /* branch "Result" */ + } /* branch "Protocol" */ + } /* branch "ProcessE" */ return buf; } @@ -271,7 +335,7 @@ static const char *payload_global_json_parser_enum(flatcc_json_parser_t *ctx, co if (w == 0x5365637572697479) { /* descend "Security" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w < 0x2e50726f63657373) { /* branch ".Process" */ if (w == 0x2e5061796c6f6164) { /* ".Payload" */ buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); if (buf != mark) { @@ -280,59 +344,93 @@ static const char *payload_global_json_parser_enum(flatcc_json_parser_t *ctx, co return unmatched; } } else { /* ".Payload" */ - return unmatched; + if ((w & 0xffffffffffff0000) == 0x2e4c6576656c0000) { /* ".Level" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 6); + if (buf != mark) { + buf = AzureIoTSecurity_Level_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* ".Level" */ + return unmatched; + } /* ".Level" */ } /* ".Payload" */ - } else { /* branch ".Protoco" */ - if (w < 0x2e526573756c7400) { /* branch ".Result" */ - if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + } else { /* branch ".Process" */ + if (w < 0x2e50726f746f636f) { /* branch ".Protoco" */ + if (w == 0x2e50726f63657373) { /* descend ".Process" */ buf += 8; w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); - if (buf != mark) { - buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { + if (w == 0x4576656e74547970) { /* descend "EventTyp" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "e" */ return unmatched; - } - } else { /* "l" */ + } /* "e" */ + } else { /* descend "EventTyp" */ return unmatched; - } /* "l" */ - } else { /* descend ".Protoco" */ + } /* descend "EventTyp" */ + } else { /* descend ".Process" */ return unmatched; - } /* descend ".Protoco" */ - } else { /* branch ".Result" */ - if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); - if (buf != mark) { - buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); - } else { - goto pfguard1; - } - } else { /* ".Result" */ - goto pfguard1; - } /* ".Result" */ - goto endpfguard1; -pfguard1: - if (w == 0x2e53657665726974) { /* descend ".Severit" */ - buf += 8; - w = flatcc_json_parser_symbol_part(buf, end); - if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ - buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + } /* descend ".Process" */ + } else { /* branch ".Protoco" */ + if (w < 0x2e526573756c7400) { /* branch ".Result" */ + if (w == 0x2e50726f746f636f) { /* descend ".Protoco" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6c00000000000000) { /* "l" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Protocol_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "l" */ + return unmatched; + } /* "l" */ + } else { /* descend ".Protoco" */ + return unmatched; + } /* descend ".Protoco" */ + } else { /* branch ".Result" */ + if ((w & 0xffffffffffffff00) == 0x2e526573756c7400) { /* ".Result" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 7); if (buf != mark) { - buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + buf = AzureIoTSecurity_Result_parse_json_enum(ctx, buf, end, value_type, value, aggregate); } else { - return unmatched; + goto pfguard1; } - } else { /* "y" */ + } else { /* ".Result" */ + goto pfguard1; + } /* ".Result" */ + goto endpfguard1; +pfguard1: + if (w == 0x2e53657665726974) { /* descend ".Severit" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7900000000000000) { /* "y" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_Severity_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "y" */ + return unmatched; + } /* "y" */ + } else { /* descend ".Severit" */ return unmatched; - } /* "y" */ - } else { /* descend ".Severit" */ - return unmatched; - } /* descend ".Severit" */ + } /* descend ".Severit" */ endpfguard1: - (void)0; - } /* branch ".Result" */ - } /* branch ".Protoco" */ + (void)0; + } /* branch ".Result" */ + } /* branch ".Protoco" */ + } /* branch ".Process" */ } else { /* descend "Security" */ return unmatched; } /* descend "Security" */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_printer.h index f366f589..9ca6c3fa 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_printer.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_json_printer.h @@ -4,6 +4,12 @@ /* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ #include "flatcc/flatcc_json_printer.h" +#ifndef LOG_JSON_PRINTER_H +#include "log_json_printer.h" +#endif +#ifndef PROCESS_JSON_PRINTER_H +#include "process_json_printer.h" +#endif #ifndef BASELINE_JSON_PRINTER_H #include "baseline_json_printer.h" #endif @@ -42,6 +48,12 @@ static void AzureIoTSecurity_Payload_print_json_union_type(flatcc_json_printer_t case 5: flatcc_json_printer_enum(ctx, "Baseline", 8); break; + case 6: + flatcc_json_printer_enum(ctx, "Process", 7); + break; + case 7: + flatcc_json_printer_enum(ctx, "Log", 3); + break; default: flatcc_json_printer_enum(ctx, "NONE", 4); break; @@ -66,6 +78,12 @@ static void AzureIoTSecurity_Payload_print_json_union(flatcc_json_printer_t *ctx case 5: flatcc_json_printer_union_table(ctx, ud, AzureIoTSecurity_Baseline_print_json_table); break; + case 6: + flatcc_json_printer_union_table(ctx, ud, AzureIoTSecurity_Process_print_json_table); + break; + case 7: + flatcc_json_printer_union_table(ctx, ud, AzureIoTSecurity_Log_print_json_table); + break; default: break; } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_reader.h index b74c248b..7d4ac8c0 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_reader.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/payload_reader.h @@ -6,6 +6,12 @@ #ifndef FLATBUFFERS_COMMON_READER_H #include "flatbuffers_common_reader.h" #endif +#ifndef LOG_READER_H +#include "log_reader.h" +#endif +#ifndef PROCESS_READER_H +#include "process_reader.h" +#endif #ifndef BASELINE_READER_H #include "baseline_reader.h" #endif @@ -45,6 +51,8 @@ __flatbuffers_define_union(flatbuffers_, AzureIoTSecurity_Payload) #define AzureIoTSecurity_Payload_ListeningPorts ((AzureIoTSecurity_Payload_union_type_t)UINT8_C(3)) #define AzureIoTSecurity_Payload_Heartbeat ((AzureIoTSecurity_Payload_union_type_t)UINT8_C(4)) #define AzureIoTSecurity_Payload_Baseline ((AzureIoTSecurity_Payload_union_type_t)UINT8_C(5)) +#define AzureIoTSecurity_Payload_Process ((AzureIoTSecurity_Payload_union_type_t)UINT8_C(6)) +#define AzureIoTSecurity_Payload_Log ((AzureIoTSecurity_Payload_union_type_t)UINT8_C(7)) static inline const char *AzureIoTSecurity_Payload_type_name(AzureIoTSecurity_Payload_union_type_t type) { @@ -55,6 +63,8 @@ static inline const char *AzureIoTSecurity_Payload_type_name(AzureIoTSecurity_Pa case AzureIoTSecurity_Payload_ListeningPorts: return "ListeningPorts"; case AzureIoTSecurity_Payload_Heartbeat: return "Heartbeat"; case AzureIoTSecurity_Payload_Baseline: return "Baseline"; + case AzureIoTSecurity_Payload_Process: return "Process"; + case AzureIoTSecurity_Payload_Log: return "Log"; default: return ""; } } @@ -68,6 +78,8 @@ static inline int AzureIoTSecurity_Payload_is_known_type(AzureIoTSecurity_Payloa case AzureIoTSecurity_Payload_ListeningPorts: return 1; case AzureIoTSecurity_Payload_Heartbeat: return 1; case AzureIoTSecurity_Payload_Baseline: return 1; + case AzureIoTSecurity_Payload_Process: return 1; + case AzureIoTSecurity_Payload_Log: return 1; default: return 0; } } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_builder.h new file mode 100644 index 00000000..2d2d4f0d --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_builder.h @@ -0,0 +1,80 @@ +#ifndef PROCESS_BUILDER_H +#define PROCESS_BUILDER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef PROCESS_READER_H +#include "process_reader.h" +#endif +#ifndef FLATBUFFERS_COMMON_BUILDER_H +#include "flatbuffers_common_builder.h" +#endif +#ifndef PROCESS_EVENT_TYPE_BUILDER_H +#include "process_event_type_builder.h" +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + +static const flatbuffers_voffset_t __AzureIoTSecurity_Process_required[] = { 0 }; +typedef flatbuffers_ref_t AzureIoTSecurity_Process_ref_t; +static AzureIoTSecurity_Process_ref_t AzureIoTSecurity_Process_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Process_table_t t); +__flatbuffers_build_table(flatbuffers_, AzureIoTSecurity_Process, 8) + +#define __AzureIoTSecurity_Process_formal_args ,\ + flatbuffers_string_ref_t v0, uint32_t v1, uint32_t v2, uint32_t v3,\ + flatbuffers_string_ref_t v4, flatbuffers_string_ref_t v5, AzureIoTSecurity_ProcessEventType_enum_t v6, uint32_t v7 +#define __AzureIoTSecurity_Process_call_args ,\ + v0, v1, v2, v3,\ + v4, v5, v6, v7 +static inline AzureIoTSecurity_Process_ref_t AzureIoTSecurity_Process_create(flatbuffers_builder_t *B __AzureIoTSecurity_Process_formal_args); +__flatbuffers_build_table_prolog(flatbuffers_, AzureIoTSecurity_Process, AzureIoTSecurity_Process_file_identifier, AzureIoTSecurity_Process_type_identifier) + +__flatbuffers_build_string_field(0, flatbuffers_, AzureIoTSecurity_Process_executable, AzureIoTSecurity_Process) +__flatbuffers_build_scalar_field(1, flatbuffers_, AzureIoTSecurity_Process_process_id, flatbuffers_uint32, uint32_t, 4, 4, UINT32_C(0), AzureIoTSecurity_Process) +__flatbuffers_build_scalar_field(2, flatbuffers_, AzureIoTSecurity_Process_parent_process_id, flatbuffers_uint32, uint32_t, 4, 4, UINT32_C(0), AzureIoTSecurity_Process) +__flatbuffers_build_scalar_field(3, flatbuffers_, AzureIoTSecurity_Process_user_id, flatbuffers_uint32, uint32_t, 4, 4, UINT32_C(0), AzureIoTSecurity_Process) +__flatbuffers_build_string_field(4, flatbuffers_, AzureIoTSecurity_Process_user_name, AzureIoTSecurity_Process) +__flatbuffers_build_string_field(5, flatbuffers_, AzureIoTSecurity_Process_commandline, AzureIoTSecurity_Process) +__flatbuffers_build_scalar_field(6, flatbuffers_, AzureIoTSecurity_Process_event_type, AzureIoTSecurity_ProcessEventType, AzureIoTSecurity_ProcessEventType_enum_t, 1, 1, INT8_C(0), AzureIoTSecurity_Process) +__flatbuffers_build_scalar_field(7, flatbuffers_, AzureIoTSecurity_Process_hit_count, flatbuffers_uint32, uint32_t, 4, 4, UINT32_C(1), AzureIoTSecurity_Process) + +static inline AzureIoTSecurity_Process_ref_t AzureIoTSecurity_Process_create(flatbuffers_builder_t *B __AzureIoTSecurity_Process_formal_args) +{ + if (AzureIoTSecurity_Process_start(B) + || AzureIoTSecurity_Process_executable_add(B, v0) + || AzureIoTSecurity_Process_process_id_add(B, v1) + || AzureIoTSecurity_Process_parent_process_id_add(B, v2) + || AzureIoTSecurity_Process_user_id_add(B, v3) + || AzureIoTSecurity_Process_user_name_add(B, v4) + || AzureIoTSecurity_Process_commandline_add(B, v5) + || AzureIoTSecurity_Process_hit_count_add(B, v7) + || AzureIoTSecurity_Process_event_type_add(B, v6)) { + return 0; + } + return AzureIoTSecurity_Process_end(B); +} + +static AzureIoTSecurity_Process_ref_t AzureIoTSecurity_Process_clone(flatbuffers_builder_t *B, AzureIoTSecurity_Process_table_t t) +{ + __flatbuffers_memoize_begin(B, t); + if (AzureIoTSecurity_Process_start(B) + || AzureIoTSecurity_Process_executable_pick(B, t) + || AzureIoTSecurity_Process_process_id_pick(B, t) + || AzureIoTSecurity_Process_parent_process_id_pick(B, t) + || AzureIoTSecurity_Process_user_id_pick(B, t) + || AzureIoTSecurity_Process_user_name_pick(B, t) + || AzureIoTSecurity_Process_commandline_pick(B, t) + || AzureIoTSecurity_Process_hit_count_pick(B, t) + || AzureIoTSecurity_Process_event_type_pick(B, t)) { + return 0; + } + __flatbuffers_memoize_end(B, t, AzureIoTSecurity_Process_end(B)); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_BUILDER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_builder.h new file mode 100644 index 00000000..05847074 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_builder.h @@ -0,0 +1,25 @@ +#ifndef PROCESS_EVENT_BUILDER_H +#define PROCESS_EVENT_BUILDER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef PROCESS_EVENT_READER_H +#include "process_event_reader.h" +#endif +#ifndef FLATBUFFERS_COMMON_BUILDER_H +#include "flatbuffers_common_builder.h" +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + +#define __AzureIoTSecurity_ProcessEvent_formal_args , AzureIoTSecurity_ProcessEvent_enum_t v0 +#define __AzureIoTSecurity_ProcessEvent_call_args , v0 +__flatbuffers_build_scalar(flatbuffers_, AzureIoTSecurity_ProcessEvent, AzureIoTSecurity_ProcessEvent_enum_t) + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_BUILDER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_parser.h new file mode 100644 index 00000000..df237d59 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_parser.h @@ -0,0 +1,135 @@ +#ifndef PROCESS_EVENT_JSON_PARSER_H +#define PROCESS_EVENT_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_ProcessEvent_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_ProcessEvent_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_sign, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x4558495400000000) { /* branch "EXIT" */ + if ((w & 0xffffffff00000000) == 0x4558454300000000) { /* "EXEC" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(1), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "EXEC" */ + return unmatched; + } /* "EXEC" */ + } else { /* branch "EXIT" */ + if ((w & 0xffffffff00000000) == 0x464f524b00000000) { /* "FORK" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "FORK" */ + if ((w & 0xffffffff00000000) == 0x4558495400000000) { /* "EXIT" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "EXIT" */ + return unmatched; + } /* "EXIT" */ + } /* "FORK" */ + } /* branch "EXIT" */ + return buf; +} + +static const char *process_event_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *process_event_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffff00000000) == 0x76656e7400000000) { /* "vent" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 4); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEvent_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "vent" */ + return unmatched; + } /* "vent" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + return buf; +} + +static const char *process_event_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x2e50726f63657373) { /* descend ".Process" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffffffff000000) == 0x4576656e74000000) { /* "Event" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 5); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEvent_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "Event" */ + return unmatched; + } /* "Event" */ + } else { /* descend ".Process" */ + return unmatched; + } /* descend ".Process" */ + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_printer.h new file mode 100644 index 00000000..a2029994 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_json_printer.h @@ -0,0 +1,22 @@ +#ifndef PROCESS_EVENT_JSON_PRINTER_H +#define PROCESS_EVENT_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#include "flatcc/flatcc_prologue.h" + + +static void AzureIoTSecurity_ProcessEvent_print_json_enum(flatcc_json_printer_t *ctx, int8_t v) +{ + + switch (v) { + case 0: flatcc_json_printer_enum(ctx, "FORK", 4); break; + case 1: flatcc_json_printer_enum(ctx, "EXEC", 4); break; + case 2: flatcc_json_printer_enum(ctx, "EXIT", 4); break; + default: flatcc_json_printer_int8(ctx, v); break; + } +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_reader.h new file mode 100644 index 00000000..fffbbb50 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_reader.h @@ -0,0 +1,53 @@ +#ifndef PROCESS_EVENT_READER_H +#define PROCESS_EVENT_READER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef FLATBUFFERS_COMMON_READER_H +#include "flatbuffers_common_reader.h" +#endif +#include "flatcc/flatcc_flatbuffers.h" +#ifndef __alignas_is_defined +#include +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + + + +typedef int8_t AzureIoTSecurity_ProcessEvent_enum_t; +__flatbuffers_define_integer_type(AzureIoTSecurity_ProcessEvent, AzureIoTSecurity_ProcessEvent_enum_t, 8) +#define AzureIoTSecurity_ProcessEvent_FORK ((AzureIoTSecurity_ProcessEvent_enum_t)INT8_C(0)) +#define AzureIoTSecurity_ProcessEvent_EXEC ((AzureIoTSecurity_ProcessEvent_enum_t)INT8_C(1)) +#define AzureIoTSecurity_ProcessEvent_EXIT ((AzureIoTSecurity_ProcessEvent_enum_t)INT8_C(2)) + +static inline const char *AzureIoTSecurity_ProcessEvent_name(AzureIoTSecurity_ProcessEvent_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_ProcessEvent_FORK: return "FORK"; + case AzureIoTSecurity_ProcessEvent_EXEC: return "EXEC"; + case AzureIoTSecurity_ProcessEvent_EXIT: return "EXIT"; + default: return ""; + } +} + +static inline int AzureIoTSecurity_ProcessEvent_is_known_value(AzureIoTSecurity_ProcessEvent_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_ProcessEvent_FORK: return 1; + case AzureIoTSecurity_ProcessEvent_EXEC: return 1; + case AzureIoTSecurity_ProcessEvent_EXIT: return 1; + default: return 0; + } +} + + + + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_READER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_builder.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_builder.h new file mode 100644 index 00000000..9372e890 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_builder.h @@ -0,0 +1,25 @@ +#ifndef PROCESS_EVENT_TYPE_BUILDER_H +#define PROCESS_EVENT_TYPE_BUILDER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef PROCESS_EVENT_TYPE_READER_H +#include "process_event_type_reader.h" +#endif +#ifndef FLATBUFFERS_COMMON_BUILDER_H +#include "flatbuffers_common_builder.h" +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + +#define __AzureIoTSecurity_ProcessEventType_formal_args , AzureIoTSecurity_ProcessEventType_enum_t v0 +#define __AzureIoTSecurity_ProcessEventType_call_args , v0 +__flatbuffers_build_scalar(flatbuffers_, AzureIoTSecurity_ProcessEventType, AzureIoTSecurity_ProcessEventType_enum_t) + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_TYPE_BUILDER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_parser.h new file mode 100644 index 00000000..04610574 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_parser.h @@ -0,0 +1,141 @@ +#ifndef PROCESS_EVENT_TYPE_JSON_PARSER_H +#define PROCESS_EVENT_TYPE_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_ProcessEventType_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_type_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_type_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_event_type_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_ProcessEventType_parse_json_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_sign, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x4558495400000000) { /* branch "EXIT" */ + if ((w & 0xffffffff00000000) == 0x4558454300000000) { /* "EXEC" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(1), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "EXEC" */ + return unmatched; + } /* "EXEC" */ + } else { /* branch "EXIT" */ + if ((w & 0xffffffff00000000) == 0x464f524b00000000) { /* "FORK" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(0), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "FORK" */ + if ((w & 0xffffffff00000000) == 0x4558495400000000) { /* "EXIT" */ + buf = flatcc_json_parser_match_constant(ctx, (mark = buf), end, 4, aggregate); + if (buf != mark) { + *value = UINT64_C(2), *value_sign = 0; + } else { + return unmatched; + } + } else { /* "EXIT" */ + return unmatched; + } /* "EXIT" */ + } /* "FORK" */ + } /* branch "EXIT" */ + return buf; +} + +static const char *process_event_type_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *process_event_type_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x76656e7454797065) { /* "ventType" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "ventType" */ + return unmatched; + } /* "ventType" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + return buf; +} + +static const char *process_event_type_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x2e50726f63657373) { /* descend ".Process" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x4576656e74547970) { /* descend "EventTyp" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "e" */ + return unmatched; + } /* "e" */ + } else { /* descend "EventTyp" */ + return unmatched; + } /* descend "EventTyp" */ + } else { /* descend ".Process" */ + return unmatched; + } /* descend ".Process" */ + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_TYPE_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_printer.h new file mode 100644 index 00000000..b4392840 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_json_printer.h @@ -0,0 +1,22 @@ +#ifndef PROCESS_EVENT_TYPE_JSON_PRINTER_H +#define PROCESS_EVENT_TYPE_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#include "flatcc/flatcc_prologue.h" + + +static void AzureIoTSecurity_ProcessEventType_print_json_enum(flatcc_json_printer_t *ctx, int8_t v) +{ + + switch (v) { + case 0: flatcc_json_printer_enum(ctx, "FORK", 4); break; + case 1: flatcc_json_printer_enum(ctx, "EXEC", 4); break; + case 2: flatcc_json_printer_enum(ctx, "EXIT", 4); break; + default: flatcc_json_printer_int8(ctx, v); break; + } +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_TYPE_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_reader.h new file mode 100644 index 00000000..515bfc98 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_event_type_reader.h @@ -0,0 +1,53 @@ +#ifndef PROCESS_EVENT_TYPE_READER_H +#define PROCESS_EVENT_TYPE_READER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef FLATBUFFERS_COMMON_READER_H +#include "flatbuffers_common_reader.h" +#endif +#include "flatcc/flatcc_flatbuffers.h" +#ifndef __alignas_is_defined +#include +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + + + +typedef int8_t AzureIoTSecurity_ProcessEventType_enum_t; +__flatbuffers_define_integer_type(AzureIoTSecurity_ProcessEventType, AzureIoTSecurity_ProcessEventType_enum_t, 8) +#define AzureIoTSecurity_ProcessEventType_FORK ((AzureIoTSecurity_ProcessEventType_enum_t)INT8_C(0)) +#define AzureIoTSecurity_ProcessEventType_EXEC ((AzureIoTSecurity_ProcessEventType_enum_t)INT8_C(1)) +#define AzureIoTSecurity_ProcessEventType_EXIT ((AzureIoTSecurity_ProcessEventType_enum_t)INT8_C(2)) + +static inline const char *AzureIoTSecurity_ProcessEventType_name(AzureIoTSecurity_ProcessEventType_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_ProcessEventType_FORK: return "FORK"; + case AzureIoTSecurity_ProcessEventType_EXEC: return "EXEC"; + case AzureIoTSecurity_ProcessEventType_EXIT: return "EXIT"; + default: return ""; + } +} + +static inline int AzureIoTSecurity_ProcessEventType_is_known_value(AzureIoTSecurity_ProcessEventType_enum_t value) +{ + switch (value) { + case AzureIoTSecurity_ProcessEventType_FORK: return 1; + case AzureIoTSecurity_ProcessEventType_EXEC: return 1; + case AzureIoTSecurity_ProcessEventType_EXIT: return 1; + default: return 0; + } +} + + + + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_EVENT_TYPE_READER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_parser.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_parser.h new file mode 100644 index 00000000..8ab1e1f5 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_parser.h @@ -0,0 +1,337 @@ +#ifndef PROCESS_JSON_PARSER_H +#define PROCESS_JSON_PARSER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_parser.h" +#ifndef PROCESS_EVENT_TYPE_JSON_PARSER_H +#include "process_event_type_json_parser.h" +#endif +#include "flatcc/flatcc_prologue.h" + +static const char *AzureIoTSecurity_Process_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result); +static const char *process_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, +int *value_type, uint64_t *value, int *aggregate); +static const char *process_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate); + +static const char *AzureIoTSecurity_Process_parse_json_table(flatcc_json_parser_t *ctx, const char *buf, const char *end, flatcc_builder_ref_t *result) +{ + int more; + void *pval; + flatcc_builder_ref_t ref, *pref; + const char *mark; + uint64_t w; + + *result = 0; + if (flatcc_builder_start_table(ctx->ctx, 8)) goto failed; + buf = flatcc_json_parser_object_start(ctx, buf, end, &more); + while (more) { + buf = flatcc_json_parser_symbol_start(ctx, buf, end); + w = flatcc_json_parser_symbol_part(buf, end); + if (w < 0x6869745f636f756e) { /* branch "hit_coun" */ + if (w < 0x6576656e745f7479) { /* branch "event_ty" */ + if (w == 0x636f6d6d616e646c) { /* descend "commandl" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffffff0000000000) == 0x696e650000000000) { /* "ine" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 3); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 5))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "ine" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "ine" */ + } else { /* descend "commandl" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "commandl" */ + } else { /* branch "event_ty" */ + if (w == 0x6576656e745f7479) { /* descend "event_ty" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x7065000000000000) { /* "pe" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + int8_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + AzureIoTSecurity_ProcessEventType_parse_json_enum, + process_local_AzureIoTSecurity_json_parser_enum, + process_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_int8(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_int8(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 6, 1, 1))) goto failed; + flatbuffers_int8_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "pe" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "pe" */ + } else { /* descend "event_ty" */ + if (w == 0x6578656375746162) { /* descend "executab" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x6c65000000000000) { /* "le" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 0))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "le" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "le" */ + } else { /* descend "executab" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "executab" */ + } /* descend "event_ty" */ + } /* branch "event_ty" */ + } else { /* branch "hit_coun" */ + if (w < 0x70726f636573735f) { /* branch "process_" */ + if (w == 0x6869745f636f756e) { /* descend "hit_coun" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x7400000000000000) { /* "t" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + process_local_AzureIoTSecurity_json_parser_enum, + process_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 1 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 7, 4, 4))) goto failed; + flatbuffers_uint32_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "t" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "t" */ + } else { /* descend "hit_coun" */ + if (w == 0x706172656e745f70) { /* descend "parent_p" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x726f636573735f69) { /* descend "rocess_i" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6400000000000000) { /* "d" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + process_local_AzureIoTSecurity_json_parser_enum, + process_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 2, 4, 4))) goto failed; + flatbuffers_uint32_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "d" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "d" */ + } else { /* descend "rocess_i" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "rocess_i" */ + } else { /* descend "parent_p" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "parent_p" */ + } /* descend "hit_coun" */ + } else { /* branch "process_" */ + if (w < 0x757365725f696400) { /* branch "user_id" */ + if (w == 0x70726f636573735f) { /* descend "process_" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xffff000000000000) == 0x6964000000000000) { /* "id" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 2); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + process_local_AzureIoTSecurity_json_parser_enum, + process_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 1, 4, 4))) goto failed; + flatbuffers_uint32_write_to_pe(pval, val); + } + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "id" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "id" */ + } else { /* descend "process_" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "process_" */ + } else { /* branch "user_id" */ + if ((w & 0xffffffffffffff00) == 0x757365725f696400) { /* "user_id" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 7); + if (mark != buf) { + uint32_t val = 0; + static flatcc_json_parser_integral_symbol_f *symbolic_parsers[] = { + process_local_AzureIoTSecurity_json_parser_enum, + process_global_json_parser_enum, 0 }; + buf = flatcc_json_parser_uint32(ctx, (mark = buf), end, &val); + if (mark == buf) { + buf = flatcc_json_parser_symbolic_uint32(ctx, (mark = buf), end, symbolic_parsers, &val); + if (buf == mark || buf == end) goto failed; + } + if (val != 0 || (ctx->flags & flatcc_json_parser_f_force_add)) { + if (!(pval = flatcc_builder_table_add(ctx->ctx, 3, 4, 4))) goto failed; + flatbuffers_uint32_write_to_pe(pval, val); + } + } else { + goto pfguard1; + } + } else { /* "user_id" */ + goto pfguard1; + } /* "user_id" */ + goto endpfguard1; +pfguard1: + if (w == 0x757365725f6e616d) { /* descend "user_nam" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_symbol(ctx, (mark = buf), end, 1); + if (mark != buf) { + buf = flatcc_json_parser_build_string(ctx, buf, end, &ref); + if (!ref || !(pref = flatcc_builder_table_add_offset(ctx->ctx, 4))) goto failed; + *pref = ref; + } else { + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } + } else { /* "e" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* "e" */ + } else { /* descend "user_nam" */ + buf = flatcc_json_parser_unmatched_symbol(ctx, buf, end); + } /* descend "user_nam" */ +endpfguard1: + (void)0; + } /* branch "user_id" */ + } /* branch "process_" */ + } /* branch "hit_coun" */ + buf = flatcc_json_parser_object_end(ctx, buf, end, &more); + } + if (ctx->error) goto failed; + if (!(*result = flatcc_builder_end_table(ctx->ctx))) goto failed; + return buf; +failed: + return flatcc_json_parser_set_error(ctx, buf, end, flatcc_json_parser_error_runtime); +} + +static inline int AzureIoTSecurity_Process_parse_json_as_root(flatcc_builder_t *B, flatcc_json_parser_t *ctx, const char *buf, size_t bufsiz, int flags, const char *fid) +{ + return flatcc_json_parser_table_as_root(B, ctx, buf, bufsiz, flags, fid, AzureIoTSecurity_Process_parse_json_table); +} + +static const char *process_local_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + /* Scope has no enum / union types to look up. */ + return buf; /* unmatched; */ +} + +static const char *process_local_AzureIoTSecurity_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x50726f6365737345) { /* descend "ProcessE" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x76656e7454797065) { /* "ventType" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 8); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "ventType" */ + return unmatched; + } /* "ventType" */ + } else { /* descend "ProcessE" */ + return unmatched; + } /* descend "ProcessE" */ + return buf; +} + +static const char *process_global_json_parser_enum(flatcc_json_parser_t *ctx, const char *buf, const char *end, + int *value_type, uint64_t *value, int *aggregate) +{ + const char *unmatched = buf; + const char *mark; + uint64_t w; + + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x417a757265496f54) { /* descend "AzureIoT" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x5365637572697479) { /* descend "Security" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x2e50726f63657373) { /* descend ".Process" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if (w == 0x4576656e74547970) { /* descend "EventTyp" */ + buf += 8; + w = flatcc_json_parser_symbol_part(buf, end); + if ((w & 0xff00000000000000) == 0x6500000000000000) { /* "e" */ + buf = flatcc_json_parser_match_scope(ctx, (mark = buf), end, 1); + if (buf != mark) { + buf = AzureIoTSecurity_ProcessEventType_parse_json_enum(ctx, buf, end, value_type, value, aggregate); + } else { + return unmatched; + } + } else { /* "e" */ + return unmatched; + } /* "e" */ + } else { /* descend "EventTyp" */ + return unmatched; + } /* descend "EventTyp" */ + } else { /* descend ".Process" */ + return unmatched; + } /* descend ".Process" */ + } else { /* descend "Security" */ + return unmatched; + } /* descend "Security" */ + } else { /* descend "AzureIoT" */ + return unmatched; + } /* descend "AzureIoT" */ + return buf; +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_JSON_PARSER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_printer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_printer.h new file mode 100644 index 00000000..ae647275 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_json_printer.h @@ -0,0 +1,32 @@ +#ifndef PROCESS_JSON_PRINTER_H +#define PROCESS_JSON_PRINTER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#include "flatcc/flatcc_json_printer.h" +#ifndef PROCESS_EVENT_TYPE_JSON_PRINTER_H +#include "process_event_type_json_printer.h" +#endif +#include "flatcc/flatcc_prologue.h" + +static void AzureIoTSecurity_Process_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td); + +static void AzureIoTSecurity_Process_print_json_table(flatcc_json_printer_t *ctx, flatcc_json_printer_table_descriptor_t *td) +{ + flatcc_json_printer_string_field(ctx, td, 0, "executable", 10); + flatcc_json_printer_uint32_field(ctx, td, 1, "process_id", 10, 0); + flatcc_json_printer_uint32_field(ctx, td, 2, "parent_process_id", 17, 0); + flatcc_json_printer_uint32_field(ctx, td, 3, "user_id", 7, 0); + flatcc_json_printer_string_field(ctx, td, 4, "user_name", 9); + flatcc_json_printer_string_field(ctx, td, 5, "commandline", 11); + flatcc_json_printer_int8_enum_field(ctx, td, 6, "event_type", 10, 0, AzureIoTSecurity_ProcessEventType_print_json_enum); + flatcc_json_printer_uint32_field(ctx, td, 7, "hit_count", 9, 1); +} + +static inline int AzureIoTSecurity_Process_print_json_as_root(flatcc_json_printer_t *ctx, const void *buf, size_t bufsiz, const char *fid) +{ + return flatcc_json_printer_table_as_root(ctx, buf, bufsiz, fid, AzureIoTSecurity_Process_print_json_table); +} + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_JSON_PRINTER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_reader.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_reader.h new file mode 100644 index 00000000..9d6e7beb --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/process_reader.h @@ -0,0 +1,60 @@ +#ifndef PROCESS_READER_H +#define PROCESS_READER_H + +/* Generated by flatcc 0.6.1-dev FlatBuffers schema compiler for C by dvide.com */ + +#ifndef FLATBUFFERS_COMMON_READER_H +#include "flatbuffers_common_reader.h" +#endif +#ifndef PROCESS_EVENT_TYPE_READER_H +#include "process_event_type_reader.h" +#endif +#include "flatcc/flatcc_flatbuffers.h" +#ifndef __alignas_is_defined +#include +#endif +#include "flatcc/flatcc_prologue.h" +#ifndef flatbuffers_identifier +#define flatbuffers_identifier 0 +#endif +#ifndef flatbuffers_extension +#define flatbuffers_extension ".bin" +#endif + + +typedef const struct AzureIoTSecurity_Process_table *AzureIoTSecurity_Process_table_t; +typedef struct AzureIoTSecurity_Process_table *AzureIoTSecurity_Process_mutable_table_t; +typedef const flatbuffers_uoffset_t *AzureIoTSecurity_Process_vec_t; +typedef flatbuffers_uoffset_t *AzureIoTSecurity_Process_mutable_vec_t; +#ifndef AzureIoTSecurity_Process_file_identifier +#define AzureIoTSecurity_Process_file_identifier flatbuffers_identifier +#endif +/* deprecated, use AzureIoTSecurity_Process_file_identifier */ +#ifndef AzureIoTSecurity_Process_identifier +#define AzureIoTSecurity_Process_identifier flatbuffers_identifier +#endif +#define AzureIoTSecurity_Process_type_hash ((flatbuffers_thash_t)0x9577302d) +#define AzureIoTSecurity_Process_type_identifier "\x2d\x30\x77\x95" + + + +struct AzureIoTSecurity_Process_table { uint8_t unused__; }; + +static inline size_t AzureIoTSecurity_Process_vec_len(AzureIoTSecurity_Process_vec_t vec) +__flatbuffers_vec_len(vec) +static inline AzureIoTSecurity_Process_table_t AzureIoTSecurity_Process_vec_at(AzureIoTSecurity_Process_vec_t vec, size_t i) +__flatbuffers_offset_vec_at(AzureIoTSecurity_Process_table_t, vec, i, 0) +__flatbuffers_table_as_root(AzureIoTSecurity_Process) + +__flatbuffers_define_string_field(0, AzureIoTSecurity_Process, executable, 0) +__flatbuffers_define_scalar_field(1, AzureIoTSecurity_Process, process_id, flatbuffers_uint32, uint32_t, UINT32_C(0)) +__flatbuffers_define_scalar_field(2, AzureIoTSecurity_Process, parent_process_id, flatbuffers_uint32, uint32_t, UINT32_C(0)) +__flatbuffers_define_scalar_field(3, AzureIoTSecurity_Process, user_id, flatbuffers_uint32, uint32_t, UINT32_C(0)) +__flatbuffers_define_string_field(4, AzureIoTSecurity_Process, user_name, 0) +__flatbuffers_define_string_field(5, AzureIoTSecurity_Process, commandline, 0) +__flatbuffers_define_scalar_field(6, AzureIoTSecurity_Process, event_type, AzureIoTSecurity_ProcessEventType, AzureIoTSecurity_ProcessEventType_enum_t, INT8_C(0)) +__flatbuffers_define_scalar_field(7, AzureIoTSecurity_Process, hit_count, flatbuffers_uint32, uint32_t, UINT32_C(1)) + + +#include "flatcc/flatcc_epilogue.h" +#endif /* PROCESS_READER_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/version.txt b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/version.txt new file mode 100644 index 00000000..bb576dbd --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/schema/version.txt @@ -0,0 +1 @@ +2.3 diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/security_message.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/security_message.h index 6b535ce3..fb340441 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/security_message.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/model/security_message.h @@ -1,9 +1,22 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + #ifndef SECURITY_MESSAGE_H #define SECURITY_MESSAGE_H #include #include +#include + #include "asc_security_core/asc_result.h" typedef struct { diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool.h index db8edac9..f42fa2e2 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool.h @@ -1,28 +1,25 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECT_POOL_H #define OBJECT_POOL_H +#include #include "asc_security_core/utils/collection/collection.h" #include "asc_security_core/utils/collection/stack.h" -#include "asc_security_core/configuration.h" -#ifdef DYNAMIC_MEMORY_ENABLED +#ifdef ASC_DYNAMIC_MEMORY_ENABLED #include "asc_security_core/object_pool_dynamic.h" #else #include "asc_security_core/object_pool_static.h" #endif -#define object_pool_get(type) object_pool_##type##_get() -#define object_pool_free(type,object) object_pool_##type##_free(object) - #endif /* OBJECT_POOL_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_def.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_def.h new file mode 100644 index 00000000..0cbbfa29 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_def.h @@ -0,0 +1,30 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef OBJECT_POOL_DEF_H +#define OBJECT_POOL_DEF_H + +#include + +#include + +#include "asc_security_core/utils/collection/stack.h" + +typedef struct { + bool initialized; + stack_collection_t stack; + size_t item_size; + size_t size; + size_t current_size; + size_t failures; +} object_pool_t; + +#endif /* OBJECT_POOL_DEF_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_dynamic.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_dynamic.h index 29856977..40fbf1ff 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_dynamic.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_dynamic.h @@ -1,49 +1,56 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECT_POOL_DYNAMIC_H #define OBJECT_POOL_DYNAMIC_H -#include -#include #include -#include "asc_security_core/logger.h" +#include +#include "asc_security_core/object_pool_def.h" + +/* Pay your attention, that this implementation is not thread safe. */ + +/* The "type" in OBJECT_POOL_DECLARATIONS(type) OBJECT_POOL_DEFINITIONS(type) macros MUST be from following type: +typedef struct NAME_OF_DATA_FOR_LINKED_LIST_t { + // This macro must be first in object + COLLECTION_INTERFACE(struct NAME_OF_DATA_FOR_LINKED_LIST_t); + < Any data > +} NAME_OF_DATA_FOR_LINKED_LIST_t; +*/ #define OBJECT_POOL_DECLARATIONS(type)\ -type *object_pool_##type##_get();\ -void object_pool_##type##_free(type *object);\ +extern type _##type##_pool_test;\ +extern object_pool_t _##type##_pool_obj; #define OBJECT_POOL_DEFINITIONS(type, pool_size)\ -static uint32_t _##type##_pool_size = pool_size;\ -static uint32_t _##type##_current_pool_size = 0;\ -type *object_pool_##type##_get() \ -{\ - if ((_##type##_current_pool_size) >= (_##type##_pool_size)) {\ - log_debug("Pool exceeded objects count %d size %d", _##type##_current_pool_size, _##type##_pool_size); \ - return NULL;\ - }\ - (_##type##_current_pool_size)++;\ - return (type*)malloc(sizeof(type));\ -}\ -void object_pool_##type##_free(type *obj) \ -{\ - if (obj) { \ - if (_##type##_current_pool_size == 0) { \ - log_fatal("Invalid memory free"); \ - } else { \ - free(obj);\ - (_##type##_current_pool_size)--; \ - } \ - } \ -}\ +type _##type##_pool_test;\ +object_pool_t _##type##_pool_obj = {.item_size = sizeof(type), .size = pool_size, .initialized = false, .stack = {0}, .current_size = 0, .failures = 0}; + +void *__object_pool_get(object_pool_t *pool, uintptr_t offset1, uintptr_t offset2); +void __object_pool_free(object_pool_t *pool, void *obj); +size_t __object_pool_get_available_size(object_pool_t *pool); + +#define object_pool_init(type) _##type##_pool_obj.initialized = true + +#define object_pool_get(type)\ +(type *)__object_pool_get((object_pool_t *)&_##type##_pool_obj, (uintptr_t)(&_##type##_pool_test), (uintptr_t)(&(_##type##_pool_test.previous))) + +#define object_pool_free(type, obj)\ +__object_pool_free((object_pool_t *)&_##type##_pool_obj, (void *)obj) + +/* Returns number of available objects of specific type. + * If the definition of pool (OBJECT_POOL_DEFINITIONS(type_t, 0)) was done with zero size - always returns SIZE_MAX. + */ +#define object_pool_get_available_size(type) \ +__object_pool_get_available_size((object_pool_t *)&_##type##_pool_obj) #endif /* OBJECT_POOL_DYNAMIC_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_static.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_static.h index ee0165c5..9b1c8922 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_static.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/object_pool_static.h @@ -1,77 +1,53 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OBJECT_POOL_STATIC_H #define OBJECT_POOL_STATIC_H -#include -#include #include -#include "asc_security_core/logger.h" +#include -#define OBJECT_POOL_DEFINITIONS(type, pool_size)\ -STACK_DEFINITIONS(type)\ -static bool _##type##_is_pool_initialized = false;\ -static type _##type##_pool[pool_size];\ -static stack_##type _stack_##type = {0};\ -static stack_##type##_handle _stack_##type##_handle;\ -static uint32_t _##type##_pool_size = pool_size;\ -static uint32_t _##type##_current_pool_size = 0;\ -static uint32_t _##type##_failures = 0;\ -void object_pool_##type##_init() \ -{\ - if (_##type##_is_pool_initialized) {\ - return;\ - }\ -\ - _stack_##type##_handle = &(_stack_##type);\ - stack_##type##_init(_stack_##type##_handle);\ - for (uint32_t i=0; i= (_##type##_pool_size)) {\ - (_##type##_failures)++;\ - if ((_##type##_failures) % (_##type##_pool_size) == 0) {\ - log_debug("Pool exceeded objects [%d/%d] failures=[%d]", _##type##_current_pool_size, _##type##_pool_size, _##type##_failures); \ - }\ - return NULL;\ - }\ - (_##type##_current_pool_size)++;\ - return stack_##type##_pop(_stack_##type##_handle);\ -}\ -void object_pool_##type##_free(type *obj) \ -{\ - if (obj) { \ - if (_##type##_current_pool_size == 0) { \ - log_fatal("Invalid memory free"); \ - } else { \ - (_##type##_current_pool_size)--; \ - stack_##type##_push(_stack_##type##_handle, obj);\ - } \ - } \ -}\ +#include "asc_security_core/object_pool_def.h" + +/* Pay your attention, that this implementation is not thread safe. */ +/* The "type" in OBJECT_POOL_DECLARATIONS(type) OBJECT_POOL_DEFINITIONS(type) macros MUST be from following type: +typedef struct NAME_OF_DATA_FOR_LINKED_LIST_t { + // This macro must be first in object + COLLECTION_INTERFACE(struct NAME_OF_DATA_FOR_LINKED_LIST_t); + < Any data > +} NAME_OF_DATA_FOR_LINKED_LIST_t; +*/ #define OBJECT_POOL_DECLARATIONS(type)\ -STACK_DECLARATIONS(type)\ -void object_pool_##type##_init();\ -type *object_pool_##type##_get();\ -void object_pool_##type##_free(type *obj);\ +extern type _##type##_pool[];\ +extern object_pool_t _##type##_pool_obj; + +#define OBJECT_POOL_DEFINITIONS(type, pool_size)\ +type _##type##_pool[pool_size];\ +object_pool_t _##type##_pool_obj = {.item_size = sizeof(type), .size = pool_size, .initialized = false, .stack = {0}, .current_size = 0, .failures = 0}; + +void *__object_pool_get(object_pool_t *pool, uintptr_t offset1, uintptr_t offset2, uintptr_t objs); +void __object_pool_free(object_pool_t *pool, void *obj); +size_t __object_pool_get_available_size(object_pool_t *pool); + +#define object_pool_get(type) \ +(type *)__object_pool_get((object_pool_t *)&_##type##_pool_obj, (uintptr_t)(&_##type##_pool[0]), (uintptr_t)(&(_##type##_pool[0].previous)), (uintptr_t)_##type##_pool) + +#define object_pool_free(type, obj) \ +__object_pool_free((object_pool_t *)&_##type##_pool_obj, (void *)obj) + +/* Returns number of available objects of specific type. */ +#define object_pool_get_available_size(type) \ +__object_pool_get_available_size((object_pool_t *)&_##type##_pool_obj) #endif /* OBJECT_POOL_STATIC_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer.h index 2e0c7cc4..e5b7539b 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer.h @@ -1,13 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef SERIALIZER_H #define SERIALIZER_H @@ -15,7 +15,8 @@ #include #include -#include "asc_security_core/configuration.h" +#include + #include "asc_security_core/asc_result.h" #include "asc_security_core/model/objects/objects.h" @@ -117,7 +118,7 @@ typedef struct serializer serializer_t; * On success sets state to: SERIALIZER_STATE_INITIALIZED * @return A new serializer */ -serializer_t *serializer_init(); +serializer_t *serializer_init(void); /** * @brief Deinitialize a serializer @@ -163,7 +164,25 @@ asc_result_t serializer_message_begin(serializer_t *serializer, const char *secu */ asc_result_t serializer_message_end(serializer_t *serializer); -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED +#ifdef ASC_COLLECTOR_LOG_ENABLED +/** + * @brief Adds a Log event to current message. + * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING + * On success sets state to: SERIALIZER_STATE_MESSAGE_PROCESSING + * + * @param serializer The serializer + * @param timestamp The event timestamp + * @param collection_interval The collection interval + * @param report_list_iter The log report list iterator + * + * @return ASC_RESULT_OK on success, + * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL + * ASC_RESULT_EXCEPTION otherwise + */ +asc_result_t serializer_event_add_log(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, log_fetcher_t *fetcher); +#endif + +#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED /** * @brief Adds a network activity event to current message. * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING @@ -179,12 +198,29 @@ asc_result_t serializer_message_end(serializer_t *serializer); * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_add_network_activity(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, +asc_result_t serializer_event_add_network_activity(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, network_activity_ipv4_t *ipv4_payload, network_activity_ipv6_t *ipv6_payload); #endif +#ifdef ASC_COLLECTOR_PROCESS_ENABLED +/** + * @brief Adds a process event to the current message. + * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING + * On success sets state to: SERIALIZER_STATE_MESSAGE_PROCESSING + * + * @param serializer The serializer + * @param timestamp The event timestamp + * @param collection_interval The collection interval + * @param payload The process payload object + * + * @return ASC_RESULT_OK on success, + * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL + * ASC_RESULT_EXCEPTION otherwise + */ +asc_result_t serializer_event_add_process(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, process_t *payload); +#endif -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED +#ifdef ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED /** * @brief Adds a system information event to current message. * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING @@ -199,12 +235,12 @@ asc_result_t serializer_event_add_network_activity(serializer_t *serializer, uin * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_add_system_information(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, +asc_result_t serializer_event_add_system_information(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, system_information_t *payload); #endif -#ifdef COLLECTOR_HEARTBEAT_ENABLED +#ifdef ASC_COLLECTOR_HEARTBEAT_ENABLED /** * @brief Adds a heartbeat event to current message. * Callable from states: SERIALIZER_STATE_MESSAGE_READY @@ -217,11 +253,11 @@ asc_result_t serializer_event_add_system_information(serializer_t *serializer, u * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval); +asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval); #endif -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED +#ifdef ASC_COLLECTOR_LISTENING_PORTS_ENABLED /** * @brief Adds a listening ports event to current message. * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING @@ -237,11 +273,11 @@ asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, uint32_t t * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_add_listening_ports(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, +asc_result_t serializer_event_add_listening_ports(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, listening_ports_ipv4_t *ipv4_payload, listening_ports_ipv6_t *ipv6_payload); #endif -#ifdef COLLECTOR_BASELINE_ENABLED +#ifdef ASC_COLLECTOR_BASELINE_ENABLED /** * @brief Adds a Baseline event to current message. * Callable from states: SERIALIZER_STATE_INITIALIZED, SERIALIZER_STATE_MESSAGE_PROCESSING @@ -256,7 +292,7 @@ asc_result_t serializer_event_add_listening_ports(serializer_t *serializer, uint * ASC_RESULT_BAD_ARGUMENT if @a serializer is NULL * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_add_baseline(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, linked_list_iterator_baseline_report_t *report_list_iter); +asc_result_t serializer_event_add_baseline(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, linked_list_t *report_list); #endif /** diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/custom_builder_allocator.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/custom_builder_allocator.h new file mode 100644 index 00000000..28e6cc6c --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/custom_builder_allocator.h @@ -0,0 +1,22 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include + +#ifndef CUSTOM_BUILDER_ALLOCATOR_H +#define CUSTOM_BUILDER_ALLOCATOR_H + +#include "flatcc/flatcc_builder.h" + +int serializer_custom_allocator(void *alloc_context, flatcc_iovec_t *b, size_t request, int zero_fill, int alloc_type); + +void serializer_custom_allocator_reset(void); + +#endif /* CUSTOM_BUILDER_ALLOCATOR_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/page_allocator.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/page_allocator.h new file mode 100644 index 00000000..2d1255be --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/serializer/page_allocator.h @@ -0,0 +1,38 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef PAGE_ALLOCATOR_H +#define PAGE_ALLOCATOR_H + +#include + +#include + +#ifdef ASC_COLLECTOR_PROCESS_ENABLED +#include "asc_security_core/model/objects/process.h" +#define COLLECTOR_PROCESS_SIZE (ASC_COLLECTOR_PROCESS_IN_CACHE * sizeof(process_t)) +#else +#define COLLECTOR_PROCESS_SIZE 0 +#endif + +#define COLLECTOR_NETWORK_ACTIVITY_SIZE (ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE * 36 + \ + ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE * 60) + +#define MAX_MESSAGE_SIZE (500 + COLLECTOR_NETWORK_ACTIVITY_SIZE + COLLECTOR_PROCESS_SIZE) + +#define MIN_PAGE_SIZE (MAX_MESSAGE_SIZE * 2) +#define PAGE_MULTIPLE ((uint32_t)64) +#define FLATCC_EMITTER_PAGE_SIZE ((MIN_PAGE_SIZE + (PAGE_MULTIPLE) - 1) & ~(2 * (PAGE_MULTIPLE) - 1)) + +void *serializer_page_alloc(size_t size); +void serializer_page_free(void *page); + +#endif /* PAGE_ALLOCATOR_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/async.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/async.h deleted file mode 100644 index 7dd2baca..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/async.h +++ /dev/null @@ -1,45 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef _ASYNC_H_ -#define _ASYNC_H_ - -#include - -#include "asc_security_core/utils/collection/collection.h" -#include "asc_security_core/utils/ievent_loop.h" - -#define ASYNC_ERROR_LEN 50 - -typedef enum { - // must be first - ASYNC_PENDING = 0, - ASYNC_IN_PROGRESS, - ASYNC_FAIL -} async_status_t; - -/** @brief A callback function called when asynchronous operation is done */ -typedef void (*event_loop_done_cb_t)(void *ctx); - -typedef struct async_t{ - COLLECTION_INTERFACE(struct async_t); - - event_loop_timer_cb_t func; - event_loop_timer_handler timer; - event_loop_done_cb_t done_callback; - uint8_t retry; - async_status_t status; - char err[ASYNC_ERROR_LEN]; - - void *ctx; -} async_t; - -#endif /* _ASYNC_H_ */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/bit_vector.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/bit_vector.h new file mode 100644 index 00000000..f9dc46c9 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/bit_vector.h @@ -0,0 +1,92 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __BIT_VECTOR_H__ +#define __BIT_VECTOR_H__ + +#include + +#include + +#define __BV_VEC_IND(index) (index>>3) +#define __BV_VEC_SHIFT(index) (index & 0x07) +#define __BV_CEIL_DIV8(x) ((x>>3)+(!!(x & 0x07))) + +#define BIT_VECTOR_DECLARATIONS(type, size) \ +typedef struct {\ + char data[__BV_CEIL_DIV8(size)]; \ +} bit_vector_##type; + +/** + * @brief Set/Clear bit at index place. + * + * @param bit_vector The pointer on @c bit_vector_##type object. + * @param index The bit index. + * @param bit Value to set: true/false. + * @param size Bit vector size. + * + * @return false on overflow, otherwise true. + */ +bool __bit_vector_set(char bit_vector[], int index, bool bit, int size); + +/** + * @brief Get bit at index place. + * + * @param bit_vector The pointer on @c bit_vector_##type object. + * @param index The bit index. + * @param size Bit vector size. + * + * @return false on overflow, otherwise the actual value. + */ +bool __bit_vector_get(char bit_vector[], int index, int size); + +/** + * @brief Check if the vector is zero. + * + * @param bit_vector The pointer on @c bit_vector_##type object. + * @param size Bit vector size. + * + * @return true if all bits in vector are zero, otherwise false. + */ +bool __is_bit_vector_zero(char bit_vector[], int size); + +/** + * @brief Set the vector to zero. + * + * @param bit_vector The pointer on @c bit_vector_##type object. + * @param size Bit vector size. + * + * @return none. + */ +void __bit_vector_clean(char bit_vector[], int size); + +/** + * @brief Takes vector size in bits by type. + * + * @param bit_vector type + * + * @return vector size in bits. + */ +#define bit_vector_size(type) ((int)(sizeof(bit_vector_##type)<<3)) + +#define bit_vector_set(type, bit_vector_ptr, index, bit) \ +__bit_vector_set((bit_vector_ptr)->data, index, bit, bit_vector_size(type)) + +#define bit_vector_get(type, bit_vector_ptr, index) \ +__bit_vector_get((bit_vector_ptr)->data, index, bit_vector_size(type)) + +#define is_bit_vector_zero(type, bit_vector_ptr) \ +__is_bit_vector_zero((bit_vector_ptr)->data, bit_vector_size(type)) + +#define bit_vector_clean(type, bit_vector_ptr) \ +__bit_vector_clean((bit_vector_ptr)->data, bit_vector_size(type)) + +#endif /* __BIT_VECTOR_H__ */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/collection.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/collection.h index 9bdcbe20..ec76b2cc 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/collection.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/collection.h @@ -1,19 +1,27 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef COLLECTION_H #define COLLECTION_H +#include +/* Pay your attention, that this implementation is not thread safe. */ +/* This macro must be first in object */ #define COLLECTION_INTERFACE(type)\ type *previous;\ type *next +typedef struct { + /* This macro must be first in object */ + COLLECTION_INTERFACE(void); +} collection_item_t; + #endif /* COLLECTION_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashset.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashset.h index ae9f7b4c..76cca0ad 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashset.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashset.h @@ -1,19 +1,21 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef HASHSET_H #define HASHSET_H #include +#include + #include "asc_security_core/utils/collection/collection.h" /** @@ -28,7 +30,7 @@ * - hashset_##type##_update * * Additional Notes: - * - Make sure the struct-type uses COLLECTION_INTERFACE (see collection.h) + * - Make sure the struct-type uses COLLECTION_INTERFACE (see collection.h) This macro must be first in object. * - The Hashset does NOT allocate any memory * - The size defined in HASHSET_DEFINITION is the expected size for any hashset instance * - When implementing hashset_##type##_hash and hashset_##type##_equals, make sure that @@ -129,7 +131,26 @@ extern int hashset_##type##_equals(type *a, type *b); * \ * @return void \ */ \ -extern void hashset_##type##_update(type *old_element, type *new_element); +extern void hashset_##type##_update(type *old_element, type *new_element); \ + \ +/** \ + * @brief Get depth of hash to exam the hash function! \ + * \ + * @param table An initialized hashset \ + * @param count Count of non null or one element linked lists (out parameter) \ + * \ + * @return zero if all hash elements have list with 0 or 1 length - otherwise the longest list length \ + */ \ +unsigned int hashset_##type##_get_depth(type *table[], unsigned int *count); \ + \ +/** \ + * @brief Check if hash table is empty \ + * \ + * @param table An initialized hashset \ + * \ + * @return true if hash table is empty - otherwise false \ + */ \ + bool hashset_##type##_is_empty(type *table[]); #define HASHSET_DEFINITIONS(type, size) \ void hashset_##type##_init(type *table[]) \ @@ -189,12 +210,13 @@ extern void hashset_##type##_add_or_update(type *table[], type *element) void hashset_##type##_for_each(type *table[], hashset_##type##_for_each_function for_each_funcion, void *context) \ { \ if (table == NULL || for_each_funcion == NULL) return; \ - type *current_element = NULL; \ + type *current_element = NULL, *tmp = NULL; \ for (unsigned int i = 0; i < size; ++i) { \ current_element = table[i]; \ while (current_element != NULL) { \ + tmp = current_element->next; \ for_each_funcion(current_element, context); \ - current_element = current_element->next; \ + current_element = tmp; \ } \ } \ } \ @@ -218,6 +240,47 @@ void hashset_##type##_clear(type *table[], hashset_##type##_for_each_function fo current_element = table[i]; \ } \ } \ +} \ + \ +unsigned int hashset_##type##_get_depth(type *table[], unsigned int *count) \ +{ \ + unsigned int max = 0; \ + *count = 0; \ + if (table == NULL) return max; \ + type *current_element = NULL; \ + for (unsigned int i = 0; i < size; ++i) { \ + unsigned int cnt = 0; \ + current_element = table[i]; \ + while (current_element != NULL) { \ + cnt++; \ + current_element = current_element->next; \ + } \ + if (cnt > 1) { \ + if (cnt > max) max = cnt; \ + (*count)++; \ + } \ + } \ + return max; \ +} \ + \ +bool hashset_##type##_is_empty(type *table[]) \ +{ \ + if (table == NULL) return true; \ + for (unsigned int i = 0; i < size; ++i) { \ + if (table[i]) return false; \ + } \ + return true; \ +} + +static inline unsigned int hashset_buffer2hash(const char *str, size_t len) +{ + unsigned int hash = 5381; + + for (size_t i = 0 ; i < len; i++) { + hash = ((hash << 5) + hash) + (unsigned int)str[i]; + } + + return hash; } #endif /* HASHSET_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashtable.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashtable.h new file mode 100644 index 00000000..665f9c5f --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/hashtable.h @@ -0,0 +1,204 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __HASHTABLE_H__ +#define __HASHTABLE_H__ + +#include +#include +#include + +#include + +#include "asc_security_core/utils/collection/collection.h" + +/* Pay your attention, that this implementation is not thread safe. */ + +#define HASH_KEY(_key) ((const void *)((uintptr_t)(_key))) + +/** + * @brief Typedef of hash function + * + * @param key Hash key + * + * @return hash value none normilized to size. + */ +typedef unsigned int (*hash_func_t)(const void *key); + +/** + * @brief Typedef of comparing function + * + * @param key Hash key calculated by @c hash_func_t provided to @c hashtable_init(...) + * @param item The item to compare + * + * @return true on equal, otherwise false + */ +typedef bool (*hash_equal_func_t)(const void *key, void *item); + +/** + * @brief Typedef of updating function + * + * @param a The old item + * @param b The new item + * + * @return none + */ +typedef void (*hash_update_func_t)(void *a, void *b); + +/** + * @brief Typedef of free function + * + * @param item The item to free + * + * @return none + */ +typedef void (*hash_free_func_t)(void *item); + +/** + * @brief Typedef of action function + * + * @param item The item for action + * @param ctx User context + * + * @return none + */ +typedef void (*hash_action_func_t)(void *item, void *ctx); + +typedef struct { + bool initialized; // single tone initializin flag + size_t size; /* Actual size of hashtable. MUST be between 1 and given in HASHTABLE_DECLARATIONS() macro. + * Warning: there is no size checking - so passing , that above will lead to crash */ + hash_func_t hash_func; + hash_equal_func_t hash_equal_func; + hash_update_func_t hash_update_func; +} hashtable_ctrl_t; + +#define HASHTABLE_DECLARATIONS(type, max_hash_size) \ +typedef struct { \ + hashtable_ctrl_t ctrl; \ + type *table[(max_hash_size)]; \ +} hashtable_##type; + +typedef struct { + hashtable_ctrl_t ctrl; + void *table[1]; +} hashtable_t; + +// API functions +/** + * @brief Run time initialization of hashtable object + * + * @param hashtable Pointer on hashtable for initialization + * @param size Actual size of hashtable. MUST be between 1 and given in HASHTABLE_DECLARATIONS() macro. + * Warning: there is no size checking - so passing size, that above number + * that given in HASHTABLE_DECLARATIONS() will lead to crash + * @param hash_func Hash function. @c hash_func_t If NULL was passed the hashtable will use simple hashing formula (key%size) + * @param hash_equal_func Hash object comparing function. @c hash_equal_func_t If NULL was passed the hashtable will use default comparing (key == item) + * @param hash_update_func Hash object updating function. @c hash_update_func_t If NULL was passed the hashtable will use @c hashtable_update_none_func(...) + * + * @return true on success, otherwise false + */ +bool hashtable_init(hashtable_t *hashtable, size_t size, hash_func_t hash_func, + hash_equal_func_t hash_equal_func, hash_update_func_t hash_update_func); + +/** + * @brief Insert new hashtable item by key. If equal item was found by @c hash_equal_func_t the @c hash_update_func_t will performed + * + * @param hashtable A pointer on initialized hashtable + * @param key Hash key calculated by @c hash_func_t provided to @c hashtable_init(...) + * @param item Item to be inserted + * + * @return the pointer on inserted item on success, otherwise NULL. + */ +void *hashtable_insert(hashtable_t *hashtable, const void *key, void *item); + +/** + * @brief Remove hashtable item by key. + * + * @param hashtable A pointer on initialized hashtable + * @param key Hash key calculated by @c hash_func_t provided to @c hashtable_init(...) + * @param hash_free_func Free data function + * + * @return the pointer on removed item on success and if the hash_free_func == NULL, otherwise NULL. + */ +void *hashtable_remove(hashtable_t *hashtable, const void *key, hash_free_func_t hash_free_func); + +/** + * @brief Find hashtable item by key. + * + * @param hashtable A pointer on initialized hashtable + * @param key Hash key calculated by @c hash_func_t provided to @c hashtable_init(...) + * + * @return the pointer on found item on success, otherwise NULL. + */ +void *hashtable_find(hashtable_t *hashtable, const void *key); + +/** + * @brief Cleanup the hashtable. + * + * @param hashtable A pointer on initialized hashtable + * @param hash_free_func Free data function + * + * @return none + */ +void hashtable_flush(hashtable_t *hashtable, hash_free_func_t hash_free_func); + +/** + * @brief Runn over all hashtable items. + * + * @param hashtable A pointer on initialized hashtable + * @param hash_action_func Action callback to be called for each item + * @param ctx User contex to be passed to @c hash_action_func(...) + * + * @return none + */ +void hashtable_foreach(hashtable_t *hashtable, hash_action_func_t hash_action_func, void *ctx); + +/** + * @brief Get depth of hash to exam the hash function. + * + * @param hashtable A pointer on initialized hashtable + * @param count Count of non null or one element linked lists (out parameter) + * + * @return zero if all hash elements have list with 0 or 1 length - otherwise the longest list length + */ +size_t hashtable_get_depth(hashtable_t *hashtable, size_t *count); + +/** + * @brief Check if hash table is empty + * + * @param table A pointer on initialized hashset + * + * @return true if hash table is empty - otherwise false + */ + bool hashtable_is_empty(hashtable_t *hashtable); + +/** @brief Run over specified column of hashtable **/ +#define hashtable_column_foreach(hashtable, iter, column) for (iter = (hashtable)->table[(column)]; (iter); iter = (iter)->next) + +/** @brief Init hashtable with default callbacks **/ +#define hashtable_init_simple(hashtable, size) hashtable_init(hashtable, size, NULL, NULL, NULL) + +// Service callbacks +/** @brief The default @c hash_equal_func_t equal function returns true is if key equals to object pointer **/ +bool hashtable_equal_default_func(const void *key, void *item); + +/** @brief The 'key is NULL terminated string' @c hash_func_t hash generic function **/ +unsigned int hashtable_hash_str_default(const void *key); + +/** @brief The default @c hash_update_func_t hash update doing nothing function **/ +void hashtable_update_none_func(void *a, void *b); + +// Service functions +/** @brief The default hash calculating function on char buffer **/ +unsigned int hashtable_buffer2hash(const char *buffer, size_t len); + +#endif // __HASHTABLE_H__ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/linked_list.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/linked_list.h index df41f7d9..8e65b23c 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/linked_list.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/linked_list.h @@ -1,22 +1,25 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef LINKED_LIST_H #define LINKED_LIST_H -#include "asc_security_core/utils/collection/collection.h" #include #include #include +#include + +#include "asc_security_core/utils/collection/collection.h" + #define LINKED_LIST_DECLARATIONS(type) \ typedef void (*linked_list_##type##_deinit_function)(type *item);\ typedef void (*linked_list_##type##_action)(type *item, void *context);\ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/list.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/list.h new file mode 100644 index 00000000..fd850258 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/list.h @@ -0,0 +1,106 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __LIST_H__ +#define __LIST_H__ + +#include +#include + +#include + +#include "asc_security_core/utils/collection/collection.h" + +/* Pay your attention, that this implementation is not thread safe. */ + +/** + * @brief Typedef of free function + * + * @param item The item to free + * + * @return none + */ +typedef void (*linked_list_free_cb)(void *item); + +/** + * @brief Typedef of condition function + * + * @param item The item to perform the condition + * @param condition_input The condition input + * + * @return true on confition is true, otherwise false + */ +typedef bool (*linked_list_condition_cb)(void *item, void *condition_input); + +/** + * @brief Typedef of updating function + * + * @param a The old item + * @param b The new item + * + * @return none + */ +typedef void (*linked_list_update_cb)(void *a, void *b); + +typedef struct linked_list_t { + collection_item_t *head; + collection_item_t *tail; + size_t size; + bool initialized; +} linked_list_t; + +/* APIs */ +/* The void *data parameter for this implementation of linked list MUST be from following type: +typedef struct NAME_OF_DATA_FOR_LINKED_LIST_t { + // This macro must be first in object + COLLECTION_INTERFACE(struct NAME_OF_DATA_FOR_LINKED_LIST_t); + < Any data > +} NAME_OF_DATA_FOR_LINKED_LIST_t; +*/ + +/** @brief Add item to tail of linked list **/ +void *linked_list_add_last(linked_list_t *list, void *data); + +/** @brief Add item to head of linked list **/ +void *linked_list_add_first(linked_list_t *list, void *data); + +/** @brief Insert item before specified item of linked list. If 'before' item does not exist or NULL - add to tail **/ +void *linked_list_insert_before(linked_list_t *list, void *before, void *data); + +/** @brief Remove item from linked list. Returns the pointer on removed item on success and if the free_function == NULL, otherwise NULL **/ +void *linked_list_remove(linked_list_t *list, void *data, linked_list_free_cb free_function); + +/** @brief Add item to tail if not exists. If equal item was found by @c linked_list_condition_cb the @c linked_list_update_cb will performed **/ +void *linked_list_add_or_update(linked_list_t *list, linked_list_condition_cb condition_function, + linked_list_update_cb update_func, void *data); + +/** @brief Init linked list object **/ +void linked_list_init(linked_list_t *list); + +/** @brief Find linked list item that meets the conditions of @c linked_list_condition_cb and condition_input. Returns NULL on fail. **/ +void *linked_list_find(linked_list_t *list, linked_list_condition_cb condition_function, void *condition_input); + +/** @brief Get head item of linked list **/ +void *linked_list_get_first(linked_list_t *list); + +/** @brief Flush the linked list **/ +void linked_list_flush(linked_list_t *list, linked_list_free_cb free_function); + +/** @brief Get current size of linked list **/ +size_t linked_list_get_size(linked_list_t *list); + +/** @brief The default @c linked_list_condition_cb condition function returns true is if condition_input equals to item object pointer **/ +bool linked_list_condition_default(void *item, void *condition_input); + +/** @brief Run over linked list object **/ +#define linked_list_foreach(list, iter) for (iter = (void *)((list)->head); (iter); iter = (iter)->next) + +#endif /* __LIST_H__ */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/stack.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/stack.h index c76476cd..116093e9 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/stack.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/collection/stack.h @@ -1,73 +1,33 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef STACK_H #define STACK_H +#include +#include + +#include + #include "asc_security_core/utils/collection/collection.h" -#define STACK_DECLARATIONS(type) \ -typedef struct {\ - type *head;\ - size_t size;\ -} stack_##type;\ -typedef stack_##type *stack_##type##_handle;\ -extern void stack_##type##_init(stack_##type##_handle stack);\ -extern void stack_##type##_push(stack_##type##_handle stack, type *item);\ -extern type *stack_##type##_pop(stack_##type##_handle stack);\ -extern type *stack_##type##_peek(stack_##type##_handle stack);\ +/* Pay your attention, that this implementation is not thread safe. */ + +typedef struct { + collection_item_t *head; + size_t size; +} stack_collection_t; -#define STACK_DEFINITIONS(type) \ -extern void stack_##type##_init(stack_##type##_handle stack) \ -{\ - if ((stack) == NULL) {\ - return;\ - }\ - (stack)->head = NULL;\ - (stack)->size = 0;\ -}\ -void stack_##type##_push(stack_##type##_handle stack, type *item) \ -{\ - type *current_head = (stack)->head;\ - if ((current_head) == NULL) {\ - (stack)->head = item;\ - (item)->next = NULL;\ - (item)->previous = NULL;\ - (stack)->size++;\ - return;\ - }\ - (item)->next = current_head;\ - (item)->previous = NULL;\ - (current_head)->previous = item;\ - (stack)->head = item;\ - (stack)->size++;\ - return;\ -}\ -type *stack_##type##_pop(stack_##type##_handle stack) \ -{\ - type *current_head = (stack)->head;\ - if ((current_head) == NULL) {\ - return NULL;\ - }\ - type *new_head = (current_head)->next;\ - (current_head)->previous = (current_head)->next = NULL;\ - if ((new_head) != NULL) {\ - (new_head)->previous = NULL;\ - }\ - (stack)->head = new_head;\ - return current_head;\ -}\ -type *stack_##type##_peek(stack_##type##_handle stack) \ -{\ - return (stack)->head;\ -}\ +void stack_push(stack_collection_t *stack, collection_item_t *item); +collection_item_t * stack_pop(stack_collection_t *stack); +collection_item_t * stack_peek(stack_collection_t *stack); #endif /* STACK_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/containerof.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/containerof.h index 94ab3640..5f48ee4d 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/containerof.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/containerof.h @@ -1,16 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef __CONTAINER_OF_H__ #define __CONTAINER_OF_H__ +#include #undef offsetof #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/event_loop_be.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/event_loop_be.h index 97627cae..2e4a4465 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/event_loop_be.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/event_loop_be.h @@ -1,24 +1,34 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef _EVENT_BE_H_ #define _EVENT_BE_H_ +#include + +#include "asc_security_core/components_factory_enum.h" #include "asc_security_core/utils/ievent_loop.h" -#include "asc_security_core/collector_enums.h" -#ifndef EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES -#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT (COLLECTOR_TYPE_COUNT + 1) +#ifndef ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES +#ifndef ASC_BE_TIMERS_OBJECT_POOL_ENTRIES +#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT (COMPONENTS_COUNT + 1) +#else +#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT (ASC_BE_TIMERS_OBJECT_POOL_ENTRIES) +#endif #else -#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT ((COLLECTOR_TYPE_COUNT + 1) + EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES) +#ifndef ASC_BE_TIMERS_OBJECT_POOL_ENTRIES +#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT ((COMPONENTS_COUNT + 1) + ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES) +#else +#define OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT ((ASC_BE_TIMERS_OBJECT_POOL_ENTRIES) + ASC_EXTRA_BE_TIMERS_OBJECT_POOL_ENTRIES) +#endif #endif @@ -27,6 +37,6 @@ * * @return @c ievent_loop_t structure represents event loop based on base effort */ -ievent_loop_t *event_loop_be_instance_attach(); +ievent_loop_t *event_loop_be_instance_attach(void); #endif //_EVENT_BE_H_ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iconv.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iconv.h new file mode 100644 index 00000000..c3473e90 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iconv.h @@ -0,0 +1,45 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef ICONV_H +#define ICONV_H + +#include + +#include + +typedef struct { + int code; + char *string; +} code2string_t; + +/** + * @brief Return the first string from the list which matches code + * + * @param list List of strings and their matching code + * @param code The code that that should be located + * + * @return The string that matches the code or NULL in case of failure. + */ +char *code2string(code2string_t *list, int code); + +/** + * @brief Return the first code from the list which matches the string + * + * @param list List of strings and their matching code + * @param string The string that should be located + * @parma len The length of the string + * + * @return The code that matches the string or -1 in case of failure. + */ +int string2code(code2string_t *list, char *string, uint32_t len); + +#endif /* ICONV_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ievent_loop.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ievent_loop.h index d636c67d..fb09d95a 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ievent_loop.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ievent_loop.h @@ -1,17 +1,23 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef _IEVENT_LOOP_H_ #define _IEVENT_LOOP_H_ +#include + +#include + +#define EVENT_LOOP_DEFAULT_MAX_COUNT_RUN_UNTIL 100 + /** * @file ievent_loop.h * @brief Event loop API. @@ -34,11 +40,17 @@ typedef uintptr_t event_loop_signal_handler; typedef void (*event_loop_signal_cb_t)(event_loop_signal_handler h, int signal_num, void *ctx); typedef struct { -/** @brief Initialize the event loop. */ - int (*init)(void); +/** @brief Initialize the event loop. Returns true on success, otherwise false */ + bool (*init)(void); -/** @brief Unitialize the event loop. */ - int (*deinit)(void); +/** + * @brief Unitialize the event loop. + * @param flush perform run_until loop on deinit + * + * Returns false if there are unhandled event callbacks still exists, otherwise true. + * If parameter (flush == false) always returns true. + */ + bool (*deinit)(bool flush); /** * @brief Handle all events registered on the loop. @@ -50,6 +62,13 @@ typedef struct { /** @brief Run only a single iteration of the loop. */ bool (*run_once)(void); +/** + * @brief Run until there are no more active and referenced handles or requests. + * @param max_count maximum count of iterations + * @return true if there are no more active and referenced handles or requests. +*/ + bool (*run_until)(int max_count); + /** @brief Stop the even loop and return from @ref event_loop_run. */ void (*stop)(void); @@ -68,8 +87,8 @@ typedef struct { * * @return An object representing the timer. Used later for destroying it */ - event_loop_timer_handler (*timer_create)(event_loop_timer_cb_t cb, void *ctx, uint64_t delay, - uint64_t repeat, event_loop_timer_handler *self); + event_loop_timer_handler (*timer_create)(event_loop_timer_cb_t cb, void *ctx, unsigned long delay, + unsigned long repeat, event_loop_timer_handler *self); /** * @brief Delete a timer. @@ -113,6 +132,6 @@ typedef struct { * * @return Global event loop object */ -extern ievent_loop_t *ievent_loop_get_instance(); +extern ievent_loop_t *ievent_loop_get_instance(void); #endif //_IEVENT_LOOP_H_ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ifile.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ifile.h index 3d9232b3..cf277f4b 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ifile.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/ifile.h @@ -1,13 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef __IFILE_H__ #define __IFILE_H__ @@ -16,6 +16,8 @@ #include #include +#include + #include "asc_security_core/asc_result.h" #include "asc_security_core/utils/istream.h" @@ -32,6 +34,17 @@ */ size_t ifile_read(const char *path, const char *mode, char *buf, size_t size); +/** + * @brief Read a file data with allocating buffer. + * + * @param path The path of the file. + * @param mode The mode of the file. + * @param size The number of bytes read. + * + * @return char* The allocated buffer or NULL in case of an error. + */ +char *ifile_alloc_read(const char *path, const char *mode, size_t *size); + /** * @brief Write a buffer into a file. * diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/irand.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/irand.h index bac69f4b..62d9beab 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/irand.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/irand.h @@ -1,19 +1,21 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef IRAND_H #define IRAND_H #include +#include + /** * @brief Initialize the seed for rand generator. */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/istream.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/istream.h new file mode 100644 index 00000000..480bcb2f --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/istream.h @@ -0,0 +1,112 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef __ISTREAM_H__ +#define __ISTREAM_H__ + +#include +#include +#include + +#include + +#include "asc_security_core/asc_result.h" + +/** + * @brief Enum to define the data source. +*/ +typedef enum { + ISTREAM_DATA_SRC_FILE = 0, + ISTREAM_DATA_SRC_CMD_OUTPUT, + ISTREAM_DATA_SRC_CMD_OUTPUT_TO_TMP, + ISTREAM_DATA_SRC_BASH_CMD_OUTPUT +} istream_data_src_t; + +typedef struct { + istream_data_src_t data_src; // Data source + bool full; // Search on full buffer (true) or line by line (false - default) + bool negative; // Make logic to be opposite, if not match - pass + bool data_not_exist_pass; // Add logic if src not exist - pass + bool data_empty_pass; // Add logic if stream is empty - pass + bool scandir_match_or; // Add logic if one of the files match the condition in scandir (asterisk) - result is pass + bool case_ignore; // Is case sensitive + bool each_line; // Matching on each line + int sub_group_or; // Add logic of sub group 'or' if one of the tests in this sub group passed - result of this sub group is pass - max 10 + int sub_group_and; // Add logic of sub group 'and' if all tests in sub this group passed - result of this sub group is pass - max 10 + const char *path; // Pointer on previous allocated stream path + const char *regex; // Pointer on previous allocated matching string + const char *base_dir; // Base dir for 'path' parameter + const char *hash; // Pointer on previous allocated hash + bool suppress_err_log; // Flag for error log suppress on low layer +} istream_match_t; + +/** + * @brief Check if there is a stream contains the specified string. + * + * @param path The stream path + * @param s The string + * @param params The parameters defined in @c istream_match_t struct + * @param buf The target buffer that is used to read result or error + * @param size The size of the buffer in bytes. + * + * @return ASC_RESULT_OK on contains, ASC_RESULT_EMPTY on not contains, otherwise ASC_RESULT_error_code. + */ +asc_result_t istream_contains_string(const char *path, const char *s, istream_match_t *params, char **buf, size_t *size); + +/** + * @brief Check if the content of the whole stream (without newline or return) given by path, is equal specified buffer. + * + * @param path The stream path + * @param s Compare the content of the stream with this string + * @param params The parameters defined in @c istream_match_t struct + * @param buf The target buffer that is used to read result or error + * @param size The size of the buffer in bytes. + * + * @return ASC_RESULT_OK on equals, ASC_RESULT_EMPTY on not equal, otherwise ASC_RESULT_error_code. + */ +asc_result_t istream_trimmed_equals_to_buffer(const char *path, const char *s, istream_match_t *params, char **buf, size_t *size); + +typedef struct { + int deep_of_substrings; // Max deep of regular expression substrings + int start_index_substring; // Start substring index to be stored + int end_index_substring; // End substring index to be stored + const char *var_delim; // Delimiter between values in output format + int regcomp_flags; // Regular expression compilation flags (see ) + istream_match_t istream_match; // The istream_match_t struct +} istream_regex_extract_t; + +/** + * @brief Fill given buffer by blocks from stream based on regular expression. + * + * @param path The stream path + * @param regex The regular expression to be extracted + * @param params The parameters defined in @c istream_get_regex_t struct + * @param buf The target buffer that is used to read result or error + * @param size The size of the buffer in bytes. + * + * @return ASC_RESULT_OK on success + */ +asc_result_t istream_regex_extract(const char *path, const char *regex, istream_regex_extract_t *params, char **buf, size_t *size); + +/** + * @brief Check if there is a line in the stream that contains the specified regular expression. + * + * @param path The stream path + * @param regex The regular expression to be matched + * @param params The parameters defined in @c istream_match_t struct + * @param buf The target buffer that is used to read result or error + * @param size The size of the buffer in bytes. + * + * @return ASC_RESULT_OK on contains, ASC_RESULT_EMPTY on not contains, otherwise ASC_RESULT_error_code. + */ +asc_result_t istream_regex_match(const char *path, const char *regex, istream_match_t *params, char **buf, size_t *size); + +#endif /* __ISTREAM_H__ */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/itime.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/itime.h index 67088944..87cbc2f5 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/itime.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/itime.h @@ -1,25 +1,28 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef ITIME_H #define ITIME_H #include -#include + +#include #define SEC_MIN (60) #define SEC_HOUR (SEC_MIN * 60) #define SEC_DAY (SEC_HOUR * 24) -typedef uint32_t (*unix_time_callback_t)(uint32_t *unix_time); +#define ITIME_FAILED ((unsigned long)(-1)) + +typedef unsigned long (*unix_time_callback_t)(unsigned long *unix_time); void itime_init(unix_time_callback_t time_callback); @@ -29,7 +32,7 @@ void itime_init(unix_time_callback_t time_callback); * @details This function provides the same functionality as the * standard C @c time() function. */ -uint32_t itime_time(uint32_t *timer); +unsigned long itime_time(unsigned long *timer); #endif /* ITIME_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/macros.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/macros.h index a668a22b..e4a28b95 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/macros.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/macros.h @@ -1,16 +1,25 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef __MACROS_H__ #define __MACROS_H__ +#include + +#ifndef MIN +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +#ifndef MAX +#define MAX(a, b) ((a) >= (b) ? (a) : (b)) +#endif #ifdef __clang__ #define ATTRIBUTE_FORMAT(fmt_index, args_index) __attribute__((__format__ (__printf__, fmt_index, args_index))) @@ -20,4 +29,12 @@ #define ATTRIBUTE_FORMAT(fmt_index, args_index) #endif +#ifdef __clang__ +#define ATTRIBUTE_NONNUL(_index, ...) __attribute__((nonnull (_index, ##__VA_ARGS__))) +#elif __GNUC__ +#define ATTRIBUTE_NONNUL(_index, ...) __attribute__((nonnull(_index, ##__VA_ARGS__))) +#else +#define ATTRIBUTE_NONNUL(_index, ...) +#endif + #endif /* __MACROS_H__ */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier.h index d9cbf6ec..73d7c04e 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier.h @@ -1,25 +1,33 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef __NOTIFIER_H__ #define __NOTIFIER_H__ +#include #include "asc_security_core/asc_result.h" -#include "asc_security_core/configuration.h" #include "asc_security_core/utils/notifier_topics.h" +#include "asc_security_core/components_factory_enum.h" -#ifndef EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES -#define NOTIFIERS_POOL_ENTRIES 1 +#ifndef ASC_DYNAMIC_MEMORY_ENABLED +#ifndef ASC_NOTIFIERS_OBJECT_POOL_ENTRIES /* if ASC_NOTIFIERS_OBJECT_POOL_ENTRIES not defined set default */ +#define ASC_NOTIFIERS_OBJECT_POOL_ENTRIES (NOTIFY_TOPICS_NUMBER * (COMPONENTS_COUNT+1)) +#endif +#ifndef ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES /* Add ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES */ +#define NOTIFIERS_POOL_ENTRIES ASC_NOTIFIERS_OBJECT_POOL_ENTRIES #else -#define NOTIFIERS_POOL_ENTRIES (1 + EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES) +#define NOTIFIERS_POOL_ENTRIES (ASC_NOTIFIERS_OBJECT_POOL_ENTRIES + ASC_EXTRA_NOTIFIERS_OBJECT_POOL_ENTRIES) +#endif +#else /* Set unlimited in case of ASC_DYNAMIC_MEMORY_ENABLED */ +#define NOTIFIERS_POOL_ENTRIES 0 #endif typedef struct notifier_t notifier_t; @@ -58,5 +66,6 @@ asc_result_t notifier_unsubscribe(notify_topic_t topic, notifier_t *notifier); * * @param topic Topic enumerator * @return ASC_RESULT_OK on success, ASC_RESULT_EXCEPTION otherwise. - */asc_result_t notifier_deinit(notify_topic_t topic); + */ +asc_result_t notifier_deinit(notify_topic_t topic); #endif \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier_topics.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier_topics.h index 903069cc..9d6e16d4 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier_topics.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/notifier_topics.h @@ -1,24 +1,38 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef __NOTIFIER_GROUPS_H__ #define __NOTIFIER_GROUPS_H__ +#include typedef enum { NOTIFY_TOPIC_SYSTEM, + NOTIFY_TOPIC_COLLECT, + NOTIFY_TOPIC_SECURITY_MODULE_STATE, NOTIFY_TOPICS_NUMBER } notify_topic_t; enum { - NOTIFY_MESSAGE_SYSTEM_CONFIGURATION = 0 +#ifdef ASC_COLLECTORS_INFO_SUPPORT + NOTIFY_SYSTEM_CONFIGURATION, +#endif + + NOTIFY_MESSAGE_READY, + + NOTIFY_SECURITY_MODULE_CONNECTED, + NOTIFY_SECURITY_MODULE_PENDING, + NOTIFY_SECURITY_MODULE_SUSPENDED, +#ifdef ASC_COMPONENT_CORE_SUPPORTS_RESTART + NOTIFY_SECURITY_MODULE_RESTART +#endif }; #endif \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/num2str.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/num2str.h new file mode 100644 index 00000000..b6722c4e --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/num2str.h @@ -0,0 +1,38 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef _NUM2STR_H_ +#define _NUM2STR_H_ +#include + +#define __STR_AUX(x) #x +#define NUM_2_STR(x) __STR_AUX(x) +#define NUM_2_STR_SIZE(x) (sizeof(NUM_2_STR(x))) + +#define ULLONG64_MAX_STR NUM_2_STR(18446744073709551615) +#define ULLONG64_MAX_STR_SIZE (sizeof(ULLONG64_MAX_STR)) + +#define LLONG64_MAX_STR NUM_2_STR(9223372036854775807) +#define LLONG64_MAX_STR_SIZE (sizeof(LLONG64_MAX_STR)) + +#define ULONG32_MAX_STR NUM_2_STR(4294967295) +#define ULONG32_MAX_STR_SIZE (sizeof(ULONG32_MAX_STR)) + +#define LONG32_MAX_STR NUM_2_STR(2147483647) +#define LONG32_MAX_STR_SIZE (sizeof(LONG32_MAX_STR)) + +#define UINT16_MAX_STR NUM_2_STR(65535) +#define UINT16_MAX_STR_SIZE (sizeof(UINT16_MAX_STR)) + +#define INT16_MAX_STR NUM_2_STR(32767) +#define INT16_MAX_STR_SIZE (sizeof(INT16_MAX_STR)) + +#endif /* _NUM2STR_H_ */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/os_utils.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/os_utils.h index 8afcda04..bc1bd992 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/os_utils.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/os_utils.h @@ -1,22 +1,23 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef OS_UTILS_H #define OS_UTILS_H +#include /** * @brief Unique hardware identifier for security module * * @return security module id */ -const char *os_utils_get_security_module_id(); +const char *os_utils_get_security_module_id(void); #endif /* OS_UTILS_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/string_utils.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/string_utils.h index 06a81ecb..7a61b3d5 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/string_utils.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/string_utils.h @@ -1,13 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef STRING_UTILS_H #define STRING_UTILS_H @@ -15,6 +15,64 @@ #include #include +#include + +#include "asc_security_core/asc_result.h" + +/** + * @brief safe strstr. + * + * @param s the buffer + * + * @return buffer size + */ +char *str_str(const char *s1, const char *s2); + +/** + * @brief Replace last newline by NULL - no reallocation memory. + * + * @param s the buffer + * + * @return non + */ +void str_trim_last_newline(char *s); + +/** + * @brief Trim whitespaces. This function returns a pointer to a substring of the original string. + * + * @param s the original string + * + * @return a pointer to a substring of the original string + */ +char *str_trim(char *s); + +/** + * @brief safe strlen. + * + * @param s the buffer + * + * @return buffer size + */ +size_t str_len(const char *s); + +/** + * @brief safe strcmp. + * + * @param s the buffer + * + * @return comparison result + */ +int str_cmp(const char *s1, const char *s2); + +/** + * @brief check if string is NULL or empty. + * + * @param s the string for check + * + * @return true if empty, otherwise false. + */ +bool str_isempty(const char *s); + /** * @brief char* value getter * @@ -22,8 +80,7 @@ * * @return char* value if is not NULL, empty otherwise */ -const char *string_utils_value_or_empty(const char *s); - +const char *str_value_or_empty(const char *s); /** * @brief Check if string is blank @@ -32,7 +89,54 @@ const char *string_utils_value_or_empty(const char *s); * * @return true iff string is blank */ -bool string_utils_is_blank(const char *s); +bool str_is_blank(const char *s); +/** + * @brief Split a string to two parts by a delimiter + * + * @param s string + * @param token A pointer to a variable to receive the token + * @param token_len A pointer to a variable to receive the length of 'token' + * @param rest A pointer to a variable to receive the rest of the string + * @param rest_len A pointer to a variable to receive the length of 'rest' + * @param delimiter The delimiter to 'split' the string + * + * @return ASC_RESULT_OK on success. + */ +asc_result_t str_split(char *s, char **token, size_t *token_len, char **rest, size_t *rest_len, char *delimiter); + +/** + * @brief Compare two strings + * + * @param s1 The first string + * @param s1_len The length of s1 + * @param s2 The second string + * @param s2_len The length of s2 + * + * @return comparison result + */ +int str_ncmp(const char *s1, size_t s1_len, const char *s2, size_t s2_len); + +/** + * @brief Check if one string is a prefix of the other string + * + * @param s1 The first string + * @param s2 The second string + * + * @return true if s2 is a prefix of s1 + */ +bool str_starts_from(const char *s1, const char *s2); + +/** + * @brief replace all instances of a char in a char array with a different char + * + * @param char_array The character array + * @param len The length to look at + * @param replace_from The character to be replaced + * @param replace_to The character to replace with + * + * @return a reference to the char array + */ +char *replace_chars(char *char_array, size_t len, char replace_from, char replace_to); #endif /* STRING_UTILS_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/uuid.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/uuid.h new file mode 100644 index 00000000..ab6d7803 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/uuid.h @@ -0,0 +1,30 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#ifndef IUUID_H +#define IUUID_H + +#include + +#include + +/** + * @brief Generate a binary uuid + * @note: not thread-safe. + * + * @param buf - The buffer to write the UUID to. Size should be at least 16 bytes. + * + * @return 0 on sucess, -1 otherwise + */ +int uuid_generate(uint8_t *buf); + + +#endif /* IUUID_H */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/version.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/version.h index aae9b8c3..5dcfc23c 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/version.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/version.h @@ -1,34 +1,20 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef VERSION_H #define VERSION_H - -#ifndef DISABLE_ASC_PORT -#include "asc_version.h" -#else -#ifndef SECURITY_MODULE_VERSION_MAJOR -#define SECURITY_MODULE_VERSION_MAJOR 0 -#endif -#ifndef SECURITY_MODULE_VERSION_MINOR -#define SECURITY_MODULE_VERSION_MINOR 0 -#endif -#ifndef SECURITY_MODULE_VERSION_PATCH -#define SECURITY_MODULE_VERSION_PATCH 0 -#endif -#endif /* DISABLE_ASC_PORT */ - +#include #define SECURITY_MODULE_VERSION ((SECURITY_MODULE_VERSION_MAJOR << 24) |\ - (SECURITY_MODULE_VERSION_MINOR << 16) |\ - SECURITY_MODULE_VERSION_PATCH) + (SECURITY_MODULE_VERSION_MINOR << 16) |\ + SECURITY_MODULE_VERSION_PATCH) #endif /* VERSION_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection.c index 3f4aa8a5..9c927764 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection.c @@ -1,35 +1,35 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include +#include + #include "asc_security_core/logger.h" -#include "asc_security_core/collector_collection.h" #include "asc_security_core/object_pool.h" -#include "asc_security_core/collector_collection_internal.h" -#include "asc_security_core/collector_collection_factory.h" -#include "asc_security_core/collectors_headers.h" + +#include "asc_security_core/collector_collection.h" #define COLLECTOR_COLLECTION_OBJECT_POOL_COUNT 1 struct priority_collectors { - uint32_t interval; collector_priority_t priority; collector_t *current_collector_ptr; - linked_list_collector_t collector_list; + linked_list_t collector_list; }; struct collector_collection { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct collector_collection); priority_collectors_t collector_array[COLLECTOR_PRIORITY_COUNT]; @@ -38,18 +38,16 @@ struct collector_collection { OBJECT_POOL_DECLARATIONS(collector_collection_t) OBJECT_POOL_DEFINITIONS(collector_collection_t, COLLECTOR_COLLECTION_OBJECT_POOL_COUNT) -static asc_result_t _collector_collection_init_collector_lists(collector_collection_t *collector_collection_ptr, collector_init_function_t *collector_init_array, uint32_t array_size); -static void _collector_collection_deinit_collector_lists(linked_list_collector_t_handle collector_list_ptr); -static bool _collector_collection_type_match_function(collector_t *collector_ptr, void *match_context); +static void _collector_collection_init_collector_lists(collector_collection_t *collector_collection_ptr); +static void _collector_collection_deinit_collector_lists(linked_list_t *collector_list_ptr); +static bool _collector_collection_type_match_function(void *item, void *match_context); -collector_collection_t *collector_collection_init() +collector_collection_t *collector_collection_init(void) { log_debug("Init collector collection"); asc_result_t result = ASC_RESULT_OK; collector_collection_t *collector_collection_ptr = NULL; - collector_init_function_t *collector_init_array = NULL; - uint32_t collector_init_array_size = 0; collector_collection_ptr = object_pool_get(collector_collection_t); if (collector_collection_ptr == NULL) { @@ -60,25 +58,8 @@ collector_collection_t *collector_collection_init() memset(collector_collection_ptr, 0, sizeof(collector_collection_t)); - result = collector_collection_factory_get_initialization_array(&collector_init_array, &collector_init_array_size); - if (result != ASC_RESULT_OK) { - log_error("Collector collection array is not being initialized properly"); - goto cleanup; - } - - result = _collector_collection_init_collector_lists(collector_collection_ptr, collector_init_array, collector_init_array_size); - if (result != ASC_RESULT_OK) { - log_error("Collector collection failed to initialize collector lists, result=[%d]", result); - goto cleanup; - } - - result = collector_collection_internal_init_startup_time(collector_collection_ptr); - if (result != ASC_RESULT_OK) { - log_error("Collector collection failed to init collectors startup time, result=[%d]", result); - goto cleanup; - } - - + _collector_collection_init_collector_lists(collector_collection_ptr); + cleanup: if (result != ASC_RESULT_OK) { log_error("Failed to initialize collector collection, result=[%d]", result); @@ -132,21 +113,27 @@ priority_collectors_t *collector_collection_get_by_priority(collector_collection } -static bool _collector_collection_type_match_function(collector_t *collector_ptr, void *match_context) +static bool _collector_collection_type_match_function(void *item, void *match_context) { - return collector_ptr == NULL ? false : collector_ptr->internal.type == *((collector_type_t *)match_context); + collector_t *collector_ptr = item; + return collector_ptr == NULL ? false : collector_ptr->internal.type == *((collector_enum_t *)match_context); } -collector_t *collector_collection_get_collector_by_priority(collector_collection_t *collector_collection_ptr, collector_type_t type) +collector_t *collector_collection_get_collector_by_priority(collector_collection_t *collector_collection_ptr, collector_enum_t type) { collector_t *collector_ptr = NULL; - priority_collectors_t *priority_collector_ptr = collector_collection_get_head_priority(collector_collection_ptr); + priority_collectors_t *priority_collector_ptr = NULL; + + if (collector_collection_ptr == NULL) { + goto cleanup; + } + priority_collector_ptr = collector_collection_get_head_priority(collector_collection_ptr); while (priority_collector_ptr != NULL) { - linked_list_collector_t_handle collector_list = priority_collectors_get_list(priority_collector_ptr); + linked_list_t *collector_list = priority_collectors_get_list(priority_collector_ptr); - collector_ptr = linked_list_collector_t_find(collector_list, _collector_collection_type_match_function, &type); + collector_ptr = linked_list_find(collector_list, _collector_collection_type_match_function, &type); if (collector_ptr != NULL) { goto cleanup; } @@ -159,84 +146,39 @@ collector_t *collector_collection_get_collector_by_priority(collector_collection } -void collector_collection_foreach(collector_collection_t *collector_collection_ptr, linked_list_collector_t_action action_function, void *context) +void collector_collection_foreach(collector_collection_t *collector_collection_ptr, void(*action_function)(collector_t *collector, void *context), void *context) { - for (priority_collectors_t *prioritized_collectors = collector_collection_get_head_priority(collector_collection_ptr) ; prioritized_collectors != NULL; prioritized_collectors = collector_collection_get_next_priority(collector_collection_ptr, prioritized_collectors)) { - linked_list_collector_t_foreach(priority_collectors_get_list(prioritized_collectors), action_function, context); - } -} - - -uint32_t priority_collectors_get_interval(priority_collectors_t *priority_collectors_ptr) -{ - return priority_collectors_ptr->interval; -} - - -asc_result_t priority_collectors_set_interval(priority_collectors_t *priority_collectors_ptr, uint32_t interval) -{ - asc_result_t result = ASC_RESULT_OK; - - if (priority_collectors_ptr == NULL) - { - result = ASC_RESULT_BAD_ARGUMENT; + if (action_function == NULL) { + return; } - else - { - priority_collectors_ptr->interval = interval; + for (priority_collectors_t *prioritized_collectors = collector_collection_get_head_priority(collector_collection_ptr) ; prioritized_collectors != NULL; prioritized_collectors = collector_collection_get_next_priority(collector_collection_ptr, prioritized_collectors)) { + linked_list_t *linked_list_handle = priority_collectors_get_list(prioritized_collectors); + collector_t *curr = NULL; + linked_list_foreach(linked_list_handle, curr) { + action_function(curr, context); + } } - - return result; } - collector_priority_t priority_collectors_get_priority(priority_collectors_t *priority_collectors_ptr) { return priority_collectors_ptr->priority; } -linked_list_collector_t_handle priority_collectors_get_list(priority_collectors_t *priority_collectors_ptr) +linked_list_t *priority_collectors_get_list(priority_collectors_t *priority_collectors_ptr) { return &(priority_collectors_ptr->collector_list); } -asc_result_t _collector_collection_init_collector_lists(collector_collection_t *collector_collection_ptr, collector_init_function_t *collector_init_array, uint32_t collector_init_array_size) +static void _collector_collection_init_collector_lists(collector_collection_t *collector_collection_ptr) { - asc_result_t result = ASC_RESULT_OK; - for (unsigned int priority=0; priority < COLLECTOR_PRIORITY_COUNT; priority++) { - linked_list_collector_t_init(&(collector_collection_ptr->collector_array[priority].collector_list), NULL); - collector_collection_ptr->collector_array[priority].interval = g_collector_collections_intervals[priority]; + linked_list_init(&(collector_collection_ptr->collector_array[priority].collector_list)); collector_collection_ptr->collector_array[priority].current_collector_ptr = NULL; collector_collection_ptr->collector_array[priority].priority = (collector_priority_t)priority; } - - uint32_t collector_count = collector_init_array_size; - for (unsigned int i=0; i < collector_count; i++){ - collector_t *collector_ptr = collector_init(collector_init_array[i]); - - if (collector_ptr == NULL) { - result = ASC_RESULT_MEMORY_EXCEPTION; - goto cleanup; - } - - collector_priority_t priority = collector_get_priority(collector_ptr); - - linked_list_collector_t_handle current_collector_list_handle = &(collector_collection_ptr->collector_array[priority].collector_list); - - if (linked_list_collector_t_add_last(current_collector_list_handle, collector_ptr) == NULL){ - log_error("Could not append collector type=[%d] to collector list", collector_ptr->internal.type); - result = ASC_RESULT_EXCEPTION; - goto cleanup; - } - collector_collection_ptr->collector_array[priority].current_collector_ptr = linked_list_collector_t_get_first(current_collector_list_handle); - } - -cleanup: - - return result; } @@ -261,7 +203,7 @@ collector_t *priority_collectors_get_next_cyclic_collector(priority_collectors_t } if (current_item->next == NULL) { - current_item = linked_list_collector_t_get_first(&(priority_collectors_ptr->collector_list)); + current_item = linked_list_get_first(&priority_collectors_ptr->collector_list); } else { current_item = current_item->next; } @@ -270,17 +212,42 @@ collector_t *priority_collectors_get_next_cyclic_collector(priority_collectors_t } -static void _collector_collection_deinit_collector_lists(linked_list_collector_t_handle collector_list_ptr) +asc_result_t collector_collection_register(collector_collection_t *collector_collection_ptr, collector_t *collector_ptr, unsigned long collect_offset) { - collector_t *collector_ptr = linked_list_collector_t_get_first(collector_list_ptr); - while (collector_ptr != NULL) { - linked_list_collector_t_remove(collector_list_ptr, collector_ptr); + asc_result_t result = ASC_RESULT_OK; + collector_priority_t priority = collector_get_priority(collector_ptr); - if (collector_ptr != NULL) { - collector_deinit(collector_ptr); - } + linked_list_t *current_collector_list_handle = &(collector_collection_ptr->collector_array[priority].collector_list); - collector_ptr = linked_list_collector_t_get_first(collector_list_ptr); + if (linked_list_add_last(current_collector_list_handle, collector_ptr) == NULL){ + log_error("Could not append collector type=[%d] to collector list", collector_ptr->internal.type); + result = ASC_RESULT_EXCEPTION; + goto cleanup; } + collector_collection_ptr->collector_array[priority].current_collector_ptr = linked_list_get_first(current_collector_list_handle); + collector_set_last_collected_timestamp(collector_ptr, collect_offset); +cleanup: + return result; +} + + +void collector_collection_unregister(collector_collection_t *collector_collection_ptr, collector_t *collector_ptr) +{ + collector_priority_t priority = collector_get_priority(collector_ptr); + + linked_list_t *current_collector_list_handle = &(collector_collection_ptr->collector_array[priority].collector_list); + + linked_list_remove(current_collector_list_handle, collector_ptr, NULL); + collector_collection_ptr->collector_array[priority].current_collector_ptr = linked_list_get_first(current_collector_list_handle); +} + + +static void _collector_collection_deinit_collector_lists(linked_list_t *collector_list_ptr) +{ + collector_t *collector_ptr = linked_list_get_first(collector_list_ptr); + while (collector_ptr != NULL) { + linked_list_remove(collector_list_ptr, collector_ptr, NULL); + collector_ptr = linked_list_get_first(collector_list_ptr); + } } \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_factory.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_factory.c deleted file mode 100644 index 3bcd2308..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_factory.c +++ /dev/null @@ -1,63 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include -#include "asc_security_core/utils/itime.h" -#include "asc_security_core/logger.h" - -#include "asc_security_core/collector_collection_factory.h" -#include "asc_security_core/collectors_headers.h" - -static collector_init_function_t collector_init_array[] = { -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED - collector_system_information_init, -#endif -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED - collector_listening_ports_init, -#endif -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED - collector_network_activity_init, -#endif -#ifdef COLLECTOR_HEARTBEAT_ENABLED - collector_heartbeat_init, -#endif -#ifdef COLLECTOR_BASELINE_ENABLED - collector_baseline_init, -#endif -}; - - -asc_result_t collector_collection_factory_get_initialization_array(collector_init_function_t **init_array, uint32_t *init_array_size) -{ - asc_result_t result = ASC_RESULT_OK; - - if (init_array == NULL) { - log_error("Collector collection array cannot be initialize due to bad arguments"); - result = ASC_RESULT_BAD_ARGUMENT; - goto cleanup; - } - - if (collector_init_array == NULL) { - log_error("Collector collection array cannot be initialize due to collector_init_array=[NULL]"); - result = ASC_RESULT_UNINITIALIZED; - goto cleanup; - } - - *init_array = collector_init_array; - *init_array_size = sizeof(collector_init_array) / sizeof(collector_init_function_t); - -cleanup: - if (result != ASC_RESULT_OK) { - log_error("Failed to retrieve collector collection initialization array"); - } - - return result; -} \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_internal.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_internal.c deleted file mode 100644 index 1c46b388..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collector_collection_internal.c +++ /dev/null @@ -1,93 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "asc_security_core/collector_collection.h" -#include "asc_security_core/collector_collection_internal.h" -#include "asc_security_core/collectors_headers.h" -#include "asc_security_core/logger.h" -#include "asc_security_core/utils/collection/linked_list.h" -#include "asc_security_core/utils/irand.h" -#include "asc_security_core/utils/itime.h" - -const char *g_collector_names[COLLECTOR_TYPE_COUNT] = { -#ifdef COLLECTOR_SYSTEM_INFORMATION_ENABLED - COLLECTOR_NAME_SYSTEM_INFORMATION, -#endif -#ifdef COLLECTOR_NETWORK_ACTIVITY_ENABLED - COLLECTOR_NAME_NETWORK_ACTIVITY, -#endif -#ifdef COLLECTOR_LISTENING_PORTS_ENABLED - COLLECTOR_NAME_LISTENING_PORTS, -#endif -#ifdef COLLECTOR_HEARTBEAT_ENABLED - COLLECTOR_NAME_HEARTBEAT, -#endif -#ifdef COLLECTOR_BASELINE_ENABLED - COLLECTOR_NAME_BASELINE, -#endif -}; - -const uint32_t g_collector_collections_intervals[COLLECTOR_PRIORITY_COUNT] = { - ASC_HIGH_PRIORITY_INTERVAL, - ASC_MEDIUM_PRIORITY_INTERVAL, - ASC_LOW_PRIORITY_INTERVAL -}; - -static asc_result_t collector_collection_internal_set_random_collected_time(priority_collectors_t *priority_collector_ptr); - -asc_result_t collector_collection_internal_init_startup_time(collector_collection_t *collector_collection_ptr) -{ - asc_result_t result = ASC_RESULT_OK; - - priority_collectors_t *priority_collector_ptr = collector_collection_get_head_priority(collector_collection_ptr); - - while (priority_collector_ptr != NULL) { - result = collector_collection_internal_set_random_collected_time(priority_collector_ptr); - if (result != ASC_RESULT_OK) { - log_error("Failed to set random collected time to collectors, collector_priority=[%d], result=[%d]", priority_collectors_get_priority(priority_collector_ptr), result); - goto cleanup; - } - - priority_collector_ptr = collector_collection_get_next_priority(collector_collection_ptr, priority_collector_ptr); - } - -cleanup: - if (result != ASC_RESULT_OK) { - log_error("Failed to init collector collection init startup time, result=[%d]", result); - } - - return result; -} - -static asc_result_t collector_collection_internal_set_random_collected_time(priority_collectors_t *priority_collector_ptr) -{ - linked_list_collector_t_handle priority_collector_list = priority_collectors_get_list(priority_collector_ptr); - uint32_t collector_interval = priority_collectors_get_interval(priority_collector_ptr); - collector_t *collector_ptr = linked_list_collector_t_get_first(priority_collector_list); - uint32_t current_time = itime_time(NULL); - uint32_t last_collected_timestamp; - -#ifdef ASC_FIRST_FORCE_COLLECTION_INTERVAL - last_collected_timestamp = current_time - collector_interval + ASC_FIRST_FORCE_COLLECTION_INTERVAL; -#else - collector_priority_t priority = priority_collectors_get_priority(priority_collector_ptr); - uint32_t interval = (uint32_t)((priority+1) * ASC_FIRST_COLLECTION_INTERVAL); - uint32_t delta = (uint32_t)(irand_int() % (2 * interval) + interval); - last_collected_timestamp = current_time - collector_interval + delta; -#endif - - while (collector_ptr != NULL) { - collector_set_last_collected_timestamp(collector_ptr, last_collected_timestamp); - collector_ptr = collector_ptr->next; - } - - return ASC_RESULT_OK; -} \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors/collector_heartbeat.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors/collector_heartbeat.c index 1b0f96dd..bbbd64c9 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors/collector_heartbeat.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors/collector_heartbeat.c @@ -1,51 +1,39 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include -#include "asc_security_core/collectors/heartbeat.h" +#include + #include "asc_security_core/logger.h" -#include "asc_security_core/collector_enums.h" +#include "asc_security_core/components_manager.h" +#include "asc_security_core/core.h" #include "asc_security_core/object_pool.h" #include "asc_security_core/utils/itime.h" -#include "asc_security_core/utils/notifier.h" -static void _collector_heartbeat_deinit(collector_internal_t *collector_internal_ptr); static asc_result_t _collector_heartbeat_get_events(collector_internal_t *collector_internal_ptr, serializer_t *serializer); -asc_result_t collector_heartbeat_init(collector_internal_t *collector_internal_ptr) -{ - if (collector_internal_ptr == NULL) { - log_error("Could not initialize collector_heartbeat, bad argument"); - return ASC_RESULT_BAD_ARGUMENT; - } +static asc_result_t _collector_heartbeat_init(component_id_t id); - memset(collector_internal_ptr, 0, sizeof(*collector_internal_ptr)); +COLLECTOR_OPS_DEFINITIONS(, _collector_heartbeat_init, collector_default_deinit, + collector_default_subscribe, collector_default_unsubscribe, collector_default_start, collector_default_stop); - collector_internal_ptr->type = COLLECTOR_TYPE_HEARTBEAT; - collector_internal_ptr->priority = COLLECTOR_PRIORITY_LOW; - collector_internal_ptr->collect_function = _collector_heartbeat_get_events; - collector_internal_ptr->deinit_function = _collector_heartbeat_deinit; - notifier_notify(NOTIFY_TOPIC_SYSTEM, NOTIFY_MESSAGE_SYSTEM_CONFIGURATION, collector_internal_ptr); - - return ASC_RESULT_OK; -} +COMPONENTS_FACTORY_DEFINITION(Heartbeat, &_ops) -static void _collector_heartbeat_deinit(collector_internal_t *collector_internal_ptr) +static asc_result_t _collector_heartbeat_init(component_id_t id) { - memset(collector_internal_ptr, 0, sizeof(*collector_internal_ptr)); + return collector_default_create(id, Heartbeat, COLLECTOR_PRIORITY_LOW, _collector_heartbeat_get_events, ASC_LOW_PRIORITY_INTERVAL, NULL); } static asc_result_t _collector_heartbeat_get_events(collector_internal_t *collector_internal_ptr, serializer_t *serializer) { - uint32_t timestamp = itime_time(NULL); - return serializer_event_add_heartbeat(serializer, timestamp, g_collector_collections_intervals[collector_internal_ptr->priority]); + unsigned long timestamp = itime_time(NULL); + return serializer_event_add_heartbeat(serializer, timestamp, collector_internal_ptr->interval); } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors_info.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors_info.c index 0617de11..35192f9a 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors_info.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/collectors_info.c @@ -1,26 +1,28 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include +#include + #include "asc_security_core/logger.h" #include "asc_security_core/object_pool.h" #include "asc_security_core/collectors_info.h" -#include "asc_security_core/collector_enums.h" #include "asc_security_core/collector.h" +#include "asc_security_core/components_factory.h" #include "asc_security_core/utils/containerof.h" #include "asc_security_core/utils/notifier.h" typedef struct notifier_container_t { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct notifier_container_t); notifier_t notifier; @@ -41,18 +43,17 @@ static void _collector_info_cb(notifier_t *notifier, int message_num, void *payl return; } - if (collector_internal_ptr->type >= COLLECTORS_INFO_SIZE || - collector_internal_ptr->priority >= COLLECTOR_PRIORITY_COUNT) { - log_error("Wrong collector type=[%d] or priority=[%d]", collector_internal_ptr->type, collector_internal_ptr->priority); + if (collector_internal_ptr->type >= COLLECTORS_INFO_SIZE) { + log_error("Wrong collector type=[%d]", collector_internal_ptr->type); } else { - info[collector_internal_ptr->type].interval = g_collector_collections_intervals[collector_internal_ptr->priority]; - log_debug("Updated configuration for collector=[%s] with interval=[%u]\n", - g_collector_names[collector_internal_ptr->type], + info[collector_internal_ptr->type].interval = collector_internal_ptr->interval; + log_debug("Updated configuration for collector=[%d] with interval=[%lu]\n", + collector_internal_ptr->type, info[collector_internal_ptr->type].interval); } } -collectors_info_t *collectors_info_init() +collectors_info_t *collectors_info_init(void) { notifier_container_t *container = object_pool_get(notifier_container_t); @@ -62,7 +63,11 @@ collectors_info_t *collectors_info_init() } memset(container, 0, sizeof(notifier_container_t)); container->notifier.notify = _collector_info_cb; - notifier_subscribe(NOTIFY_TOPIC_SYSTEM, &container->notifier); + if (notifier_subscribe(NOTIFY_TOPIC_SYSTEM, &container->notifier) != ASC_RESULT_OK) { + collectors_info_deinit((collectors_info_t *)container); + return NULL; + } + return (collectors_info_t *)container; } @@ -86,6 +91,8 @@ collector_info_t *collectors_info_get(collectors_info_t *collectors_info, uint32 log_error("collectors_info_t *is NULL"); return NULL; } - *size = COLLECTORS_INFO_SIZE; + if (size) { + *size = COLLECTORS_INFO_SIZE; + } return container->info; } \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_factory.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_factory.c new file mode 100644 index 00000000..8371594b --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_factory.c @@ -0,0 +1,141 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#include + +#include + +#include "asc_security_core/components_factory_declarations.h" +#include "asc_security_core/components_manager.h" + +components_factory_t g_component_factory[COMPONENTS_COUNT]; + +static component_load_function_t *component_load_function_array[] = { + COMPONENTS_FACTORY_LOAD(ManagerCore), + COMPONENTS_FACTORY_LOAD(Logger), +#ifdef ASC_COMPONENT_SECURITY_MODULE + COMPONENTS_FACTORY_LOAD(SecurityModule), +#endif + COMPONENTS_FACTORY_LOAD(CollectorsCore), +#ifdef ASC_COMPONENT_CONFIGURATION + COMPONENTS_FACTORY_LOAD(Configuration), +#endif +#ifdef ASC_COMPONENT_CONFIGURATION_PLAT + COMPONENTS_FACTORY_LOAD(ConfigurationPlatform), +#endif +#ifdef ASC_COMPONENT_COMMAND_EXECUTOR_PLAT + COMPONENTS_FACTORY_LOAD(CommandExecutorPlatform), +#endif +#ifdef ASC_COLLECTOR_HEARTBEAT_ENABLED + COMPONENTS_FACTORY_LOAD(Heartbeat), +#endif +#ifdef ASC_COLLECTOR_BASELINE_ENABLED + COMPONENTS_FACTORY_LOAD(Baseline), +#endif +#ifdef ASC_COMPONENT_BASELINE_PLAT + COMPONENTS_FACTORY_LOAD(BaselinePlatform), +#endif +#ifdef ASC_COMPONENT_IPC_PLAT + COMPONENTS_FACTORY_LOAD(IpcPlatform), +#endif +#ifdef ASC_COMPONENT_CLI_PLAT + #ifdef ASC_COMPONENT_DEMO_CLI_PLAT + COMPONENTS_FACTORY_LOAD(CliDemoPlatform), + #endif + COMPONENTS_FACTORY_LOAD(CliPlatform), +#endif +#ifdef ASC_COLLECTOR_SYSTEM_INFORMATION_ENABLED + COMPONENTS_FACTORY_LOAD(SystemInformation), +#endif +#ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_ENABLED + COMPONENTS_FACTORY_LOAD(NetworkActivity), +#endif +#ifdef ASC_COLLECTOR_LISTENING_PORTS_ENABLED + COMPONENTS_FACTORY_LOAD(ListeningPorts), +#endif +#ifdef ASC_COLLECTOR_PROCESS_ENABLED + COMPONENTS_FACTORY_LOAD(Process), +#endif + NULL +}; + +component_load_function_t **components_factory_get_load_array(void) +{ + return component_load_function_array; +} + +component_id_t components_factory_create_id(int index) +{ + return (component_id_t)(&g_component_factory[index].component); +} + +asc_result_t components_factory_set(const char *name, int index, component_ops_t *ops, bool auto_disable) +{ + if (name == NULL || str_str(name, "_")) { + log_fatal("Component name=[%s] is wrong (NULL or has '_')", name ? name : "NULL"); + return ASC_RESULT_BAD_ARGUMENT; + } + if (components_manager_get_id_by_name(name, str_len(name))) { + log_fatal("Component name=[%s] already exists", name); + return ASC_RESULT_BAD_ARGUMENT; + } + g_component_factory[index].component.info.state = COMPONENT_LOADED; + g_component_factory[index].component.info.last_result = ASC_RESULT_OK; + g_component_factory[index].component.info.log_level = ASC_LOG_LEVEL; + g_component_factory[index].component.ops = ops; + g_component_factory[index].component.info.id = components_factory_create_id(index); + g_component_factory[index].component.info.name = name; + g_component_factory[index].component.info.enumerator = index; + g_component_factory[index].component.info.auto_start_disable = auto_disable; + bit_vector_clean(component_owners_t, &g_component_factory[index].component.info.owners); + //__auto_generated_self_id = g_component_factory[_component].component.info.id; + return ASC_RESULT_OK; +} + +#ifdef ASC_DYNAMIC_FACTORY_ENABLED +asc_result_t components_factory_set_dynamic_collector(const char *name, int index, component_ops_t *ops, bool auto_disable) +{ + if (index < (__COLLECTOR_COUNT + ASC_EXTRA_COLLECTORS_COUNT) || index >= COLLECTORS_COUNT) { + log_fatal("Index=[%d] is out of dynamic collectors area", index); + return ASC_RESULT_MEMORY_EXCEPTION; + } + return components_factory_set(name, index, ops, auto_disable); +} + +asc_result_t components_factory_set_dynamic_component(const char *name, int index, component_ops_t *ops, bool auto_disable) +{ + if (index < (__COMPONENT_COUNT + ASC_EXTRA_COMPONENTS_COUNT) || index >= COMPONENTS_COUNT) { + log_fatal("Index=[%d] is out of dynamic components area", index); + return ASC_RESULT_MEMORY_EXCEPTION; + } + return components_factory_set(name, index, ops, auto_disable); +} +#endif + +void component_factory_unload(int index) +{ + g_component_factory[index].component.ops = NULL; + g_component_factory[index].component.info.state = COMPONENT_UNLOADED; + g_component_factory[index].component.info.id = 0; + g_component_factory[index].component.info.name = NULL; + g_component_factory[index].component.info.enumerator = COMPONENTS_COUNT; + g_component_factory[index].component.info.log_level = ASC_LOG_LEVEL; + bit_vector_clean(component_owners_t, &g_component_factory[index].component.info.owners); +} + +void components_factory_unload(void) +{ + int index; + + for (index = 0; index < COMPONENTS_COUNT; index++) { + component_factory_unload(index); + } +} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_manager.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_manager.c new file mode 100644 index 00000000..c2900b3c --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/components_manager.c @@ -0,0 +1,458 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include +#include +#include + +#include + +#include "asc_security_core/logger.h" +#include "asc_security_core/utils/string_utils.h" + +#include "asc_security_core/components_factory_declarations.h" +#include "asc_security_core/components_manager.h" + +static bool _components_manager_initialized = false; +static uintptr_t _components_manager_global_context; + +static void components_manager_do_lcm_action(component_state_enum_t to_state, component_state_enum_t from_state); +static int _get_owner_enumerator(component_id_t owner_id); + +asc_result_t components_manager_init(void) +{ + asc_result_t result = ASC_RESULT_OK; + + if (_components_manager_initialized) { + log_debug("Aleady initialized"); + return ASC_RESULT_INITIALIZED; + } + + log_debug("Init"); + int index = 0; + component_load_function_t *func_ptr = NULL; + component_load_function_t **init_array = components_factory_get_load_array(); + + if (init_array == NULL) { + log_fatal("Unable to get components init array"); + return ASC_RESULT_EXCEPTION; + } + _components_manager_initialized = true; + + while ((func_ptr = init_array[index++])) { + component_load_function_t func = *func_ptr; + + if (func) { + asc_result_t ret = func(); + if (ret != ASC_RESULT_OK) { + result = ret; + log_fatal("Unable to load component with index=[%d]", index-1); + } + } + } + +#ifdef ASC_DYNAMIC_FACTORY_ENABLED + asc_result_t result_dyn = components_factory_load_dynamic(NULL); + if (result_dyn != ASC_RESULT_OK && result_dyn != ASC_RESULT_EMPTY) { + result = result_dyn; + } +#endif + + components_manager_do_lcm_action(COMPONENT_INITIALIZED, COMPONENT_LOADED); + components_manager_do_lcm_action(COMPONENT_SUBSCRIBED, COMPONENT_INITIALIZED); + components_manager_do_lcm_action(COMPONENT_RUNNING, COMPONENT_SUBSCRIBED); + + return result; +} + +asc_result_t components_manager_deinit(void) +{ + if (!_components_manager_initialized) { + log_debug("Unintialized"); + return ASC_RESULT_IMPOSSIBLE; + } + _components_manager_initialized = false; + log_debug("Deinit"); + components_manager_do_lcm_action(COMPONENT_STOPED, COMPONENT_RUNNING); + components_manager_do_lcm_action(COMPONENT_UNSUBSCRIBED, COMPONENT_UNDEFINED); + components_manager_do_lcm_action(COMPONENT_LOADED, COMPONENT_UNDEFINED); + +#ifdef ASC_DYNAMIC_FACTORY_ENABLED + components_factory_unload_dynamic(); // must be before components_factory_unload(); +#endif + components_factory_unload(); + _components_manager_global_context = 0; + return ASC_RESULT_OK; +} + +void components_manager_global_context_set(uintptr_t ctx) +{ + _components_manager_global_context = ctx; +} + +uintptr_t components_manager_global_context_get(void) +{ + return _components_manager_global_context; +} + +#ifdef ASC_COMPONENT_CONFIGURATION +bool components_manager_set_log_level(component_id_t id, int set) +{ + unsigned int level = (set < 0) ? ASC_LOG_LEVEL : (unsigned int)set; + + if (level > ASC_LOG_LEVEL) { + log_error("Requested log level=[%u] is above than compiled=[%u]", level, ASC_LOG_LEVEL); + return false; + } + if (!id) { + id = components_manager_get_id(ManagerCore); + } + component_info_t *info = components_manager_get_info(id); + + if (info) { + info->log_level = level; + return true; + } + return false; +} + +unsigned int components_manager_get_log_level(component_id_t id) +{ + if (!id) { + id = components_manager_get_id(ManagerCore); + } + component_info_t *info = components_manager_get_info(id); + + // return debug if no info or not initialized yet to not lost the log print + if (!info || info->state == COMPONENT_UNLOADED) { + return LOG_LEVEL_DEBUG; + } + + return info->log_level; +} + +bool components_manager_set_log_level_all(int set) +{ + unsigned int level = (set < 0) ? ASC_LOG_LEVEL : (unsigned int)set; + + if (level > ASC_LOG_LEVEL) { + log_error("Requested log level=[%u] is above than compiled=[%u]", level, ASC_LOG_LEVEL); + return false; + } + for (int index = 0; index < COMPONENTS_COUNT; index++) { + g_component_factory[index].component.info.log_level = level; + } + return true; +} +#endif + +component_t *components_manager_get_component(component_id_t id) +{ + for (int index = 0; index < COMPONENTS_COUNT; index++) { + if (g_component_factory[index].component.info.id == id) { + return &g_component_factory[index].component; + } + } + return NULL; +} + +component_id_t components_manager_get_id_by_name(const char *name, size_t len) +{ + if (str_isempty(name)) { + return 0; + } + + for (int index = 0; index < COMPONENTS_COUNT; index++) { + + if (!str_ncmp(g_component_factory[index].component.info.name, + str_len(g_component_factory[index].component.info.name), name, len)) { + return g_component_factory[index].component.info.id; + } + } + return 0; +} + +component_info_t *components_manager_get_info(component_id_t id) +{ + component_t *component = components_manager_get_component(id); + + return component ? &component->info : NULL; +} + +void *__components_manager_get_ctx(component_id_t id) +{ + component_t *component = components_manager_get_component(id); + + return component ? component->info.ctx : NULL; +} + +void __components_manager_set_ctx(component_id_t id, void *ctx) +{ + component_t *component = components_manager_get_component(id); + + if (component) { + component->info.ctx = ctx; + } +} + +asc_result_t components_manager_get_last_result(component_id_t id) +{ + component_t *component = components_manager_get_component(id); + + return component ? component->info.last_result : ASC_RESULT_UNINITIALIZED; +} + +const char *components_manager_get_name(component_id_t id) +{ + component_t *component = components_manager_get_component(id); + + return component ? component->info.name : ""; +} + +asc_result_t components_manager_start(component_id_t id, component_id_t owner_id) +{ + asc_result_t result = ASC_RESULT_OK; + component_t *component = components_manager_get_component(id); + int owner_enumerator = -1; + component_state_enum_t cur_state = COMPONENT_UNLOADED; + component_ops_t *ops = NULL; + lcm_func_t func = NULL; + + if (!component) { + return ASC_RESULT_BAD_ARGUMENT; + } + + owner_enumerator = _get_owner_enumerator(owner_id); + if (owner_enumerator < 0) { + return ASC_RESULT_BAD_ARGUMENT; + } + + cur_state = component->info.state; + if (cur_state != COMPONENT_SUBSCRIBED && cur_state != COMPONENT_STOPED && cur_state != COMPONENT_RUNNING) { + result = ASC_RESULT_IMPOSSIBLE; + goto cleanup; + } + + /* Handle case already in running state */ + if (cur_state == COMPONENT_RUNNING) { + bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, true); + goto cleanup; + } + + ops = component->ops; + func = ops ? ops->start : NULL; + + result = func ? func(id) : ASC_RESULT_OK; + if (result == ASC_RESULT_OK) { + bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, true); + component->info.state = COMPONENT_RUNNING; + } + goto cleanup; + +cleanup: + if (result != ASC_RESULT_OK) { + component->info.state = COMPONENT_FAIL; + log_error("failed to start component=[%s]", component->info.name); + } + return result; +} + +asc_result_t components_manager_stop(component_id_t id, component_id_t owner_id, bool ignore_self_owner, bool force) +{ + asc_result_t result = ASC_RESULT_OK; + component_t *component = components_manager_get_component(id); + int owner_enumerator = -1; + bool owner = false; + bool self_owner = false; + + if (!component) { + return ASC_RESULT_BAD_ARGUMENT; + } + + owner_enumerator = _get_owner_enumerator(owner_id); + if (owner_enumerator < 0) { + return ASC_RESULT_BAD_ARGUMENT; + } + + if (component->info.state == COMPONENT_FAIL) { + result = ASC_RESULT_IMPOSSIBLE; + goto cleanup; + } + + /* Handle case already in stopped state */ + if (component->info.state != COMPONENT_RUNNING) { + if (force) { + bit_vector_clean(component_owners_t, &component->info.owners); + } else { + if (ignore_self_owner) { + bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, false); + } + bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, false); + } + goto cleanup; + } + + /* Prepare vector */ + if (force) { + bit_vector_clean(component_owners_t, &component->info.owners); + } else { + owner = bit_vector_get(component_owners_t, &component->info.owners, owner_enumerator); + self_owner = bit_vector_get(component_owners_t, &component->info.owners, component->info.enumerator); + if (ignore_self_owner) { + bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, false); + } + bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, false); + } + + /* Performe stop */ + if (is_bit_vector_zero(component_owners_t, &component->info.owners)) { + component_ops_t *ops = component->ops; + lcm_func_t func = ops ? ops->stop : NULL; + + result = func ? func(id) : ASC_RESULT_OK; + if (result == ASC_RESULT_OK) { + component->info.state = COMPONENT_STOPED; + } else { + /* Restore status of owners */ + bit_vector_set(component_owners_t, &component->info.owners, owner_enumerator, owner); + bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, self_owner); + } + } else { + /* Restore status of self owner */ + bit_vector_set(component_owners_t, &component->info.owners, component->info.enumerator, self_owner); + } + +cleanup: + if (result != ASC_RESULT_OK) { + component->info.state = COMPONENT_FAIL; + log_error("failed to stop component=[%s]", component->info.name); + } + return result; +} + +static lcm_func_t _load_lcm_function(int index, component_state_enum_t to_state, component_state_enum_t from_state) +{ + lcm_func_t func = NULL; + component_ops_t *ops = g_component_factory[index].component.ops; + + if (ops) { + switch (to_state) { + case COMPONENT_INITIALIZED: + func = ops->init; + break; + case COMPONENT_SUBSCRIBED: + func = ops->subscribe; + break; + case COMPONENT_RUNNING: + func = ops->start; + break; + case COMPONENT_STOPED: + func = ops->stop; + break; + case COMPONENT_UNSUBSCRIBED: + func = ops->unsubscribe; + break; + case COMPONENT_LOADED: + func = ops->deinit; + break; + default: + g_component_factory[index].component.info.last_result = ASC_RESULT_NOT_SUPPORTED_EXCEPTION; + log_fatal("Unsupported LCM state=[%d]", to_state); + return NULL; + } + } + + log_debug("lcm function component=[%s] ops=[%p] is defined=[%d] to=[%d] from=[%d] current=[%d]", + g_component_factory[index].component.info.name, + (void *)ops, func ? 1 : 0, to_state, from_state, + g_component_factory[index].component.info.state); + + return func; +} + +static void _perform_lcm_action(lcm_func_t func, int index, component_state_enum_t to_state) +{ + switch (to_state) + { + case COMPONENT_RUNNING: + if (!g_component_factory[index].component.info.auto_start_disable) { + g_component_factory[index].component.info.last_result = + components_manager_start(g_component_factory[index].component.info.id, g_component_factory[index].component.info.id); + } else { + log_debug("%d function is disabled by auto_start_disable==true in component=[%s]", to_state, g_component_factory[index].component.info.name); + } + + break; + case COMPONENT_STOPED: + g_component_factory[index].component.info.last_result = + components_manager_stop(g_component_factory[index].component.info.id, g_component_factory[index].component.info.id, false, true); + break; + default: + if (func == NULL) { + if (g_component_factory[index].component.info.state != COMPONENT_FAIL) { + g_component_factory[index].component.info.state = to_state; + } + log_debug("%d function function in component=[%s] is not armed", to_state, g_component_factory[index].component.info.name); + return; + } + g_component_factory[index].component.info.last_result = func(g_component_factory[index].component.info.id); + + if (g_component_factory[index].component.info.last_result != ASC_RESULT_OK) { + g_component_factory[index].component.info.state = COMPONENT_FAIL; + log_error("failed to %d function component=[%s]", to_state, g_component_factory[index].component.info.name); + } else { + g_component_factory[index].component.info.state = to_state; + log_debug("%d function component=[%s] done", to_state, g_component_factory[index].component.info.name); + } + break; + } +} + +static void components_manager_do_lcm_action(component_state_enum_t to_state, component_state_enum_t from_state) +{ + for (int index = 0; index < COMPONENTS_COUNT; index++) { + if (g_component_factory[index].component.info.state == COMPONENT_UNLOADED) { + continue; + } + g_component_factory[index].component.info.last_result = ASC_RESULT_OK; + + lcm_func_t func = _load_lcm_function(index, to_state, from_state); + + if (g_component_factory[index].component.info.last_result == ASC_RESULT_NOT_SUPPORTED_EXCEPTION) { + return; + } + + bool is_stop_start_same_state = false; + + if (g_component_factory[index].component.info.state == to_state && (to_state == COMPONENT_RUNNING || to_state == COMPONENT_STOPED)) { + is_stop_start_same_state = true; + } + + if (func && !is_stop_start_same_state && from_state != COMPONENT_UNDEFINED && g_component_factory[index].component.info.state != from_state) { + log_error("Expected=[%d] state is not match current=[%d] component=[%s]", from_state, g_component_factory[index].component.info.state, g_component_factory[index].component.info.name); + g_component_factory[index].component.info.last_result = ASC_RESULT_PARSE_EXCEPTION; + continue; + } + _perform_lcm_action(func, index, to_state); + } +} + +static int _get_owner_enumerator(component_id_t owner_id) +{ + component_t *owner = components_manager_get_component(owner_id); + + if (owner == NULL) { + return -1; + } + return owner->info.enumerator; +} + +/* Component manager is component itself */ +COMPONENTS_FACTORY_DEFINITION(ManagerCore, NULL) diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c index b148e535..5a6be1cb 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/core.c @@ -1,35 +1,130 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include -#include "asc_security_core/collector_collection.h" -#include "asc_security_core/configuration.h" +#include + +#include "asc_security_core/components_manager.h" #include "asc_security_core/logger.h" -#include "asc_security_core/collector.h" #include "asc_security_core/object_pool.h" #include "asc_security_core/serializer.h" +#include "asc_security_core/utils/ievent_loop.h" #include "asc_security_core/utils/itime.h" +#include "asc_security_core/utils/irand.h" +#include "asc_security_core/utils/notifier.h" #include "asc_security_core/utils/os_utils.h" #include "asc_security_core/core.h" +#include "asc_security_core/version.h" #define CORE_OBJECT_POOL_COUNT 1 +#define CORE_RESTART_SLEEP 1 + +typedef struct core { + /* This macro must be first in object */ + COLLECTION_INTERFACE(struct core); + + const char *security_module_id; + uint32_t security_module_version; + collector_collection_t *collector_collection_ptr; + + uint8_t *message_buffer; + size_t message_buffer_size; +#ifdef ASC_DYNAMIC_MEMORY_ENABLED + bool message_allocated; +#endif + bool message_empty; + + serializer_t *serializer; + unsigned long init_random_collect_offset; + unsigned long nearest_collect_time; + event_loop_timer_handler h_collect; + event_loop_timer_handler h_start; + notifier_t security_module_state_notifier; +} core_t; OBJECT_POOL_DECLARATIONS(core_t) OBJECT_POOL_DEFINITIONS(core_t, CORE_OBJECT_POOL_COUNT) -core_t *core_init() +typedef struct { + unsigned long minimum; + unsigned long curr_time; + bool is_in_start; +} calc_nearest_collect_t; + +static asc_result_t _cm_init(component_id_t id); +static asc_result_t _cm_deinit(component_id_t id); +static asc_result_t _cm_start(component_id_t id); +static asc_result_t _cm_stop(component_id_t id); +static component_ops_t _ops = { + .init = _cm_init, + .deinit = _cm_deinit, + .start = _cm_start, + .stop = _cm_stop, +}; + +COMPONENTS_FACTORY_DEFINITION(CollectorsCore, &_ops) + +static void _core_deinit(core_t *core_ptr, component_id_t id); +static asc_result_t _set_next_collect_timer(core_t *core_ptr, unsigned long curr_time, bool is_in_start); +static void _security_module_state_cb(notifier_t *notifier, int message_num, void *payload); + +static void _init_random_collect_offset(core_t *core_ptr) +{ + unsigned long now = itime_time(NULL); + if (now == ITIME_FAILED) { + log_error("Error get current time"); + now = 0; + } +#ifdef ASC_FIRST_FORCE_COLLECTION_INTERVAL + #if ASC_FIRST_FORCE_COLLECTION_INTERVAL < 0 + core_ptr->init_random_collect_offset = now; + #else + core_ptr->init_random_collect_offset = now + ASC_FIRST_FORCE_COLLECTION_INTERVAL; + #endif +#else + core_ptr->init_random_collect_offset = now + (unsigned long)(irand_int() % (2 * ASC_FIRST_COLLECTION_INTERVAL) + ASC_FIRST_COLLECTION_INTERVAL); +#endif +} + +static unsigned long _calculate_collector_time_offset(core_t *core_ptr, collector_t *collector_ptr, component_state_enum_t state) +{ + unsigned long offset, base_collecting_time = core_ptr->init_random_collect_offset; + + // TODO it breaks sequence of collections and cause to increasing of security messages - need to sync on init_random_collect_offset + if (state == COMPONENT_RUNNING) { + unsigned long now = itime_time(NULL); + if (now == ITIME_FAILED) { + log_error("Error get current time"); + now = 0; + } + base_collecting_time = now + ASC_FIRST_COLLECTION_INTERVAL; + } + if (collector_ptr->internal.interval > core_ptr->init_random_collect_offset) { + // should never happens + offset = base_collecting_time; + } else { + if (base_collecting_time >= collector_ptr->internal.interval) { + offset = base_collecting_time - collector_ptr->internal.interval; + } else { + // should never happens + offset = base_collecting_time; + } + } + return offset; +} + +static core_t *core_init(component_id_t id) { asc_result_t result = ASC_RESULT_OK; core_t *core_ptr = NULL; @@ -41,6 +136,7 @@ core_t *core_init() goto cleanup; } memset(core_ptr, 0, sizeof(core_t)); + core_ptr->nearest_collect_time = CORE_NEAREST_TIMER_UNSET_VAL; core_ptr->security_module_id = os_utils_get_security_module_id(); if (core_ptr->security_module_id == NULL) { @@ -67,29 +163,34 @@ core_t *core_init() result = serializer_message_begin(core_ptr->serializer, core_ptr->security_module_id, core_ptr->security_module_version); -#ifdef DYNAMIC_MEMORY_ENABLED +#ifdef ASC_DYNAMIC_MEMORY_ENABLED core_ptr->message_allocated = false; #endif core_ptr->message_empty = true; + _init_random_collect_offset(core_ptr); + + core_ptr->security_module_state_notifier.notify = _security_module_state_cb; + result = notifier_subscribe(NOTIFY_TOPIC_SECURITY_MODULE_STATE, &core_ptr->security_module_state_notifier); cleanup: if (result != ASC_RESULT_OK) { log_error("Failed to init client core_t"); - core_deinit(core_ptr); + _core_deinit(core_ptr, id); core_ptr = NULL; } return core_ptr; } -void core_deinit(core_t *core_ptr) +static void _core_deinit(core_t *core_ptr, component_id_t id) { if (core_ptr != NULL) { + notifier_unsubscribe(NOTIFY_TOPIC_SECURITY_MODULE_STATE, &core_ptr->security_module_state_notifier); if (core_ptr->collector_collection_ptr != NULL) { collector_collection_deinit(core_ptr->collector_collection_ptr); } -#ifdef DYNAMIC_MEMORY_ENABLED +#ifdef ASC_DYNAMIC_MEMORY_ENABLED if (core_ptr->message_allocated) { free(core_ptr->message_buffer); core_ptr->message_buffer = NULL; @@ -103,31 +204,154 @@ void core_deinit(core_t *core_ptr) object_pool_free(core_t, core_ptr); core_ptr = NULL; } + components_manager_set_self_ctx(NULL); +} + +static void _start_stop_all_collectors(collector_t *collector_ptr, void *context) +{ + bool do_start = *(bool*)context; + + component_id_t collector_id = components_manager_get_id(collector_ptr->internal.type); + component_id_t core_id = components_manager_get_self_id(); + + if (do_start) { + components_manager_start(collector_id, core_id); + } else { + components_manager_stop(collector_id, core_id, true, false); + } +} + +#ifdef ASC_COMPONENT_CORE_SUPPORTS_RESTART +static void _reset_last_collected_timestamp(collector_t *collector_ptr, void *context) +{ + core_t *core_ptr = context; + + unsigned long offset = _calculate_collector_time_offset(core_ptr, collector_ptr, COMPONENT_STOPED); + + collector_set_last_collected_timestamp(collector_ptr, offset); +} + +static void cb_do_start(event_loop_timer_handler h, void *ctx) +{ + core_t *core_ptr = ctx; + ievent_loop_t *el = ievent_loop_get_instance(); + + el->timer_delete(h); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return; + } + bool do_start = true; + component_id_t core_id = components_manager_get_self_id(); + _init_random_collect_offset(core_ptr); + collector_collection_foreach(core_ptr->collector_collection_ptr, _reset_last_collected_timestamp, core_ptr); + collector_collection_foreach(core_ptr->collector_collection_ptr, _start_stop_all_collectors, &do_start); + components_manager_start(core_id, core_id); +} +#endif + +static void _start_stop_collection(bool do_start, bool restart) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return; + } + component_id_t core_id = components_manager_get_self_id(); + +#ifdef ASC_COMPONENT_CORE_SUPPORTS_RESTART + if (restart) { + bool restart_do_start = false; + collector_collection_foreach(core_ptr->collector_collection_ptr, _start_stop_all_collectors, &restart_do_start); + components_manager_stop(core_id, core_id, false, false); + core_message_deinit(); + ievent_loop_t *el = ievent_loop_get_instance(); + el->timer_delete(core_ptr->h_start); + core_ptr->h_start = el->timer_create(cb_do_start, core_ptr, CORE_RESTART_SLEEP, 0, &core_ptr->h_start); + } else +#endif + { + collector_collection_foreach(core_ptr->collector_collection_ptr, _start_stop_all_collectors, &do_start); + + if (do_start) { + components_manager_start(core_id, core_id); + } else { + components_manager_stop(core_id, core_id, false, false); + } + } } -asc_result_t core_collect(core_t *core_ptr) +static void _security_module_state_cb(notifier_t *notifier, int message_num, void *payload) +{ + switch (message_num) + { + case NOTIFY_SECURITY_MODULE_CONNECTED: + _start_stop_collection(true, false); + log_info("Security Module inserted to 'Connected' state"); + break; +#ifdef ASC_COMPONENT_CORE_SUPPORTS_RESTART + case NOTIFY_SECURITY_MODULE_RESTART: + _start_stop_collection(true, true); + log_info("Security Module inserted to 'Connected' state with restart"); + break; +#endif + case NOTIFY_SECURITY_MODULE_PENDING: + _start_stop_collection(true, false); + log_info("Security Module inserted to 'Pending' state"); + break; + case NOTIFY_SECURITY_MODULE_SUSPENDED: + _start_stop_collection(false, false); + log_info("Security Module inserted to 'Suspended' state"); + break; + default: + log_error("Unsupported Security Module state"); + break; + } +} + +static asc_result_t core_collect(core_t *core_ptr, unsigned long now) { asc_result_t result = ASC_RESULT_OK; - uint32_t current_snapshot = itime_time(NULL); bool at_least_one_success = false; bool time_passed = false; + if (now == ITIME_FAILED) { + log_error("Error get current time"); + return ASC_RESULT_IMPOSSIBLE; + } + + core_message_deinit(); + for (priority_collectors_t *prioritized_collectors = collector_collection_get_head_priority(core_ptr->collector_collection_ptr); prioritized_collectors != NULL; prioritized_collectors = collector_collection_get_next_priority(core_ptr->collector_collection_ptr, prioritized_collectors) ) { - linked_list_collector_t_handle collector_list = priority_collectors_get_list(prioritized_collectors); + linked_list_t *collector_list = priority_collectors_get_list(prioritized_collectors); + collector_t *current_collector = NULL; + linked_list_foreach(collector_list, current_collector) + { + component_info_t *info = components_manager_get_info(components_manager_get_id(current_collector->internal.type)); + if (!info || info->state != COMPONENT_RUNNING) { + continue; + } - for (collector_t *current_collector=linked_list_collector_t_get_first(collector_list); - current_collector!=NULL; - current_collector=current_collector->next - ) { - uint32_t last_collected = collector_get_last_collected_timestamp(current_collector); - double interval = priority_collectors_get_interval(prioritized_collectors); + unsigned long last_collected = collector_get_last_collected_timestamp(current_collector); + unsigned long interval = current_collector->internal.interval; + unsigned long delta; + if (now > last_collected) { + delta = now - last_collected; + } else { + log_error("Current time is less than last collected interval"); + delta = interval; + } - if (current_snapshot - last_collected >= interval) { + if (delta >= interval) { time_passed = true; result = collector_serialize_events(current_collector, core_ptr->serializer); + // overwrite last collected time with common start value to store sequence of collections + collector_set_last_collected_timestamp(current_collector, now); if (result == ASC_RESULT_EMPTY) { log_debug("empty, collector type=[%d]", current_collector->internal.type); continue; @@ -145,18 +369,114 @@ asc_result_t core_collect(core_t *core_ptr) error: // In case of serializer failure, it is unsafe to keep building the message - core_message_deinit(core_ptr); + core_message_deinit(); return ASC_RESULT_EXCEPTION; } +static void _collector_collection_calc_nearest_collect(collector_t *collector_ptr, void *context) +{ + calc_nearest_collect_t *ctx = (calc_nearest_collect_t *)context; + component_info_t *info = components_manager_get_info(components_manager_get_id(collector_ptr->internal.type)); + + /* Exclude failed collectors from nearest collect time calculation */ + if (!info) { + return; + } + if (!ctx->is_in_start) { + if (info->state != COMPONENT_RUNNING) { + return; + } + } else { /* If we are in core start function take in account also subscribed collectors */ + if (info->state != COMPONENT_RUNNING && info->state != COMPONENT_SUBSCRIBED) { + return; + } + } + + unsigned long curr_time = ctx->curr_time; + unsigned long last_collected = collector_get_last_collected_timestamp(collector_ptr); + unsigned long interval = collector_ptr->internal.interval; + unsigned long next_time; + + if (last_collected > curr_time) { + next_time = last_collected - curr_time + interval; + } else { + unsigned long delta = curr_time - last_collected; + if (interval <= delta) { + next_time = 0; + } else { + next_time = interval - delta; + } + } + + if (next_time < ctx->minimum) { + ctx->minimum = next_time; + } +} + +static void cb_collect(event_loop_timer_handler h, void *ctx) +{ + core_t *core_ptr = ctx; + ievent_loop_t *el = ievent_loop_get_instance(); + + el->timer_delete(h); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return; + } + unsigned long curr_time = itime_time(NULL); + + if (core_collect(core_ptr, curr_time) == ASC_RESULT_OK) { + notifier_notify(NOTIFY_TOPIC_COLLECT, NOTIFY_MESSAGE_READY, NULL); + } + _set_next_collect_timer(core_ptr, curr_time, false); +} + +static asc_result_t _set_next_collect_timer(core_t *core_ptr, unsigned long now, bool is_in_start) +{ + ievent_loop_t *el = ievent_loop_get_instance(); + calc_nearest_collect_t ctx; + + // stop existing timer + el->timer_delete(core_ptr->h_collect); -asc_result_t core_message_get(core_t* core_ptr, security_message_t* security_message_ptr) { + if (now == ITIME_FAILED) { + log_error("Error get current time"); + core_ptr->h_collect = el->timer_create(cb_collect, core_ptr, ASC_HIGH_PRIORITY_INTERVAL, 0, &core_ptr->h_collect); + core_ptr->nearest_collect_time = ASC_HIGH_PRIORITY_INTERVAL; + return ASC_RESULT_OK; + } + + ctx.minimum = CORE_NEAREST_TIMER_UNSET_VAL; + ctx.curr_time = now; + ctx.is_in_start = is_in_start; + + collector_collection_foreach(core_ptr->collector_collection_ptr, _collector_collection_calc_nearest_collect, &ctx); + + if (ctx.minimum == CORE_NEAREST_TIMER_UNSET_VAL) { + log_info("the list of collectors is empty"); + ctx.minimum = ASC_HIGH_PRIORITY_INTERVAL; + core_ptr->h_collect = el->timer_create(cb_collect, core_ptr, ctx.minimum, 0, &core_ptr->h_collect); + } else { + log_debug("the nearest collection interval=[%lu]", ctx.minimum); + core_ptr->h_collect = el->timer_create(cb_collect, core_ptr, ctx.minimum, 0, &core_ptr->h_collect); + } + + core_ptr->nearest_collect_time = ctx.minimum; + + return ASC_RESULT_OK; +} + +/* API Functions */ +asc_result_t core_message_get(security_message_t* security_message_ptr) +{ asc_result_t result = ASC_RESULT_OK; + core_t *core_ptr = components_manager_get_self_ctx(); if (core_ptr == NULL || security_message_ptr == NULL) { - result = ASC_RESULT_BAD_ARGUMENT; - log_error("bad argument"); + result = ASC_RESULT_MEMORY_EXCEPTION; + log_error("core uninitialized"); goto cleanup; } @@ -181,11 +501,11 @@ asc_result_t core_message_get(core_t* core_ptr, security_message_t* security_mes } if (result == ASC_RESULT_IMPOSSIBLE) { -#ifndef DYNAMIC_MEMORY_ENABLED +#ifndef ASC_DYNAMIC_MEMORY_ENABLED log_error("failed in serializer_buffer_get, message too big"); result = ASC_RESULT_EXCEPTION; goto cleanup; -#else /* DYNAMIC_MEMORY_ENABLED */ +#else /* ASC_DYNAMIC_MEMORY_ENABLED */ result = ASC_RESULT_OK; log_debug("failed in serializer_buffer_get on first attempt, re-allocating buffer..."); if (serializer_buffer_get_size(core_ptr->serializer, &core_ptr->message_buffer_size) != ASC_RESULT_OK) { @@ -209,7 +529,7 @@ asc_result_t core_message_get(core_t* core_ptr, security_message_t* security_mes goto cleanup; } log_debug("re-allocating buffer done successfully"); -#endif /* DYNAMIC_MEMORY_ENABLED */ +#endif /* ASC_DYNAMIC_MEMORY_ENABLED */ } } @@ -219,20 +539,60 @@ asc_result_t core_message_get(core_t* core_ptr, security_message_t* security_mes cleanup: if (result == ASC_RESULT_EXCEPTION || result == ASC_RESULT_MEMORY_EXCEPTION) { - core_message_deinit(core_ptr); + core_message_deinit(); } return result; } -asc_result_t core_message_deinit(core_t *core_ptr) +asc_result_t core_collector_register(collector_t *collector_ptr) { + core_t *core_ptr = components_manager_get_self_ctx(); + if (core_ptr == NULL) { - log_error("bad argument"); - return ASC_RESULT_BAD_ARGUMENT; + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + component_state_enum_t state = components_manager_get_info(components_manager_get_self_id())->state; + unsigned long offset = _calculate_collector_time_offset(core_ptr, collector_ptr, state); + + asc_result_t result = collector_collection_register(core_ptr->collector_collection_ptr, collector_ptr, offset); + + if (state == COMPONENT_RUNNING) { + _set_next_collect_timer(core_ptr, itime_time(NULL), false); } + return result; +} -#ifdef DYNAMIC_MEMORY_ENABLED +asc_result_t core_collector_unregister(collector_t *collector_ptr) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + + collector_collection_unregister(core_ptr->collector_collection_ptr, collector_ptr); + + component_state_enum_t state = components_manager_get_info(components_manager_get_self_id())->state; + + if (state == COMPONENT_RUNNING) { + _set_next_collect_timer(core_ptr, itime_time(NULL), false); + } + return ASC_RESULT_OK; +} + +asc_result_t core_message_deinit(void) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + +#ifdef ASC_DYNAMIC_MEMORY_ENABLED if (core_ptr->message_allocated) { free(core_ptr->message_buffer); core_ptr->message_allocated = false; @@ -255,3 +615,93 @@ asc_result_t core_message_deinit(core_t *core_ptr) return ASC_RESULT_OK; } + +unsigned long core_get_init_random_collect_offset(void) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return 0; + } + return core_ptr->init_random_collect_offset; +} + +unsigned long core_get_nearest_collect_time(void) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return 0; + } + return core_ptr->nearest_collect_time; +} + +collector_collection_t *core_get_collector_collection(void) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return NULL; + } + return core_ptr->collector_collection_ptr; +} + +/* OPS Functions */ +static asc_result_t _cm_init(component_id_t id) +{ + core_t *ptr = core_init(id); + + if (ptr == NULL) { + components_manager_set_self_ctx(NULL); + return ASC_RESULT_EXCEPTION; + } + components_manager_set_self_ctx(ptr); + + return ASC_RESULT_OK; +} + +static asc_result_t _cm_deinit(component_id_t id) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + + _core_deinit(core_ptr, id); + return ASC_RESULT_OK; +} + +asc_result_t _cm_stop(component_id_t id) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + ievent_loop_t *el = ievent_loop_get_instance(); + el->timer_delete(core_ptr->h_start); + el->timer_delete(core_ptr->h_collect); + core_ptr->nearest_collect_time = CORE_NEAREST_TIMER_UNSET_VAL; + + return ASC_RESULT_OK; +} + +static asc_result_t _cm_start(component_id_t id) +{ + core_t *core_ptr = components_manager_get_self_ctx(); + + if (core_ptr == NULL) { + log_error("core uninitialized"); + return ASC_RESULT_MEMORY_EXCEPTION; + } + ievent_loop_t *el = ievent_loop_get_instance(); + el->timer_delete(core_ptr->h_start); + /* Last parameter is 'true' because we do not want to base on sequence so we taking in account all registered collectors here */ + return _set_next_collect_timer(core_ptr, itime_time(NULL), true); +} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/logger.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/logger.c index 1f56716e..a9a99b33 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/logger.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/logger.c @@ -1,33 +1,260 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include + +#include +#include "asc_security_core/components_manager.h" +// #define ASC_TIME_H_SUPPORT + +#if ASC_LOG_LEVEL != LOG_LEVEL_NOTSET + +#ifdef ASC_TIME_H_SUPPORT +#include +#endif + +#include "asc_security_core/logger.h" +#include "asc_security_core/utils/itime.h" +#include "asc_security_core/utils/string_utils.h" +#ifdef ASC_COMPONENT_CONFIGURATION +#include "asc_security_core/configuration.h" +#endif +#include "asc_security_core/utils/iconv.h" +#include "asc_security_core/utils/string_utils.h" #include "asc_security_core/logger.h" -#if LOG_LEVEL != LOG_LEVEL_NOTSET -bool logger_init() +static unsigned int _system_level = ASC_LOG_LEVEL; +#ifdef ASC_LOG_TIMESTAMP_DEFAULT +static bool _timestamp = true; +#else +static bool _timestamp = false; +#endif + +static code2string_t _log_levels[] = { + {LOG_LEVEL_NOTSET, "NOSET"}, + {LOG_LEVEL_FATAL, "FATAL"}, + {LOG_LEVEL_ERROR, "ERROR"}, + {LOG_LEVEL_WARN, "WARN"}, + {LOG_LEVEL_INFO, "INFO"}, + {LOG_LEVEL_DEBUG, "DEBUG"}, + {-1, NULL} +}; + +static asc_result_t _cm_init(component_id_t id) +{ + return ASC_RESULT_OK; +} + +#ifdef ASC_COMPONENT_CONFIGURATION +static bool _conf_validate_level(conf_t *conf) { + if (conf->value.type != CONF_TYPE_STRING) { + log_error("Invalid configuration for component=[%.*s]: invalid type for key=[%.*s]", + conf->component.length, conf->component.string, conf->key.length, conf->key.string); + return false; + } + + if (string2code(_log_levels, conf->value.value.string.string, conf->value.value.string.length) == -1) { + log_error("Invalid configuration for component=[%.*s]: invalid type for key=[%.*s]", + conf->component.length, conf->component.string, conf->key.length, conf->key.string); + return false; + } + return true; } -void logger_deinit() +static asc_result_t _conf_validate_or_apply(linked_list_t *conf_list, conf_origin_t origin, bool validate_only) { + conf_t *conf; + bool all_pass = true; + + linked_list_foreach(conf_list, conf) + { + char *token = NULL, *rest = NULL; + size_t token_len = 0, rest_len = 0; + component_id_t id; + int code; + log_debug("Validating [%.*s]: key=[%.*s]", + conf->component.length, conf->component.string, conf->key.length, conf->key.string); + + if (!str_ncmp(conf->key.string, conf->key.length, "Level", str_len("Level"))) { + if (!_conf_validate_level(conf)) { + all_pass = false; + continue; + } + + if (validate_only) { + continue; + } + + code = string2code(_log_levels, conf->value.value.string.string, conf->value.value.string.length); + logger_set_system_log_level(code); + continue; + } + + if (origin == CONF_ORIGIN_TWIN) { + all_pass = false; + log_error("Component=[%.*s] key=[%.*s] can't be configured via device twin", + conf->component.length, conf->component.string, conf->key.length, conf->key.string); + continue; + } + + /* Validate key in format: _Level */ + if (str_split(conf->key.string, &token, &token_len, &rest, &rest_len, "_") != ASC_RESULT_OK) { + log_error("Invalid configuration for component=[%.*s]: key=[%.*s]", + conf->component.length, conf->component.string, conf->key.length, conf->key.string); + all_pass = false; + continue; + } + + id = components_manager_get_id_by_name(token, token_len); + if (id == 0) { + log_error("Invalid component=[%.*s]", (uint32_t)token_len, token); + all_pass = false; + continue; + } + + if (str_ncmp("Level", str_len("Level"), rest, rest_len)) { + log_error("Invalid key=[%.*s]", (uint32_t)rest_len, rest); + all_pass = false; + continue; + } + + if (!_conf_validate_level(conf)) { + all_pass = false; + continue; + } + + if (validate_only) { + continue; + } + + if (!all_pass) { + /* Shouldn't happen (it should fail on validation step) */ + log_error("Can't apply new log configuration - validation failed"); + continue; + } + + code = string2code(_log_levels, conf->value.value.string.string, conf->value.value.string.length); + components_manager_set_log_level(id, code); + } + + return all_pass ? ASC_RESULT_OK : ASC_RESULT_BAD_ARGUMENT; +} + +static asc_result_t _conf_validate(linked_list_t *conf_list, conf_origin_t origin) +{ + return _conf_validate_or_apply(conf_list, origin, true); } -void logger_log(const char *level, const char *filename, const char *func, int line, const char *fmt, ...) +static asc_result_t _conf_apply(linked_list_t *conf_list, conf_origin_t origin) { - printf(MDC_FORMAT , level, filename, func, line); + return _conf_validate_or_apply(conf_list, origin, false); +} +#endif + +static asc_result_t _cm_deinit(component_id_t id) +{ + return ASC_RESULT_OK; +} + +static asc_result_t _cm_subscribe(component_id_t id) +{ +#ifdef ASC_COMPONENT_CONFIGURATION + return configuration_component_register(components_manager_get_name(id), _conf_validate, _conf_apply); +#else + return ASC_RESULT_OK; +#endif +} + +static asc_result_t _cm_unsubscribe(component_id_t id) +{ +#ifdef ASC_COMPONENT_CONFIGURATION + return configuration_component_unregister(components_manager_get_name(id)); +#else + return ASC_RESULT_OK; +#endif +} + +static component_ops_t _ops = { + .init = _cm_init, + .deinit = _cm_deinit, + .subscribe = _cm_subscribe, + .unsubscribe = _cm_unsubscribe, +}; + +COMPONENTS_FACTORY_DEFINITION(Logger, &_ops) + +bool logger_set_system_log_level(int set) +{ + unsigned int level = (set < 0) ? ASC_LOG_LEVEL : (unsigned int)set; + + if (level > ASC_LOG_LEVEL) { + log_error("Requested log level=[%u] is above than compiled=[%u]", level, ASC_LOG_LEVEL); + return false; + } + _system_level = level; + return true; +} + +int logger_get_system_log_level(void) +{ + return (int)_system_level; +} + +void logger_set_timestamp(bool set) +{ + _timestamp = set; +} + +bool logger_log(component_id_t id, unsigned int level, const char *filename, const char *func, int line, const char *fmt, ...) +{ +#define MDC_FORMAT "%s [%s/%s:%d] " +#define MDC_TS_FORMAT "%s %lu - [%s/%s:%d] " +#ifdef ASC_TIME_H_SUPPORT + #define MDC_TS_TIME_H_FORMAT "%s %02d:%02d:%02d [%s/%s:%d] " +#endif + const char *level_str = NULL; + + if (_system_level < level +#ifdef ASC_COMPONENT_CONFIGURATION + || components_manager_get_log_level(id) < level +#endif + ) + { + return false; + } + + level_str = code2string(_log_levels, (int)level); + if (level_str == NULL) { + level_str = "UNDEF"; + } + + if (_timestamp) { + unsigned long rawtime = itime_time(NULL); +#ifdef ASC_TIME_H_SUPPORT + struct tm *ptm = localtime((time_t *)&rawtime); + if (ptm == NULL) { + printf(MDC_TS_FORMAT, level_str, rawtime, filename, func, line); + } else { + printf(MDC_TS_TIME_H_FORMAT, level_str, ptm->tm_hour, ptm->tm_min, ptm->tm_sec, filename, func, line); + } +#else + printf(MDC_TS_FORMAT, level_str, rawtime, filename, func, line); +#endif + } else { + printf(MDC_FORMAT, level_str, filename, func, line); + } va_list args; va_start(args, fmt); @@ -35,5 +262,8 @@ void logger_log(const char *level, const char *filename, const char *func, int l va_end(args); printf("\n"); + return true; } +#else +COMPONENTS_FACTORY_DEFINITION(Logger, NULL) #endif diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/collector.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/collector.c index 328b1628..29cc2646 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/collector.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/collector.c @@ -1,86 +1,132 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include +#include + +#include "asc_security_core/utils/itime.h" #include "asc_security_core/logger.h" +#include "asc_security_core/components_manager.h" +#include "asc_security_core/core.h" +#include "asc_security_core/utils/notifier.h" + #include "asc_security_core/collector.h" OBJECT_POOL_DEFINITIONS(collector_t, COLLECTOR_OBJECT_POOL_COUNT) -LINKED_LIST_DEFINITIONS(collector_t) -collector_t *collector_init(collector_init_function_t collector_internal_init_function) +static collector_t *collector_alloc(component_id_t id) { - asc_result_t result = ASC_RESULT_OK; - collector_t *collector_ptr = NULL; + collector_t *collector_ptr = object_pool_get(collector_t); - if (collector_internal_init_function == NULL) { - log_error("Failed to initialize collector due to bad argument"); - result = ASC_RESULT_BAD_ARGUMENT; + __components_manager_set_ctx(id, collector_ptr); + if (collector_ptr == NULL) { + log_error("Failed to allocate collector=[%s]", components_manager_get_name(id)); goto cleanup; } + memset(collector_ptr, 0, sizeof(collector_t)); + +cleanup: + return collector_ptr; +} + +static asc_result_t collector_init_with_params(collector_internal_t *collector_internal_ptr, collector_enum_t type, collector_priority_t priority, collector_serialize_function_t collect_function, unsigned long interval, void *state) +{ + if (collector_internal_ptr == NULL) { + return ASC_RESULT_BAD_ARGUMENT; + } + + memset(collector_internal_ptr, 0, sizeof(*collector_internal_ptr)); + + collector_internal_ptr->type = type; + collector_internal_ptr->priority = priority; + collector_internal_ptr->interval = interval; + collector_internal_ptr->collect_function = collect_function; + collector_internal_ptr->state = state; + + return ASC_RESULT_OK; +} + +asc_result_t collector_default_create(component_id_t id, collector_enum_t type, collector_priority_t priority, collector_serialize_function_t collect_function, unsigned long interval, void *state) +{ + asc_result_t result = ASC_RESULT_OK; + collector_t *collector_ptr = collector_alloc(id); - collector_ptr = object_pool_get(collector_t); if (collector_ptr == NULL) { - log_error("Failed to allocate collector"); + log_error("Failed to init collector type=[%d] name=[%s]", type, components_manager_get_name(id)); result = ASC_RESULT_MEMORY_EXCEPTION; goto cleanup; } - - memset(collector_ptr, 0, sizeof(collector_t)); - - result = collector_internal_init_function(&collector_ptr->internal); + result = collector_init_with_params(&collector_ptr->internal, type, priority, collect_function, interval, state); if (result != ASC_RESULT_OK) { - log_error("Failed to initialize collector internal, result=[%d]", result); + log_error("Failed to init internal collector parameters type=[%d] name=[%s]", type, components_manager_get_name(id)); goto cleanup; } +#ifdef ASC_COLLECTORS_INFO_SUPPORT + notifier_notify(NOTIFY_TOPIC_SYSTEM, NOTIFY_SYSTEM_CONFIGURATION, &collector_ptr->internal); +#endif - log_debug("Initialize collector, type=[%d], priority=[%d]", collector_ptr->internal.type, collector_ptr->internal.priority); +cleanup: + return result; +} - // default parameters - collector_ptr->enabled = true; - collector_ptr->status = COLLECTOR_STATUS_OK; - collector_ptr->failure_count = 0; - collector_ptr->last_collected_timestamp = 0; - collector_ptr->last_sent_timestamp = 0; +asc_result_t collector_default_deinit(component_id_t id) +{ + collector_t *collector_ptr = __components_manager_get_ctx(id); -cleanup: - if (result != ASC_RESULT_OK) { - log_error("Failed to initialize collector, result=[%d]", result); - collector_deinit(collector_ptr); - collector_ptr = NULL; + if (collector_ptr == NULL) { + log_error("collector uninitialized name=[%s]", components_manager_get_name(id)); + return ASC_RESULT_MEMORY_EXCEPTION; } - - return collector_ptr; + memset(collector_ptr, 0, sizeof(collector_t)); + object_pool_free(collector_t, collector_ptr); + __components_manager_set_ctx(id, NULL); + return ASC_RESULT_OK; } -void collector_deinit(collector_t *collector_ptr) +asc_result_t collector_default_subscribe(component_id_t id) { + collector_t *collector_ptr = __components_manager_get_ctx(id); + if (collector_ptr == NULL) { - return; + log_error("collector uninitialized name=[%s]", components_manager_get_name(id)); + return ASC_RESULT_MEMORY_EXCEPTION; } - log_debug("Deinitialize collector, type=[%d], priority=[%d]", collector_ptr->internal.type, collector_ptr->internal.priority); + return core_collector_register(collector_ptr); +} - if (collector_ptr->internal.deinit_function != NULL) { - collector_ptr->internal.deinit_function(&collector_ptr->internal); +asc_result_t collector_default_unsubscribe(component_id_t id) +{ + collector_t *collector_ptr = __components_manager_get_ctx(id); + + if (collector_ptr == NULL) { + log_error("collector uninitialized name=[%s]", components_manager_get_name(id)); + return ASC_RESULT_MEMORY_EXCEPTION; } + return core_collector_unregister(collector_ptr); +} - object_pool_free(collector_t, collector_ptr); - collector_ptr = NULL; +asc_result_t collector_default_start(component_id_t id) +{ + return ASC_RESULT_OK; +} + +asc_result_t collector_default_stop(component_id_t id) +{ + return ASC_RESULT_OK; } collector_priority_t collector_get_priority(collector_t *collector_ptr) { - collector_priority_t priority = COLLECTOR_PRIORITY_HIGH; + collector_priority_t priority = COLLECTOR_PRIORITY_COUNT; if (collector_ptr == NULL) { log_error("Failed to retrieve collector priority, bad argument"); @@ -91,9 +137,9 @@ collector_priority_t collector_get_priority(collector_t *collector_ptr) return priority; } -uint32_t collector_get_last_collected_timestamp(collector_t *collector_ptr) +unsigned long collector_get_last_collected_timestamp(collector_t *collector_ptr) { - uint32_t last_collected_timestamp = 0; + unsigned long last_collected_timestamp = 0; if (collector_ptr == NULL) { log_error("Failed to retrieve collector last collected timestamp, bad argument"); @@ -104,7 +150,7 @@ uint32_t collector_get_last_collected_timestamp(collector_t *collector_ptr) return last_collected_timestamp; } -asc_result_t collector_set_last_collected_timestamp(collector_t *collector_ptr, uint32_t last_collected_timestamp) +asc_result_t collector_set_last_collected_timestamp(collector_t *collector_ptr, unsigned long last_collected_timestamp) { if (collector_ptr == NULL) { log_error("Failed to set collector last collected timestamp, bad argument"); @@ -122,8 +168,13 @@ asc_result_t collector_serialize_events(collector_t *collector_ptr, serializer_t log_error("Collector failed to serialize events, bad argument"); return ASC_RESULT_BAD_ARGUMENT; } + unsigned long now = itime_time(NULL); + if (now == ITIME_FAILED) { + log_error("Error get current time"); + now = 0; + } - collector_ptr->last_collected_timestamp = itime_time(NULL); + collector_ptr->last_collected_timestamp = now; if (collector_ptr->internal.collect_function == NULL) { log_error("Collector failed to serialize events, internal collect function is NULL"); diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/security_message.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/security_message.c index a1c086f6..880bf5d4 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/security_message.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/model/security_message.c @@ -1,7 +1,19 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include +#include + #include "asc_security_core/model/security_message.h" diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/object_pool_static.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/object_pool_static.c new file mode 100644 index 00000000..6f886aac --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/object_pool_static.c @@ -0,0 +1,71 @@ + +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include +#include + +#include + +#include "asc_security_core/logger.h" +#include "asc_security_core/object_pool_static.h" + +static bool _object_pool_init(object_pool_t *pool, uintptr_t offset1, uintptr_t offset2, uintptr_t objs) +{ + if (!pool || pool->size == 0) { + log_fatal("Wrong definition pool=[%p] size=[%zu]", (void *)pool, pool ? pool->size : 0); + return false; + } + if (!pool->initialized) { + if (offset1 != offset2) { + log_fatal("Wrong offset of pool typedef, COLLECTION_INTERFACE(...) is not on top."); + return false; + } + for (size_t i=0; isize; i++) { + uintptr_t obj = objs + (i * pool->item_size); + stack_push(&pool->stack, (collection_item_t *)obj); + } + pool->initialized = true; + } + return true; +} + +void *__object_pool_get(object_pool_t *pool, uintptr_t offset1, uintptr_t offset2, uintptr_t objs) +{ + if (!_object_pool_init(pool, offset1, offset2, objs)) { + return NULL; + } + if (pool->current_size >= pool->size) { + if (++pool->failures % pool->size == 0) { + log_debug("Pool exceeded objects [%zu/%zu] failures=[%zu]", pool->current_size, pool->size, pool->failures); + } + return NULL; + } + pool->current_size++; + return (void *)stack_pop(&pool->stack); +} + +void __object_pool_free(object_pool_t *pool, void *obj) +{ + if (!pool || !obj || !pool->initialized) { + return; + } + if (pool->current_size == 0) { + log_fatal("Invalid memory free"); + } else { + pool->current_size--; + stack_push(&pool->stack, (collection_item_t *)obj); + } +} + +size_t __object_pool_get_available_size(object_pool_t *pool) +{ + return (pool->size - pool->current_size); +} \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.c index 239629cc..a5f8c83f 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/custom_builder_allocator.c @@ -1,19 +1,20 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include +#include + #include "asc_security_core/logger.h" -#include "custom_builder_allocator.h" +#include "asc_security_core/serializer/custom_builder_allocator.h" #define VS_SIZE 64 #define DS_SIZE 512 @@ -67,7 +68,7 @@ int serializer_custom_allocator(void *alloc_context, flatcc_iovec_t *b, size_t r return 0; } -void serializer_custom_allocator_reset() +void serializer_custom_allocator_reset(void) { for (int i = 0; i < FLATCC_BUILDER_ALLOC_BUFFER_COUNT; ++i) { if (buffers[i].iov_base != NULL) { diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.c index 71bc2f3f..08676034 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.c @@ -1,17 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "page_allocator.h" - -#include "asc_security_core/configuration.h" +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include + +#include "asc_security_core/serializer/page_allocator.h" + #include "asc_security_core/logger.h" #include "asc_security_core/object_pool.h" #include "asc_security_core/utils/collection/collection.h" @@ -21,12 +21,13 @@ typedef struct emitter_page emitter_page_t; struct emitter_page { + /* This macro must be first in object */ COLLECTION_INTERFACE(emitter_page_t); flatcc_emitter_page_t page; }; OBJECT_POOL_DECLARATIONS(emitter_page_t) -OBJECT_POOL_DEFINITIONS(emitter_page_t, EMITTER_PAGE_CACHE_SIZE) +OBJECT_POOL_DEFINITIONS(emitter_page_t, ASC_EMITTER_PAGE_CACHE_SIZE) void *serializer_page_alloc(size_t size) { @@ -35,7 +36,7 @@ void *serializer_page_alloc(size_t size) return NULL; } - emitter_page_t *page = object_pool_emitter_page_t_get(); + emitter_page_t *page = object_pool_get(emitter_page_t); if (page != NULL) { static flatcc_emitter_page_t *temp; temp = &(page->page); @@ -55,5 +56,5 @@ void serializer_page_free(void *page) } emitter_page_t *page_ptr = containerof(page, emitter_page_t, page); - object_pool_emitter_page_t_free(page_ptr); + object_pool_free(emitter_page_t, page_ptr); } diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.h deleted file mode 100644 index 63bdc189..00000000 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/extensions/page_allocator.h +++ /dev/null @@ -1,30 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef PAGE_ALLOCATOR_H -#define PAGE_ALLOCATOR_H - -#include - -#include "asc_security_core/configuration.h" - -#define MAX_MESSAGE_SIZE (500 + \ - ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV4_OBJECTS_IN_CACHE * 36 + \ - ASC_COLLECTOR_NETWORK_ACTIVITY_MAX_IPV6_OBJECTS_IN_CACHE * 60) - -#define MIN_PAGE_SIZE (MAX_MESSAGE_SIZE * 2) -#define PAGE_MULTIPLE 64 -#define FLATCC_EMITTER_PAGE_SIZE ((MIN_PAGE_SIZE + (PAGE_MULTIPLE) - 1) & ~(2 * (PAGE_MULTIPLE) - 1)) - -void *serializer_page_alloc(size_t size); -void serializer_page_free(void *page); - -#endif /* PAGE_ALLOCATOR_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/heartbeat.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/heartbeat.c index 0c7070b1..c11c99d9 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/heartbeat.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/heartbeat.c @@ -1,13 +1,14 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include #include "asc_security_core/logger.h" #include "asc_security_core/model/schema/message_builder.h" @@ -15,9 +16,9 @@ #include "asc_security_core/serializer.h" #include "serializer_private.h" -asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval) +asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval) { - log_debug("serializer_event_add_heartbeat, serializer=[%p], timestamp=[%u], collection_interval=[%u]", + log_debug("serializer_event_add_heartbeat, serializer=[%p], timestamp=[%lu], collection_interval=[%lu]", (void*)serializer, timestamp, collection_interval); if (serializer == NULL) { @@ -40,7 +41,7 @@ asc_result_t serializer_event_add_heartbeat(serializer_t *serializer, uint32_t t return ASC_RESULT_EXCEPTION; } - if (AzureIoTSecurity_Message_events_push_end(&serializer->builder) == NULL) { + if (AzureIoTSecurity_Event_vec_push_end(&serializer->builder) == NULL) { log_error("failed in AzureIoTSecurity_Event_vec_push_end"); serializer->state = SERIALIZER_STATE_EXCEPTION; return ASC_RESULT_EXCEPTION; diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/network_activity.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/network_activity.c index f249585c..33252780 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/network_activity.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/network_activity.c @@ -1,15 +1,15 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "asc_security_core/configuration.h" +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include + #include "asc_security_core/logger.h" #include "asc_security_core/model/schema/event_builder.h" #include "asc_security_core/serializer.h" @@ -24,10 +24,10 @@ static asc_result_t _serializer_network_activity_add_ipv4_activity(serializer_t static asc_result_t _serializer_network_activity_add_ipv6_activity(serializer_t *serializer, network_activity_ipv6_t *ipv6_payload); static asc_result_t _serializer_network_activity_add_common(serializer_t *serializer, network_activity_common_t *common); -asc_result_t serializer_event_add_network_activity(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, +asc_result_t serializer_event_add_network_activity(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, network_activity_ipv4_t *ipv4_payload, network_activity_ipv6_t *ipv6_payload) { - log_debug("serializer_event_add_network_activity, serializer=[%p], timestamp=[%u], collection_interval=[%u], ipv4_payload=[%p], ipv6_payload=[%p]", + log_debug("serializer_event_add_network_activity, serializer=[%p], timestamp=[%lu], collection_interval=[%lu], ipv4_payload=[%p], ipv6_payload=[%p]", (void*)serializer, timestamp, collection_interval, (void*)ipv4_payload, (void*)ipv6_payload); #ifndef ASC_COLLECTOR_NETWORK_ACTIVITY_SEND_EMPTY_EVENTS diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/protocol_serialize_enum.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/protocol_serialize_enum.h index 069491e0..bedf4486 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/protocol_serialize_enum.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/protocol_serialize_enum.h @@ -1,16 +1,17 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef PROTOCOL_PRIVATE_H #define PROTOCOL_PRIVATE_H +#include #include "asc_security_core/model/objects/transport_protocol.h" #include "asc_security_core/model/schema/protocol_builder.h" diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer.c index bfca583a..9b664d2d 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer.c @@ -1,19 +1,19 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "asc_security_core/configuration.h" +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include + #include "asc_security_core/logger.h" #include "asc_security_core/model/schema/message_builder.h" #include "asc_security_core/object_pool.h" -#include "asc_security_core/utils/iuuid.h" +#include "asc_security_core/utils/uuid.h" #include "asc_security_core/serializer.h" #include "serializer_private.h" @@ -22,13 +22,13 @@ OBJECT_POOL_DECLARATIONS(serializer_t) OBJECT_POOL_DEFINITIONS(serializer_t, 1) #ifdef ASC_SERIALIZER_USE_CUSTOM_ALLOCATOR -#include "extensions/custom_builder_allocator.h" +#include "asc_security_core/serializer/custom_builder_allocator.h" #define ASC_SERIALIZER_CUSTOM_ALLOCATOR serializer_custom_allocator #else #define ASC_SERIALIZER_CUSTOM_ALLOCATOR NULL #endif -serializer_t *serializer_init() +serializer_t *serializer_init(void) { log_debug("serializer_init"); diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.c index fa80eb96..3d5ee06a 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.c @@ -1,23 +1,24 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include +#include + #include "asc_security_core/logger.h" #include "asc_security_core/model/schema/message_builder.h" -#include "asc_security_core/utils/iuuid.h" +#include "asc_security_core/utils/uuid.h" #include "serializer_private.h" -asc_result_t serializer_event_start(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval) +asc_result_t serializer_event_start(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval) { if (serializer->state == SERIALIZER_STATE_MESSAGE_EMPTY && flatbuffers_failed(AzureIoTSecurity_Message_events_start(&serializer->builder))) { log_error("failed in AzureIoTSecurity_Message_events_start"); @@ -32,8 +33,8 @@ asc_result_t serializer_event_start(serializer_t *serializer, uint32_t timestamp } uint8_t uuid[16] = { 0 }; - if (iuuid_generate(uuid) < 0) { - log_error("failed in iuuid_generate"); + if (uuid_generate(uuid) < 0) { + log_error("failed in uuid_generate"); serializer->state = SERIALIZER_STATE_EXCEPTION; return ASC_RESULT_EXCEPTION; } @@ -45,13 +46,13 @@ asc_result_t serializer_event_start(serializer_t *serializer, uint32_t timestamp } - if (flatbuffers_failed(AzureIoTSecurity_Event_time_add(&serializer->builder, timestamp))) { + if (flatbuffers_failed(AzureIoTSecurity_Event_time_add(&serializer->builder, (uint32_t)timestamp))) { log_error("failed in AzureIoTSecurity_Event_time_add"); serializer->state = SERIALIZER_STATE_EXCEPTION; return ASC_RESULT_EXCEPTION; } - if (flatbuffers_failed(AzureIoTSecurity_Event_collection_interval_add(&serializer->builder, collection_interval))) { + if (flatbuffers_failed(AzureIoTSecurity_Event_collection_interval_add(&serializer->builder, (uint32_t)collection_interval))) { log_error("failed in AzureIoTSecurity_Event_collection_interval_add"); serializer->state = SERIALIZER_STATE_EXCEPTION; return ASC_RESULT_EXCEPTION; diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.h b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.h index ed734aa6..2915c008 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.h +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/serializer_private.h @@ -1,13 +1,13 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #ifndef SERIALIZER_PRIVATE_H #define SERIALIZER_PRIVATE_H @@ -15,12 +15,15 @@ #include #include +#include + #include "flatcc/flatcc_builder.h" #include "asc_security_core/utils/collection/collection.h" #include "asc_security_core/serializer.h" struct serializer { + /* This macro must be first in object */ COLLECTION_INTERFACE(serializer_t); flatcc_builder_t builder; @@ -40,6 +43,6 @@ struct serializer { * @return ASC_RESULT_OK on success, * ASC_RESULT_EXCEPTION otherwise */ -asc_result_t serializer_event_start(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval); +asc_result_t serializer_event_start(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval); #endif /* SERIALIZER_PRIVATE_H */ diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/system_information.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/system_information.c index 40d2c750..5fa324ab 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/system_information.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/serializer/system_information.c @@ -1,13 +1,14 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include #include "asc_security_core/logger.h" #include "asc_security_core/model/schema/event_builder.h" @@ -15,10 +16,10 @@ #include "asc_security_core/serializer.h" #include "serializer_private.h" -asc_result_t serializer_event_add_system_information(serializer_t *serializer, uint32_t timestamp, uint32_t collection_interval, +asc_result_t serializer_event_add_system_information(serializer_t *serializer, unsigned long timestamp, unsigned long collection_interval, system_information_t *payload) { - log_debug("serializer_event_add_system_information, serializer=[%p], timestamp=[%u], collection_interval=[%u], payload=[%p]", + log_debug("serializer_event_add_system_information, serializer=[%p], timestamp=[%lu], collection_interval=[%lu], payload=[%p]", (void*)serializer, timestamp, collection_interval, (void*)payload); if (serializer == NULL) { diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/bit_vector.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/bit_vector.c new file mode 100644 index 00000000..ed9cbdcb --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/bit_vector.c @@ -0,0 +1,54 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include +#include + +#include + +#include "asc_security_core/utils/collection/bit_vector.h" + +bool __bit_vector_set(char bit_vector[], int index, bool bit, int size) +{ + if (index >= 0 && index < size) { + if (bit) { + bit_vector[__BV_VEC_IND(index)] |= (char)(0x01 << __BV_VEC_SHIFT(index)); + } else { + bit_vector[__BV_VEC_IND(index)] &= (char)~(0x01 << __BV_VEC_SHIFT(index)); + } + return true; + } + return false; +} + +bool __bit_vector_get(char bit_vector[], int index, int size) +{ + if (index >= 0 && index < size) { + return (!!(bit_vector[__BV_VEC_IND(index)] & (0x01 << __BV_VEC_SHIFT(index)))); + } + return false; +} + +bool __is_bit_vector_zero(char bit_vector[], int size) +{ + int vector_size_in_bytes = size>>3; + + for(int i = 0; i < vector_size_in_bytes; i++) { + if (bit_vector[i] != 0x00) { + return false; + } + } + return true; +} + +void __bit_vector_clean(char bit_vector[], int size) +{ + memset(bit_vector, 0, (size_t)size>>3); +} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/hashtable.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/hashtable.c new file mode 100644 index 00000000..2bf330b8 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/hashtable.c @@ -0,0 +1,229 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include + +#include + +#include +#include +#include + +static unsigned int _hash_calc(hashtable_t *hashtable, const void *key); +static void *_hashtable_find(hashtable_t *hashtable, const void *key, unsigned int *index); + +// API functions +bool hashtable_init(hashtable_t *hashtable, size_t size, hash_func_t hash_func, + hash_equal_func_t hash_equal_func, hash_update_func_t hash_update_func) +{ + if (!hashtable || !size) { + log_error("Wrong hashtable init parametrs"); + return false; + } + hashtable->ctrl.size = size; + hashtable->ctrl.hash_func = hash_func; + hashtable->ctrl.hash_equal_func = hash_equal_func ? hash_equal_func : hashtable_equal_default_func; + hashtable->ctrl.hash_update_func = hash_update_func ? hash_update_func : hashtable_update_none_func; + memset(hashtable->table, 0, size * sizeof(void *)); + hashtable->ctrl.initialized = true; + return true; +} + +void *hashtable_insert(hashtable_t *hashtable, const void *key, void *item) +{ + if (!hashtable || !hashtable->ctrl.initialized || !key || !item) { + log_error("Wrong parametrs"); + return NULL; + } + collection_item_t *element = item; + unsigned int index = 0; + collection_item_t *existing_element = _hashtable_find(hashtable, key, &index); + + if (existing_element == NULL) { + collection_item_t *column = hashtable->table[index]; + element->previous = NULL; + element->next = column; + if (column != NULL) { + column->previous = element; + } + hashtable->table[index] = element; + } else { + hashtable->ctrl.hash_update_func(existing_element, element); + } + return item; +} + +void *hashtable_remove(hashtable_t *hashtable, const void *key, hash_free_func_t hash_free_func) +{ + if (!hashtable || !hashtable->ctrl.initialized || !key) { + log_error("Wrong parametrs"); + return NULL; + } + unsigned int index = 0; + collection_item_t *existing_element = _hashtable_find(hashtable, key, &index); + + if (existing_element == NULL) { + return NULL; + } + collection_item_t *previous_element = existing_element->previous; + collection_item_t *next_element = existing_element->next; + + if (next_element != NULL) { + next_element->previous = previous_element; + } + if (previous_element == NULL) { + hashtable->table[index] = next_element; + } else { + previous_element->next = next_element; + } + if (hash_free_func) { + hash_free_func(existing_element); + return NULL; + } + return existing_element; +} + +void *hashtable_find(hashtable_t *hashtable, const void *key) +{ + if (!hashtable || !hashtable->ctrl.initialized || !key) { + log_error("Wrong parametrs"); + return NULL; + } + unsigned int index; + return _hashtable_find(hashtable, key, &index); +} + +size_t hashtable_get_depth(hashtable_t *hashtable, size_t *count) +{ + size_t max = 0; + if (count) { + *count = 0; + } + if (!hashtable || !hashtable->ctrl.initialized) { + return 0; + } + for (size_t i = 0; i < hashtable->ctrl.size; i++) { + collection_item_t *current_element = NULL; + size_t cnt = 0; + hashtable_column_foreach(hashtable, current_element, i) { + cnt++; + } + if (cnt > 1) { + if (cnt > max) { + max = cnt; + } + if (count) { + (*count)++; + } + } + } + return max; +} + +void hashtable_foreach(hashtable_t *hashtable, hash_action_func_t hash_action_func, void *ctx) +{ + if (!hashtable || !hashtable->ctrl.initialized || !hash_action_func) { + return; + } + for (unsigned int i = 0; i < hashtable->ctrl.size; i++) { + // not using hashtable_column_foreach() because of 'tmp = current_element->next for safe action' + collection_item_t *current_element = hashtable->table[i]; // get column head + while (current_element != NULL) { + collection_item_t *tmp = current_element->next; + hash_action_func(current_element, ctx); + current_element = tmp; + } + } +} + +void hashtable_flush(hashtable_t *hashtable, hash_free_func_t hash_free_func) +{ + if (!hashtable || !hashtable->ctrl.initialized) { + return; + } + if (!hash_free_func) { + goto cleanup; + } + for (size_t i = 0; i < hashtable->ctrl.size; i++) { + // not using hashtable_column_foreach() because of 'tmp = current_element->next for safe free' + collection_item_t *current_element = hashtable->table[i]; // get column head + while (current_element != NULL) { + collection_item_t *tmp = current_element->next; + hash_free_func(current_element); + current_element = tmp; + } + } +cleanup: + memset(hashtable->table, 0, hashtable->ctrl.size * sizeof(void *)); +} + +bool hashtable_is_empty(hashtable_t *hashtable) +{ + if (!hashtable || !hashtable->ctrl.initialized) { + return true; + } + for (size_t i = 0; i < hashtable->ctrl.size; i++) { + collection_item_t *column = hashtable->table[i]; + if (column) { + return false; + } + } + return true; +} + +// Service callbacks and functions +void hashtable_update_none_func(void *a, void *b) +{ + log_error("Should never happens"); +} + +bool hashtable_equal_default_func(const void *key, void *item) +{ + return (key == item); +} + +unsigned int hashtable_hash_str_default(const void *key) +{ + const char *buffer = key; + return hashtable_buffer2hash(buffer, str_len(buffer)); +} + +unsigned int hashtable_buffer2hash(const char *buffer, size_t len) +{ + unsigned int hash = 5381; + + for (size_t i = 0 ; i < len; i++) { + hash = ((hash << 5) + hash) + (unsigned int)buffer[i]; + } + + return hash; +} + +// Internal functions +static unsigned int _hash_calc(hashtable_t *hashtable, const void *key) +{ + return hashtable->ctrl.hash_func ? (unsigned int)(hashtable->ctrl.hash_func(key) % hashtable->ctrl.size) : + (unsigned int)((uintptr_t)key % hashtable->ctrl.size); +} + +static void *_hashtable_find(hashtable_t *hashtable, const void *key, unsigned int *index) +{ + *index = _hash_calc(hashtable, key); + collection_item_t *current_element = NULL; + + hashtable_column_foreach(hashtable, current_element, *index) { + if (hashtable->ctrl.hash_equal_func(key, current_element) != 0) { + break; + } + } + + return current_element; +} + diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/list.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/list.c new file mode 100644 index 00000000..0db4711c --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/list.c @@ -0,0 +1,183 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ + +#include + +#include "asc_security_core/utils/collection/list.h" + +void linked_list_init(linked_list_t *list) +{ + if (list == NULL) { + return; + } + list->head = NULL; + list->tail = NULL; + list->size = 0; + list->initialized = true; +} + +void *linked_list_get_first(linked_list_t *list) +{ + if (list == NULL) { + return NULL; + } + return list->head; +} + +void *linked_list_find(linked_list_t *list, linked_list_condition_cb condition_function, void *condition_input) +{ + if (list == NULL || (condition_function) == NULL) { + return NULL; + } + collection_item_t *curr = NULL; + linked_list_foreach(list, curr) { + if (condition_function(curr, condition_input) == true) { + break; + } + } + return curr; +} + +void *linked_list_add_or_update(linked_list_t *list, linked_list_condition_cb condition_function, + linked_list_update_cb update_func, void *data) +{ + if (list == NULL || (condition_function) == NULL || update_func == NULL) { + return NULL; + } + collection_item_t *curr = NULL; + linked_list_foreach(list, curr) { + if (condition_function(curr, data) == true) { + update_func(curr, data); + return curr; + } + } + return linked_list_add_last(list, data); +} + +void *linked_list_add_last(linked_list_t *list, void *data) +{ + collection_item_t *item = data; + if (list == NULL || item == NULL) { + return NULL; + } + item->next = NULL; + if (list->head == NULL) { + item->previous = NULL; + list->head = item; + list->tail = item; + } else { + item->previous = list->tail; + list->tail->next = item; + list->tail = item; + } + + list->size += 1; + return data; +} + +void *linked_list_add_first(linked_list_t *list, void *data) +{ + collection_item_t *item = data; + if (list == NULL || item == NULL) { + return NULL; + } + item->previous = NULL; + item->next = NULL; + if (list->head == NULL) { + list->head = item; + list->tail = item; + } else { + list->head->previous = item; + item->next = list->head; + list->head = item; + } + list->size += 1; + return item; +} + +void *linked_list_insert_before(linked_list_t *list, void *before, void *data) +{ + collection_item_t *item = data; + if (list == NULL || item == NULL) { + return NULL; + } + if (before == NULL) { + return linked_list_add_last(list, item); + } + collection_item_t *before_item = linked_list_find(list, linked_list_condition_default, before); + if (before_item == NULL) { + return linked_list_add_last(list, item); + } + collection_item_t *previous_item = before_item->previous; + if (previous_item == NULL) { + return linked_list_add_first(list, item); + } + item->next = before_item; + item->previous = previous_item; + previous_item->next = item; + before_item->previous = item; + list->size += 1; + return item; +} + +void *linked_list_remove(linked_list_t *list, void *data, linked_list_free_cb free_function) +{ + collection_item_t *item = data; + if (list == NULL || item == NULL) { + return NULL; + } + if (linked_list_find(list, linked_list_condition_default, item) == NULL) { + return NULL; + } + collection_item_t *previous_item = item->previous; + collection_item_t *next_item = item->next; + if (next_item != NULL) { + next_item->previous = previous_item; + } + if (previous_item == NULL) { + list->head = next_item; + } else { + previous_item->next = next_item; + } + if (item == list->tail) { + list->tail = previous_item; + } + list->size -= 1; + if (free_function != NULL) { + free_function(item); + return NULL; + } + return item; +} + +void linked_list_flush(linked_list_t *list, linked_list_free_cb free_function) +{ + if (list == NULL) { + return; + } + while (list->head != NULL) { + linked_list_remove(list, list->head, free_function); + } + linked_list_init(list); +} + +size_t linked_list_get_size(linked_list_t *list) +{ + if (list == NULL) { + return 0; + } + return list->size; +} + +bool linked_list_condition_default(void *item, void *condition_input) +{ + return (item==condition_input); +} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/stack.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/stack.c new file mode 100644 index 00000000..d7b94015 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/collection/stack.c @@ -0,0 +1,62 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include +#include + +#include + +#include "asc_security_core/utils/collection/stack.h" + +collection_item_t *stack_pop(stack_collection_t *stack) +{ + if (!stack) { + return NULL; + } + collection_item_t *current_head = stack->head; + if (current_head == NULL) { + return NULL; + } + collection_item_t *new_head = current_head->next; + current_head->previous = current_head->next = NULL; + if (new_head != NULL) { + new_head->previous = NULL; + } + stack->head = new_head; + return current_head; +} + +void stack_push(stack_collection_t *stack, collection_item_t *item) +{ + if (!stack || !item) { + return; + } + collection_item_t *current_head = stack->head; + if (current_head == NULL) { + stack->head = item; + item->next = NULL; + item->previous = NULL; + stack->size++; + } else { + item->next = current_head; + item->previous = NULL; + current_head->previous = item; + stack->head = item; + stack->size++; + } +} + +collection_item_t * stack_peek(stack_collection_t *stack) +{ + if (!stack) { + return NULL; + } + return stack->head; +} diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/event_loop_be.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/event_loop_be.c index 06f7c34e..f93f6717 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/event_loop_be.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/event_loop_be.c @@ -1,95 +1,121 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include -#include + +#include #include "asc_security_core/logger.h" #include "asc_security_core/object_pool.h" -#include "asc_security_core/utils/collection/linked_list.h" +#include "asc_security_core/utils/collection/list.h" #include "asc_security_core/utils/itime.h" #include "asc_security_core/utils/event_loop_be.h" /** @brief An opaque structure representing a timer. */ typedef struct event_timer event_timer_t; -/** @brief A callback function called when the timer expires. */ -typedef void (*event_timer_cb_t)(event_timer_t *t, void *ctx); + +/** @brief Flag to know if we are in timer callback to avoid inserting to another timer callbacks that where created +* in current loop. +*/ +static bool _in_timer_cb; struct event_timer { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct event_timer); - uint64_t delay; - uint64_t repeat; - event_timer_cb_t cb; + unsigned long delay; + unsigned long repeat; + event_loop_timer_cb_t cb; event_timer_t **self; void *ctx; + bool added_in_cb; }; OBJECT_POOL_DECLARATIONS(event_timer_t) OBJECT_POOL_DEFINITIONS(event_timer_t, OBJECT_POOL_BE_EVENT_LOOP_TIMERS_COUNT) -LINKED_LIST_DECLARATIONS(event_timer_t) -LINKED_LIST_DEFINITIONS(event_timer_t) -static linked_list_event_timer_t _event_timer_linked_list; -static linked_list_event_timer_t_handle _event_timer_linked_list_handler = &_event_timer_linked_list; -static int _event_loop_initialized; -static int _event_loop_is_stop; +static linked_list_t _event_timer_linked_list; +static bool _event_loop_initialized; +static bool _event_loop_is_running; + +static bool _run_until(int max_count); +static void _timer_del(event_timer_t *t); // #define DEBUG_BE 1 -#if (DEBUG_BE) && (LOG_LEVEL == LOG_LEVEL_DEBUG) -static void _timers_list_debug_print() +#if (DEBUG_BE) && (ASC_LOG_LEVEL == LOG_LEVEL_DEBUG) +static void _timers_list_debug_print(void) { - event_timer_t *iter = NULL; - - log_error("Timers total number %u", linked_list_event_timer_t_get_size(_event_timer_linked_list_handler)); - - linked_list_iterator_event_timer_t event_timer_iter = {0}; - linked_list_iterator_event_timer_t_init(&event_timer_iter, _event_timer_linked_list_handler); + event_timer_t *curr = NULL; - while ((iter = linked_list_iterator_event_timer_t_next(&event_timer_iter)) != NULL) { - log_debug("timer=[%p] with delay=[%lu]", (void *)iter, iter->delay); - + log_error("Timers total number %zu", linked_list_get_size(&_event_timer_linked_list)); + linked_list_foreach(&_event_timer_linked_list, curr) { + log_debug("timer=[%p] with delay=[%lu]", (void *)curr, curr->delay); } } #else #define _timers_list_debug_print() #endif -static int _init(void) +static bool _be_init(void) { _event_loop_initialized = true; - _event_loop_is_stop = false; + _event_loop_is_running = true; /* Default deinit function is not set, because in case of periodic timer we will want to remove timer without free. */ - linked_list_event_timer_t_init(_event_timer_linked_list_handler, NULL); - return 0; + linked_list_init(&_event_timer_linked_list); + return true; } -static int _deinit(void) +static bool _be_deinit(bool flush) { - return (_event_loop_initialized = 0); + if (!_event_loop_initialized) { + return true; + } + bool flush_result = true; + if (flush) { + flush_result = _run_until(EVENT_LOOP_DEFAULT_MAX_COUNT_RUN_UNTIL); + } + event_timer_t *curr; + while((curr = linked_list_get_first(&_event_timer_linked_list))) { + _timer_del(curr); + } + _event_loop_initialized = false; + if (!flush_result) { + log_warn("There are active and referenced handles or requests on event loop"); + } + return flush_result; +} + +static void _timers_reset_added_in_run() +{ + event_timer_t *curr = NULL; + linked_list_foreach(&_event_timer_linked_list, curr) { + curr->added_in_cb = false; + } } -static void timer_del(event_timer_t *t) +static void _timer_del(event_timer_t *t) { +#ifdef DEBUG_BE log_debug("deleting timer=[%p]", (void *)t); +#endif if (t) { event_timer_t **self = t->self; - +#ifdef DEBUG_BE log_debug("deleting timer=[%p] delay=[%lu] repeat=[%lu] ", (void *)t, t->delay, t->repeat); +#endif - linked_list_event_timer_t_remove(_event_timer_linked_list_handler, t); - object_pool_event_timer_t_free(t); + linked_list_remove(&_event_timer_linked_list, t, NULL); + object_pool_free(event_timer_t, t); if (self) { *self = NULL; @@ -98,124 +124,148 @@ static void timer_del(event_timer_t *t) _timers_list_debug_print(); } -static event_timer_t *timer_add(event_timer_t *t, event_timer_cb_t cb, void *ctx, uint64_t delay, uint64_t repeat, event_timer_t **self) +static event_timer_t *_timer_add(event_timer_t *t, event_loop_timer_cb_t cb, void *ctx, unsigned long delay, unsigned long repeat, event_timer_t **self) { - event_timer_t *iter = NULL, *new; + event_timer_t *curr = NULL, *new; bool is_periodic = !!t; - uint64_t current_time = itime_time(NULL); - linked_list_iterator_event_timer_t event_timer_iter = {0}; + unsigned long now = itime_time(NULL); + if (now == ITIME_FAILED) { + log_error("Error get current time"); + now = 0; + } +#ifdef DEBUG_BE log_debug("is_periodic=[%d]", is_periodic); +#endif if (is_periodic) { new = t; } else { - if (!(new = object_pool_event_timer_t_get())) { + if (!(new = object_pool_get(event_timer_t))) { log_error("Failed to allocate timer struct."); goto cleanup; } } - new->delay = delay + current_time; + new->delay = delay + now; new->repeat = repeat; new->ctx = ctx; new->self = self; new->cb = cb; + new->added_in_cb = _in_timer_cb; - linked_list_iterator_event_timer_t_init(&event_timer_iter, _event_timer_linked_list_handler); - - while ((iter = linked_list_iterator_event_timer_t_next(&event_timer_iter)) != NULL) { - if (new->delay < iter->delay) { + linked_list_foreach(&_event_timer_linked_list, curr) { + if (new->delay < curr->delay) { break; } } - if (linked_list_event_timer_t_insert(_event_timer_linked_list_handler, iter, new) != new) { + if (linked_list_insert_before(&_event_timer_linked_list, curr, new) != new) { log_error("Failed to insert timer to queue."); - timer_del(new); + _timer_del(new); new = NULL; goto cleanup; } - log_debug("added timer=[%p] delay=[%lu] repeat=[%lu] from preiodic=[%d]", (void *)new, new->delay, new->repeat, is_periodic); +#ifdef DEBUG_BE + log_debug("added timer=[%p] delay=[%lu] offset=[%lu] repeat=[%lu] from preiodic=[%d]", (void *)new, delay, new->delay, new->repeat, is_periodic); +#endif _timers_list_debug_print(); cleanup: return new; } -static void be_timer_wrapper(event_timer_t *t) +static void _be_timer_wrapper(event_timer_t *t) { - uint64_t repeat = t->repeat; + unsigned long repeat = t->repeat; - linked_list_event_timer_t_remove(_event_timer_linked_list_handler, t); + linked_list_remove(&_event_timer_linked_list, t, NULL); // Add timer to next period so in parameter 'delay' we will set 'repeat' value - if (repeat) { - timer_add(t, t->cb, t->ctx, t->repeat, t->repeat, t->self); + if (repeat && _event_loop_is_running) { + _timer_add(t, t->cb, t->ctx, t->repeat, t->repeat, t->self); } +#ifdef DEBUG_BE log_debug("calling timer=[%p] delay=[%lu] repeat=[%lu] ", (void *)t, t->delay, t->repeat); +#endif - t->cb(t, t->ctx); + t->cb((event_loop_timer_handler)t, t->ctx); } static bool _run_once(void) { - event_timer_t *iter; - uint64_t current_time = itime_time(NULL); - /* Get count to avoid dead loop */ - uint32_t count = linked_list_event_timer_t_get_size(_event_timer_linked_list_handler); + event_timer_t *t; + unsigned long now = itime_time(NULL); + if (now == ITIME_FAILED) { + log_error("Error get current time"); + now = 0; + } - log_debug("calling timers total count=[%d]", count); +#ifdef DEBUG_BE + log_debug("calling timers total count=[%zu]", linked_list_get_size(&_event_timer_linked_list)); +#endif _timers_list_debug_print(); /* stop() might be called in one of callbacks, so need to check it on each iteration. - * _event_timer_linked_list is changing on each call, so always get first. + * _event_timer_linked_list might change on each call, so always get first. */ - while(!_event_loop_is_stop && count-- && (iter = linked_list_event_timer_t_get_first(_event_timer_linked_list_handler))) { - if (iter->delay <= current_time) { - be_timer_wrapper(iter); + _in_timer_cb = true; + + while(_event_loop_initialized && (t = linked_list_get_first(&_event_timer_linked_list))) { + // we are adding timer to the end of same sorted sequence so if we met t->added_in_cb = true we can break + if (!t->added_in_cb && t->delay <= now) { + _be_timer_wrapper(t); } else { break; } } + _in_timer_cb = false; + _timers_reset_added_in_run(); _timers_list_debug_print(); - return !_event_loop_is_stop; + return _event_loop_is_running; } -static void _stop(void) +static bool _run_until(int max_count) { - event_timer_t *iter; + int cnt = 0; + while (cnt++ < max_count) { + if (!linked_list_get_size(&_event_timer_linked_list)) { + return true; + } + _run_once(); + } + return false; +} +static void _stop(void) +{ _timers_list_debug_print(); - - _event_loop_is_stop = true; - while((iter = linked_list_event_timer_t_get_first(_event_timer_linked_list_handler))) { - timer_del(iter); - } + _event_loop_is_running = false; } -static event_loop_timer_handler _timer_create(event_loop_timer_cb_t cb, void *ctx, uint64_t delay, uint64_t repeat, event_loop_timer_handler *self) +static event_loop_timer_handler _timer_create(event_loop_timer_cb_t cb, void *ctx, unsigned long delay, unsigned long repeat, event_loop_timer_handler *self) { if (!_event_loop_initialized) { return (event_loop_timer_handler)NULL; } - return (event_loop_timer_handler)timer_add(NULL, (event_timer_cb_t)cb, ctx, delay, repeat, (event_timer_t **)self); + return (event_loop_timer_handler)_timer_add(NULL, cb, ctx, delay, repeat, (event_timer_t **)self); } static void _timer_delete(event_loop_timer_handler handler) { if (handler) { - timer_del((event_timer_t *)handler); + _timer_del((event_timer_t *)handler); } } -ievent_loop_t *event_loop_be_instance_attach() +ievent_loop_t *event_loop_be_instance_attach(void) { static ievent_loop_t event_loop = { - .init = _init, - .deinit = _deinit, + .init = _be_init, + .deinit = _be_deinit, .run = NULL, .run_once = _run_once, + .run_until = _run_until, .stop = _stop, .signal_create = NULL, .signal_delete = NULL, diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/iconv.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/iconv.c new file mode 100644 index 00000000..c50ea0a2 --- /dev/null +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/iconv.c @@ -0,0 +1,34 @@ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include +#include +#include +#include + +#include + +#include "asc_security_core/utils/string_utils.h" +#include "asc_security_core/utils/iconv.h" +#include "asc_security_core/utils/string_utils.h" + +char *code2string(code2string_t *list, int code) +{ + for (; list->code != -1 && list->code!=code; list++); + + return list->string; +} + +int string2code(code2string_t *list, char *string, uint32_t len) +{ + for (; list->code != -1 && str_ncmp(list->string, str_len(list->string), string, len); list++); + + return list->code; +} \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/notifier.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/notifier.c index 1e136d22..aee98b82 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/notifier.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/notifier.c @@ -1,96 +1,89 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ +#include #include "asc_security_core/logger.h" -#include "asc_security_core/utils/collection/linked_list.h" +#include "asc_security_core/utils/collection/list.h" #include "asc_security_core/object_pool.h" #include "asc_security_core/utils/notifier.h" typedef struct notifier_item_t { + /* This macro must be first in object */ COLLECTION_INTERFACE(struct notifier_item_t); - notifier_t *notifier; + notifier_t *notifier; } notifier_item_t; -typedef struct { - int msg_num; - void *payload; -} notify_param_t; - -LINKED_LIST_DECLARATIONS(notifier_item_t) -LINKED_LIST_DEFINITIONS(notifier_item_t) OBJECT_POOL_DECLARATIONS(notifier_item_t) OBJECT_POOL_DEFINITIONS(notifier_item_t, NOTIFIERS_POOL_ENTRIES) -static linked_list_notifier_item_t _notify_arr[NOTIFY_TOPICS_NUMBER] = {0}; +static linked_list_t _notify_arr[NOTIFY_TOPICS_NUMBER] = {0}; -static bool _linked_list_find_condition(notifier_item_t *handle, void *condition_input) +static void object_pool_notifier_item_t_free(void *item) { - notifier_t *notifier = condition_input; - - return (notifier == handle->notifier); + object_pool_free(notifier_item_t, item); } -static void _notify(notifier_item_t *handle, void *ctx) +static bool _linked_list_find_condition(void *item, void *condition_input) { - notify_param_t *param = ctx; + notifier_item_t *handle = item; + notifier_t *notifier = condition_input; - if (handle->notifier->notify) { - handle->notifier->notify(handle->notifier, param->msg_num, param->payload); - } + return (notifier == handle->notifier); } int32_t notifier_notify(notify_topic_t topic, int msg_num, void *payload) { - linked_list_notifier_item_t_handle linked_list_handle; - notify_param_t param; + linked_list_t *linked_list_handle = NULL; + notifier_item_t *curr = NULL; - if (topic >= NOTIFY_TOPICS_NUMBER) { + if (topic >= NOTIFY_TOPICS_NUMBER) { log_error("Failed to remove notifier due to bad argument"); goto error; } - linked_list_handle = &_notify_arr[topic]; - param.msg_num = msg_num; - param.payload = payload; - linked_list_notifier_item_t_foreach(linked_list_handle, _notify, ¶m); - return (int32_t)linked_list_notifier_item_t_get_size(linked_list_handle); + linked_list_handle = &_notify_arr[topic]; + linked_list_foreach(linked_list_handle, curr) { + if (curr->notifier->notify) { + curr->notifier->notify(curr->notifier, msg_num, payload); + } + } + + return (int32_t)linked_list_get_size(linked_list_handle); error: - return -1; + return -1; } asc_result_t notifier_subscribe(notify_topic_t topic, notifier_t *notifier) { - asc_result_t result = ASC_RESULT_OK; - notifier_item_t *add; - linked_list_notifier_item_t_handle linked_list_handle; + asc_result_t result = ASC_RESULT_OK; + notifier_item_t *add; + linked_list_t *linked_list_handle; - if (topic >= NOTIFY_TOPICS_NUMBER) { + if (topic >= NOTIFY_TOPICS_NUMBER) { log_error("Failed to initialize notifier due to bad argument"); result = ASC_RESULT_BAD_ARGUMENT; - goto cleanup; + goto cleanup; } - - linked_list_handle = &_notify_arr[topic]; - if (linked_list_handle->initialized == false) { - linked_list_notifier_item_t_init(linked_list_handle, object_pool_notifier_item_t_free); - } - - add = object_pool_notifier_item_t_get(); + add = object_pool_get(notifier_item_t); if (add == NULL) { log_error("Failed to allocate notifier"); - result = ASC_RESULT_MEMORY_EXCEPTION; - goto cleanup; + result = ASC_RESULT_MEMORY_EXCEPTION; + goto cleanup; + } + add->notifier = notifier; + linked_list_handle = &_notify_arr[topic]; + if (linked_list_handle->initialized == false) { + linked_list_init(linked_list_handle); } - add->notifier = notifier; - linked_list_notifier_item_t_add_first(linked_list_handle, add); + linked_list_add_first(linked_list_handle, add); cleanup: return result; @@ -98,25 +91,25 @@ asc_result_t notifier_subscribe(notify_topic_t topic, notifier_t *notifier) asc_result_t notifier_unsubscribe(notify_topic_t topic, notifier_t *notifier) { - asc_result_t result = ASC_RESULT_OK; - linked_list_notifier_item_t_handle linked_list_handle; - notifier_item_t *handle; + asc_result_t result = ASC_RESULT_OK; + linked_list_t *linked_list_handle; + notifier_item_t *handle; - if (topic >= NOTIFY_TOPICS_NUMBER) { + if (topic >= NOTIFY_TOPICS_NUMBER) { log_error("Failed to remove notifier due to bad argument topic"); result = ASC_RESULT_BAD_ARGUMENT; - goto cleanup; + goto cleanup; } - linked_list_handle = &_notify_arr[topic]; - handle = linked_list_notifier_item_t_find(linked_list_handle, _linked_list_find_condition, notifier); - if (handle == NULL) { - log_error("Failed to remove notifier due to bad argument notifier"); + linked_list_handle = &_notify_arr[topic]; + handle = linked_list_find(linked_list_handle, _linked_list_find_condition, notifier); + if (handle == NULL) { + log_error("Failed to remove notifier due to bad argument notifier"); result = ASC_RESULT_BAD_ARGUMENT; - goto cleanup; - } + goto cleanup; + } - linked_list_notifier_item_t_remove(linked_list_handle, handle); + linked_list_remove(linked_list_handle, handle, object_pool_notifier_item_t_free); cleanup: return result; @@ -124,19 +117,18 @@ asc_result_t notifier_unsubscribe(notify_topic_t topic, notifier_t *notifier) asc_result_t notifier_deinit(notify_topic_t topic) { - asc_result_t result = ASC_RESULT_OK; - linked_list_notifier_item_t_handle linked_list_handle; + asc_result_t result = ASC_RESULT_OK; + linked_list_t *linked_list_handle; - if (topic >= NOTIFY_TOPICS_NUMBER) { + if (topic >= NOTIFY_TOPICS_NUMBER) { log_error("Failed to remove notifier due to bad argument topic"); result = ASC_RESULT_BAD_ARGUMENT; - goto cleanup; + goto cleanup; } + linked_list_handle = &_notify_arr[topic]; - linked_list_handle = &_notify_arr[topic]; - - linked_list_notifier_item_t_deinit(linked_list_handle); + linked_list_flush(linked_list_handle, object_pool_notifier_item_t_free); cleanup: - return result; + return result; } \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/string_utils.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/string_utils.c index dcb2f136..51170665 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/string_utils.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/string_utils.c @@ -1,28 +1,97 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include +#include + +#include +#include "asc_security_core/logger.h" #include "asc_security_core/utils/string_utils.h" +size_t str_len(const char *s) +{ + return s ? strlen(s) : 0; +} -const char *string_utils_value_or_empty(const char *s) +char *str_str(const char *s1, const char *s2) { - return (s == NULL) ? "" : s; + if (!s1 || !s2) { + return NULL; + } + return strstr(s1, s2); +} + +int str_cmp(const char *s1, const char *s2) +{ + return strcmp(s1 ? s1 : "", s2 ? s2 : ""); +} + +void str_trim_last_newline(char *s) +{ + size_t len; + + if (!s) { + return; + } + len = str_len(s); + + while (len) { + if (s[len-1] == '\n' || s[len-1] == '\r') { + s[len-1] = '\0'; + } else { + break; + } + len --; + } } +char *str_trim(char *s) +{ + char *end; -bool string_utils_is_blank(const char *s) + if (!s) { + return NULL; + } + // Trim leading space + while(isspace((unsigned char)*s)) { + s++; + } + // All spaces? + if(*s == '\0') { + return s; + } + // Trim trailing space + end = s + str_len(s) - 1; + while(end > s && isspace((unsigned char)*end)) { + end--; + } + // Write new null terminator character + end[1] = '\0'; + + return s; +} + +bool str_isempty(const char *s) +{ + return !s || !*s; +} + +const char *str_value_or_empty(const char *s) +{ + return (s == NULL) ? "" : s; +} + +bool str_is_blank(const char *s) { if (s == NULL) { return true; @@ -37,4 +106,64 @@ bool string_utils_is_blank(const char *s) } return true; -} \ No newline at end of file +} + +asc_result_t str_split(char *s, char **token, size_t *token_len, char **rest, size_t *rest_len, char *delimiter) +{ + asc_result_t result = ASC_RESULT_BAD_ARGUMENT; + char *p = str_str(s, delimiter); + size_t index = 0; + + if (p == NULL) { + log_error("Failed to find '%s' in string (s=%s)", delimiter, s); + goto cleanup; + } + + index = (str_len(s) - str_len(p)); + + if (index <= 0 || index+1 >= str_len(s)) { + log_error("Invalid key format (s=%s)", s); + goto cleanup; + } + + *token = s; + *token_len = index; + *rest = p + str_len(delimiter); + *rest_len = str_len(s) - index - str_len(delimiter); + result = ASC_RESULT_OK; + +cleanup: + return result; +} + +int str_ncmp(const char *s1, size_t s1_len, const char *s2, size_t s2_len) +{ + if (s1_len < s2_len) { + return -1; + } + + if (s2_len < s1_len) { + return 1; + } + + /* s1_len == s2_len */ + return strncmp(s1 ? s1 : "", s2 ? s2 : "", s1_len); +} + +bool str_starts_from(const char *s1, const char *s2) +{ + char *p = str_str(s1, s2); + return (p==s1); +} + +char *replace_chars(char *char_array, size_t len, char replace_from, char replace_to) +{ + for (size_t j = 0 ; j < len; j++) + { + if (char_array[j] == replace_from) { + char_array[j] = replace_to; + } + } + + return char_array; +} diff --git a/addons/azure_iot/azure_iot_security_module/src/utils/iuuid.c b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/uuid.c similarity index 59% rename from addons/azure_iot/azure_iot_security_module/src/utils/iuuid.c rename to addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/uuid.c index 78750e9e..f0812046 100644 --- a/addons/azure_iot/azure_iot_security_module/src/utils/iuuid.c +++ b/addons/azure_iot/azure_iot_security_module/iot-security-module-core/src/utils/uuid.c @@ -1,27 +1,28 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - +/*******************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure Defender for IoT. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureDefenderForIoT_EULA */ +/* and in the root directory of this software. */ +/* */ +/*******************************************************************************/ #include #include #include #include +#include + #include "asc_security_core/utils/irand.h" -#include "asc_security_core/utils/iuuid.h" +#include "asc_security_core/utils/uuid.h" static bool _initialized = false; static uint64_t _uuid[2]; -int iuuid_generate(uint8_t *buf_out) +int uuid_generate(uint8_t *buf_out) { if (!_initialized) { diff --git a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c index 9e44ac83..9acc642d 100644 --- a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c +++ b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.c @@ -8,16 +8,25 @@ /* and in the root directory of this software. */ /* */ /**************************************************************************/ +#include +#include + +#include #include "nx_azure_iot_hub_client.h" #include "nx_azure_iot_security_module.h" #include "asc_security_core/logger.h" -#include "asc_security_core/utils/irand.h" +#include "asc_security_core/components_manager.h" +#include "asc_security_core/utils/containerof.h" +#include "asc_security_core/utils/notifier.h" +#include "asc_security_core/utils/ievent_loop.h" #include "asc_security_core/utils/itime.h" +#include "asc_security_core/utils/collection/bit_vector.h" #include "iot_security_module/mti.h" +BIT_VECTOR_DECLARATIONS(hubs_t, ASC_SECURITY_MODULE_MAX_HUB_DEVICES) #define AZURE_IOT_SECURITY_MODULE_NAME "Azure IoT Security Module" #define AZURE_IOT_SECURITY_MODULE_EVENTS (NX_CLOUD_MODULE_AZURE_ISM_EVENT | NX_CLOUD_COMMON_PERIODIC_EVENT) @@ -26,78 +35,216 @@ static const CHAR *telemetry_headers[MAX_PROPERTY_COUNT][2] = {{MTI_KEY, MTI_VALUE}, {"%24.ifid", "urn%3Aazureiot%3ASecurity%3ASecurityAgent%3A1"}}; -static NX_AZURE_IOT_SECURITY_MODULE _security_module; -static NX_AZURE_IOT_SECURITY_MODULE *_security_module_ptr = NULL; - - -static uint32_t _security_module_unix_time_get(uint32_t *unix_time); +static unsigned long _security_module_unix_time_get(unsigned long *unix_time); static VOID _security_module_event_process(VOID *security_module_ptr, ULONG common_events, ULONG module_own_events); -static UINT _security_module_event_process_state_pending(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); -static UINT _security_module_event_process_state_active(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); -static UINT _security_module_event_process_state_suspended(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); +static void _security_module_event_process_state_pending(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); +static void _security_module_event_process_state_active(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); +static void _security_module_event_process_state_suspended(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); static UINT _security_module_message_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, security_message_t *security_message_ptr); -static VOID _security_module_clear_message(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); -static asc_result_t _security_module_collect(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); -static UINT _security_module_update_state(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, security_module_state_t state); +static void _security_module_update_state(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, security_module_state_t state); static bool _security_module_exists_connected_iot_hub(NX_AZURE_IOT *nx_azure_iot_ptr); +static void _security_module_state_machine(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr); +static void _security_module_state_machine_cb(event_loop_timer_handler h, void *ctx); +static void _security_module_state_machine_schedule(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, unsigned long delay); +static UINT _security_module_get_nx_status(UINT current); +static void _security_module_message_ready_cb(notifier_t *notifier, int msg, void *payload); +static NX_AZURE_IOT_HUB_CLIENT *_security_module_get_connected_hub_client(NX_AZURE_IOT_RESOURCE *resource_ptr); +static bool _is_skip_resource( + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, + NX_AZURE_IOT_RESOURCE *resource_ptr, + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + bit_vector_hubs_t *send_bitmap_vector, + bool send_failed_once_over_map_limit); + +static bool _initialized; + +static asc_result_t _cm_init(component_id_t id); +static asc_result_t _cm_deinit(component_id_t id); +static asc_result_t _cm_start(component_id_t id); +static component_ops_t _ops = { + .init = _cm_init, + .start = _cm_start, + .deinit = _cm_deinit +}; + +COMPONENTS_FACTORY_DEFINITION(SecurityModule, &_ops) + +static asc_result_t _cm_start(component_id_t id) +{ + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = components_manager_get_self_ctx(); + if (!security_module_ptr) { + return ASC_RESULT_MEMORY_EXCEPTION; + } + /* Set security module state as pending. */ + _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_PENDING); + _security_module_state_machine(security_module_ptr); -UINT nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr) + return ASC_RESULT_OK; +} + +static asc_result_t _cm_init(component_id_t id) { -UINT status = NX_AZURE_IOT_SUCCESS; + asc_result_t result = ASC_RESULT_OK; + component_info_t *info; + UINT status = NX_AZURE_IOT_SUCCESS; + static NX_AZURE_IOT_SECURITY_MODULE _security_module; + + memset(&_security_module, 0, sizeof(NX_AZURE_IOT_SECURITY_MODULE)); + components_manager_set_self_ctx(&_security_module); + + /* Persist the nx_azure_iot_ptr. */ + _security_module.nx_azure_iot_ptr = (NX_AZURE_IOT *)components_manager_global_context_get(); + + /* Register Azure IoT Security Module on cloud helper. */ + if ((status = nx_cloud_module_register( + &(_security_module.nx_azure_iot_ptr->nx_azure_iot_cloud), + &(_security_module.nx_azure_iot_security_module_cloud), + AZURE_IOT_SECURITY_MODULE_NAME, + AZURE_IOT_SECURITY_MODULE_EVENTS, + _security_module_event_process, + &_security_module + ))) + { + LogError(LogLiteralArgs("Security module register fail, error=%d"), status); + goto cleanup; + } - /* Check if Security Module instance is already been initialized. */ - if (_security_module_ptr == NULL) - { + _security_module.message_ready.notify = _security_module_message_ready_cb; + result = notifier_subscribe(NOTIFY_TOPIC_COLLECT, &_security_module.message_ready); + _security_module.state = SECURITY_MODULE_STATE_NOT_INITIALIZED; - if (nx_azure_iot_ptr == NULL) - { - status = NX_AZURE_IOT_INVALID_PARAMETER; - goto cleanup; - } - - /* Update singleton pointer. */ - _security_module_ptr = &_security_module; +cleanup: + /* Store NX status to be able return right result from nx_azure_iot_security_module_enable() */ + info = components_manager_get_info(components_manager_get_self_id()); + if (info) + { + info->ext_ctx = (uintptr_t)status; + } + if (status != NX_AZURE_IOT_SUCCESS) + { + LogError(LogLiteralArgs("Failed to init Azure IoT Security Module component, error=%d"), status); + return ASC_RESULT_EXCEPTION; + } + return result; +} - memset(_security_module_ptr, 0, sizeof(NX_AZURE_IOT_SECURITY_MODULE)); +static asc_result_t _cm_deinit(component_id_t id) +{ + UINT status = NX_AZURE_IOT_SUCCESS; + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = components_manager_get_self_ctx(); - /* Persist the nx_azure_iot_ptr. */ - _security_module_ptr->nx_azure_iot_ptr = nx_azure_iot_ptr; + if (!security_module_ptr) { + return ASC_RESULT_MEMORY_EXCEPTION; + } + ievent_loop_get_instance()->timer_delete(security_module_ptr->h_state_machine); - /* Initialize Security Module time interface. */ - itime_init((unix_time_callback_t)_security_module_unix_time_get); + notifier_unsubscribe(NOTIFY_TOPIC_COLLECT, &security_module_ptr->message_ready); - /* Initialize Security Module core. */ - _security_module_ptr->core_ptr = core_init(); - if (_security_module_ptr->core_ptr == NULL) + /* Deregister Azure IoT Security Module from cloud helper. */ + if (security_module_ptr->nx_azure_iot_ptr != NULL) + { + if ((status = nx_cloud_module_deregister( + &(security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_cloud), + &(security_module_ptr->nx_azure_iot_security_module_cloud) + ))) { + LogError(LogLiteralArgs("Failed to deregister Azure IoT Security Module, error=%d"), status); status = NX_AZURE_IOT_FAILURE; - LogError(LogLiteralArgs("Failed to enable IoT Security Module, CORE INIT FAIL")); - goto cleanup; } + } + components_manager_set_self_ctx(NULL); + if (status != NX_AZURE_IOT_SUCCESS) + { + LogError(LogLiteralArgs("Failed to deinit Azure IoT Security Module component, error=%d"), status); + return ASC_RESULT_EXCEPTION; + } + return ASC_RESULT_OK; +} - /* Register Azure IoT Security Module on cloud helper. */ - if ((status = nx_cloud_module_register( - &(nx_azure_iot_ptr->nx_azure_iot_cloud), - &(_security_module_ptr->nx_azure_iot_security_module_cloud), - AZURE_IOT_SECURITY_MODULE_NAME, - AZURE_IOT_SECURITY_MODULE_EVENTS, - _security_module_event_process, - _security_module_ptr - ))) +UINT nx_azure_iot_security_module_enable(NX_AZURE_IOT *nx_azure_iot_ptr) +{ + UINT status = NX_AZURE_IOT_SUCCESS; + asc_result_t result = ASC_RESULT_OK; + ievent_loop_t *event_loop = ievent_loop_get_instance(); + ULONG t = (ULONG)-1; + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = NULL; + + /* Check if Security Module instance is already been initialized. */ + if (_initialized) + { + security_module_ptr = components_manager_get_self_ctx(); + if (security_module_ptr == NULL) { - LogError(LogLiteralArgs("Security module register fail, error=%d"), status); + LogError(LogLiteralArgs("Security Module is not running")); + status = NX_AZURE_IOT_FAILURE; goto cleanup; } - - /* Set security module state as active. */ - if ((status = _security_module_update_state(_security_module_ptr, SECURITY_MODULE_STATE_PENDING))) + if (security_module_ptr->nx_azure_iot_ptr != nx_azure_iot_ptr) { - LogError(LogLiteralArgs("Failed to update Security Module state, error=%d"), status); + LogError(LogLiteralArgs("Multiple initializing with different nx_azure_iot_ptr")); + status = NX_AZURE_IOT_INVALID_PARAMETER; goto cleanup; } + goto cleanup; + } + + if (nx_azure_iot_ptr == NULL) + { + status = NX_AZURE_IOT_INVALID_PARAMETER; + goto cleanup; + } + + if (nx_azure_iot_ptr->nx_azure_iot_unix_time_get(&t) != NX_AZURE_IOT_SUCCESS) + { + status = NX_AZURE_IOT_FAILURE; + LogError(LogLiteralArgs("Failed to retrieve UNIX time")); + goto cleanup; + } + if (t == (ULONG)-1) + { + status = NX_AZURE_IOT_FAILURE; + LogError(LogLiteralArgs("Failed to retrieve UNIX time")); + goto cleanup; + } + + itime_init((unix_time_callback_t)_security_module_unix_time_get); + + if (event_loop == NULL) + { + /* Should never happen */ + status = NX_AZURE_IOT_FAILURE; + LogError(LogLiteralArgs("Failed to retrieve event loop")); + goto cleanup; } + event_loop->init(); + components_manager_global_context_set((uintptr_t)nx_azure_iot_ptr); + + result = components_manager_init(); + switch (result) + { + case ASC_RESULT_INITIALIZED: + goto cleanup; + break; + case ASC_RESULT_OK: + break; + default: + status = NX_AZURE_IOT_FAILURE; + LogError(LogLiteralArgs("Failed to init component manager")); + goto cleanup; + break; + } + + security_module_ptr = components_manager_get_self_ctx(); + if (security_module_ptr == NULL) + { + LogError(LogLiteralArgs("Failed to init Security Module")); + status = NX_AZURE_IOT_FAILURE; + goto cleanup; + } + status = _security_module_get_nx_status(status); + cleanup: if (status != NX_AZURE_IOT_SUCCESS) { @@ -108,55 +255,43 @@ UINT status = NX_AZURE_IOT_SUCCESS; } else { + _initialized = true; LogInfo(LogLiteralArgs("Azure IoT Security Module has been enabled, status=%d"), status); } return status; } - UINT nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; + UINT status = NX_AZURE_IOT_SUCCESS; + ievent_loop_t *event_loop = ievent_loop_get_instance(); + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = components_manager_get_self_ctx(); - if (_security_module_ptr != NULL) + if (security_module_ptr == NULL) { - if (_security_module_ptr->nx_azure_iot_ptr != nx_azure_iot_ptr && nx_azure_iot_ptr != NULL) - { - status = NX_AZURE_IOT_INVALID_PARAMETER; - } - else - { - - /* Set security module state as not initialized. */ - if ((status = _security_module_update_state(_security_module_ptr, SECURITY_MODULE_STATE_NOT_INITIALIZED))) - { - LogError(LogLiteralArgs("Failed to update IoT Security state, error=%d"), status); - } - - /* Deregister Azure IoT Security Module from cloud helper. */ - if (_security_module_ptr->nx_azure_iot_ptr != NULL) - { - if ((status = nx_cloud_module_deregister( - &(_security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_cloud), - &(_security_module_ptr->nx_azure_iot_security_module_cloud) - ))) - { - LogError(LogLiteralArgs("Failed to deregister Azure IoT Security Module, error=%d"), status); - status = NX_AZURE_IOT_FAILURE; - } - } - - core_deinit(_security_module_ptr->core_ptr); - _security_module_ptr->core_ptr = NULL; - - _security_module_ptr = NULL; - } + LogInfo(LogLiteralArgs("Security Module is not runnung")); + goto cleanup; + } + if (security_module_ptr->nx_azure_iot_ptr != nx_azure_iot_ptr && nx_azure_iot_ptr != NULL) + { + LogError(LogLiteralArgs("Disabling with wrong nx_azure_iot_ptr")); + status = NX_AZURE_IOT_INVALID_PARAMETER; + goto cleanup; + } + _initialized = false; + security_module_ptr->state = SECURITY_MODULE_STATE_NOT_INITIALIZED; + components_manager_deinit(); + if (event_loop != NULL) /* (event_loop == NULL) - Should never happen */ + { + event_loop->stop(); + event_loop->deinit(true); } +cleanup: if (status != NX_AZURE_IOT_SUCCESS) { - LogError(LogLiteralArgs("Failed to disable IoT Security Module, error=%d"), status); + LogError(LogLiteralArgs("Failed to disable Azure IoT Security Module, error=%d"), status); } else { @@ -166,71 +301,113 @@ UINT status = NX_AZURE_IOT_SUCCESS; return status; } +static void _security_module_message_ready_cb(notifier_t *notifier, int msg, void *payload) +{ + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = containerof(notifier, NX_AZURE_IOT_SECURITY_MODULE, message_ready); + + if (security_module_ptr == NULL) + { + /* Should never happen */ + LogError(LogLiteralArgs("Azure IoT Security Module component is not initialized")); + return; + } + _security_module_state_machine(security_module_ptr); +} -static uint32_t _security_module_unix_time_get(uint32_t *unix_time) +static unsigned long _security_module_unix_time_get(unsigned long *unix_time) { -ULONG t; + ULONG t; + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = components_manager_get_self_ctx(); - if (_security_module_ptr == NULL || _security_module_ptr->nx_azure_iot_ptr == NULL) + if (security_module_ptr == NULL || security_module_ptr->nx_azure_iot_ptr == NULL) { - return (uint32_t)-1; + return ITIME_FAILED; } - if (_security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_unix_time_get(&t) == NX_SUCCESS) + if (security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_unix_time_get(&t) == NX_AZURE_IOT_SUCCESS) { if (unix_time != NULL) { - *unix_time = (uint32_t)t; + *unix_time = (unsigned long)t; } - return (uint32_t)t; + return (unsigned long)t; } - return (uint32_t)-1; + return ITIME_FAILED; } +static UINT _security_module_get_nx_status(UINT current) +{ + UINT status = current; + asc_result_t result = ASC_RESULT_OK; + + if (current != NX_AZURE_IOT_SUCCESS) + { + return current; + } + result = components_manager_get_last_result(components_manager_get_self_id()); + if (result != ASC_RESULT_OK) + { + status = NX_AZURE_IOT_FAILURE; + component_info_t *info = components_manager_get_info(components_manager_get_self_id()); + if (info && (UINT)info->ext_ctx != NX_AZURE_IOT_SUCCESS) + { + status = (UINT)info->ext_ctx; + } + } + return status; +} + +static void _security_module_state_machine(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +{ + ievent_loop_get_instance()->timer_delete(security_module_ptr->h_state_machine); + switch(security_module_ptr->state) + { + case SECURITY_MODULE_STATE_NOT_INITIALIZED: + /* Cannot occurred. */ + break; + case SECURITY_MODULE_STATE_PENDING: + _security_module_event_process_state_pending(security_module_ptr); + break; + case SECURITY_MODULE_STATE_ACTIVE: + _security_module_event_process_state_active(security_module_ptr); + break; + case SECURITY_MODULE_STATE_SUSPENDED: + _security_module_event_process_state_suspended(security_module_ptr); + break; + default: + LogError(LogLiteralArgs("Unsupported Security Module state=%d"), security_module_ptr->state); + break; + } +} -static VOID _security_module_event_process(VOID *security_module_ptr, ULONG common_events, ULONG module_own_events) +static void _security_module_state_machine_cb(event_loop_timer_handler h, void *ctx) { -UINT status = NX_AZURE_IOT_SUCCESS; -NX_AZURE_IOT_SECURITY_MODULE *security_module = (NX_AZURE_IOT_SECURITY_MODULE*)security_module_ptr; + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = (NX_AZURE_IOT_SECURITY_MODULE *)ctx; + + ievent_loop_get_instance()->timer_delete(h); + _security_module_state_machine(security_module_ptr); +} + +static VOID _security_module_event_process(VOID *ctx, ULONG common_events, ULONG module_own_events) +{ + UINT status = NX_AZURE_IOT_SUCCESS; + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr = (NX_AZURE_IOT_SECURITY_MODULE*)ctx; NX_PARAMETER_NOT_USED(module_own_events); - /* Process common events. */ + /* Process common events. */ if (common_events & NX_CLOUD_COMMON_PERIODIC_EVENT) { - if (security_module == NULL) + if (security_module_ptr == NULL) { /* Periodic events must use instance of security module. */ status = NX_AZURE_IOT_INVALID_PARAMETER; LogError(LogLiteralArgs("Security Module process periodic events must receive an instance, status=%d"), status); goto error; } - - switch(security_module->state) - { - case SECURITY_MODULE_STATE_NOT_INITIALIZED: - /* Cannot occurred. */ - break; - case SECURITY_MODULE_STATE_PENDING: - status = _security_module_event_process_state_pending(security_module); - break; - case SECURITY_MODULE_STATE_ACTIVE: - status = _security_module_event_process_state_active(security_module); - break; - case SECURITY_MODULE_STATE_SUSPENDED: - status = _security_module_event_process_state_suspended(security_module); - break; - default: - LogError(LogLiteralArgs("Unsupported Security Module state=%d"), security_module->state); - } - - if (status != NX_AZURE_IOT_SUCCESS) - { - LogError(LogLiteralArgs("Failed to process state=%d"), security_module->state); - goto error; - } + ievent_loop_get_instance()->run_once(); } error: @@ -240,34 +417,84 @@ NX_AZURE_IOT_SECURITY_MODULE *security_module = (NX_AZURE_IOT_SECURITY_MODULE*)s } } +static void _security_module_state_machine_schedule(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, unsigned long delay) +{ + ievent_loop_get_instance()->timer_delete(security_module_ptr->h_state_machine); + security_module_ptr->h_state_machine = ievent_loop_get_instance()->timer_create( + _security_module_state_machine_cb, security_module_ptr, + delay, + 0, + &security_module_ptr->h_state_machine + ); +} -static UINT _security_module_event_process_state_pending(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +static NX_AZURE_IOT_HUB_CLIENT *_security_module_get_connected_hub_client(NX_AZURE_IOT_RESOURCE *resource_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; -asc_result_t asc_result = ASC_RESULT_OK; -uint32_t now_timestamp; -security_message_t *security_message_ptr = &security_module_ptr->security_message; + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NULL; - /* Check if Security Message is already cached */ - if (!security_message_is_empty(security_message_ptr)) + hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource_ptr->resource_data_ptr; + if (hub_client_ptr == NULL) { - /* Security Message is cached clear Security Message. */ - _security_module_clear_message(security_module_ptr); + return NULL; } - - /* Collect security events. */ - asc_result = _security_module_collect(security_module_ptr); - if (asc_result == ASC_RESULT_EMPTY) + /* Filter only connected IoT Hubs. */ + if (hub_client_ptr->nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) { - /* No security message */ - status = NX_AZURE_IOT_SUCCESS; + return NULL; } - else if (asc_result != ASC_RESULT_OK) + return hub_client_ptr; +} + +static bool _is_skip_resource( + NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, + NX_AZURE_IOT_RESOURCE *resource_ptr, + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + bit_vector_hubs_t *send_bitmap_vector, + bool send_failed_once_over_map_limit) +{ + int prev_hub_index = -1; + + /* Iterate over previous seen IoT Hub resources and send Security Message only for unique devices. */ + for (NX_AZURE_IOT_RESOURCE *prev_resource_ptr = security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_resource_list_header; + prev_resource_ptr != resource_ptr; + prev_resource_ptr = prev_resource_ptr->resource_next) { - status = NX_AZURE_IOT_FAILURE; - LogError(LogLiteralArgs("Core failed to collect security message, error=%d"), status); - goto error; + if (prev_resource_ptr->resource_type != NX_AZURE_IOT_RESOURCE_IOT_HUB) + { + continue; + } + NX_AZURE_IOT_HUB_CLIENT *prev_hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)prev_resource_ptr->resource_data_ptr; + prev_hub_index++; + bool was_send; + if (prev_hub_index < bit_vector_size(hubs_t)) + { + was_send = bit_vector_get(hubs_t, send_bitmap_vector, prev_hub_index); + } + else + { + LogError(LogLiteralArgs("Hub index %d is over max supported history hubs %d - broadcast will send - change ASC_SECURITY_MODULE_MAX_HUB_DEVICES config"), prev_hub_index+1, ASC_SECURITY_MODULE_MAX_HUB_DEVICES); + was_send = !send_failed_once_over_map_limit; + } + + if (was_send && + az_span_is_content_equal( + hub_client_ptr->iot_hub_client_core._internal.iot_hub_hostname, + prev_hub_client_ptr->iot_hub_client_core._internal.iot_hub_hostname) && + az_span_is_content_equal( + hub_client_ptr->iot_hub_client_core._internal.device_id, + prev_hub_client_ptr->iot_hub_client_core._internal.device_id + )) + { + return true; + } } + return false; +} + +static void _security_module_event_process_state_pending(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +{ + unsigned long now_timestamp; + unsigned long delay = ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME; /* Reevaluate Security Module State */ if (_security_module_exists_connected_iot_hub(security_module_ptr->nx_azure_iot_ptr)) @@ -275,148 +502,124 @@ security_message_t *security_message_ptr = &security_module_ptr->security_messag /* Security Module is able to send security messages. */ /* Update security Module state to active. */ - if ((status = _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_ACTIVE))) - { - LogError(LogLiteralArgs("Failed to update IoT Security state, error=%d"), status); - goto error; - } + delay = 0; + _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_ACTIVE); + goto cleanup; } /* Get current timestamp. */ - if (_security_module_unix_time_get(&now_timestamp) == (uint32_t)-1) + if (itime_time(&now_timestamp) == ITIME_FAILED) { - status = NX_AZURE_IOT_FAILURE; - LogError(LogLiteralArgs("Failed to retrieve timestamp, error=%d"), status); - goto error; + LogError(LogLiteralArgs("Failed to retrieve timestamp")); } - if (now_timestamp - security_module_ptr->state_timestamp > ASC_SECURITY_MODULE_PENDING_TIME) + if (security_module_ptr->state_timestamp != ITIME_FAILED && + now_timestamp != ITIME_FAILED && + now_timestamp - security_module_ptr->state_timestamp > ASC_SECURITY_MODULE_PENDING_TIME) { /* Security Module pending state time expired. */ /* Update security Module state to suspend. */ - if ((status = _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_SUSPENDED))) - { - LogError(LogLiteralArgs("Failed to update Security Module state, error=%d"), status); - goto error; - } + _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_SUSPENDED); } -error: - if (status != NX_AZURE_IOT_SUCCESS) - { - LogError(LogLiteralArgs("Failed to process security module pending state, error=%d"), status); - } - - return status; +cleanup: + _security_module_state_machine_schedule(security_module_ptr, delay); } - -static UINT _security_module_event_process_state_active(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +static void _security_module_event_process_state_active(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; -asc_result_t asc_result = ASC_RESULT_OK; -security_message_t *security_message_ptr = &security_module_ptr->security_message; -NX_AZURE_IOT_RESOURCE *resource_ptr; + asc_result_t result = ASC_RESULT_OK; + security_message_t security_message = { 0 }; + NX_AZURE_IOT_RESOURCE *resource_ptr; - if (security_message_is_empty(security_message_ptr)) + result = core_message_get(&security_message); + if (result == ASC_RESULT_EMPTY) { - asc_result = _security_module_collect(security_module_ptr); + LogInfo(LogLiteralArgs("Azure IoT Security Module message is empty")); + return; } - - if (asc_result == ASC_RESULT_EMPTY) + if (result != ASC_RESULT_OK) { - /* Security message has no events, skip. */ + LogError(LogLiteralArgs("Fail to get security message result=%d"), result); + core_message_deinit(); + return; } - else if (asc_result == ASC_RESULT_OK) + + /* If exists at least one connected IoT Hub, Security Module will remain in active state. */ + bool exists_connected_iot_hub = false; + /* If was failure on send message on hub number > 64, we want to try to send to all connected hubs. */ + bool send_failed_once_over_map_limit = false; + /* If was not passed on send message, we want to retry to send in short time. */ + bool send_passed_once = false; + + bit_vector_hubs_t send_bitmap_vector; + memset(&send_bitmap_vector, 0, sizeof(bit_vector_hubs_t)); + + int hub_index = -1; + + /* Iterate over all NX_AZURE_IOT_HUB_CLIENT instances. */ + for (resource_ptr = security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_resource_list_header; + resource_ptr != NX_NULL; + resource_ptr = resource_ptr->resource_next) { - /* Send security message to IoT Hubs. */ + if (resource_ptr->resource_type != NX_AZURE_IOT_RESOURCE_IOT_HUB) + { + continue; + } + hub_index++; + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = _security_module_get_connected_hub_client(resource_ptr); + if (hub_client_ptr == NULL) + { + continue; + } + exists_connected_iot_hub = true; - /* If exists at least one connected IoT Hub, Security Module will remain in active state. */ - bool exists_connected_iot_hub = false; + /* + Skip resource iff a security message is already been sent to this specific device. Avoid + sending security message to a Device Identity and to his Module Identities if both connected. + */ + bool skip_resource = _is_skip_resource(security_module_ptr, resource_ptr, hub_client_ptr, &send_bitmap_vector, send_failed_once_over_map_limit); - /* Iterate over all NX_AZURE_IOT_HUB_CLIENT instances. */ - for (resource_ptr = security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_resource_list_header; - resource_ptr != NX_NULL; - resource_ptr = resource_ptr->resource_next) + if (!skip_resource) { - /* Filter only IoT Hub resources */ - if (resource_ptr->resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB) + UINT status = _security_module_message_send(hub_client_ptr, &security_message); + if (status != NX_AZURE_IOT_SUCCESS) { - NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource_ptr->resource_data_ptr; - - /* Filter only connected IoT Hubs. */ - if (hub_client_ptr->nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + if (hub_index >= bit_vector_size(hubs_t)) { - exists_connected_iot_hub = true; - - /* - Skip resource iff a security message is already been sent to this specific device. Avoid - sending security message to a Device Identity and to his Module Identities if both connected. - */ - bool skip_resource = false; - - if (resource_ptr != security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_resource_list_header) - { - /* Iterate over previous seen IoT Hub resources and send Security Message only for unique devices. */ - for (NX_AZURE_IOT_RESOURCE *prev_resource_ptr = security_module_ptr->nx_azure_iot_ptr->nx_azure_iot_resource_list_header; - prev_resource_ptr != resource_ptr; - prev_resource_ptr = prev_resource_ptr->resource_next) - { - NX_AZURE_IOT_HUB_CLIENT *prev_hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)prev_resource_ptr->resource_data_ptr; - - if (az_span_is_content_equal( - hub_client_ptr->iot_hub_client_core._internal.iot_hub_hostname, - prev_hub_client_ptr->iot_hub_client_core._internal.iot_hub_hostname - ) && az_span_is_content_equal( - hub_client_ptr->iot_hub_client_core._internal.device_id, - prev_hub_client_ptr->iot_hub_client_core._internal.device_id - )) - { - skip_resource = true; - break; - } - } - } - - if (!skip_resource) - { - if ((status = _security_module_message_send(hub_client_ptr, security_message_ptr))) - { - LogError(LogLiteralArgs("Failed to send security message, error=%d"), status); - } - } + send_failed_once_over_map_limit = true; } + LogError(LogLiteralArgs("Failed to send security message, error=%d"), status); } - } - - if (!exists_connected_iot_hub) - { - /* Update security Module state to pending. */ - if ((status = _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_PENDING))) + else { - LogError(LogLiteralArgs("Failed to update IoT Security state, error=%d"), status); + bit_vector_set(hubs_t, &send_bitmap_vector, hub_index, true); + send_passed_once = true; } } - - if (status == NX_AZURE_IOT_SUCCESS) - { - _security_module_clear_message(security_module_ptr); - } + } + if (!exists_connected_iot_hub) + { + _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_PENDING); + _security_module_state_machine_schedule(security_module_ptr, ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME); } else { - status = NX_AZURE_IOT_FAILURE; - LogError(LogLiteralArgs("Security Module event process failed, error=%d"), status); + if (!send_passed_once) + { + _security_module_state_machine_schedule(security_module_ptr, ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME); + } + else + { + core_message_deinit(); + } } - - return status; } - -static UINT _security_module_event_process_state_suspended(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +static void _security_module_event_process_state_suspended(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; + unsigned long delay = ASC_SECURITY_MODULE_SEND_MESSAGE_RETRY_TIME; /* Reevaluate Security Module State */ if (_security_module_exists_connected_iot_hub(security_module_ptr->nx_azure_iot_ptr)) @@ -424,20 +627,19 @@ UINT status = NX_AZURE_IOT_SUCCESS; /* Security Module is able to send security messages. */ /* Update security Module state to active. */ - if ((status = _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_ACTIVE))) - { - LogError(LogLiteralArgs("Failed to update IoT Security state, error=%d"), status); - } + delay = 0; + _security_module_update_state(security_module_ptr, SECURITY_MODULE_STATE_ACTIVE); + goto cleanup; } - return status; +cleanup: + _security_module_state_machine_schedule(security_module_ptr, delay); } - static UINT _security_module_message_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, security_message_t *security_message_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; -NX_PACKET *packet_ptr = NULL; + UINT status = NX_AZURE_IOT_SUCCESS; + NX_PACKET *packet_ptr = NULL; /* Create a telemetry message packet. */ if ((status = nx_azure_iot_hub_client_telemetry_message_create(hub_client_ptr, @@ -469,7 +671,7 @@ NX_PACKET *packet_ptr = NULL; } UCHAR *data = security_message_ptr->data; - size_t data_length = security_message_ptr->size; + UINT data_length = (UINT)security_message_ptr->size; if ((status = nx_azure_iot_hub_client_telemetry_send(hub_client_ptr, packet_ptr, @@ -491,87 +693,56 @@ NX_PACKET *packet_ptr = NULL; return status; } - -static VOID _security_module_clear_message(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) +static int _state2notify(security_module_state_t state) { -security_message_t *security_message_ptr = &security_module_ptr->security_message; - - /* Clear security message */ - core_message_deinit(security_module_ptr->core_ptr); - - security_message_clear(security_message_ptr); - security_message_ptr = NULL; -} - - -static asc_result_t _security_module_collect(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr) -{ -asc_result_t asc_result = ASC_RESULT_OK; -security_message_t *security_message_ptr = &security_module_ptr->security_message; - - /* Collect security events. */ - asc_result = core_collect(security_module_ptr->core_ptr); - if (asc_result == ASC_RESULT_EMPTY) - { - /* No events found */ - return ASC_RESULT_OK; - } - else if (asc_result != ASC_RESULT_OK) - { - LogError(LogLiteralArgs("Core failed to collect events, error=%d"), asc_result); - return asc_result; - } - - /* Sign and retrieve Security Message. */ - asc_result = core_message_get(security_module_ptr->core_ptr, security_message_ptr); - if (asc_result == ASC_RESULT_EMPTY) - { - /* No events found */ - } - else if (asc_result != ASC_RESULT_OK) - { - LogError(LogLiteralArgs("Core failed to set security message, error=%d"), asc_result); - return asc_result; + switch(state) + { + case SECURITY_MODULE_STATE_PENDING: + return NOTIFY_SECURITY_MODULE_PENDING; + case SECURITY_MODULE_STATE_ACTIVE: + return NOTIFY_SECURITY_MODULE_CONNECTED; + case SECURITY_MODULE_STATE_SUSPENDED: + return NOTIFY_SECURITY_MODULE_SUSPENDED; + default: + LogError(LogLiteralArgs("Unsupported Security Module state=%d"), state); + return -1; } - - return asc_result; } - -static UINT _security_module_update_state(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, security_module_state_t state) +static void _security_module_update_state(NX_AZURE_IOT_SECURITY_MODULE *security_module_ptr, security_module_state_t state) { -UINT status = NX_AZURE_IOT_SUCCESS; + unsigned long now_timestamp; if (security_module_ptr->state == state) { /* Security Module is already set to given state. */ - goto cleanup; + return; } /* Set security module state timestamp. */ - if (itime_time(&(security_module_ptr->state_timestamp)) == (uint32_t)-1) + if (itime_time(&now_timestamp) == ITIME_FAILED) { - status = NX_AZURE_IOT_FAILURE; LogError(LogLiteralArgs("Failed to retrive time")); - goto cleanup; + } + else + { + security_module_ptr->state_timestamp = now_timestamp; } /* Set security module state. */ security_module_ptr->state = state; -cleanup: - if (status != NX_AZURE_IOT_SUCCESS) + int notification_enum = _state2notify(state); + if (notification_enum >= 0) { - LogError(LogLiteralArgs("Failed to update Security Message state, error=%d"), status); + notifier_notify(NOTIFY_TOPIC_SECURITY_MODULE_STATE, _state2notify(state), security_module_ptr); } - - return status; } static bool _security_module_exists_connected_iot_hub(NX_AZURE_IOT *nx_azure_iot_ptr) { -NX_AZURE_IOT_RESOURCE *resource_ptr; + NX_AZURE_IOT_RESOURCE *resource_ptr; /* Iterate over all NX_AZURE_IOT_HUB_CLIENT instances. */ for (resource_ptr = nx_azure_iot_ptr->nx_azure_iot_resource_list_header; @@ -580,10 +751,10 @@ NX_AZURE_IOT_RESOURCE *resource_ptr; { if (resource_ptr->resource_type == NX_AZURE_IOT_RESOURCE_IOT_HUB) { - NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource_ptr->resource_data_ptr; - /* Check IoT Hub client connectivity. */ - if (hub_client_ptr->nx_azure_iot_hub_client_state == NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = _security_module_get_connected_hub_client(resource_ptr); + + if (hub_client_ptr != NULL) { return true; } diff --git a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.h b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.h index a8720bf4..6194a42f 100644 --- a/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.h +++ b/addons/azure_iot/azure_iot_security_module/nx_azure_iot_security_module.h @@ -12,6 +12,12 @@ #ifndef NX_AZURE_IOT_SECURITY_MODULE_H #define NX_AZURE_IOT_SECURITY_MODULE_H +#include + +#ifdef __ASC_CONFIG_EXCLUDE_PORT__H__ +#error Platform includes error +#endif + #ifdef __cplusplus extern "C" { #endif @@ -26,12 +32,13 @@ extern "C" { #include "asc_security_core/core.h" #include "asc_security_core/version.h" - +#include "asc_security_core/utils/itime.h" +#include "asc_security_core/utils/notifier.h" +#include "asc_security_core/utils/ievent_loop.h" /* Define AZ IoT ASC event flags. These events are processed by the Cloud thread. */ #define AZ_IOT_SECURITY_MODULE_SEND_EVENT ((ULONG)0x00000001) /* Security send event. */ - /** * @brief Azure IoT Security Module state enum * @@ -74,8 +81,6 @@ typedef enum security_module_state SECURITY_MODULE_STATE_SUSPENDED = 3 } security_module_state_t; - - /** * @struct NX_AZURE_IOT_SECURITY_MODULE * @@ -98,17 +103,15 @@ typedef enum security_module_state typedef struct NX_AZURE_IOT_SECURITY_MODULE_STRUCT { security_module_state_t state; - uint32_t state_timestamp; - - core_t *core_ptr; - security_message_t security_message; + notifier_t message_ready; + unsigned long state_timestamp; + event_loop_timer_handler h_state_machine; NX_AZURE_IOT *nx_azure_iot_ptr; NX_CLOUD_MODULE nx_azure_iot_security_module_cloud; } NX_AZURE_IOT_SECURITY_MODULE; - /** * @brief Enable Azure IoT Security Module * diff --git a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c index f39a6ebf..8a5d3eac 100644 --- a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c +++ b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_network_activity.c @@ -9,6 +9,8 @@ /* */ /**************************************************************************/ +#include + #include "nx_api.h" #include "nx_ip.h" #include "nx_ipv4.h" @@ -20,11 +22,14 @@ #include "nx_ipv6.h" #endif /* NX_DISABLE_IPV6 */ -#include "asc_security_core/configuration.h" -#include "asc_security_core/collectors/network_activity.h" #include "asc_security_core/logger.h" +#include "asc_security_core/collector.h" +#include "asc_security_core/components_factory_declarations.h" +#include "asc_security_core/components_manager.h" +#include "asc_security_core/serializer.h" #include "asc_security_core/utils/itime.h" #include "asc_security_core/utils/notifier.h" +#include "asc_security_core/serializer.h" #include "iot_security_module/model/objects/object_network_activity_ext.h" @@ -84,7 +89,7 @@ static void _append_ipv6_payload_to_list(network_activity_ipv6_t *data_ptr, void * * @return network_activity_t* */ -static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, byte_order_t ip_header_byte_order); +static network_activity_ipv6_t *_ipv6_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr_st, UINT direction, byte_order_t ip_header_byte_order); #endif /* NX_DISABLE_IPV6 */ /** @@ -94,7 +99,7 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, * @param direction The direction of the packet (NX_IP_PACKET_IN / NX_IP_PACKET_OUT) * @param ip_header_byte_order The byte order of the IP header */ -static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direction, byte_order_t ip_header_byte_order); +static VOID _collector_network_activity_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction, byte_order_t ip_header_byte_order); /** * @brief Initialize the port layer of the network activity collector. @@ -111,7 +116,7 @@ static asc_result_t _collector_network_activity_port_init(); * * @return NX_SUCCESS **/ -static UINT _collector_network_activity_port_ip_callback(VOID* ip_packet, UINT direction); +static UINT _collector_network_activity_port_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction); #ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY /** @@ -144,13 +149,6 @@ static VOID _collector_network_activity_port_icmp_callback(struct NX_IP_STRUCT * **/ static VOID _collector_network_activity_port_deinit(); -/** - * @brief Function which used in order to free a specific collector. - * - * @param collector_internal_ptr A handle to the collector internal to deinitialize. - */ -static void _collector_network_activity_deinit(collector_internal_t *collector_internal_ptr); - /** * @brief Serialize events from the collector * @@ -179,22 +177,22 @@ static nx_ip_transport_packet_receive_cb_t _udp_packet_receive_original = NULL; static nx_ip_transport_packet_receive_cb_t _icmp_packet_receive_original = NULL; #endif /* ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY */ -static collector_internal_t *_collector_internal_ptr = NULL; +static asc_result_t _cm_init(component_id_t id); +static asc_result_t _cm_start(component_id_t id); +static asc_result_t _cm_stop(component_id_t id); +COLLECTOR_OPS_DEFINITIONS(, _cm_init, collector_default_deinit, collector_default_subscribe, collector_default_unsubscribe, _cm_start, _cm_stop); -asc_result_t collector_network_activity_init(collector_internal_t *collector_internal_ptr) -{ - if (_collector_internal_ptr != NULL) - { - return ASC_RESULT_OK; - } +COMPONENTS_FACTORY_DEFINITION(NetworkActivity, &_ops) - if (collector_internal_ptr == NULL) - { - log_error("Could not initialize collector_network_activity, bad argument"); - return ASC_RESULT_BAD_ARGUMENT; - } +static asc_result_t _cm_init(component_id_t id) +{ + return collector_default_create(id, NetworkActivity, COLLECTOR_PRIORITY_HIGH, + _collector_network_activity_serialize_events, ASC_HIGH_PRIORITY_INTERVAL, NULL); +} +static asc_result_t _cm_start(component_id_t id) +{ hashset_network_activity_ipv4_t_init(_ipv4_hashtables[0]); hashset_network_activity_ipv4_t_init(_ipv4_hashtables[1]); _current_ipv4_hashtable_index = 0; @@ -206,34 +204,11 @@ asc_result_t collector_network_activity_init(collector_internal_t *collector_int _current_ipv6_hashtable_index = 0; _current_ipv6_hashtable = _ipv6_hashtables[_current_ipv6_hashtable_index]; #endif /* NX_DISABLE_IPV6 */ - - _collector_internal_ptr = collector_internal_ptr; - - _collector_internal_ptr->collect_function = _collector_network_activity_serialize_events; - _collector_internal_ptr->deinit_function = _collector_network_activity_deinit; - _collector_internal_ptr->priority = COLLECTOR_PRIORITY_HIGH; - _collector_internal_ptr->state = NULL; - _collector_internal_ptr->type = COLLECTOR_TYPE_NETWORK_ACTIVITY; - - if (_collector_network_activity_port_init() != ASC_RESULT_OK) - { - _collector_network_activity_deinit(_collector_internal_ptr); - } - else - { - notifier_notify(NOTIFY_TOPIC_SYSTEM, NOTIFY_MESSAGE_SYSTEM_CONFIGURATION, _collector_internal_ptr); - } - - return ASC_RESULT_OK; + return _collector_network_activity_port_init(); } -static void _collector_network_activity_deinit(collector_internal_t *collector_internal_ptr) +static asc_result_t _cm_stop(component_id_t id) { - if (_collector_internal_ptr == NULL) - { - return; - } - _collector_network_activity_port_deinit(); _current_ipv4_hashtable = NULL; @@ -246,7 +221,7 @@ static void _collector_network_activity_deinit(collector_internal_t *collector_i hashset_network_activity_ipv6_t_clear(_ipv6_hashtables[1], network_activity_ipv6_deinit, NULL); #endif /* NX_DISABLE_IPV6 */ - _collector_internal_ptr = NULL; + return ASC_RESULT_OK; } static asc_result_t _collector_network_activity_serialize_events(collector_internal_t *collector_internal_ptr, serializer_t *serializer) @@ -261,15 +236,7 @@ static asc_result_t _collector_network_activity_serialize_events(collector_inter network_activity_ipv6_t **previous_ipv6_hashtable = NULL; #endif /* NX_DISABLE_IPV6 */ - uint32_t current_time; - uint32_t collection_interval; - - if (_collector_internal_ptr == NULL) - { - log_error("collector uninitialized, cannot collect"); - result = ASC_RESULT_UNINITIALIZED; - goto cleanup; - } + unsigned long current_time; if (serializer == NULL) { @@ -279,7 +246,6 @@ static asc_result_t _collector_network_activity_serialize_events(collector_inter } current_time = itime_time(NULL); - collection_interval = g_collector_collections_intervals[collector_internal_ptr->priority]; previous_ipv4_hashtable = _current_ipv4_hashtable; #ifndef NX_DISABLE_IPV6 @@ -293,7 +259,7 @@ static asc_result_t _collector_network_activity_serialize_events(collector_inter hashset_network_activity_ipv6_t_clear(previous_ipv6_hashtable, _append_ipv6_payload_to_list, &ipv6_list); #endif /* NX_DISABLE_IPV6 */ - result = serializer_event_add_network_activity(serializer, current_time, collection_interval, ipv4_list, ipv6_list); + result = serializer_event_add_network_activity(serializer, current_time, collector_internal_ptr->interval, ipv4_list, ipv6_list); /* Release all IPv4 objects. */ while (ipv4_list != NULL) @@ -338,7 +304,7 @@ static asc_result_t _collector_network_activity_port_init() while (created_count--) { - nx_ip_ptr->nx_ip_packet_filter = _collector_network_activity_port_ip_callback; + nx_ip_ptr->nx_ip_packet_filter_extended = _collector_network_activity_port_ip_callback; #ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY if (nx_ip_ptr->nx_ip_tcp_packet_receive) @@ -368,7 +334,7 @@ static asc_result_t _collector_network_activity_port_init() } -static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT direction) +static UINT _collector_network_activity_port_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction) { #ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY /* Incoming packets are captured on the transport layer */ @@ -377,8 +343,7 @@ static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT d return NX_SUCCESS; } #endif - - _collector_network_activity_ip_callback(ip_packet, direction, BYTE_ORDER_NETWORK); + _collector_network_activity_ip_callback(ip_ptr, packet_ptr, direction, BYTE_ORDER_NETWORK); /* return NX_SUCCESS, otherwise NetX will drop the packet */ return NX_SUCCESS; @@ -388,7 +353,7 @@ static UINT _collector_network_activity_port_ip_callback(VOID *ip_packet, UINT d #ifdef ASC_COLLECTOR_NETWORK_ACTIVITY_CAPTURE_UNICAST_ONLY static VOID _collector_network_activity_port_tcp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr) { - _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST); + _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST); if (_tcp_packet_receive_original) { @@ -399,7 +364,7 @@ static VOID _collector_network_activity_port_tcp_callback(struct NX_IP_STRUCT *i static VOID _collector_network_activity_port_udp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr) { - _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST); + _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST); if (_udp_packet_receive_original) { @@ -410,7 +375,7 @@ static VOID _collector_network_activity_port_udp_callback(struct NX_IP_STRUCT *i static VOID _collector_network_activity_port_icmp_callback(struct NX_IP_STRUCT *ip_ptr, struct NX_PACKET_STRUCT *packet_ptr) { - _collector_network_activity_ip_callback(packet_ptr->nx_packet_ip_header, NX_IP_PACKET_IN, BYTE_ORDER_HOST); + _collector_network_activity_ip_callback(ip_ptr, packet_ptr, NX_IP_PACKET_IN, BYTE_ORDER_HOST); if (_icmp_packet_receive_original) { @@ -568,8 +533,9 @@ static void _append_ipv6_payload_to_list(network_activity_ipv6_t *data_ptr, void } -static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, byte_order_t ip_header_byte_order) +static network_activity_ipv6_t *_ipv6_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr_st, UINT direction, byte_order_t ip_header_byte_order) { + VOID * ip_packet = packet_ptr_st->nx_packet_ip_header; network_activity_ipv6_t *result = network_activity_ipv6_init(); if (result == NULL) { @@ -586,7 +552,6 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, uint16_t payload_length = (uint16_t)(ip_header_word_1 >> 16); uint16_t header_length = 40; packet_ptr += header_length; - bool found_transport_header = false; /* @@ -630,11 +595,17 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, } payload_length = (uint16_t)(payload_length - header_length); - packet_ptr += header_length; if (!found_transport_header) { next_header_type = (uint8_t)(ip_header_word_0 >> 24); } + + if ((ALIGN_TYPE)(packet_ptr + header_length) >= (ALIGN_TYPE)(packet_ptr_st ->nx_packet_append_ptr)) + { + network_activity_ipv6_deinit(result, NULL); + return NULL; + } + packet_ptr += header_length; } while (!found_transport_header); @@ -703,8 +674,9 @@ static network_activity_ipv6_t *_ipv6_callback(VOID *ip_packet, UINT direction, #endif -static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direction, byte_order_t ip_header_byte_order) +static VOID _collector_network_activity_ip_callback(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction, byte_order_t ip_header_byte_order) { + VOID * ip_packet = packet_ptr->nx_packet_ip_header; uint32_t ip_header_word_0 = (ip_header_byte_order == BYTE_ORDER_NETWORK) ? ntohl(*(uint32_t *)ip_packet) : *(uint32_t *)ip_packet; uint8_t version = (uint8_t)(ip_header_word_0 >> 28); @@ -719,7 +691,7 @@ static void _collector_network_activity_ip_callback(VOID* ip_packet, UINT direct else if (version == NX_IP_VERSION_V6) { #ifndef NX_DISABLE_IPV6 - network_activity_ipv6_t *ipv6_object = _ipv6_callback(ip_packet, direction, ip_header_byte_order); + network_activity_ipv6_t *ipv6_object = _ipv6_callback(ip_ptr, packet_ptr, direction, ip_header_byte_order); if (ipv6_object != NULL) { hashset_network_activity_ipv6_t_add_or_update(_current_ipv6_hashtable, ipv6_object); diff --git a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_system_information.c b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_system_information.c index 800d0afd..d75dd88b 100644 --- a/addons/azure_iot/azure_iot_security_module/src/collectors/collector_system_information.c +++ b/addons/azure_iot/azure_iot_security_module/src/collectors/collector_system_information.c @@ -9,61 +9,44 @@ /* */ /**************************************************************************/ +#include + #include "nx_api.h" #include "tx_api.h" #include "asc_security_core/logger.h" +#include "asc_security_core/collector.h" +#include "asc_security_core/components_factory_declarations.h" +#include "asc_security_core/components_manager.h" #include "asc_security_core/serializer.h" +#include "asc_security_core/utils/itime.h" #include "asc_security_core/utils/notifier.h" +#include "asc_security_core/utils/num2str.h" -#include "asc_security_core/collectors/system_information.h" - -#undef STR_AUX -#undef STR -#define STR_AUX(x) #x -#define STR(x) STR_AUX(x) #define OS_NAME "Azure RTOS " -#define OS_INFO OS_NAME STR(THREADX_MAJOR_VERSION) "." STR(THREADX_MINOR_VERSION) +#define OS_INFO OS_NAME NUM_2_STR(THREADX_MAJOR_VERSION) "." NUM_2_STR(THREADX_MINOR_VERSION) -static void _collector_system_information_deinit(collector_internal_t *collector_internal_ptr); static asc_result_t _collector_system_information_serialize_events(collector_internal_t *collector_internal_ptr, serializer_t *serializer); static asc_result_t _collect_operation_system_information(collector_internal_t *collector_internal_ptr, system_information_t *data_ptr); -asc_result_t collector_system_information_init(collector_internal_t *collector_internal_ptr) -{ - if (collector_internal_ptr == NULL) - { - log_error("Could not initialize collector_system_information, bad argument"); - return ASC_RESULT_BAD_ARGUMENT; - } - memset(collector_internal_ptr, 0, sizeof(*collector_internal_ptr)); - collector_internal_ptr->type = COLLECTOR_TYPE_SYSTEM_INFORMATION; - collector_internal_ptr->priority = COLLECTOR_PRIORITY_LOW; - collector_internal_ptr->collect_function = _collector_system_information_serialize_events; - collector_internal_ptr->deinit_function = _collector_system_information_deinit; +static asc_result_t _cm_init(component_id_t id); - notifier_notify(NOTIFY_TOPIC_SYSTEM, NOTIFY_MESSAGE_SYSTEM_CONFIGURATION, collector_internal_ptr); +COLLECTOR_OPS_DEFINITIONS(, _cm_init, collector_default_deinit, + collector_default_subscribe, collector_default_unsubscribe, collector_default_start, collector_default_stop); - return ASC_RESULT_OK; -} +COMPONENTS_FACTORY_DEFINITION(SystemInformation, &_ops) -static void _collector_system_information_deinit(collector_internal_t *collector_internal_ptr) +static asc_result_t _cm_init(component_id_t id) { - if (collector_internal_ptr == NULL) - { - log_error("Could not deinitialize collector_system_information, bad argument"); - return; - } - - memset(collector_internal_ptr, 0, sizeof(*collector_internal_ptr)); + return collector_default_create(id, SystemInformation, COLLECTOR_PRIORITY_LOW, + _collector_system_information_serialize_events, ASC_LOW_PRIORITY_INTERVAL, NULL); } static asc_result_t _collector_system_information_serialize_events(collector_internal_t *collector_internal_ptr, serializer_t *serializer) { asc_result_t result = ASC_RESULT_OK; system_information_t system_information; - uint32_t current_time; - uint32_t collection_interval; + unsigned long current_time; memset(&system_information, 0, sizeof(system_information_t)); @@ -77,9 +60,7 @@ static asc_result_t _collector_system_information_serialize_events(collector_int } current_time = itime_time(NULL); - collection_interval = g_collector_collections_intervals[collector_internal_ptr->priority]; - - result = serializer_event_add_system_information(serializer, current_time, collection_interval, &system_information); + result = serializer_event_add_system_information(serializer, current_time, collector_internal_ptr->interval, &system_information); cleanup: if (result != ASC_RESULT_OK) diff --git a/addons/azure_iot/azure_iot_security_module/src/model/objects/object_network_activity_ext.c b/addons/azure_iot/azure_iot_security_module/src/model/objects/object_network_activity_ext.c index 3dca1b99..5dcd82bf 100644 --- a/addons/azure_iot/azure_iot_security_module/src/model/objects/object_network_activity_ext.c +++ b/addons/azure_iot/azure_iot_security_module/src/model/objects/object_network_activity_ext.c @@ -8,9 +8,10 @@ /* and in the root directory of this software. */ /* */ /**************************************************************************/ - #include +#include + #include "nx_api.h" #include "nx_ip.h" #include "nx_ipv6.h" @@ -26,12 +27,12 @@ HASHSET_DEFINITIONS(network_activity_ipv4_t, IPV4_HASHSET_SIZE) network_activity_ipv4_t *network_activity_ipv4_init() { - return object_pool_network_activity_ipv4_t_get(); + return object_pool_get(network_activity_ipv4_t); } void network_activity_ipv4_deinit(network_activity_ipv4_t *network_activity_ipv4, void *context) { - object_pool_network_activity_ipv4_t_free(network_activity_ipv4); + object_pool_free(network_activity_ipv4_t, network_activity_ipv4); } @@ -72,7 +73,7 @@ void hashset_network_activity_ipv4_t_update(network_activity_ipv4_t *old_data, n { old_data->common.bytes_in += new_data->common.bytes_in; old_data->common.bytes_out += new_data->common.bytes_out; - object_pool_network_activity_ipv4_t_free(new_data); + object_pool_free(network_activity_ipv4_t, new_data); } @@ -83,13 +84,13 @@ HASHSET_DEFINITIONS(network_activity_ipv6_t, IPV6_HASHSET_SIZE) network_activity_ipv6_t *network_activity_ipv6_init() { - return object_pool_network_activity_ipv6_t_get(); + return object_pool_get(network_activity_ipv6_t); } void network_activity_ipv6_deinit(network_activity_ipv6_t *network_activity_ipv6, void *context) { - object_pool_network_activity_ipv6_t_free(network_activity_ipv6); + object_pool_free(network_activity_ipv6_t, network_activity_ipv6); } @@ -130,6 +131,6 @@ void hashset_network_activity_ipv6_t_update(network_activity_ipv6_t *old_data, n { old_data->common.bytes_in += new_data->common.bytes_in; old_data->common.bytes_out += new_data->common.bytes_out; - object_pool_network_activity_ipv6_t_free(new_data); + object_pool_free(network_activity_ipv6_t, new_data); } #endif /* NX_DISABLE_IPV6 */ \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iuuid.h b/addons/azure_iot/azure_iot_security_module/src/utils/ievent_loop.c similarity index 71% rename from addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iuuid.h rename to addons/azure_iot/azure_iot_security_module/src/utils/ievent_loop.c index b4907096..4f9146d5 100644 --- a/addons/azure_iot/azure_iot_security_module/iot-security-module-core/inc/asc_security_core/utils/iuuid.h +++ b/addons/azure_iot/azure_iot_security_module/src/utils/ievent_loop.c @@ -9,21 +9,12 @@ /* */ /**************************************************************************/ -#ifndef IUUID_H -#define IUUID_H +#include -#include +#include "asc_security_core/utils/event_loop_be.h" +#include "asc_security_core/utils/ievent_loop.h" - -/** - * @brief Generate a binary uuid - * @note: not thread-safe. - * - * @param buf - The buffer to write the UUID to. Size should be at least 16 bytes. - * - * @return 0 on sucess, -1 otherwise - */ -int iuuid_generate(uint8_t *buf); - - -#endif /* IUUID_H */ \ No newline at end of file +ievent_loop_t *ievent_loop_get_instance(void) +{ + return event_loop_be_instance_attach(); +} \ No newline at end of file diff --git a/addons/azure_iot/azure_iot_security_module/src/utils/irand.c b/addons/azure_iot/azure_iot_security_module/src/utils/irand.c index 5aba8b8a..810516de 100644 --- a/addons/azure_iot/azure_iot_security_module/src/utils/irand.c +++ b/addons/azure_iot/azure_iot_security_module/src/utils/irand.c @@ -9,6 +9,8 @@ /* */ /**************************************************************************/ +#include + #include "nx_api.h" #include "asc_security_core/utils/irand.h" diff --git a/addons/azure_iot/azure_iot_security_module/src/utils/itime.c b/addons/azure_iot/azure_iot_security_module/src/utils/itime.c index b3026798..7fbe0e43 100644 --- a/addons/azure_iot/azure_iot_security_module/src/utils/itime.c +++ b/addons/azure_iot/azure_iot_security_module/src/utils/itime.c @@ -1,3 +1,17 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ +#include + +#include + #include "asc_security_core/utils/itime.h" static unix_time_callback_t _time_callback = NULL; @@ -7,11 +21,11 @@ void itime_init(unix_time_callback_t time_callback) _time_callback = time_callback; } -uint32_t itime_time(uint32_t *timer) +unsigned long itime_time(unsigned long *timer) { if (_time_callback == NULL) { - return (uint32_t)-1; + return ITIME_FAILED; } return _time_callback(timer); diff --git a/addons/azure_iot/azure_iot_security_module/src/utils/os_utils.c b/addons/azure_iot/azure_iot_security_module/src/utils/os_utils.c index e1b4a7d1..ee4f0994 100644 --- a/addons/azure_iot/azure_iot_security_module/src/utils/os_utils.c +++ b/addons/azure_iot/azure_iot_security_module/src/utils/os_utils.c @@ -9,7 +9,8 @@ /* */ /**************************************************************************/ -#include "asc_security_core/configuration.h" +#include + #include "asc_security_core/utils/os_utils.h" const char *os_utils_get_security_module_id() diff --git a/addons/azure_iot/docs/README.md b/addons/azure_iot/docs/README.md deleted file mode 100644 index d3c59c2f..00000000 --- a/addons/azure_iot/docs/README.md +++ /dev/null @@ -1,120 +0,0 @@ -# Azure IoT Middleware for Azure RTOS - -Azure IoT Middleware for Azure RTOS is a platform specific library that acts as a binding layer between the Azure RTOS and the [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c/tree/master/sdk/docs/iot). Goals of this layer are following: - -* Expose smart client interfaces (IoTHub_Client, DeviceProvisioning_Client) for the customers, to be consumed in their application. -* Orchestrate the interaction between Embedded C SDK and platform. -* Provide Azure RTOS platform initialization. -* IoT Plug and Play support. -* Security capabilities. -* Resource limitation aware. -* Protocol support. - -## Getting Started - -Azure IoT Middleware for Azure RTOS stays as an addon for the Azure RTOS NetXDuo. It facilitates the MQTT and TLS stacks that have been provided in the NetXDuo. - -![diagram](./img/diagram.png) - -### Build - -The Azure IoT Middleware for Azure RTOS is built as part of the NetXDuo. Make sure you have defined the following *marcos* when building it: - -Module | Marcos | -| --- | --- | -| Azure IoT Middleware for Azure RTOS | `NX_ENABLE_EXTENDED_NOTIFY_SUPPORT`
`NX_SECURE_ENABLE`
`NXD_MQTT_CLOUD_ENABLE` -| Azure Defender for IoT security module | `NX_ENABLE_IP_PACKET_FILTER` - -**NOTE:** Azure Defender for IoT security module is enabled by default. You can define `NX_AZURE_DISABLE_IOT_SECURITY_MODULE` to disable it. [Learn more](#azure-defender-for-iot-security-module). - -Follow [this example](/ports/cortex_m7/iar/inc/nx_port.h) to see how to define these *marcos* in the header file. - -### Samples - -For complete samples on how to get started on different devices with Azure IoT Middleware for Azure RTOS, see the following samples: - -Manufacturer | Device | Samples | -| --- | --- | --- | -| Microchip | [ATSAME54-XPRO](https://www.microchip.com/developmenttools/productdetails/atsame54-xpro) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/Microchip/ATSAME54-XPRO) • [IAR](https://aka.ms/azrtos-sample/e54-iar) • [MPLAB](https://aka.ms/azrtos-sample/e54-mplab) -| MXCHIP | [AZ3166](https://aka.ms/iot-devkit) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/MXChip/AZ3166) -| NXP | [MIMXRT1060-EVK](https://www.nxp.com/design/development-boards/i-mx-evaluation-and-development-boards/mimxrt1060-evk-i-mx-rt1060-evaluation-kit:MIMXRT1060-EVK) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/NXP/MIMXRT1060-EVK) • [IAR](https://aka.ms/azrtos-sample/rt1060-iar) • [MCUXpresso](https://aka.ms/azrtos-sample/rt1060-mcuxpresso) -| STMicroelectronics | [STM32F746GDISCOVERY](https://www.st.com/en/evaluation-tools/32f746gdiscovery.html) | [IAR](https://aka.ms/azrtos-sample/f746g-iar) • [STM32Cube](https://aka.ms/azrtos-sample/f746g-cubeide) -| STMicroelectronics | [B-L4S5I-IOT01](https://www.st.com/en/evaluation-tools/b-l4s5i-iot01a.html) / [B-L475E-IOT01](https://www.st.com/en/evaluation-tools/b-l475e-iot01a.html) | [GCC/CMake](https://github.com/azure-rtos/getting-started/tree/master/STMicroelectronics/STM32L4_L4%2B) • [IAR](https://aka.ms/azrtos-sample/l4s5-iar) • [STM32Cube](https://aka.ms/azrtos-sample/l4s5-cubeide) - -## Features - -Basic features provided by [Azure SDK for Embedded C](https://github.com/Azure/azure-sdk-for-c/tree/master/sdk/docs/iot): -* Connect to IoTHub via MQTT. -* Send device to cloud (D2C) message. -* Receive cloud to device (C2D) message. -* Device Twins. -* Receive direct method. -* Authentication: SAS Token. - -Enhanced features provided in middleware: -* Authentication: X.509 client certificate. -* Device Provisioning Service. -* JSON parser. - -## Azure Defender for IoT security module - -The [Azure Defender for IoT security module](https://docs.microsoft.com/azure/defender-for-iot/iot-security-azure-rtos) provides a comprehensive security solution for Azure RTOS devices. The middleware ships with the ASC for IoT Security Module built-in and enabled by default to detect common threats and potential malicious activities. - -### Opt-out - -To disable (opt-out) the module for your application, you can choose one of these two options: -* Define `NX_AZURE_DISABLE_IOT_SECURITY_MODULE` in NetXDuo header file such as [`nx_port.h`](/ports/cortex_m7/iar/inc/nx_port.h) when building the middleware. -* Call [`UINT nx_azure_iot_security_module_disable(NX_AZURE_IOT *nx_azure_iot_ptr)`](https://docs.microsoft.com/azure/defender-for-iot/azure-rtos-security-module-api#disable-azure-iot-security-module) in your application code. - -### Data collection - -By enabling the module, it analyzes inbound and outbound network activity on IPv4 and IPv6 supported protocols: -* TCP -* UDP -* ICMP - -And with below data collected: -* Local and remote address -* Local and remote port -* Bytes in -* Bytes out - -### Resource requirements: - -ASC for IoT module leverages existing Azure RTOS resources, and sends security messages in the background, without interfering with the user application, using the same connection to the IoT Hub. - -The extra resource it will take on device and connection: - -**Memory Footprint** (using default config - 4 unique monitored connection in IPv4 in an hour): -Toolchain | RAM | ROM | -| --- | --- | --- | -| IAR Embedded Workbench (iccarm) | 4Kb | 10Kb -| GUN ARM Embedded Toolchain (arm-gcc) | 4Kb | 13Kb - -**Additional Connection**: -Connection Type | RAM | Network | -| --- | --- | --- | -| IPv4 | 52bytes | 36bytes -| IPv6 | 200bytes | 60bytes - -So the total additional connection traffic will be: -*Total (in bytes) = Metadata (e.g. 300 bytes) + IPv4 Connections * 36 + IPv6 Connections * 60* - -Learn [here](https://docs.microsoft.com/en-us/azure/defender-for-iot) for more information about Azure Defender for IoT. - -## APIs - -* [nx_azure_iot](./azure_rtos_iot.md) -* [nx_azure_iot_hub_client](./azure_rtos_iot_hub_client.md) -* [nx_azure_iot_provisioning_client](./azure_rtos_iot_provisioning_client.md) -* [nx_azure_iot_json](./azure_rtos_iot_json.md) -* [nx_azure_iot_security_module](../azure_iot_security_module/docs/nx_azure_iot_security_module.md) - -## Need Help? - -* File an issue via [Github Issues](https://github.com/azure-rtos/netxduo/issues/new/choose). -* Check [previous questions](https://stackoverflow.com/questions/tagged/azure-rtos+netxduo) or ask new ones on StackOverflow using the [azure-rtos](https://stackoverflow.com/questions/tagged/azure-rtos) and [netxduo](https://stackoverflow.com/questions/tagged/netxduo) tags. - -## Licensing - -View [Licensing](https://github.com/azure-rtos/netxduo#licensing) of Azure RTOS NetXDuo. diff --git a/addons/azure_iot/docs/azure_rtos_iot_adu_agent.md b/addons/azure_iot/docs/azure_rtos_iot_adu_agent.md new file mode 100644 index 00000000..6ad46443 --- /dev/null +++ b/addons/azure_iot/docs/azure_rtos_iot_adu_agent.md @@ -0,0 +1,193 @@ +# Azure IoT ADU Agent + +**nx_azure_iot_adu_agent_start** +*** +
Start Azure IoT ADU agent.
+ +**Prototype** +```c +UINT nx_azure_iot_adu_agent_start(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_update_notify)(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UCHAR *provider, UINT provider_length, + UCHAR *name, UINT name_length, + UCHAR *version, UINT version_length), + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +``` +**Description** + +

This routine starts the ADU agent. Properties (manufacturer and model) of a device this update is compatible with. Installed criteria is used to determine if the update is installed or not, typically it is a version string (1.0.0). The installed criteria may be set into adu agent, then agent will check the update internally, otherwise, adu agent will set NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK command to let driver (adu_agent_driver) do the check.

+ +**Parameters** + +| Name | Description | +| - |:-| +| adu_agent_ptr [in] | A pointer to a `NX_AZURE_IOT_ADU_AGENT`. | +| iothub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`.| +| manufacturer [in] | A pointer to the manufacturer. Must be NULL terminated string. | +| manufacturer_length [in] | Length of the manufacturer. | +| model [in] | A pointer to the model. Must be NULL terminated string. | +| model_length [in] | Length of the model. | +| installed_criteria [in] | A pointer to the installed criteria string, such as: version string. Must be NULL terminated string. | +| installed_criteria_length [in] | Length of the installed_criteria. | +| adu_agent_update_notify [in] | Pointer to a callback function invoked once update is received. | +| adu_agent_driver [in] | User supplied driver for flash operation. | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully started the Azure IoT ADU agent. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to start the Azure IoT ADU agent due to invalid parameter. +* NX_AZURE_IOT_NO_AVAILABLE_CIPHER Fail to start the Azure IoT ADU agent due to no available cipher. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to start the Azure IoT ADU agent due to insufficient buffer space. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_adu_agent_proxy_update_add** +*** +
Add proxy update on device update agent.
+ +**Prototype** +```c +UINT nx_azure_iot_adu_agent_proxy_update_add(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +``` +**Description** + +

This routine adds the proxy update on device update agent. Properties (manufacturer and model) of a device this update is compatible with, installed criteria is used to check if the update is installed or not, the installed criteria may be version string. If the installed criteria is set into adu agent, the agent will check the update, otherwise, adu agent will call NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK to driver, then the adu_agent_driver must implement NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK command to check if the update is installed or not according to the installed criteria.

+ +**Parameters** + +| Name | Description | +| - |:-| +| adu_agent_ptr [in] | A pointer to a `NX_AZURE_IOT_ADU_AGENT`. | +| manufacturer [in] | A pointer to the manufacturer. Must be NULL terminated string. | +| manufacturer_length [in] | Length of the manufacturer. | +| model [in] | A pointer to the model. Must be NULL terminated string. | +| model_length [in] | Length of the model. | +| installed_criteria [in] | A pointer to the installed criteria string, such as: version string. Must be NULL terminated string. | +| installed_criteria_length [in] | Length of the installed_criteria. | +| adu_agent_driver [in] | User supplied driver for flash operation. | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully started the Azure IoT ADU agent. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to start the Azure IoT ADU agent due to invalid parameter. +* NX_AZURE_IOT_NO_MORE_ENTRIES Fail to start the Azure IoT ADU agent due to no more entries. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_adu_agent_stop** +*** +
Stop Azure IoT ADU agent.
+ +**Prototype** +```c +UINT nx_azure_iot_adu_agent_stop(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +``` +**Description** + +

This routine stops the ADU agent.

+ +**Parameters** +| | | +| - |:-| +| adu_agent_ptr [in] | A pointer to a `NX_AZURE_IOT_ADU_AGENT` | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully stopped the Azure IoT ADU agent. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to stop the Azure IoT ADU agent due to invalid parameter. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_adu_agent_update_download_and_install** +*** +
Start to download and install the new update.
+ +**Prototype** +```c +UINT nx_azure_iot_adu_agent_update_download_and_install(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +``` +**Description** + +

The routine starts to download and install the new update.

+ +**Parameters** +| | | +| - |:-| +| adu_agent_ptr [in] | A pointer to a `NX_AZURE_IOT_ADU_AGENT` | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully started to download and install the new update. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to download and install the new update due to invalid parameter. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_adu_agent_update_apply** +*** +
Start to apply the new update.
+ +**Prototype** +```c +UINT nx_azure_iot_adu_agent_update_apply(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +``` +**Description** + +

The routine starts to apply the new update. The device may reboot after applying the update successfully.

+ +**Parameters** +| | | +| - |:-| +| adu_agent_ptr [in] | A pointer to a `NX_AZURE_IOT_ADU_AGENT` | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully started to apply the new update. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to apply the new update due to invalid parameter. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
diff --git a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md index ea912887..e3297bd7 100644 --- a/addons/azure_iot/docs/azure_rtos_iot_hub_client.md +++ b/addons/azure_iot/docs/azure_rtos_iot_hub_client.md @@ -1,6 +1,72 @@ # Azure IoT Hub Client -**nx_azure_iot_hub_client_initialize** +## APIs: + +### Connect + +* [nx_azure_iot_hub_client_initialize](#nx_azure_iot_hub_client_initialize) +* [nx_azure_iot_hub_client_deinitialize](#nx_azure_iot_hub_client_deinitialize) +* [nx_azure_iot_hub_client_model_id_set](#nx_azure_iot_hub_client_model_id_set) +* [nx_azure_iot_hub_client_component_add](#nx_azure_iot_hub_client_component_add) +* [nx_azure_iot_hub_client_trusted_cert_add](#nx_azure_iot_hub_client_trusted_cert_add) +* [nx_azure_iot_hub_client_device_cert_set](#nx_azure_iot_hub_client_device_cert_set) +* [nx_azure_iot_hub_client_symmetric_key_set](#nx_azure_iot_hub_client_symmetric_key_set) +* [nx_azure_iot_hub_client_websocket_enable](#nx_azure_iot_hub_client_websocket_enable) +* [nx_azure_iot_hub_client_connect](#nx_azure_iot_hub_client_connect) +* [nx_azure_iot_hub_client_disconnect](#nx_azure_iot_hub_client_disconnect) +* [nx_azure_iot_hub_client_connection_status_callback_set](#nx_azure_iot_hub_client_connection_status_callback_set) +* [nx_azure_iot_hub_client_receive_callback_set](#nx_azure_iot_hub_client_receive_callback_set) + +### C2D + +* [nx_azure_iot_hub_client_cloud_message_enable](#nx_azure_iot_hub_client_cloud_message_enable) +* [nx_azure_iot_hub_client_cloud_message_disable](#nx_azure_iot_hub_client_cloud_message_disable) +* [nx_azure_iot_hub_client_cloud_message_receive](#nx_azure_iot_hub_client_cloud_message_receive) +* [nx_azure_iot_hub_client_cloud_message_property_get](#nx_azure_iot_hub_client_cloud_message_property_get) + +### Telemetry + +* [nx_azure_iot_hub_client_telemetry_message_create](#nx_azure_iot_hub_client_telemetry_message_create) +* [nx_azure_iot_hub_client_telemetry_message_delete](#nx_azure_iot_hub_client_telemetry_message_delete) +* [nx_azure_iot_hub_client_telemetry_component_set](#nx_azure_iot_hub_client_telemetry_component_set) +* [nx_azure_iot_hub_client_telemetry_property_add](#nx_azure_iot_hub_client_telemetry_property_add) +* [nx_azure_iot_hub_client_telemetry_send](#nx_azure_iot_hub_client_telemetry_send) + +### Command + +* [nx_azure_iot_hub_client_command_enable](#nx_azure_iot_hub_client_command_enable) +* [nx_azure_iot_hub_client_command_disable](#nx_azure_iot_hub_client_command_disable) +* [nx_azure_iot_hub_client_command_message_receive](#nx_azure_iot_hub_client_command_message_receive) +* [nx_azure_iot_hub_client_command_message_response](#nx_azure_iot_hub_client_command_message_response) + +### Direct Method + +* [nx_azure_iot_hub_client_direct_method_enable](#nx_azure_iot_hub_client_direct_method_enable) +* [nx_azure_iot_hub_client_direct_method_disable](#nx_azure_iot_hub_client_direct_method_disable) +* [nx_azure_iot_hub_client_direct_method_message_receive](#nx_azure_iot_hub_client_direct_method_message_receive) +* [nx_azure_iot_hub_client_direct_method_message_response](#nx_azure_iot_hub_client_direct_method_message_response) + +### Properties + +* [nx_azure_iot_hub_client_properties_enable](#nx_azure_iot_hub_client_properties_enable) +* [nx_azure_iot_hub_client_properties_disable](#nx_azure_iot_hub_client_properties_disable) +* [nx_azure_iot_hub_client_reported_properties_response_callback_set](#nx_azure_iot_hub_client_reported_properties_response_callback_set) +* [nx_azure_iot_hub_client_reported_properties_create](#nx_azure_iot_hub_client_reported_properties_create) +* [nx_azure_iot_hub_client_reported_properties_send](#nx_azure_iot_hub_client_reported_properties_send) +* [nx_azure_iot_hub_client_properties_request](#nx_azure_iot_hub_client_properties_request) +* [nx_azure_iot_hub_client_properties_receive](#nx_azure_iot_hub_client_properties_receive) +* [nx_azure_iot_hub_client_writable_properties_receive](#nx_azure_iot_hub_client_writable_properties_receive) + +### Device Twin + +* [nx_azure_iot_hub_client_device_twin_enable](#nx_azure_iot_hub_client_device_twin_enable) +* [nx_azure_iot_hub_client_device_twin_disable](#nx_azure_iot_hub_client_device_twin_disable) +* [nx_azure_iot_hub_client_device_twin_reported_properties_send](#nx_azure_iot_hub_client_device_twin_reported_properties_send) +* [nx_azure_iot_hub_client_device_twin_properties_request](#nx_azure_iot_hub_client_device_twin_properties_request) +* [nx_azure_iot_hub_client_device_twin_properties_receive](#nx_azure_iot_hub_client_device_twin_properties_receive) +* [nx_azure_iot_hub_client_device_twin_desired_properties_receive](#nx_azure_iot_hub_client_device_twin_desired_properties_receive) + +#### **nx_azure_iot_hub_client_initialize** ***
Initialize Azure IoT hub instance
@@ -55,7 +121,7 @@ Threads
-**nx_azure_iot_hub_client_deinitialize** +#### **nx_azure_iot_hub_client_deinitialize** ***
Cleanup the Azure IoT Hub
@@ -87,7 +153,42 @@ Threads
-**nx_azure_iot_hub_client_device_cert_set** +#### **nx_azure_iot_hub_client_trusted_cert_add** +*** +
Add trusted certificate
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_trusted_cert_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate); +``` +**Description** + +

This routine adds the trusted certificate. It can be called multiple times to set multiple trusted certificates.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT` | +| trusted_certificate [in] | A pointer to a `NX_SECURE_X509_CERT` | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully add trusted certificate to Azure IoT Hub Instance. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to add trusted certificate to Azure IoT Hub Instance due to invalid parameter. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add trusted certificate due to `NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS` is too small. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_device_cert_set** ***
Set client certificate
@@ -98,7 +199,7 @@ UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client ``` **Description** -

This routine sets the device certificate.

+

This routine sets the device certificate. It can be called multiple times to set certificate chain.

**Parameters** @@ -108,8 +209,9 @@ UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client | device_certificate [in] | A pointer to a `NX_SECURE_X509_CERT` | **Return Values** -* NX_AZURE_IOT_SUCCESS Successfully set device certificate to AZ IoT Hub Instance. -* NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certificate to AZ IoT Hub Instance due to invalid parameter. +* NX_AZURE_IOT_SUCCESS Successfully set device certificate to Azure IoT Hub Instance. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certificate to Azure IoT Hub Instance due to invalid parameter. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to set device certificate due to `NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS` is too small. **Allowed From** @@ -121,7 +223,7 @@ Threads
-**nx_azure_iot_hub_client_symmetric_key_set** +#### **nx_azure_iot_hub_client_symmetric_key_set** ***
Set symmetric key
@@ -156,7 +258,7 @@ Threads
-**nx_azure_iot_hub_client_model_id_set** +#### **nx_azure_iot_hub_client_model_id_set** ***
Set Device Twin model id in the IoT Hub client.
@@ -167,7 +269,7 @@ UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_pt ``` **Description** -

This routine sets the Device Twin model id. Note: THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE.

+

This routine sets the model id in the IoT Hub client to enable PnP.

**Parameters** @@ -191,7 +293,76 @@ Threads
-**nx_azure_iot_hub_client_connect** +#### **nx_azure_iot_hub_client_component_add** +*** +
Add component to IoT Hub client
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_component_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length); +``` +**Description** + +

This routine should be called for all the components in the IoT hub model.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT` | +| component_name_ptr [in] | A pointer to component, that is part of IoT hub model. | +| component_name_length [in] | Length of the `component_name_ptr`. | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully set device certificate to AZ IoT Hub Instance. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add the component name due to out of memory. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_websocket_enable** +*** +
Enables MQTT over WebSocket to connect to IoT Hub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_websocket_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +``` +**Description** + +

This routine enables MQTT over WebSocket to connect to the Azure IoT Hub.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT` | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if MQTT over Websocket is enabled. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to enable MQTT over WebSocket due to invalid parameter. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_connect** ***
Connects to IoT Hub
@@ -241,7 +412,7 @@ Threads
-**nx_azure_iot_hub_client_disconnect** +#### **nx_azure_iot_hub_client_disconnect** ***
Disconnects the client
@@ -274,7 +445,7 @@ Threads
-**nx_azure_iot_hub_client_connection_status_callback_set** +#### **nx_azure_iot_hub_client_connection_status_callback_set** ***
Sets connection status callback function
@@ -296,6 +467,7 @@ UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLI * NXD_MQTT_ERROR_SERVER_UNAVAILABLE * NXD_MQTT_ERROR_NOT_AUTHORIZED * NX_AZURE_IOT_DISCONNECTED +* NX_AZURE_IOT_SAS_TOKEN_EXPIRED **Parameters** @@ -319,7 +491,7 @@ Threads
-**nx_azure_iot_hub_client_receive_callback_set** +#### **nx_azure_iot_hub_client_receive_callback_set** ***
Sets receive callback function
@@ -333,7 +505,7 @@ UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_c ``` **Description** -

This routine sets the IoT Hub receive callback function. This callback function is invoked when a message is received from Azure IoT hub. Setting the callback function to NULL disables the callback function. Message types can be NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE, NX_AZURE_IOT_HUB_DIRECT_METHOD, NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES and NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES.

+

This routine sets the IoT Hub receive callback function. This callback function is invoked when a message is received from Azure IoT hub. Setting the callback function to NULL disables the callback function. Message types can be NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE, NX_AZURE_IOT_HUB_COMMAND, NX_AZURE_IOT_HUB_PROPERTIES, NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES, NX_AZURE_IOT_HUB_DIRECT_METHOD, NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES and NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES.

**Parameters** @@ -360,7 +532,7 @@ Threads
-**nx_azure_iot_hub_client_telemetry_message_create** +#### **nx_azure_iot_hub_client_telemetry_message_create** ***
Creates telemetry message
@@ -399,7 +571,7 @@ Threads
-**nx_azure_iot_hub_client_telemetry_message_delete** +#### **nx_azure_iot_hub_client_telemetry_message_delete** ***
Deletes telemetry message
@@ -431,7 +603,47 @@ Threads
-**nx_azure_iot_hub_client_telemetry_property_add** +#### **nx_azure_iot_hub_client_telemetry_component_set** +*** +
Sets component to telemetry message
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_telemetry_component_set(NX_PACKET *packet_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT wait_option)); +``` +**Description** + +

This routine allows an application to set a component name to a telemetry message before it is being sent. The component is stored in the sequence which the routine is called. The component must be set after a telemetry packet is created, and before the telemetry message is being sent.

+ +**Parameters** + +| Name | Description | +| - |:-| +| packet_ptr [in] | A pointer to telemetry component packet. | +| component_name_ptr [in] | A pointer to a component name. | +| component_name_length [in] | Length of component name. | +| wait_option [in] | Ticks to wait if packet needs to be expanded. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if component is set. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to set component due to invalid parameter. +* NX_NO_PACKET Fail to set component due to no available packet in pool. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_telemetry_property_add** ***
Adds property to telemetry message
@@ -473,7 +685,7 @@ Threads
-**nx_azure_iot_hub_client_telemetry_send** +#### **nx_azure_iot_hub_client_telemetry_send** ***
Sends telemetry message to IoTHub
@@ -515,7 +727,7 @@ Threads
-**nx_azure_iot_hub_client_cloud_message_enable** +#### **nx_azure_iot_hub_client_cloud_message_enable** ***
Enables receiving C2D message from IoTHub
@@ -551,7 +763,7 @@ Threads
-**nx_azure_iot_hub_client_cloud_message_disable** +#### **nx_azure_iot_hub_client_cloud_message_disable** ***
Disables receiving C2D message from IoTHub
@@ -587,7 +799,7 @@ Threads
-**nx_azure_iot_hub_client_cloud_message_receive** +#### **nx_azure_iot_hub_client_cloud_message_receive** ***
Receives C2D message from IoTHub
@@ -627,7 +839,7 @@ Threads
-**nx_azure_iot_hub_client_cloud_message_property_get** +#### **nx_azure_iot_hub_client_cloud_message_property_get** ***
Retrieve the property with given property name in the C2D message
@@ -670,7 +882,7 @@ Threads
-**nx_azure_iot_hub_client_direct_method_enable** +#### **nx_azure_iot_hub_client_direct_method_enable** ***
Enables receiving direct method messages from IoTHub
@@ -705,7 +917,7 @@ Threads
-**nx_azure_iot_hub_client_direct_method_disable** +#### **nx_azure_iot_hub_client_direct_method_disable** ***
Disables receiving direct method messages from IoTHub
@@ -741,7 +953,7 @@ Threads
-**nx_azure_iot_hub_client_direct_method_message_receive** +#### **nx_azure_iot_hub_client_direct_method_message_receive** ***
Receives direct method message from IoTHub
@@ -788,7 +1000,7 @@ Threads
-**nx_azure_iot_hub_client_direct_method_message_response** +#### **nx_azure_iot_hub_client_direct_method_message_response** ***
Return response to direct method message from IoTHub
@@ -829,10 +1041,178 @@ Threads **See Also** +
+ +#### **nx_azure_iot_hub_client_command_enable** +*** +
Enables receiving command messages from IoTHub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_command_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +``` +**Description** + +

This routine enables receiving command messages from IoT Hub.

+ +**Parameters** +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT` | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if command message receiving is enabled. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to enable command message receiving due to invalid parameter. +* NXD_MQTT_NOT_CONNECTED Fail to enable command message receiving due to MQTT not connected. +* NXD_MQTT_PACKET_POOL_FAILURE Fail to enable command message receiving due to no available packet in pool. +* NXD_MQTT_COMMUNICATION_FAILURE Fail to enable command message receiving due to TCP/TLS error. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_command_disable** +*** +
Disables receiving command messages from IoTHub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_command_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +``` +**Description** + +

This routine disables receiving command messages from IoT Hub.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if command message receiving is disabled. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to disable command message receiving due to invalid parameter. +* NXD_MQTT_NOT_CONNECTED Fail to disable command message receiving due to MQTT not connected. +* NXD_MQTT_PACKET_POOL_FAILURE Fail to disable command message receiving due to no available packet in pool. +* NXD_MQTT_COMMUNICATION_FAILURE Fail to disable command message receiving due to TCP/TLS error. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_command_message_receive** +*** +
Receives IoT Hub command message from IoTHub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_command_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR **component_name_pptr, + USHORT *component_name_length_ptr, + const UCHAR **pnp_command_name_pptr, + USHORT *pnp_command_name_length_ptr, + VOID **context_pptr, + USHORT *context_length_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); +``` +**Description** + +

This routine receives IoT Hub command message from IoT Hub. If there are no messages in the receive queue, this routine can block.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| component_name_pptr [out] | Return a pointer to IoT Hub component name on success. | +| component_name_length_ptr [out] | Return length of `*component_name_pptr` on success. | +| pnp_command_name_pptr [out] | Return a pointer to IoT Hub command name on success. | +| pnp_command_name_length_ptr [out] | Return length of `*pnp_command_name_pptr` on success. | +| context_pptr [out] | Return a pointer to context pointer on success. | +| context_length_ptr [out] | Return length of context on success. | +| packet_pptr [out] | Return `NX_PACKET` containing the command payload on success. Caller owns the `NX_PACKET` memory. | +| wait_option [in] | Ticks to wait for message to arrive. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if IoT Hub command message is received. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to receive IoT Hub command message due to invalid parameter. +* NX_AZURE_IOT_NOT_ENABLED Fail to receive IoT Hub command message due to it is not enabled. +* NX_AZURE_IOT_NO_PACKET Fail to receive IoT Hub command message due to timeout. +* NX_AZURE_IOT_INVALID_PACKET Fail to receive IoT Hub command message due to invalid packet. +* NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive IoT Hub command message due to SDK core error. +* NX_AZURE_IOT_DISCONNECTED Fail to receive IoT Hub command message due to disconnect. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_command_message_response** +*** +
Return response to IoT hub command message from IoTHub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_command_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload_ptr, + UINT payload_length, UINT wait_option); +``` +**Description** + +

This routine returns response to the IoT hub command message from IoT Hub. Note: request_id ties the correlation between command receive and response.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| status_code [in] | Status code for pnp command message. | +| context_ptr [in] | Pointer to context return from nx_azure_iot_hub_client_command_receive. | +| context_length [in] | Length of context. | +| payload [in] | Pointer to `UCHAR` containing the payload for the IoT Hub command response. Payload is in JSON format. | +| payload_length [in] | Length of the payload | +| wait_option [in] | Ticks to wait for message to send. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if IoT Hub command response is send. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to send IoT Hub command response due to invalid parameter. +* NX_AZURE_IOT_SDK_CORE_ERROR Fail to send IoT Hub command response due to SDK core error. +* NX_NO_PACKET Fail send IoT Hub command response due to no available packet in pool. + +**Allowed From** + +Threads + +**Example** + +**See Also**
-**nx_azure_iot_hub_client_device_twin_enable** +#### **nx_azure_iot_hub_client_device_twin_enable** ***
Enables device twin feature
@@ -869,7 +1249,7 @@ Threads
-**nx_azure_iot_hub_client_device_twin_disable** +#### **nx_azure_iot_hub_client_device_twin_disable** ***
Disables device twin feature
@@ -906,20 +1286,20 @@ Threads
-**nx_azure_iot_hub_client_report_properties_response_callback_set** +#### **nx_azure_iot_hub_client_reported_properties_response_callback_set** ***
Sets reported properties response callback function
**Prototype** ```c -UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - VOID (*callback_ptr)( - NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT request_id, - UINT response_status, - ULONG version, - VOID *args), - VOID *callback_args); +UINT nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + VOID (*callback_ptr)( + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT request_id, + UINT response_status, + ULONG version, + VOID *args), + VOID *callback_args); ``` **Description** @@ -949,7 +1329,7 @@ Threads
-**nx_azure_iot_hub_client_device_twin_reported_properties_send** +#### **nx_azure_iot_hub_client_device_twin_reported_properties_send** ***
Send device twin reported properties to IoT Hub
@@ -998,7 +1378,7 @@ Threads
-**nx_azure_iot_hub_client_device_twin_properties_request** +#### **nx_azure_iot_hub_client_device_twin_properties_request** ***
Request complete device twin properties
@@ -1038,7 +1418,7 @@ Threads
-**nx_azure_iot_hub_client_device_twin_properties_receive** +#### **nx_azure_iot_hub_client_device_twin_properties_receive** ***
Receive complete device twin properties
@@ -1080,7 +1460,7 @@ Threads
-**nx_azure_iot_hub_client_device_twin_desired_properties_receive** +#### **nx_azure_iot_hub_client_device_twin_desired_properties_receive** ***
Receive desired properties form IoTHub
@@ -1119,3 +1499,291 @@ Threads **See Also**
+ +#### **nx_azure_iot_hub_client_properties_enable** +*** +
Enables properties feature
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +``` +**Description** + +

This routine enables properties feature.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if properties feature is enabled. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to enable properties feature due to invalid parameter. +* NXD_MQTT_NOT_CONNECTED Fail to enable properties feature due to MQTT not connected. +* NXD_MQTT_PACKET_POOL_FAILURE Fail to enable properties feature due to no available packet in pool. +* NXD_MQTT_COMMUNICATION_FAILURE Fail to enable properties feature due to TCP/TLS error. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +#### **nx_azure_iot_hub_client_properties_disable** +*** +
Disables properties feature
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +``` +**Description** + +

This routine disables properties feature.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if properties feature is disabled. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to disable properties feature due to invalid parameter. +* NXD_MQTT_NOT_CONNECTED Fail to disable properties feature due to MQTT not connected. +* NXD_MQTT_PACKET_POOL_FAILURE Fail to disable properties feature due to no available packet in pool. +* NXD_MQTT_COMMUNICATION_FAILURE Fail to disable properties feature due to TCP/TLS error. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +#### **nx_azure_iot_hub_client_reported_properties_create** +*** +
Creates IoT Hub reported property message.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option) +``` +**Description** + +

This routine creates a reported properties message.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| packet_pptr [out] | Return allocated packet on success. | +| wait_option [in] | Ticks to wait for writer creation. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if a message writer is created. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to create message writer due to invalid parameter. +* NX_AZURE_IOT_SDK_CORE_ERROR Fail to create message writer due to SDK core error. +* NX_NO_PACKET Fail to create message writer due to no available packet in pool. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +#### **nx_azure_iot_hub_client_reported_properties_send** +*** +
Sends IoT Hub reported properties message to IoTHub.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option); +``` +**Description** + +

This routine sends the reported properties contain in the packet.

+

Note: The return status of the API indicates if the reported properties is sent out successfully or not, +the response status is used to track if the reported properties is accepted or not by IoT Hub, and the +reponse status is available only when the return status is NX_AZURE_IOT_SUCCESS.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| packet_ptr [in] | A pointer to a #NX_PACKET. | +| request_id_ptr [out] | Request Id assigned to the request. | +| response_status_ptr [out] | Status return for successful send of reported properties. | +| version_ptr [out] | Version return for successful send of reported properties. | +| wait_option [in] | Ticks to wait for message to send. | + + +**Return Values** + * NX_AZURE_IOT_SUCCESS Successful if reported properties is sent. + * NX_AZURE_IOT_INVALID_PARAMETER Fail to send reported properties due to invalid parameter. + * NX_AZURE_IOT_NOT_ENABLED Fail to send reported properties due to property is not enabled. + * NX_AZURE_IOT_SDK_CORE_ERROR Fail to send reported properties due to SDK core error. + * NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to send reported properties due to buffer size is too small. + * NX_NO_PACKET Fail to send reported properties due to no packet available. + * NX_AZURE_IOT_DISCONNECTED Fail to send reported properties due to disconnect. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_properties_request** +*** +
Request complete properties
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT wait_option); +``` +**Description** + +

This routine requests complete properties.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| wait_option [in] | Ticks to wait for to wait for sending request. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if request get all properties is sent.. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to request get all properties due to invalid parameter. +* NX_AZURE_IOT_NO_SUBSCRIBE_ACK Fail to request get all properties due to no subscribe ack. +* NX_AZURE_IOT_SDK_CORE_ERROR Fail to request get all properties due to SDK core error. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to request get all properties due to buffer size is too small. +* NX_AZURE_IOT_NO_PACKET Fail to request get all properties due to no packet available. +* NX_NO_PACKET Fail to request get all properties due to no packet available. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_properties_receive** +*** +
Receive all the properties
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); +``` +**Description** + +

This routine receives all the properties.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| packet_pptr [out] | A pointer to a #NX_PACKET containing all the properties. | +| wait_option [in] | Ticks to wait for message to receive. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if all properties is received. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to receive all properties due to invalid parameter. +* NX_AZURE_IOT_NOT_ENABLED Fail to receive all properties due to it is not enabled. +* NX_AZURE_IOT_NO_PACKET Fail to receive all properties due to timeout. +* NX_AZURE_IOT_INVALID_PACKET Fail to receive all properties due to invalid packet. +* NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive all properties due to SDK core error. +* NX_AZURE_IOT_SERVER_RESPONSE_ERROR Response code from server is not 2xx. +* NX_AZURE_IOT_DISCONNECTED Fail to receive all properties due to disconnect. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +#### **nx_azure_iot_hub_client_writable_properties_receive** +*** +
Receive writable properties form IoTHub
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_writable_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); +``` +**Description** + +

This routine receives writable properties from IoTHub.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| packet_pptr [out] | A pointer to a #NX_PACKET containing writable properties. | +| wait_option [in] | Ticks to wait for message to receive. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if writable properties is received. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to receive writable properties due to invalid parameter. +* NX_AZURE_IOT_NOT_ENABLED Fail to receive writable properties due to it is not enabled. +* NX_AZURE_IOT_NO_PACKET Fail to receive writable properties due to timeout. +* NX_AZURE_IOT_INVALID_PACKET Fail to receive writable properties due to invalid packet. +* NX_AZURE_IOT_DISCONNECTED Fail to receive writable properties due to disconnect. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ diff --git a/addons/azure_iot/docs/azure_rtos_iot_hub_client_properties.md b/addons/azure_iot/docs/azure_rtos_iot_hub_client_properties.md new file mode 100644 index 00000000..9bba4ece --- /dev/null +++ b/addons/azure_iot/docs/azure_rtos_iot_hub_client_properties.md @@ -0,0 +1,350 @@ +# Azure IoT Hub Client Properties + +**nx_azure_iot_hub_client_reported_properties_component_begin** +*** +
Append the necessary characters to a reported property JSON payload belonging to a subcomponent.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_component_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length); +``` +**Description** + +

This routine appends the necessary characters to a reported properties JSON payload belonging to a subcomponent. The payload will be of the form:

+ +```c +"reported": { + "": { + "__t": "c", + "temperature": 23 + } +} +``` + +**Note** This API should be used in conjunction with +```c +nx_azure_iot_hub_client_reported_properties_component_end() +``` + +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| writer_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_WRITER. | +| component_name_ptr [in] | A pointer to a component name. | +| component_name_length [in] | Length of `component_name_ptr`. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if JSON payload was prefixed successfully. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +**nx_azure_iot_hub_client_reported_properties_component_end** +*** +
Append the necessary characters to end a reported property JSON payload belonging to a subcomponent.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_component_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); +``` +**Description** + +

This routine appends the necessary characters to end a reported properties JSON payload

+ +**Note** This API should be used in conjunction with + +```c +nx_azure_iot_hub_client_reported_properties_component_begin() +``` + + +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| writer_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_WRITER. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS The JSON payload was suffixed successfully. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +**nx_azure_iot_hub_client_reported_properties_status_begin** +*** +
Begin a property response payload with confirmation status.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_status_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *property_name_ptr, + UINT property_name_length, + UINT status_code, + ULONG version, + const UCHAR *description_ptr, + UINT description_length); +``` +**Description** + +

This API should be used in response to an incoming writable property. More details can be found +here: + +https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-convention#writable-properties + +The payload will be of the form: +

+**Without component** + +```c +//{ +// "":{ +// "ac": , +// "av": , +// "ad": "", +// "value": +// } +//} +``` + +

To send a status for a property belonging to a component, first call the +nx_azure_iot_hub_client_reported_property_status_begin() API to prefix the payload with the +necessary identification. The API call flow would look like the following with the listed JSON +payload being generated.

+ +**With component** + +```c +nx_azure_iot_hub_client_reported_properties_component_begin() +nx_azure_iot_hub_client_reported_properties_status_begin() +// Append user value here () +nx_azure_iot_hub_client_reported_properties_status_end() +nx_azure_iot_hub_client_reported_properties_component_end() + +//{ +// "": { +// "__t": "c", +// "": { +// "ac": , +// "av": , +// "ad": "", +// "value": +// } +// } +//} +``` + +**Note** This API should be used in conjunction with +```c +nx_azure_iot_hub_client_reported_properties_status_end() +``` + +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| writer_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_WRITER. | +| property_name_ptr [in] | A pointer to property name. | +| property_name_length [in] | Length of `property_name_ptr`. | +| status_code [in] | The HTTP-like status code to respond with. | +| version [in] | The version of the property the application is acknowledging. | +| description_ptr [in] | An optional pointer to description detailing the context or any details about the acknowledgement. This can be empty string. | +| description_length [in] | Length of description_ptr. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful appended JSON prefix. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +

+ +**nx_azure_iot_hub_client_reported_properties_status_end** +*** +
End a property response payload with confirmation status.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_reported_properties_status_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); +``` +**Description** + +

This routine ends the property response payload.

+ +**Note** This API should be used in conjunction with +```c +nx_azure_iot_hub_client_reported_properties_status_begin() +``` + +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| writer_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_WRITER. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful appended JSON suffix. + +**Allowed From** + +Threads + +**Example** + +**See Also** + + +
+ +**nx_azure_iot_hub_client_properties_version_get** +*** +
Get the property version
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_version_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, ULONG *version_ptr); +``` +**Description** + +

This routine gets the property version.

+ +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| reader_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_READER containing properties document. | +| message_type [in] | Type of message repsonse, only valid value are NX_AZURE_IOT_HUB_PROPERTIES or NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES. | +| version_ptr [out] | The numeric version of the properties in JSON payload. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if got the property version. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ +**nx_azure_iot_hub_client_properties_component_property_next_get** +*** +
Return the next desired or reported property in the property document passed.
+ +**Prototype** +```c +UINT nx_azure_iot_hub_client_properties_component_property_next_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, UINT property_type, + const UCHAR **component_name_pptr, + USHORT *component_name_length_ptr); +``` +**Description** + +

This routine gets the next writable or reported property in the properties document passed.

+ +**Note** that between calls, the UCHAR* pointed to by \p component_name_pptr shall not be modified, only checked and compared. Internally, the pointer is only changed if the component name changes in the JSON document and is not necessarily set every invocation of the function. + +On success, the `reader_ptr` will be set on a valid property name. After checking the property name, the reader can be advanced to the property value by calling nx_azure_iot_json_reader_next_token(). Note that on the subsequent call to this API, it is expected that the json reader will be placed AFTER the read property name and value. That means that after reading the property value (including single values or complex objects), the user must call nx_azure_iot_json_reader_next_token(). + +Below is a code snippet which you can use as a starting point: +```c + while ((status = nx_azure_iot_hub_client_properties_component_property_next_get(&iothub_client, + &json_reader, + message_type, + NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE, + &component_name_ptr, &component_length)) == NX_AZURE_IOT_SUCCESS) + { + + /* Check if property is of interest (substitute user_property for your own property name) */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, user_property, user_property_length)) + { + nx_azure_iot_json_reader_next_token(&json_reader); + + /* Get the property value here + Example: nx_azure_iot_json_reader_token_int32_get(&json_reader, &user_int); */ + + /* Skip to next property value */ + nx_azure_iot_json_reader_next_token(&json_reader); + } + else + { + + /* The JSON reader must be advanced regardless of whether the property + is of interest or not. */ + nx_azure_iot_json_reader_next_token(&json_reader); + + /* Skip children in case the property value is an object. */ + nx_azure_iot_json_reader_skip_children(&json_reader); + nx_azure_iot_json_reader_next_token(&json_reader); + } +} +``` + +**Parameters** + +| Name | Description | +| - |:-| +| hub_client_ptr [in] | A pointer to a `NX_AZURE_IOT_HUB_CLIENT`. | +| reader_ptr [in] | A pointer to a #NX_AZURE_IOT_JSON_READER containing properties document. | +| message_type [in] | Type of message repsonse, only valid value are NX_AZURE_IOT_HUB_PROPERTIES or NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES. | +| property_type [in] | Type of property, only valid value are NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE or NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE. | +| component_name_pptr [out] | A pointer to component name for the property returned using reader_ptr. | +| component_name_length_ptr [out] | Length of the component name. | + + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successful if next property is found. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ diff --git a/addons/azure_iot/docs/azure_rtos_iot_json.md b/addons/azure_iot/docs/azure_rtos_iot_json.md index df4bad1b..6faca527 100644 --- a/addons/azure_iot/docs/azure_rtos_iot_json.md +++ b/addons/azure_iot/docs/azure_rtos_iot_json.md @@ -199,6 +199,40 @@ Threads
+**nx_azure_iot_json_reader_token_uint32_get** +*** +
Gets the JSON token's number as a 32-bit unsigned integer
+ +**Prototype** +```c +UINT nx_azure_iot_json_reader_token_uint32_get(NX_AZURE_IOT_JSON_READER *reader_ptr, + uint32_t *value_ptr); + +``` +**Description** + +

Gets the JSON token's number as a 32-bit unsigned integer.

+ +**Parameters** + +| Name | Description | +| - |:-| +| reader_ptr [in] | A pointer to an #NX_AZURE_IOT_JSON_READER instance containing the JSON to read. | +| value_ptr [out] | A pointer to a variable to receive the value. | + +**Return Values** +* NX_AZURE_IOT_SUCCESS The number is returned. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ **nx_azure_iot_json_reader_token_int32_get** ***
Gets the JSON token's number as a 32-bit signed integer
diff --git a/addons/azure_iot/docs/azure_rtos_iot_provisioning_client.md b/addons/azure_iot/docs/azure_rtos_iot_provisioning_client.md index 99f3e067..90560d25 100644 --- a/addons/azure_iot/docs/azure_rtos_iot_provisioning_client.md +++ b/addons/azure_iot/docs/azure_rtos_iot_provisioning_client.md @@ -89,6 +89,40 @@ Threads
+**nx_azure_iot_provisioning_client_trusted_cert_add** +*** +
Add trusted certificate
+ +**Prototype** +```c +UINT nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate); +``` +**Description** + +

This routine adds trusted certificate. It can be called multiple times to set certificate chain.

+ +**Parameters** +| Name | Description | +| - |:-| +| prov_client_ptr [in] | A pointer to a `NX_AZURE_IOT_PROVISIONING_CLIENT` | +| trusted_certificate [in] | A pointer to a `NX_SECURE_X509_CERT` | + +**Return Values** +* NX_AZURE_IOT_SUCCESS Successfully add trusted certs to AZ IoT Provisioning Client Instance. +* NX_AZURE_IOT_INVALID_PARAMETER Fail to add trusted certs to AZ IoT Provisioning Client Instance due to invalid parameter. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add trusted certificate due to `NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS` is too small. + +**Allowed From** + +Threads + +**Example** + +**See Also** + +
+ **nx_azure_iot_provisioning_client_device_cert_set** ***
Set client certificate
@@ -100,7 +134,7 @@ UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_ ``` **Description** -

This routine sets device certificate.

+

This routine sets device certificate. It can be called multiple times to set certificate chain.

**Parameters** | Name | Description | @@ -111,6 +145,7 @@ UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_ **Return Values** * NX_AZURE_IOT_SUCCESS Successfully set device certs to AZ IoT Provisioning Client Instance. * NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certs to AZ IoT Provisioning Client Instance due to invalid parameter. +* NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to set device certificate due to `NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS` is too small. **Allowed From** diff --git a/addons/azure_iot/docs/azure_rtos_iot_sdk_api.md b/addons/azure_iot/docs/azure_rtos_iot_sdk_api.md index 42ea42bc..27e56ef5 100644 --- a/addons/azure_iot/docs/azure_rtos_iot_sdk_api.md +++ b/addons/azure_iot/docs/azure_rtos_iot_sdk_api.md @@ -2,5 +2,6 @@ ### [Azure IoT](./azure_rtos_iot.md) ### [Azure IoT Hub Client](./azure_rtos_iot_hub_client.md) +### [Azure IoT Hub Client Properties](./azure_rtos_iot_hub_client_properties.md) ### [Azure IoT Provisioning Client](./azure_rtos_iot_provisioning_client.md) ### [Azure IoT JSON](./azure_rtos_iot_json.md) \ No newline at end of file diff --git a/addons/azure_iot/docs/img/iothub_configuration.png b/addons/azure_iot/docs/img/iothub_configuration.png deleted file mode 100644 index 4ffeb0ad..00000000 Binary files a/addons/azure_iot/docs/img/iothub_configuration.png and /dev/null differ diff --git a/addons/azure_iot/nx_azure_iot.c b/addons/azure_iot/nx_azure_iot.c index 698ed5b0..06bfcf68 100644 --- a/addons/azure_iot/nx_azure_iot.c +++ b/addons/azure_iot/nx_azure_iot.c @@ -10,14 +10,15 @@ /**************************************************************************/ /* Version: 6.1 */ +#include +#include + -#include "nx_azure_iot.h" #ifndef NX_AZURE_DISABLE_IOT_SECURITY_MODULE #include "nx_azure_iot_security_module.h" #endif /* NX_AZURE_DISABLE_IOT_SECURITY_MODULE */ -#include -#include +#include "nx_azure_iot.h" #include "azure/core/internal/az_log_internal.h" @@ -25,9 +26,6 @@ #define NX_AZURE_IOT_WAIT_OPTION NX_WAIT_FOREVER #endif /* NX_AZURE_IOT_WAIT_OPTION */ -/* Define offset of MQTT telemetry packet. */ -#define NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET 7 - /* Convert number to upper hex. */ #define NX_AZURE_IOT_NUMBER_TO_UPPER_HEX(number) (CHAR)(number + (number < 10 ? '0' : 'A' - 10)) @@ -37,9 +35,6 @@ NX_AZURE_IOT *_nx_azure_iot_created_ptr; /* Define the callback for logging. */ static VOID(*_nx_azure_iot_log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len); -/* Define the base64 letters. */ -static CHAR _nx_azure_iot_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - extern UINT _nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, USHORT packet_id, UINT QoS, ULONG wait_option); @@ -170,14 +165,6 @@ static VOID nx_azure_iot_log_listener(az_log_classification classification, az_s VOID nx_azure_iot_log_init(VOID(*log_callback)(az_log_classification classification, UCHAR *msg, UINT msg_len)) { -static az_log_classification const classifications[] = {AZ_LOG_IOT_AZURERTOS, - AZ_LOG_MQTT_RECEIVED_TOPIC, - AZ_LOG_MQTT_RECEIVED_PAYLOAD, - AZ_LOG_IOT_RETRY, - AZ_LOG_IOT_SAS_TOKEN, - _az_LOG_END_OF_LIST}; - - _az_log_set_classifications(classifications); _nx_azure_iot_log_callback = log_callback; az_log_set_message_callback(nx_azure_iot_log_listener); } @@ -421,12 +408,12 @@ USHORT id = 0; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id, UINT wait_option) +UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id) { UINT status; /* Get packet id under mutex */ - status = tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, wait_option); + status = tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, NX_WAIT_FOREVER); if (status) { return(status); @@ -622,6 +609,7 @@ UINT nx_azure_iot_mqtt_tls_setup(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESS NX_SECURE_X509_CERT *trusted_certificate) { UINT status; +UINT i; NX_AZURE_IOT_RESOURCE *resource_ptr; NX_PARAMETER_NOT_USED(certificate); @@ -654,21 +642,30 @@ NX_AZURE_IOT_RESOURCE *resource_ptr; LogError(LogLiteralArgs("Failed to create TLS session status: %d"), status); return(status); } - - status = nx_secure_tls_trusted_certificate_add(tls_session, resource_ptr -> resource_trusted_certificate); - if (status) + + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++) { - LogError(LogLiteralArgs("Failed to add trusted CA certificate to session status: %d"), status); - return(status); + if (resource_ptr -> resource_trusted_certificates[i]) + { + status = nx_secure_tls_trusted_certificate_add(tls_session, resource_ptr -> resource_trusted_certificates[i]); + if (status) + { + LogError(LogLiteralArgs("Failed to add trusted CA certificate to session status: %d"), status); + return(status); + } + } } - if (resource_ptr -> resource_device_certificate) + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++) { - status = nx_secure_tls_local_certificate_add(tls_session, resource_ptr -> resource_device_certificate); - if (status) + if (resource_ptr -> resource_device_certificates[i]) { - LogError(LogLiteralArgs("Failed to add device certificate to session status: %d"), status); - return(status); + status = nx_secure_tls_local_certificate_add(tls_session, resource_ptr -> resource_device_certificates[i]); + if (status) + { + LogError(LogLiteralArgs("Failed to add device certificate to session status: %d"), status); + return(status); + } } } @@ -713,198 +710,6 @@ UINT nx_azure_iot_unix_time_get(NX_AZURE_IOT *nx_azure_iot_ptr, ULONG *unix_time return(nx_azure_iot_ptr -> nx_azure_iot_unix_time_get(unix_time)); } -static UINT nx_azure_iot_base64_decode(CHAR *base64name, UINT length, UCHAR *name, UINT name_size, UINT *bytes_copied) -{ -UINT i, j; -UINT value1, value2; -UINT step; -UINT sourceLength = length; - - /* Adjust the length to represent the ASCII name. */ - length = ((length * 6) / 8); - - if (base64name[sourceLength - 1] == '=') - { - if (base64name[sourceLength - 2] == '=') - { - length --; - } - length--; - } - - if (name_size < length) - { - LogError(LogLiteralArgs("Failed to find enough memory")); - return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); - } - - /* Setup index into the ASCII name. */ - j = 0; - - /* Compute the ASCII name. */ - step = 0; - i = 0; - while ((j < length) && (base64name[i]) && (base64name[i] != '=')) - { - - /* Derive values of the Base64 name. */ - if ((base64name[i] >= 'A') && (base64name[i] <= 'Z')) - value1 = (UINT) (base64name[i] - 'A'); - else if ((base64name[i] >= 'a') && (base64name[i] <= 'z')) - value1 = (UINT) (base64name[i] - 'a') + 26; - else if ((base64name[i] >= '0') && (base64name[i] <= '9')) - value1 = (UINT) (base64name[i] - '0') + 52; - else if (base64name[i] == '+') - value1 = 62; - else if (base64name[i] == '/') - value1 = 63; - else - value1 = 0; - - /* Derive value for the next character. */ - if ((base64name[i+1] >= 'A') && (base64name[i+1] <= 'Z')) - value2 = (UINT) (base64name[i+1] - 'A'); - else if ((base64name[i+1] >= 'a') && (base64name[i+1] <= 'z')) - value2 = (UINT) (base64name[i+1] - 'a') + 26; - else if ((base64name[i+1] >= '0') && (base64name[i+1] <= '9')) - value2 = (UINT) (base64name[i+1] - '0') + 52; - else if (base64name[i+1] == '+') - value2 = 62; - else if (base64name[i+1] == '/') - value2 = 63; - else - value2 = 0; - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first value and first 2 bits of second value. */ - name[j++] = (UCHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3)); - i++; - step++; - } - else if (step == 1) - { - - /* Use last 4 bits of first value and first 4 bits of next value. */ - name[j++] = (UCHAR) (((value1 & 0xF) << 4) | (value2 >> 2)); - i++; - step++; - } - else if (step == 2) - { - - /* Use first 2 bits and following 6 bits of next value. */ - name[j++] = (UCHAR) (((value1 & 3) << 6) | (value2 & 0x3f)); - i++; - i++; - step = 0; - } - } - - /* Put a NULL character in. */ - name[j] = NX_NULL; - *bytes_copied = j; - - return(NX_AZURE_IOT_SUCCESS); -} - -static UINT nx_azure_iot_base64_encode(UCHAR *name, UINT length, CHAR *base64name, UINT base64name_size) -{ -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - - /* Default padding to none. */ - pad = 0; - - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) - { - - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; - } - - if (base64name_size <= length) - { - LogError(LogLiteralArgs("Failed to find enough memory")); - return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); - } - - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) - { - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first 6 bits of name character for index. */ - base64name[j++] = (CHAR)_nx_azure_iot_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) - { - - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = (CHAR)_nx_azure_iot_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; - } - else if (step == 2) - { - - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = (CHAR)_nx_azure_iot_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ - { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = (CHAR)_nx_azure_iot_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; - } - } - - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < base64name_size)) - { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; - } - - /* Put a NULL character in. */ - base64name[j] = NX_NULL; - - return(NX_AZURE_IOT_SUCCESS); -} - /* HMAC-SHA256(master key, message ) */ static UINT nx_azure_iot_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_ptr, UCHAR *key, UINT key_size, const UCHAR *message, UINT message_size, UCHAR *output) @@ -979,13 +784,14 @@ UINT nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_p UINT status; UCHAR *hash_buf; UINT hash_buf_size = 33; -CHAR *encoded_hash_buf; +UCHAR *encoded_hash_buf; UINT encoded_hash_buf_size = 48; +UINT encoded_hash_size; UINT binary_key_buf_size; binary_key_buf_size = buffer_len; - status = nx_azure_iot_base64_decode((CHAR *)key_ptr, key_size, - buffer_ptr, binary_key_buf_size, &binary_key_buf_size); + status = _nx_utility_base64_decode((UCHAR *)key_ptr, key_size, + buffer_ptr, binary_key_buf_size, &binary_key_buf_size); if (status) { LogError(LogLiteralArgs("Failed to base64 decode")); @@ -1009,20 +815,20 @@ UINT binary_key_buf_size; } buffer_len -= hash_buf_size; - encoded_hash_buf = (CHAR *)(hash_buf + hash_buf_size); + encoded_hash_buf = hash_buf + hash_buf_size; /* Additional space is required by encoder. */ hash_buf[hash_buf_size - 1] = 0; - status = nx_azure_iot_base64_encode(hash_buf, hash_buf_size - 1, - encoded_hash_buf, encoded_hash_buf_size); + status = _nx_utility_base64_encode(hash_buf, hash_buf_size - 1, + encoded_hash_buf, encoded_hash_buf_size, &encoded_hash_size); if (status) { LogError(LogLiteralArgs("Failed to base64 encode")); return(status); } - *output_pptr = (UCHAR *)(encoded_hash_buf); - *output_len_ptr = strlen(encoded_hash_buf); + *output_pptr = encoded_hash_buf; + *output_len_ptr = encoded_hash_size; return(NX_AZURE_IOT_SUCCESS); } diff --git a/addons/azure_iot/nx_azure_iot.h b/addons/azure_iot/nx_azure_iot.h index d4229d2f..beee5e74 100644 --- a/addons/azure_iot/nx_azure_iot.h +++ b/addons/azure_iot/nx_azure_iot.h @@ -48,6 +48,18 @@ extern "C" { #define NX_AZURE_IOT_LOG_LEVEL 2 #endif /* NX_AZURE_IOT_LOG_LEVEL */ +/* Define maximum trusted certificates count. */ +#ifndef NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS +#define NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS 3 +#endif /* NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS */ + +/* Define maximum device certificates count. */ +#ifndef NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS +#define NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS 2 +#endif /* NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS */ + +#define NX_AZURE_IOT_ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) + /* Define the az iot log function. */ #define LogError(...) #define LogInfo(...) @@ -65,15 +77,15 @@ UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_l #if NX_AZURE_IOT_LOG_LEVEL > 0 #undef LogError -#define LogError(...) nx_azure_iot_log(LogLiteralArgs("[ERROR] "), ##__VA_ARGS__) +#define LogError(...) nx_azure_iot_log(LogLiteralArgs("[ERROR] "), __VA_ARGS__) #endif /* NX_AZURE_IOT_LOG_LEVEL > 0 */ #if NX_AZURE_IOT_LOG_LEVEL > 1 #undef LogInfo -#define LogInfo(...) nx_azure_iot_log(LogLiteralArgs("[INFO] "), ##__VA_ARGS__) +#define LogInfo(...) nx_azure_iot_log(LogLiteralArgs("[INFO] "), __VA_ARGS__) #endif /* NX_AZURE_IOT_LOG_LEVEL > 1 */ #if NX_AZURE_IOT_LOG_LEVEL > 2 #undef LogDebug -#define LogDebug(...) nx_azure_iot_log(LogLiteralArgs("[DEBUG] "), ##__VA_ARGS__) +#define LogDebug(...) nx_azure_iot_log(LogLiteralArgs("[DEBUG] "), __VA_ARGS__) #endif /* NX_AZURE_IOT_LOG_LEVEL > 2 */ #define NX_AZURE_IOT_MQTT_QOS_0 0 @@ -128,6 +140,10 @@ UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_l #define NX_AZURE_IOT_NO_SUBSCRIBE_ACK 0x20014 #define NX_AZURE_IOT_THROTTLED 0x20015 +#define NX_AZURE_IOT_EMPTY_JSON 0x20016 +#define NX_AZURE_IOT_SAS_TOKEN_EXPIRED 0x20017 +#define NX_AZURE_IOT_NO_MORE_ENTRIES 0x20018 + /* Resource type managed by AZ_IOT. */ #define NX_AZURE_IOT_RESOURCE_IOT_HUB 0x1 #define NX_AZURE_IOT_RESOURCE_IOT_PROVISIONING 0x2 @@ -146,6 +162,9 @@ UINT nx_azure_iot_log(UCHAR *type_ptr, UINT type_len, UCHAR *msg_ptr, UINT msg_l /* MQTT Subscribe topic offset. */ #define NX_AZURE_IOT_MQTT_SUBSCRIBE_TOPIC_OFFSET 6 +/* MQTT Publish offset. */ +#define NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET 7 + /** * @brief Resource struct * @@ -170,8 +189,8 @@ typedef struct NX_AZURE_IOT_RESOURCE_STRUCT UINT resource_cipher_map_size; UCHAR *resource_metadata_ptr; UINT resource_metadata_size; - NX_SECURE_X509_CERT *resource_trusted_certificate; - NX_SECURE_X509_CERT *resource_device_certificate; + NX_SECURE_X509_CERT *resource_trusted_certificates[NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS]; + NX_SECURE_X509_CERT *resource_device_certificates[NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS]; const UCHAR *resource_hostname; UINT resource_hostname_length; struct NX_AZURE_IOT_RESOURCE_STRUCT *resource_next; @@ -198,6 +217,15 @@ typedef struct NX_AZURE_IOT_STRUCT UINT (*nx_azure_iot_unix_time_get)(ULONG *unix_time); } NX_AZURE_IOT; +typedef struct NX_AZURE_IOT_THREAD_STRUCT +{ + TX_THREAD *thread_ptr; + struct NX_AZURE_IOT_THREAD_STRUCT *thread_next; + UINT thread_message_type; + UINT thread_expected_id; /* Used by device twin. */ + NX_PACKET *thread_received_message; +} NX_AZURE_IOT_THREAD; + /** * @brief Create the Azure IoT subsystem * @@ -287,7 +315,7 @@ UINT nx_azure_iot_publish_mqtt_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *pa UINT topic_len, UCHAR *packet_id, UINT qos, UINT wait_option); UINT nx_azure_iot_publish_packet_get(NX_AZURE_IOT *nx_azure_iot_ptr, NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_pptr, UINT wait_option); -UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id, UINT wait_option); +UINT nx_azure_iot_mqtt_packet_id_get(NXD_MQTT_CLIENT *client_ptr, UCHAR *packet_id); VOID nx_azure_iot_mqtt_packet_adjust(NX_PACKET *packet_ptr); UINT nx_azure_iot_mqtt_tls_setup(NXD_MQTT_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_X509_CERT *certificate, @@ -298,7 +326,6 @@ UINT nx_azure_iot_base64_hmac_sha256_calculate(NX_AZURE_IOT_RESOURCE *resource_p UCHAR *buffer_ptr, UINT buffer_len, UCHAR **output_ptr, UINT *output_len_ptr); - #ifdef __cplusplus } #endif diff --git a/addons/azure_iot/nx_azure_iot_adu_agent.c b/addons/azure_iot/nx_azure_iot_adu_agent.c new file mode 100644 index 00000000..c4da49a5 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_adu_agent.c @@ -0,0 +1,4405 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 */ + +#include "nx_azure_iot_adu_agent.h" + +/* Update buffer pointer and buffer size. */ +#define NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(a, b, c, d) { \ + (a) = (c); \ + (c) += (b); \ + (d) -= (b); \ + } + +static VOID nx_azure_iot_adu_agent_event_process(VOID *adu_agent, ULONG common_events, ULONG module_own_events); +static VOID nx_azure_iot_adu_agent_timer_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static VOID nx_azure_iot_adu_agent_update_check_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static VOID nx_azure_iot_adu_agent_download_install_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static VOID nx_azure_iot_adu_agent_apply_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static UINT nx_azure_iot_adu_agent_manifest_verify(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static UINT nx_azure_iot_adu_agent_jws_split(UCHAR *jws, UINT jws_length, + UCHAR **header, UINT *header_length, + UCHAR **payload, UINT *payload_length, + UCHAR **signature, UINT *signature_length); +static UINT nx_azure_iot_adu_agent_service_properties_get(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_JSON_READER *json_reader_ptr); +static UINT nx_azure_iot_adu_agent_service_update_manifest_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UCHAR *update_manifest, + UINT update_manifest_size, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *update_manifest_content, + UCHAR *update_manifest_content_buffer, + UINT update_manifest_content_buffer_size); +static UINT nx_azure_iot_adu_agent_service_reported_properties_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UINT status_code, ULONG version, const CHAR *description, + ULONG wait_option); +static UINT nx_azure_iot_adu_agent_reported_properties_startup_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT wait_option); +static UINT nx_azure_iot_adu_agent_reported_properties_state_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static VOID nx_azure_iot_adu_agent_step_state_update(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT step_state); +static UINT nx_azure_iot_adu_agent_file_find(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *manifest_content, + UCHAR *file_id, UINT file_id_length, + NX_AZURE_IOT_ADU_AGENT_FILE **file); +static UINT nx_azure_iot_adu_agent_method_is_installed(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY *compatibility, + NX_AZURE_IOT_ADU_AGENT_STEP *step, + UINT *is_installed); +static UINT nx_azure_iot_adu_agent_method_download(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_FILE *file, + UINT type, UCHAR *buffer_ptr, UINT buffer_size, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +static UINT nx_azure_iot_adu_agent_method_install(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +static UINT nx_azure_iot_adu_agent_method_apply(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +static const NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY *nx_azure_iot_adu_agent_rsa_root_key_find(const UCHAR* kid, UINT kid_size); +static UINT nx_azure_iot_adu_agent_sha256_calculate(NX_CRYPTO_METHOD *sha256_method, + UCHAR *metadata_ptr, UINT metadata_size, + UCHAR *input_ptr, ULONG input_size, + UCHAR *output_ptr, ULONG output_size); +static UINT nx_azure_iot_adu_agent_rs256_verify(NX_AZURE_IOT_ADU_AGENT_CRYPTO *adu_agent_crypto, + UCHAR *input_ptr, ULONG input_size, + UCHAR *signature_ptr, ULONG signature_size, + UCHAR *n, ULONG n_size, + UCHAR *e, ULONG e_size, + UCHAR *buffer_ptr, UINT buffer_size); +static UINT nx_azure_iot_adu_agent_file_url_parse(UCHAR *file_url, ULONG file_url_length, + UCHAR *buffer_ptr, UINT buffer_size, + NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr); +static void nx_azure_iot_adu_agent_dns_query(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static void nx_azure_iot_adu_agent_dns_response_notify(NX_UDP_SOCKET *socket_ptr); +static void nx_azure_iot_adu_agent_dns_response_get(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static void nx_azure_iot_adu_agent_http_connect(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static void nx_azure_iot_adu_agent_http_request_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static void nx_azure_iot_adu_agent_http_response_receive(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); +static void nx_azure_iot_adu_agent_http_establish_notify(NX_TCP_SOCKET *socket_ptr); +static void nx_azure_iot_adu_agent_http_receive_notify(NX_TCP_SOCKET *socket_ptr); +static void nx_azure_iot_adu_agent_download_state_update(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT success); +static UINT nx_azure_iot_adu_agent_component_properties_process(VOID *reader_ptr, + ULONG version, + VOID *args); +extern UINT nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT (*callback_ptr)(VOID *json_reader_ptr, + ULONG version, + VOID *args), + VOID *callback_args); +extern VOID nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, UINT message_type); + +UINT nx_azure_iot_adu_agent_start(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_update_notify)(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UINT update_state, + UCHAR *provider, UINT provider_length, + UCHAR *name, UINT name_length, + UCHAR *version, UINT version_length), + VOID (*adu_agent_update_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)) +{ +UINT i; +UINT status; +NX_AZURE_IOT *nx_azure_iot_ptr; +NX_AZURE_IOT_RESOURCE *resource_ptr; +NX_CRYPTO_METHOD *method_sha256 = NX_NULL; +NX_CRYPTO_METHOD *method_rsa = NX_NULL; +NX_SECURE_TLS_SESSION *tls_session; +NX_AZURE_IOT_ADU_AGENT_CRYPTO *adu_agent_crypto; +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; +UINT component_added = NX_FALSE; + + if ((adu_agent_ptr == NX_NULL) || (iothub_client_ptr == NX_NULL) || + (manufacturer == NX_NULL) || (manufacturer_length == 0) || + (model == NX_NULL) || (model_length == 0) || + ((installed_criteria == NX_NULL) && (installed_criteria_length != 0)) || + (adu_agent_update_driver == NX_NULL)) + { + LogError(LogLiteralArgs("ADU agent start fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Check if IoT Hub connected. */ + if (iothub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + { + LogError(LogLiteralArgs("ADU agent start fail: IOTHUB NOT CONNECTED")); + return(NX_AZURE_IOT_WRONG_STATE); + } + + /* Check if properties is enabled. */ + if (iothub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_enable == NX_NULL) + { + LogError(LogLiteralArgs("ADU agent start fail: PROPERTIES NOT ENABLED")); + return(NX_AZURE_IOT_NOT_ENABLED); + } + + memset(adu_agent_ptr, 0, sizeof(NX_AZURE_IOT_ADU_AGENT)); + + /* Set iothub client pointer and azure iot pointer. */ + adu_agent_ptr -> nx_azure_iot_hub_client_ptr = iothub_client_ptr; + nx_azure_iot_ptr = iothub_client_ptr -> nx_azure_iot_ptr; + + /* Set component process routine for system component. */ + iothub_client_ptr -> nx_azure_iot_hub_client_component_properties_process = nx_azure_iot_hub_client_properties_component_process; + + /* Check if the component has been added. */ + for (i = 0; i < (UINT)iothub_client_ptr -> iot_hub_client_core._internal.options.component_names_length; i++) + { + + /* Compare the component. */ + if ((iothub_client_ptr -> iot_hub_client_core._internal.options.component_names[i]._internal.size == sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1) && + (!memcmp(iothub_client_ptr -> iot_hub_client_core._internal.options.component_names[i]._internal.ptr, NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME, sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1))) + { + component_added = NX_TRUE; + } + } + + /* Add ADU component. */ + if (component_added == NX_FALSE) + { + if ((status = nx_azure_iot_hub_client_component_add_internal(iothub_client_ptr, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1, + nx_azure_iot_adu_agent_component_properties_process, + adu_agent_ptr))) + { + LogError(LogLiteralArgs("ADU agent start fail: COMPONENT ADD FAIL: %d"), status); + return(status); + } + } + + /* Save the mutex. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr = nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr; + + /* Find RSA and SHA256. */ + resource_ptr = &(iothub_client_ptr -> nx_azure_iot_hub_client_resource); + for(i = 0; i < resource_ptr -> resource_crypto_array_size; i++) + { + if(resource_ptr -> resource_crypto_array[i] -> nx_crypto_algorithm == NX_CRYPTO_HASH_SHA256) + { + method_sha256 = (NX_CRYPTO_METHOD *)resource_ptr -> resource_crypto_array[i]; + } + else if(resource_ptr -> resource_crypto_array[i] -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA) + { + method_rsa = (NX_CRYPTO_METHOD *)resource_ptr -> resource_crypto_array[i]; + } + + if ((method_sha256) && (method_rsa)) + { + break; + } + } + + /* Check if find the crypto method. */ + if ((method_sha256 == NX_NULL) || + (method_sha256 -> nx_crypto_operation == NX_NULL) || + (method_rsa == NX_NULL) || + (method_rsa -> nx_crypto_init == NX_NULL) || + (method_rsa -> nx_crypto_operation == NX_NULL) ) + { + LogError(LogLiteralArgs("ADU agent start fail: NO AVAILABLE CIPHER")); + return(NX_AZURE_IOT_NO_AVAILABLE_CIPHER); + } + + /* Check if the metadata size is enough. */ + if (method_sha256 -> nx_crypto_metadata_area_size > NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE) + { + LogError(LogLiteralArgs("ADU agent start fail: INSUFFICIENT BUFFER FOR SHA256")); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + /* Save the crypto methods (RS256) for verifying update manifest. */ + adu_agent_crypto = &(adu_agent_ptr -> nx_azure_iot_adu_agent_crypto); + + /* Set RSA crypto, reuse the metadata from tls session. */ + tls_session = &(iothub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt.nxd_mqtt_tls_session); + adu_agent_crypto -> method_rsa = method_rsa; + adu_agent_crypto -> method_rsa_metadata = tls_session -> nx_secure_public_cipher_metadata_area; + adu_agent_crypto -> method_rsa_metadata_size = tls_session -> nx_secure_public_cipher_metadata_size; + + /* Set SHA256 crypto. */ + adu_agent_crypto -> method_sha256 = method_sha256; + + /* Call the driver to initialize the hardware. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_INITIALIZE; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (adu_agent_update_driver)(&driver_request); + + /* Check status. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + LogError(LogLiteralArgs("ADU agent start fail: DRIVER ERROR")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Save the device properties (manufacturer and model). */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device_properties.manufacturer = manufacturer; + adu_agent_ptr -> nx_azure_iot_adu_agent_device_properties.manufacturer_length = manufacturer_length; + adu_agent_ptr -> nx_azure_iot_adu_agent_device_properties.model = model; + adu_agent_ptr -> nx_azure_iot_adu_agent_device_properties.model_length = model_length; + + /* Save the device properties for compatibility. Compatibility defines the criteria of a device that can install the update. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].device_properties.manufacturer = manufacturer; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].device_properties.manufacturer_length = manufacturer_length; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].device_properties.model = model; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].device_properties.model_length = model_length; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].installed_criteria = installed_criteria; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].installed_criteria_length = installed_criteria_length; + + /* Save the driver. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].device_driver_entry = adu_agent_update_driver; + + /* Set the entry as valid. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[0].valid = NX_TRUE; + + /* Send agent startup message. */ + status = nx_azure_iot_adu_agent_reported_properties_startup_send(adu_agent_ptr, NX_WAIT_FOREVER); + if (status) + { + LogError(LogLiteralArgs("ADU agent start fail: CLIENT REPORTED PROPERTIES SEND FAIL")); + return(status); + } + + /* Set the state change notification. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_update_notify = adu_agent_update_notify; + + /* Set the dns pointer. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.dns_ptr = nx_azure_iot_ptr -> nx_azure_iot_dns_ptr; + + /* Set the UDP socket receive callback function for non-blocking DNS. */ + nx_azure_iot_ptr -> nx_azure_iot_dns_ptr -> nx_dns_socket.nx_udp_socket_reserved_ptr = adu_agent_ptr; + nx_udp_socket_receive_notify(&(nx_azure_iot_ptr -> nx_azure_iot_dns_ptr -> nx_dns_socket), + nx_azure_iot_adu_agent_dns_response_notify); + + /* Register ADU module on cloud helper. */ + status = nx_cloud_module_register(&(nx_azure_iot_ptr -> nx_azure_iot_cloud), + &(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + "Azure Device Update Module", + (NX_CLOUD_MODULE_AZURE_ADU_EVENT | NX_CLOUD_COMMON_PERIODIC_EVENT), + nx_azure_iot_adu_agent_event_process, adu_agent_ptr); + if (status) + { + LogError(LogLiteralArgs("ADU module register fail status: %d"), status); + return(status); + } + + LogInfo(LogLiteralArgs("ADU agent started successfully!")); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_adu_agent_stop(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + + if ((adu_agent_ptr == NX_NULL) || (adu_agent_ptr -> nx_azure_iot_hub_client_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("ADU agent stop fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Obtain the mutex. */ + tx_mutex_get(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr, NX_WAIT_FOREVER); + + /* Check if there is downloading socket. */ + if ((adu_agent_ptr -> nx_azure_iot_adu_agent_state == NX_AZURE_IOT_ADU_AGENT_STATE_DEPLOYMENT_IN_PROGRESS) && + (adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.state >= NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONNECT)) + { + + /* Delete http client. */ + nx_web_http_client_delete(&(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.http_client)); + } + + /* Release the mutex. */ + tx_mutex_put(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr); + + /* Deregister ADU module on cloud helper. */ + nx_cloud_module_deregister(&(adu_agent_ptr -> nx_azure_iot_hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_cloud), + &(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module)); + + LogInfo(LogLiteralArgs("ADU agent stopped!")); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_adu_agent_update_download_and_install(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; + + if (adu_agent_ptr == NX_NULL) + { + LogError(LogLiteralArgs("ADU agent download&install fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Reset the step. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_current_step = NX_NULL; + + /* Set event to download and install update. */ + status = nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_DOWNLOAD_INSTALL_EVENT); + + return(status); +} + +UINT nx_azure_iot_adu_agent_update_apply(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; + + if (adu_agent_ptr == NX_NULL) + { + LogError(LogLiteralArgs("ADU agent apply fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Set event to deploy update. */ + status = nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_APPLY_EVENT); + + return(status); +} + +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) +UINT nx_azure_iot_adu_agent_proxy_update_add(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_proxy_update_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)) +{ +UINT i; +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; + + if ((adu_agent_ptr == NX_NULL) || + (manufacturer == NX_NULL) || (manufacturer_length == 0) || + (model == NX_NULL) || (model_length == 0) || + ((installed_criteria == NX_NULL) && (installed_criteria_length != 0)) || + (adu_agent_proxy_update_driver == NX_NULL)) + { + LogError(LogLiteralArgs("ADU agent proxy update fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Compatibility defines the criteria of a device that can install the update. It contains device properties (manufacturer and model). */ + + /* Obtain the mutex. */ + tx_mutex_get(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr, NX_WAIT_FOREVER); + + /* Find available entry. */ + for (i = 0; i < NX_AZURE_IOT_ADU_AGENT_DEVICE_COUNT; i++) + { + if (adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].valid == NX_FALSE) + { + + /* Find available entry. */ + break; + } + } + + /* Check if find an available entry. */ + if (i >= NX_AZURE_IOT_ADU_AGENT_DEVICE_COUNT) + { + + /* Release the mutex. */ + tx_mutex_put(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr); + return(NX_AZURE_IOT_NO_MORE_ENTRIES); + } + + /* Call the driver to initialize the hardware. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_INITIALIZE; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (adu_agent_proxy_update_driver)(&driver_request); + + /* Check status. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + + /* Release the mutex. */ + tx_mutex_put(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr); + LogError(LogLiteralArgs("ADU agent start fail: DRIVER ERROR")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Setup the driver. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_driver_entry = adu_agent_proxy_update_driver; + + /* Save the device properties for compatibility. Compatibility defines the criteria of a device that can install the update. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.manufacturer = manufacturer; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.manufacturer_length = manufacturer_length; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.model = model; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.model_length = model_length; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].installed_criteria = installed_criteria; + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].installed_criteria_length = installed_criteria_length; + + /* Set the entry as valid. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].valid = NX_TRUE; + + /* Release the mutex. */ + tx_mutex_put(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} +#endif /* (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) */ + +static UINT nx_azure_iot_adu_agent_component_properties_process(VOID *reader_ptr, + ULONG version, + VOID *args) +{ +UINT status; +NX_AZURE_IOT_JSON_READER *json_reader_ptr = (NX_AZURE_IOT_JSON_READER *)reader_ptr; +NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr = (NX_AZURE_IOT_ADU_AGENT *)args; + + /* Check the state. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_state == NX_AZURE_IOT_ADU_AGENT_STATE_DEPLOYMENT_IN_PROGRESS) + { + + /* The JSON reader must be advanced regardless of whether the property + is of interest or not. */ + nx_azure_iot_json_reader_next_token(reader_ptr); + + /* Skip children in case the property value is an object. */ + if (nx_azure_iot_json_reader_token_type(reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + nx_azure_iot_json_reader_skip_children(reader_ptr); + } + nx_azure_iot_json_reader_next_token(reader_ptr); + + return(NX_AZURE_IOT_SUCCESS); + } + + /* Check "service" property name. */ + if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SERVICE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SERVICE) - 1)) + { + + /* Get service property value. */ + status = nx_azure_iot_adu_agent_service_properties_get(adu_agent_ptr, json_reader_ptr); + if (status) + { + LogError(LogLiteralArgs("ADU agent component process fail: SERVICE PROPERTIES GET FAIL")); + return(status); + } + + /* Send service response. */ + nx_azure_iot_adu_agent_service_reported_properties_send(adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_STATUS_SUCCESS, version, "", + NX_NO_WAIT); + + /* Check the action. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.action == NX_AZURE_IOT_ADU_AGENT_ACTION_CANCEL) + { + + /* Reset the state. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_IDLE; + + LogInfo(LogLiteralArgs("Cancel Command received")); + return(NX_AZURE_IOT_SUCCESS); + } + + else if (adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.action != NX_AZURE_IOT_ADU_AGENT_ACTION_APPLY_DEPLOYMENT) + { + return(NX_AZURE_IOT_FAILURE); + } + + + /* Verify manifest. */ + if (nx_azure_iot_adu_agent_manifest_verify(adu_agent_ptr) != NX_TRUE) + { + LogError(LogLiteralArgs("Failed to verify update manifest signature")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Process deployable update manifest. */ + if (nx_azure_iot_adu_agent_service_update_manifest_process(adu_agent_ptr, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_size, + &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content), + adu_agent_ptr -> nx_azure_iot_adu_agent_buffer, + NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE)) + { + LogError(LogLiteralArgs("ADU agent component process fail: UPDATE MANIFEST PROCESS FAIL")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Reset. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_current_step = NX_NULL; + adu_agent_ptr -> nx_azure_iot_adu_agent_update_flag = NX_FALSE; + + /* Update the state. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_DEPLOYMENT_IN_PROGRESS; + + /* Set event to start update automatically. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_UPDATE_EVENT); + } + else + { + return(NX_AZURE_IOT_FAILURE); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static VOID nx_azure_iot_adu_agent_event_process(VOID *adu_agent, ULONG common_events, ULONG module_own_events) +{ + +NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr = (NX_AZURE_IOT_ADU_AGENT *)adu_agent; + + /* Obtain the mutex. */ + tx_mutex_get(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr, NX_WAIT_FOREVER); + + /* Process common periodic event. */ + if (common_events & NX_CLOUD_COMMON_PERIODIC_EVENT) + { + + /* Process timer event. */ + nx_azure_iot_adu_agent_timer_event_process(adu_agent_ptr); + } + + /* Process events. */ + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_UPDATE_EVENT) + { + + /* Update check. */ + nx_azure_iot_adu_agent_update_check_event_process(adu_agent_ptr); + } + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_DOWNLOAD_INSTALL_EVENT) + { + + /* Update download and install. */ + nx_azure_iot_adu_agent_download_install_event_process(adu_agent_ptr); + } + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_APPLY_EVENT) + { + + /* Update apply. */ + nx_azure_iot_adu_agent_apply_event_process(adu_agent_ptr); + } + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_DNS_RESPONSE_RECEIVE_EVENT) + { + + /* Process DNS response get event. */ + nx_azure_iot_adu_agent_dns_response_get(adu_agent_ptr); + } + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_DONE_EVENT) + { + + /* Process HTTP connect done event. */ + nx_azure_iot_adu_agent_http_request_send(adu_agent_ptr); + } + if (module_own_events & NX_AZURE_IOT_ADU_AGENT_HTTP_RECEIVE_EVENT) + { + + /* Process HTTP receive event. */ + nx_azure_iot_adu_agent_http_response_receive(adu_agent_ptr); + } + + /* Release the mutex. */ + tx_mutex_put(adu_agent_ptr -> nx_azure_iot_adu_agent_mutex_ptr); +} + +static VOID nx_azure_iot_adu_agent_timer_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + /* Check the timer for DNS/HTTP. */ + if (downloader_ptr -> timeout) + { + + /* Decrease the timeout. */ + downloader_ptr -> timeout--; + + /* Check if it is timeout. */ + if (downloader_ptr -> timeout != 0) + { + return; + } + + /* Check the state. */ + if (downloader_ptr -> state == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_QUERY) + { + + /* DNS query timeout, try to receive dns response, if there is no DNS response. Retry DNS query. */ + nx_azure_iot_adu_agent_dns_response_get(adu_agent_ptr); + } + else if ((downloader_ptr -> state == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONNECT) || + (downloader_ptr -> state == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONTENT_GET)) + { + LogError(LogLiteralArgs("Firmware download fail: TIMEOUT")); + + /* Timeout for http connect or http content get. */ + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + } + } +} + +static VOID nx_azure_iot_adu_agent_update_check_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *update_manifest_content = &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content); +NX_AZURE_IOT_ADU_AGENT_STEP *step; +NX_AZURE_IOT_ADU_AGENT_FILE *file; +UINT is_installed = NX_FALSE; +UINT i; +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) +UCHAR *json_data_ptr; +NX_AZURE_IOT_JSON_READER json_reader; +UCHAR *proxy_update_manifest_ptr; +UINT proxy_update_manifest_size; +NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *proxy_update_manifest_content; +NX_AZURE_IOT_ADU_AGENT_STEP *proxy_step; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); +#endif /* (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) */ + + /* Check if current step is completed or not. */ + if ((adu_agent_ptr -> nx_azure_iot_adu_agent_current_step == NX_NULL) || + (adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED) || + (adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_SUCCEEDED)) + { + for (i = 0; i < update_manifest_content -> steps_count; i++) + { + + /* Check the state. */ + if (update_manifest_content -> steps[i].state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_IDLE) + { + adu_agent_ptr -> nx_azure_iot_adu_agent_current_step = &(update_manifest_content -> steps[i]); + break; + } + } + + /* Check if all steps are checked. */ + if (i == update_manifest_content -> steps_count) + { + + /* Check if all updates are installed. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_update_flag == NX_TRUE) + { + + /* If there is a new update, report deployment in progress state to server and start to download. */ + nx_azure_iot_adu_agent_reported_properties_state_send(adu_agent_ptr); + + /* Check if set the update notify. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_update_notify) + { + + /* Notify the user and let users control the update. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_update_notify(adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_UPDATE_RECEIVED, + (UCHAR *)update_manifest_content -> update_id.provider, + update_manifest_content -> update_id.provider_length, + (UCHAR *)update_manifest_content -> update_id.name, + update_manifest_content -> update_id.name_length, + (UCHAR *)update_manifest_content -> update_id.version, + update_manifest_content -> update_id.version_length); + } + else + { + + /* Set event to start update automatically. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_DOWNLOAD_INSTALL_EVENT); + } + } + else + { + + /* All updates are installed and applied. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_IDLE; + + /* Send reported properties to notify server. */ + nx_azure_iot_adu_agent_reported_properties_state_send(adu_agent_ptr); + } + + return; + } + } + + step = adu_agent_ptr -> nx_azure_iot_adu_agent_current_step; + switch (step -> state) + { + + /* Idle. */ + case NX_AZURE_IOT_ADU_AGENT_STEP_STATE_IDLE: + { + + /* Check the type and handler properties. */ + if (((step -> type_length != 0) && + (step -> type_length == sizeof(NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_INLINE) - 1) && + (!memcmp(step -> type, NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_INLINE, step -> type_length))) || + ((step -> type_length == 0) && + (step -> handler_length == sizeof(NX_AZURE_IOT_ADU_AGENT_STEP_HANDLER_SWUPDATE) - 1) && + (!memcmp(step -> handler, NX_AZURE_IOT_ADU_AGENT_STEP_HANDLER_SWUPDATE, step -> handler_length)))) + { + + /* Call method to check if the update is installed. */ + if (nx_azure_iot_adu_agent_method_is_installed(adu_agent_ptr, &(update_manifest_content -> compatibility), step, &is_installed)) + { + LogError(LogLiteralArgs("Failed to check the update")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + if (is_installed == NX_TRUE) + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_SUCCEEDED); + } + else + { + + /* Find the new update file and update it into step. */ + if (nx_azure_iot_adu_agent_file_find(adu_agent_ptr, update_manifest_content, (UCHAR *)step -> file_id, step -> file_id_length, &file)) + { + LogError(LogLiteralArgs("Failed to find update file")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + /* Set the file as new update. */ + step -> file = file; + adu_agent_ptr -> nx_azure_iot_adu_agent_update_flag = NX_TRUE; + + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED); + } + } +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) + else if ((step -> type_length == sizeof(NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_REFERENCE) - 1) && + (!memcmp(step -> type, NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_REFERENCE, step -> type_length))) + { + + /* Leaf update. */ + + /* Find the manifest file. */ + if (nx_azure_iot_adu_agent_file_find(adu_agent_ptr, update_manifest_content, (UCHAR *)step -> file_id, step -> file_id_length, &file)) + { + LogError(LogLiteralArgs("Failed to find proxy manifest file")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + /* Update the state. */ + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_MANIFEST_DOWNLOAD_STARTED); + + /* Start to download firmware. */ + if (nx_azure_iot_adu_agent_method_download(adu_agent_ptr, file, NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_MANIFEST, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE, + NX_NULL)) + { + LogError(LogLiteralArgs("Failed to download proxy manifest file")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + } + + return; + } +#endif /* (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) */ + + break; + } + +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) + case NX_AZURE_IOT_ADU_AGENT_STEP_STATE_MANIFEST_DOWNLOAD_SUCCEEDED: + { + json_data_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature; + proxy_update_manifest_ptr = json_data_ptr + downloader_ptr -> received_firmware_size; + proxy_update_manifest_size = NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE - downloader_ptr -> received_firmware_size; + proxy_update_manifest_content = &(adu_agent_ptr -> nx_azure_iot_adu_agent_proxy_update_manifest_content); + + /* There may be 3 BOM bytes (EF BB BF) for UTF-8 json, skip them if exist. */ + if ((downloader_ptr -> received_firmware_size > 3) && + ((json_data_ptr[0] == 0xEF) && (json_data_ptr[1] == 0xBB) && (json_data_ptr[2] == 0XBF))) + { + json_data_ptr +=3; + downloader_ptr -> received_firmware_size -= 3; + } + + /* Initialize the update manifest string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, + json_data_ptr, + downloader_ptr -> received_firmware_size)) + { + LogError(LogLiteralArgs("Failed to initialize proxy update manifest")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) || + (!nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST) - 1)) || + (nx_azure_iot_json_reader_next_token(&json_reader)) || + (nx_azure_iot_json_reader_token_string_get(&json_reader, + proxy_update_manifest_ptr, + proxy_update_manifest_size, + &proxy_update_manifest_size))) + { + LogError(LogLiteralArgs("Failed to process proxy update manifest")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + /* Process proxy update manifest. */ + if (nx_azure_iot_adu_agent_service_update_manifest_process(adu_agent_ptr, + proxy_update_manifest_ptr, + proxy_update_manifest_size, + proxy_update_manifest_content, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_sjwk, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE)) + { + LogError(LogLiteralArgs("Failed to process proxy update manifest")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + if (proxy_update_manifest_content -> steps_count != 1) + { + LogError(LogLiteralArgs("Failed to process proxy update manifest")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + proxy_step = &(proxy_update_manifest_content -> steps[0]); + + /* Update the installed criteria for reference step. */ + step -> installed_criteria = proxy_step -> installed_criteria; + step -> installed_criteria_length = proxy_step -> installed_criteria_length; + + /* Call method to check if the update is installed. */ + if (nx_azure_iot_adu_agent_method_is_installed(adu_agent_ptr, &(proxy_update_manifest_content -> compatibility), step, &is_installed)) + { + LogError(LogLiteralArgs("Failed to check the update")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + if (is_installed == NX_TRUE) + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_SUCCEEDED); + } + else + { + + /* Find the new update file and update it into step. */ + if (nx_azure_iot_adu_agent_file_find(adu_agent_ptr, proxy_update_manifest_content, (UCHAR *)proxy_step -> file_id, proxy_step -> file_id_length, &file)) + { + LogError(LogLiteralArgs("Failed to find update file")); + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + /* Set the file as new update. */ + step -> file = file; + adu_agent_ptr -> nx_azure_iot_adu_agent_update_flag = NX_TRUE; + + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED); + } + + break; + } +#endif /* (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) */ + + default: + { + return; + } + } + + /* Set event for next update check. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_UPDATE_EVENT); +} + +static VOID nx_azure_iot_adu_agent_download_install_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + +NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *update_manifest_content = &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content); +NX_AZURE_IOT_ADU_AGENT_STEP *step; +UINT i; + + /* Check if current step is completed or not. */ + if ((adu_agent_ptr -> nx_azure_iot_adu_agent_current_step == NX_NULL) || + (adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_SUCCEEDED) || + (adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_SUCCEEDED)) + { + + /* Find next step to download and install the next firmware. */ + for (i = 0; i < update_manifest_content -> steps_count; i++) + { + if (update_manifest_content -> steps[i].state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED) + { + break; + } + } + + if (i < update_manifest_content -> steps_count) + { + + /* Update the step to execute. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_current_step = &(update_manifest_content -> steps[i]); + } + else + { + + /* All updates are downloaded and installed. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_update_notify) + { + + /* Notify the user and let users control the update. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_update_notify(adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_UPDATE_INSTALLED, + (UCHAR *)update_manifest_content -> update_id.provider, + update_manifest_content -> update_id.provider_length, + (UCHAR *)update_manifest_content -> update_id.name, + update_manifest_content -> update_id.name_length, + (UCHAR *)update_manifest_content -> update_id.version, + update_manifest_content -> update_id.version_length); + } + else + { + + /* Set event to apply update automatically. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_APPLY_EVENT); + } + return; + } + } + + step = adu_agent_ptr -> nx_azure_iot_adu_agent_current_step; + switch (step -> state) + { + case NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED: + { + + /* Download firmware. */ + LogInfo(LogLiteralArgs("Updating firmware...")); + LogInfo(LogLiteralArgs("Manufacturer: %s"), step -> device -> device_properties.manufacturer, step -> device -> device_properties.manufacturer_length); + LogInfo(LogLiteralArgs("Model: %s"), step -> device -> device_properties.model, step -> device -> device_properties.model_length); + + /* Start to download firmware for host update. */ + if (nx_azure_iot_adu_agent_method_download(adu_agent_ptr, step -> file, NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE, + NX_NULL, 0, + step -> device -> device_driver_entry)) + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + return; + } + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_SUCCEEDED: + { + + /* Install firmware. */ + if (nx_azure_iot_adu_agent_method_install(adu_agent_ptr, step -> device -> device_driver_entry)) + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + } + else + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_SUCCEEDED); + } + + break; + } + + default: + { + break; + } + } + + return; +} + +static VOID nx_azure_iot_adu_agent_apply_event_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *manifest_content = &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content); +NX_AZURE_IOT_ADU_AGENT_STEP *step; +UINT i; +UINT step_fail = NX_FALSE; + + + /* Loop to apply the updates. */ + for (i = 0; i < manifest_content -> steps_count; i++) + { + step = &(manifest_content -> steps[i]); + + /* Check the state. */ + if (step -> state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_SUCCEEDED) + { + LogInfo(LogLiteralArgs("Applying firmware...")); + LogInfo(LogLiteralArgs("Manufacturer: %s"), step -> device -> device_properties.manufacturer, step -> device -> device_properties.manufacturer_length); + LogInfo(LogLiteralArgs("Model: %s"), step -> device -> device_properties.model, step -> device -> device_properties.model_length); + + /* Apply the update. */ + nx_azure_iot_adu_agent_method_apply(adu_agent_ptr, manifest_content -> steps[i].device -> device_driver_entry); + } + else if (manifest_content -> steps[i].state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED) + { + step_fail = NX_TRUE; + break; + } + } + + /* All steps done, update the state. */ + if (step_fail == NX_TRUE) + { + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_FAILED; + } + else + { + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_IDLE; + } + + /* Send reported properties to notify server. */ + nx_azure_iot_adu_agent_reported_properties_state_send(adu_agent_ptr); +} + +static UINT nx_azure_iot_adu_agent_manifest_verify(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; +UCHAR *header_b64; +UINT header_b64_length; +UCHAR *payload_b64; +UINT payload_b64_length; +UCHAR *signature_b64; +UINT signature_b64_length; +UCHAR *jwk_header_b64; +UINT jwk_header_b64_length; +UCHAR *jwk_payload_b64; +UINT jwk_payload_b64_length; +UCHAR *jwk_signature_b64; +UINT jwk_signature_b64_length; +UCHAR *signature; +UINT signature_length; +UINT sjwk_size = 0; +UCHAR *alg_ptr = NX_NULL; +UINT alg_size = 0; +UCHAR *kid_ptr = NX_NULL; +UINT kid_size = 0; +UCHAR *kty_ptr = NX_NULL; +UINT kty_size = 0; +UCHAR *n_b64_ptr = NX_NULL; +UINT n_b64_size = 0; +UCHAR *e_b64_ptr = NX_NULL; +UINT e_b64_size = 0; +UCHAR *n_ptr = NX_NULL; +UINT n_size = 0; +UCHAR *e_ptr = NX_NULL; +UINT e_size = 0; +UCHAR *buffer_ptr; +UINT buffer_size; +UINT bytes_copied; +NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY *rsa_root_key; +NX_AZURE_IOT_ADU_AGENT_CRYPTO *adu_agent_crypto = &(adu_agent_ptr -> nx_azure_iot_adu_agent_crypto); +NX_AZURE_IOT_JSON_READER json_reader; +UCHAR *sha256_generated_hash_ptr; +UCHAR *sha256_decoded_hash_64_ptr; +UCHAR *sha256_decoded_hash_ptr; + + /* The updateManifestSignature is used to ensure that the information contained within the updateManifest + hasn't been tampered with. + https://docs.microsoft.com/en-us/azure/iot-hub-device-update/device-update-security#json-web-signature-jws */ + + /* JWS value format: BASE64URL(UTF8(header)) + "." + BASE64URL(UTF8(payload) + "." + BASE64URL(signature)). */ + + /* Step1. Parse JWS data. */ + + /* Header: + { + "alg": "RS256", + "sjwk": "signed JWK" + } + + Payload: + { + "sha256":"xxx...xxx" + } + + Signature: + */ + + /* Initialize. */ + alg_size = 0; + sjwk_size = 0; + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_buffer; + buffer_size = NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE; + + /* 1.1 Split header, payload and signature. */ + if (nx_azure_iot_adu_agent_jws_split(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature_size, + &header_b64, &header_b64_length, + &payload_b64, &payload_b64_length, + &signature_b64, &signature_b64_length) == NX_FALSE) + { + return(NX_FALSE); + } + + /* 1.2 Decode header. */ + if (_nx_utility_base64_decode(header_b64, header_b64_length, + buffer_ptr, buffer_size, &bytes_copied)) + { + return(NX_FALSE); + } + + /* Initialize the header string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, buffer_ptr, bytes_copied)) + { + return(NX_FALSE); + } + buffer_ptr += bytes_copied; + buffer_size -= bytes_copied; + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_FALSE); + } + + /* Loop to process all data. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Get alg value. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"alg", sizeof("alg") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &alg_size)) + { + return(NX_FALSE); + } + alg_ptr = buffer_ptr; + buffer_ptr += alg_size; + buffer_size -= alg_size; + } + + /* Get sjwk value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"sjwk", sizeof("sjwk") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_sjwk, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE, + &sjwk_size)) + { + return(NX_FALSE); + } + } + else + { + return(NX_FALSE); + } + } + else + { + break; + } + } + + /* Check if there are "alg" and "sjwk" properties. */ + if ((alg_size == 0) || (sjwk_size == 0)) + { + return(NX_FALSE); + } + + /* Check if alg is supported. */ + if ((alg_size != sizeof("RS256") - 1) || memcmp(alg_ptr, "RS256", alg_size)) + { + return(NX_FALSE); + } + + /* Step2. Verify signing key is signed by master key. */ + + /* Header: + { + "alg": "RS256", + "kid": "ADU.200702.R" + } + + Payload: + { + "kty": "RSA", + "n": "xxx...xxx", + "e": "AQAB", + "alg": "RS256" + "kid": "ADU.Signing.2020-04-29" + } + + Signature: + */ + + /* Initialize. */ + alg_size = 0; + kid_size = 0; + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_buffer; + buffer_size = NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE; + + /* 2.1 Split sjwk header, payload and signature. */ + if (nx_azure_iot_adu_agent_jws_split(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_sjwk, sjwk_size, + &jwk_header_b64, &jwk_header_b64_length, + &jwk_payload_b64, &jwk_payload_b64_length, + &jwk_signature_b64, &jwk_signature_b64_length) == NX_FALSE) + { + return(NX_FALSE); + } + + /* 2.2 Decode sjwk header. */ + if (_nx_utility_base64_decode(jwk_header_b64, jwk_header_b64_length, + buffer_ptr, NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE, &bytes_copied)) + { + return(NX_FALSE); + } + + /* Initialize the header string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, buffer_ptr, bytes_copied)) + { + return(NX_FALSE); + } + buffer_ptr += bytes_copied; + buffer_size -= bytes_copied; + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_FALSE); + } + + /* Loop to process all header data. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Get alg value. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"alg", sizeof("alg") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &alg_size)) + { + return(NX_FALSE); + } + alg_ptr = buffer_ptr; + buffer_ptr += alg_size; + buffer_size -= alg_size; + } + + /* Get kid value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"kid", sizeof("kid") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &kid_size)) + { + return(NX_FALSE); + } + kid_ptr = buffer_ptr; + buffer_ptr += kid_size; + buffer_size -= kid_size; + } + else + { + return(NX_FALSE); + } + } + else + { + break; + } + } + + /* Check if there are "alg" and "kid" properties. */ + if ((alg_size == 0) || (kid_size == 0)) + { + return(NX_FALSE); + } + + /* Check if alg is supported. */ + if ((alg_size != sizeof("RS256") - 1) || memcmp(alg_ptr, "RS256", alg_size)) + { + return(NX_FALSE); + } + + /* Search master key. */ + rsa_root_key = (NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY *)nx_azure_iot_adu_agent_rsa_root_key_find(kid_ptr, kid_size); + if (rsa_root_key == NX_NULL) + { + return(NX_FALSE); + } + + /* 2.3 Decode sjwk signature. */ + signature = adu_agent_ptr -> nx_azure_iot_adu_agent_buffer; + signature_length = NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE; + if (_nx_utility_base64_decode(jwk_signature_b64, jwk_signature_b64_length, + signature, signature_length, &signature_length)) + { + return(NX_FALSE); + } + + /* 2.4 Verify signature. */ + if (nx_azure_iot_adu_agent_rs256_verify(&adu_agent_ptr -> nx_azure_iot_adu_agent_crypto, + jwk_header_b64, (jwk_header_b64_length + 1 + jwk_payload_b64_length), + signature, signature_length, + (UCHAR *)rsa_root_key -> n, rsa_root_key -> n_size, + (UCHAR *)rsa_root_key -> e, rsa_root_key -> e_size, + adu_agent_ptr -> nx_azure_iot_adu_agent_buffer + signature_length, + NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE - signature_length) == NX_FALSE) + { + return(NX_FALSE); + } + + /* Step3. Verify distroman signature is signed by the signing key. */ + + /* Initialize. */ + kty_size = 0; + n_size = 0; + e_size = 0; + kid_size = 0; + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_buffer; + buffer_size = NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE; + + /* 3.1 Decode sjwk payload to get the signing key. */ + if (_nx_utility_base64_decode(jwk_payload_b64, jwk_payload_b64_length, + buffer_ptr, buffer_size, &bytes_copied)) + { + return(NX_FALSE); + } + + /* Initialize the payload string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, buffer_ptr, bytes_copied)) + { + return(NX_FALSE); + } + buffer_ptr += bytes_copied; + buffer_size -= bytes_copied; + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_FALSE); + } + + /* Loop to process all header data. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Get kty value. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"kty", sizeof("kty") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &kty_size)) + { + return(NX_FALSE); + } + kty_ptr = buffer_ptr; + buffer_ptr += kty_size; + buffer_size -= kty_size; + } + + /* Get n value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"n", sizeof("n") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &n_b64_size)) + { + return(NX_FALSE); + } + n_b64_ptr = buffer_ptr; + buffer_ptr += n_b64_size; + buffer_size -= n_b64_size; + } + + /* Get e value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"e", sizeof("e") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &e_b64_size)) + { + return(NX_FALSE); + } + e_b64_ptr = buffer_ptr; + buffer_ptr += e_b64_size; + buffer_size -= e_b64_size; + } + + /* Get alg value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"alg", sizeof("alg") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &alg_size)) + { + return(NX_FALSE); + } + alg_ptr = buffer_ptr; + buffer_ptr += alg_size; + buffer_size -= alg_size; + } + + /* Get kid value. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"kid", sizeof("kid") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &kid_size)) + { + return(NX_FALSE); + } + kid_ptr = buffer_ptr; + buffer_ptr += kid_size; + buffer_size -= kid_size; + } + + else + { + return(NX_FALSE); + } + } + else + { + break; + } + } + + /* Check if there are "alg" and "kid" properties. */ + if ((kty_size == 0) || (n_b64_size == 0) || (e_b64_size == 0) || (kid_size == 0)) + { + return(NX_FALSE); + } + + /* Check if alg is supported. */ + if ((alg_size != sizeof("RS256") - 1) || memcmp(alg_ptr, "RS256", alg_size)) + { + return(NX_FALSE); + } + + /* Check if alg is supported. */ + if ((kty_size != sizeof("RSA") - 1) || memcmp(kty_ptr, "RSA", kty_size)) + { + return(NX_FALSE); + } + + /* 3.2 Use sjwk to decode n, e, signature and verify signature. */ + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_sjwk; + buffer_size = NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE; + n_ptr = buffer_ptr; + n_size = buffer_size; + if (_nx_utility_base64_decode(n_b64_ptr, n_b64_size, + n_ptr, n_size, &n_size)) + { + return(NX_FALSE); + } + buffer_ptr += n_size; + buffer_size -= n_size; + + e_ptr = buffer_ptr; + e_size = buffer_size; + if (_nx_utility_base64_decode(e_b64_ptr, e_b64_size, + e_ptr, e_size, &e_size)) + { + return(NX_FALSE); + } + buffer_ptr += e_size; + buffer_size -= e_size; + + signature = buffer_ptr; + signature_length = buffer_size; + if (_nx_utility_base64_decode(signature_b64, signature_b64_length, + signature, signature_length, &signature_length)) + { + return(NX_FALSE); + } + buffer_ptr += signature_length; + buffer_size -= signature_length; + + /* 3.3 Verify signature. */ + if (nx_azure_iot_adu_agent_rs256_verify(&adu_agent_ptr -> nx_azure_iot_adu_agent_crypto, + header_b64, (header_b64_length + 1 + payload_b64_length), + signature, signature_length, + n_ptr, n_size, + e_ptr, e_size, + buffer_ptr, buffer_size) == NX_FALSE) + { + return(NX_FALSE); + } + + /* Step4. Verify distroman body digest (update manifest) matches what's in JWS payload section. */ + + /* Initialize. */ + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_buffer; + buffer_size = NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE; + + /* 4.1 Calculate update manifest sha256 value. */ + sha256_generated_hash_ptr = buffer_ptr; + status = nx_azure_iot_adu_agent_sha256_calculate(adu_agent_crypto -> method_sha256, + adu_agent_crypto -> method_sha256_metadata, + NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_size, + sha256_generated_hash_ptr, + NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE); + + /* Check status. */ + if (status) + { + return(NX_FALSE); + } + buffer_ptr += NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE; + buffer_size -= NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE; + + /* 4.2 Decode the payload to get the sha256 base64 value. */ + status = _nx_utility_base64_decode(payload_b64, payload_b64_length, + buffer_ptr, buffer_size, &bytes_copied); + + /* Initialize the payload string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, buffer_ptr, bytes_copied)) + { + return(NX_FALSE); + } + buffer_ptr += bytes_copied; + buffer_size -= bytes_copied; + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_FALSE); + } + + /* Get the next token. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME)) + { + return(NX_FALSE); + } + sha256_decoded_hash_64_ptr = buffer_ptr; + + /* Get sha256 base64 value. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, (UCHAR *)"sha256", sizeof("sha256") - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + sha256_decoded_hash_64_ptr, + buffer_size, + &bytes_copied)) + { + return(NX_FALSE); + } + } + else + { + return(NX_FALSE); + } + buffer_ptr += bytes_copied; + buffer_size -= bytes_copied; + + sha256_decoded_hash_ptr = buffer_ptr; + + /* Decode sha256 base64 hash. */ + if (_nx_utility_base64_decode(sha256_decoded_hash_64_ptr, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_BASE64_SIZE, + sha256_decoded_hash_ptr, buffer_size, &bytes_copied)) + { + return(NX_FALSE); + } + + /* Verify the hash value. */ + if (memcmp(sha256_generated_hash_ptr, sha256_decoded_hash_ptr, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE)) + { + return(NX_FALSE); + } + + return(NX_TRUE); +} + +static UINT nx_azure_iot_adu_agent_jws_split(UCHAR *jws, UINT jws_length, + UCHAR **header, UINT *header_length, + UCHAR **payload, UINT *payload_length, + UCHAR **signature, UINT *signature_length) +{ + +UCHAR *dot1_pointer; +UCHAR *dot2_pointer; +UINT dot_count = 0; +UINT i = 0; + + /* Set the header pointer. */ + *header = jws; + + /* Loop to find the dots. */ + while(i < jws_length) + { + if (*jws == '.') + { + dot_count++; + + if (dot_count == 1) + { + dot1_pointer = jws; + } + else if (dot_count == 2) + { + dot2_pointer = jws; + } + else if (dot_count > 2) + { + return(NX_FALSE); + } + } + jws++; + i++; + } + + /* Check if the dot count is correct. */ + if ((dot_count != 2) || (dot2_pointer >= (*header + jws_length - 1))) + { + return(NX_FALSE); + } + + /* Set the header, payload and signature. */ + *header_length = (UINT)(dot1_pointer - *header); + *payload = dot1_pointer + 1; + *payload_length = (UINT)(dot2_pointer - *payload); + *signature = dot2_pointer + 1; + *signature_length = (UINT)((*header + jws_length) - *signature); + + return(NX_TRUE); +} + +static VOID nx_azure_iot_adu_agent_step_state_update(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT step_state) +{ + + /* Update state. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state = step_state; + + /* Check the step state. */ + if (step_state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED) + { + adu_agent_ptr -> nx_azure_iot_adu_agent_state = NX_AZURE_IOT_ADU_AGENT_STATE_FAILED; + + LogError(LogLiteralArgs("Failed to deploy update!")); + + /* Report state to server. */ + nx_azure_iot_adu_agent_reported_properties_state_send(adu_agent_ptr); + } + else if (step_state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_MANIFEST_DOWNLOAD_SUCCEEDED) + { + + /* Set event for update check. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_UPDATE_EVENT); + } + else if ((step_state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_SUCCEEDED) || + (step_state == NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_SUCCEEDED)) + { + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_DOWNLOAD_INSTALL_EVENT); + } +} + +static UINT nx_azure_iot_adu_agent_file_find(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *manifest_content, + UCHAR *file_id, UINT file_id_length, + NX_AZURE_IOT_ADU_AGENT_FILE **file) +{ +UINT i; + + *file = NX_NULL; + + /* Find file. */ + for (i = 0; i < manifest_content -> files_count; i++) + { + + /* Check the file id. */ + if ((file_id_length == manifest_content -> files[i].file_id_length) && + (!memcmp(file_id, manifest_content -> files[i].file_id, file_id_length))) + { + + /* Find the file. */ + *file = &(manifest_content -> files[i]); + break; + } + } + + /* Check if find the file. */ + if (*file == NX_NULL) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + + /* Find the file url. */ + for (i = 0; i < adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls_count; i++) + { + + /* Check the file id. */ + if ((file_id_length == adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls[i].file_id_length) && + (!memcmp(file_id, adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls[i].file_id, file_id_length))) + { + + /* Find the file url. */ + (*file) -> file_url = adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls[i].file_url; + (*file) -> file_url_length = adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls[i].file_url_length; + break; + } + } + + /* Check if find the file url. */ + if (i >= adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls_count) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_adu_agent_method_is_installed(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY *compatibility, + NX_AZURE_IOT_ADU_AGENT_STEP *step, + UINT *is_installed) +{ +UINT i; +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; + + *is_installed = NX_FALSE; + + /* Check if compatibility and installed criteria in step are correct. */ + if ((compatibility -> device_manufacturer == NX_NULL) || + (compatibility -> device_manufacturer_length == 0) || + (compatibility -> device_model == NX_NULL) || + (compatibility -> device_model_length == 0) || + (step -> installed_criteria == NX_NULL) || + (step -> installed_criteria_length == 0)) + { + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Find the device according to compatibility. */ + for (i = 0; i < NX_AZURE_IOT_ADU_AGENT_DEVICE_COUNT; i++) + { + + /* Check if the device is valid. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].valid == NX_FALSE) + { + continue; + } + + /* Compare the compatility (manufacturer and model). */ + if ((compatibility -> device_manufacturer_length == adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.manufacturer_length) && + (!memcmp(compatibility -> device_manufacturer, adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.manufacturer, compatibility -> device_manufacturer_length)) && + (compatibility -> device_model_length == adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.model_length) && + (!memcmp(compatibility -> device_model, adu_agent_ptr -> nx_azure_iot_adu_agent_device[i].device_properties.model, compatibility -> device_model_length))) + { + + /* Set the matching device. */ + step -> device = &adu_agent_ptr -> nx_azure_iot_adu_agent_device[i]; + break; + } + } + + /* Check if device with matching properties. */ + if (step -> device == NX_NULL) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + + /* Check if agent has the installed criteria. */ + if (step -> device -> installed_criteria_length) + { + + /* Check if already installed this update. */ + if ((step -> installed_criteria_length == step -> device -> installed_criteria_length) && + (!memcmp(step -> installed_criteria, step -> device -> installed_criteria, step -> installed_criteria_length))) + { + *is_installed = NX_TRUE; + } + else + { + *is_installed = NX_FALSE; + } + + } + else + { + + /* Call the driver to check if this update is installed. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK; + driver_request.nx_azure_iot_adu_agent_driver_installed_criteria = step -> installed_criteria; + driver_request.nx_azure_iot_adu_agent_driver_installed_criteria_length = step -> installed_criteria_length; + driver_request.nx_azure_iot_adu_agent_driver_return_ptr = (ULONG *)is_installed; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (step -> device -> device_driver_entry)(&driver_request); + + /* Check status. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + return(NX_AZURE_IOT_FAILURE); + } + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_adu_agent_method_download(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_ADU_AGENT_FILE *file, + UINT type, UCHAR *manifest_buffer_ptr, UINT manifest_buffer_size, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)) +{ +UINT status; +UCHAR *buffer_ptr; +UINT buffer_size; +NX_DNS *dns_ptr; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr; +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; + + + /* Check if include download file. */ + if ((file -> file_url == NX_NULL) || + (file -> file_url_length == 0) || + (file -> file_sha256 == NX_NULL) || + (file -> file_sha256_length == 0) || + (file -> file_size_in_bytes == 0)) + { + return(NX_AZURE_IOT_FAILURE); + } + + /* Check type. */ + if (((type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE) && (adu_agent_driver == NX_NULL)) || + ((type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_MANIFEST) && ((manifest_buffer_ptr == NX_NULL) || (manifest_buffer_size == 0)))) + { + return(NX_AZURE_IOT_FAILURE); + } + + /* Initialization. */ + downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + dns_ptr = downloader_ptr -> dns_ptr; + memset(downloader_ptr, 0, sizeof(NX_AZURE_IOT_ADU_AGENT_DOWNLOADER)); + downloader_ptr -> dns_ptr = dns_ptr; + downloader_ptr -> file = file; + downloader_ptr -> type = type; + downloader_ptr -> manifest_buffer_ptr = manifest_buffer_ptr; + downloader_ptr -> manifest_buffer_size = manifest_buffer_size; + downloader_ptr -> driver_entry = adu_agent_driver; + + buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest; + buffer_size = NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE; + + if (type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE) + { + + /* Output info. */ + LogInfo(LogLiteralArgs("Firmware downloading...")); + + /* Send the preprocess request to the driver. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_PREPROCESS; + driver_request.nx_azure_iot_adu_agent_driver_firmware_size = file -> file_size_in_bytes; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (downloader_ptr -> driver_entry)(&driver_request); + + /* Check status. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + LogError(LogLiteralArgs("Firmware download fail: DRIVER PREPROCESS ERROR")); + return(NX_AZURE_IOT_FAILURE); + } + } + + /* Parse the url. */ + status = nx_azure_iot_adu_agent_file_url_parse(file -> file_url, + file -> file_url_length, + buffer_ptr, buffer_size, downloader_ptr); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: URL PARSE ERROR")); + return(status); + } + + /* Check if start dns query to get the address. */ + if (downloader_ptr -> state == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_URL_PARSED) + { + + /* Start dns query. */ + nx_azure_iot_adu_agent_dns_query(adu_agent_ptr); + } + else if (downloader_ptr -> state == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_DONE) + { + + /* Start HTTP connect. */ + nx_azure_iot_adu_agent_http_connect(adu_agent_ptr); + } + + /* Return. */ + return(status); +} + +static UINT nx_azure_iot_adu_agent_method_install(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)) +{ +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; + + NX_PARAMETER_NOT_USED(adu_agent_ptr); + + /* Output info. */ + LogInfo(LogLiteralArgs("Firmware installing...")); + + /* Send the firmware install request to the driver. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_INSTALL; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (adu_agent_driver)(&driver_request); + + /* Install firmware. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + LogError(LogLiteralArgs("Firmware install fail: DRIVER ERROR")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Output info. */ + LogInfo(LogLiteralArgs("Firmware installed")); + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_adu_agent_method_apply(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + VOID (*adu_agent_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)) +{ +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; + + NX_PARAMETER_NOT_USED(adu_agent_ptr); + + /* Applying... */ + LogInfo(LogLiteralArgs("Firmware applying...")); + + /* Send the firmware apply request to the driver. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_APPLY; + (adu_agent_driver)(&driver_request); + + /* Install firmware. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + LogError(LogLiteralArgs("Firmware apply fail: DRIVER ERROR")); + return(NX_AZURE_IOT_FAILURE); + } + + /* Applying host update will reboot the device and never return. */ + LogInfo(LogLiteralArgs("Firmware applied\r\n\r\n")); + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_adu_agent_service_properties_get(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_JSON_READER *json_reader_ptr) +{ +UCHAR *file_buffer_ptr; +UINT file_buffer_size; +NX_AZURE_IOT_ADU_AGENT_FILE_URLS *file_urls = &(adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls); +NX_AZURE_IOT_ADU_AGENT_WORKFLOW *workflow = &(adu_agent_ptr -> nx_azure_iot_adu_agent_workflow); + + + /* Initialization. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_size = 0; + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature_size = 0; + memset(file_urls, 0, sizeof (NX_AZURE_IOT_ADU_AGENT_FILE_URLS)); + memset(workflow, 0, sizeof (NX_AZURE_IOT_ADU_AGENT_WORKFLOW)); + + /* Skip service property. */ + nx_azure_iot_json_reader_next_token(json_reader_ptr); + + /* Next one should be begin object. */ + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Loop to process all data. */ + while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Workflow. */ + if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW) - 1)) + { + + /* Skip the workflow property name. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Check the token type. */ + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Loop to process workflow content. */ + while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION) - 1)) + { + /* Get action data. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || + nx_azure_iot_json_reader_token_int32_get(json_reader_ptr, (int32_t *)&(workflow -> action))) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Get id. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID) - 1)) + { + + /* Get id string. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || + nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + workflow -> id, + NX_AZURE_IOT_ADU_AGENT_WORKFLOW_ID_SIZE, + &(workflow -> id_length))) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Get retry timestamp. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP) - 1)) + { + + /* Get retry timestamp string. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || + nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + workflow -> retry_timestamp, + NX_AZURE_IOT_ADU_AGENT_WORKFLOW_RETRY_TIMESTAMP_SIZE, + &(workflow -> retry_timestamp_length))) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + } + + /* Update manifest. */ + if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST) - 1)) + { + + /* Get update manifest string. */ + if ((nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_SUCCESS) && + (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_STRING)) + { + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE, + &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_size))) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + + /* Update manifest signature. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST_SIGNATURE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST_SIGNATURE) - 1)) + { + + /* Get update manifest signature. */ + if ((nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_SUCCESS) && + (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_STRING)) + { + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE, + &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_signature_size))) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + + /* File URLs. + Note: 1. file urls property can exist or not. + 2. file urls property value can be object. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILEURLS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILEURLS) - 1)) + { + + /* Skip the file urls property name. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Check the token type. */ + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + + /* Start to parse file array. */ + file_buffer_ptr = adu_agent_ptr -> nx_azure_iot_adu_agent_file_urls.file_urls_buffer; + file_buffer_size = NX_AZURE_IOT_ADU_AGENT_FILE_URLS_MAX; + + while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) + { + + /* Check if it is the end object. */ + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + + if (file_urls -> file_urls_count < NX_AZURE_IOT_ADU_AGENT_FILES_MAX) + { + + /* Store the file number. */ + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + file_buffer_ptr, + file_buffer_size, + &(file_urls -> file_urls[file_urls -> file_urls_count].file_id_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(file_urls -> file_urls[file_urls -> file_urls_count].file_id, + file_urls -> file_urls[file_urls -> file_urls_count].file_id_length, + file_buffer_ptr, file_buffer_size); + + /* Get file url. */ + if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || + nx_azure_iot_json_reader_token_string_get(json_reader_ptr, + file_buffer_ptr, + file_buffer_size, + &(file_urls -> file_urls[file_urls -> file_urls_count].file_url_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file url pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(file_urls -> file_urls[file_urls -> file_urls_count].file_url, + file_urls -> file_urls[file_urls -> file_urls_count].file_url_length, + file_buffer_ptr, file_buffer_size); + + file_urls -> file_urls_count++; + } + else + { + if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + } + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == + NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_adu_agent_service_update_manifest_process(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UCHAR *update_manifest, + UINT update_manifest_size, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *update_manifest_content, + UCHAR *update_manifest_content_buffer, + UINT update_manifest_content_buffer_size) +{ + +UCHAR *buffer_ptr = update_manifest_content_buffer; +UINT buffer_size = update_manifest_content_buffer_size; +UINT i = 0; +NX_AZURE_IOT_JSON_READER json_reader; +NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY *compatibility = &(update_manifest_content -> compatibility); + + NX_PARAMETER_NOT_USED(adu_agent_ptr); + + /* Initialization. */ + memset(update_manifest_content, 0, sizeof (NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT)); + + /* Initialize the update manifest string as json. */ + if (nx_azure_iot_json_reader_with_buffer_init(&json_reader, update_manifest, update_manifest_size)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Loop to process all data. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Manifest version. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANIFEST_VERSION, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANIFEST_VERSION) - 1)) + { + + /* Get manifest version value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> manifest_version_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> manifest_version, + update_manifest_content -> manifest_version_length, + buffer_ptr, buffer_size); + } + + /* Update id. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_ID) - 1)) + { + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Loop to process all update id field. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Provider. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER) - 1)) + { + + /* Get the provider value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> update_id.provider_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> update_id.provider, + update_manifest_content -> update_id.provider_length, + buffer_ptr, buffer_size); + } + + /* Name. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME) - 1)) + { + + /* Get the name value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> update_id.name_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> update_id.name, + update_manifest_content -> update_id.name_length, + buffer_ptr, buffer_size); + } + + /* Version. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION) - 1)) + { + + /* Get the version value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> update_id.version_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> update_id.version, + update_manifest_content -> update_id.version_length, + buffer_ptr, buffer_size); + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + + else if (nx_azure_iot_json_reader_token_type(&json_reader) == + NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == + NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + } + + /* Compatibility. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPATIBILITY, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPATIBILITY) - 1)) + { + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_ARRAY) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Device manufacturer. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANUFACTURER, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANUFACTURER) - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(compatibility -> device_manufacturer_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(compatibility -> device_manufacturer, + compatibility -> device_manufacturer_length, + buffer_ptr, buffer_size); + } + + /* Device model. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MODEL, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MODEL) - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(compatibility -> device_model_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(compatibility -> device_model, + compatibility -> device_model_length, + buffer_ptr, buffer_size); + } + + /* Group. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_GROUP, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_GROUP) - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(compatibility -> group_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(compatibility -> group, + compatibility -> group_length, + buffer_ptr, buffer_size); + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_END_ARRAY)) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Instructions. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTRUCTIONS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTRUCTIONS) - 1)) + { + + /* Skip the first begin object. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEPS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEPS) - 1) != NX_TRUE) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_ARRAY)) + { + return(NX_NOT_SUCCESSFUL); + } + + i = 0; + + /* Loop to process steps array. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_END_ARRAY) + { + break; + } + + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + + /* Check if have enough space. */ + if (update_manifest_content -> steps_count >= NX_AZURE_IOT_ADU_AGENT_STEPS_MAX) + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + continue; + } + + /* Loop to process properties in step. */ + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Type. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_TYPE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_TYPE) - 1)) + { + + /* Get type value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> steps[i].type_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file number pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> steps[i].type, + update_manifest_content -> steps[i].type_length, + buffer_ptr, buffer_size); + } + + /* Handler. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLE) - 1)) + { + + /* Get handle value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> steps[i].handler_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> steps[i].handler, + update_manifest_content -> steps[i].handler_length, + buffer_ptr, buffer_size); + } + + /* Handler properties: installedCriteria. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLER_PROPERTIES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLER_PROPERTIES) - 1)) + { + + /* Skip the installedCriteria property name. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CRITERIA, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CRITERIA) - 1) != NX_TRUE)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Get installedCriteria value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> steps[i].installed_criteria_length)) || + (nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_END_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> steps[i].installed_criteria, + update_manifest_content -> steps[i].installed_criteria_length, + buffer_ptr, buffer_size); + } + + /* Files. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILES) - 1)) + { + + /* Get files value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_ARRAY) || + nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> steps[i].file_id_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> steps[i].file_id, + update_manifest_content -> steps[i].file_id_length, + buffer_ptr, buffer_size); + + /* Skip end array. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_END_ARRAY)) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Detached Manifest File Id. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DETACHED_MANIFEST_FILED, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DETACHED_MANIFEST_FILED) - 1)) + { + + /* Get files value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> steps[i].file_id_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> steps[i].file_id, + update_manifest_content -> steps[i].file_id_length, + buffer_ptr, buffer_size); + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + i++; + update_manifest_content -> steps_count++; + break; + } + } + } + } + + /* Skip the end object of steps. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_END_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Files. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILES) - 1)) + { + i = 0; + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + if (update_manifest_content -> files_count >= NX_AZURE_IOT_ADU_AGENT_FILES_MAX) + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + continue; + } + + /* Get the file id. */ + if (nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> files[i].file_id_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file id pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> files[i].file_id, + update_manifest_content -> files[i].file_id_length, + buffer_ptr, buffer_size); + + while (nx_azure_iot_json_reader_next_token(&json_reader) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) + { + + /* Filename. */ + if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILE_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILE_NAME) - 1)) + { + + /* Get the file name value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> files[i].file_name_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Set file name pointer and update the buffer size. */ + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> files[i].file_name, + update_manifest_content -> files[i].file_name_length, + buffer_ptr, buffer_size); + } + + /* Size in bytes. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SIZE_IN_BYTES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SIZE_IN_BYTES) - 1)) + { + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_uint32_get(&json_reader, + (uint32_t *)&(update_manifest_content -> files[i].file_size_in_bytes))) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Hashes. */ + else if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HASHES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HASHES) - 1)) + { + + /* Skip the begin object of hashes property. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* sha256. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + !nx_azure_iot_json_reader_token_is_text_equal(&json_reader, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SHA256, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SHA256) - 1)) + { + return(NX_NOT_SUCCESSFUL); + } + + /* Get the sha256 value value. */ + if (nx_azure_iot_json_reader_next_token(&json_reader) || + nx_azure_iot_json_reader_token_string_get(&json_reader, + buffer_ptr, + buffer_size, + &(update_manifest_content -> files[i].file_sha256_length))) + { + return(NX_NOT_SUCCESSFUL); + } + + NX_AZURE_IOT_ADU_AGENT_PTR_UPDATE(update_manifest_content -> files[i].file_sha256, + update_manifest_content -> files[i].file_sha256_length, + buffer_ptr, buffer_size); + + /* Skip the end object of hashes property. */ + if ((nx_azure_iot_json_reader_next_token(&json_reader) != NX_AZURE_IOT_SUCCESS) || + (nx_azure_iot_json_reader_token_type(&json_reader) != NX_AZURE_IOT_READER_TOKEN_END_OBJECT)) + { + return(NX_NOT_SUCCESSFUL); + } + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + i++; + update_manifest_content -> files_count++; + break; + } + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == + NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + } + + /* Skip the unknown properties. */ + else + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + } + + else if (nx_azure_iot_json_reader_token_type(&json_reader) == + NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + if (nx_azure_iot_json_reader_skip_children(&json_reader)) + { + return(NX_NOT_SUCCESSFUL); + } + } + else if (nx_azure_iot_json_reader_token_type(&json_reader) == + NX_AZURE_IOT_READER_TOKEN_END_OBJECT) + { + break; + } + } + + return(NX_AZURE_IOT_SUCCESS); +} + +/* agent reported properties for startup: +{ + "deviceUpdate": { + "__t": "c", + "agent": { + "deviceProperties": { + "manufacturer": "Microsoft", + "model": "MS-Board", + "interfaceId": "dtmi:azure:iot:deviceUpdate;1", + }, + "compatPropertyNames": "manufacturer,model", + } + } +} +*/ +static UINT nx_azure_iot_adu_agent_reported_properties_startup_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT wait_option) +{ + +NX_PACKET *packet_ptr; +NX_AZURE_IOT_JSON_WRITER json_writer; +NX_AZURE_IOT_ADU_AGENT_DEVICE_PROPERTIES *device_properties = &(adu_agent_ptr -> nx_azure_iot_adu_agent_device_properties); +UINT status; +UINT response_status; + + /* Create json writer for client reported property. */ + status = nx_azure_iot_hub_client_reported_properties_create(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, &packet_ptr, wait_option); + if (status) + { + return(status); + } + + /* Init json writer. */ + status = nx_azure_iot_json_writer_init(&json_writer, packet_ptr, wait_option); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Append begin object. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the ADU agent component name. */ + status = nx_azure_iot_hub_client_reported_properties_component_begin(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, + &json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Fill the agent property name. */ + if (nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_AGENT, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_AGENT) - 1)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Start to fill agent property value. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the deviceProperties. */ + if ((nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DEVICEPROPERTIES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DEVICEPROPERTIES) - 1)) || + (nx_azure_iot_json_writer_append_begin_object(&json_writer)) || + (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANUFACTURER, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANUFACTURER) - 1, + device_properties -> manufacturer, device_properties -> manufacturer_length)) || + (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MODEL, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MODEL) - 1, + device_properties -> model, device_properties -> model_length)) || + (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INTERFACE_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INTERFACE_ID) - 1, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_INTERFACE_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_INTERFACE_ID) - 1)) || + (nx_azure_iot_json_writer_append_end_object(&json_writer))) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the comatability property. */ + if (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPAT_PROPERTY_NAMES, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPAT_PROPERTY_NAMES) - 1, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_VALUE_COMPATIBILITY, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_VALUE_COMPATIBILITY) - 1)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* End the client property value. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* End ADU agent component. */ + if (nx_azure_iot_hub_client_reported_properties_component_end(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, &json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* End json object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Send agent reported properties startup message to IoT Hub. */ + status = nx_azure_iot_hub_client_reported_properties_send(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, + packet_ptr, + NX_NULL, &response_status, + NX_NULL, wait_option); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Check the response statue for blocking. */ + if (wait_option) + { + if ((response_status < 200) || (response_status >= 300)) + { + return(NX_NOT_SUCCESSFUL); + } + } + + return(NX_AZURE_IOT_SUCCESS); +} + +/* agent reported properties state: +{ + "deviceUpdate": { + "__t": "c", + "agent": { + "state": 0, + "workflow": { + "action": 3, + "id": "someguid", + "retryTimestamp": "2020-04-22T12:12:12.0000000+00:00" + }, + "installedUpdateId": "{\"provider\":\"Microsoft\",\"Name\":\"MS-Board\",\"Version\":\"1.0.0\"}",, + "lastInstallResult": { + "resultCode": 700, + "extendedResultCode": 0, + "resultDetails": "", + "stepResults": { + "step_0": { + "resultCode": 700, + "extendedResultCode": 0, + "resultDetails": "" + } + } + } + } + } +} +*/ +static UINT nx_azure_iot_adu_agent_reported_properties_state_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + +NX_PACKET *packet_ptr; +NX_AZURE_IOT_JSON_WRITER json_writer; +NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT *manifest_content = &(adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content); +UINT status; +UINT result_code; +UINT i; +/* Prepare the buffer for step name: such as: "step_0", the max name is "step_xxx". */ +CHAR step_property_name[8] = "step_"; +UINT step_size = sizeof("step_") - 1; +UINT step_property_name_size; +UINT update_id_length; + + /* Create json writer for client reported property. */ + status = nx_azure_iot_hub_client_reported_properties_create(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, &packet_ptr, NX_NO_WAIT); + if (status) + { + return(status); + } + + /* Init json writer. */ + status = nx_azure_iot_json_writer_init(&json_writer, packet_ptr, NX_NO_WAIT); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Append begin object. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the ADU agent component name. */ + status = nx_azure_iot_hub_client_reported_properties_component_begin(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, + &json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Fill the agent property name. */ + if (nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_AGENT, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_AGENT) - 1)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Start to fill agent property value. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the state. */ + if (nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STATE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STATE) - 1, + (INT)adu_agent_ptr -> nx_azure_iot_adu_agent_state)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the workflow. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.id_length) + { + if (nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW, + sizeof (NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW) - 1) || + nx_azure_iot_json_writer_append_begin_object(&json_writer) || + nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION) - 1, + (INT)adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.action) || + nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.id, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.id_length)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* End workflow object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + } + + /* Append retry timestamp in workflow if existed. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp_length) + { + if (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp_length)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + } + + /* Fill installed update id. */ + if ((adu_agent_ptr -> nx_azure_iot_adu_agent_state == NX_AZURE_IOT_ADU_AGENT_STATE_IDLE) && + (adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content.steps_count)) + { + + /* Use nx_azure_iot_adu_agent_update_manifest as temporary buffer to encode the update id as string.*/ + update_id_length = (UINT)snprintf((CHAR *)adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE, + "{\"%.*s\":\"%.*s\",\"%.*s\":\"%.*s\",\"%.*s\":\"%.*s\"}", + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER) - 1, + NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER, + manifest_content -> update_id.provider_length, manifest_content -> update_id.provider, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME) - 1, + NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME, + manifest_content -> update_id.name_length, manifest_content -> update_id.name, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION) - 1, + NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION, + manifest_content -> update_id.version_length, manifest_content -> update_id.version); + + if (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CONTENT_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CONTENT_ID) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + update_id_length)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + } + + /* Fill the last install result. */ + if ((adu_agent_ptr -> nx_azure_iot_adu_agent_state != NX_AZURE_IOT_ADU_AGENT_STATE_DEPLOYMENT_IN_PROGRESS) && + (adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content.steps_count)) + { + + /* Check the state. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_state == NX_AZURE_IOT_ADU_AGENT_STATE_IDLE) + { + result_code = NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_APPLY_SUCCESS; + } + else + { + result_code = NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_FAILURE; + } + + if ((nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_LAST_INSTALL_RESULT, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_LAST_INSTALL_RESULT) - 1)) || + (nx_azure_iot_json_writer_append_begin_object(&json_writer)) || + (nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_CODE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_CODE) - 1, + (int32_t)result_code)) || + (nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_EXTENDED_RESULT_CODE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_EXTENDED_RESULT_CODE) - 1, + 0)) || + (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_DETAILS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_DETAILS) - 1, + NX_NULL, 0)) || + (nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEP_RESULTS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEP_RESULTS) - 1)) || + (nx_azure_iot_json_writer_append_begin_object(&json_writer))) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Loop to fill the step results. */ + for (i = 0; i < adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_content.steps_count; i++) + { + if ((step_property_name_size = _nx_utility_uint_to_string(i, 10, &step_property_name[step_size], 8 - step_size)) == 0) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + step_property_name_size += step_size; + + if ((nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)step_property_name, + step_property_name_size)) || + (nx_azure_iot_json_writer_append_begin_object(&json_writer)) || + (nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_CODE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_CODE) - 1, + (int32_t)result_code)) || + (nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_EXTENDED_RESULT_CODE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_EXTENDED_RESULT_CODE) - 1, + 0)) || + (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_DETAILS, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_DETAILS) - 1, + NX_NULL, 0)) || + (nx_azure_iot_json_writer_append_end_object(&json_writer))) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + } + + if ((nx_azure_iot_json_writer_append_end_object(&json_writer)) || + (nx_azure_iot_json_writer_append_end_object(&json_writer))) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + } + + /* End the client property value. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* End ADU agent component. */ + if (nx_azure_iot_hub_client_reported_properties_component_end(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, &json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* End json object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Send device info reported properties message to IoT Hub. */ + status = nx_azure_iot_hub_client_reported_properties_send(adu_agent_ptr -> nx_azure_iot_hub_client_ptr, + packet_ptr, + NX_NULL, NX_NULL, + NX_NULL, NX_NO_WAIT); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +/* service reported properties sample: + + { + "azureDeviceUpdateAgent": { + "__t": "c", + "": { + "ac": , + "av": , + "ad": "", + "value": + } + } + } +*/ + +/** + * @brief Send service reported properties. + * + * @param updateState state to report. + * @param result Result to report (optional, can be NULL). + */ +static UINT nx_azure_iot_adu_agent_service_reported_properties_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UINT status_code, ULONG version, const CHAR *description, + ULONG wait_option) +{ +NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = adu_agent_ptr -> nx_azure_iot_hub_client_ptr; +NX_AZURE_IOT_JSON_WRITER json_writer; +NX_PACKET *packet_ptr; +UINT status; + + /* Create json writer for service reported property. */ + status = nx_azure_iot_hub_client_reported_properties_create(iothub_client_ptr, &packet_ptr, wait_option); + if (status) + { + return(status); + } + + /* Init json writer. */ + status = nx_azure_iot_json_writer_init(&json_writer, packet_ptr, wait_option); + if (status) + { + nx_packet_release(packet_ptr); + return(status); + } + + /* Append begin object. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill the response of writable service properties. */ + if (nx_azure_iot_hub_client_reported_properties_component_begin(iothub_client_ptr, &json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME, + sizeof(NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME) - 1) || + nx_azure_iot_hub_client_reported_properties_status_begin(iothub_client_ptr, &json_writer, + (UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SERVICE, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SERVICE) - 1, + status_code, version, + (const UCHAR *)description, strlen(description))) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* Append begin object to start to fill user value. */ + if (nx_azure_iot_json_writer_append_begin_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* Fill the workflow. */ + if (nx_azure_iot_json_writer_append_property_name(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW, + sizeof (NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW) - 1) || + nx_azure_iot_json_writer_append_begin_object(&json_writer) || + nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION) - 1, + (INT)adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.action) || + nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.id, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.id_length)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* Append retry timestamp in workflow if existed. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp_length) + { + if (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp, + adu_agent_ptr -> nx_azure_iot_adu_agent_workflow.retry_timestamp_length)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + } + + /* End workflow object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Fill updateManifest. */ + if (nx_azure_iot_json_writer_append_property_with_string_value(&json_writer, + (const UCHAR *)NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST, + sizeof(NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST) - 1, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest, + adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest_size)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* Append end object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* End status and component. */ + if (nx_azure_iot_hub_client_reported_properties_status_end(iothub_client_ptr, &json_writer) || + nx_azure_iot_hub_client_reported_properties_component_end(iothub_client_ptr, &json_writer)) + { + nx_packet_release(packet_ptr); + return (NX_NOT_SUCCESSFUL); + } + + /* End json object. */ + if (nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + nx_packet_release(packet_ptr); + return(NX_NOT_SUCCESSFUL); + } + + /* Send service reported property. */ + status = nx_azure_iot_hub_client_reported_properties_send(iothub_client_ptr, + packet_ptr, NX_NULL, + NX_NULL, NX_NULL, + wait_option); + if(status) + { + nx_packet_release(packet_ptr); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +extern const NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY _nx_azure_iot_adu_agent_rsa_root_key_list[]; +extern const UINT _nx_azure_iot_adu_agent_rsa_root_key_list_size; +static const NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY *nx_azure_iot_adu_agent_rsa_root_key_find(const UCHAR* kid, UINT kid_size) +{ + + /* Loop to find the root key. */ + for (UINT i = 0; i < _nx_azure_iot_adu_agent_rsa_root_key_list_size; i++) + { + + /* Check the kid. */ + if ((kid_size == _nx_azure_iot_adu_agent_rsa_root_key_list[i].kid_size) && + (memcmp(kid, _nx_azure_iot_adu_agent_rsa_root_key_list[i].kid, kid_size) == 0)) + { + + /* Find the root key. */ + return(&_nx_azure_iot_adu_agent_rsa_root_key_list[i]); + } + } + + return(NX_NULL); +} + +/* SHA256. */ +static UINT nx_azure_iot_adu_agent_sha256_calculate(NX_CRYPTO_METHOD *sha256_method, + UCHAR *metadata_ptr, UINT metadata_size, + UCHAR *input_ptr, ULONG input_size, + UCHAR *output_ptr, ULONG output_size) +{ +UINT status; + + + /* Initialize crypto method. */ + if (sha256_method -> nx_crypto_init) + { + status = sha256_method -> nx_crypto_init((NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + NX_NULL, + metadata_ptr, + metadata_size); + + /* Check status. */ + if (status) + { + return(status); + } + } + + /* Initialize hash. */ + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, + NX_NULL, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + NX_NULL, + 0, + metadata_ptr, + metadata_size, + NX_NULL, + NX_NULL); + + /* Update hash value for data. */ + if (status == NX_SUCCESS) + { + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + NX_NULL, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + input_ptr, + input_size, + NX_NULL, + NX_NULL, + 0, + metadata_ptr, + metadata_size, + NX_NULL, + NX_NULL); + } + + /* Calculate the hash value. */ + if (status == NX_SUCCESS) + { + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, + NX_NULL, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + output_ptr, + output_size, + metadata_ptr, + metadata_size, + NX_NULL, + NX_NULL); + } + + /* Cleanup. */ + if (sha256_method -> nx_crypto_cleanup) + { + sha256_method -> nx_crypto_cleanup(metadata_ptr); + } + + return(status); +} + + +/* RS256. */ +static UINT nx_azure_iot_adu_agent_rs256_verify(NX_AZURE_IOT_ADU_AGENT_CRYPTO *adu_agent_crypto, + UCHAR *input_ptr, ULONG input_size, + UCHAR *signature_ptr, ULONG signature_size, + UCHAR *n, ULONG n_size, + UCHAR *e, ULONG e_size, + UCHAR *buffer_ptr, UINT buffer_size) +{ + +UINT status; +UCHAR *oid; +UINT oid_length; +UCHAR *decrypted_hash; +UINT decrypted_hash_length; +UCHAR *rsa_buffer = buffer_ptr; +UCHAR *sha_buffer = buffer_ptr + NX_AZURE_IOT_ADU_AGENT_RSA3072_SIZE; + + /* Check buffer size. */ + if (buffer_size < (NX_AZURE_IOT_ADU_AGENT_RSA3072_SIZE + NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE)) + { + return(NX_FALSE); + } + + /* Decrypt the signature by RSA. */ + + /* Initialize. */ + status = adu_agent_crypto -> method_rsa -> nx_crypto_init((NX_CRYPTO_METHOD*)adu_agent_crypto -> method_rsa, + n, + n_size << 3, + NX_NULL, + adu_agent_crypto -> method_rsa_metadata, + adu_agent_crypto -> method_rsa_metadata_size); + + /* Check status. */ + if (status) + { + return(NX_FALSE); + } + + /* Decrypt the signature. */ + status = adu_agent_crypto -> method_rsa -> nx_crypto_operation(NX_CRYPTO_DECRYPT, + NX_NULL, + (NX_CRYPTO_METHOD*)adu_agent_crypto -> method_rsa, + e, + e_size << 3, + signature_ptr, + signature_size, + NX_NULL, + rsa_buffer, + NX_AZURE_IOT_ADU_AGENT_RSA3072_SIZE, + adu_agent_crypto -> method_rsa_metadata, + adu_agent_crypto -> method_rsa_metadata_size, + NX_NULL, + NX_NULL); + + /* Cleanup. */ + if (adu_agent_crypto -> method_rsa -> nx_crypto_cleanup) + { + adu_agent_crypto -> method_rsa -> nx_crypto_cleanup(adu_agent_crypto -> method_rsa_metadata); + } + + /* Check status. */ + if (status) + { + return(NX_FALSE); + } + + /* Decode the decrypted signature, which should be in PKCS#7 format. */ + status = _nx_secure_x509_pkcs7_decode(rsa_buffer, signature_size, + (const UCHAR **)&oid, &oid_length, + (const UCHAR **)&decrypted_hash, &decrypted_hash_length); + + /* Check status. */ + if (status) + { + return(NX_FALSE); + } + + /* Calculate input by SHA256. */ + status = nx_azure_iot_adu_agent_sha256_calculate(adu_agent_crypto -> method_sha256, + adu_agent_crypto -> method_sha256_metadata, + NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE, + input_ptr, input_size, + sha_buffer, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE); + + /* Check status. */ + if (status) + { + return(NX_FALSE); + } + + /* Verify. */ + if ((decrypted_hash_length != NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE) || + (memcmp(decrypted_hash, sha_buffer, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE))) + { + return(NX_FALSE); + } + + return(NX_TRUE); +} + +static UINT nx_azure_iot_adu_agent_file_url_parse(UCHAR *file_url, ULONG file_url_length, + UCHAR *buffer_ptr, UINT buffer_size, + NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr) +{ +UINT i; +UINT dot_count = 0; +UINT temp = 0; +ULONG ip_address = 0; +UCHAR address_found = NX_FALSE; +UCHAR port_found = NX_FALSE; + + + /* Initialize. */ + downloader_ptr -> host = NX_NULL; + downloader_ptr -> resource = NX_NULL; + + /* Format: http://host:port/resource. */ + if (memcmp(file_url, NX_AZURE_IOT_ADU_AGENT_HTTP_PROTOCOL, sizeof(NX_AZURE_IOT_ADU_AGENT_HTTP_PROTOCOL) - 1)) + { + return(NX_AZURE_IOT_FAILURE); + } + + /* Set the host ptr. */ + file_url += (sizeof(NX_AZURE_IOT_ADU_AGENT_HTTP_PROTOCOL) - 1); + file_url_length -= (sizeof(NX_AZURE_IOT_ADU_AGENT_HTTP_PROTOCOL) - 1); + + /* Try to detect whether the host is numerical IP address. */ + for (i = 0; i < file_url_length; i++) + { + if (file_url[i] >= '0' && file_url[i] <= '9') + { + temp = (UINT)(temp * 10 + (UINT)(file_url[i] - '0')); + if ((temp > 0xFF && port_found == NX_FALSE) || + (temp > 0xFFFF && port_found == NX_TRUE)) + { + break; + } + } + else if (file_url[i] == '.') + { + if (dot_count++ == 3) + { + break; + } + ip_address = (ip_address << 8) + temp; + temp = 0; + } + else if (file_url[i] == ':') + { + if ((dot_count != 3) || (port_found == NX_TRUE)) + { + break; + } + ip_address = (ip_address << 8) + temp; + + /* Set the address. */ + downloader_ptr -> address.nxd_ip_version = NX_IP_VERSION_V4; + downloader_ptr -> address.nxd_ip_address.v4 = ip_address; + address_found = NX_TRUE; + + /* Try to reslove the port. */ + temp = 0; + port_found = NX_TRUE; + } + else if (file_url[i] == '/') + { + if (dot_count == 3) + { + if (port_found) + { + downloader_ptr -> port = temp; + } + else + { + ip_address = (ip_address << 8) + temp; + + /* Set the address. */ + downloader_ptr -> address.nxd_ip_version = NX_IP_VERSION_V4; + downloader_ptr -> address.nxd_ip_address.v4 = ip_address; + address_found = NX_TRUE; + } + } + break; + } + else + { + break; + } + } + + /* Check if there is enough buffer. */ + if (file_url_length >= buffer_size) + { + return(NX_AZURE_IOT_FAILURE); + } + + /* Split host and resource url . */ + for (; i < file_url_length; i++) + { + if (file_url[i] == '/') + { + + /* Store the host ans resource. */ + downloader_ptr -> host = buffer_ptr; + memcpy(downloader_ptr -> host, file_url, i); /* Use case of memcpy is verified. */ + *(buffer_ptr + i) = NX_NULL; + + /* Set the resource url. */ + downloader_ptr -> resource = (buffer_ptr + i + 1); + memcpy(downloader_ptr -> resource, &file_url[i + 1], (file_url_length - i - 1)); /* Use case of memcpy is verified. */ + *(buffer_ptr + file_url_length) = NX_NULL; + + /* Update buffer size. */ + buffer_size -= (file_url_length + 1); + break; + } + } + + /* Check the host and resource. */ + if ((downloader_ptr -> host == NX_NULL) || (downloader_ptr -> resource == NX_NULL)) + { + return(NX_AZURE_IOT_FAILURE); + } + + /* Update the state. */ + if (address_found == NX_FALSE) + { + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_URL_PARSED; + } + else + { + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_DONE; + } + + /* Check if found the port. */ + if (port_found == NX_FALSE) + { + + /* Set tht http port as default. */ + downloader_ptr -> port = NX_WEB_HTTP_SERVER_PORT; + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static void nx_azure_iot_adu_agent_dns_query(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + + /* Check the state. */ + if ((downloader_ptr -> state != NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_URL_PARSED) && + (downloader_ptr -> state != NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_QUERY)) + { + return; + } + + /* Check if reach the max retry count. */ + if (downloader_ptr -> dns_query_count <= NX_AZURE_IOT_ADU_AGENT_DNS_RETRANSMIT_COUNT) + { + + /* Set the timeout. */ + downloader_ptr -> timeout = (ULONG)(NX_AZURE_IOT_ADU_AGENT_DNS_INITIAL_TIMEOUT << downloader_ptr -> dns_query_count); + + /* Update the query count. */ + downloader_ptr -> dns_query_count++; + + /* Update state. */ + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_QUERY; + + /* Resolve the host name by DNS. */ + status = nxd_dns_host_by_name_get(downloader_ptr -> dns_ptr, + downloader_ptr -> host, + &(downloader_ptr -> address), + NX_NO_WAIT, NX_IP_VERSION_V4); + + /* Check status. */ + if (status == NX_SUCCESS) + { + + /* Got the address, update the state. */ + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_DONE; + + /* Start HTTP connect. */ + nx_azure_iot_adu_agent_http_connect(adu_agent_ptr); + return; + } + else if (status == NX_IN_PROGRESS) + { + + /* Query in progress. */ + return; + } + } + + LogError(LogLiteralArgs("Firmware download fail: DNS QUERY FAIL")); + + /* Send dns query failed or already reach the max retransmission count. */ + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); +} + +static void nx_azure_iot_adu_agent_dns_response_notify(NX_UDP_SOCKET *socket_ptr) +{ +NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr; + + + /* Set adu agent pointer. */ + adu_agent_ptr = (NX_AZURE_IOT_ADU_AGENT *)socket_ptr -> nx_udp_socket_reserved_ptr; + + /* Set the DNS response receive event. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_DNS_RESPONSE_RECEIVE_EVENT); +} + +static void nx_azure_iot_adu_agent_dns_response_get(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; +UINT record_count; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + + /* Try to get the response. */ + status = _nx_dns_response_get(downloader_ptr -> dns_ptr, downloader_ptr -> host, + (UCHAR *)&downloader_ptr -> address.nxd_ip_address.v4, sizeof(ULONG), + &record_count, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + + /* Retry DNS query. */ + nx_azure_iot_adu_agent_dns_query(adu_agent_ptr); + } + else + { + + /* Set the address version. */ + downloader_ptr -> address.nxd_ip_version = NX_IP_VERSION_V4; + + /* Update the state. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_DONE; + + /* Start HTTP connect. */ + nx_azure_iot_adu_agent_http_connect(adu_agent_ptr); + } +} + +static void nx_azure_iot_adu_agent_http_connect(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + +UINT status; +NX_IP *ip_ptr; +NX_CRYPTO_METHOD *sha256_method; +UCHAR *sha256_method_metadata; +ULONG sha256_method_metadata_size; +VOID *handler; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + /* Initialize. */ + ip_ptr = adu_agent_ptr -> nx_azure_iot_hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_ip_ptr; + downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + /* Initialize hash for downloading firmware. */ + sha256_method = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256; + sha256_method_metadata = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256_metadata; + sha256_method_metadata_size = NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE; + handler = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.handler; + + /* Initialize the crypto. */ + if (sha256_method -> nx_crypto_init) + { + status = sha256_method -> nx_crypto_init((NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + &handler, + sha256_method_metadata, + sha256_method_metadata_size); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: SHA256 INIT ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + } + + /* Initialize the sha256 for firmware hash. */ + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, + handler, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + NX_NULL, + 0, + sha256_method_metadata, + sha256_method_metadata_size, + NX_NULL, + NX_NULL); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: SHA256 INIT ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Create an HTTP client instance. */ + status = nx_web_http_client_create(&(downloader_ptr -> http_client), + "HTTP Client", + ip_ptr, ip_ptr -> nx_ip_default_packet_pool, + NX_AZURE_IOT_ADU_AGENT_HTTP_WINDOW_SIZE); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: CLIENT CREATE FAIL")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Update the state and timeout. */ + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONNECT; + downloader_ptr -> timeout = NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_TIMEOUT; + + /* Set the notify. */ + downloader_ptr -> http_client.nx_web_http_client_socket.nx_tcp_socket_reserved_ptr = adu_agent_ptr; + nx_tcp_socket_establish_notify(&(downloader_ptr -> http_client.nx_web_http_client_socket), + nx_azure_iot_adu_agent_http_establish_notify); + nx_tcp_socket_receive_notify(&(downloader_ptr -> http_client.nx_web_http_client_socket), + nx_azure_iot_adu_agent_http_receive_notify); + + /* Connect to Server. */ + status = nx_web_http_client_connect(&(downloader_ptr -> http_client), + &(downloader_ptr -> address), + downloader_ptr -> port, + NX_NO_WAIT); + + /* Check status. */ + if (status == NX_SUCCESS) + { + + /* Connection established. Start to get file content. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_DONE_EVENT); + return; + } + else if (status == NX_IN_PROGRESS) + { + + /* Query in progress. */ + return; + } + + LogError(LogLiteralArgs("Firmware download fail: CLIENT CONNECT FAIL")); + + /* Failed. */ + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; +} + +static void nx_azure_iot_adu_agent_http_request_send(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ +UINT status; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + + /* Update the state and timeout. */ + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONTENT_GET; + downloader_ptr -> timeout = NX_AZURE_IOT_ADU_AGENT_HTTP_DOWNLOAD_TIMEOUT; + + /* Use the service to send a GET request to the server . */ + status = nx_web_http_client_request_initialize(&(downloader_ptr -> http_client), + NX_WEB_HTTP_METHOD_GET, + (CHAR *)downloader_ptr -> resource, + (CHAR *)downloader_ptr -> host, + 0, NX_FALSE, NX_NULL, NX_NULL, + NX_NO_WAIT); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: CLIENT REQUEST INIT FAIL")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Send the HTTP request we just built. */ + status = nx_web_http_client_request_send(&(downloader_ptr -> http_client), NX_NO_WAIT); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware download fail: CLIENT REQUEST SEND FAIL")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } +} + +static void nx_azure_iot_adu_agent_http_response_receive(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr) +{ + +UINT status; +UINT get_status; +NX_PACKET *received_packet; +NX_PACKET *data_packet; +UINT data_size; +NX_CRYPTO_METHOD *sha256_method = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256; +UCHAR *sha256_method_metadata = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256_metadata;; +ULONG sha256_method_metadata_size = NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE; +VOID *handler = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.handler; +UCHAR *generated_hash; +UCHAR *decoded_hash; +UINT bytes_copied; +NX_AZURE_IOT_ADU_AGENT_DRIVER driver_request; +NX_AZURE_IOT_ADU_AGENT_DOWNLOADER *downloader_ptr = &(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader); + + /* Check the state. */ + if (downloader_ptr -> state != NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONTENT_GET) + { + return; + } + + /* Receive response data from the server. Loop until all data is received. */ + get_status = NX_SUCCESS; + while ((get_status != NX_WEB_HTTP_GET_DONE) && (downloader_ptr -> received_firmware_size < downloader_ptr -> file -> file_size_in_bytes)) + { + get_status = nx_web_http_client_response_body_get(&(downloader_ptr -> http_client), &received_packet, NX_NO_WAIT); + + /* Check for error. */ + if ((get_status == NX_SUCCESS) || (get_status == NX_WEB_HTTP_GET_DONE) || (get_status == NX_WEB_HTTP_STATUS_CODE_PARTIAL_CONTENT)) + { + + /* Loop to write the data from packet into flash. */ + data_packet = received_packet; +#ifndef NX_DISABLE_PACKET_CHAIN + while(data_packet) + { +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* Calculate the data size in current packet. */ + data_size = (UINT)(data_packet -> nx_packet_append_ptr - data_packet -> nx_packet_prepend_ptr); + + /* Update the hash value for data. */ + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + NX_NULL, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + data_packet -> nx_packet_prepend_ptr, + (ULONG)data_size, + NX_NULL, + NX_NULL, + 0, + sha256_method_metadata, + sha256_method_metadata_size, + NX_NULL, + NX_NULL); + + /* Check status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(received_packet); + LogError(LogLiteralArgs("Firmware download fail: HASH UPDATE ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + if (downloader_ptr -> type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE) + { + + /* Send the firmware write request to the driver. */ + driver_request.nx_azure_iot_adu_agent_driver_command = NX_AZURE_IOT_ADU_AGENT_DRIVER_WRITE; + driver_request.nx_azure_iot_adu_agent_driver_firmware_data_offset = downloader_ptr -> received_firmware_size; + driver_request.nx_azure_iot_adu_agent_driver_firmware_data_ptr = data_packet -> nx_packet_prepend_ptr; + driver_request.nx_azure_iot_adu_agent_driver_firmware_data_size = data_size; + driver_request.nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + (downloader_ptr -> driver_entry)(&driver_request); + + /* Check status. */ + if (driver_request.nx_azure_iot_adu_agent_driver_status) + { + + /* Release the packet. */ + nx_packet_release(received_packet); + LogError(LogLiteralArgs("Firmware download fail: DRIVER WRITE ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + } + else + { + + if ((downloader_ptr -> received_firmware_size + data_size) > downloader_ptr -> manifest_buffer_size) + { + + /* Release the packet. */ + nx_packet_release(received_packet); + LogError(LogLiteralArgs("Firmware download fail: BUFFER ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + memcpy(downloader_ptr -> manifest_buffer_ptr + downloader_ptr -> received_firmware_size, /* Use case of memcpy is verified. */ + data_packet -> nx_packet_prepend_ptr, data_size); + } + + /* Update received firmware size. */ + downloader_ptr -> received_firmware_size += data_size; + +#ifndef NX_DISABLE_PACKET_CHAIN + data_packet = data_packet -> nx_packet_next; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* Release the packet. */ + nx_packet_release(received_packet); + + if (downloader_ptr -> type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE) + { + LogInfo(LogLiteralArgs("Getting download data... %d"), downloader_ptr -> received_firmware_size); + } + } + else + { + if (get_status != NX_NO_PACKET) + { + LogError(LogLiteralArgs("Firmware download fail: RECEIVE ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + } + return; + } + } + + /* Output info. */ + if (downloader_ptr -> type == NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE) + { + LogInfo(LogLiteralArgs("Firmware downloaded")); + } + downloader_ptr -> state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_DONE; + + /* Firmware downloaded. Verify the hash. */ + + /* Set hash buffer. */ + if ((NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE - (downloader_ptr -> host_length + 1 + downloader_ptr -> resource_length + 1)) < + ((NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE + 1) << 1)) + { + LogError(LogLiteralArgs("Firmware verify fail: INSUFFICIENT BUFFER FOR SHA256")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + generated_hash = adu_agent_ptr -> nx_azure_iot_adu_agent_update_manifest + + downloader_ptr -> host_length + 1 + downloader_ptr -> resource_length + 1; + decoded_hash = generated_hash + NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE + 1; + + /* Calculate the hash value. */ + status = sha256_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, + handler, + (NX_CRYPTO_METHOD*)sha256_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + generated_hash, + NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE, + sha256_method_metadata, + sha256_method_metadata_size, + NX_NULL, + NX_NULL); + + /* Check status. */ + if (status) + { + LogError(LogLiteralArgs("Firmware verify fail: HASH ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Decode the file hash (base64). */ + if (_nx_utility_base64_decode(downloader_ptr -> file -> file_sha256, + downloader_ptr -> file -> file_sha256_length, + decoded_hash, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE + 1, &bytes_copied)) + { + LogError(LogLiteralArgs("Firmware verify fail: HASH ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Verify the hash value. */ + if (memcmp(generated_hash, decoded_hash, NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE)) + { + LogError(LogLiteralArgs("Firmware verify fail: HASH ERROR")); + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_FALSE); + return; + } + + /* Update download state. */ + nx_azure_iot_adu_agent_download_state_update(adu_agent_ptr, NX_TRUE); +} + +static void nx_azure_iot_adu_agent_http_establish_notify(NX_TCP_SOCKET *socket_ptr) +{ +NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr; + + + /* Set adu agent pointer. */ + adu_agent_ptr = (NX_AZURE_IOT_ADU_AGENT *)socket_ptr -> nx_tcp_socket_reserved_ptr; + + /* Set the DNS response receive event. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_DONE_EVENT); +} + +static void nx_azure_iot_adu_agent_http_receive_notify(NX_TCP_SOCKET *socket_ptr) +{ +NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr; + + + /* Set adu agent pointer. */ + adu_agent_ptr = (NX_AZURE_IOT_ADU_AGENT *)socket_ptr -> nx_tcp_socket_reserved_ptr; + + /* Set the DNS response receive event. */ + nx_cloud_module_event_set(&(adu_agent_ptr -> nx_azure_iot_adu_agent_cloud_module), + NX_AZURE_IOT_ADU_AGENT_HTTP_RECEIVE_EVENT); +} + +static void nx_azure_iot_adu_agent_download_state_update(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, UINT success) +{ +NX_CRYPTO_METHOD *sha256_method = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256; +UCHAR *sha256_method_metadata = adu_agent_ptr -> nx_azure_iot_adu_agent_crypto.method_sha256_metadata; + + /* Cleanup download socket. */ + if (adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.state >= NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONNECT) + { + + /* Delete http client. */ + nx_web_http_client_delete(&(adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.http_client)); + } + + /* Reset the state. */ + adu_agent_ptr -> nx_azure_iot_adu_agent_downloader.state = NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_IDLE; + + /* Cleanup sha256. */ + if (sha256_method -> nx_crypto_cleanup) + { + sha256_method -> nx_crypto_cleanup(sha256_method_metadata); + } + + /* Update the state according to the download status. */ + if (success == NX_TRUE) + { + + /* Download complete, update state to next state. */ + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, adu_agent_ptr -> nx_azure_iot_adu_agent_current_step -> state + 1); + } + else + { + nx_azure_iot_adu_agent_step_state_update(adu_agent_ptr, NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED); + } +} diff --git a/addons/azure_iot/nx_azure_iot_adu_agent.h b/addons/azure_iot/nx_azure_iot_adu_agent.h new file mode 100644 index 00000000..6cb1ff4a --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_adu_agent.h @@ -0,0 +1,806 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 */ + +/** + * @file nx_azure_iot_adu_agent.h + * + * @brief Definition for the Azure IoT ADU agent interface. + * + * @note More details about Azure Device Update can be found online + * at https://docs.microsoft.com/en-us/azure/iot-hub-device-update/understand-device-update + * + */ + +#ifndef NX_AZURE_IOT_ADU_AGENT_H +#define NX_AZURE_IOT_ADU_AGENT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nx_azure_iot_hub_client_properties.h" +#include "nx_web_http_client.h" + +#ifndef NX_ENABLE_EXTENDED_NOTIFY_SUPPORT +#error "NX_ENABLE_EXTENDED_NOTIFY_SUPPORT must be defined" +#endif /* NX_ENABLE_EXTENDED_NOTIFY_SUPPORT */ + +/* Define the proxy update count. The value is 0 by default, it means only supporting host-level update. + To enable proxy update for leaf-level update, redefine NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT +#define NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT 0 +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + +/* Define the ADU agent component name. */ +#define NX_AZURE_IOT_ADU_AGENT_COMPONENT_NAME "deviceUpdate" + +/* Define the ADU agent interface ID. */ +#define NX_AZURE_IOT_ADU_AGENT_INTERFACE_ID "dtmi:azure:iot:deviceUpdate;1" + +/* Define the compatibility value. */ +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_VALUE_COMPATIBILITY "manufacturer,model" + +/* Define the ADU agent property name "agent" and sub property names. */ +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_AGENT "agent" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DEVICEPROPERTIES "deviceProperties" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANUFACTURER "manufacturer" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MODEL "model" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INTERFACE_ID "interfaceId" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ADU_VERSION "aduVer" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DO_VERSION "doVer" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPAT_PROPERTY_NAMES "compatPropertyNames" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CONTENT_ID "installedUpdateId" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_PROVIDER "provider" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_NAME "name" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_VERSION "version" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_LAST_INSTALL_RESULT "lastInstallResult" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_CODE "resultCode" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_EXTENDED_RESULT_CODE "extendedResultCode" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RESULT_DETAILS "resultDetails" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEP_RESULTS "stepResults" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STATE "state" + +/* Define the ADU agent property name "service" and sub property names. */ +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SERVICE "service" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_WORKFLOW "workflow" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ACTION "action" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_ID "id" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_RETRY_TIMESTAMP "retryTimestamp" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST "updateManifest" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_MANIFEST_SIGNATURE "updateManifestSignature" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILEURLS "fileUrls" + +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_MANIFEST_VERSION "manifestVersion" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_UPDATE_ID "updateId" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_COMPATIBILITY "compatibility" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DEVICE_MANUFACTURER "deviceManufacturer" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DEVICE_MODEL "deviceModel" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_GROUP "group" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTRUCTIONS "instructions" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_STEPS "steps" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_TYPE "type" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLE "handler" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILES "files" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_DETACHED_MANIFEST_FILED "detachedManifestFileId" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HANDLER_PROPERTIES "handlerProperties" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_INSTALLED_CRITERIA "installedCriteria" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_FILE_NAME "fileName" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SIZE_IN_BYTES "sizeInBytes" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_HASHES "hashes" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_SHA256 "sha256" +#define NX_AZURE_IOT_ADU_AGENT_PROPERTY_NAME_CREATED_DATE_TIME "createdDateTime" + +/* Define ADU events. These events are processed by the cloud thread. */ +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_EVENT ((ULONG)0x00000001) +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOAD_INSTALL_EVENT ((ULONG)0x00000002) +#define NX_AZURE_IOT_ADU_AGENT_APPLY_EVENT ((ULONG)0x00000004) +#define NX_AZURE_IOT_ADU_AGENT_DNS_RESPONSE_RECEIVE_EVENT ((ULONG)0x00000008) +#define NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_DONE_EVENT ((ULONG)0x00000010) +#define NX_AZURE_IOT_ADU_AGENT_HTTP_RECEIVE_EVENT ((ULONG)0x00000020) + +/* Define the agent state values. Interaction between agent and server. + https://docs.microsoft.com/en-us/azure/iot-hub-device-update/device-update-plug-and-play#state */ +#define NX_AZURE_IOT_ADU_AGENT_STATE_IDLE 0 +#define NX_AZURE_IOT_ADU_AGENT_STATE_DEPLOYMENT_IN_PROGRESS 6 +#define NX_AZURE_IOT_ADU_AGENT_STATE_FAILED 255 + +/* Define the agent action values. Interaction between agent and server. + https://docs.microsoft.com/en-us/azure/iot-hub-device-update/device-update-plug-and-play#action */ +#define NX_AZURE_IOT_ADU_AGENT_ACTION_APPLY_DEPLOYMENT 3 +#define NX_AZURE_IOT_ADU_AGENT_ACTION_CANCEL 255 + +/* Define the result code value. Interaction between agent and server. */ +#define NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_FAILURE 0 +#define NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_IDLE_SUCCESS 200 +#define NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_APPLY_SUCCESS 700 +#define NX_AZURE_IOT_ADU_AGENT_RESULT_CODE_APPLY_INPROGRESS 701 + +/* Define the agent update state for adu_agent_update_notify(). */ +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_RECEIVED 0 +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_DOWNLOADED 1 +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_INSTALLED 2 + +/* FIXME: status codes should be defined in iothub client. */ +/* Status codes, closely mapping to HTTP status. */ +#define NX_AZURE_IOT_ADU_AGENT_STATUS_SUCCESS 200 +#define NX_AZURE_IOT_ADU_AGENT_STATUS_BAD_FORMAT 400 +#define NX_AZURE_IOT_ADU_AGENT_STATUS_NOT_FOUND 404 +#define NX_AZURE_IOT_ADU_AGENT_STATUS_INTERNAL_ERROR 500 + +/* Define the crypto size. */ +#define NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_SIZE 32 +#define NX_AZURE_IOT_ADU_AGENT_SHA256_HASH_BASE64_SIZE 44 +#define NX_AZURE_IOT_ADU_AGENT_RSA3072_SIZE 384 + +/* Define the sha256 metadata buffer size used for verifying file hash. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE +#define NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE 400 +#endif /* NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE */ + +/* Define the max size of workflow id, including a null terminator. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_WORKFLOW_ID_SIZE +#define NX_AZURE_IOT_ADU_AGENT_WORKFLOW_ID_SIZE 48 +#endif /* NX_AZURE_IOT_ADU_AGENT_WORKFLOW_ID_SIZE */ + +/* Define the max size of workflow retry timestamp, including a null terminator. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_WORKFLOW_RETRY_TIMESTAMP_SIZE +#define NX_AZURE_IOT_ADU_AGENT_WORKFLOW_RETRY_TIMESTAMP_SIZE 80 +#endif /* NX_AZURE_IOT_ADU_AGENT_WORKFLOW_RETRY_TIMESTAMP_SIZE */ + +/* Define the max size for one file string including id, file name, file size and hashes. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_FILE_STRING_SIZE +#define NX_AZURE_IOT_ADU_AGENT_FILE_STRING_SIZE 256 +#endif /* NX_AZURE_IOT_ADU_AGENT_FILE_STRING_SIZE */ + +/* Define the max update manifest size, the buffer is used to store the original string data. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE (1024 + (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT * NX_AZURE_IOT_ADU_AGENT_FILE_STRING_SIZE)) +#endif /* NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE */ + +/* Define the max update manifest signature size (base64). */ +#ifndef NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE 3072 +#endif /* NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE */ + +/* Define the max update manifest sjwk size (base64). */ +#ifndef NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE +#define NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE 2048 +#endif /* NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE */ + +/* Define the buffer for parsing file url, update manifest content in service property. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE +#define NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE 2048 +#endif /* NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE */ + +/* Define the steps of update manifest instructions. (1 step for host update and steps for proxy update) */ +#define NX_AZURE_IOT_ADU_AGENT_STEPS_MAX (1 + NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT) + +/* Define the max number of file updates (1 host update + (1 leaf manifest + 1 leaf update) * count). */ +#ifndef NX_AZURE_IOT_ADU_AGENT_FILES_MAX +#define NX_AZURE_IOT_ADU_AGENT_FILES_MAX (1 + (2 * NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT)) +#endif /* NX_AZURE_IOT_ADU_AGENT_FILES_MAX */ + +/* Define the buffer size for one file URL. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_FILE_URL_SIZE +#define NX_AZURE_IOT_ADU_AGENT_FILE_URL_SIZE (320) +#endif /* NX_AZURE_IOT_ADU_AGENT_FILE_URL_SIZE */ + +/* Define the buffer size of storing file URLs. */ +#define NX_AZURE_IOT_ADU_AGENT_FILE_URLS_MAX (NX_AZURE_IOT_ADU_AGENT_FILE_URL_SIZE * NX_AZURE_IOT_ADU_AGENT_FILES_MAX) + +/* Define the device count. */ +#define NX_AZURE_IOT_ADU_AGENT_DEVICE_COUNT (1 + NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT) + +/* Define the initial timeout for DNS query, the default wait time is 1s. + For the next retransmission, the timeout will be doubled. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_DNS_INITIAL_TIMEOUT +#define NX_AZURE_IOT_ADU_AGENT_DNS_INITIAL_TIMEOUT (1) +#endif /* NX_AZURE_IOT_ADU_AGENT_DNS_INITIAL_TIMEOUT */ + +/* Define the maximum number of retries to a DNS server. The default count is 3. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_DNS_RETRANSMIT_COUNT +#define NX_AZURE_IOT_ADU_AGENT_DNS_RETRANSMIT_COUNT (3) +#endif /* NX_AZURE_IOT_ADU_AGENT_DNS_RETRANSMIT_COUNT */ + +/* Define the window size of HTTP for downloading firmware. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_HTTP_WINDOW_SIZE +#define NX_AZURE_IOT_ADU_AGENT_HTTP_WINDOW_SIZE (16 * 1024) +#endif /* NX_AZURE_IOT_ADU_AGENT_HTTP_WINDOW_SIZE */ + +/* Define the timeout of HTTP for connecting. The default time is 30s. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_TIMEOUT +#define NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_TIMEOUT (30) +#endif /* NX_AZURE_IOT_ADU_AGENT_HTTP_CONNECT_TIMEOUT */ + +/* Define the total timeout of HTTP for downloading the whole firmware. The default time is 300s. */ +#ifndef NX_AZURE_IOT_ADU_AGENT_HTTP_DOWNLOAD_TIMEOUT +#define NX_AZURE_IOT_ADU_AGENT_HTTP_DOWNLOAD_TIMEOUT (300) +#endif /* NX_AZURE_IOT_ADU_AGENT_HTTP_DOWNLOAD_TIMEOUT */ + +/* Define the http protocol string. */ +#define NX_AZURE_IOT_ADU_AGENT_HTTP_PROTOCOL "http://" + +/* Define the step type. */ +#define NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_INLINE "inline" +#define NX_AZURE_IOT_ADU_AGENT_STEP_TYPE_REFERENCE "reference" + +/* Define the step handler. */ +#define NX_AZURE_IOT_ADU_AGENT_STEP_HANDLER_SWUPDATE "microsoft/swupdate:1" + +/* Define the firmware update state. */ +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_IDLE 0 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_MANIFEST_DOWNLOAD_STARTED 1 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_MANIFEST_DOWNLOAD_SUCCEEDED 2 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_STARTED 3 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_DOWNLOAD_SUCCEEDED 4 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_STARTED 5 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_INSTALL_SUCCEEDED 6 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_STARTED 7 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FIRMWARE_APPLY_SUCCEEDED 8 +#define NX_AZURE_IOT_ADU_AGENT_STEP_STATE_FAILED 255 + +/* Define the downloader type. */ +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_MANIFEST 0 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_TYPE_FIRMWARE 1 + +/* Define the downloader state. */ +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_IDLE 0 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_URL_PARSED 1 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_QUERY 2 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_ADDRESS_DONE 3 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONNECT 4 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_HTTP_CONTENT_GET 5 +#define NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_DONE 6 + +/* Define ADU driver constants. */ +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_INITIALIZE 0 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK 1 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_PREPROCESS 2 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_WRITE 3 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_INSTALL 4 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_APPLY 5 +#define NX_AZURE_IOT_ADU_AGENT_DRIVER_CANCEL 6 + +/* Define string macro. */ +#define NX_AZURE_IOT_ADU_AGENT_STRING(p) p, sizeof(p) - 1 + +/** + * @brief ADU update id struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_UPDATE_ID_STRUCT +{ + + /* Provider. */ + const UCHAR *provider; + UINT provider_length; + + /* Name. */ + const UCHAR *name; + UINT name_length; + + /* Version. */ + const UCHAR *version; + UINT version_length; + +} NX_AZURE_IOT_ADU_AGENT_UPDATE_ID; + +/** + * @brief ADU driver struct + * + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_DRIVER_STRUCT +{ + + /* Define the driver command. */ + UINT nx_azure_iot_adu_agent_driver_command; + + /* Define the driver return status. */ + UINT nx_azure_iot_adu_agent_driver_status; + + /* Define the firmware size for the driver to preprocess. */ + UINT nx_azure_iot_adu_agent_driver_firmware_size; + + /* Define the firmware data for the driver to write. */ + UINT nx_azure_iot_adu_agent_driver_firmware_data_offset; + UCHAR *nx_azure_iot_adu_agent_driver_firmware_data_ptr; + UINT nx_azure_iot_adu_agent_driver_firmware_data_size; + + /* Define the return pointer for raw driver command requests. */ + ULONG *nx_azure_iot_adu_agent_driver_return_ptr; + + /* Installed criteria. */ + const UCHAR *nx_azure_iot_adu_agent_driver_installed_criteria; + UINT nx_azure_iot_adu_agent_driver_installed_criteria_length; + +} NX_AZURE_IOT_ADU_AGENT_DRIVER; + +/** + * @brief ADU crypto struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_CRYPTO_STRUCT +{ + + /* RS256. */ + + /* RSA. Reuse the metadata from TLS cipher metadata. */ + NX_CRYPTO_METHOD *method_rsa; + UCHAR *method_rsa_metadata; + ULONG method_rsa_metadata_size; + VOID *handler; + + /* SHA256. */ + NX_CRYPTO_METHOD *method_sha256; + UCHAR method_sha256_metadata[NX_AZURE_IOT_ADU_AGENT_SHA256_METADATA_SIZE]; + +} NX_AZURE_IOT_ADU_AGENT_CRYPTO; + +/** + * @brief ADU workflow struct. + * Format: + * { + "action": 3, + "id": "someguid", + "retryTimestamp": "2020-04-22T12:12:12.0000000+00:00" + } + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_WORKFLOW_STRUCT +{ + + /* Action. */ + UINT action; + + /* ID. */ + UCHAR id[NX_AZURE_IOT_ADU_AGENT_WORKFLOW_ID_SIZE]; + UINT id_length; + + /* Retry Timestamp. */ + UCHAR retry_timestamp[NX_AZURE_IOT_ADU_AGENT_WORKFLOW_RETRY_TIMESTAMP_SIZE]; + UINT retry_timestamp_length; + +} NX_AZURE_IOT_ADU_AGENT_WORKFLOW; + +/** + * @brief ADU result struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_RESULT_STRUCT +{ + + /* Result. */ + UINT result_code; + + /* Extended result code. */ + UINT extended_result_code; + +} NX_AZURE_IOT_ADU_AGENT_RESULT; + +/** + * @brief ADU device properties struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_DEVICE_PROPERTIES_STRUCT +{ + + /* Manufacturer. */ + const UCHAR *manufacturer; + UINT manufacturer_length; + + /* Name/model. */ + const UCHAR *model; + UINT model_length; + +} NX_AZURE_IOT_ADU_AGENT_DEVICE_PROPERTIES; + +/** + * @brief ADU device struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_DEVICE_STRUCT +{ + + /* State. */ + UINT valid; + + /* Device properties. */ + NX_AZURE_IOT_ADU_AGENT_DEVICE_PROPERTIES device_properties; + + /* Installed criteria. */ + const UCHAR *installed_criteria; + UINT installed_criteria_length; + + /* Driver entry point for updating firmware. */ + VOID (*device_driver_entry)(NX_AZURE_IOT_ADU_AGENT_DRIVER *); + +} NX_AZURE_IOT_ADU_AGENT_DEVICE; + +/** + * @brief ADU update manifest files struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_FILE_STRUCT +{ + + /* File number. */ + const UCHAR *file_id; + UINT file_id_length; + + /* File name. */ + UCHAR *file_name; + UINT file_name_length; + + /* File size in bytes. */ + UINT file_size_in_bytes; + + /* File sha256. */ + UCHAR *file_sha256; + UINT file_sha256_length; + + /* File url. */ + UCHAR *file_url; + UINT file_url_length; + +} NX_AZURE_IOT_ADU_AGENT_FILE; + +/** + * @brief ADU update manifest steps struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_STEP_STRUCT +{ + + /* Type. */ + const UCHAR *type; + UINT type_length; + + /* Handler. */ + const UCHAR *handler; + UINT handler_length; + + /* Installed criteria. */ + const UCHAR *installed_criteria; + UINT installed_criteria_length; + + /* File id. */ + const UCHAR *file_id; + UINT file_id_length; + + /* Step state. */ + UINT state; + + /* Result. */ + NX_AZURE_IOT_ADU_AGENT_RESULT result; + + /* Device. */ + NX_AZURE_IOT_ADU_AGENT_DEVICE *device; + + /* File. */ + NX_AZURE_IOT_ADU_AGENT_FILE *file; + +} NX_AZURE_IOT_ADU_AGENT_STEP; + +/** + * @brief ADU compatibility struct. + * @note Compatibility defines the criteria of a device that can install the update. It contains device properties. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY_STRUCT +{ + + /* Compatibility: deviceManufacturer. */ + UCHAR *device_manufacturer; + UINT device_manufacturer_length; + + /* Compatibility: deviceModel. */ + UCHAR *device_model; + UINT device_model_length; + + /* Compatibility: group. */ + const UCHAR *group; + UINT group_length; + +} NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY; + +/** + * @brief ADU update manifest content struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT_STRUCT +{ + + /* Manifest version. */ + UCHAR *manifest_version; + UINT manifest_version_length; + + /* Update Id. */ + NX_AZURE_IOT_ADU_AGENT_UPDATE_ID update_id; + + /* Compatibility: deviceManufacturer. */ + NX_AZURE_IOT_ADU_AGENT_COMPATIBILITY compatibility; + + /* Instructions: steps. */ + NX_AZURE_IOT_ADU_AGENT_STEP steps[NX_AZURE_IOT_ADU_AGENT_STEPS_MAX]; + UINT steps_count; + + /* Files. */ + NX_AZURE_IOT_ADU_AGENT_FILE files[NX_AZURE_IOT_ADU_AGENT_FILES_MAX]; + UINT files_count; + +} NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT; + +/** + * @brief ADU file urls file struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_FILE_URLS_FILE_STRUCT +{ + + /* File id string. */ + UCHAR *file_id; + UINT file_id_length; + + /* File URL. */ + UCHAR *file_url; + UINT file_url_length; + +} NX_AZURE_IOT_ADU_AGENT_FILE_URLS_FILE; + +/** + * @brief ADU file urls struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_FILE_URLS_STRUCT +{ + + /* File struct. */ + NX_AZURE_IOT_ADU_AGENT_FILE_URLS_FILE file_urls[NX_AZURE_IOT_ADU_AGENT_FILES_MAX]; + + /* Count of file urls. */ + UINT file_urls_count; + + /* Buffer. */ + UCHAR file_urls_buffer[NX_AZURE_IOT_ADU_AGENT_FILE_URLS_MAX]; + +} NX_AZURE_IOT_ADU_AGENT_FILE_URLS; + +/** + * @brief ADU downloader struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_DOWNLOADER_STRUCT +{ + + /* Download type (manifest or firmware). */ + UINT type; + + /* Download file. */ + NX_AZURE_IOT_ADU_AGENT_FILE *file; + + /* HTTP Client for downloading firmware. */ + NX_WEB_HTTP_CLIENT http_client; + + /* Host string. */ + UCHAR *host; + UINT host_length; + + /* Resource string. */ + UCHAR *resource; + UINT resource_length; + + /* HTTP server address. */ + NXD_ADDRESS address; + + /* HTTP server port. */ + UINT port; + + /* Received firmware size. */ + UINT received_firmware_size; + + /* Downloading state. */ + UINT state; + + /* DNS. */ + NX_DNS *dns_ptr; + + /* DNS query count. */ + UINT dns_query_count; + + /* Timeout. */ + ULONG timeout; + + /* Buffer for manifest. */ + UCHAR *manifest_buffer_ptr; + UINT manifest_buffer_size; + + /* Driver entry point for firmware. */ + VOID (*driver_entry)(NX_AZURE_IOT_ADU_AGENT_DRIVER *); + +} NX_AZURE_IOT_ADU_AGENT_DOWNLOADER; + +/** + * @brief ADU RSA root key struct. + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY_STRUCT +{ + const UCHAR *kid; + const UINT kid_size; + + const UCHAR *n; + const UINT n_size; + + const UCHAR *e; + const UINT e_size; +} NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY; + +/** + * @brief ADU agent struct + * + */ +typedef struct NX_AZURE_IOT_ADU_AGENT_STRUCT +{ + + /* IoTHub client pointer. */ + NX_AZURE_IOT_HUB_CLIENT *nx_azure_iot_hub_client_ptr; + + /* Mutex. */ + TX_MUTEX *nx_azure_iot_adu_agent_mutex_ptr; + + /* Cloud module. */ + NX_CLOUD_MODULE nx_azure_iot_adu_agent_cloud_module; + + /* Downloader. */ + NX_AZURE_IOT_ADU_AGENT_DOWNLOADER nx_azure_iot_adu_agent_downloader; + + /* ADU crypto. */ + NX_AZURE_IOT_ADU_AGENT_CRYPTO nx_azure_iot_adu_agent_crypto; + + /* ADU device properties. */ + NX_AZURE_IOT_ADU_AGENT_DEVICE_PROPERTIES nx_azure_iot_adu_agent_device_properties; + + /* Agent state. */ + UINT nx_azure_iot_adu_agent_state; + + /* Flag for new update. */ + UINT nx_azure_iot_adu_agent_update_flag; + + /* Workflow. */ + NX_AZURE_IOT_ADU_AGENT_WORKFLOW nx_azure_iot_adu_agent_workflow; + + /* Deployable update manifest string. */ + UCHAR nx_azure_iot_adu_agent_update_manifest[NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIZE]; + UINT nx_azure_iot_adu_agent_update_manifest_size; + + /* Update manifest signature. After verifying the deployable update manifest, the buffer will be used for leaf update manifest. */ + UCHAR nx_azure_iot_adu_agent_update_manifest_signature[NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SIGNATURE_SIZE]; + UINT nx_azure_iot_adu_agent_update_manifest_signature_size; + + /* SJWK. After verifying the deployable update manifest, the buffer will be used for leaf update manifest content. */ + UCHAR nx_azure_iot_adu_agent_update_manifest_sjwk[NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_SJWK_SIZE]; + UINT nx_azure_iot_adu_agent_update_manifest_sjwk_size; + + /* File URL. */ + NX_AZURE_IOT_ADU_AGENT_FILE_URLS nx_azure_iot_adu_agent_file_urls; + + /* Deployable update manifest content. */ + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT nx_azure_iot_adu_agent_update_manifest_content; + NX_AZURE_IOT_ADU_AGENT_STEP *nx_azure_iot_adu_agent_current_step; + + /* Buffer for storing file number string, file urls and update manifest content. */ + UCHAR nx_azure_iot_adu_agent_buffer[NX_AZURE_IOT_ADU_AGENT_BUFFER_SIZE]; + UINT nx_azure_iot_adu_agent_buffer_size; + + /* Device info. */ + NX_AZURE_IOT_ADU_AGENT_DEVICE nx_azure_iot_adu_agent_device[NX_AZURE_IOT_ADU_AGENT_DEVICE_COUNT]; + +#if NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT + /* Leaf-level manifest content. */ + NX_AZURE_IOT_ADU_AGENT_UPDATE_MANIFEST_CONTENT nx_azure_iot_adu_agent_proxy_update_manifest_content; +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + + /* Define the callback function for new update notification. If specified + by the application, this function is called when new update occurs. */ + VOID (*nx_azure_iot_adu_agent_update_notify)(struct NX_AZURE_IOT_ADU_AGENT_STRUCT *adu_agent_ptr, + UINT update_state, + UCHAR *provider, UINT provider_length, + UCHAR *name, UINT name_length, + UCHAR *version, UINT version_length); + +} NX_AZURE_IOT_ADU_AGENT; + +/** + * @brief Start Azure IoT ADU agent + * + * @param[in] adu_agent_ptr A pointer to a #NX_AZURE_IOT_ADU_AGENT. + * @param[in] iothub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] manufacturer A `UCHAR` pointer to the manufacturer + * @param[in] manufacturer_length Length of the `manufacturer`. Does not include the `NULL` terminator. + * @param[in] model A `UCHAR` pointer to the model + * @param[in] model_length Length of the `model`. Does not include the `NULL` terminator. + * @param[in] installed_criteria A `UCHAR` pointer to the installed criteria string, such as: version string. + * @param[in] installed_criteria_length Length of the `installed_criteria`. Does not include the `NULL` terminator. + * @param[in] adu_agent_update_notify User supplied update receive change callback. + * @param[in] adu_agent_update_driver User supplied driver for flash operation. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully start ADU agent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to start the Azure IoT ADU agent due to invalid parameter. + * @retval #NX_AZURE_IOT_NO_AVAILABLE_CIPHER Fail to start the Azure IoT ADU agent due to no available cipher. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to start the Azure IoT ADU agent due to insufficient buffer space. + */ +UINT nx_azure_iot_adu_agent_start(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_update_notify)(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UINT update_state, + UCHAR *provider, UINT provider_length, + UCHAR *name, UINT name_length, + UCHAR *version, UINT version_length), + VOID (*adu_agent_update_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); + +#if NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT +/** + * @brief Add proxy update on device update agent + * + * @param[in] adu_agent_ptr A pointer to a #NX_AZURE_IOT_ADU_AGENT. + * @param[in] provider A `UCHAR` pointer to the provider. + * @param[in] provider_length Length of the `provider`. Does not include the `NULL` terminator. + * @param[in] name A `UCHAR` pointer to the name + * @param[in] name_length Length of the `name`. Does not include the `NULL` terminator. + * @param[in] installed_criteria A `UCHAR` pointer to the installed criteria string, such as: version string. + * @param[in] installed_criteria_length Length of the `installed_criteria`. Does not include the `NULL` terminator. + * @param[in] adu_agent_proxy_driver User supplied driver for proxy update operation. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully add ADU agent proxy update on leaf device. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to start the Azure IoT ADU agent due to invalid parameter. + * @retval #NX_AZURE_IOT_NO_MORE_ENTRIES Fail to start the Azure IoT ADU agent due to no more entries. + */ +UINT nx_azure_iot_adu_agent_proxy_update_add(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + const UCHAR *manufacturer, UINT manufacturer_length, + const UCHAR *model, UINT model_length, + const UCHAR *installed_criteria, UINT installed_criteria_length, + VOID (*adu_agent_proxy_update_driver)(NX_AZURE_IOT_ADU_AGENT_DRIVER *)); +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + +/** + * @brief Stop Azure IoT ADU agent + * + * @param[in] adu_agent_ptr A pointer to a #NX_AZURE_IOT_ADU_AGENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully stop ADU agent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to stop the Azure IoT ADU agent due to invalid parameter. + */ +UINT nx_azure_iot_adu_agent_stop(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); + +/** + * @brief Start to download and install firmware immediately. + * @note Agent will download and install new firmware. + * + * @param[in] adu_agent_ptr A pointer to a #NX_AZURE_IOT_ADU_AGENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully start to update new firmware. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to start to update new firmware due to invalid parameter. + */ +UINT nx_azure_iot_adu_agent_update_download_and_install(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); + +/** + * @brief Start to apply firmware immediately. + * @note Agent will apply new firmware, may reboot the device. + * + * @param[in] adu_agent_ptr A pointer to a #NX_AZURE_IOT_ADU_AGENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully start to apply new firmware. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to start to apply new firmware due to invalid parameter. + */ +UINT nx_azure_iot_adu_agent_update_apply(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr); + +#ifdef __cplusplus +} +#endif +#endif /* NX_AZURE_IOT_ADU_AGENT_H */ diff --git a/addons/azure_iot/nx_azure_iot_adu_root_key.c b/addons/azure_iot/nx_azure_iot_adu_root_key.c new file mode 100644 index 00000000..c668aae8 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_adu_root_key.c @@ -0,0 +1,121 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 */ + +#include "nx_azure_iot_adu_agent.h" + +/* Update manifest is meant for ADU devices to know what files are needed to be downloaded and installed. + The update manifest is signed by ADU so devices can trust that the content wasnot altered during the + transmission. + + ADU will leverage two types of keys - Root Key(s) and Signing Key(s). Signing keys will be used to + digest sign the update manifest and root keys will be used to sign the signing keys. + + *Root key - used to sign signing public key; root public key is hardcoded in ADU devices. + *Signing key - used to sign update manifest; signing public key signed with the master key is included in digest signature header. +*/ + +/* Root keys. */ + +/* ADU.200702.R: root production key from 7/2/2020 */ +const UCHAR adu_root_key_200702_r_kid[] = "ADU.200702.R"; +const UCHAR adu_root_key_200702_r_n[] = {0x00, 0xd5, 0x42, 0x2e, 0xaf, 0x11, 0x54, 0xa3, 0x50, 0x65, 0x87, 0xa2, 0x4d, 0x5b, 0xba, + 0x1a, 0xfb, 0xa9, 0x32, 0xdf, 0xe9, 0x99, 0x5f, 0x05, 0x45, 0xc8, 0xaf, 0xbd, 0x35, 0x1d, + 0x89, 0xe8, 0x27, 0x27, 0x58, 0xa3, 0xa8, 0xee, 0xc5, 0xc5, 0x1e, 0x4f, 0xf7, 0x92, 0xa6, + 0x12, 0x06, 0x7d, 0x3d, 0x7d, 0xb0, 0x07, 0xf6, 0x2c, 0x7f, 0xde, 0x6d, 0x2a, 0xf5, 0xbc, + 0x49, 0xbc, 0x15, 0xef, 0xf0, 0x81, 0xcb, 0x3f, 0x88, 0x4f, 0x27, 0x1d, 0x88, 0x71, 0x28, + 0x60, 0x08, 0xb6, 0x19, 0xd2, 0xd2, 0x39, 0xd0, 0x05, 0x1f, 0x3c, 0x76, 0x86, 0x71, 0xbb, + 0x59, 0x58, 0xbc, 0xb1, 0x88, 0x7b, 0xab, 0x56, 0x28, 0xbf, 0x31, 0x73, 0x44, 0x32, 0x10, + 0xfd, 0x3d, 0xd3, 0x96, 0x5c, 0xff, 0x4e, 0x5c, 0xb3, 0x6b, 0xff, 0x8b, 0x84, 0x9b, 0x8b, + 0x80, 0xb8, 0x49, 0xd0, 0x7d, 0xfa, 0xd6, 0x40, 0x58, 0x76, 0x4d, 0xc0, 0x72, 0x27, 0x75, + 0xcb, 0x9a, 0x2f, 0x9b, 0xb4, 0x9f, 0x0f, 0x25, 0xf1, 0x1c, 0xc5, 0x1b, 0x0b, 0x5a, 0x30, + 0x7d, 0x2f, 0xb8, 0xef, 0xa7, 0x26, 0x58, 0x53, 0xaf, 0xd5, 0x1d, 0x55, 0x01, 0x51, 0x0d, + 0xe9, 0x1b, 0xa2, 0x0f, 0x3f, 0xd7, 0xe9, 0x1d, 0x20, 0x41, 0xa6, 0xe6, 0x14, 0x0a, 0xae, + 0xfe, 0xf2, 0x1c, 0x2a, 0xd6, 0xe4, 0x04, 0x7b, 0xf6, 0x14, 0x7e, 0xec, 0x0f, 0x97, 0x83, + 0xfa, 0x58, 0xfa, 0x81, 0x36, 0x21, 0xb9, 0xa3, 0x2b, 0xfa, 0xd9, 0x61, 0x0b, 0x1a, 0x94, + 0xf7, 0xc1, 0xbe, 0x7f, 0x40, 0x14, 0x4a, 0xc9, 0xfa, 0x35, 0x7f, 0xef, 0x66, 0x70, 0x00, + 0xb1, 0xfd, 0xdb, 0xd7, 0x61, 0x0d, 0x3b, 0x58, 0x74, 0x67, 0x94, 0x89, 0x75, 0x76, 0x96, + 0x7c, 0x91, 0x87, 0xd2, 0x8e, 0x11, 0x97, 0xee, 0x7b, 0x87, 0x6c, 0x9a, 0x2f, 0x45, 0xd8, + 0x65, 0x3f, 0x52, 0x70, 0x98, 0x2a, 0xcb, 0xc8, 0x04, 0x63, 0xf5, 0xc9, 0x47, 0xcf, 0x70, + 0xf4, 0xed, 0x64, 0xa7, 0x74, 0xa5, 0x23, 0x8f, 0xb6, 0xed, 0xf7, 0x1c, 0xd3, 0xb0, 0x1c, + 0x64, 0x57, 0x12, 0x5a, 0xa9, 0x81, 0x84, 0x1f, 0xa0, 0xe7, 0x50, 0x19, 0x96, 0xb4, 0x82, + 0xb1, 0xac, 0x48, 0xe3, 0xe1, 0x32, 0x82, 0xcb, 0x40, 0x1f, 0xac, 0xc4, 0x59, 0xbc, 0x10, + 0x34, 0x51, 0x82, 0xf9, 0x28, 0x8d, 0xa8, 0x1e, 0x9b, 0xf5, 0x79, 0x45, 0x75, 0xb2, 0xdc, + 0x9a, 0x11, 0x43, 0x08, 0xbe, 0x61, 0xcc, 0x9a, 0xc4, 0xcb, 0x77, 0x36, 0xff, 0x83, 0xdd, + 0xa8, 0x71, 0x4f, 0x51, 0x8e, 0x0e, 0x7b, 0x4d, 0xfa, 0x79, 0x98, 0x8d, 0xbe, 0xfc, 0x82, + 0x7e, 0x40, 0x48, 0xa9, 0x12, 0x01, 0xa8, 0xd9, 0x7e, 0xf3, 0xa5, 0x1b, 0xf1, 0xfb, 0x90, + 0x77, 0x3e, 0x40, 0x87, 0x18, 0xc9, 0xab, 0xd9, 0xf7, 0x79}; +const UCHAR adu_root_key_200702_r_e[] = {0x01, 0x00, 0x01}; + + +/* ADU.200702.R.T: root test key from 7/2/2020 */ +const UCHAR adu_root_key_200702_r_t_kid[] = "ADU.200702.R.T"; +const UCHAR adu_root_key_200702_r_t_n[] = {0x00, 0xb9, 0xc2, 0x80, 0x24, 0xc9, 0x2c, 0x91, 0x55, 0x4a, 0x8e, 0xd5, 0x4b, 0x15, 0xda, + 0xda, 0x31, 0x27, 0x74, 0x71, 0x36, 0xb6, 0x55, 0xc9, 0xdd, 0x92, 0x57, 0xb9, 0xe3, 0x4b, + 0x26, 0x83, 0x76, 0xb6, 0xbf, 0x88, 0x58, 0x5e, 0x81, 0xd6, 0x05, 0xa0, 0x34, 0xb6, 0x46, + 0x63, 0xe5, 0x53, 0x35, 0x7d, 0x64, 0x7e, 0x5d, 0xc8, 0xc7, 0x27, 0xd3, 0x51, 0x87, 0xbe, + 0x13, 0xce, 0xc1, 0xea, 0x3c, 0x93, 0x83, 0x5e, 0x7d, 0x3c, 0xe6, 0xd5, 0x86, 0x33, 0x03, + 0xb3, 0x50, 0x43, 0xe1, 0x39, 0x20, 0x33, 0x45, 0xa6, 0x3e, 0x14, 0x2a, 0xf6, 0xdd, 0x22, + 0x2a, 0x33, 0xa0, 0x07, 0x09, 0x83, 0xf1, 0xce, 0x22, 0x9b, 0xcf, 0xd9, 0x04, 0x70, 0x3e, + 0x9e, 0xd3, 0x8d, 0xd4, 0xc8, 0x24, 0x4c, 0xc8, 0xb7, 0xfc, 0x7d, 0x02, 0x77, 0x48, 0xeb, + 0xc1, 0x5c, 0x23, 0x68, 0x55, 0x29, 0x22, 0x43, 0xca, 0xf0, 0x70, 0x37, 0x87, 0x8c, 0x58, + 0x92, 0xce, 0x4f, 0xc1, 0x2f, 0x2d, 0x09, 0x19, 0x18, 0xdf, 0xcc, 0x96, 0x45, 0xf2, 0x5f, + 0xaa, 0xd4, 0xdf, 0x95, 0xaa, 0x9a, 0xb7, 0x56, 0xd3, 0xa6, 0x40, 0x9a, 0x61, 0x6e, 0x54, + 0x8b, 0xe9, 0xb0, 0xbd, 0x01, 0x1d, 0x46, 0x36, 0xbb, 0xda, 0x25, 0xb1, 0xe2, 0x49, 0xc8, + 0x9a, 0x16, 0xfb, 0xa2, 0xb9, 0xc9, 0xde, 0x54, 0x1b, 0xb7, 0x07, 0xa6, 0xd8, 0xd3, 0x01, + 0x22, 0x9f, 0x6d, 0x31, 0xfc, 0x2a, 0xe3, 0x4c, 0xd9, 0xa2, 0x58, 0x4b, 0x6e, 0x63, 0xfc, + 0xe8, 0x53, 0x12, 0x46, 0x2c, 0x64, 0x15, 0x1e, 0x4c, 0xc9, 0x45, 0x10, 0x10, 0xc1, 0xe1, + 0xf1, 0xc3, 0xf1, 0x43, 0x48, 0xc7, 0x77, 0x52, 0x18, 0x88, 0x35, 0x1b, 0x8d, 0xed, 0x06, + 0xf7, 0xaf, 0xf4, 0xbd, 0x1c, 0xfa, 0x05, 0x36, 0x46, 0x6f, 0x68, 0xe5, 0x15, 0x39, 0x57, + 0xbb, 0x59, 0x46, 0x34, 0x8c, 0x01, 0x48, 0xcd, 0x55, 0x04, 0x72, 0xad, 0x82, 0x4f, 0x1e, + 0x37, 0xa7, 0x45, 0xef, 0x68, 0xb7, 0x98, 0x13, 0x3f, 0x83, 0xb0, 0x6f, 0x91, 0x94, 0xf9, + 0x24, 0x4f, 0x68, 0xbe, 0xd7, 0x29, 0x04, 0x87, 0x0b, 0x49, 0x7e, 0xc2, 0x86, 0x0d, 0x32, + 0x0f, 0xe6, 0x63, 0xc3, 0xb2, 0x56, 0x64, 0x4d, 0x44, 0x9c, 0x81, 0x91, 0x51, 0x31, 0x3a, + 0x09, 0x77, 0x03, 0xad, 0x18, 0xa9, 0x00, 0xcc, 0x65, 0xd0, 0x3e, 0x5b, 0xed, 0x7f, 0x72, + 0x0b, 0xe3, 0xd7, 0xd4, 0x4c, 0xce, 0x2b, 0xf1, 0xda, 0x48, 0x73, 0xb1, 0x35, 0x37, 0x60, + 0xe3, 0xb7, 0xde, 0x3f, 0xfe, 0x47, 0x1d, 0x63, 0x57, 0xbc, 0x27, 0x17, 0xe0, 0x44, 0x7e, + 0xd1, 0xa2, 0x24, 0x02, 0x01, 0x31, 0xde, 0xa7, 0xaf, 0xa6, 0x41, 0x6e, 0x54, 0x2a, 0xaf, + 0xe8, 0x9c, 0x95, 0xb6, 0x6c, 0xda, 0x3b, 0x8b, 0xd1, 0x9b}; +const UCHAR adu_root_key_200702_r_t_e[] = {0x01, 0x00, 0x01}; + +/* RSA Root key for verifying manifest. */ +const NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY _nx_azure_iot_adu_agent_rsa_root_key_list[] = +{ + { + /* kid */ + adu_root_key_200702_r_kid, + sizeof(adu_root_key_200702_r_kid) - 1, + + /* n */ + adu_root_key_200702_r_n, + sizeof(adu_root_key_200702_r_n), + + /* e */ + adu_root_key_200702_r_e, + sizeof(adu_root_key_200702_r_e), + }, + { + /* kid */ + adu_root_key_200702_r_t_kid, + sizeof(adu_root_key_200702_r_t_kid) - 1, + + /* n */ + adu_root_key_200702_r_t_n, + sizeof(adu_root_key_200702_r_t_n), + + /* e */ + adu_root_key_200702_r_t_e, + sizeof(adu_root_key_200702_r_t_e), + } +}; + +const UINT _nx_azure_iot_adu_agent_rsa_root_key_list_size = (sizeof(_nx_azure_iot_adu_agent_rsa_root_key_list) / sizeof(NX_AZURE_IOT_ADU_AGENT_RSA_ROOT_KEY)); diff --git a/addons/azure_iot/nx_azure_iot_hub_client.c b/addons/azure_iot/nx_azure_iot_hub_client.c index 3cdff666..c10323da 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.c +++ b/addons/azure_iot/nx_azure_iot_hub_client.c @@ -21,17 +21,37 @@ #define NX_AZURE_IOT_HUB_CLIENT_THROTTLE_STATUS_CODE 429 #ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT +#ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE +#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE NX_INTERFACE_TYPE_UNKNOWN +#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE +#endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE */ -/* Useragent e.g: DeviceClientType=c%2F1.0.0-preview.1%20%28nx%206.0%3Bazrtos%206.0%29 */ +#ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR +#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR 0 +#endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR */ + +#ifndef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE +#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE "U" +#endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE */ + +/* Useragent e.g: azsdk-c%2F1.3.0%20%28azrtos%206.1.2%3B0%3B0%3BU%29 */ #define NX_AZURE_IOT_HUB_CLIENT_STR(C) #C #define NX_AZURE_IOT_HUB_CLIENT_TO_STR(x) NX_AZURE_IOT_HUB_CLIENT_STR(x) -#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT "DeviceClientType=c%2F" AZ_SDK_VERSION_STRING "%20%28nx%20" \ - NX_AZURE_IOT_HUB_CLIENT_TO_STR(NETXDUO_MAJOR_VERSION) "." \ - NX_AZURE_IOT_HUB_CLIENT_TO_STR(NETXDUO_MINOR_VERSION) "%3Bazrtos%20"\ +#define NX_AZURE_IOT_HUB_CLIENT_USER_AGENT "azsdk-c%2F" AZ_SDK_VERSION_STRING "%20%28azrtos%20" \ NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MAJOR_VERSION) "." \ - NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MINOR_VERSION) "%29" + NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_MINOR_VERSION) "." \ + NX_AZURE_IOT_HUB_CLIENT_TO_STR(THREADX_PATCH_VERSION) "%3B"\ + NX_AZURE_IOT_HUB_CLIENT_TO_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_INTERFACE_TYPE) "%3B"\ + NX_AZURE_IOT_HUB_CLIENT_TO_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_VENDOR) "%3B"\ + NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_DEVICE_TYPE "%29" +static UCHAR _nx_azure_iot_hub_client_user_agent[] = NX_AZURE_IOT_HUB_CLIENT_USER_AGENT; + #endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT */ +#define NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING "$.sub" + +#define NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH "/$iothub/websocket" + static VOID nx_azure_iot_hub_client_received_message_cleanup(NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE *message); static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT is_subscribe); @@ -44,29 +64,38 @@ static UINT nx_azure_iot_hub_client_c2d_process(NX_AZURE_IOT_HUB_CLIENT *hub_cli NX_PACKET *packet_ptr, ULONG topic_offset, USHORT topic_length); -static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, - USHORT topic_length); +static UINT nx_azure_iot_hub_client_properties_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + ULONG topic_offset, + USHORT topic_length); +static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, ULONG topic_offset, + USHORT topic_length, UINT *request_id_ptr, + ULONG *version_ptr, UINT *message_type_ptr, + UINT *status_ptr); extern UINT _nxd_mqtt_process_publish_packet(NX_PACKET *packet_ptr, ULONG *topic_offset_ptr, USHORT *topic_length_ptr, ULONG *message_offset_ptr, ULONG *message_length_ptr); static VOID nx_azure_iot_hub_client_mqtt_connect_notify(struct NXD_MQTT_CLIENT_STRUCT *client_ptr, UINT status, VOID *context); static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *client_ptr); +static VOID nx_azure_iot_hub_client_mqtt_ack_receive_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, + USHORT packet_id, NX_PACKET *transmit_packet_ptr, + VOID *context); static VOID nx_azure_iot_hub_client_thread_dequeue(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_AZURE_IOT_THREAD *thread_list_ptr); static UINT nx_azure_iot_hub_client_sas_token_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, ULONG expiry_time_secs, const UCHAR *key, UINT key_len, UCHAR *sas_buffer, UINT sas_buffer_len, UINT *sas_length); static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); -static VOID nx_azure_iot_hub_client_device_twin_ack_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, - USHORT packet_id, NX_PACKET *transmit_packet_ptr, VOID *context); -static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, ULONG topic_offset, - USHORT topic_length, UINT *request_id_ptr, - ULONG *version_ptr, UINT *message_type_ptr, - UINT *status_ptr); +UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr); +UINT nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT (*callback_ptr)(VOID *json_reader_ptr, + ULONG version, + VOID *args), + VOID *callback_args); static UINT nx_azure_iot_hub_client_throttle_with_jitter(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { @@ -155,11 +184,13 @@ az_result core_result; hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_cipher_map_size = cipher_map_size; hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_ptr = metadata_memory; hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_metadata_size = memory_size; - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_trusted_certificate = trusted_certificate; + hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_trusted_certificates[0] = trusted_certificate; hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname = host_name; hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_hostname_length = host_name_length; options.module_id = az_span_create((UCHAR *)module_id, (INT)module_id_length); options.user_agent = AZ_SPAN_FROM_STR(NX_AZURE_IOT_HUB_CLIENT_USER_AGENT); + options.component_names = hub_client_ptr -> nx_azure_iot_hub_client_component_list; + options.component_names_length = 0; core_result = az_iot_hub_client_init(&hub_client_ptr -> iot_hub_client_core, hostname_span, device_id_span, &options); @@ -240,6 +271,107 @@ UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLI } +#ifdef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE +static VOID nx_azure_iot_hub_client_user_agent_update(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NXD_ADDRESS *server_address) +{ +NX_IP *ip_ptr = hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_ip_ptr; +NX_INTERFACE *outgoing_interface = NX_NULL; +UINT status; +#ifndef NX_DISABLE_IPV4 +ULONG next_hop_address; +#endif /* NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 +NXD_IPV6_ADDRESS *ipv6_addr; +#endif /* FEATURE_NX_IPV6 */ +ULONG interface_type; +ULONG index; + + /* Make sure the server IP address is accesible. */ +#ifndef NX_DISABLE_IPV4 + if (server_address -> nxd_ip_version == NX_IP_VERSION_V4) + { + if (_nx_ip_route_find(ip_ptr, server_address -> nxd_ip_address.v4, &outgoing_interface, &next_hop_address) != NX_SUCCESS) + { + return; + } + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + /* For IPv6 connections, find a suitable outgoing interface, based on the TCP peer address. */ + if (server_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + + status = _nxd_ipv6_interface_find(ip_ptr, server_address -> nxd_ip_address.v6, + &ipv6_addr, + NX_NULL); + + if (status != NX_SUCCESS) + { + return; + } + + outgoing_interface = ipv6_addr -> nxd_ipv6_address_attached; + } +#endif /* FEATURE_NX_IPV6 */ + + /* Check if found the outgoing interface. */ + if (outgoing_interface == NX_NULL) + { + return; + } + + /* Get the interface type. */ + status = nx_ip_driver_interface_direct_command(ip_ptr, NX_LINK_GET_INTERFACE_TYPE, outgoing_interface -> nx_interface_index, &interface_type); + + /* Check status. */ + if (status != NX_SUCCESS) + { + return; + } + + /* Check if the interface type is listed in nx_api.h. */ + if (interface_type > NX_INTERFACE_TYPE_LORAWAN) + { + interface_type = NX_INTERFACE_TYPE_OTHER; + } + + /* Update the interface type in user agent. */ + for (index = 0; index < sizeof(_nx_azure_iot_hub_client_user_agent) - 3; index++) + { + + /* The interface type is after the first semicolon. */ + if ((_nx_azure_iot_hub_client_user_agent[index] == '%') && + (_nx_azure_iot_hub_client_user_agent[index + 1] == '3') && + (_nx_azure_iot_hub_client_user_agent[index + 2] == 'B')) + { + _nx_azure_iot_hub_client_user_agent[index + 3] = (UCHAR)(interface_type + '0'); + hub_client_ptr -> iot_hub_client_core._internal.options.user_agent = AZ_SPAN_FROM_BUFFER(_nx_azure_iot_hub_client_user_agent); + return; + } + } +} +#endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE */ + +#ifdef NXD_MQTT_OVER_WEBSOCKET +UINT nx_azure_iot_hub_client_websocket_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ +NX_AZURE_IOT_RESOURCE *resource_ptr; + + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub WebSocket enable fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Set resource pointer. */ + resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); + + return(nxd_mqtt_client_websocket_set(&(resource_ptr -> resource_mqtt), (UCHAR *)resource_ptr -> resource_hostname, resource_ptr -> resource_hostname_length, + (UCHAR *)NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH, sizeof(NX_AZURE_IOT_HUB_CLIENT_WEB_SOCKET_PATH) - 1)); +} +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + UINT nx_azure_iot_hub_client_connect(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT clean_session, UINT wait_option) { @@ -253,6 +385,7 @@ VOID *buffer_context; UINT buffer_length; ULONG expiry_time_secs; az_result core_result; +UINT server_port; /* Check for invalid input pointers. */ if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL)) @@ -296,13 +429,18 @@ az_result core_result; /* Obtain the mutex. */ tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); +#ifdef NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE + /* Add the real interface type into the user agent string. */ + nx_azure_iot_hub_client_user_agent_update(hub_client_ptr, &server_address); +#endif /* NX_AZURE_IOT_HUB_CLIENT_USER_AGENT_UPDATE */ + /* Set resource pointer and buffer context. */ resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); /* Build client id. */ buffer_length = buffer_size; core_result = az_iot_hub_client_get_client_id(&(hub_client_ptr -> iot_hub_client_core), - (CHAR *)buffer_ptr, buffer_length, &buffer_length); + (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length); if (az_result_failed(core_result)) { @@ -322,7 +460,7 @@ az_result core_result; /* Build user name. */ buffer_length = buffer_size; core_result = az_iot_hub_client_get_user_name(&hub_client_ptr -> iot_hub_client_core, - (CHAR *)buffer_ptr, buffer_length, &buffer_length); + (CHAR *)buffer_ptr, buffer_length, (size_t *)&buffer_length); if (az_result_failed(core_result)) { @@ -353,7 +491,7 @@ az_result core_result; return(status); } - expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY; + expiry_time_secs += NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT; status = hub_client_ptr -> nx_azure_iot_hub_client_token_refresh(hub_client_ptr, expiry_time_secs, hub_client_ptr -> nx_azure_iot_hub_client_symmetric_key, @@ -370,6 +508,7 @@ az_result core_result; LogError(LogLiteralArgs("IoTHub client connect fail: Token generation failed status: %d"), status); return(status); } + hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time = expiry_time_secs; } else { @@ -413,8 +552,21 @@ az_result core_result; /* Release the mutex. */ tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (mqtt_client_ptr -> nxd_mqtt_client_use_websocket == NX_TRUE) + { + server_port = NXD_MQTT_OVER_WEBSOCKET_TLS_PORT; + } + else + { + server_port = NXD_MQTT_TLS_PORT; + } +#else + server_port = NXD_MQTT_TLS_PORT; +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Start MQTT connection. */ - status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, NXD_MQTT_TLS_PORT, + status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, server_port, nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE, clean_session, wait_option); @@ -539,6 +691,7 @@ static VOID nx_azure_iot_hub_client_mqtt_disconnect_notify(NXD_MQTT_CLIENT *clie NX_AZURE_IOT_RESOURCE *resource = nx_azure_iot_resource_search(client_ptr); NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = NX_NULL; NX_AZURE_IOT_THREAD *thread_list_ptr; +ULONG current_time = 0; /* This function is protected by MQTT mutex. */ @@ -546,13 +699,12 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; { hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)resource -> resource_data_ptr; } - else + + if (hub_client_ptr == NX_NULL) { return; } - NX_ASSERT(hub_client_ptr != NX_NULL); - /* Wake up all threads. */ for (thread_list_ptr = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; thread_list_ptr; @@ -569,8 +721,20 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; /* Call connection notify if it is set. */ if (hub_client_ptr && hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback) { - hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, - NX_AZURE_IOT_DISCONNECTED); + if (hub_client_ptr -> nx_azure_iot_hub_client_token_refresh && + (nx_azure_iot_unix_time_get(hub_client_ptr -> nx_azure_iot_ptr, + ¤t_time) == NX_AZURE_IOT_SUCCESS) && + (current_time > hub_client_ptr -> nx_azure_iot_hub_client_sas_token_expiry_time)) + { + hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, + NX_AZURE_IOT_SAS_TOKEN_EXPIRED); + } + else + { + hub_client_ptr -> nx_azure_iot_hub_client_connection_status_callback(hub_client_ptr, + NX_AZURE_IOT_DISCONNECTED); + } + } } } @@ -616,9 +780,11 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; /* Cleanup received messages. */ nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message)); - nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message)); + nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_properties_message)); + nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message)); + nx_azure_iot_hub_client_received_message_cleanup(&(hub_client_ptr -> nx_azure_iot_hub_client_command_message)); + + hub_client_ptr -> nx_azure_iot_hub_client_state = NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED; /* Release the mutex. */ tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); @@ -647,6 +813,31 @@ NX_PACKET *next_ptr; message -> message_tail = NX_NULL; } +static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ +UINT status = NX_AZURE_IOT_SUCCESS; + + if (status == NX_AZURE_IOT_SUCCESS && + (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process != NX_NULL)) + { + status = hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable(hub_client_ptr); + } + + if (status == NX_AZURE_IOT_SUCCESS && + (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process != NX_NULL)) + { + status = hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_enable(hub_client_ptr); + } + + if (status == NX_AZURE_IOT_SUCCESS && + (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process != NX_NULL)) + { + status = hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_enable(hub_client_ptr); + } + + return(status); +} + UINT nx_azure_iot_hub_client_deinitialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; @@ -688,9 +879,53 @@ UINT status; return(NX_AZURE_IOT_SUCCESS); } +UINT nx_azure_iot_hub_client_trusted_cert_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate) +{ +UINT i; +NX_AZURE_IOT_RESOURCE *resource_ptr; + + if ((hub_client_ptr == NX_NULL) || + (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || + (trusted_certificate == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++) + { + if (resource_ptr -> resource_trusted_certificates[i] == NX_NULL) + { + resource_ptr -> resource_trusted_certificates[i] = trusted_certificate; + break; + } + } + + /* Release the mutex. */ + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates)) + { + return(NX_AZURE_IOT_SUCCESS); + } + else + { + + /* No more space to store trusted certificate. */ + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } +} + UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_SECURE_X509_CERT *device_certificate) { +UINT i; +NX_AZURE_IOT_RESOURCE *resource_ptr; if ((hub_client_ptr == NX_NULL) || (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || @@ -703,12 +938,29 @@ UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client /* Obtain the mutex. */ tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_device_certificate = device_certificate; + resource_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource); + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++) + { + if (resource_ptr -> resource_device_certificates[i] == NX_NULL) + { + resource_ptr -> resource_device_certificates[i] = device_certificate; + break; + } + } /* Release the mutex. */ tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_SUCCESS); + if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates)) + { + return(NX_AZURE_IOT_SUCCESS); + } + else + { + + /* No more space to store device certificate. */ + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } } UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -758,6 +1010,55 @@ UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_pt return(NX_AZURE_IOT_SUCCESS); } +UINT nx_azure_iot_hub_client_component_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length) +{ + return(nx_azure_iot_hub_client_component_add_internal(hub_client_ptr, component_name_ptr, component_name_length, NX_NULL, NX_NULL)); +} + +UINT nx_azure_iot_hub_client_component_add_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT (*callback_ptr)(VOID *json_reader_ptr, + ULONG version, + VOID *args), + VOID *callback_args) +{ +UINT length_of_componet_list; + + if ((hub_client_ptr == NX_NULL) || + (component_name_ptr == NX_NULL) || + (component_name_length == NX_NULL)) + { + LogError(LogLiteralArgs("IoT Hub add component fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + length_of_componet_list = + (UINT)hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length; + + if (length_of_componet_list >= NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST) + { + LogError(LogLiteralArgs("IoT Hub fail due to buffer insufficient")); + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + /* Using internal fields for faster update */ + hub_client_ptr -> nx_azure_iot_hub_client_component_list[length_of_componet_list] = + az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length); + hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length++; + hub_client_ptr -> nx_azure_iot_hub_client_component_callback[length_of_componet_list] = callback_ptr; + hub_client_ptr -> nx_azure_iot_hub_client_component_callback_args[length_of_componet_list] = callback_args; + + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + UINT nx_azure_iot_hub_client_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_PACKET **packet_pptr, UINT wait_option) { @@ -784,9 +1085,9 @@ az_result core_result; } topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); - core_result = az_iot_hub_client_telemetry_get_publish_topic(&hub_client_ptr -> iot_hub_client_core, + core_result = az_iot_hub_client_telemetry_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), NULL, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - topic_length, &topic_length); + topic_length, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub client telemetry message create fail with error status: %d"), core_result); @@ -805,6 +1106,35 @@ UINT nx_azure_iot_hub_client_telemetry_message_delete(NX_PACKET *packet_ptr) return(nx_packet_release(packet_ptr)); } +UINT nx_azure_iot_hub_client_telemetry_component_set(NX_PACKET *packet_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT wait_option) +{ +UINT status; + + if ((packet_ptr == NX_NULL) || + (component_name_ptr == NX_NULL) || + (component_name_length == 0)) + { + LogError(LogLiteralArgs("IoTHub telemetry component set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + status = nx_azure_iot_hub_client_telemetry_property_add(packet_ptr, + (const UCHAR*)NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING, + sizeof(NX_AZURE_IOT_HUB_CLIENT_COMPONENT_STRING) - 1, + component_name_ptr, component_name_length, + wait_option); + if (status) + { + LogError(LogLiteralArgs("Telemetry component append fail: error status: %d"), status); + return(status); + } + + return(NX_AZURE_IOT_SUCCESS); +} + UINT nx_azure_iot_hub_client_telemetry_property_add(NX_PACKET *packet_ptr, const UCHAR *property_name, USHORT property_name_length, const UCHAR *property_value, USHORT property_value_length, @@ -877,7 +1207,7 @@ UCHAR packet_id[2]; topic_len = packet_ptr -> nx_packet_length; status = nx_azure_iot_mqtt_packet_id_get(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_id, wait_option); + packet_id); if (status) { LogError(LogLiteralArgs("Failed to get packet id")); @@ -941,20 +1271,20 @@ UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_c hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback = callback_ptr; hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_callback_args = callback_args; } - else if (message_type == NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES) + else if (message_type == NX_AZURE_IOT_HUB_PROPERTIES) { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_callback_args = callback_args; + hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_callback = callback_ptr; + hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_callback_args = callback_args; } - else if (message_type == NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES) + else if (message_type == NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES) { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_callback_args = callback_args; + hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_callback = callback_ptr; + hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_callback_args = callback_args; } - else if (message_type == NX_AZURE_IOT_HUB_DIRECT_METHOD) + else if (message_type == NX_AZURE_IOT_HUB_COMMAND) { - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_callback = callback_ptr; - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_callback_args = callback_args; + hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_callback = callback_ptr; + hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_callback_args = callback_args; } else { @@ -972,11 +1302,24 @@ UINT nx_azure_iot_hub_client_receive_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_c UINT nx_azure_iot_hub_client_cloud_message_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { + + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_TRUE)); } UINT nx_azure_iot_hub_client_cloud_message_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub cloud message unsubscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + return(nx_azure_iot_hub_client_cloud_message_sub_unsub(hub_client_ptr, NX_FALSE)); } @@ -1106,7 +1449,7 @@ NX_AZURE_IOT_THREAD thread_list; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr) +UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr) { UINT status; ULONG topic_offset; @@ -1153,6 +1496,14 @@ UINT nx_azure_iot_hub_client_cloud_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_ { UINT status; + if ((hub_client_ptr == NX_NULL) || + (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub cloud message receive fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE, &(hub_client_ptr -> nx_azure_iot_hub_client_c2d_message), packet_pptr, wait_option); @@ -1235,8 +1586,9 @@ az_span span; return(NX_AZURE_IOT_SUCCESS); } -static VOID nx_azure_iot_hub_client_device_twin_ack_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, - USHORT packet_id, NX_PACKET *transmit_packet_ptr, VOID *context) +static VOID nx_azure_iot_hub_client_mqtt_ack_receive_notify(NXD_MQTT_CLIENT *client_ptr, UINT type, + USHORT packet_id, NX_PACKET *transmit_packet_ptr, + VOID *context) { NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr = (NX_AZURE_IOT_HUB_CLIENT *)context; @@ -1248,7 +1600,7 @@ ULONG bytes_copied; NX_PARAMETER_NOT_USED(packet_id); NX_PARAMETER_NOT_USED(context); - /* Mointor subscribe ack. */ + /* Monitor subscribe ack. */ if (type == MQTT_CONTROL_PACKET_TYPE_SUBACK) { @@ -1265,33 +1617,33 @@ ULONG bytes_copied; (!memcmp(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC, buffer, sizeof(AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_SUBSCRIBE_TOPIC) - 1))) { - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack = NX_TRUE; + hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack = NX_TRUE; } } } -UINT nx_azure_iot_hub_client_device_twin_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +UINT nx_azure_iot_hub_client_properties_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; NXD_MQTT_CLIENT *client_ptr; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub client device twin subscribe fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client properties subscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); /* Atomically update the handler as we need to serialize the handler with incoming messages. */ - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process = - nx_azure_iot_hub_client_device_twin_process; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_process = - nx_azure_iot_hub_client_device_twin_process; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_enable = - nx_azure_iot_hub_client_device_twin_enable; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_enable = - nx_azure_iot_hub_client_device_twin_enable; + hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process = + nx_azure_iot_hub_client_properties_process; + hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_process = + nx_azure_iot_hub_client_properties_process; + hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_enable = + nx_azure_iot_hub_client_properties_enable; + hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_enable = + nx_azure_iot_hub_client_properties_enable; /* Register callbacks even if not connect and when connect complete subscribe for topics. */ if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) @@ -1301,11 +1653,11 @@ NXD_MQTT_CLIENT *client_ptr; } /* Initialize variables. */ - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack = NX_FALSE; + hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack = NX_FALSE; /* Set ack receive notify for subscribe ack. */ client_ptr = &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt); - client_ptr -> nxd_mqtt_ack_receive_notify = nx_azure_iot_hub_client_device_twin_ack_notify; + client_ptr -> nxd_mqtt_ack_receive_notify = nx_azure_iot_hub_client_mqtt_ack_receive_notify; client_ptr -> nxd_mqtt_ack_receive_context = hub_client_ptr; tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); @@ -1339,13 +1691,13 @@ NXD_MQTT_CLIENT *client_ptr; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_device_twin_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +UINT nx_azure_iot_hub_client_properties_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client properties unsubscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } @@ -1367,20 +1719,20 @@ UINT status; return(status); } - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process = NX_NULL; - hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message.message_process = NX_NULL; + hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process = NX_NULL; + hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message.message_process = NX_NULL; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - VOID (*callback_ptr)( - NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT request_id, - UINT response_status, - ULONG version, - VOID *args), - VOID *callback_args) +UINT nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + VOID (*callback_ptr)( + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT request_id, + UINT response_status, + ULONG version, + VOID *args), + VOID *callback_args) { if (hub_client_ptr == NX_NULL) { @@ -1388,16 +1740,20 @@ UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IO return(NX_AZURE_IOT_INVALID_PARAMETER); } + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback = callback_ptr; hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback_args = callback_args; + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_twin_request_id_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UCHAR *buffer_ptr, UINT buffer_len, - az_span *request_id_span_ptr, - UINT *request_id_ptr, UINT odd_seq) +static UINT nx_azure_iot_hub_client_properties_request_id_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UCHAR *buffer_ptr, UINT buffer_len, + az_span *request_id_span_ptr, + UINT *request_id_ptr, UINT odd_seq) { az_span span; @@ -1439,7 +1795,7 @@ az_span span; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_device_twin_reponse_topic_status(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT wait_option) +static UINT nx_azure_iot_hub_client_properties_subscribe_status_check(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT wait_option) { /* Wait for subscribe ack of topic "$iothub/twin/res/#". */ @@ -1458,7 +1814,7 @@ static UINT nx_azure_iot_hub_client_device_twin_reponse_topic_status(NX_AZURE_IO } /* Check if receive the subscribe ack. */ - if (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_response_subscribe_ack == NX_TRUE) + if (hub_client_ptr -> nx_azure_iot_hub_client_properties_subscribe_ack == NX_TRUE) { /* Clean ack receive notify. */ @@ -1488,50 +1844,92 @@ static UINT nx_azure_iot_hub_client_device_twin_reponse_topic_status(NX_AZURE_IO return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_device_twin_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - const UCHAR *message_buffer, UINT message_length, - UINT *request_id_ptr, UINT *response_status_ptr, - ULONG *version_ptr, UINT wait_option) +static UINT nx_azure_iot_hub_client_properties_request_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT request_id, NX_PACKET *packet_ptr, ULONG topic_length, + const UCHAR *message_buffer, UINT message_length, UINT message_type, + NX_PACKET **response_packet_pptr, UINT wait_option) { -UINT status; -UINT buffer_size; -NX_PACKET *packet_ptr; -UINT topic_length; -UINT request_id; -az_span request_id_span; NX_AZURE_IOT_THREAD thread_list; -az_result core_result; -ULONG topic_offset; -USHORT length; +UINT status; - if (hub_client_ptr == NX_NULL) + if ((message_buffer != NX_NULL) && (message_length != 0)) { - LogError(LogLiteralArgs("IoTHub client reported state send fail: INVALID POINTER")); - return(NX_AZURE_IOT_INVALID_PARAMETER); - } - if ((status = nx_azure_iot_hub_client_device_twin_reponse_topic_status(hub_client_ptr, wait_option))) - { - LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status); - return(status); + /* Append payload. */ + status = nx_packet_data_append(packet_ptr, (VOID *)message_buffer, message_length, + packet_ptr -> nx_packet_pool_owner, + wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed")); + return(status); + } } - /* Check if the last request was throttled and if the next need to be throttled. */ - if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr))) - { - LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status); - return(status); - } + /* Obtain the mutex. */ + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - /* Steps. - * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}" - * 2. Wait for the response if required. - * 3. Return result if present. - * */ - if (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process == NX_NULL) + thread_list.thread_message_type = message_type; + thread_list.thread_ptr = tx_thread_identify(); + thread_list.thread_expected_id = request_id; + thread_list.thread_received_message = NX_NULL; + thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; + hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list; + + /* Release the mutex. */ + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), + packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, + wait_option); + + if (status) { - LogError(LogLiteralArgs("IoTHub client reported state send fail: NOT ENABLED")); - return(NX_AZURE_IOT_NOT_ENABLED); + + /* Remove thread from waiting suspend queue. */ + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + LogError(LogLiteralArgs("IoTHub transport send: PUBLISH FAIL status: %d"), status); + return(status); + } + + if ((thread_list.thread_received_message) == NX_NULL && wait_option) + { + tx_thread_sleep(wait_option); + } + + /* Obtain the mutex. */ + tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); + *response_packet_pptr = thread_list.thread_received_message; + + /* Release the mutex. */ + tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_reported_properties_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option) +{ +UINT status; +NX_PACKET *packet_ptr; +UINT request_id; +UCHAR *buffer_ptr; +ULONG buffer_size; +az_span request_id_span; +az_result core_result; +UINT topic_length; + + if ((hub_client_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub reported properties create fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, @@ -1539,40 +1937,41 @@ USHORT length; &packet_ptr, wait_option); if (status) { - LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER ALLOCATE FAIL")); + LogError(LogLiteralArgs("IoTHub client reported properties create fail: BUFFER ALLOCATE FAIL")); return(status); } buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); if (buffer_size <= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE) { - LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER INSUFFICENT")); + LogError(LogLiteralArgs("IoTHub client reported properties create fail: BUFFER INSUFFICENT")); nx_packet_release(packet_ptr); return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); } buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE; - /* Generate odd request id for reported properties send. */ - status = nx_azure_iot_hub_client_twin_request_id_get(hub_client_ptr, - (UCHAR *)(packet_ptr -> nx_packet_data_end - - NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE), - NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE, - &request_id_span, &request_id, NX_TRUE); + /* Generate odd request id for reported properties send */ + status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr, + (UCHAR *)(packet_ptr -> nx_packet_data_end - + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE), + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE, + &request_id_span, &request_id, NX_TRUE); if (status) { - LogError(LogLiteralArgs("IoTHub client reported state send failed to get request id")); + LogError(LogLiteralArgs("IoTHub client reported properties create fail: get request id failed")); nx_packet_release(packet_ptr); return(status); } - core_result = az_iot_hub_client_twin_patch_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), - request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - buffer_size, &topic_length); + core_result = az_iot_hub_client_properties_get_reported_publish_topic(&(hub_client_ptr -> iot_hub_client_core), + request_id_span, + (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + buffer_size, &topic_length); if (az_result_failed(core_result)) { - LogError(LogLiteralArgs("IoTHub client reported state send fail: NX_AZURE_IOT_HUB_CLIENT_TOPIC_SIZE is too small.")); + LogError(LogLiteralArgs("IoTHub client reported properties create fail: NX_AZURE_IOT_PNP_CLIENT_TOPIC_SIZE is too small.")); nx_packet_release(packet_ptr); return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); } @@ -1580,102 +1979,123 @@ USHORT length; packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; packet_ptr -> nx_packet_length = topic_length; - /* Append payload. */ - status = nx_packet_data_append(packet_ptr, (VOID *)message_buffer, message_length, - packet_ptr -> nx_packet_pool_owner, - wait_option); - if (status) - { - LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed")); - nx_packet_release(packet_ptr); - return(status); - } + /* Set the buffer pointer. */ + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET; - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + /* encode topic length */ + buffer_ptr[5] = (UCHAR)(packet_ptr -> nx_packet_length >> 8); + buffer_ptr[6] = (UCHAR)(packet_ptr -> nx_packet_length & 0xFF); - thread_list.thread_message_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE; - thread_list.thread_ptr = tx_thread_identify(); - thread_list.thread_expected_id = request_id; - thread_list.thread_received_message = NX_NULL; - thread_list.thread_next = hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended; - hub_client_ptr -> nx_azure_iot_hub_client_thread_suspended = &thread_list; + /* encode request id */ + buffer_ptr[4] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[3] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[2] = (UCHAR)((request_id & 0xFF)); + request_id >>= 8; + buffer_ptr[1] = (UCHAR)(request_id & 0xFF); - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + *packet_pptr = packet_ptr; - status = nx_azure_iot_publish_mqtt_packet(&(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), - packet_ptr, topic_length, NX_NULL, NX_AZURE_IOT_MQTT_QOS_0, - wait_option); + return(NX_AZURE_IOT_SUCCESS); +} - if (status) - { - nx_packet_release(packet_ptr); +UINT nx_azure_iot_hub_client_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option) +{ +NX_PACKET *response_packet_ptr; +UINT topic_length; +UINT request_id = 0; +ULONG topic_offset; +USHORT length; +UCHAR *buffer_ptr; +UINT status; - /* remove thread from waiting suspend queue. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); - nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + if ((hub_client_ptr == NX_NULL) || + (packet_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub client reported properties send fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } - LogError(LogLiteralArgs("IoTHub client reported state send: PUBLISH FAIL status: %d"), status); + /* Check if properties is subscribed */ + if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option))) + { + LogError(LogLiteralArgs("IoTHub client reported properties send fail with error %d"), status); return(status); } - LogDebug(LogLiteralArgs("request_id: %d"), request_id); - if ((thread_list.thread_received_message) == NX_NULL && wait_option) + /* Check if the last request was throttled and if the next need to be throttled. */ + if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr))) { - tx_thread_sleep(wait_option); + LogError(LogLiteralArgs("IoTHub client reported properties send fail with error %d"), status); + return(status); } - /* Obtain the mutex. */ - tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + /* Steps. + * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}" + * 2. Wait for the response if required. + * 3. Return result if present. + * */ - nx_azure_iot_hub_client_thread_dequeue(hub_client_ptr, &thread_list); - packet_ptr = thread_list.thread_received_message; + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr - NX_AZURE_IOT_PUBLISH_PACKET_START_OFFSET; - /* Release the mutex. */ - tx_mutex_put(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + topic_length = (UINT)((buffer_ptr[5] << 8) | buffer_ptr[6]); - if (request_id_ptr) + request_id += (buffer_ptr[1] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[2] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[3] & 0xFF); + request_id <<= 8; + request_id += (buffer_ptr[4] & 0xFF); + + status = nx_azure_iot_hub_client_properties_request_response(hub_client_ptr, + request_id, packet_ptr, topic_length, NX_NULL, 0, + NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE, + &response_packet_ptr, wait_option); + if (status) { - *request_id_ptr = request_id; + LogError(LogLiteralArgs("IoTHub client reported properties send fail: append failed")); + return(status); } - if (packet_ptr == NX_NULL) - { - LogError(LogLiteralArgs("IoTHub client reported state not responded")); - if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) - { - return(NX_AZURE_IOT_DISCONNECTED); - } + /* The packet of reported properties has been sent out successfully, + next the return value should be NX_AZURE_IOT_SUCCESS. */ - return(NX_AZURE_IOT_NO_PACKET); + /* Continue to process response and the caller can check the response status to see if iothub accept the properties or not, + the reponse status is available only when the return status is NX_AZURE_IOT_SUCCESS. */ + if (request_id_ptr) + { + *request_id_ptr = request_id; } - if ((status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, - &topic_offset, &length))) + if (response_status_ptr) { - nx_packet_release(packet_ptr); - return(status); + *response_status_ptr = 0; } - if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, - packet_ptr, topic_offset, length, - NX_NULL, version_ptr, NX_NULL, - response_status_ptr))) + if (response_packet_ptr) { - nx_packet_release(packet_ptr); - return(status); - } + if(nx_azure_iot_hub_client_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr, + &topic_offset, &length) == NX_AZURE_IOT_SUCCESS) + { + nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, + response_packet_ptr, topic_offset, length, + NX_NULL, version_ptr, NX_NULL, + response_status_ptr); + } - /* Release message block. */ - nx_packet_release(packet_ptr); + nx_packet_release(response_packet_ptr); + } return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_device_twin_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT wait_option) +UINT nx_azure_iot_hub_client_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT wait_option) { UINT status; UINT topic_length; @@ -1687,20 +2107,20 @@ az_result core_result; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub client device twin publish fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client properties request failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - - if ((status = nx_azure_iot_hub_client_device_twin_reponse_topic_status(hub_client_ptr, wait_option))) + + if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option))) { - LogError(LogLiteralArgs("IoTHub client device twin publish fail with error %d"), status); + LogError(LogLiteralArgs("IoTHub client properties request failed with error %d"), status); return(status); } /* Check if the last request was throttled and if the next need to be throttled. */ if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr))) { - LogError(LogLiteralArgs("IoTHub client device twin publish failed with error %d"), status); + LogError(LogLiteralArgs("IoTHub client properties request failed with error %d"), status); return(status); } @@ -1712,7 +2132,7 @@ az_result core_result; &packet_ptr, wait_option); if (status) { - LogError(LogLiteralArgs("IoTHub client device twin publish fail: BUFFER ALLOCATE FAIL")); + LogError(LogLiteralArgs("IoTHub client properties request failed: BUFFER ALLOCATE FAIL")); return(status); } @@ -1726,12 +2146,12 @@ az_result core_result; buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE; - /* Generate even request id for twin properties request. */ - status = nx_azure_iot_hub_client_twin_request_id_get(hub_client_ptr, - (UCHAR *)(packet_ptr -> nx_packet_data_end - - NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE), - NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE, - &request_id_span, &request_id, NX_FALSE); + /* Generate even request id for properties request. */ + status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr, + (UCHAR *)(packet_ptr -> nx_packet_data_end - + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE), + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE, + &request_id_span, &request_id, NX_FALSE); if (status) { LogError(LogLiteralArgs("IoTHub client device twin failed to get request id")); @@ -1739,9 +2159,9 @@ az_result core_result; return(status); } - core_result = az_iot_hub_client_twin_document_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), - request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - buffer_size, &topic_length); + core_result = az_iot_hub_client_properties_document_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), + request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + buffer_size, (size_t *)&topic_length); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub client device twin get topic fail.")); @@ -1765,39 +2185,39 @@ az_result core_result; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_device_twin_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET **packet_pptr, UINT wait_option) +UINT nx_azure_iot_hub_client_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option) { UINT status; ULONG topic_offset; USHORT topic_length; az_result core_result; az_span topic_span; -az_iot_hub_client_twin_response out_twin_response; +az_iot_hub_client_properties_message out_message; NX_PACKET *packet_ptr; - if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + if ((hub_client_ptr == NX_NULL) || (packet_pptr == NX_NULL)) { - LogError(LogLiteralArgs("IoTHub client device twin receive failed: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client properties receive failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } /* Steps. - * 1. Check if the twin document is available to receive from linklist. + * 1. Check if the properties document is available to receive from linklist. * 2. If present check the response. * 3. Return the payload of the response. * */ - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message), + status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_PROPERTIES, + &(hub_client_ptr -> nx_azure_iot_hub_client_properties_message), &packet_ptr, wait_option); if (status) { LogError(LogLiteralArgs("IoTHub client device twin receive failed status: %d"), status); return(status); } - - if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, - &topic_length)) + + if (nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, &topic_length)) { /* Message not supported. It will be released. */ @@ -1806,63 +2226,280 @@ NX_PACKET *packet_ptr; } topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), (INT)topic_length); - core_result = az_iot_hub_client_twin_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), - topic_span, &out_twin_response); + core_result = az_iot_hub_client_properties_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), + topic_span, &out_message); if (az_result_failed(core_result)) { - /* Topic name does not match device twin format. */ + /* Topic name does not match properties format. */ nx_packet_release(packet_ptr); return(NX_AZURE_IOT_SDK_CORE_ERROR); } - if ((out_twin_response.status < 200) || (out_twin_response.status >= 300)) + if ((out_message.status < 200) || (out_message.status >= 300)) { nx_packet_release(packet_ptr); return(NX_AZURE_IOT_SERVER_RESPONSE_ERROR); } + if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + *packet_pptr = packet_ptr; - return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr)); + return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET **packet_pptr, UINT wait_option) +UINT nx_azure_iot_hub_client_writable_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option) { UINT status; +NX_PACKET *packet_ptr; - if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + if ((hub_client_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) { - LogError(LogLiteralArgs("IoTHub client device twin receive properties failed: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client receive properties failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } /* Steps. - * 1. Check if the desired properties document is available to receive from linklist. - * 2. Return result if present. + * 1. Check if the writable properties document is available to receive from linklist. + * 2. Parse result if present. + * 3. Return parse result. * */ - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message), - packet_pptr, wait_option); + status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES, + &(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message), + &packet_ptr, wait_option); if (status) { + LogError(LogLiteralArgs("IoTHub client device twin receive failed status: %d"), status); return(status); } - return(nx_azure_iot_hub_client_adjust_payload(*packet_pptr)); + if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr))) + { + nx_packet_release(packet_ptr); + return(status); + } + + *packet_pptr = packet_ptr; + + return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT is_subscribe) + +UINT nx_azure_iot_hub_client_device_twin_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ + + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client device twin subscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_client_properties_enable(hub_client_ptr)); +} + +UINT nx_azure_iot_hub_client_device_twin_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ + + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client device twin unsubscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_client_properties_disable(hub_client_ptr)); +} + + +UINT nx_azure_iot_hub_client_device_twin_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *message_buffer, UINT message_length, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option) { UINT status; +UINT buffer_size; +NX_PACKET *packet_ptr; +UINT topic_length; +UINT request_id; +az_span request_id_span; +az_result core_result; +ULONG topic_offset; +USHORT length; +NX_PACKET *response_packet_ptr; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub cloud message subscribe fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client reported state send fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + if ((status = nx_azure_iot_hub_client_properties_subscribe_status_check(hub_client_ptr, wait_option))) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status); + return(status); + } + + /* Check if the last request was throttled and if the next need to be throttled. */ + if ((status = nx_azure_iot_hub_client_throttled_check(hub_client_ptr))) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail with error %d"), status); + return(status); + } + + /* Steps. + * 1. Publish message to topic "$iothub/twin/PATCH/properties/reported/?$rid={request id}" + * 2. Wait for the response if required. + * 3. Return result if present. + * */ + if (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: NOT ENABLED")); + return(NX_AZURE_IOT_NOT_ENABLED); + } + + status = nx_azure_iot_publish_packet_get(hub_client_ptr -> nx_azure_iot_ptr, + &(hub_client_ptr -> nx_azure_iot_hub_client_resource.resource_mqtt), + &packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER ALLOCATE FAIL")); + return(status); + } + + buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); + if (buffer_size <= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: BUFFER INSUFFICENT")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + buffer_size -= NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE; + + /* Generate odd request id for reported properties send. */ + status = nx_azure_iot_hub_client_properties_request_id_get(hub_client_ptr, + (UCHAR *)(packet_ptr -> nx_packet_data_end - + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE), + NX_AZURE_IOT_HUB_CLIENT_U32_MAX_BUFFER_SIZE, + &request_id_span, &request_id, NX_TRUE); + + if (status) + { + LogError(LogLiteralArgs("IoTHub client reported state send failed to get request id")); + nx_packet_release(packet_ptr); + return(status); + } + + core_result = az_iot_hub_client_twin_patch_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), + request_id_span, (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + buffer_size, (size_t *)&topic_length); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: NX_AZURE_IOT_HUB_CLIENT_TOPIC_SIZE is too small.")); + nx_packet_release(packet_ptr); + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } + + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; + packet_ptr -> nx_packet_length = topic_length; + + status = nx_azure_iot_hub_client_properties_request_response(hub_client_ptr, + request_id, packet_ptr, topic_length, message_buffer, message_length, + NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE, + &response_packet_ptr, wait_option); + if (status) + { + LogError(LogLiteralArgs("IoTHub client reported state send fail: append failed")); + nx_packet_release(packet_ptr); + return(status); + } + + if (request_id_ptr) + { + *request_id_ptr = request_id; + } + + if (response_packet_ptr == NX_NULL) + { + if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) + { + return(NX_AZURE_IOT_DISCONNECTED); + } + return(NX_AZURE_IOT_NO_PACKET); + } + + if ((status = nx_azure_iot_hub_client_process_publish_packet(response_packet_ptr -> nx_packet_prepend_ptr, + &topic_offset, &length))) + { + nx_packet_release(response_packet_ptr); + return(status); + } + + if ((status = nx_azure_iot_hub_client_device_twin_parse(hub_client_ptr, + response_packet_ptr, topic_offset, length, + NX_NULL, version_ptr, NX_NULL, + response_status_ptr))) + { + nx_packet_release(response_packet_ptr); + return(status); + } + + /* Release message block. */ + nx_packet_release(response_packet_ptr); + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_device_twin_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT wait_option) +{ + + if (hub_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client device twin properties request failed: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } + return(nx_azure_iot_hub_client_properties_request(hub_client_ptr, wait_option)); +} + +UINT nx_azure_iot_hub_client_device_twin_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, UINT wait_option) +{ + + if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client device twin properties receive failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_client_properties_receive(hub_client_ptr, packet_pptr, wait_option)); +} + +UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, UINT wait_option) +{ + + if (hub_client_ptr == NX_NULL || packet_pptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTHub client device twin desired properties receive failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_client_writable_properties_receive(hub_client_ptr, packet_pptr, wait_option)); +} + +static UINT nx_azure_iot_hub_client_cloud_message_sub_unsub(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT is_subscribe) +{ +UINT status; + if (is_subscribe) { tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); @@ -1955,8 +2592,8 @@ USHORT topic_length; topic_offset) & 0xFFFF); } - if (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process && - (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process(hub_client_ptr, packet_ptr, + if (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process && + (hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process(hub_client_ptr, packet_ptr, topic_offset, topic_length) == NX_AZURE_IOT_SUCCESS)) { @@ -1975,8 +2612,8 @@ USHORT topic_length; continue; } - if ((hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process) && - (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process(hub_client_ptr, + if ((hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process) && + (hub_client_ptr -> nx_azure_iot_hub_client_properties_message.message_process(hub_client_ptr, packet_ptr, topic_offset, topic_length) == NX_AZURE_IOT_SUCCESS)) { @@ -2105,13 +2742,13 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_direct_method_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, - USHORT topic_length) +static UINT nx_azure_iot_hub_client_command_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + ULONG topic_offset, + USHORT topic_length) { UCHAR *topic_name; -az_iot_hub_client_method_request request; +az_iot_hub_client_command_request request; az_span receive_topic; az_result core_result; UINT status; @@ -2130,8 +2767,8 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; } receive_topic = az_span_create(topic_name, topic_length); - core_result = az_iot_hub_client_methods_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), - receive_topic, &request); + core_result = az_iot_hub_client_commands_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), + receive_topic, &request); if (az_result_failed(core_result)) { @@ -2141,7 +2778,7 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr, packet_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, + NX_AZURE_IOT_HUB_COMMAND, 0, &thread_list_ptr); if (status == NX_AZURE_IOT_SUCCESS) { @@ -2151,44 +2788,42 @@ NX_AZURE_IOT_THREAD *thread_list_ptr; /* No thread is waiting for direct method message yet. */ nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message), + &(hub_client_ptr -> nx_azure_iot_hub_client_command_message), packet_ptr); return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_device_twin_message_type_get(az_iot_hub_client_twin_response *out_twin_response_ptr, - UINT request_id) +static UINT nx_azure_iot_hub_client_properties_message_type_get(UINT core_message_type, UINT request_id) { -UINT mesg_type; +UINT message_type; - switch (out_twin_response_ptr -> response_type) + switch (core_message_type) { - case AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_GET : + case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE : /* Fall through. */ - case AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_REPORTED_PROPERTIES : + case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_ACKNOWLEDGEMENT : { /* Odd requests are of reported properties and even of twin properties. */ - mesg_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : - NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE; + message_type = request_id % 2 == 0 ? NX_AZURE_IOT_HUB_PROPERTIES : NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE; } break; - case AZ_IOT_HUB_CLIENT_TWIN_RESPONSE_TYPE_DESIRED_PROPERTIES : + case AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED : { - mesg_type = NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES; + message_type = NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES; } break; default : { - mesg_type = NX_AZURE_IOT_HUB_NONE; + message_type = NX_AZURE_IOT_HUB_NONE; } } - return mesg_type; + return message_type; } static UINT nx_azure_iot_hub_client_device_twin_parse(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, @@ -2238,8 +2873,8 @@ uint32_t version; if (message_type_ptr) { - *message_type_ptr = nx_azure_iot_hub_client_device_twin_message_type_get(&out_twin_response, - (UINT)request_id); + *message_type_ptr = nx_azure_iot_hub_client_properties_message_type_get((UINT)out_twin_response.response_type, + (UINT)request_id); } if (status_ptr) @@ -2250,10 +2885,10 @@ uint32_t version; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_device_twin_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - NX_PACKET *packet_ptr, - ULONG topic_offset, - USHORT topic_length) +static UINT nx_azure_iot_hub_client_properties_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + ULONG topic_offset, + USHORT topic_length) { NX_AZURE_IOT_THREAD *thread_list_ptr; UINT message_type; @@ -2290,7 +2925,12 @@ ULONG current_time; hub_client_ptr -> nx_azure_iot_hub_client_throttle_end_time = 0; } - if (message_type == NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE) + if (message_type == NX_AZURE_IOT_HUB_NONE) + { + LogError(LogLiteralArgs("IoTHub client fail to parse device twin: %d"), NX_AZURE_IOT_SERVER_RESPONSE_ERROR); + return(NX_AZURE_IOT_SERVER_RESPONSE_ERROR); + } + else if (message_type == NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE) { /* Only requested thread should be woken. */ @@ -2301,6 +2941,13 @@ ULONG current_time; /* Any thread can be woken. */ correlation_id = 0; + + /* Process system component. */ + if ((hub_client_ptr -> nx_azure_iot_hub_client_component_properties_process) && + ((response_status >= 200) && (response_status < 300))) + { + hub_client_ptr -> nx_azure_iot_hub_client_component_properties_process(hub_client_ptr, packet_ptr, message_type); + } } status = nx_azure_iot_hub_client_receive_thread_find(hub_client_ptr, @@ -2315,7 +2962,7 @@ ULONG current_time; switch(message_type) { - case NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE : + case NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE : { if (hub_client_ptr -> nx_azure_iot_hub_client_report_properties_response_callback) { @@ -2330,22 +2977,22 @@ ULONG current_time; } break; - case NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES : + case NX_AZURE_IOT_HUB_PROPERTIES : { /* No thread is waiting for device twin message yet. */ nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message), + &(hub_client_ptr -> nx_azure_iot_hub_client_properties_message), packet_ptr); } break; - case NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES : + case NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES : { /* No thread is waiting for device twin message yet. */ nx_azure_iot_hub_client_message_notify(hub_client_ptr, - &(hub_client_ptr -> nx_azure_iot_hub_client_device_twin_desired_properties_message), + &(hub_client_ptr -> nx_azure_iot_hub_client_writable_properties_message), packet_ptr); } break; @@ -2429,7 +3076,7 @@ az_result core_result; buffer_span = az_span_create(output_ptr, (INT)output_len); core_result= az_iot_hub_client_sas_get_password(&(hub_client_ptr -> iot_hub_client_core), expiry_time_secs, buffer_span, AZ_SPAN_EMPTY, - (CHAR *)sas_buffer, sas_buffer_len, &sas_buffer_len); + (CHAR *)sas_buffer, sas_buffer_len, (size_t *)&sas_buffer_len); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTHub failed to generate token with error status: %d"), core_result); @@ -2443,21 +3090,21 @@ az_result core_result; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +UINT nx_azure_iot_hub_client_command_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub client direct method subscribe fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client command subscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } tx_mutex_get(hub_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); /* Atomically update the handler as we need to serialize the handler with incoming messages. */ - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process = nx_azure_iot_hub_client_direct_method_process; - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_enable = nx_azure_iot_hub_client_direct_method_enable; + hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process = nx_azure_iot_hub_client_command_process; + hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_enable = nx_azure_iot_hub_client_command_enable; /* Register callbacks even if not connect and when connect complete subscribe for topics. */ if (hub_client_ptr -> nx_azure_iot_hub_client_state != NX_AZURE_IOT_HUB_CLIENT_STATUS_CONNECTED) @@ -2474,20 +3121,20 @@ UINT status; NX_AZURE_IOT_MQTT_QOS_0); if (status) { - LogError(LogLiteralArgs("IoTHub client direct method subscribe fail %d"), status); + LogError(LogLiteralArgs("IoTHub client command subscribe fail %d"), status); return(status); } return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +UINT nx_azure_iot_hub_client_command_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status; if (hub_client_ptr == NX_NULL) { - LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client command unsubscribe fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } @@ -2496,51 +3143,50 @@ UINT status; sizeof(AZ_IOT_HUB_CLIENT_METHODS_SUBSCRIBE_TOPIC) - 1); if (status) { - LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail status: %d"), status); + LogError(LogLiteralArgs("IoTHub client command unsubscribe fail status: %d"), status); return(status); } - hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process = NX_NULL; + hub_client_ptr -> nx_azure_iot_hub_client_command_message.message_process = NX_NULL; return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - const UCHAR **method_name_pptr, USHORT *method_name_length_ptr, - VOID **context_pptr, USHORT *context_length_ptr, - NX_PACKET **packet_pptr, UINT wait_option) +UINT nx_azure_iot_hub_client_command_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR **component_name_pptr, USHORT *component_name_length_ptr, + const UCHAR **command_name_pptr, USHORT *command_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_PACKET **packet_pptr, UINT wait_option) { + UINT status; -ULONG topic_offset; -USHORT topic_length; +ULONG topic_offset = 0; +USHORT topic_length = 0; az_span topic_span; -ULONG message_offset; -ULONG message_length; -NX_PACKET *packet_ptr; +NX_PACKET *packet_ptr = NX_NULL; az_result core_result; -az_iot_hub_client_method_request request; +az_iot_hub_client_command_request request; if ((hub_client_ptr == NX_NULL) || - (method_name_pptr == NX_NULL) || - (method_name_length_ptr == NX_NULL) || + (command_name_pptr == NX_NULL) || + (command_name_length_ptr == NX_NULL) || (context_pptr == NX_NULL) || (context_length_ptr == NX_NULL) || (packet_pptr == NX_NULL)) { - LogError(LogLiteralArgs("IoTHub client direct method receive fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoT PnP client command receive fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } - status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_DIRECT_METHOD, - &(hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message), - packet_pptr, wait_option); + status = nx_azure_iot_hub_client_message_receive(hub_client_ptr, NX_AZURE_IOT_HUB_COMMAND, + &(hub_client_ptr -> nx_azure_iot_hub_client_command_message), + &packet_ptr, wait_option); if (status) { return(status); } - packet_ptr = *packet_pptr; - status = _nxd_mqtt_process_publish_packet(packet_ptr, &topic_offset, &topic_length, &message_offset, &message_length); + status = nx_azure_iot_hub_client_process_publish_packet(packet_ptr -> nx_packet_prepend_ptr, &topic_offset, &topic_length); if (status) { nx_packet_release(packet_ptr); @@ -2548,49 +3194,38 @@ az_iot_hub_client_method_request request; } topic_span = az_span_create(&(packet_ptr -> nx_packet_prepend_ptr[topic_offset]), topic_length); - core_result = az_iot_hub_client_methods_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), - topic_span, &request); + core_result = az_iot_hub_client_commands_parse_received_topic(&(hub_client_ptr -> iot_hub_client_core), + topic_span, &request); if (az_result_failed(core_result)) { nx_packet_release(packet_ptr); return(NX_AZURE_IOT_SDK_CORE_ERROR); } - *packet_pptr = packet_ptr; - packet_ptr -> nx_packet_length = message_length; - - /* Adjust packet to pointer to message payload. */ - while (packet_ptr) + if ((status = nx_azure_iot_hub_client_adjust_payload(packet_ptr))) { - if ((ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) > message_offset) - { - - /* This packet contains message payload. */ - packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + message_offset; - break; - } - - message_offset -= (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr); - - /* Set current packet to empty. */ - packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_append_ptr; - - /* Move to next packet. */ - packet_ptr = packet_ptr -> nx_packet_next; + nx_packet_release(packet_ptr); + return(status); } - *method_name_pptr = az_span_ptr(request.name); - *method_name_length_ptr = (USHORT)az_span_size(request.name); + *packet_pptr = packet_ptr; + if ((component_name_pptr) && (component_name_length_ptr)) + { + *component_name_pptr = (const UCHAR *)az_span_ptr(request.component_name); + *component_name_length_ptr = (USHORT)az_span_size(request.component_name); + } + *command_name_pptr = (const UCHAR *)az_span_ptr(request.command_name); + *command_name_length_ptr = (USHORT)az_span_size(request.command_name); *context_pptr = (VOID*)az_span_ptr(request.request_id); *context_length_ptr = (USHORT)az_span_size(request.request_id); return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT status_code, VOID *context_ptr, - USHORT context_length, const UCHAR *payload, - UINT payload_length, UINT wait_option) +UINT nx_azure_iot_hub_client_command_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload, + UINT payload_length, UINT wait_option) { NX_PACKET *packet_ptr; UINT topic_length; @@ -2603,7 +3238,7 @@ az_result core_result; (context_ptr == NX_NULL) || (context_length == 0)) { - LogError(LogLiteralArgs("IoTHub direct method response fail: INVALID POINTER")); + LogError(LogLiteralArgs("IoTHub client command response fail: INVALID POINTER")); return(NX_AZURE_IOT_INVALID_PARAMETER); } @@ -2619,18 +3254,17 @@ az_result core_result; topic_length = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); request_id_span = az_span_create((UCHAR*)context_ptr, (INT)context_length); - core_result = az_iot_hub_client_methods_response_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), - request_id_span, (USHORT)status_code, - (CHAR *)packet_ptr -> nx_packet_prepend_ptr, - topic_length, &topic_length); + core_result = az_iot_hub_client_commands_response_get_publish_topic(&(hub_client_ptr -> iot_hub_client_core), + request_id_span, (USHORT)status_code, + (CHAR *)packet_ptr -> nx_packet_prepend_ptr, + topic_length, (size_t *)&topic_length); if (az_result_failed(core_result)) { - LogError(LogLiteralArgs("Failed to create the method response topic")); + LogError(LogLiteralArgs("Failed to create the command response topic")); nx_packet_release(packet_ptr); return(NX_AZURE_IOT_SDK_CORE_ERROR); } - packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + topic_length; packet_ptr -> nx_packet_length = topic_length; @@ -2643,7 +3277,7 @@ az_result core_result; wait_option); if (status) { - LogError(LogLiteralArgs("Method reponse data append fail")); + LogError(LogLiteralArgs("Command response data append fail")); nx_packet_release(packet_ptr); return(status); } @@ -2669,7 +3303,7 @@ az_result core_result; wait_option); if (status) { - LogError(LogLiteralArgs("IoTHub client method response fail: PUBLISH FAIL status: %d"), status); + LogError(LogLiteralArgs("IoTHub client command response fail: PUBLISH FAIL status: %d"), status); nx_packet_release(packet_ptr); return(status); } @@ -2677,27 +3311,70 @@ az_result core_result; return(NX_AZURE_IOT_SUCCESS); } -static UINT nx_azure_iot_hub_client_messages_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -UINT status = NX_AZURE_IOT_SUCCESS; - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_process != NX_NULL)) + if (hub_client_ptr == NX_NULL) { - status = hub_client_ptr -> nx_azure_iot_hub_client_c2d_message.message_enable(hub_client_ptr); + LogError(LogLiteralArgs("IoTHub client direct method subscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_process != NX_NULL)) + return(nx_azure_iot_hub_client_command_enable(hub_client_ptr)); +} + +UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ + + if (hub_client_ptr == NX_NULL) { - status = hub_client_ptr -> nx_azure_iot_hub_client_direct_method_message.message_enable(hub_client_ptr); + LogError(LogLiteralArgs("IoTHub client direct method unsubscribe fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (status == NX_AZURE_IOT_SUCCESS && - (hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_process != NX_NULL)) + return(nx_azure_iot_hub_client_command_disable(hub_client_ptr)); +} + +UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR **method_name_pptr, USHORT *method_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_PACKET **packet_pptr, UINT wait_option) +{ + + if ((hub_client_ptr == NX_NULL) || + (method_name_pptr == NX_NULL) || + (method_name_length_ptr == NX_NULL) || + (context_pptr == NX_NULL) || + (context_length_ptr == NX_NULL) || + (packet_pptr == NX_NULL)) { - status = hub_client_ptr -> nx_azure_iot_hub_client_device_twin_message.message_enable(hub_client_ptr); + LogError(LogLiteralArgs("IoTHub client direct method receive fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - return(status); -} \ No newline at end of file + return(nx_azure_iot_hub_client_command_message_receive(hub_client_ptr, NX_NULL, NX_NULL, + method_name_pptr, method_name_length_ptr, + context_pptr, context_length_ptr, + packet_pptr, wait_option)); +} + +UINT nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload, + UINT payload_length, UINT wait_option) +{ + + if ((hub_client_ptr == NX_NULL) || + (hub_client_ptr -> nx_azure_iot_ptr == NX_NULL) || + (context_ptr == NX_NULL) || + (context_length == 0)) + { + LogError(LogLiteralArgs("IoTHub direct method response fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + return(nx_azure_iot_hub_client_command_message_response(hub_client_ptr, status_code, + context_ptr, context_length, + payload, payload_length, + wait_option)); +} diff --git a/addons/azure_iot/nx_azure_iot_hub_client.h b/addons/azure_iot/nx_azure_iot_hub_client.h index a510bb81..4ff16d59 100644 --- a/addons/azure_iot/nx_azure_iot_hub_client.h +++ b/addons/azure_iot/nx_azure_iot_hub_client.h @@ -27,12 +27,8 @@ extern "C" { #endif -#include "azure/iot/az_iot_hub_client.h" #include "nx_azure_iot.h" -#include "nx_api.h" -#include "nx_cloud.h" -#include "nxd_dns.h" -#include "nxd_mqtt_client.h" +#include "azure/iot/az_iot_hub_client.h" /**< Value denoting a message is of "None" type */ #define NX_AZURE_IOT_HUB_NONE 0x00000000 @@ -43,27 +39,37 @@ extern "C" { /**< Value denoting a message is a cloud-to-device message */ #define NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE 0x00000001 -/**< Value denoting a message is a direct method */ -#define NX_AZURE_IOT_HUB_DIRECT_METHOD 0x00000002 +/**< Value denoting a message is a command message */ +#define NX_AZURE_IOT_HUB_COMMAND 0x00000002 -/**< Value denoting a message is a device twin message */ -#define NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES 0x00000004 +/**< Value denoting a message is a properties message */ +#define NX_AZURE_IOT_HUB_PROPERTIES 0x00000004 -/**< Value denoting a message is a device twin desired properties message */ -#define NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES 0x00000008 +/**< Value denoting a message is a writable properties message */ +#define NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES 0x00000008 -/**< Value denoting a message is a device reported properties response */ -#define NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE 0x00000010 +/**< Value denoting a message is a reported properties response */ +#define NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE 0x00000010 + +/* Map the message type. */ +#define NX_AZURE_IOT_HUB_DIRECT_METHOD NX_AZURE_IOT_HUB_COMMAND +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES NX_AZURE_IOT_HUB_PROPERTIES +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES +#define NX_AZURE_IOT_HUB_DEVICE_TWIN_REPORTED_PROPERTIES_RESPONSE NX_AZURE_IOT_HUB_REPORTED_PROPERTIES_RESPONSE /* Set the default timeout for DNS query. */ #ifndef NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT #define NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT (5 * NX_IP_PERIODIC_RATE) #endif /* NX_AZURE_IOT_HUB_CLIENT_DNS_TIMEOUT */ -/* Set the default token expiry in secs. */ -#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY -#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY (3600) +/* Set the default timeout for connection with SAS token authentication in secs. */ +#ifndef NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT +#ifdef NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY +#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY +#else +#define NX_AZURE_IOT_HUB_CLIENT_TOKEN_CONNECTION_TIMEOUT (3600) #endif /* NX_AZURE_IOT_HUB_CLIENT_TOKEN_EXPIRY */ +#endif /* NX_AZURE_IOT_HUB_CLIENT_SAS_CONNECTION_TIMEOUT */ #ifndef NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC #define NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_IN_SEC (10 * 60) @@ -77,7 +83,7 @@ extern "C" { #define NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_JITTER_PERCENT (60) #endif /* NX_AZURE_IOT_HUB_CLIENT_MAX_BACKOFF_JITTER_PERCENT */ -/* Define AZ IoT Hub Client state. */ +/* Define Azure IoT Hub Client state. */ /**< The client is not connected */ #define NX_AZURE_IOT_HUB_CLIENT_STATUS_NOT_CONNECTED 0 @@ -92,14 +98,9 @@ extern "C" { #define NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS NX_AZURE_IOT_MQTT_QOS_1 #endif /* NX_AZURE_IOT_HUB_CLIENT_TELEMETRY_QOS */ -typedef struct NX_AZURE_IOT_THREAD_STRUCT -{ - TX_THREAD *thread_ptr; - struct NX_AZURE_IOT_THREAD_STRUCT *thread_next; - UINT thread_message_type; - UINT thread_expected_id; /* Used by device twin. */ - NX_PACKET *thread_received_message; -} NX_AZURE_IOT_THREAD; +#ifndef NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST +#define NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST (4) +#endif /* NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST */ /* Forward declration*/ struct NX_AZURE_IOT_HUB_CLIENT_STRUCT; @@ -126,9 +127,9 @@ typedef struct NX_AZURE_IOT_HUB_CLIENT_STRUCT UINT nx_azure_iot_hub_client_state; NX_AZURE_IOT_THREAD *nx_azure_iot_hub_client_thread_suspended; NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_c2d_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_device_twin_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_device_twin_desired_properties_message; - NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_direct_method_message; + NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_command_message; + NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_properties_message; + NX_AZURE_IOT_HUB_CLIENT_RECEIVE_MESSAGE nx_azure_iot_hub_client_writable_properties_message; VOID (*nx_azure_iot_hub_client_report_properties_response_callback)( struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, UINT request_id, UINT response_status, ULONG version, VOID *args); @@ -147,12 +148,22 @@ typedef struct NX_AZURE_IOT_HUB_CLIENT_STRUCT UINT nx_azure_iot_hub_client_symmetric_key_length; NX_AZURE_IOT_RESOURCE nx_azure_iot_hub_client_resource; - volatile UCHAR nx_azure_iot_hub_client_device_twin_response_subscribe_ack; + volatile UCHAR nx_azure_iot_hub_client_properties_subscribe_ack; UCHAR reserved[3]; az_iot_hub_client iot_hub_client_core; UINT nx_azure_iot_hub_client_throttle_count; ULONG nx_azure_iot_hub_client_throttle_end_time; + ULONG nx_azure_iot_hub_client_sas_token_expiry_time; + az_span nx_azure_iot_hub_client_component_list[NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST]; + UINT (*nx_azure_iot_hub_client_component_callback[NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST]) + (VOID *json_reader_ptr, + ULONG version, + VOID *args); + VOID *nx_azure_iot_hub_client_component_callback_args[NX_AZURE_IOT_HUB_CLIENT_MAX_COMPONENT_LIST]; + VOID (*nx_azure_iot_hub_client_component_properties_process)(struct NX_AZURE_IOT_HUB_CLIENT_STRUCT *hub_client_ptr, + NX_PACKET *packet_ptr, + UINT message_type); } NX_AZURE_IOT_HUB_CLIENT; @@ -200,13 +211,27 @@ UINT nx_azure_iot_hub_client_initialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT nx_azure_iot_hub_client_deinitialize(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); /** - * @brief Set the client certificate in the IoT Hub client. + * @brief Add more trusted certificate in the IoT Hub client if needed. It can be called multiple times to set multiple trusted certificates. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] trusted_certificate A pointer to a `NX_SECURE_X509_CERT`, which is the trusted certificate. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully add trusted certificate to Azure IoT Hub Instance. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to add trusted certificate to Azure IoT Hub Instance due to invalid parameter. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add trusted certificate due to NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS is too small. + */ +UINT nx_azure_iot_hub_client_trusted_cert_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate); + +/** + * @brief Set the client certificate in the IoT Hub client. It can be called multiple times to set certificate chain. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. * @param[in] device_certificate A pointer to a `NX_SECURE_X509_CERT`, which is the device certificate. * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successfully set device certificate to AZ IoT Hub Instance. - * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certificate to AZ IoT Hub Instance due to invalid parameter. + * @retval #NX_AZURE_IOT_SUCCESS Successfully set device certificate to Azure IoT Hub Instance. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certificate to Azure IoT Hub Instance due to invalid parameter. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to set device certificate due to NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS is too small. */ UINT nx_azure_iot_hub_client_device_cert_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, NX_SECURE_X509_CERT *device_certificate); @@ -225,9 +250,9 @@ UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_clie const UCHAR *symmetric_key, UINT symmetric_key_length); /** - * @brief Set Device Twin model id in the IoT Hub client. - * - * @warning THIS FUNCTION IS TEMPORARY. IT IS SUBJECT TO CHANGE OR BE REMOVED IN THE FUTURE. + * @brief Set model id in the IoT Hub client to enable PnP. + * @note To enable pnp, this routine should be called immediately after nx_azure_iot_hub_client_initialize(), + if model id is not set, only normal iothub APIs can be used, if it is set, only pnp APIs can be used. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. * @param[in] model_id_ptr A pointer to a model id. @@ -239,6 +264,36 @@ UINT nx_azure_iot_hub_client_symmetric_key_set(NX_AZURE_IOT_HUB_CLIENT *hub_clie UINT nx_azure_iot_hub_client_model_id_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, const UCHAR *model_id_ptr, UINT model_id_length); +/** + * @brief Add component name to IoT Hub client. + * @note This routine should be called for all the component in the PnP model. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] component_name_ptr A pointer to component, that is part of PnP model. + * @param[in] component_name_length Length of the `component_name_ptr`. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully add the component name to the PnP client. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add the component name due to out of memory. + */ +UINT nx_azure_iot_hub_client_component_add(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length); + +#ifdef NXD_MQTT_OVER_WEBSOCKET +/** + * @brief Enable using MQTT over WebSocket to connect to IoTHub. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if MQTT over WebSocket is enabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable C2D message receiving due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to enable C2D message receiving due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to enable C2D message receiving due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to enable C2D message receiving due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_websocket_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /** * @brief Connect to IoT Hub. * @@ -311,9 +366,9 @@ UINT nx_azure_iot_hub_client_connection_status_callback_set(NX_AZURE_IOT_HUB_CLI * callback function to `NULL` disables the callback function. Message types can be: * * - #NX_AZURE_IOT_HUB_CLOUD_TO_DEVICE_MESSAGE - * - #NX_AZURE_IOT_HUB_DIRECT_METHOD - * - #NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES - * - #NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES + * - #NX_AZURE_IOT_HUB_COMMAND / NX_AZURE_IOT_HUB_DIRECT_METHOD + * - #NX_AZURE_IOT_HUB_PROPERTIES / NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES + * - #NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES / NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. * @param[in] message_type Message type of callback function. @@ -358,6 +413,25 @@ UINT nx_azure_iot_hub_client_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *h */ UINT nx_azure_iot_hub_client_telemetry_message_delete(NX_PACKET *packet_ptr); +/** + * @brief Set component to telemetry message. + * @details This routine allows an application to set a component name to a telemetry message + * before it is being sent. The component is stored in the sequence which the routine is being called. + * + * @param[in] packet_ptr A pointer to telemetry property packet. + * @param[in] component_name_ptr A pointer to a component name. + * @param[in] component_name_length Length of `component_name_ptr`. Does not include the `NULL` terminator. + * @param[in] wait_option Ticks to wait if no packet is available. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if component is set. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set component due to invalid parameter. + * @retval NX_NO_PACKET Fail to set component due to no available packet in pool. + */ +UINT nx_azure_iot_hub_client_telemetry_component_set(NX_PACKET *packet_pptr, + const UCHAR *component_name_ptr, + USHORT component_name_length, + UINT wait_option); + /** * @brief Add property to telemetry message * @details This routine allows an application to add user-defined properties to a telemetry message @@ -469,6 +543,161 @@ UINT nx_azure_iot_hub_client_cloud_message_property_get(NX_AZURE_IOT_HUB_CLIENT USHORT property_name_length, const UCHAR **property_value, USHORT *property_value_length); +/** + * @brief Enables receiving direct method messages from IoTHub + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @return + * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message receiving is enabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable direct method message receiving due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to enable direct method message receiving due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to enable direct method message receiving due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to enable direct method message receiving due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Disables receiving direct method messages from IoTHub + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message receiving is disabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to disable direct method message receiving due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to disable direct method message receiving due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to disable direct method message receiving due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to disable direct method message receiving due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Receives direct method message from IoTHub + * @details This routine receives direct method message from IoT Hub. If there are no + * messages in the receive queue, this routine can block. The amount of time it waits for a + * message is determined by the `wait_option` parameter. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[out] method_name_pptr Return a pointer to method name on success. + * @param[out] method_name_length_ptr Return length of `method_name_pptr` on success. + * @param[out] context_pptr Return a pointer to the context pointer on success. + * @param[out] context_length_ptr Return length of `context` on success. + * @param[out] packet_pptr Return `NX_PACKET` containing the method payload on success. Caller owns the `NX_PACKET` memory. + * @param[in] wait_option Ticks to wait for message to arrive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive direct method message due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive direct method message due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive direct method message due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive direct method message due to invalid packet. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive direct method message due to SDK core error. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive direct method message due to disconnect. + */ +UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR **method_name_pptr, USHORT *method_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_PACKET **packet_pptr, UINT wait_option); + +/** + * @brief Return response to direct method message from IoTHub + * @details This routine returns response to the direct method message from IoT Hub. + * @note request_id ties the correlation between direct method receive and response. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] status_code Status code for direct method. + * @param[in] context_ptr Pointer to context return from nx_azure_iot_hub_client_direct_method_message_receive(). + * @param[in] context_length Length of context. + * @param[in] payload Pointer to `UCHAR` containing the payload for the direct method response. Payload is in JSON format. + * @param[in] payload_length Length of `payload` + * @param[in] wait_option Ticks to wait for message to send. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method response is send. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send direct method response due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send direct method response due to SDK core error. + * @retval NX_NO_PACKET Fail send direct method response due to no available packet in pool. + */ +UINT nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload, + UINT payload_length, UINT wait_option); + +/** + * @brief Enables receiving command messages from IoTHub + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @return + * @retval #NX_AZURE_IOT_SUCCESS Successful if command message receiving is enabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable command message receiving due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to enable command message receiving due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to enable command message receiving due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to enable command message receiving due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_command_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Disables receiving command messages from IoTHub + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if command message receiving is disabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to disable command message receiving due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to disable command message receiving due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to disable command message receiving due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to disable command message receiving due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_command_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Receives PnP command message from IoTHub + * @details This routine receives command message from IoT Hub. If there are no + * messages in the receive queue, this routine can block. The amount of time it waits for a + * message is determined by the `wait_option` parameter. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[out] component_name_pptr Return a pointer to PnP component name on success. + * @param[out] component_name_length_ptr Return length of `*component_name_pptr` on success. + * @param[out] command_name_pptr Return a pointer to command name on success. + * @param[out] command_name_length_ptr Return length of `command_name_pptr` on success. + * @param[out] context_pptr Return a pointer to the context pointer on success. + * @param[out] context_length_ptr Return length of `context` on success. + * @param[out] packet_pptr Return `NX_PACKET` containing the command payload on success. Caller owns the `NX_PACKET` memory. + * @param[in] wait_option Ticks to wait for message to arrive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if command message is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive command message due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive command message due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive command message due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive command message due to invalid packet. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive command message due to SDK core error. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive command message due to disconnect. + */ +UINT nx_azure_iot_hub_client_command_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + const UCHAR **component_name_pptr, USHORT *component_name_length_ptr, + const UCHAR **command_name_pptr, USHORT *command_name_length_ptr, + VOID **context_pptr, USHORT *context_length_ptr, + NX_PACKET **packet_pptr, UINT wait_option); + +/** + * @brief Return response to PnP command message from IoTHub + * @details This routine returns response to the command message from IoT Hub. + * @note request_id ties the correlation between command receive and response. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] status_code Status code for command. + * @param[in] context_ptr Pointer to context return from nx_azure_iot_hub_client_command_message_receive(). + * @param[in] context_length Length of context. + * @param[in] payload Pointer to `UCHAR` containing the payload for the command response. Payload is in JSON format. + * @param[in] payload_length Length of `payload` + * @param[in] wait_option Ticks to wait for message to send. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if command response is send. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send command response due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send command response due to SDK core error. + * @retval NX_NO_PACKET Fail send command response due to no available packet in pool. + */ +UINT nx_azure_iot_hub_client_command_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT status_code, VOID *context_ptr, + USHORT context_length, const UCHAR *payload, + UINT payload_length, UINT wait_option); + /** * @brief Enables device twin feature * @details This routine enables device twin feature. @@ -511,14 +740,17 @@ UINT nx_azure_iot_hub_client_device_twin_disable(NX_AZURE_IOT_HUB_CLIENT *hub_cl * @retval #NX_AZURE_IOT_SUCCESS Successful if callback function is set. * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set callback due to invalid parameter. */ -UINT nx_azure_iot_hub_client_report_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - VOID (*callback_ptr)( - NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT request_id, - UINT response_status, - ULONG version, - VOID *args), - VOID *callback_args); +UINT nx_azure_iot_hub_client_reported_properties_response_callback_set(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + VOID (*callback_ptr)( + NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT request_id, + UINT response_status, + ULONG version, + VOID *args), + VOID *callback_args); + +/* Map old API to new API. */ +#define nx_azure_iot_hub_client_report_properties_response_callback_set nx_azure_iot_hub_client_reported_properties_response_callback_set /** * @brief Send device twin reported properties to IoT Hub @@ -603,80 +835,133 @@ UINT nx_azure_iot_hub_client_device_twin_desired_properties_receive(NX_AZURE_IOT NX_PACKET **packet_pptr, UINT wait_option); /** - * @brief Enables receiving direct method messages from IoTHub + * @brief Enables properties feature + * @details This routine enables property feature. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if property feature is enabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable property feature due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to enable property feature due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to enable property feature due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to enable property feature due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_properties_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Disables properties feature + * @details This routine disables property feature. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if property feature is disabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to disable property feature due to invalid parameter. + * @retval NXD_MQTT_NOT_CONNECTED Fail to disable property feature due to MQTT not connected. + * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to disable property feature due to no available packet in pool. + * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to disable property feature due to TCP/TLS error. + */ +UINT nx_azure_iot_hub_client_properties_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +/** + * @brief Creates reported properties message. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. - * @return - * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message receiving is enabled. - * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable direct method message receiving due to invalid parameter. - * @retval NXD_MQTT_NOT_CONNECTED Fail to enable direct method message receiving due to MQTT not connected. - * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to enable direct method message receiving due to no available packet in pool. - * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to enable direct method message receiving due to TCP/TLS error. + * @param[out] packet_pptr Return `NX_PACKET` containing the reported properties payload on success. + * @param[in] wait_option Ticks to wait for writer creation + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if a message writer is created. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to create message writer due to invalid parameter. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to create message writer due to SDK core error. + * @retval NX_NO_PACKET Fail to create message writer due to no available packet in pool. */ -UINT nx_azure_iot_hub_client_direct_method_enable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +UINT nx_azure_iot_hub_client_reported_properties_create(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); /** - * @brief Disables receiving direct method messages from IoTHub + * @brief Sends reported properties message to IoTHub. + * @note The return status of the API indicates if the reported properties is sent out successfully or not, + * the response status is used to track if the reported properties is accepted or not by IoT Hub, and the + * reponse status is available only when the return status is NX_AZURE_IOT_SUCCESS. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] packet_ptr A pointer to a #NX_PACKET + * @param[out] request_id_ptr Request Id assigned to the request. + * @param[out] response_status_ptr Status return for successful send of reported properties. + * @param[out] version_ptr Version return for successful send of reported properties. + * @param[in] wait_option Ticks to wait for message to send. * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message receiving is disabled. - * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to disable direct method message receiving due to invalid parameter. - * @retval NXD_MQTT_NOT_CONNECTED Fail to disable direct method message receiving due to MQTT not connected. - * @retval NXD_MQTT_PACKET_POOL_FAILURE Fail to disable direct method message receiving due to no available packet in pool. - * @retval NXD_MQTT_COMMUNICATION_FAILURE Fail to disable direct method message receiving due to TCP/TLS error. + * @retval #NX_AZURE_IOT_SUCCESS Successful if reported properties is sent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send reported properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to send reported properties due to property is not enabled. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send reported properties due to SDK core error. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to send reported properties due to buffer size is too small. + * @retval NX_NO_PACKET Fail to send reported properties due to no packet available. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to send reported properties due to disconnect. */ -UINT nx_azure_iot_hub_client_direct_method_disable(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +UINT nx_azure_iot_hub_client_reported_properties_send(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, + UINT *request_id_ptr, UINT *response_status_ptr, + ULONG *version_ptr, UINT wait_option); /** - * @brief Receives direct method message from IoTHub - * @details This routine receives direct method message from IoT Hub. If there are no - * messages in the receive queue, this routine can block. The amount of time it waits for a - * message is determined by the `wait_option` parameter. + * @brief Request complete properties + * @details This routine requests complete properties. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. - * @param[out] method_name_pptr Return a pointer to method name on success. - * @param[out] method_name_length_ptr Return length of `method_name_pptr` on success. - * @param[out] context_pptr Return a pointer to the context pointer on success. - * @param[out] context_length_ptr Return length of `context` on success. - * @param[out] packet_pptr Return `NX_PACKET` containing the method payload on success. Caller owns the `NX_PACKET` memory. - * @param[in] wait_option Ticks to wait for message to arrive. + * @param[in] wait_option Ticks to wait for request to send. * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method message is received. - * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive direct method message due to invalid parameter. - * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive direct method message due to it is not enabled. - * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive direct method message due to timeout. - * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive direct method message due to invalid packet. - * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive direct method message due to SDK core error. - * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive direct method message due to disconnect. + * @retval #NX_AZURE_IOT_SUCCESS Successful if request get all properties is sent. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to request get all properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NO_SUBSCRIBE_ACK Fail to request get all properties due to no subscribe ack. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to request get all properties due to SDK core error. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to request get all properties due to buffer size is too small. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to request get all properties due to no packet available. + * @retval NX_NO_PACKET Fail to request get all properties due to no packet available. */ -UINT nx_azure_iot_hub_client_direct_method_message_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - const UCHAR **method_name_pptr, USHORT *method_name_length_ptr, - VOID **context_pptr, USHORT *context_length_ptr, - NX_PACKET **packet_pptr, UINT wait_option); +UINT nx_azure_iot_hub_client_properties_request(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + UINT wait_option); /** - * @brief Return response to direct method message from IoTHub - * @details This routine returns response to the direct method message from IoT Hub. - * @note request_id ties the correlation between direct method receive and response. + * @brief Receive all the properties + * @details This routine receives all the properties. * * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. - * @param[in] status_code Status code for direct method. - * @param[in] context_ptr Pointer to context return from nx_azure_iot_hub_client_direct_method_message_receive(). - * @param[in] context_length Length of context. - * @param[in] payload Pointer to `UCHAR` containing the payload for the direct method response. Payload is in JSON format. - * @param[in] payload_length Length of `payload` - * @param[in] wait_option Ticks to wait for message to send. + * @param[out] packet_pptr Return `NX_PACKET` containing properties payload on success. + * @param[in] wait_option Ticks to wait for message to receive. * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if direct method response is send. - * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to send direct method response due to invalid parameter. - * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to send direct method response due to SDK core error. - * @retval NX_NO_PACKET Fail send direct method response due to no available packet in pool. + * @retval #NX_AZURE_IOT_SUCCESS Successful if all properties is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive all properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive all properties due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive all properties due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive all properties due to invalid packet. + * @retval #NX_AZURE_IOT_SDK_CORE_ERROR Fail to receive all properties due to SDK core error. + * @retval #NX_AZURE_IOT_SERVER_RESPONSE_ERROR Response code from server is not 2xx. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive all properties due to disconnect. */ -UINT nx_azure_iot_hub_client_direct_method_message_response(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, - UINT status_code, VOID *context_ptr, - USHORT context_length, const UCHAR *payload, - UINT payload_length, UINT wait_option); +UINT nx_azure_iot_hub_client_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); + +/** + * @brief Receive writable properties form IoTHub + * @details This routine receives writable properties from IoTHub. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[out] packet_pptr A pointer to a #NX_PACKET containing writable properties on success. + * @param[in] wait_option Ticks to wait for message to receive. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if writable properties is received. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to receive writable properties due to invalid parameter. + * @retval #NX_AZURE_IOT_NOT_ENABLED Fail to receive writable properties due to it is not enabled. + * @retval #NX_AZURE_IOT_NO_PACKET Fail to receive writable properties due to timeout. + * @retval #NX_AZURE_IOT_INVALID_PACKET Fail to receive writable properties due to invalid packet. + * @retval #NX_AZURE_IOT_DISCONNECTED Fail to receive writable properties due to disconnect. + */ +UINT nx_azure_iot_hub_client_writable_properties_receive(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET **packet_pptr, + UINT wait_option); + #ifdef __cplusplus } #endif diff --git a/addons/azure_iot/nx_azure_iot_hub_client_properties.c b/addons/azure_iot/nx_azure_iot_hub_client_properties.c new file mode 100644 index 00000000..cd1740aa --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_hub_client_properties.c @@ -0,0 +1,381 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 */ + +#include "nx_azure_iot_hub_client_properties.h" + +extern UINT nx_azure_iot_hub_client_adjust_payload(NX_PACKET *packet_ptr); +VOID nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, UINT message_type); + +UINT nx_azure_iot_hub_client_reported_properties_component_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length) +{ +az_result core_result; +az_span component_name; + + if ((hub_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL) || + (component_name_ptr == NX_NULL) || + (component_name_length == 0)) + { + LogError(LogLiteralArgs("IoT PnP reported property begin fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + component_name = az_span_create((UCHAR *)component_name_ptr, (INT)component_name_length); + + core_result = az_iot_hub_client_properties_writer_begin_component(&(hub_client_ptr -> iot_hub_client_core), + &(writer_ptr -> json_writer), component_name); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_reported_properties_component_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr) +{ +az_result core_result; + + if ((hub_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP reported property end fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_result = az_iot_hub_client_properties_writer_end_component(&(hub_client_ptr -> iot_hub_client_core), + &(writer_ptr -> json_writer)); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoT PnP failed to append component, core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_reported_properties_status_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *property_name_ptr, UINT property_name_length, + UINT status_code, ULONG version, + const UCHAR *description_ptr, UINT description_length) +{ +az_span property_name; +az_span description; +az_result core_result; + + if ((hub_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL) || + (property_name_ptr == NX_NULL) || + (property_name_length == 0) ) + { + LogError(LogLiteralArgs("IoT PnP client begin reported status failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + property_name = az_span_create((UCHAR *)property_name_ptr, (INT)property_name_length); + description = az_span_create((UCHAR *)description_ptr, (INT)description_length); + + core_result = az_iot_hub_client_properties_writer_begin_response_status(&(hub_client_ptr -> iot_hub_client_core), + &(writer_ptr -> json_writer), + property_name, (int32_t)status_code, + (int32_t)version, description); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to prefix data with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_reported_properties_status_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr) +{ +az_result core_result; + + if ((hub_client_ptr == NX_NULL) || + (writer_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoT PnP client end reported status failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_result = az_iot_hub_client_properties_writer_end_response_status(&(hub_client_ptr -> iot_hub_client_core), + &(writer_ptr -> json_writer)); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to suffix data with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +UINT nx_azure_iot_hub_client_properties_version_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, ULONG *version_ptr) +{ +az_result core_result; +az_iot_hub_client_properties_message_type core_message_type; + + if ((hub_client_ptr == NX_NULL) || + (reader_ptr == NX_NULL) || + (version_ptr == NX_NULL) || + ((message_type != NX_AZURE_IOT_HUB_PROPERTIES) && + (message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES))) + { + LogError(LogLiteralArgs("IoTHub client get properties version failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + core_message_type = (message_type == NX_AZURE_IOT_HUB_PROPERTIES) ? AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE : + AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED; + + core_result = az_iot_hub_client_properties_get_properties_version(&(hub_client_ptr -> iot_hub_client_core), + &(reader_ptr -> json_reader), + core_message_type, + (int32_t *)version_ptr); + if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("IoTHub client get properties version failed : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + +static UINT nx_azure_iot_hub_client_properties_component_property_next_get_internal(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, UINT property_type, + const UCHAR **component_name_pptr, + USHORT *component_name_length_ptr, + UINT *component_index, + UINT parse_system_component) +{ +az_span component_name; +az_iot_hub_client_properties_message_type core_message_type; +az_iot_hub_client_property_type core_property_type; +az_result core_result; +UINT index; +UINT system_component; + + if (((message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES) && + (message_type != NX_AZURE_IOT_HUB_PROPERTIES)) || + ((property_type != NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) && + (property_type != NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE)) || + ((property_type == NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) && + (message_type != NX_AZURE_IOT_HUB_PROPERTIES))) + { + LogError(LogLiteralArgs("Invalid response type or property type passed")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + component_name = az_span_create((UCHAR *)*component_name_pptr, (INT)*component_name_length_ptr); + core_message_type = (message_type == NX_AZURE_IOT_HUB_PROPERTIES) ? AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_GET_RESPONSE : + AZ_IOT_HUB_CLIENT_PROPERTIES_MESSAGE_TYPE_WRITABLE_UPDATED; + core_property_type = (property_type == NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE) ? AZ_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE : + AZ_IOT_HUB_CLIENT_PROPERTY_WRITABLE; + + do + { + core_result = az_iot_hub_client_properties_get_next_component_property(&(hub_client_ptr -> iot_hub_client_core), + &(reader_ptr -> json_reader), + core_message_type, core_property_type, + &component_name); + if (core_result == AZ_ERROR_IOT_END_OF_PROPERTIES) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + else if (az_result_failed(core_result)) + { + LogError(LogLiteralArgs("Failed to parse document with core error : %d"), core_result); + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + *component_name_pptr = az_span_ptr(component_name); + *component_name_length_ptr = (USHORT)az_span_size(component_name); + + /* Check if it is system component. */ + system_component = NX_FALSE; + for (index = 0; index < (UINT)hub_client_ptr -> iot_hub_client_core._internal.options.component_names_length; index++) + { + if ((az_span_is_content_equal(component_name, hub_client_ptr -> nx_azure_iot_hub_client_component_list[index]))&& + (hub_client_ptr -> nx_azure_iot_hub_client_component_callback[index] != NX_NULL)) + { + system_component = NX_TRUE; + break; + } + } + + /* System component. */ + if ((parse_system_component == NX_TRUE) && (system_component == NX_TRUE)) + { + *component_index = index; + return(NX_AZURE_IOT_SUCCESS); + } + else if ((parse_system_component == NX_FALSE) && (system_component == NX_FALSE)) + { + return(NX_AZURE_IOT_SUCCESS); + } + + /* Skip it and find the next one. */ + nx_azure_iot_json_reader_next_token(reader_ptr); + + /* Skip children in case the property value is an object. */ + if (nx_azure_iot_json_reader_token_type(reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + nx_azure_iot_json_reader_skip_children(reader_ptr); + } + nx_azure_iot_json_reader_next_token(reader_ptr); + + } while(1); +} + +UINT nx_azure_iot_hub_client_properties_component_property_next_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, UINT property_type, + const UCHAR **component_name_pptr, + USHORT *component_name_length_ptr) +{ + +UINT status; + + if ((hub_client_ptr == NX_NULL) || + (reader_ptr == NX_NULL) || + (component_name_pptr == NX_NULL) || + (component_name_length_ptr == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub client component next property failed: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + status = nx_azure_iot_hub_client_properties_component_property_next_get_internal(hub_client_ptr, reader_ptr, + message_type, property_type, + component_name_pptr, component_name_length_ptr, + NX_NULL, NX_FALSE); + + return(status); +} + +VOID nx_azure_iot_hub_client_properties_component_process(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_PACKET *packet_ptr, UINT message_type) +{ + +UINT status; +ULONG version; +NX_AZURE_IOT_JSON_READER reader_ptr; +const UCHAR *component_name_ptr = NX_NULL; +USHORT component_name_length = 0; +UINT component_index; +UCHAR *prepend_ptr = NX_NULL; + + + /* Check the message type. */ + if ((message_type != NX_AZURE_IOT_HUB_PROPERTIES) && + (message_type != NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES)) + { + return; + } + + /* Record the prepend pointer. */ + prepend_ptr = packet_ptr -> nx_packet_prepend_ptr; + + if (nx_azure_iot_hub_client_adjust_payload(packet_ptr)) + { + return; + } + + if (nx_azure_iot_json_reader_init(&reader_ptr, packet_ptr)) + { + + /* Recover the prepend pointer since other functions will retreive the topic again. */ + packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr); + packet_ptr -> nx_packet_prepend_ptr = prepend_ptr; + return; + } + + /* Get the version. */ + status = nx_azure_iot_hub_client_properties_version_get(hub_client_ptr, &reader_ptr, + message_type, &version); + if (status) + { + + /* Recover the prepend pointer since other functions will retreive the topic again. */ + packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr); + packet_ptr -> nx_packet_prepend_ptr = prepend_ptr; + return; + } + + /* Re-initialize the JSON reader state */ + if (nx_azure_iot_json_reader_init(&reader_ptr, packet_ptr)) + { + + /* Recover the prepend pointer since other functions will retreive the topic again. */ + packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr); + packet_ptr -> nx_packet_prepend_ptr = prepend_ptr; + return; + } + + /* Loop to process system component. */ + while (nx_azure_iot_hub_client_properties_component_property_next_get_internal(hub_client_ptr, + &reader_ptr, message_type, + NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE, + &component_name_ptr, &component_name_length, + &component_index, NX_TRUE) == NX_AZURE_IOT_SUCCESS) + { + + /* Check if it is system component. */ + if ((component_name_ptr) && (component_name_length) && + (hub_client_ptr -> nx_azure_iot_hub_client_component_callback[component_index])) + { + status = hub_client_ptr -> nx_azure_iot_hub_client_component_callback[component_index](&reader_ptr, version, + hub_client_ptr -> nx_azure_iot_hub_client_component_callback_args[component_index]); + if (status) + { + + /* Recover the prepend pointer since other functions will retreive the topic again. */ + packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr); + packet_ptr -> nx_packet_prepend_ptr = prepend_ptr; + return; + } + + } + else + { + + /* The JSON reader must be advanced regardless of whether the property + is of interest or not. */ + nx_azure_iot_json_reader_next_token(&reader_ptr); + + /* Skip children in case the property value is an object. */ + if (nx_azure_iot_json_reader_token_type(&reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + nx_azure_iot_json_reader_skip_children(&reader_ptr); + } + nx_azure_iot_json_reader_next_token(&reader_ptr); + } + } + + /* Recover the prepend pointer since other functions will retreive the topic again. */ + packet_ptr -> nx_packet_length += (ULONG)(packet_ptr -> nx_packet_prepend_ptr - prepend_ptr); + packet_ptr -> nx_packet_prepend_ptr = prepend_ptr; + + return; +} diff --git a/addons/azure_iot/nx_azure_iot_hub_client_properties.h b/addons/azure_iot/nx_azure_iot_hub_client_properties.h new file mode 100644 index 00000000..91d0ffd9 --- /dev/null +++ b/addons/azure_iot/nx_azure_iot_hub_client_properties.h @@ -0,0 +1,266 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/* Version: 6.1 */ + +/** + * @file nx_azure_iot_hub_client.h + * + * @brief Definition for the Azure IoT Hub client. + * @remark The IoT Hub MQTT protocol is described at + * https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-mqtt-support. + * + */ + +#ifndef NX_AZURE_IOT_HUB_CLIENT_PROPERTIES_H +#define NX_AZURE_IOT_HUB_CLIENT_PROPERTIES_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "azure/iot/az_iot_hub_client_properties.h" +#include "nx_azure_iot_hub_client.h" +#include "nx_azure_iot_json_reader.h" +#include "nx_azure_iot_json_writer.h" + +/* Property type. */ +#define NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE 0 +#define NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE 1 + +/** + * @brief Append the necessary characters to a reported property JSON payload belonging to a + * subcomponent. + * + * The payload will be of the form: + * + * @code + * "reported": { + * "": { + * "__t": "c", + * "temperature": 23 + * } + * } + * @endcode + * + * @note This API should be used in conjunction with + * nx_azure_iot_hub_client_reported_properties_component_end(). + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[in] component_name_ptr A pointer to a component name + * @param[in] component_name_length Length of `component_name_ptr` + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if JSON payload was prefixed successfully. + */ +UINT nx_azure_iot_hub_client_reported_properties_component_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *component_name_ptr, + USHORT component_name_length); + +/** + * @brief Append the necessary characters to end a reported property JSON payload belonging to a + * subcomponent. + * + * @note This API should be used in conjunction with + * nx_azure_iot_hub_client_reported_properties_component_begin(). + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS The JSON payload was suffixed successfully. + */ +UINT nx_azure_iot_hub_client_reported_properties_component_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); + +/** + * @brief Begin a property response payload with confirmation status. + * + * This API should be used in response to an incoming writable property. More details can be found + * here: + * + * https://docs.microsoft.com/en-us/azure/iot-pnp/concepts-convention#writable-properties + * + * The payload will be of the form: + * + * **Without component** + * @code + * //{ + * // "":{ + * // "ac": , + * // "av": , + * // "ad": "", + * // "value": + * // } + * //} + * @endcode + * + * To send a status for a property belonging to a component, first call the + * nx_azure_iot_hub_client_reported_property_status_begin() API to prefix the payload with the + * necessary identification. The API call flow would look like the following with the listed JSON + * payload being generated. + * + * **With component** + * @code + * + * nx_azure_iot_hub_client_reported_properties_component_begin() + * nx_azure_iot_hub_client_reported_properties_status_begin() + * // Append user value here () + * nx_azure_iot_hub_client_reported_properties_status_end() + * nx_azure_iot_hub_client_reported_properties_component_end() + * + * //{ + * // "": { + * // "__t": "c", + * // "": { + * // "ac": , + * // "av": , + * // "ad": "", + * // "value": + * // } + * // } + * //} + * @endcode + * + * @note This API should be used in conjunction with + * nx_azure_iot_hub_client_reported_properties_status_end(). + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * @param[in] property_name_ptr A pointer to property name. + * @param[in] property_name_length Length of `property_name_ptr`. + * @param[in] status_code The HTTP-like status code to respond with. + * @param[in] version The version of the property the application is acknowledging. + * This can be retrieved from the service request by calling nx_azure_iot_hub_client_properties_version_get. + * @param[in] description_ptr An optional pointer to description detailing the context or any details about + * the acknowledgement. This can be empty string. + * @param[in] description_length Length of description_ptr + * + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful appended JSON prefix. + */ +UINT nx_azure_iot_hub_client_reported_properties_status_begin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr, + const UCHAR *property_name_ptr, UINT property_name_length, + UINT status_code, ULONG version, + const UCHAR *description_ptr, UINT description_length); + +/** + * @brief End a property response payload with confirmation status. + * + * @note This API should be used in conjunction with + * nx_azure_iot_hub_client_reported_properties_status_begin(). + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] writer_ptr A pointer to a #NX_AZURE_IOT_JSON_WRITER + * + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful appended JSON suffix. + */ +UINT nx_azure_iot_hub_client_reported_properties_status_end(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_WRITER *writer_ptr); + + +/** + * @brief Get the property version. the next writable property in the property document passed. + * + * @warning This modifies the state of the json reader. To then use the same json reader + * with nx_azure_iot_hub_client_properties_component_property_next_get(), you must call + * nx_azure_iot_json_reader_init() again after this call and before the call to + * nx_azure_iot_hub_client_properties_component_property_next_get() or make an additional copy before + * calling this API. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing properties document + * @param[in] message_type Type of message repsonse, only valid value are NX_AZURE_IOT_HUB_PROPERTIES or NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES + * @param[out] version_ptr The numeric version of the properties in JSON payload + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if next writable property is found. + */ +UINT nx_azure_iot_hub_client_properties_version_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, ULONG *version_ptr); + +/** + * @brief Iteratively read the Azure IoT Plug and Play component properties. + * + * Note that between calls, the UCHAR* pointed to by \p component_name_pptr shall not be modified, + * only checked and compared. Internally, the pointer is only changed if the component name changes + * in the JSON document and is not necessarily set every invocation of the function. + * + * On success, the `reader_ptr` will be set on a valid property name. After checking the + * property name, the reader can be advanced to the property value by calling + * nx_azure_iot_json_reader_next_token(). Note that on the subsequent call to this API, it is expected that + * the json reader will be placed AFTER the read property name and value. That means that after + * reading the property value (including single values or complex objects), the user must call + * nx_azure_iot_json_reader_next_token(). + * + * Below is a code snippet which you can use as a starting point: + * + * @code + * + * while ((status = nx_azure_iot_hub_client_properties_component_property_next_get(&iothub_client, + * &json_reader, + * message_type, + * NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE, + * &component_name_ptr, &component_length)) == NX_AZURE_IOT_SUCCESS) + * { + * + * // Check if property is of interest (substitute user_property for your own property name) + * if (nx_azure_iot_json_reader_token_is_text_equal(&json_reader, user_property, user_property_length)) + * { + * nx_azure_iot_json_reader_next_token(&json_reader); + * + * // Get the property value here + * // Example: nx_azure_iot_json_reader_token_int32_get(&json_reader, &user_int); + * + * // Skip to next property value + * nx_azure_iot_json_reader_next_token(&json_reader); + * } + * else + * { + * // The JSON reader must be advanced regardless of whether the property + * // is of interest or not. + * nx_azure_iot_json_reader_next_token(&json_reader); + * + * // Skip children in case the property value is an object + * nx_azure_iot_json_reader_skip_children(&json_reader); + * nx_azure_iot_json_reader_next_token(&json_reader); + * } + * } + * + * @endcode + * + * @warning If you need to retrieve more than one \p property_type, you should first complete the + * scan of all components for the first property type (until the API returns + * NX_AZURE_IOT_NOT_FOUND). Then you must call nx_azure_iot_json_reader_init() again after this call + * and before the next call to `nx_azure_iot_hub_client_properties_component_property_next_get` with the + * different \p property_type. + * + * @param[in] hub_client_ptr A pointer to a #NX_AZURE_IOT_HUB_CLIENT. + * @param[in] reader_ptr A pointer to a #NX_AZURE_IOT_JSON_READER containing properties document + * @param[in] message_type Type of message repsonse, only valid value are NX_AZURE_IOT_HUB_PROPERTIES or NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES + * @param[in] property_type Type of property, only valid value are NX_AZURE_IOT_HUB_CLIENT_PROPERTY_REPORTED_FROM_DEVICE or NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE + * @param[out] component_name_pptr A pointer to component name for the property returned using reader_ptr + * @param[out] component_name_length_ptr Length of the component name + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if next writable property is found. + */ +UINT nx_azure_iot_hub_client_properties_component_property_next_get(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT message_type, UINT property_type, + const UCHAR **component_name_pptr, + USHORT *component_name_length_ptr); + +#ifdef __cplusplus +} +#endif +#endif /* NX_AZURE_IOT_HUB_CLIENT_PROPERTIES_H */ diff --git a/addons/azure_iot/nx_azure_iot_json_reader.c b/addons/azure_iot/nx_azure_iot_json_reader.c index cd480db3..031bb97f 100644 --- a/addons/azure_iot/nx_azure_iot_json_reader.c +++ b/addons/azure_iot/nx_azure_iot_json_reader.c @@ -15,19 +15,50 @@ #include "nx_azure_iot.h" +static UINT nx_azure_iot_json_reader_translate_error_code(NX_AZURE_IOT_JSON_READER *reader_ptr, + az_result core_result) +{ + if (az_result_failed(core_result)) + { + if (core_result == AZ_ERROR_JSON_READER_DONE) + { + return(NX_AZURE_IOT_NOT_FOUND); + } + + if (reader_ptr -> json_length == 0) + { + return(NX_AZURE_IOT_EMPTY_JSON); + } + + return(NX_AZURE_IOT_SDK_CORE_ERROR); + } + + return(NX_AZURE_IOT_SUCCESS); +} + UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr, const UCHAR *buffer_ptr, UINT buffer_len) { az_span span = az_span_create((UCHAR *)buffer_ptr, (INT)buffer_len); if ((reader_ptr == NX_NULL) || - (buffer_ptr == NX_NULL) || (buffer_len == 0)) + (buffer_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } memset(reader_ptr, 0, sizeof(NX_AZURE_IOT_JSON_READER)); + /* Allow initializing with zero size buffer, as any futher call will fail for empty JSON */ + if (buffer_len == 0) + { + reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE; + + return(NX_AZURE_IOT_SUCCESS); + } + + reader_ptr -> json_length = (ULONG)buffer_len; + if (az_result_failed(az_json_reader_init(&(reader_ptr -> json_reader), span, NX_NULL))) { @@ -43,8 +74,7 @@ UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr, UINT count = 0; if ((reader_ptr == NX_NULL) || - (packet_ptr == NX_NULL) || - (packet_ptr -> nx_packet_length == 0)) + (packet_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } @@ -53,6 +83,16 @@ UINT count = 0; reader_ptr -> packet_ptr = packet_ptr; + /* Allow initializing with zero size packet, as any futher call will fail for empty JSON */ + if (packet_ptr -> nx_packet_length == 0) + { + reader_ptr -> json_reader.token.kind = AZ_JSON_TOKEN_NONE; + + return(NX_AZURE_IOT_SUCCESS); + } + + reader_ptr -> json_length = packet_ptr -> nx_packet_length; + while (packet_ptr != NX_NULL) { if (count >= NX_AZURE_IOT_READER_MAX_LIST) @@ -87,7 +127,6 @@ UINT nx_azure_iot_json_reader_deinit(NX_AZURE_IOT_JSON_READER *reader_ptr) if (reader_ptr -> packet_ptr) { - nx_packet_release(reader_ptr -> packet_ptr); reader_ptr -> packet_ptr = NX_NULL; } @@ -110,43 +149,61 @@ az_span span = az_span_create(value_ptr, (INT)value_len); UINT nx_azure_iot_json_reader_next_token(NX_AZURE_IOT_JSON_READER *reader_ptr) { +az_result core_result; + if ((reader_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (az_result_failed(az_json_reader_next_token(&(reader_ptr -> json_reader)))) + core_result = az_json_reader_next_token(&(reader_ptr -> json_reader)); + + return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result)); +} + +UINT nx_azure_iot_json_reader_skip_children(NX_AZURE_IOT_JSON_READER *reader_ptr) +{ +az_result core_result; + + if ((reader_ptr == NX_NULL)) { - return(NX_AZURE_IOT_SDK_CORE_ERROR); + return(NX_AZURE_IOT_INVALID_PARAMETER); } - return(NX_AZURE_IOT_SUCCESS); + core_result = az_json_reader_skip_children(&(reader_ptr -> json_reader)); + + return(nx_azure_iot_json_reader_translate_error_code(reader_ptr, core_result)); } -UINT nx_azure_iot_json_reader_skip_children(NX_AZURE_IOT_JSON_READER *reader_ptr) +UINT nx_azure_iot_json_reader_token_bool_get(NX_AZURE_IOT_JSON_READER *reader_ptr, + UINT *value_ptr) { - if ((reader_ptr == NX_NULL)) +bool bool_value; + + if ((reader_ptr == NX_NULL) || (value_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (az_result_failed(az_json_reader_skip_children(&(reader_ptr -> json_reader)))) + if (az_result_failed(az_json_token_get_boolean(&(reader_ptr -> json_reader.token), &bool_value))) { return(NX_AZURE_IOT_SDK_CORE_ERROR); } + *value_ptr = bool_value; + return(NX_AZURE_IOT_SUCCESS); } -UINT nx_azure_iot_json_reader_token_bool_get(NX_AZURE_IOT_JSON_READER *reader_ptr, - UINT *value_ptr) +UINT nx_azure_iot_json_reader_token_uint32_get(NX_AZURE_IOT_JSON_READER *reader_ptr, + uint32_t *value_ptr) { if ((reader_ptr == NX_NULL) || (value_ptr == NX_NULL)) { return(NX_AZURE_IOT_INVALID_PARAMETER); } - if (az_result_failed(az_json_token_get_boolean(&(reader_ptr -> json_reader.token), (bool *)value_ptr))) + if (az_result_failed(az_json_token_get_uint32(&(reader_ptr -> json_reader.token), value_ptr))) { return(NX_AZURE_IOT_SDK_CORE_ERROR); } diff --git a/addons/azure_iot/nx_azure_iot_json_reader.h b/addons/azure_iot/nx_azure_iot_json_reader.h index 7fefa51d..62157de9 100644 --- a/addons/azure_iot/nx_azure_iot_json_reader.h +++ b/addons/azure_iot/nx_azure_iot_json_reader.h @@ -54,6 +54,7 @@ typedef struct NX_AZURE_IOT_READER_STRUCT NX_PACKET *packet_ptr; az_json_reader json_reader; az_span span_list[NX_AZURE_IOT_READER_MAX_LIST]; + ULONG json_length; } NX_AZURE_IOT_JSON_READER; /** @@ -68,7 +69,6 @@ typedef struct NX_AZURE_IOT_READER_STRUCT * @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully. * @retval other Initialization failed. * - * @remarks The provided json buffer must not be empty, as that is invalid JSON. */ UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ptr, const UCHAR *buffer_ptr, UINT buffer_len); @@ -83,8 +83,6 @@ UINT nx_azure_iot_json_reader_with_buffer_init(NX_AZURE_IOT_JSON_READER *reader_ * @retval #NX_AZURE_IOT_SUCCESS The #NX_AZURE_IOT_JSON_READER is initialized successfully. * @retval other Initialization failed. * - * @remarks The provided json buffer must not be empty, as that is invalid JSON. - * * @remarks Ownership of #NX_PACKET is taken by the reader. */ UINT nx_azure_iot_json_reader_init(NX_AZURE_IOT_JSON_READER *reader_ptr, @@ -138,6 +136,18 @@ UINT nx_azure_iot_json_reader_skip_children(NX_AZURE_IOT_JSON_READER *reader_ptr UINT nx_azure_iot_json_reader_token_bool_get(NX_AZURE_IOT_JSON_READER *reader_ptr, UINT *value_ptr); +/** + * @brief Gets the JSON token's number as a 32-bit unsigned integer. + * + * @param[in] reader_ptr A pointer to an #NX_AZURE_IOT_JSON_READER instance. + * @param[out] value_ptr A pointer to a variable to receive the value. + * + * @return An `UINT` value indicating the result of the operation. + * @retval #NX_AZURE_IOT_SUCCESS The number is returned. + */ +UINT nx_azure_iot_json_reader_token_uint32_get(NX_AZURE_IOT_JSON_READER *reader_ptr, + uint32_t *value_ptr); + /** * @brief Gets the JSON token's number as a 32-bit signed integer. * diff --git a/addons/azure_iot/nx_azure_iot_json_writer.c b/addons/azure_iot/nx_azure_iot_json_writer.c index eb4e3c43..4c18b339 100644 --- a/addons/azure_iot/nx_azure_iot_json_writer.c +++ b/addons/azure_iot/nx_azure_iot_json_writer.c @@ -72,6 +72,8 @@ NX_PACKET *tail_packet_ptr; static VOID nx_azure_iot_json_writer_packet_update(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr) { NX_PACKET *tail_packet_ptr; +UINT last_chunk_size = + (UINT)az_span_size(az_json_writer_get_bytes_used_in_destination(&(json_writer_ptr -> json_writer))); if (json_writer_ptr -> packet_ptr == NX_NULL) { @@ -88,14 +90,12 @@ NX_PACKET *tail_packet_ptr; } NX_ASSERT((tail_packet_ptr -> nx_packet_data_start + json_writer_ptr -> nx_tail_packet_offset + - (UINT)json_writer_ptr -> json_writer._internal.bytes_written) <= - tail_packet_ptr -> nx_packet_data_end); + last_chunk_size) <= tail_packet_ptr -> nx_packet_data_end); tail_packet_ptr -> nx_packet_append_ptr = - tail_packet_ptr -> nx_packet_data_start + json_writer_ptr -> nx_tail_packet_offset + - (UINT)json_writer_ptr -> json_writer._internal.bytes_written; + tail_packet_ptr -> nx_packet_data_start + json_writer_ptr -> nx_tail_packet_offset + last_chunk_size; json_writer_ptr -> packet_ptr -> nx_packet_length = - json_writer_ptr -> nx_packet_init_length + (UINT)json_writer_ptr -> json_writer._internal.total_bytes_written; + json_writer_ptr -> nx_packet_init_length + (UINT)json_writer_ptr -> json_writer.total_bytes_written; } UINT nx_azure_iot_json_writer_init(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, @@ -177,7 +177,6 @@ UINT nx_azure_iot_json_writer_deinit(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr) if (json_writer_ptr -> packet_ptr) { - nx_packet_release(json_writer_ptr -> packet_ptr); json_writer_ptr -> packet_ptr = NX_NULL; } @@ -192,7 +191,7 @@ UINT nx_azure_iot_json_writer_get_bytes_used(NX_AZURE_IOT_JSON_WRITER *json_writ return(NX_AZURE_IOT_INVALID_PARAMETER); } - return((UINT)json_writer_ptr -> json_writer._internal.total_bytes_written); + return((UINT)json_writer_ptr -> json_writer.total_bytes_written); } UINT nx_azure_iot_json_writer_append_string(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, @@ -344,8 +343,6 @@ UINT nx_azure_iot_json_writer_append_begin_object(NX_AZURE_IOT_JSON_WRITER *json return(NX_AZURE_IOT_SDK_CORE_ERROR); } - json_writer_ptr -> object_depth++; - nx_azure_iot_json_writer_packet_update(json_writer_ptr); return(NX_AZURE_IOT_SUCCESS); @@ -382,8 +379,6 @@ UINT nx_azure_iot_json_writer_append_end_object(NX_AZURE_IOT_JSON_WRITER *json_w return(NX_AZURE_IOT_SDK_CORE_ERROR); } - json_writer_ptr -> object_depth--; - nx_azure_iot_json_writer_packet_update(json_writer_ptr); return(NX_AZURE_IOT_SUCCESS); diff --git a/addons/azure_iot/nx_azure_iot_json_writer.h b/addons/azure_iot/nx_azure_iot_json_writer.h index e40b999f..6a6a3622 100644 --- a/addons/azure_iot/nx_azure_iot_json_writer.h +++ b/addons/azure_iot/nx_azure_iot_json_writer.h @@ -38,7 +38,6 @@ typedef struct NX_AZURE_IOT_JSON_WRITER_STRUCT { NX_PACKET *packet_ptr; az_json_writer json_writer; - UINT object_depth; UINT wait_option; ULONG nx_tail_packet_offset; ULONG nx_packet_init_length; diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.c b/addons/azure_iot/nx_azure_iot_provisioning_client.c index 78a4d014..9cc94f97 100644 --- a/addons/azure_iot/nx_azure_iot_provisioning_client.c +++ b/addons/azure_iot/nx_azure_iot_provisioning_client.c @@ -33,10 +33,7 @@ #define NX_AZURE_IOT_PROVISIONING_CLIENT_PAYLOAD_END "}" #define NX_AZURE_IOT_PROVISIONING_CLIENT_POLICY_NAME "registration" -/* Set the default timeout for connecting on cloud thread. */ -#ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT -#define NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT (20 * NX_IP_PERIODIC_RATE) -#endif /* NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT */ +#define NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH "/$iothub/websocket" /* Set the default retry to Provisioning service. */ #ifndef NX_AZURE_IOT_PROVISIONING_CLIENT_DEFAULT_RETRY @@ -97,7 +94,7 @@ UINT status; &response -> register_response); if (az_result_failed(core_result)) { - LogError(LogLiteralArgs("IoTProvisioning client failed to parse packet, error status: "), core_result); + LogError(LogLiteralArgs("IoTProvisioning client failed to parse packet, error status: %d"), core_result); return(NX_AZURE_IOT_SDK_CORE_ERROR); } @@ -139,6 +136,7 @@ UINT status; NXD_ADDRESS server_address; NXD_MQTT_CLIENT *mqtt_client_ptr; NX_AZURE_IOT_RESOURCE *resource_ptr; +UINT server_port; /* Resolve the host name. */ status = nxd_dns_host_by_name_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_dns_ptr, @@ -166,8 +164,21 @@ NX_AZURE_IOT_RESOURCE *resource_ptr; return(status); } +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (mqtt_client_ptr -> nxd_mqtt_client_use_websocket == NX_TRUE) + { + server_port = NXD_MQTT_OVER_WEBSOCKET_TLS_PORT; + } + else + { + server_port = NXD_MQTT_TLS_PORT; + } +#else + server_port = NXD_MQTT_TLS_PORT; +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Start MQTT connection. */ - status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, NXD_MQTT_TLS_PORT, + status = nxd_mqtt_client_secure_connect(mqtt_client_ptr, &server_address, server_port, nx_azure_iot_mqtt_tls_setup, NX_AZURE_IOT_MQTT_KEEP_ALIVE, NX_FALSE, wait_option); @@ -465,7 +476,7 @@ UINT status; { /* Start new operation. */ - status = nx_azure_iot_provisioning_client_send_req(context, NULL, NX_AZURE_IOT_PROVISIONING_CLIENT_CONNECT_TIMEOUT); + status = nx_azure_iot_provisioning_client_send_req(context, NULL, NX_NO_WAIT); } if (status) @@ -627,7 +638,7 @@ az_result core_result; buffer_size = (UINT)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr); status = nx_azure_iot_mqtt_packet_id_get(&(prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_mqtt), - packet_id, wait_option); + packet_id); if (status) { LogError(LogLiteralArgs("failed to get packetId ")); @@ -635,16 +646,20 @@ az_result core_result; return(status); } - if (register_response == NULL) + /* if no registration response or operation Id is missing, send new registration request. */ + if ((register_response == NULL) || + (az_span_size(register_response -> operation_id) == 0)) { core_result = az_iot_provisioning_client_register_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), - (CHAR *)buffer_ptr, buffer_size, &mqtt_topic_length); + (CHAR *)buffer_ptr, buffer_size, + (size_t *)&mqtt_topic_length); } else { core_result = az_iot_provisioning_client_query_status_get_publish_topic(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), register_response -> operation_id, (CHAR *)buffer_ptr, - buffer_size, &mqtt_topic_length); + buffer_size, + (size_t *)&mqtt_topic_length); } if (az_result_failed(core_result)) @@ -772,7 +787,7 @@ az_span policy_name = AZ_SPAN_LITERAL_FROM_STR(NX_AZURE_IOT_PROVISIONING_CLIENT_ buffer_span, expiry_time_secs, policy_name, (CHAR *)resource_ptr -> resource_mqtt_sas_token, prov_client_ptr -> nx_azure_iot_provisioning_client_sas_token_buff_size, - &(resource_ptr -> resource_mqtt_sas_token_length)); + (size_t *)&(resource_ptr -> resource_mqtt_sas_token_length)); if (az_result_failed(core_result)) { LogError(LogLiteralArgs("IoTProvisioning failed to generate token with error : %d"), core_result); @@ -837,7 +852,7 @@ az_span registration_id_span = az_span_create((UCHAR *)registration_id, (INT)reg prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_cipher_map_size = cipher_map_size; prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_metadata_ptr = metadata_memory; prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_metadata_size = memory_size; - prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_trusted_certificate = trusted_certificate; + prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_trusted_certificates[0] = trusted_certificate; prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_hostname = endpoint; prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_hostname_length = endpoint_length; resource_ptr -> resource_mqtt_client_id_length = prov_client_ptr -> nx_azure_iot_provisioning_client_registration_id_length; @@ -892,7 +907,8 @@ az_span registration_id_span = az_span_create((UCHAR *)registration_id, (INT)reg /* Build user name. */ if (az_result_failed(az_iot_provisioning_client_get_user_name(&(prov_client_ptr -> nx_azure_iot_provisioning_client_core), - (CHAR *)buffer_ptr, buffer_size, &mqtt_user_name_length))) + (CHAR *)buffer_ptr, buffer_size, + (size_t *)&mqtt_user_name_length))) { LogError(LogLiteralArgs("IoTProvisioning client connect fail: NX_AZURE_IOT_Provisioning_CLIENT_USERNAME_SIZE is too small.")); nx_azure_iot_buffer_free(buffer_context); @@ -1009,9 +1025,54 @@ UINT status; return(NX_AZURE_IOT_SUCCESS); } +UINT nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate) +{ +UINT i; +NX_AZURE_IOT_RESOURCE *resource_ptr; + + if ((prov_client_ptr == NX_NULL) || + (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) || + (trusted_certificate == NX_NULL)) + { + LogError(LogLiteralArgs("IoTHub device certificate set fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Obtain the mutex. */ + tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, TX_WAIT_FOREVER); + + resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource); + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates); i++) + { + if (resource_ptr -> resource_trusted_certificates[i] == NX_NULL) + { + resource_ptr -> resource_trusted_certificates[i] = trusted_certificate; + break; + } + } + + /* Release the mutex. */ + tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); + + if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_trusted_certificates)) + { + return(NX_AZURE_IOT_SUCCESS); + } + else + { + + /* No more space to store trusted certificate. */ + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } +} + UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, NX_SECURE_X509_CERT *x509_cert) { +UINT i; +NX_AZURE_IOT_RESOURCE *resource_ptr; + if ((prov_client_ptr == NX_NULL) || (prov_client_ptr -> nx_azure_iot_ptr == NX_NULL) || (x509_cert == NX_NULL)) { LogError(LogLiteralArgs("IoTProvisioning device cert set fail: INVALID POINTER")); @@ -1021,14 +1082,49 @@ UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_ /* Obtain the mutex. */ tx_mutex_get(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr, NX_WAIT_FOREVER); - prov_client_ptr -> nx_azure_iot_provisioning_client_resource.resource_device_certificate = x509_cert; + resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource); + for (i = 0; i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates); i++) + { + if (resource_ptr -> resource_device_certificates[i] == NX_NULL) + { + resource_ptr -> resource_device_certificates[i] = x509_cert; + break; + } + } /* Release the mutex. */ tx_mutex_put(prov_client_ptr -> nx_azure_iot_ptr -> nx_azure_iot_mutex_ptr); - return(NX_AZURE_IOT_SUCCESS); + if (i < NX_AZURE_IOT_ARRAY_SIZE(resource_ptr -> resource_device_certificates)) + { + return(NX_AZURE_IOT_SUCCESS); + } + else + { + + /* No more space to store device certificate. */ + return(NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE); + } } +#ifdef NXD_MQTT_OVER_WEBSOCKET +UINT nx_azure_iot_provisioning_client_websocket_enable(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr) +{ +NX_AZURE_IOT_RESOURCE *resource_ptr; + + if (prov_client_ptr == NX_NULL) + { + LogError(LogLiteralArgs("IoTProvisioning client WebSocket enable fail: INVALID POINTER")); + return(NX_AZURE_IOT_INVALID_PARAMETER); + } + + /* Set resource pointer. */ + resource_ptr = &(prov_client_ptr -> nx_azure_iot_provisioning_client_resource); + + return(nxd_mqtt_client_websocket_set(&(resource_ptr -> resource_mqtt), (UCHAR *)resource_ptr -> resource_hostname, resource_ptr -> resource_hostname_length, + (UCHAR *)NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH, sizeof(NX_AZURE_IOT_PROVISIONING_CLIENT_WEB_SOCKET_PATH) - 1)); +} +#endif /* NXD_MQTT_OVER_WEBSOCKET */ static VOID nx_azure_iot_provisioning_client_event_process(NX_AZURE_IOT *nx_azure_iot_ptr, ULONG common_events, ULONG module_own_events) diff --git a/addons/azure_iot/nx_azure_iot_provisioning_client.h b/addons/azure_iot/nx_azure_iot_provisioning_client.h index cba71332..01d88dbc 100644 --- a/addons/azure_iot/nx_azure_iot_provisioning_client.h +++ b/addons/azure_iot/nx_azure_iot_provisioning_client.h @@ -159,15 +159,29 @@ UINT nx_azure_iot_provisioning_client_initialize(NX_AZURE_IOT_PROVISIONING_CLIEN */ UINT nx_azure_iot_provisioning_client_deinitialize(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr); +/** + * @brief Add more trusted certificate in the IoT Provisioning client if needed. It can be called multiple times to set certificate chain. + * + * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT. + * @param[in] trusted_certificate A pointer to a `NX_SECURE_X509_CERT`, which is the trusted certificate. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successfully add trusted certificate to AZ IoT Provisioning Client Instance. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to add trusted certificate to AZ IoT Provisioning Client Instance due to invalid parameter. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to add trusted certificate due to NX_AZURE_IOT_MAX_NUM_OF_TRUSTED_CERTS is too small. + */ +UINT nx_azure_iot_provisioning_client_trusted_cert_add(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, + NX_SECURE_X509_CERT *trusted_certificate); + /** * @brief Set client certificate. - * @details This routine sets the device certificate. + * @details This routine sets the device certificate. It can be called multiple times to set certificate chain. * * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT. * @param[in] x509_cert A pointer to a `NX_SECURE_X509_CERT` client cert. * @return A `UINT` with the result of the API. * @retval #NX_AZURE_IOT_SUCCESS Successfully set device certs to AZ IoT Provisioning Client Instance. * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to set device certs to AZ IoT Provisioning Client Instance due to invalid parameter. + * @retval #NX_AZURE_IOT_INSUFFICIENT_BUFFER_SPACE Fail to set device certificate due to NX_AZURE_IOT_MAX_NUM_OF_DEVICE_CERTS is too small. */ UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, NX_SECURE_X509_CERT *x509_cert); @@ -186,6 +200,18 @@ UINT nx_azure_iot_provisioning_client_device_cert_set(NX_AZURE_IOT_PROVISIONING_ UINT nx_azure_iot_provisioning_client_symmetric_key_set(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, const UCHAR *symmetric_key, UINT symmetric_key_length); +#ifdef NXD_MQTT_OVER_WEBSOCKET +/** + * @brief Enable using MQTT over WebSocket to register device to Azure IoT Provisioning service. + * + * @param[in] prov_client_ptr A pointer to a #NX_AZURE_IOT_PROVISIONING_CLIENT. + * @return A `UINT` with the result of the API. + * @retval #NX_AZURE_IOT_SUCCESS Successful if MQTT over WebSocket is enabled. + * @retval #NX_AZURE_IOT_INVALID_PARAMETER Fail to enable MQTT over WebSocket due to invalid parameter. + */ +UINT nx_azure_iot_provisioning_client_websocket_enable(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr); +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /** * @brief Register device to Azure IoT Provisioning service. * @details This routine registers device to Azure IoT Provisioning service. diff --git a/addons/azure_iot/samples/cert/nx_azure_iot_cert.c b/addons/azure_iot/samples/cert/nx_azure_iot_cert.c index 30341b4a..cde72833 100644 --- a/addons/azure_iot/samples/cert/nx_azure_iot_cert.c +++ b/addons/azure_iot/samples/cert/nx_azure_iot_cert.c @@ -72,5 +72,169 @@ const unsigned char _nx_azure_iot_root_cert[] = { 0x47, 0xd2, 0x38, 0x2e, 0xd0, 0xfe, 0x81, 0xdc, 0x32, 0x6a, 0x1e, 0xb5, 0xee, 0x3c, 0xd5, 0xfc, 0xe7, 0x81, 0x1d, 0x19, 0xc3, 0x24, 0x42, 0xea, 0x63, 0x39, 0xa9 }; - const unsigned int _nx_azure_iot_root_cert_size = sizeof(_nx_azure_iot_root_cert); + +/* Azure IoT Hub and DPS will migrate to the Digicert Global Root G2. + To continue without disruption due to this changes, Microsoft recommends that + client applications or devices trust the Digicert Global Root G2. */ + +/* Digicert Global Root G2 */ +const unsigned char _nx_azure_iot_root_cert_2[] = { + 0x30, 0x82, 0x03, 0x8e, 0x30, 0x82, 0x02, 0x76, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x03, + 0x3a, 0xf1, 0xe6, 0xa7, 0x11, 0xa9, 0xa0, 0xbb, 0x28, 0x64, 0xb1, 0x1d, 0x09, 0xfa, 0xe5, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x61, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x15, 0x30, + 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, 0x72, 0x74, + 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x10, 0x77, + 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, 0x6f, 0x6d, 0x31, + 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, 0x69, 0x43, 0x65, + 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x47, + 0x32, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x38, 0x30, 0x31, 0x31, 0x32, 0x30, 0x30, 0x30, + 0x30, 0x5a, 0x17, 0x0d, 0x33, 0x38, 0x30, 0x31, 0x31, 0x35, 0x31, 0x32, 0x30, 0x30, 0x30, 0x30, + 0x5a, 0x30, 0x61, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, + 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0c, 0x44, 0x69, 0x67, 0x69, 0x43, + 0x65, 0x72, 0x74, 0x20, 0x49, 0x6e, 0x63, 0x31, 0x19, 0x30, 0x17, 0x06, 0x03, 0x55, 0x04, 0x0b, + 0x13, 0x10, 0x77, 0x77, 0x77, 0x2e, 0x64, 0x69, 0x67, 0x69, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x63, + 0x6f, 0x6d, 0x31, 0x20, 0x30, 0x1e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x17, 0x44, 0x69, 0x67, + 0x69, 0x43, 0x65, 0x72, 0x74, 0x20, 0x47, 0x6c, 0x6f, 0x62, 0x61, 0x6c, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x20, 0x47, 0x32, 0x30, 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, + 0x02, 0x82, 0x01, 0x01, 0x00, 0xbb, 0x37, 0xcd, 0x34, 0xdc, 0x7b, 0x6b, 0xc9, 0xb2, 0x68, 0x90, + 0xad, 0x4a, 0x75, 0xff, 0x46, 0xba, 0x21, 0x0a, 0x08, 0x8d, 0xf5, 0x19, 0x54, 0xc9, 0xfb, 0x88, + 0xdb, 0xf3, 0xae, 0xf2, 0x3a, 0x89, 0x91, 0x3c, 0x7a, 0xe6, 0xab, 0x06, 0x1a, 0x6b, 0xcf, 0xac, + 0x2d, 0xe8, 0x5e, 0x09, 0x24, 0x44, 0xba, 0x62, 0x9a, 0x7e, 0xd6, 0xa3, 0xa8, 0x7e, 0xe0, 0x54, + 0x75, 0x20, 0x05, 0xac, 0x50, 0xb7, 0x9c, 0x63, 0x1a, 0x6c, 0x30, 0xdc, 0xda, 0x1f, 0x19, 0xb1, + 0xd7, 0x1e, 0xde, 0xfd, 0xd7, 0xe0, 0xcb, 0x94, 0x83, 0x37, 0xae, 0xec, 0x1f, 0x43, 0x4e, 0xdd, + 0x7b, 0x2c, 0xd2, 0xbd, 0x2e, 0xa5, 0x2f, 0xe4, 0xa9, 0xb8, 0xad, 0x3a, 0xd4, 0x99, 0xa4, 0xb6, + 0x25, 0xe9, 0x9b, 0x6b, 0x00, 0x60, 0x92, 0x60, 0xff, 0x4f, 0x21, 0x49, 0x18, 0xf7, 0x67, 0x90, + 0xab, 0x61, 0x06, 0x9c, 0x8f, 0xf2, 0xba, 0xe9, 0xb4, 0xe9, 0x92, 0x32, 0x6b, 0xb5, 0xf3, 0x57, + 0xe8, 0x5d, 0x1b, 0xcd, 0x8c, 0x1d, 0xab, 0x95, 0x04, 0x95, 0x49, 0xf3, 0x35, 0x2d, 0x96, 0xe3, + 0x49, 0x6d, 0xdd, 0x77, 0xe3, 0xfb, 0x49, 0x4b, 0xb4, 0xac, 0x55, 0x07, 0xa9, 0x8f, 0x95, 0xb3, + 0xb4, 0x23, 0xbb, 0x4c, 0x6d, 0x45, 0xf0, 0xf6, 0xa9, 0xb2, 0x95, 0x30, 0xb4, 0xfd, 0x4c, 0x55, + 0x8c, 0x27, 0x4a, 0x57, 0x14, 0x7c, 0x82, 0x9d, 0xcd, 0x73, 0x92, 0xd3, 0x16, 0x4a, 0x06, 0x0c, + 0x8c, 0x50, 0xd1, 0x8f, 0x1e, 0x09, 0xbe, 0x17, 0xa1, 0xe6, 0x21, 0xca, 0xfd, 0x83, 0xe5, 0x10, + 0xbc, 0x83, 0xa5, 0x0a, 0xc4, 0x67, 0x28, 0xf6, 0x73, 0x14, 0x14, 0x3d, 0x46, 0x76, 0xc3, 0x87, + 0x14, 0x89, 0x21, 0x34, 0x4d, 0xaf, 0x0f, 0x45, 0x0c, 0xa6, 0x49, 0xa1, 0xba, 0xbb, 0x9c, 0xc5, + 0xb1, 0x33, 0x83, 0x29, 0x85, 0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x42, 0x30, 0x40, 0x30, 0x0f, + 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, + 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, + 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x4e, 0x22, 0x54, 0x20, 0x18, 0x95, + 0xe6, 0xe3, 0x6e, 0xe6, 0x0f, 0xfa, 0xfa, 0xb9, 0x12, 0xed, 0x06, 0x17, 0x8f, 0x39, 0x30, 0x0d, + 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03, 0x82, 0x01, + 0x01, 0x00, 0x60, 0x67, 0x28, 0x94, 0x6f, 0x0e, 0x48, 0x63, 0xeb, 0x31, 0xdd, 0xea, 0x67, 0x18, + 0xd5, 0x89, 0x7d, 0x3c, 0xc5, 0x8b, 0x4a, 0x7f, 0xe9, 0xbe, 0xdb, 0x2b, 0x17, 0xdf, 0xb0, 0x5f, + 0x73, 0x77, 0x2a, 0x32, 0x13, 0x39, 0x81, 0x67, 0x42, 0x84, 0x23, 0xf2, 0x45, 0x67, 0x35, 0xec, + 0x88, 0xbf, 0xf8, 0x8f, 0xb0, 0x61, 0x0c, 0x34, 0xa4, 0xae, 0x20, 0x4c, 0x84, 0xc6, 0xdb, 0xf8, + 0x35, 0xe1, 0x76, 0xd9, 0xdf, 0xa6, 0x42, 0xbb, 0xc7, 0x44, 0x08, 0x86, 0x7f, 0x36, 0x74, 0x24, + 0x5a, 0xda, 0x6c, 0x0d, 0x14, 0x59, 0x35, 0xbd, 0xf2, 0x49, 0xdd, 0xb6, 0x1f, 0xc9, 0xb3, 0x0d, + 0x47, 0x2a, 0x3d, 0x99, 0x2f, 0xbb, 0x5c, 0xbb, 0xb5, 0xd4, 0x20, 0xe1, 0x99, 0x5f, 0x53, 0x46, + 0x15, 0xdb, 0x68, 0x9b, 0xf0, 0xf3, 0x30, 0xd5, 0x3e, 0x31, 0xe2, 0x8d, 0x84, 0x9e, 0xe3, 0x8a, + 0xda, 0xda, 0x96, 0x3e, 0x35, 0x13, 0xa5, 0x5f, 0xf0, 0xf9, 0x70, 0x50, 0x70, 0x47, 0x41, 0x11, + 0x57, 0x19, 0x4e, 0xc0, 0x8f, 0xae, 0x06, 0xc4, 0x95, 0x13, 0x17, 0x2f, 0x1b, 0x25, 0x9f, 0x75, + 0xf2, 0xb1, 0x8e, 0x99, 0xa1, 0x6f, 0x13, 0xb1, 0x41, 0x71, 0xfe, 0x88, 0x2a, 0xc8, 0x4f, 0x10, + 0x20, 0x55, 0xd7, 0xf3, 0x14, 0x45, 0xe5, 0xe0, 0x44, 0xf4, 0xea, 0x87, 0x95, 0x32, 0x93, 0x0e, + 0xfe, 0x53, 0x46, 0xfa, 0x2c, 0x9d, 0xff, 0x8b, 0x22, 0xb9, 0x4b, 0xd9, 0x09, 0x45, 0xa4, 0xde, + 0xa4, 0xb8, 0x9a, 0x58, 0xdd, 0x1b, 0x7d, 0x52, 0x9f, 0x8e, 0x59, 0x43, 0x88, 0x81, 0xa4, 0x9e, + 0x26, 0xd5, 0x6f, 0xad, 0xdd, 0x0d, 0xc6, 0x37, 0x7d, 0xed, 0x03, 0x92, 0x1b, 0xe5, 0x77, 0x5f, + 0x76, 0xee, 0x3c, 0x8d, 0xc4, 0x5d, 0x56, 0x5b, 0xa2, 0xd9, 0x66, 0x6e, 0xb3, 0x35, 0x37, 0xe5, + 0x32, 0xb6 +}; +const unsigned int _nx_azure_iot_root_cert_size_2 = sizeof(_nx_azure_iot_root_cert_2); + +/* To prevent future disruption, client applications or devices should also add the following root. */ + +/* Microsoft RSA Root Certificate Authority 2017 */ +const unsigned char _nx_azure_iot_root_cert_3[] = { + 0x30, 0x82, 0x05, 0xa8, 0x30, 0x82, 0x03, 0x90, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0x1e, + 0xd3, 0x97, 0x09, 0x5f, 0xd8, 0xb4, 0xb3, 0x47, 0x70, 0x1e, 0xaa, 0xbe, 0x7f, 0x45, 0xb3, 0x30, + 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x30, 0x65, + 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, + 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, + 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, + 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6f, 0x6f, 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, + 0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x39, 0x31, 0x32, 0x31, 0x38, 0x32, + 0x32, 0x35, 0x31, 0x32, 0x32, 0x5a, 0x17, 0x0d, 0x34, 0x32, 0x30, 0x37, 0x31, 0x38, 0x32, 0x33, + 0x30, 0x30, 0x32, 0x33, 0x5a, 0x30, 0x65, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, + 0x13, 0x02, 0x55, 0x53, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x15, 0x4d, + 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x43, 0x6f, 0x72, 0x70, 0x6f, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x31, 0x36, 0x30, 0x34, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x2d, 0x4d, + 0x69, 0x63, 0x72, 0x6f, 0x73, 0x6f, 0x66, 0x74, 0x20, 0x52, 0x53, 0x41, 0x20, 0x52, 0x6f, 0x6f, + 0x74, 0x20, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x20, 0x32, 0x30, 0x31, 0x37, 0x30, 0x82, 0x02, 0x22, + 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + 0x82, 0x02, 0x0f, 0x00, 0x30, 0x82, 0x02, 0x0a, 0x02, 0x82, 0x02, 0x01, 0x00, 0xca, 0x5b, 0xbe, + 0x94, 0x33, 0x8c, 0x29, 0x95, 0x91, 0x16, 0x0a, 0x95, 0xbd, 0x47, 0x62, 0xc1, 0x89, 0xf3, 0x99, + 0x36, 0xdf, 0x46, 0x90, 0xc9, 0xa5, 0xed, 0x78, 0x6a, 0x6f, 0x47, 0x91, 0x68, 0xf8, 0x27, 0x67, + 0x50, 0x33, 0x1d, 0xa1, 0xa6, 0xfb, 0xe0, 0xe5, 0x43, 0xa3, 0x84, 0x02, 0x57, 0x01, 0x5d, 0x9c, + 0x48, 0x40, 0x82, 0x53, 0x10, 0xbc, 0xbf, 0xc7, 0x3b, 0x68, 0x90, 0xb6, 0x82, 0x2d, 0xe5, 0xf4, + 0x65, 0xd0, 0xcc, 0x6d, 0x19, 0xcc, 0x95, 0xf9, 0x7b, 0xac, 0x4a, 0x94, 0xad, 0x0e, 0xde, 0x4b, + 0x43, 0x1d, 0x87, 0x07, 0x92, 0x13, 0x90, 0x80, 0x83, 0x64, 0x35, 0x39, 0x04, 0xfc, 0xe5, 0xe9, + 0x6c, 0xb3, 0xb6, 0x1f, 0x50, 0x94, 0x38, 0x65, 0x50, 0x5c, 0x17, 0x46, 0xb9, 0xb6, 0x85, 0xb5, + 0x1c, 0xb5, 0x17, 0xe8, 0xd6, 0x45, 0x9d, 0xd8, 0xb2, 0x26, 0xb0, 0xca, 0xc4, 0x70, 0x4a, 0xae, + 0x60, 0xa4, 0xdd, 0xb3, 0xd9, 0xec, 0xfc, 0x3b, 0xd5, 0x57, 0x72, 0xbc, 0x3f, 0xc8, 0xc9, 0xb2, + 0xde, 0x4b, 0x6b, 0xf8, 0x23, 0x6c, 0x03, 0xc0, 0x05, 0xbd, 0x95, 0xc7, 0xcd, 0x73, 0x3b, 0x66, + 0x80, 0x64, 0xe3, 0x1a, 0xac, 0x2e, 0xf9, 0x47, 0x05, 0xf2, 0x06, 0xb6, 0x9b, 0x73, 0xf5, 0x78, + 0x33, 0x5b, 0xc7, 0xa1, 0xfb, 0x27, 0x2a, 0xa1, 0xb4, 0x9a, 0x91, 0x8c, 0x91, 0xd3, 0x3a, 0x82, + 0x3e, 0x76, 0x40, 0xb4, 0xcd, 0x52, 0x61, 0x51, 0x70, 0x28, 0x3f, 0xc5, 0xc5, 0x5a, 0xf2, 0xc9, + 0x8c, 0x49, 0xbb, 0x14, 0x5b, 0x4d, 0xc8, 0xff, 0x67, 0x4d, 0x4c, 0x12, 0x96, 0xad, 0xf5, 0xfe, + 0x78, 0xa8, 0x97, 0x87, 0xd7, 0xfd, 0x5e, 0x20, 0x80, 0xdc, 0xa1, 0x4b, 0x22, 0xfb, 0xd4, 0x89, + 0xad, 0xba, 0xce, 0x47, 0x97, 0x47, 0x55, 0x7b, 0x8f, 0x45, 0xc8, 0x67, 0x28, 0x84, 0x95, 0x1c, + 0x68, 0x30, 0xef, 0xef, 0x49, 0xe0, 0x35, 0x7b, 0x64, 0xe7, 0x98, 0xb0, 0x94, 0xda, 0x4d, 0x85, + 0x3b, 0x3e, 0x55, 0xc4, 0x28, 0xaf, 0x57, 0xf3, 0x9e, 0x13, 0xdb, 0x46, 0x27, 0x9f, 0x1e, 0xa2, + 0x5e, 0x44, 0x83, 0xa4, 0xa5, 0xca, 0xd5, 0x13, 0xb3, 0x4b, 0x3f, 0xc4, 0xe3, 0xc2, 0xe6, 0x86, + 0x61, 0xa4, 0x52, 0x30, 0xb9, 0x7a, 0x20, 0x4f, 0x6f, 0x0f, 0x38, 0x53, 0xcb, 0x33, 0x0c, 0x13, + 0x2b, 0x8f, 0xd6, 0x9a, 0xbd, 0x2a, 0xc8, 0x2d, 0xb1, 0x1c, 0x7d, 0x4b, 0x51, 0xca, 0x47, 0xd1, + 0x48, 0x27, 0x72, 0x5d, 0x87, 0xeb, 0xd5, 0x45, 0xe6, 0x48, 0x65, 0x9d, 0xaf, 0x52, 0x90, 0xba, + 0x5b, 0xa2, 0x18, 0x65, 0x57, 0x12, 0x9f, 0x68, 0xb9, 0xd4, 0x15, 0x6b, 0x94, 0xc4, 0x69, 0x22, + 0x98, 0xf4, 0x33, 0xe0, 0xed, 0xf9, 0x51, 0x8e, 0x41, 0x50, 0xc9, 0x34, 0x4f, 0x76, 0x90, 0xac, + 0xfc, 0x38, 0xc1, 0xd8, 0xe1, 0x7b, 0xb9, 0xe3, 0xe3, 0x94, 0xe1, 0x46, 0x69, 0xcb, 0x0e, 0x0a, + 0x50, 0x6b, 0x13, 0xba, 0xac, 0x0f, 0x37, 0x5a, 0xb7, 0x12, 0xb5, 0x90, 0x81, 0x1e, 0x56, 0xae, + 0x57, 0x22, 0x86, 0xd9, 0xc9, 0xd2, 0xd1, 0xd7, 0x51, 0xe3, 0xab, 0x3b, 0xc6, 0x55, 0xfd, 0x1e, + 0x0e, 0xd3, 0x74, 0x0a, 0xd1, 0xda, 0xaa, 0xea, 0x69, 0xb8, 0x97, 0x28, 0x8f, 0x48, 0xc4, 0x07, + 0xf8, 0x52, 0x43, 0x3a, 0xf4, 0xca, 0x55, 0x35, 0x2c, 0xb0, 0xa6, 0x6a, 0xc0, 0x9c, 0xf9, 0xf2, + 0x81, 0xe1, 0x12, 0x6a, 0xc0, 0x45, 0xd9, 0x67, 0xb3, 0xce, 0xff, 0x23, 0xa2, 0x89, 0x0a, 0x54, + 0xd4, 0x14, 0xb9, 0x2a, 0xa8, 0xd7, 0xec, 0xf9, 0xab, 0xcd, 0x25, 0x58, 0x32, 0x79, 0x8f, 0x90, + 0x5b, 0x98, 0x39, 0xc4, 0x08, 0x06, 0xc1, 0xac, 0x7f, 0x0e, 0x3d, 0x00, 0xa5, 0x02, 0x03, 0x01, + 0x00, 0x01, 0xa3, 0x54, 0x30, 0x52, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x01, 0x01, 0xff, + 0x04, 0x04, 0x03, 0x02, 0x01, 0x86, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, + 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, + 0x04, 0x14, 0x09, 0xcb, 0x59, 0x7f, 0x86, 0xb2, 0x70, 0x8f, 0x1a, 0xc3, 0x39, 0xe3, 0xc0, 0xd9, + 0xe9, 0xbf, 0xbb, 0x4d, 0xb2, 0x23, 0x30, 0x10, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0x82, + 0x37, 0x15, 0x01, 0x04, 0x03, 0x02, 0x01, 0x00, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, + 0xf7, 0x0d, 0x01, 0x01, 0x0c, 0x05, 0x00, 0x03, 0x82, 0x02, 0x01, 0x00, 0xac, 0xaf, 0x3e, 0x5d, + 0xc2, 0x11, 0x96, 0x89, 0x8e, 0xa3, 0xe7, 0x92, 0xd6, 0x97, 0x15, 0xb8, 0x13, 0xa2, 0xa6, 0x42, + 0x2e, 0x02, 0xcd, 0x16, 0x05, 0x59, 0x27, 0xca, 0x20, 0xe8, 0xba, 0xb8, 0xe8, 0x1a, 0xec, 0x4d, + 0xa8, 0x97, 0x56, 0xae, 0x65, 0x43, 0xb1, 0x8f, 0x00, 0x9b, 0x52, 0xcd, 0x55, 0xcd, 0x53, 0x39, + 0x6d, 0x62, 0x4c, 0x8b, 0x0d, 0x5b, 0x7c, 0x2e, 0x44, 0xbf, 0x83, 0x10, 0x8f, 0xf3, 0x53, 0x82, + 0x80, 0xc3, 0x4f, 0x3a, 0xc7, 0x6e, 0x11, 0x3f, 0xe6, 0xe3, 0x16, 0x91, 0x84, 0xfb, 0x6d, 0x84, + 0x7f, 0x34, 0x74, 0xad, 0x89, 0xa7, 0xce, 0xb9, 0xd7, 0xd7, 0x9f, 0x84, 0x64, 0x92, 0xbe, 0x95, + 0xa1, 0xad, 0x09, 0x53, 0x33, 0xdd, 0xee, 0x0a, 0xea, 0x4a, 0x51, 0x8e, 0x6f, 0x55, 0xab, 0xba, + 0xb5, 0x94, 0x46, 0xae, 0x8c, 0x7f, 0xd8, 0xa2, 0x50, 0x25, 0x65, 0x60, 0x80, 0x46, 0xdb, 0x33, + 0x04, 0xae, 0x6c, 0xb5, 0x98, 0x74, 0x54, 0x25, 0xdc, 0x93, 0xe4, 0xf8, 0xe3, 0x55, 0x15, 0x3d, + 0xb8, 0x6d, 0xc3, 0x0a, 0xa4, 0x12, 0xc1, 0x69, 0x85, 0x6e, 0xdf, 0x64, 0xf1, 0x53, 0x99, 0xe1, + 0x4a, 0x75, 0x20, 0x9d, 0x95, 0x0f, 0xe4, 0xd6, 0xdc, 0x03, 0xf1, 0x59, 0x18, 0xe8, 0x47, 0x89, + 0xb2, 0x57, 0x5a, 0x94, 0xb6, 0xa9, 0xd8, 0x17, 0x2b, 0x17, 0x49, 0xe5, 0x76, 0xcb, 0xc1, 0x56, + 0x99, 0x3a, 0x37, 0xb1, 0xff, 0x69, 0x2c, 0x91, 0x91, 0x93, 0xe1, 0xdf, 0x4c, 0xa3, 0x37, 0x76, + 0x4d, 0xa1, 0x9f, 0xf8, 0x6d, 0x1e, 0x1d, 0xd3, 0xfa, 0xec, 0xfb, 0xf4, 0x45, 0x1d, 0x13, 0x6d, + 0xcf, 0xf7, 0x59, 0xe5, 0x22, 0x27, 0x72, 0x2b, 0x86, 0xf3, 0x57, 0xbb, 0x30, 0xed, 0x24, 0x4d, + 0xdc, 0x7d, 0x56, 0xbb, 0xa3, 0xb3, 0xf8, 0x34, 0x79, 0x89, 0xc1, 0xe0, 0xf2, 0x02, 0x61, 0xf7, + 0xa6, 0xfc, 0x0f, 0xbb, 0x1c, 0x17, 0x0b, 0xae, 0x41, 0xd9, 0x7c, 0xbd, 0x27, 0xa3, 0xfd, 0x2e, + 0x3a, 0xd1, 0x93, 0x94, 0xb1, 0x73, 0x1d, 0x24, 0x8b, 0xaf, 0x5b, 0x20, 0x89, 0xad, 0xb7, 0x67, + 0x66, 0x79, 0xf5, 0x3a, 0xc6, 0xa6, 0x96, 0x33, 0xfe, 0x53, 0x92, 0xc8, 0x46, 0xb1, 0x11, 0x91, + 0xc6, 0x99, 0x7f, 0x8f, 0xc9, 0xd6, 0x66, 0x31, 0x20, 0x41, 0x10, 0x87, 0x2d, 0x0c, 0xd6, 0xc1, + 0xaf, 0x34, 0x98, 0xca, 0x64, 0x83, 0xfb, 0x13, 0x57, 0xd1, 0xc1, 0xf0, 0x3c, 0x7a, 0x8c, 0xa5, + 0xc1, 0xfd, 0x95, 0x21, 0xa0, 0x71, 0xc1, 0x93, 0x67, 0x71, 0x12, 0xea, 0x8f, 0x88, 0x0a, 0x69, + 0x19, 0x64, 0x99, 0x23, 0x56, 0xfb, 0xac, 0x2a, 0x2e, 0x70, 0xbe, 0x66, 0xc4, 0x0c, 0x84, 0xef, + 0xe5, 0x8b, 0xf3, 0x93, 0x01, 0xf8, 0x6a, 0x90, 0x93, 0x67, 0x4b, 0xb2, 0x68, 0xa3, 0xb5, 0x62, + 0x8f, 0xe9, 0x3f, 0x8c, 0x7a, 0x3b, 0x5e, 0x0f, 0xe7, 0x8c, 0xb8, 0xc6, 0x7c, 0xef, 0x37, 0xfd, + 0x74, 0xe2, 0xc8, 0x4f, 0x33, 0x72, 0xe1, 0x94, 0x39, 0x6d, 0xbd, 0x12, 0xaf, 0xbe, 0x0c, 0x4e, + 0x70, 0x7c, 0x1b, 0x6f, 0x8d, 0xb3, 0x32, 0x93, 0x73, 0x44, 0x16, 0x6d, 0xe8, 0xf4, 0xf7, 0xe0, + 0x95, 0x80, 0x8f, 0x96, 0x5d, 0x38, 0xa4, 0xf4, 0xab, 0xde, 0x0a, 0x30, 0x87, 0x93, 0xd8, 0x4d, + 0x00, 0x71, 0x62, 0x45, 0x27, 0x4b, 0x3a, 0x42, 0x84, 0x5b, 0x7f, 0x65, 0xb7, 0x67, 0x34, 0x52, + 0x2d, 0x9c, 0x16, 0x6b, 0xaa, 0xa8, 0xd8, 0x7b, 0xa3, 0x42, 0x4c, 0x71, 0xc7, 0x0c, 0xca, 0x3e, + 0x83, 0xe4, 0xa6, 0xef, 0xb7, 0x01, 0x30, 0x5e, 0x51, 0xa3, 0x79, 0xf5, 0x70, 0x69, 0xa6, 0x41, + 0x44, 0x0f, 0x86, 0xb0, 0x2c, 0x91, 0xc6, 0x3d, 0xea, 0xae, 0x0f, 0x84 +}; +const unsigned int _nx_azure_iot_root_cert_size_3 = sizeof(_nx_azure_iot_root_cert_3); diff --git a/addons/azure_iot/samples/cert/nx_azure_iot_cert.h b/addons/azure_iot/samples/cert/nx_azure_iot_cert.h index 196ff93b..90f60ff4 100644 --- a/addons/azure_iot/samples/cert/nx_azure_iot_cert.h +++ b/addons/azure_iot/samples/cert/nx_azure_iot_cert.h @@ -26,6 +26,10 @@ extern "C" { /* Users can use this root certificate as sample, and also can build the root certificate by themself. */ extern const unsigned char _nx_azure_iot_root_cert[]; extern const unsigned int _nx_azure_iot_root_cert_size; +extern const unsigned char _nx_azure_iot_root_cert_2[]; +extern const unsigned int _nx_azure_iot_root_cert_size_2; +extern const unsigned char _nx_azure_iot_root_cert_3[]; +extern const unsigned int _nx_azure_iot_root_cert_size_3; /* Determine if a C++ compiler is being used. If so, ensure that standard diff --git a/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.c b/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.c index a40dd3f6..7ed5f9fa 100644 --- a/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.c +++ b/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.c @@ -24,6 +24,7 @@ extern NX_CRYPTO_METHOD crypto_method_hmac; extern NX_CRYPTO_METHOD crypto_method_hmac_sha256; extern NX_CRYPTO_METHOD crypto_method_tls_prf_sha256; extern NX_CRYPTO_METHOD crypto_method_sha256; +extern NX_CRYPTO_METHOD crypto_method_sha384; extern NX_CRYPTO_METHOD crypto_method_aes_cbc_128; extern NX_CRYPTO_METHOD crypto_method_rsa; #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE @@ -38,6 +39,7 @@ const NX_CRYPTO_METHOD *_nx_azure_iot_tls_supported_crypto[] = &crypto_method_hmac_sha256, &crypto_method_tls_prf_sha256, &crypto_method_sha256, + &crypto_method_sha384, &crypto_method_aes_cbc_128, &crypto_method_rsa, #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE @@ -59,6 +61,7 @@ extern const NX_CRYPTO_CIPHERSUITE nx_crypto_tls_rsa_with_aes_128_cbc_sha256; /* Define supported X.509 ciphersuites. */ extern const NX_CRYPTO_CIPHERSUITE nx_crypto_x509_rsa_sha_256; +extern const NX_CRYPTO_CIPHERSUITE nx_crypto_x509_rsa_sha_384; #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE extern const NX_CRYPTO_CIPHERSUITE nx_crypto_x509_ecdsa_sha_256; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ @@ -75,6 +78,7 @@ const NX_CRYPTO_CIPHERSUITE *_nx_azure_iot_tls_ciphersuite_map[] = /* X.509 ciphersuites. */ &nx_crypto_x509_rsa_sha_256, + &nx_crypto_x509_rsa_sha_384, #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE &nx_crypto_x509_ecdsa_sha_256, #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ diff --git a/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.h b/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.h index 8b71fc59..270c02f9 100644 --- a/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.h +++ b/addons/azure_iot/samples/cert/nx_azure_iot_ciphersuites.h @@ -23,7 +23,7 @@ extern const UINT _nx_azure_iot_tls_ciphersuite_map_size; /* Define the metadata size for _nx_azure_iot_tls_ciphers. */ #ifndef NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE -#define NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE (9 * 1024) +#define NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE (10 * 1024) #endif /* NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE */ #endif /* NX_AZURE_IOT_CIPHERSUITES_H */ diff --git a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c b/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c deleted file mode 100644 index 167195ef..00000000 --- a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.c +++ /dev/null @@ -1,443 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "nx_azure_iot_pnp_helpers.h" - -#include - -#include "azure/core/az_json.h" -#include "nx_api.h" - -/* Telemetry message property used to indicate the message's component. */ -static const CHAR sample_pnp_telemetry_component_property[] = "$.sub"; - -/* Reported property response property keys. */ -static const CHAR sample_pnp_component_type_property_name[] = "__t"; -static const CHAR reported_component_type_value[] = "c"; -static const CHAR reported_value_property_name[] = "value"; -static const CHAR reported_status_property_name[] = "ac"; -static const CHAR reported_version_property_name[] = "av"; -static const CHAR reported_description_property_name[] = "ad"; - -/* PnP command seperator. */ -static const az_span command_separator = AZ_SPAN_LITERAL_FROM_STR("*"); - -/* Device twin keys */ -static const CHAR sample_iot_hub_twin_desired_version[] = "$version"; -static const CHAR sample_iot_hub_twin_desired[] = "desired"; - -/* Move reader to the value of property name. */ -static UINT sample_json_child_token_move(NX_AZURE_IOT_JSON_READER *json_reader_ptr, - UCHAR *property_name_ptr, UINT property_name_len) -{ - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if ((nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) && - nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, - property_name_ptr, - property_name_len)) - { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to read next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip child of complex object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - return(NX_AZURE_IOT_NOT_FOUND); - } - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -/* Visit component property Object and call callback on each property of that component. */ -static UINT visit_component_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT version, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), VOID *context_ptr) -{ -UINT len; - - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) - { - if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, scratch_buf, scratch_buf_len, &len)) - { - printf("Failed to get string property value\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to get next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((len == sizeof(sample_pnp_component_type_property_name) - 1) && - (memcmp((VOID *)scratch_buf, (VOID *)sample_pnp_component_type_property_name, len) == 0)) - { - continue; - } - - if ((len == sizeof(sample_iot_hub_twin_desired_version) - 1) && - (memcmp((VOID *)scratch_buf, (VOID *)sample_iot_hub_twin_desired_version, len) == 0)) - { - continue; - } - - sample_desired_property_callback(component_name_ptr, component_name_len, - scratch_buf, len, *json_reader_ptr, version, context_ptr); - - } - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - break; - } - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Check if component is part of component list. */ -static UINT is_component_in_model(UCHAR *component_name_ptr, UINT component_name_len, - CHAR **sample_components_ptr, UINT sample_components_num, - UINT *out_index) -{ -UINT index = 0; - - if (component_name_ptr == NX_NULL || component_name_len == 0) - { - return(NX_NOT_SUCCESSFUL); - } - - while (index < sample_components_num) - { - if ((component_name_len == strlen(sample_components_ptr[index])) && - (memcmp((VOID *)component_name_ptr, (VOID *)sample_components_ptr[index], component_name_len) == 0)) - { - *out_index = index; - return(NX_AZURE_IOT_SUCCESS); - } - - index++; - } - - return(NX_AZURE_IOT_NOT_FOUND); -} - -/* Parse PnP command names. */ -UINT nx_azure_iot_pnp_helper_command_name_parse(const UCHAR *method_name_ptr, UINT method_name_length, - const UCHAR **component_name_pptr, UINT *component_name_length_ptr, - const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr) -{ -INT index; -az_span method_name = az_span_create((UCHAR *)method_name_ptr, (INT)method_name_length); - - if ((index = az_span_find(method_name, command_separator)) != -1) - { - /* If a separator character is present in the device method name, then a command on a subcomponent of - the model is being targeted (e.g. thermostat1*getMaxMinReport). */ - *component_name_pptr = method_name_ptr; - *component_name_length_ptr = (UINT)index; - *pnp_command_name_pptr = method_name_ptr + index + 1; - *pnp_command_name_length_ptr = method_name_length - (UINT)index - 1; - } - else - { - /* The separator character is optional. If it is not present, it indicates a command of the root - component and not a subcomponent (e.g. "reboot"). */ - *component_name_pptr = NULL; - *component_name_length_ptr = 0; - *pnp_command_name_pptr = method_name_ptr; - *pnp_command_name_length_ptr = method_name_length; - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Parse twin data and call callback on each desired property. */ -UINT nx_azure_iot_pnp_helper_twin_data_parse(NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT is_partial, - CHAR **sample_components_ptr, UINT sample_components_num, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, UCHAR *property_name_ptr, - UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), - VOID *context_ptr) -{ -NX_AZURE_IOT_JSON_READER copy_json_reader; -UINT version; -UINT len; -UINT index; -UINT status; - - if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr))) - { - printf("Failed to initialize json reader: error %d\r\n", status); - return(status); - } - - if (!is_partial && sample_json_child_token_move(json_reader_ptr, - (UCHAR *)sample_iot_hub_twin_desired, - sizeof(sample_iot_hub_twin_desired) - 1)) - { - printf("Failed to get desired property\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - copy_json_reader = *json_reader_ptr; - if (sample_json_child_token_move(©_json_reader, - (UCHAR *)sample_iot_hub_twin_desired_version, - sizeof(sample_iot_hub_twin_desired_version) - 1) || - nx_azure_iot_json_reader_token_int32_get(©_json_reader, (int32_t *)&version)) - { - printf("Failed to get version\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - while (nx_azure_iot_json_reader_next_token(json_reader_ptr) == NX_AZURE_IOT_SUCCESS) - { - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) - { - if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, scratch_buf, - scratch_buf_len, &len)) - { - printf("Failed to string value for property name\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((len == sizeof(sample_iot_hub_twin_desired_version) - 1) && - (memcmp((VOID *)sample_iot_hub_twin_desired_version, (VOID *)scratch_buf, len) == 0)) - { - continue; - } - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT && - sample_components_ptr != NX_NULL && - (is_component_in_model(scratch_buf, len, - sample_components_ptr, sample_components_num, - &index) == NX_AZURE_IOT_SUCCESS)) - { - if (visit_component_properties((UCHAR *)sample_components_ptr[index], - strlen(sample_components_ptr[index]), - json_reader_ptr, version, scratch_buf, scratch_buf_len, - sample_desired_property_callback, context_ptr)) - { - printf("Failed to visit component properties\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else - { - sample_desired_property_callback(NX_NULL, 0, scratch_buf, len, - *json_reader_ptr, version, context_ptr); - - if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader_ptr)) - { - printf("Failed to skip children of object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == - NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - break; - } - } - - return(NX_AZURE_IOT_SUCCESS); -} - -/* Create PnP telemetry message. */ -UINT nx_azure_iot_pnp_helper_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name, UINT component_name_len, - NX_PACKET **packet_pptr, UINT wait_option) -{ -UINT status; - - /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_hub_client_telemetry_message_create(iothub_client_ptr, packet_pptr, wait_option))) - { - printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - } - - /* If the component will be used, then specify this as a property of the message. */ - else if ((component_name != NULL) && - (status = nx_azure_iot_hub_client_telemetry_property_add(*packet_pptr, - (UCHAR *)sample_pnp_telemetry_component_property, - (USHORT)sizeof(sample_pnp_telemetry_component_property) - 1, - component_name, (USHORT)component_name_len, - NX_WAIT_FOREVER)) != NX_AZURE_IOT_SUCCESS) - { - printf("nx_azure_iot_hub_client_telemetry_property_add=%s failed, error=%d", - sample_pnp_telemetry_component_property, status); - nx_azure_iot_hub_client_telemetry_message_delete(*packet_pptr); - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -/* Build PnP reported property into user provided buffer. */ -UINT nx_azure_iot_pnp_helper_build_reported_property(UCHAR *component_name_ptr, UINT component_name_len, - UINT (*append_reported_property)(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, - VOID *context), - VOID *context, NX_AZURE_IOT_JSON_WRITER *json_builder_ptr) -{ -UINT status; - - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - (component_name_ptr != NX_NULL && - (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - component_name_ptr, - component_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)sample_pnp_component_type_property_name, - sizeof(sample_pnp_component_type_property_name) - 1, - (UCHAR *)reported_component_type_value, - sizeof(reported_component_type_value) - 1))) || - (append_reported_property(json_builder_ptr, context) != NX_AZURE_IOT_SUCCESS) || - (component_name_ptr != NX_NULL && nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed to build reported property\r\n"); - status = NX_NOT_SUCCESSFUL; - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -/* Build reported property with status. */ -UINT nx_azure_iot_pnp_helper_build_reported_property_with_status(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - UINT (*append_value)(NX_AZURE_IOT_JSON_WRITER *builder, - VOID *context), - VOID *context, - INT result, UCHAR *description_ptr, - UINT description_len, - UINT ack_version, - NX_AZURE_IOT_JSON_WRITER *json_builder_ptr) -{ - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr)) - { - printf("Failed initializing json writer \r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (component_name_ptr != NX_NULL && - (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - component_name_ptr, - component_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)sample_pnp_component_type_property_name, - sizeof(sample_pnp_component_type_property_name) - 1, - (UCHAR *)reported_component_type_value, - sizeof(reported_component_type_value) - 1))) - { - printf("Failed build reported property with status message \r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - property_name_ptr, property_name_len) || - nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_name(json_builder_ptr, - (UCHAR *)reported_value_property_name, - sizeof(reported_value_property_name) - 1) || - (append_value(json_builder_ptr, context) != NX_AZURE_IOT_SUCCESS) || - nx_azure_iot_json_writer_append_property_with_int32_value(json_builder_ptr, - (UCHAR *)reported_status_property_name, - sizeof(reported_status_property_name) - 1, - result) || - nx_azure_iot_json_writer_append_property_with_string_value(json_builder_ptr, - (UCHAR *)reported_description_property_name, - sizeof(reported_description_property_name) - 1, - description_ptr, description_len) || - nx_azure_iot_json_writer_append_property_with_int32_value(json_builder_ptr, - (UCHAR *)reported_version_property_name, - sizeof(reported_version_property_name) - 1, - (INT)ack_version) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed build reported property with status message\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if (component_name_ptr != NX_NULL && - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - printf("Failed build reported property with status message\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); -} diff --git a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h b/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h deleted file mode 100644 index ba6ffb7e..00000000 --- a/addons/azure_iot/samples/common/nx_azure_iot_pnp_helpers.h +++ /dev/null @@ -1,125 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef NX_AZURE_IOT_PNP_HELPERS_H -#define NX_AZURE_IOT_PNP_HELPERS_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nx_azure_iot_json_reader.h" -#include "nx_azure_iot_json_writer.h" -#include "nx_azure_iot_hub_client.h" -#include "nx_api.h" - -/** - * @brief Parse PnP command name - * - * @param[in] method_name_ptr Pointer to method name - * @param[in] method_name_length Length of method name - * @param[out] component_name_pptr Pointer to component pointer - * @param[out] component_name_length_ptr Pointer to length of component name length - * @param[out] pnp_command_name_pptr Pointer to command name pointer - * @param[out] pnp_command_name_length_ptr Pointer to length of command name - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful parsed command name. - */ -UINT nx_azure_iot_pnp_helper_command_name_parse(const UCHAR *method_name_ptr, UINT method_name_length, - const UCHAR **component_name_pptr, UINT *component_name_length_ptr, - const UCHAR **pnp_command_name_pptr, UINT *pnp_command_name_length_ptr); - -/** - * @brief Parse twin data and call callback on each desired property - * - * @param[in] json_reader_ptr `NX_AZURE_IOT_JSON_READER` pointer containing the twin data - * @param[in] is_partial 1 if twin data is patch else 0 if full twin document - * @param[in] sample_components_ptr Pointer to list of all components name pointers - * @param[in] sample_components_num Size of component list - * @param[in] scratch_buf Temporary buffer used for staging property names out of the JSON document - * @param[in] scratch_buf_len Temporary buffer length size - * @param[in] sample_desired_property_callback Callback called with each desired property - * @param[in] context_ptr Context passed to the callback - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful parsed twin data. - */ -UINT nx_azure_iot_pnp_helper_twin_data_parse(NX_AZURE_IOT_JSON_READER *json_reader_ptr, UINT is_partial, - CHAR **sample_components_ptr, UINT sample_components_num, - UCHAR *scratch_buf, UINT scratch_buf_len, - VOID (*sample_desired_property_callback)(UCHAR *component_name_ptr, - UINT component_name_len, UCHAR *property_name_ptr, - UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback), - VOID *context_ptr); - -/** - * @brief Create PnP telemetry message - * - * @param[in] iothub_client_ptr Pointer to `NX_AZURE_IOT_HUB_CLIENT` - * @param[in] component_name Pointer to component name - * @param[in] component_name_len Length of component name - * @param[out] packet_pptr `NX_PACKET` return via the API. - * @param[in] wait_option Ticks to wait if no packet is available. - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created NX_PACKET. - */ -UINT nx_azure_iot_pnp_helper_telemetry_message_create(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name, UINT component_name_len, - NX_PACKET **packet_pptr, UINT wait_option); - -/** - * @brief Build PnP reported property into user provided buffer - * - * @param[in] component_name_ptr Pointer to component name - * @param[in] component_name_len Length of component name - * @param[in] append_reported_property Callback to add reported property - * @param[in] context Context pass to callback - * @param[out] json_builder_ptr Pointer to `NX_AZURE_IOT_JSON_WRITER`, containing the json reported property - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created reported property message. - */ -UINT nx_azure_iot_pnp_helper_build_reported_property(UCHAR *component_name_ptr, UINT component_name_len, - UINT (*append_reported_property)(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, - VOID *context), - VOID *context, NX_AZURE_IOT_JSON_WRITER *json_builder_ptr); - -/** - * @brief Build reported property with status - * - * @param[in] component_name_ptr Pointer to component name - * @param[in] component_name_len Length of component name - * @param[in] property_name_ptr Pointer to property name - * @param[in] property_name_len Length of property name - * @param[in] append_value Callback to add property value - * @param[in] context Context pass to callback - * @param[in] result Status for reported property - * @param[in] description Pointer to description - * @param[in] description_len Length of description - * @param[in] ack_version ack version - * @param[out] json_builder_ptr Pointer to `NX_AZURE_IOT_JSON_WRITER`, containing the json reported property - * @return A `UINT` with the result of the API. - * @retval #NX_AZURE_IOT_SUCCESS Successful if successful created reported property message. - */ -UINT nx_azure_iot_pnp_helper_build_reported_property_with_status(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - UINT (*append_value)(NX_AZURE_IOT_JSON_WRITER *builder, - VOID *context), - VOID *context, - INT result, UCHAR *description_ptr, - UINT description_len, - UINT ack_version, - NX_AZURE_IOT_JSON_WRITER *json_builder_ptr); - -#ifdef __cplusplus -} -#endif -#endif /* NX_AZURE_IOT_PNP_HELPERS_H */ \ No newline at end of file diff --git a/addons/azure_iot/samples/main.c b/addons/azure_iot/samples/main.c index e0d417f8..93592de0 100644 --- a/addons/azure_iot/samples/main.c +++ b/addons/azure_iot/samples/main.c @@ -9,15 +9,29 @@ /* */ /**************************************************************************/ -#include - #include "nx_api.h" #ifndef SAMPLE_DHCP_DISABLE #include "nxd_dhcp_client.h" #endif /* SAMPLE_DHCP_DISABLE */ #include "nxd_dns.h" +#include "nxd_sntp_client.h" #include "nx_secure_tls_api.h" +/* Defined, HTTP proxy is enabled. */ +/* +#define SAMPLE_HTTP_PROXY_ENABLE +*/ + +#ifdef SAMPLE_HTTP_PROXY_ENABLE +#ifndef NX_ENABLE_HTTP_PROXY +#error "SYMBOL NX_ENABLE_HTTP_PROXY must be defined. " +#endif /* NX_ENABLE_HTTP_PROXY */ +#endif /* SAMPLE_HTTP_PROXY_ENABLE */ + +#if defined(SAMPLE_HTTP_PROXY_ENABLE) +#include "nx_http_proxy_client.h" +#endif /* SAMPLE_HTTP_PROXY_ENABLE */ + /* Include the sample. */ extern VOID sample_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)); @@ -53,7 +67,7 @@ extern VOID sample_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_pt #define SAMPLE_IP_THREAD_PRIORITY (1) #endif /* SAMPLE_IP_THREAD_PRIORITY */ -#ifdef SAMPLE_DHCP_DISABLE +#if defined(SAMPLE_DHCP_DISABLE) && !defined(SAMPLE_NETWORK_CONFIGURE) #ifndef SAMPLE_IPV4_ADDRESS /*#define SAMPLE_IPV4_ADDRESS IP_ADDRESS(192, 168, 100, 33)*/ #error "SYMBOL SAMPLE_IPV4_ADDRESS must be defined. This symbol specifies the IP address of device. " @@ -76,8 +90,50 @@ extern VOID sample_entry(NX_IP* ip_ptr, NX_PACKET_POOL* pool_ptr, NX_DNS* dns_pt #else #define SAMPLE_IPV4_ADDRESS IP_ADDRESS(0, 0, 0, 0) #define SAMPLE_IPV4_MASK IP_ADDRESS(0, 0, 0, 0) + +#ifndef SAMPLE_DHCP_WAIT_OPTION +#define SAMPLE_DHCP_WAIT_OPTION (20 * NX_IP_PERIODIC_RATE) +#endif /* SAMPLE_DHCP_WAIT_OPTION */ + #endif /* SAMPLE_DHCP_DISABLE */ +#ifndef SAMPLE_SNTP_SYNC_MAX +#define SAMPLE_SNTP_SYNC_MAX 30 +#endif /* SAMPLE_SNTP_SYNC_MAX */ + +#ifndef SAMPLE_SNTP_UPDATE_MAX +#define SAMPLE_SNTP_UPDATE_MAX 10 +#endif /* SAMPLE_SNTP_UPDATE_MAX */ + +#ifndef SAMPLE_SNTP_UPDATE_INTERVAL +#define SAMPLE_SNTP_UPDATE_INTERVAL (NX_IP_PERIODIC_RATE / 2) +#endif /* SAMPLE_SNTP_UPDATE_INTERVAL */ + +/* Default time. GMT: Friday, Jan 1, 2022 12:00:00 AM. Epoch timestamp: 1640995200. */ +#ifndef SAMPLE_SYSTEM_TIME +#define SAMPLE_SYSTEM_TIME 1640995200 +#endif /* SAMPLE_SYSTEM_TIME */ + +/* Seconds between Unix Epoch (1/1/1970) and NTP Epoch (1/1/1999) */ +#define SAMPLE_UNIX_TO_NTP_EPOCH_SECOND 0x83AA7E80 + +#if defined(SAMPLE_HTTP_PROXY_ENABLE) +#ifndef SAMPLE_HTTP_PROXY_SERVER +#define SAMPLE_HTTP_PROXY_SERVER IP_ADDRESS(192, 168, 100, 6) +#endif /* SAMPLE_HTTP_PROXY_SERVER */ + +#ifndef SAMPLE_HTTP_PROXY_SERVER_PORT +#define SAMPLE_HTTP_PROXY_SERVER_PORT 8888 +#endif /* SAMPLE_HTTP_PROXY_SERVER_PORT */ + +#ifndef SAMPLE_HTTP_PROXY_USER_NAME +#define SAMPLE_HTTP_PROXY_USER_NAME "" +#endif /* SAMPLE_HTTP_PROXY_USER_NAME */ + +#ifndef SAMPLE_HTTP_PROXY_PASSWORD +#define SAMPLE_HTTP_PROXY_PASSWORD "" +#endif /* SAMPLE_HTTP_PROXY_PASSWORD */ +#endif /* SAMPLE_HTTP_PROXY_ENABLE */ static TX_THREAD sample_helper_thread; static NX_PACKET_POOL pool_0; @@ -86,7 +142,10 @@ static NX_DNS dns_0; #ifndef SAMPLE_DHCP_DISABLE static NX_DHCP dhcp_0; #endif /* SAMPLE_DHCP_DISABLE */ +static NX_SNTP_CLIENT sntp_client; +/* System clock time for UTC. */ +static ULONG unix_time_base; /* Define the stack/cache for ThreadX. */ static ULONG sample_ip_stack[SAMPLE_IP_STACK_SIZE / sizeof(ULONG)]; @@ -97,27 +156,55 @@ static ULONG sample_pool_stack_size = sizeof(sample_pool_stack); extern ULONG sample_pool_stack[]; extern ULONG sample_pool_stack_size; #endif +#ifndef SAMPLE_NETWORK_CONFIGURE static ULONG sample_arp_cache_area[SAMPLE_ARP_CACHE_SIZE / sizeof(ULONG)]; +#endif static ULONG sample_helper_thread_stack[SAMPLE_HELPER_STACK_SIZE / sizeof(ULONG)]; +static const CHAR *sntp_servers[] = +{ + "0.pool.ntp.org", + "1.pool.ntp.org", + "2.pool.ntp.org", + "3.pool.ntp.org", +}; +static UINT sntp_server_index; + /* Define the prototypes for sample thread. */ static void sample_helper_thread_entry(ULONG parameter); #ifndef SAMPLE_DHCP_DISABLE -static void dhcp_wait(); +static UINT dhcp_wait(); #endif /* SAMPLE_DHCP_DISABLE */ -static UINT dns_create(); +static UINT dns_create(ULONG dns_server_address); +static UINT sntp_time_sync(); static UINT unix_time_get(ULONG *unix_time); +#ifndef SAMPLE_NETWORK_DRIVER +#define SAMPLE_NETWORK_DRIVER _nx_ram_network_driver +#endif /* SAMPLE_NETWORK_DRIVER */ + /* Include the platform IP driver. */ -void _nx_ram_network_driver(struct NX_IP_DRIVER_STRUCT *driver_req); +void SAMPLE_NETWORK_DRIVER(struct NX_IP_DRIVER_STRUCT *driver_req); + +#ifdef SAMPLE_BOARD_SETUP +void SAMPLE_BOARD_SETUP(); +#endif /* SAMPLE_BOARD_SETUP */ + +#ifdef SAMPLE_NETWORK_CONFIGURE +void SAMPLE_NETWORK_CONFIGURE(NX_IP *ip_ptr, ULONG *dns_address); +#endif /* Define main entry point. */ int main(void) { +#ifdef SAMPLE_BOARD_SETUP + SAMPLE_BOARD_SETUP(); +#endif /* SAMPLE_BOARD_SETUP */ + /* Enter the ThreadX kernel. */ tx_kernel_enter(); } @@ -128,7 +215,6 @@ void tx_application_define(void *first_unused_memory) UINT status; - NX_PARAMETER_NOT_USED(first_unused_memory); /* Initialize the NetX system. */ @@ -148,7 +234,7 @@ UINT status; /* Create an IP instance. */ status = nx_ip_create(&ip_0, "NetX IP Instance 0", SAMPLE_IPV4_ADDRESS, SAMPLE_IPV4_MASK, - &pool_0, _nx_ram_network_driver, + &pool_0, SAMPLE_NETWORK_DRIVER, (UCHAR*)sample_ip_stack, sizeof(sample_ip_stack), SAMPLE_IP_THREAD_PRIORITY); @@ -159,6 +245,7 @@ UINT status; return; } +#ifndef SAMPLE_NETWORK_CONFIGURE /* Enable ARP and supply ARP cache memory for IP Instance 0. */ status = nx_arp_enable(&ip_0, (VOID *)sample_arp_cache_area, sizeof(sample_arp_cache_area)); @@ -178,6 +265,7 @@ UINT status; printf("nx_icmp_enable fail: %u\r\n", status); return; } +#endif /* Enable TCP traffic. */ status = nx_tcp_enable(&ip_0); @@ -202,7 +290,7 @@ UINT status; /* Initialize TLS. */ nx_secure_tls_initialize(); - /* Create sample helper thread. */ + /* Create sample helper thread. */ status = tx_thread_create(&sample_helper_thread, "Demo Thread", sample_helper_thread_entry, 0, sample_helper_thread_stack, SAMPLE_HELPER_STACK_SIZE, @@ -220,25 +308,54 @@ UINT status; /* Define sample helper thread entry. */ void sample_helper_thread_entry(ULONG parameter) { + UINT status; ULONG ip_address = 0; ULONG network_mask = 0; ULONG gateway_address = 0; - +UINT unix_time; +ULONG dns_server_address[3]; +#ifndef SAMPLE_DHCP_DISABLE +UINT dns_server_address_size = sizeof(dns_server_address); +#endif +#if defined(SAMPLE_HTTP_PROXY_ENABLE) +NXD_ADDRESS proxy_server_address; +#endif /* SAMPLE_HTTP_PROXY_ENABLE */ NX_PARAMETER_NOT_USED(parameter); +#if defined(SAMPLE_HTTP_PROXY_ENABLE) + + /* Enabled HTTP proxy. */ + proxy_server_address.nxd_ip_version = NX_IP_VERSION_V4; + proxy_server_address.nxd_ip_address.v4 = SAMPLE_HTTP_PROXY_SERVER; + status = nx_http_proxy_client_enable(&ip_0, &proxy_server_address, SAMPLE_HTTP_PROXY_SERVER_PORT, + SAMPLE_HTTP_PROXY_USER_NAME, sizeof(SAMPLE_HTTP_PROXY_USER_NAME) - 1, + SAMPLE_HTTP_PROXY_PASSWORD, sizeof(SAMPLE_HTTP_PROXY_PASSWORD) - 1); + if (status) + { + printf("Failed to enable HTTP proxy!\r\n"); + return; + } +#endif /* SAMPLE_HTTP_PROXY_ENABLE */ + #ifndef SAMPLE_DHCP_DISABLE - dhcp_wait(); + if (dhcp_wait()) + { + printf("Failed to get the IP address!\r\n"); + return; + } +#elif defined(SAMPLE_NETWORK_CONFIGURE) + SAMPLE_NETWORK_CONFIGURE(&ip_0, &dns_server_address[0]); #else nx_ip_gateway_address_set(&ip_0, SAMPLE_GATEWAY_ADDRESS); #endif /* SAMPLE_DHCP_DISABLE */ - /* Get IP address and gateway address. */ + /* Get IP address and gateway address. */ nx_ip_address_get(&ip_0, &ip_address, &network_mask); nx_ip_gateway_address_get(&ip_0, &gateway_address); - /* Output IP address and gateway address. */ + /* Output IP address and gateway address. */ printf("IP address: %lu.%lu.%lu.%lu\r\n", (ip_address >> 24), (ip_address >> 16 & 0xFF), @@ -255,8 +372,16 @@ ULONG gateway_address = 0; (gateway_address >> 8 & 0xFF), (gateway_address & 0xFF)); +#ifndef SAMPLE_DHCP_DISABLE + /* Retrieve DNS server address. */ + nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)(dns_server_address), + &dns_server_address_size); +#elif !defined(SAMPLE_NETWORK_CONFIGURE) + dns_server_address[0] = SAMPLE_DNS_SERVER_ADDRESS; +#endif /* SAMPLE_DHCP_DISABLE */ + /* Create DNS. */ - status = dns_create(); + status = dns_create(dns_server_address[0]); /* Check for DNS create errors. */ if (status) @@ -265,52 +390,97 @@ ULONG gateway_address = 0; return; } - /* Use time to init the seed. FIXME: use real rand on device. */ - srand((unsigned int)time(NULL)); + /* Sync up time by SNTP at start up. */ + status = sntp_time_sync(); + + /* Check status. */ + if (status) + { + printf("SNTP Time Sync failed.\r\n"); + printf("Set Time to default value: SAMPLE_SYSTEM_TIME."); + unix_time_base = SAMPLE_SYSTEM_TIME; + } + else + { + printf("SNTP Time Sync successfully.\r\n"); + } + + unix_time_get((ULONG *)&unix_time); + srand(unix_time); /* Start sample. */ sample_entry(&ip_0, &pool_0, &dns_0, unix_time_get); } #ifndef SAMPLE_DHCP_DISABLE -static void dhcp_wait() +static UINT dhcp_wait() { +UINT status; ULONG actual_status; printf("DHCP In Progress...\r\n"); /* Create the DHCP instance. */ - nx_dhcp_create(&dhcp_0, &ip_0, "DHCP Client"); + status = nx_dhcp_create(&dhcp_0, &ip_0, "DHCP Client"); + + /* Check status. */ + if (status) + { + return(status); + } + + /* Request NTP server. */ + status = nx_dhcp_user_option_request(&dhcp_0, NX_DHCP_OPTION_NTP_SVR); + + /* Check status. */ + if (status) + { + nx_dhcp_delete(&dhcp_0); + return(status); + } /* Start the DHCP Client. */ - nx_dhcp_start(&dhcp_0); + status = nx_dhcp_start(&dhcp_0); + + /* Check status. */ + if (status) + { + nx_dhcp_delete(&dhcp_0); + return(status); + } + + /* Wait util address is solved. */ + status = nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, SAMPLE_DHCP_WAIT_OPTION); + + /* Check status. */ + if (status) + { + nx_dhcp_delete(&dhcp_0); + return(status); + } - /* Wait util address is solved. */ - nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER); + return(NX_SUCCESS); } #endif /* SAMPLE_DHCP_DISABLE */ -static UINT dns_create() +static UINT dns_create(ULONG dns_server_address) { - UINT status; -ULONG dns_server_address[3]; -UINT dns_server_address_size = 12; /* Create a DNS instance for the Client. Note this function will create the DNS Client packet pool for creating DNS message packets intended - for querying its DNS server. */ + for querying its DNS server. */ status = nx_dns_create(&dns_0, &ip_0, (UCHAR *)"DNS Client"); if (status) { return(status); } - /* Is the DNS client configured for the host application to create the packet pool? */ + /* Is the DNS client configured for the host application to create the packet pool? */ #ifdef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL /* Yes, use the packet pool created above which has appropriate payload size - for DNS messages. */ + for DNS messages. */ status = nx_dns_packet_pool_set(&dns_0, ip_0.nx_ip_default_packet_pool); if (status) { @@ -319,16 +489,8 @@ UINT dns_server_address_size = 12; } #endif /* NX_DNS_CLIENT_USER_CREATE_PACKET_POOL */ -#ifndef SAMPLE_DHCP_DISABLE - /* Retrieve DNS server address. */ - nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)(dns_server_address), - &dns_server_address_size); -#else - dns_server_address[0] = SAMPLE_DNS_SERVER_ADDRESS; -#endif /* SAMPLE_DHCP_DISABLE */ - - /* Add an IPv4 server address to the Client list. */ - status = nx_dns_server_add(&dns_0, dns_server_address[0]); + /* Add an IPv4 server address to the Client list. */ + status = nx_dns_server_add(&dns_0, dns_server_address); if (status) { nx_dns_delete(&dns_0); @@ -337,20 +499,194 @@ UINT dns_server_address_size = 12; /* Output DNS Server address. */ printf("DNS Server address: %lu.%lu.%lu.%lu\r\n", - (dns_server_address[0] >> 24), - (dns_server_address[0] >> 16 & 0xFF), - (dns_server_address[0] >> 8 & 0xFF), - (dns_server_address[0] & 0xFF)); + (dns_server_address >> 24), + (dns_server_address >> 16 & 0xFF), + (dns_server_address >> 8 & 0xFF), + (dns_server_address & 0xFF)); return(NX_SUCCESS); } +/* Sync up the local time. */ +static UINT sntp_time_sync_internal(ULONG sntp_server_address) +{ +UINT status; +UINT server_status; +UINT i; + + /* Create the SNTP Client to run in broadcast mode.. */ + status = nx_sntp_client_create(&sntp_client, &ip_0, 0, &pool_0, + NX_NULL, + NX_NULL, + NX_NULL /* no random_number_generator callback */); + + /* Check status. */ + if (status) + { + return(status); + } + + /* Use the IPv4 service to initialize the Client and set the IPv4 SNTP server. */ + status = nx_sntp_client_initialize_unicast(&sntp_client, sntp_server_address); + + /* Check status. */ + if (status) + { + nx_sntp_client_delete(&sntp_client); + return(status); + } + + /* Set local time to 0 */ + status = nx_sntp_client_set_local_time(&sntp_client, 0, 0); + + /* Check status. */ + if (status) + { + nx_sntp_client_delete(&sntp_client); + return(status); + } + + /* Run Unicast client */ + status = nx_sntp_client_run_unicast(&sntp_client); + + /* Check status. */ + if (status) + { + nx_sntp_client_stop(&sntp_client); + nx_sntp_client_delete(&sntp_client); + return(status); + } + + /* Wait till updates are received */ + for (i = 0; i < SAMPLE_SNTP_UPDATE_MAX; i++) + { + + /* First verify we have a valid SNTP service running. */ + status = nx_sntp_client_receiving_updates(&sntp_client, &server_status); + + /* Check status. */ + if ((status == NX_SUCCESS) && (server_status == NX_TRUE)) + { + + /* Server status is good. Now get the Client local time. */ + ULONG sntp_seconds, sntp_fraction; + ULONG system_time_in_second; + + /* Get the local time. */ + status = nx_sntp_client_get_local_time(&sntp_client, &sntp_seconds, &sntp_fraction, NX_NULL); + + /* Check status. */ + if (status != NX_SUCCESS) + { + continue; + } + + /* Get the system time in second. */ + system_time_in_second = tx_time_get() / TX_TIMER_TICKS_PER_SECOND; + + /* Convert to Unix epoch and minus the current system time. */ + unix_time_base = (sntp_seconds - (system_time_in_second + SAMPLE_UNIX_TO_NTP_EPOCH_SECOND)); + + /* Time sync successfully. */ + + /* Stop and delete SNTP. */ + nx_sntp_client_stop(&sntp_client); + nx_sntp_client_delete(&sntp_client); + + return(NX_SUCCESS); + } + + /* Sleep. */ + tx_thread_sleep(SAMPLE_SNTP_UPDATE_INTERVAL); + } + + /* Time sync failed. */ + + /* Stop and delete SNTP. */ + nx_sntp_client_stop(&sntp_client); + nx_sntp_client_delete(&sntp_client); + + /* Return success. */ + return(NX_NOT_SUCCESSFUL); +} + +static UINT sntp_time_sync() +{ +UINT status; +ULONG gateway_address; +ULONG sntp_server_address[3]; +#ifndef SAMPLE_DHCP_DISABLE +UINT sntp_server_address_size = sizeof(sntp_server_address); +#endif + +#ifndef SAMPLE_DHCP_DISABLE + /* Retrieve NTP server address. */ + status = nx_dhcp_interface_user_option_retrieve(&dhcp_0, 0, NX_DHCP_OPTION_NTP_SVR, (UCHAR *)(sntp_server_address), + &sntp_server_address_size); + + /* Check status. */ + if (status == NX_SUCCESS) + { + for (UINT i = 0; (i * 4) < sntp_server_address_size; i++) + { + printf("SNTP Time Sync...%lu.%lu.%lu.%lu (DHCP)\r\n", + (sntp_server_address[i] >> 24), + (sntp_server_address[i] >> 16 & 0xFF), + (sntp_server_address[i] >> 8 & 0xFF), + (sntp_server_address[i] & 0xFF)); + + /* Start SNTP to sync the local time. */ + status = sntp_time_sync_internal(sntp_server_address[i]); + + /* Check status. */ + if(status == NX_SUCCESS) + { + return(NX_SUCCESS); + } + } + } +#endif /* SAMPLE_DHCP_DISABLE */ + + /* Sync time by NTP server array. */ + for (UINT i = 0; i < SAMPLE_SNTP_SYNC_MAX; i++) + { + printf("SNTP Time Sync...%s\r\n", sntp_servers[sntp_server_index]); + + /* Make sure the network is still valid. */ + while (nx_ip_gateway_address_get(&ip_0, &gateway_address)) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + } + + /* Look up SNTP Server address. */ + status = nx_dns_host_by_name_get(&dns_0, (UCHAR *)sntp_servers[sntp_server_index], &sntp_server_address[0], 5 * NX_IP_PERIODIC_RATE); + + /* Check status. */ + if (status == NX_SUCCESS) + { + + /* Start SNTP to sync the local time. */ + status = sntp_time_sync_internal(sntp_server_address[0]); + + /* Check status. */ + if(status == NX_SUCCESS) + { + return(NX_SUCCESS); + } + } + + /* Switch SNTP server every time. */ + sntp_server_index = (sntp_server_index + 1) % (sizeof(sntp_servers) / sizeof(sntp_servers[0])); + } + + return(NX_NOT_SUCCESSFUL); +} + static UINT unix_time_get(ULONG *unix_time) { - /* Using time() to get unix time on x86. - Note: User needs to implement own time function to get the real time on device, such as: SNTP. */ - *unix_time = (ULONG)time(NULL); + /* Return number of seconds since Unix Epoch (1/1/1970 00:00:00). */ + *unix_time = unix_time_base + (tx_time_get() / TX_TIMER_TICKS_PER_SECOND); return(NX_SUCCESS); } diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c index ac21c657..22f040ea 100644 --- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk.c @@ -22,6 +22,8 @@ /* Define Azure RTOS TLS info. */ static NX_SECURE_X509_CERT root_ca_cert; +static NX_SECURE_X509_CERT root_ca_cert_2; +static NX_SECURE_X509_CERT root_ca_cert_3; static UCHAR nx_azure_iot_tls_metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE]; static ULONG nx_azure_iot_thread_stack[NX_AZURE_IOT_STACK_SIZE / sizeof(ULONG)]; @@ -48,7 +50,10 @@ static SAMPLE_CLIENT client; #ifdef ENABLE_DPS_SAMPLE #define prov_client client.prov_client #endif /* ENABLE_DPS_SAMPLE */ - + +static volatile UINT sample_connection_status = NX_AZURE_IOT_NOT_INITIALIZED; +static volatile UINT sample_properties_request_sent = NX_FALSE; + /* Using X509 certificate authenticate to connect to IoT Hub, set the device certificate as your device. */ #if (USE_DEVICE_CERTIFICATE == 1) @@ -115,6 +120,10 @@ static void sample_direct_method_thread_entry(ULONG parameter); static void sample_device_twin_thread_entry(ULONG parameter); #endif /* DISABLE_DEVICE_TWIN_SAMPLE */ +/* Include the connection monitor function from sample_azure_iot_embedded_sdk_connect.c. */ +extern VOID sample_connection_monitor(NX_IP *ip_ptr, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, UINT connection_status, + UINT (*iothub_init)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)); + static VOID printf_packet(NX_PACKET *packet_ptr) { while (packet_ptr != NX_NULL) @@ -136,6 +145,8 @@ static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, { printf("Connected to IoTHub.\r\n"); } + + sample_connection_status = status; } static UINT sample_initialize_iothub(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) @@ -184,14 +195,24 @@ UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; return(status); } + /* Add more CA certificates. */ + if ((status = nx_azure_iot_hub_client_trusted_cert_add(iothub_client_ptr, &root_ca_cert_2))) + { + printf("Failed on nx_azure_iot_hub_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + else if ((status = nx_azure_iot_hub_client_trusted_cert_add(iothub_client_ptr, &root_ca_cert_3))) + { + printf("Failed on nx_azure_iot_hub_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + #if (USE_DEVICE_CERTIFICATE == 1) /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, - (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, - NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, - DEVICE_KEY_TYPE))) + else if ((status = nx_secure_x509_certificate_initialize(&device_certificate, + (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, + NX_NULL, 0, + (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, + DEVICE_KEY_TYPE))) { printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); } @@ -204,14 +225,23 @@ UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; #else /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, - (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) + else if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, + (UCHAR *)DEVICE_SYMMETRIC_KEY, + sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!\r\n"); } #endif /* USE_DEVICE_CERTIFICATE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET + + /* Enable MQTT over WebSocket to connect to IoT Hub */ + else if ((status = nx_azure_iot_hub_client_websocket_enable(iothub_client_ptr))) + { + printf("Failed on nx_azure_iot_hub_client_websocket_enable!\r\n"); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Set connection status callback. */ else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, connection_status_callback))) @@ -269,7 +299,7 @@ UINT loop = NX_TRUE; return; } - /* Initialize CA certificate. */ + /* Initialize CA certificates. */ if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, (USHORT)_nx_azure_iot_root_cert_size, NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) @@ -278,22 +308,35 @@ UINT loop = NX_TRUE; nx_azure_iot_delete(&nx_azure_iot); return; } - - if ((status = sample_initialize_iothub(&iothub_client))) + + if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert_2, (UCHAR *)_nx_azure_iot_root_cert_2, + (USHORT)_nx_azure_iot_root_cert_size_2, + NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) { - printf("Failed to initialize iothub client: error code = 0x%08x\r\n", status); + printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); nx_azure_iot_delete(&nx_azure_iot); return; } - if (nx_azure_iot_hub_client_connect(&iothub_client, NX_TRUE, NX_WAIT_FOREVER)) + if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert_3, (UCHAR *)_nx_azure_iot_root_cert_3, + (USHORT)_nx_azure_iot_root_cert_size_3, + NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) { - printf("Failed on nx_azure_iot_hub_client_connect!\r\n"); - nx_azure_iot_hub_client_deinitialize(&iothub_client); + printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); nx_azure_iot_delete(&nx_azure_iot); return; } - + + if ((status = sample_initialize_iothub(&iothub_client))) + { + printf("Failed to initialize iothub client: error code = 0x%08x\r\n", status); + sample_connection_status = NX_AZURE_IOT_NOT_INITIALIZED; + } + else if ((sample_connection_status = nx_azure_iot_hub_client_connect(&iothub_client, NX_TRUE, NX_WAIT_FOREVER))) + { + printf("Failed on nx_azure_iot_hub_client_connect!\r\n"); + } + #ifndef DISABLE_TELEMETRY_SAMPLE /* Create Telemetry sample thread. */ @@ -346,11 +389,18 @@ UINT loop = NX_TRUE; } #endif /* DISABLE_DEVICE_TWIN_SAMPLE */ - /* Simply loop in sample. */ while (loop) { + + /* Connection monitor. */ + sample_connection_monitor(ip_ptr, &iothub_client, sample_connection_status, sample_initialize_iothub); + tx_thread_sleep(NX_IP_PERIODIC_RATE); } + + /* Cleanup. */ + nx_azure_iot_hub_client_deinitialize(&iothub_client); + nx_azure_iot_delete(&nx_azure_iot); } #ifdef ENABLE_DPS_SAMPLE @@ -382,11 +432,21 @@ UINT status; *iothub_hostname_length = sizeof(sample_iothub_hostname); *iothub_device_id_length = sizeof(sample_iothub_device_id); + /* Add more CA certificates. */ + if ((status = nx_azure_iot_provisioning_client_trusted_cert_add(&prov_client, &root_ca_cert_2))) + { + printf("Failed on nx_azure_iot_provisioning_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + else if ((status = nx_azure_iot_provisioning_client_trusted_cert_add(&prov_client, &root_ca_cert_3))) + { + printf("Failed on nx_azure_iot_provisioning_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + #if (USE_DEVICE_CERTIFICATE == 1) /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) + else if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, + (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) { printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); } @@ -399,13 +459,22 @@ UINT status; #else /* Set symmetric key. */ - if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(&prov_client, (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) + else if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(&prov_client, (UCHAR *)DEVICE_SYMMETRIC_KEY, + sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); } #endif /* USE_DEVICE_CERTIFICATE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET + + /* Enable MQTT over WebSocket. */ + else if ((status = nx_azure_iot_provisioning_client_websocket_enable(&prov_client))) + { + printf("Failed on nx_azure_iot_provisioning_client_websocket_enable!\r\n"); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Register device */ else if ((status = nx_azure_iot_provisioning_client_register(&prov_client, NX_WAIT_FOREVER))) { @@ -448,12 +517,17 @@ NX_PACKET *packet_ptr; /* Loop to send telemetry message. */ while (loop) { + if (sample_connection_status != NX_SUCCESS) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + continue; + } /* Create a telemetry message packet. */ if ((status = nx_azure_iot_hub_client_telemetry_message_create(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) { printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - break; + continue; } /* Add properties to telemetry message. */ @@ -475,7 +549,7 @@ NX_PACKET *packet_ptr; if (status) { nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - break; + continue; } buffer_length = (UINT)snprintf(buffer, sizeof(buffer), "{\"Message ID\":%u}", i++); @@ -484,7 +558,7 @@ NX_PACKET *packet_ptr; { printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - break; + continue; } printf("Telemetry message send: %s.\r\n", buffer); @@ -507,10 +581,16 @@ const UCHAR *property_buf; /* Loop to receive c2d message. */ while (loop) { + if (sample_connection_status != NX_SUCCESS) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + continue; + } + if ((status = nx_azure_iot_hub_client_cloud_message_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) { printf("C2D receive failed!: error code = 0x%08x\r\n", status); - break; + continue; } if ((status = nx_azure_iot_hub_client_cloud_message_property_get(&iothub_client, packet_ptr, @@ -547,13 +627,19 @@ VOID *context_ptr; /* Loop to receive direct method message. */ while (loop) { + if (sample_connection_status != NX_SUCCESS) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + continue; + } + if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&iothub_client, &method_name_ptr, &method_name_length, &context_ptr, &context_length, &packet_ptr, NX_WAIT_FOREVER))) { printf("Direct method receive failed!: error code = 0x%08x\r\n", status); - break; + continue; } printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); @@ -567,7 +653,7 @@ VOID *context_ptr; { printf("Direct method response failed!: error code = 0x%08x\r\n", status); nx_packet_release(packet_ptr); - break; + continue; } nx_packet_release(packet_ptr); @@ -587,31 +673,42 @@ ULONG reported_property_version; NX_PARAMETER_NOT_USED(parameter); - if ((status = nx_azure_iot_hub_client_device_twin_properties_request(&iothub_client, NX_WAIT_FOREVER))) + /* Loop to receive device twin message. */ + while (loop) { - printf("device twin document request failed!: error code = 0x%08x\r\n", status); - return; - } + if (sample_connection_status != NX_SUCCESS) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + continue; + } - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) - { - printf("device twin document receive failed!: error code = 0x%08x\r\n", status); - return; - } + /* Only one properties request. */ + if (sample_properties_request_sent == NX_FALSE) + { + if ((status = nx_azure_iot_hub_client_device_twin_properties_request(&iothub_client, NX_WAIT_FOREVER))) + { + printf("device twin document request failed!: error code = 0x%08x\r\n", status); + continue; + } - printf("Receive twin properties :"); - printf_packet(packet_ptr); - printf("\r\n"); - nx_packet_release(packet_ptr); + if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) + { + printf("device twin document receive failed!: error code = 0x%08x\r\n", status); + continue; + } + + printf("Receive twin properties :"); + printf_packet(packet_ptr); + printf("\r\n"); + nx_packet_release(packet_ptr); + sample_properties_request_sent = NX_TRUE; + } - /* Loop to receive device twin message. */ - while (loop) - { if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) { printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); - break; + continue; } printf("Receive desired property call: "); @@ -626,13 +723,12 @@ ULONG reported_property_version; NX_WAIT_FOREVER))) { printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - break; + continue; } if ((response_status < 200) || (response_status >= 300)) { printf("device twin report properties failed with code : %d\r\n", response_status); - break; } } } diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_proxy_simulator_driver.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_proxy_simulator_driver.c new file mode 100644 index 00000000..9b4ff45e --- /dev/null +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_proxy_simulator_driver.c @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +#include "nx_azure_iot_adu_agent.h" + +void nx_azure_iot_adu_agent_proxy_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr); + +/****** DRIVER SPECIFIC ******/ +void nx_azure_iot_adu_agent_proxy_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr) +{ + + /* Default to successful return. */ + driver_req_ptr -> nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + + /* Process according to the driver request type. */ + switch (driver_req_ptr -> nx_azure_iot_adu_agent_driver_command) + { + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_INITIALIZE: + { + + /* Process initialize requests. */ + printf("Proxy driver initalized successfully.\r\n"); + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK: + { + + /* Compare the installed_criteria (such as: version) to check if the update is installed or not. + If installed, return NX_TRUE, else return NX_FALSE. */ + *(driver_req_ptr -> nx_azure_iot_adu_agent_driver_return_ptr) = NX_FALSE; + + printf("Proxy driver update check successfully.\r\n"); + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_PREPROCESS: + { + + /* Process firmware preprocess requests before writing firmware. + Such as: erase the flash at once to improve the speed. */ + printf("Proxy driver flash erased successfully.\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_WRITE: + { + + /* Process firmware write requests. */ + + /* Write firmware contents. + 1. This function must be able to figure out which bank it should write to. + 2. Write firmware contents into new bank. + 3. Decrypt and authenticate the firmware itself if needed. + */ + printf("Proxy driver firmware writing...\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_INSTALL: + { + + /* Set the new firmware for next boot. */ + printf("Proxy driver firmware installed successfully.\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_APPLY: + { + + /* Apply the new firmware, and reboot device from there.*/ + printf("Proxy driver firmware apply successfully.\r\n"); + + break; + } + default: + { + + /* Invalid driver request. */ + + /* Default to successful return. */ + driver_req_ptr -> nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_FAILURE; + } + } +} diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_simulator_driver.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_simulator_driver.c new file mode 100644 index 00000000..8d56a6d4 --- /dev/null +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/nx_azure_iot_adu_agent_simulator_driver.c @@ -0,0 +1,97 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +#include "nx_azure_iot_adu_agent.h" + +void nx_azure_iot_adu_agent_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr); + +/****** DRIVER SPECIFIC ******/ +void nx_azure_iot_adu_agent_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr) +{ + + /* Default to successful return. */ + driver_req_ptr -> nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_SUCCESS; + + /* Process according to the driver request type. */ + switch (driver_req_ptr -> nx_azure_iot_adu_agent_driver_command) + { + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_INITIALIZE: + { + + /* Process initialize requests. */ + printf("Driver initialized successfully.\r\n"); + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_UPDATE_CHECK: + { + + /* Compare the installed_criteria (such as: version) to check if the update is installed or not. + If installed, return NX_TRUE, else return NX_FALSE. */ + *(driver_req_ptr -> nx_azure_iot_adu_agent_driver_return_ptr) = NX_FALSE; + + printf("Proxy driver update check successfully.\r\n"); + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_PREPROCESS: + { + + /* Process firmware preprocess requests before writing firmware. + Such as: erase the flash at once to improve the speed. */ + printf("Driver flash erased successfully.\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_WRITE: + { + + /* Process firmware write requests. */ + + /* Write firmware contents. + 1. This function must be able to figure out which bank it should write to. + 2. Write firmware contents into new bank. + 3. Decrypt and authenticate the firmware itself if needed. + */ + printf("Driver firmware writing...\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_INSTALL: + { + + /* Set the new firmware for next boot. */ + printf("Driver firmware installed successfully.\r\n"); + + break; + } + + case NX_AZURE_IOT_ADU_AGENT_DRIVER_APPLY: + { + + /* Apply the new firmware, and reboot device from that.*/ + printf("Driver firmware apply successfully.\r\n"); + + break; + } + default: + { + + /* Invalid driver request. */ + + /* Default to successful return. */ + driver_req_ptr -> nx_azure_iot_adu_agent_driver_status = NX_AZURE_IOT_FAILURE; + } + } +} diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/sample_azure_iot_embedded_sdk_adu.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/sample_azure_iot_embedded_sdk_adu.c new file mode 100644 index 00000000..3ee821bd --- /dev/null +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_adu/sample_azure_iot_embedded_sdk_adu.c @@ -0,0 +1,112 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ +#include "nx_azure_iot_adu_agent.h" + +/* Device properties. */ +#ifndef SAMPLE_DEVICE_MANUFACTURER +#define SAMPLE_DEVICE_MANUFACTURER "Contoso" +#endif /* SAMPLE_DEVICE_MANUFACTURER*/ + +#ifndef SAMPLE_DEVICE_MODEL +#define SAMPLE_DEVICE_MODEL "IoTDevice" +#endif /* SAMPLE_DEVICE_MODEL */ + +#ifndef SAMPLE_DEVICE_INSTALLED_CRITERIA +#define SAMPLE_DEVICE_INSTALLED_CRITERIA "1.0.0" +#endif /* SAMPLE_DEVICE_INSTALLED_CRITERIA */ + +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) +/* Device properties. */ +#ifndef SAMPLE_LEAF_DEVICE_MANUFACTURER +#define SAMPLE_LEAF_DEVICE_MANUFACTURER "Contoso" +#endif /* SAMPLE_LEAF_DEVICE_MANUFACTURER*/ + +#ifndef SAMPLE_LEAF_DEVICE_MODEL +#define SAMPLE_LEAF_DEVICE_MODEL "IoTDevice-Leaf" +#endif /* SAMPLE_LEAF_DEVICE_MODEL */ + +#ifndef SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA +#define SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA "1.0.0" +#endif /* SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA */ +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + +static NX_AZURE_IOT_ADU_AGENT adu_agent; +static UINT adu_agent_started = NX_FALSE; + +VOID sample_adu_start(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); + +extern void nx_azure_iot_adu_agent_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr); +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) +extern void nx_azure_iot_adu_agent_proxy_driver(NX_AZURE_IOT_ADU_AGENT_DRIVER *driver_req_ptr); +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + +static void adu_agent_update_notify(NX_AZURE_IOT_ADU_AGENT *adu_agent_ptr, + UINT update_state, + UCHAR *provider, UINT provider_length, + UCHAR *name, UINT name_length, + UCHAR *version, UINT version_length) +{ + + if (update_state == NX_AZURE_IOT_ADU_AGENT_UPDATE_RECEIVED) + { + + /* Received new update. */ + printf("Received new update: Provider: %.*s; Name: %.*s, Version: %.*s\r\n", + provider_length, provider, name_length, name, version_length, version); + + /* Start to download and install update immediately for testing. */ + nx_azure_iot_adu_agent_update_download_and_install(adu_agent_ptr); + } + else if(update_state == NX_AZURE_IOT_ADU_AGENT_UPDATE_INSTALLED) + { + + /* Start to apply update immediately for testing. */ + nx_azure_iot_adu_agent_update_apply(adu_agent_ptr); + } +} + +VOID sample_adu_start(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ + if (adu_agent_started == NX_FALSE) + { + + /* Start ADU agent. */ + if (nx_azure_iot_adu_agent_start(&adu_agent, hub_client_ptr, + (const UCHAR *)SAMPLE_DEVICE_MANUFACTURER, sizeof(SAMPLE_DEVICE_MANUFACTURER) - 1, + (const UCHAR *)SAMPLE_DEVICE_MODEL, sizeof(SAMPLE_DEVICE_MODEL) - 1, + (const UCHAR *)SAMPLE_DEVICE_INSTALLED_CRITERIA, sizeof(SAMPLE_DEVICE_INSTALLED_CRITERIA) - 1, + adu_agent_update_notify, + nx_azure_iot_adu_agent_driver)) + { + printf("Failed on nx_azure_iot_adu_agent_start!\r\n"); + return; + } + + printf("Manufacturer: %s, Model: %s, Installed Criteria: %s.\r\n", SAMPLE_DEVICE_MANUFACTURER, SAMPLE_DEVICE_MODEL, SAMPLE_DEVICE_INSTALLED_CRITERIA); + +#if (NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT >= 1) + /* Enable proxy update for leaf device. */ + if (nx_azure_iot_adu_agent_proxy_update_add(&adu_agent, + (const UCHAR *)SAMPLE_LEAF_DEVICE_MANUFACTURER, sizeof(SAMPLE_LEAF_DEVICE_MANUFACTURER) - 1, + (const UCHAR *)SAMPLE_LEAF_DEVICE_MODEL, sizeof(SAMPLE_LEAF_DEVICE_MODEL) - 1, + (const UCHAR *)SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA, sizeof(SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA) - 1, + nx_azure_iot_adu_agent_proxy_driver)) + { + printf("Failed on nx_azure_iot_adu_agent_proxy_update_add!\r\n"); + return; + } + + printf("Manufacturer: %s, Model: %s, Installed Criteria: %s.\r\n", SAMPLE_LEAF_DEVICE_MANUFACTURER, SAMPLE_LEAF_DEVICE_MODEL, SAMPLE_LEAF_DEVICE_INSTALLED_CRITERIA); +#endif /* NX_AZURE_IOT_ADU_AGENT_PROXY_UPDATE_COUNT */ + + adu_agent_started = NX_TRUE; + } +} diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_connect.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_connect.c new file mode 100644 index 00000000..2cb5f8b1 --- /dev/null +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_connect.c @@ -0,0 +1,205 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +#include + +#include "nx_azure_iot_hub_client.h" + +#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC +#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC (10 * 60) +#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC */ + +#ifndef SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC +#define SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC (3) +#endif /* SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC */ + +#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT +#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT (60) +#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT */ + +VOID sample_connection_monitor(NX_IP *ip_ptr, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, UINT sample_status, + UINT (*iothub_init)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)); + +static UINT exponential_retry_count; + +static UINT iothub_init_count = 0; + +static UINT exponential_backoff_with_jitter() +{ +double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); +UINT base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; +uint64_t delay; + + if (exponential_retry_count < (sizeof(UINT) * 8)) + { + delay = (uint64_t)((1 << exponential_retry_count) * SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC); + if (delay <= (UINT)(-1)) + { + base_delay = (UINT)delay; + } + } + + if (base_delay > SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC) + { + base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; + } + else + { + exponential_retry_count++; + } + + return((UINT)(base_delay * (1 + jitter_percent)) * NX_IP_PERIODIC_RATE) ; +} + +static VOID exponential_backoff_reset() +{ + exponential_retry_count = 0; +} + +/** + * + * Connection state + * + * + * +--------------+ +--------------+ +--------------+ + * | | INIT | | NETWORK | | + * | | SUCCESS | | GOOD | | + * | INIT | | NETWORK | | CONNECT | + * | +-------------> CHECK +---------------------> +---------+ + * | | | | | | | + * | | | | | | | + * +------^-------+ +------^-------+ +------+-------+ | + * | | | | + * | | CONNECT FAIL | | + * | | +--------------------------+ | + * | | | CONNECTED | + * | RECONNECT | | | + * | | | | + * | | +------v-------+ +--------------+ | + * | REINITIALIZE | | | | | | + * | +---+ | DISCONNECT | | | + * | | DISCONNECTED | | CONNECTED | | + * | | <--------------+ <------+ + * +--------------------------------+ | | | + * | | | | + * +--------------+ +---^------+---+ + * | |(TELEMETRY | + * | | C2D | + * | | COMMAND | METHOD | + * +------+ PROPERTIES | DEVICE TWIN) + * + * + * + */ +VOID sample_connection_monitor(NX_IP *ip_ptr, NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT connection_status, + UINT (*iothub_init)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)) +{ +UINT loop = NX_TRUE; +ULONG gateway_address; + + /* Check parameters. */ + if ((ip_ptr == NX_NULL) || (hub_client_ptr == NX_NULL) || (iothub_init == NX_NULL)) + { + return; + } + + /* Check if connected. */ + if (connection_status == NX_SUCCESS) + { + + /* Reset the exponential. */ + exponential_backoff_reset(); + } + else + { + + /* Disconnect. */ + if (connection_status != NX_AZURE_IOT_NOT_INITIALIZED) + { + nx_azure_iot_hub_client_disconnect(hub_client_ptr); + } + + /* Recover. */ + while (loop) + { + switch (connection_status) + { + + /* Something bad has happened with client state, we need to re-initialize it. */ + case NX_DNS_QUERY_FAILED : + case NXD_MQTT_ERROR_BAD_USERNAME_PASSWORD : + case NXD_MQTT_ERROR_NOT_AUTHORIZED : + { + + /* Deinitialize iot hub client. */ + nx_azure_iot_hub_client_deinitialize(hub_client_ptr); + } + /* fallthrough */ + + case NX_AZURE_IOT_NOT_INITIALIZED: + { + if (iothub_init_count++) + { + printf("Re-initializing iothub connection, after backoff\r\n"); + tx_thread_sleep(exponential_backoff_with_jitter()); + } + + /* Initialize iot hub. */ + if (iothub_init(hub_client_ptr)) + { + connection_status = NX_AZURE_IOT_NOT_INITIALIZED; + } + else + { + + /* Wait for network. */ + while (nx_ip_gateway_address_get(ip_ptr, &gateway_address)) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + } + + /* Connect to iot hub. */ + connection_status = nx_azure_iot_hub_client_connect(hub_client_ptr, NX_FALSE, NX_WAIT_FOREVER); + } + } + break; + + case NX_AZURE_IOT_SAS_TOKEN_EXPIRED: + { + printf("SAS token expired\r\n"); + } + /* fallthrough */ + + default : + { + printf("Reconnecting iothub, after backoff\r\n"); + + tx_thread_sleep(exponential_backoff_with_jitter()); + + /* Wait for network. */ + while (nx_ip_gateway_address_get(ip_ptr, &gateway_address)) + { + tx_thread_sleep(NX_IP_PERIODIC_RATE); + } + + connection_status = nx_azure_iot_hub_client_connect(hub_client_ptr, NX_FALSE, NX_WAIT_FOREVER); + } + break; + } + + /* Check status. */ + if (connection_status == NX_SUCCESS) + { + return; + } + } + } +} diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c index 7b4faac4..c5db826e 100644 --- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c +++ b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_pnp.c @@ -13,8 +13,7 @@ #include "nx_api.h" #include "nx_azure_iot_hub_client.h" -#include "nx_azure_iot_json_reader.h" -#include "nx_azure_iot_json_writer.h" +#include "nx_azure_iot_hub_client_properties.h" #include "nx_azure_iot_provisioning_client.h" /* These are sample files, user can build their own certificate and ciphersuites. */ @@ -22,42 +21,21 @@ #include "nx_azure_iot_ciphersuites.h" #include "sample_config.h" -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC (10 * 60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC (3) -#endif /* SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT (60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT */ - +/* Define sample wait option. */ #ifndef SAMPLE_WAIT_OPTION #define SAMPLE_WAIT_OPTION (NX_NO_WAIT) #endif /* SAMPLE_WAIT_OPTION */ -/* Sample events. */ +/* Define sample events. */ #define SAMPLE_ALL_EVENTS ((ULONG)0xFFFFFFFF) -#define SAMPLE_CONNECT_EVENT ((ULONG)0x00000001) -#define SAMPLE_INITIALIZATION_EVENT ((ULONG)0x00000002) -#define SAMPLE_METHOD_MESSAGE_EVENT ((ULONG)0x00000004) -#define SAMPLE_DEVICE_TWIN_GET_EVENT ((ULONG)0x00000008) -#define SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT ((ULONG)0x00000010) -#define SAMPLE_TELEMETRY_SEND_EVENT ((ULONG)0x00000020) -#define SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT ((ULONG)0x00000040) -#define SAMPLE_DISCONNECT_EVENT ((ULONG)0x00000080) -#define SAMPLE_RECONNECT_EVENT ((ULONG)0x00000100) -#define SAMPLE_CONNECTED_EVENT ((ULONG)0x00000200) - -/* Sample states. */ -#define SAMPLE_STATE_NONE (0) -#define SAMPLE_STATE_INIT (1) -#define SAMPLE_STATE_CONNECTING (2) -#define SAMPLE_STATE_CONNECT (3) -#define SAMPLE_STATE_CONNECTED (4) -#define SAMPLE_STATE_DISCONNECTED (5) +#define SAMPLE_CONNECTED_EVENT ((ULONG)0x00000001) +#define SAMPLE_DISCONNECT_EVENT ((ULONG)0x00000002) +#define SAMPLE_PERIODIC_EVENT ((ULONG)0x00000004) +#define SAMPLE_TELEMETRY_SEND_EVENT ((ULONG)0x00000008) +#define SAMPLE_COMMAND_RECEIVE_EVENT ((ULONG)0x00000010) +#define SAMPLE_PROPERTIES_RECEIVE_EVENT ((ULONG)0x00000020) +#define SAMPLE_WRITABLE_PROPERTIES_RECEIVE_EVENT ((ULONG)0x00000040) +#define SAMPLE_REPORTED_PROPERTIES_SEND_EVENT ((ULONG)0x00000080) #define SAMPLE_DEAFULT_START_TEMP_CELSIUS (22) #define DOUBLE_DECIMAL_PLACE_DIGITS (2) @@ -65,37 +43,30 @@ #define SAMPLE_COMMAND_SUCCESS_STATUS (200) #define SAMPLE_COMMAND_ERROR_STATUS (500) -#define SAMPLE_PNP_MODEL_ID "dtmi:com:example:Thermostat;1" +#define SAMPLE_PNP_MODEL_ID "dtmi:com:example:Thermostat;3" #define SAMPLE_PNP_DPS_PAYLOAD "{\"modelId\":\"" SAMPLE_PNP_MODEL_ID "\"}" -/* Define Sample context. */ -typedef struct SAMPLE_CONTEXT_STRUCT -{ - UINT state; - UINT action_result; - ULONG last_periodic_action_tick; - - TX_EVENT_FLAGS_GROUP sample_events; +/* Generally, IoTHub Client and DPS Client do not run at the same time, user can use union as below to + share the memory between IoTHub Client and DPS Client. - /* Generally, IoTHub Client and DPS Client do not run at the same time, user can use union as below to - share the memory between IoTHub Client and DPS Client. + NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ +typedef union SAMPLE_CLIENT_UNION +{ + NX_AZURE_IOT_HUB_CLIENT iothub_client; - NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ - union SAMPLE_CLIENT_UNION - { - NX_AZURE_IOT_HUB_CLIENT iothub_client; #ifdef ENABLE_DPS_SAMPLE - NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; + NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; #endif /* ENABLE_DPS_SAMPLE */ - } client; + +} SAMPLE_CLIENT; + +static SAMPLE_CLIENT client; #define iothub_client client.iothub_client #ifdef ENABLE_DPS_SAMPLE #define prov_client client.prov_client #endif /* ENABLE_DPS_SAMPLE */ -} SAMPLE_CONTEXT; - void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)); #ifdef ENABLE_DPS_SAMPLE @@ -106,6 +77,8 @@ static UINT sample_dps_entry(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, /* Define Azure RTOS TLS info. */ static NX_SECURE_X509_CERT root_ca_cert; +static NX_SECURE_X509_CERT root_ca_cert_2; +static NX_SECURE_X509_CERT root_ca_cert_3; static UCHAR nx_azure_iot_tls_metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE]; static ULONG nx_azure_iot_thread_stack[NX_AZURE_IOT_STACK_SIZE / sizeof(ULONG)]; @@ -128,20 +101,19 @@ static UCHAR sample_iothub_device_id[SAMPLE_MAX_BUFFER]; /* Define the prototypes for AZ IoT. */ static NX_AZURE_IOT nx_azure_iot; -static SAMPLE_CONTEXT sample_context; -static volatile UINT sample_connection_status = NX_NOT_CONNECTED; -static UINT exponential_retry_count; +static TX_EVENT_FLAGS_GROUP sample_events; +static TX_TIMER sample_timer; +static volatile UINT sample_connection_status = NX_AZURE_IOT_NOT_INITIALIZED; +static volatile ULONG sample_periodic_counter = 0; /* Telemetry. */ static const CHAR telemetry_name[] = "temperature"; /* Device command. */ -static const CHAR report_method_name[] = "getMaxMinReport"; +static const CHAR report_command_name[] = "getMaxMinReport"; -/* Twin properties. */ -static const CHAR desired_temp_property_name[] = "targetTemperature"; -static const CHAR desired_property_name[] = "desired"; -static const CHAR desired_version_property_name[] = "$version"; +/* Device properties. */ +static const CHAR writable_temp_property_name[] = "targetTemperature"; static const CHAR reported_max_temp_since_last_reboot[] = "maxTempSinceLastReboot"; static const CHAR report_max_temp_name[] = "maxTemp"; static const CHAR report_min_temp_name[] = "minTemp"; @@ -149,10 +121,6 @@ static const CHAR report_avg_temp_name[] = "avgTemp"; static const CHAR report_start_time_name[] = "startTime"; static const CHAR report_end_time_name[] = "endTime"; static const CHAR reported_temp_property_name[] = "targetTemperature"; -static const CHAR reported_value_property_name[] = "value"; -static const CHAR reported_status_property_name[] = "ac"; -static const CHAR reported_version_property_name[] = "av"; -static const CHAR reported_description_property_name[] = "ad"; static const CHAR temp_response_description[] = "success"; /* Fake device data. */ @@ -167,163 +135,114 @@ static double device_min_temp = SAMPLE_DEAFULT_START_TEMP_CELSIUS; static double device_avg_temp = SAMPLE_DEAFULT_START_TEMP_CELSIUS; static UCHAR scratch_buffer[256]; -/* Move reader to the value of property name. */ -static UINT sample_json_child_token_move(NX_AZURE_IOT_JSON_READER *json_reader, - UCHAR *property_name_ptr, UINT property_name_len) -{ - while (nx_azure_iot_json_reader_next_token(json_reader) == NX_AZURE_IOT_SUCCESS) - { - if ((nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_PROPERTY_NAME) && - nx_azure_iot_json_reader_token_is_text_equal(json_reader, - property_name_ptr, - property_name_len)) - { - if (nx_azure_iot_json_reader_next_token(json_reader)) - { - printf("Failed to read next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - return(NX_AZURE_IOT_SUCCESS); - } - else if (nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) - { - if (nx_azure_iot_json_reader_skip_children(json_reader)) - { - printf("Failed to skip child of complex object\r\n"); - return(NX_NOT_SUCCESSFUL); - } - } - else if (nx_azure_iot_json_reader_token_type(json_reader) == NX_AZURE_IOT_READER_TOKEN_END_OBJECT) - { - return(NX_AZURE_IOT_NOT_FOUND); - } - } +/* Include the connection monitor function from sample_azure_iot_embedded_sdk_connect.c. */ +extern VOID sample_connection_monitor(NX_IP *ip_ptr, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, UINT connection_status, + UINT (*iothub_init)(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr)); - return(NX_AZURE_IOT_NOT_FOUND); -} +#ifndef DISABLE_ADU_SAMPLE +/* Include the adu start function from sample_azure_iot_embedded_sdk_adu.c. */ +extern VOID sample_adu_start(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr); +#endif /* DISABLE_ADU_SAMPLE */ -/* Build reported property JSON. */ -static UINT sample_build_reported_property(NX_AZURE_IOT_JSON_WRITER *json_builder_ptr, double temp) -{ -UINT ret; - - if (nx_azure_iot_json_writer_append_begin_object(json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_double_value(json_builder_ptr, - (UCHAR *)reported_max_temp_since_last_reboot, - sizeof(reported_max_temp_since_last_reboot) - 1, - temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_end_object(json_builder_ptr)) - { - ret = 1; - printf("Failed to build reported property\r\n"); - } - else - { - ret = 0; - } - - return(ret); -} - -/* Send desired property response as reported property. */ -static VOID sample_send_target_temperature_report(SAMPLE_CONTEXT *context, double current_device_temp_value, - UINT status, UINT version, UCHAR *description_ptr, +/* Send writable properties response as reported property. */ +static VOID sample_send_target_temperature_report(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, double current_device_temp_value, + UINT status, ULONG version, UCHAR *description_ptr, UINT description_len) { -NX_AZURE_IOT_JSON_WRITER json_builder; -UINT bytes_copied; +NX_AZURE_IOT_JSON_WRITER json_writer; +NX_PACKET *packet_ptr; UINT response_status; UINT request_id; -ULONG reported_property_version; - if (nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) + if (nx_azure_iot_hub_client_reported_properties_create(hub_client_ptr, + &packet_ptr, NX_WAIT_FOREVER)) { printf("Failed to build reported response\r\n"); return; } - if (nx_azure_iot_json_writer_append_begin_object(&json_builder) || - nx_azure_iot_json_writer_append_property_name(&json_builder, - (UCHAR *)reported_temp_property_name, - sizeof(reported_temp_property_name) - 1) || - nx_azure_iot_json_writer_append_begin_object(&json_builder) || - nx_azure_iot_json_writer_append_property_with_double_value(&json_builder, - (UCHAR *)reported_value_property_name, - sizeof(reported_value_property_name) - 1, - current_device_temp_value, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_int32_value(&json_builder, - (UCHAR *)reported_status_property_name, - sizeof(reported_status_property_name) - 1, - (int32_t)status) || - nx_azure_iot_json_writer_append_property_with_int32_value(&json_builder, - (UCHAR *)reported_version_property_name, - sizeof(reported_version_property_name) - 1, - (int32_t)version) || - nx_azure_iot_json_writer_append_property_with_string_value(&json_builder, - (UCHAR *)reported_description_property_name, - sizeof(reported_description_property_name) - 1, - description_ptr, description_len) || - nx_azure_iot_json_writer_append_end_object(&json_builder) || - nx_azure_iot_json_writer_append_end_object(&json_builder)) - { - nx_azure_iot_json_writer_deinit(&json_builder); + if (nx_azure_iot_json_writer_init(&json_writer, packet_ptr, NX_WAIT_FOREVER)) + { printf("Failed to build reported response\r\n"); + nx_packet_release(packet_ptr); + return; + } + + if (nx_azure_iot_json_writer_append_begin_object(&json_writer) || + nx_azure_iot_hub_client_reported_properties_status_begin(hub_client_ptr, + &json_writer, (const UCHAR *)reported_temp_property_name, + sizeof(reported_temp_property_name) - 1, + status, version, + description_ptr, description_len) || + nx_azure_iot_json_writer_append_double(&json_writer, + current_device_temp_value, + DOUBLE_DECIMAL_PLACE_DIGITS) || + nx_azure_iot_hub_client_reported_properties_status_end(hub_client_ptr, &json_writer) || + nx_azure_iot_json_writer_append_end_object(&json_writer)) + { + printf("Failed to build reported response\r\n"); + nx_packet_release(packet_ptr); } else { - bytes_copied = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if (nx_azure_iot_hub_client_device_twin_reported_properties_send(&(context -> iothub_client), - scratch_buffer, bytes_copied, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE))) + if (nx_azure_iot_hub_client_reported_properties_send(hub_client_ptr, + packet_ptr, &request_id, + &response_status, NX_NULL, + (5 * NX_IP_PERIODIC_RATE))) { printf("Failed to send reported response\r\n"); + nx_packet_release(packet_ptr); } - nx_azure_iot_json_writer_deinit(&json_builder); } } -/* Parses device twin document. */ -static UINT sample_parse_desired_temp_property(SAMPLE_CONTEXT *context, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, - UINT is_partial) +/* Parses writable properties document. */ +static UINT sample_parse_writable_temp_property(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, + NX_AZURE_IOT_JSON_READER *json_reader_ptr, + UINT message_type, ULONG version) { double parsed_value; -UINT version; -NX_AZURE_IOT_JSON_READER copy_json_reader; - - if (nx_azure_iot_json_reader_next_token(json_reader_ptr)) - { - printf("Failed to move to next token\r\n"); - return(NX_NOT_SUCCESSFUL); - } +UINT status; +const UCHAR *component_name_ptr; +USHORT component_length = 0; + + while ((status = nx_azure_iot_hub_client_properties_component_property_next_get(hub_client_ptr, + json_reader_ptr, + message_type, + NX_AZURE_IOT_HUB_CLIENT_PROPERTY_WRITABLE, + &component_name_ptr, &component_length)) == NX_AZURE_IOT_SUCCESS) + { + if (nx_azure_iot_json_reader_token_is_text_equal(json_reader_ptr, + (UCHAR *)writable_temp_property_name, + sizeof(writable_temp_property_name) - 1)) + { + if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr)) || + (status = nx_azure_iot_json_reader_token_double_get(json_reader_ptr, &parsed_value))) + { + return(status); + } - if (!is_partial && sample_json_child_token_move(json_reader_ptr, - (UCHAR *)desired_property_name, - sizeof(desired_property_name) - 1)) - { - printf("Failed to get desired property\r\n"); - return(NX_NOT_SUCCESSFUL); - } + break; + } + else + { - copy_json_reader = *json_reader_ptr; - if (sample_json_child_token_move(©_json_reader, - (UCHAR *)desired_version_property_name, - sizeof(desired_version_property_name) - 1) || - nx_azure_iot_json_reader_token_int32_get(©_json_reader, (int32_t *)&version)) - { - printf("Failed to get version\r\n"); - return(NX_NOT_SUCCESSFUL); + /* The JSON reader must be advanced regardless of whether the property + is of interest or not. */ + nx_azure_iot_json_reader_next_token(json_reader_ptr); + + /* Skip children in case the property value is an object. */ + if (nx_azure_iot_json_reader_token_type(json_reader_ptr) == NX_AZURE_IOT_READER_TOKEN_BEGIN_OBJECT) + { + nx_azure_iot_json_reader_skip_children(json_reader_ptr); + } + nx_azure_iot_json_reader_next_token(json_reader_ptr); + } } - if (sample_json_child_token_move(json_reader_ptr, - (UCHAR *)desired_temp_property_name, - sizeof(desired_temp_property_name) - 1) || - nx_azure_iot_json_reader_token_double_get(json_reader_ptr, &parsed_value)) + if (status) { - return(NX_NOT_SUCCESSFUL); + return(status); } current_device_temp = parsed_value; @@ -342,26 +261,26 @@ NX_AZURE_IOT_JSON_READER copy_json_reader; device_temperature_avg_total += current_device_temp; device_avg_temp = device_temperature_avg_total / device_temperature_avg_count; - sample_send_target_temperature_report(context, current_device_temp, 200, - (UINT)version, (UCHAR *)temp_response_description, + sample_send_target_temperature_report(hub_client_ptr, current_device_temp, 200, + version, (UCHAR *)temp_response_description, sizeof(temp_response_description) - 1); return(NX_AZURE_IOT_SUCCESS); } -/* sample direct method implementation. */ +/* sample command implementation. */ static UINT sample_get_maxmin_report(NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) + NX_AZURE_IOT_JSON_WRITER *out_json_writer_ptr) { UINT status; UCHAR *start_time = (UCHAR *)fake_start_report_time; UINT start_time_len = sizeof(fake_start_report_time) - 1; UCHAR time_buf[32]; - if (json_reader_ptr != NX_NULL) + /* Check for start time if present */ + if ((status = nx_azure_iot_json_reader_next_token(json_reader_ptr)) == NX_AZURE_IOT_SUCCESS) { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, + if (nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, sizeof(time_buf), &start_time_len)) { return(NX_NOT_SUCCESSFUL); @@ -369,30 +288,37 @@ UCHAR time_buf[32]; start_time = time_buf; } - - if (nx_azure_iot_json_writer_append_begin_object(out_json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + else + { + if (status != NX_AZURE_IOT_EMPTY_JSON) + { + return(NX_NOT_SUCCESSFUL); + } + } + + if (nx_azure_iot_json_writer_append_begin_object(out_json_writer_ptr) || + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_max_temp_name, sizeof(report_max_temp_name) - 1, device_max_temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_min_temp_name, sizeof(report_min_temp_name) - 1, device_min_temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_double_value(out_json_writer_ptr, (UCHAR *)report_avg_temp_name, sizeof(report_avg_temp_name) - 1, device_avg_temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_string_value(out_json_writer_ptr, (UCHAR *)report_start_time_name, sizeof(report_start_time_name) - 1, start_time, start_time_len) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, + nx_azure_iot_json_writer_append_property_with_string_value(out_json_writer_ptr, (UCHAR *)report_end_time_name, sizeof(report_end_time_name) - 1, (UCHAR *)fake_end_report_time, sizeof(fake_end_report_time) - 1) || - nx_azure_iot_json_writer_append_end_object(out_json_builder_ptr)) + nx_azure_iot_json_writer_append_end_object(out_json_writer_ptr)) { printf("Failed to build getMaxMinReport response \r\n"); status = NX_NOT_SUCCESSFUL; @@ -405,147 +331,46 @@ UCHAR time_buf[32]; return(status); } -static VOID printf_packet(NX_PACKET *packet_ptr) -{ - while (packet_ptr != NX_NULL) - { - printf("%.*s", (INT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr), - (CHAR *)packet_ptr -> nx_packet_prepend_ptr); - packet_ptr = packet_ptr -> nx_packet_next; - } -} - -static UINT exponential_backoff_with_jitter() -{ -double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); -UINT base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; -uint64_t delay; - - if (exponential_retry_count < (sizeof(UINT) * 8)) - { - delay = (uint64_t)((1 << exponential_retry_count) * SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC); - if (delay <= (UINT)(-1)) - { - base_delay = (UINT)delay; - } - } - - if (base_delay > SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC) - { - base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; - } - else - { - exponential_retry_count++; - } - - return((UINT)(base_delay * (1 + jitter_percent)) * NX_IP_PERIODIC_RATE) ; -} - -static VOID exponential_backoff_reset() -{ - exponential_retry_count = 0; -} - static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status) { NX_PARAMETER_NOT_USED(hub_client_ptr); - - sample_connection_status = status; - if (status) { printf("Disconnected from IoTHub!: error code = 0x%08x\r\n", status); - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_DISCONNECT_EVENT, TX_OR); + tx_event_flags_set(&sample_events, SAMPLE_DISCONNECT_EVENT, TX_OR); } else { printf("Connected to IoTHub.\r\n"); - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_CONNECTED_EVENT, TX_OR); - exponential_backoff_reset(); + tx_event_flags_set(&sample_events, SAMPLE_CONNECTED_EVENT, TX_OR); } -} -static VOID message_receive_callback_twin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) -{ -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; - - NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_GET_EVENT, TX_OR); + sample_connection_status = status; } -static VOID message_receive_callback_method(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_properties(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) { -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_METHOD_MESSAGE_EVENT, TX_OR); + NX_PARAMETER_NOT_USED(context); + tx_event_flags_set(&sample_events, SAMPLE_PROPERTIES_RECEIVE_EVENT, TX_OR); } -static VOID message_receive_callback_desire_property(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) +static VOID message_receive_callback_command(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) { -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; - NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT, TX_OR); -} - -static VOID sample_connect_action(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_CONNECT) - { - return; - } - - context -> action_result = nx_azure_iot_hub_client_connect(&(context -> iothub_client), NX_FALSE, SAMPLE_WAIT_OPTION); - - if (context -> action_result == NX_AZURE_IOT_CONNECTING) - { - context -> state = SAMPLE_STATE_CONNECTING; - } - else if (context -> action_result != NX_SUCCESS) - { - sample_connection_status = context -> action_result; - context -> state = SAMPLE_STATE_DISCONNECTED; - } - else - { - context -> state = SAMPLE_STATE_CONNECTED; - - context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); - } + NX_PARAMETER_NOT_USED(context); + tx_event_flags_set(&(sample_events), SAMPLE_COMMAND_RECEIVE_EVENT, TX_OR); } -static VOID sample_disconnect_action(SAMPLE_CONTEXT *context) +static VOID message_receive_callback_writable_properties(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) { - if (context -> state != SAMPLE_STATE_CONNECTED && - context -> state != SAMPLE_STATE_CONNECTING) - { - return; - } - - context -> action_result = nx_azure_iot_hub_client_disconnect(&(context -> iothub_client)); - context -> state = SAMPLE_STATE_DISCONNECTED; -} - -static VOID sample_connected_action(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_CONNECTING) - { - return; - } - - context -> state = SAMPLE_STATE_CONNECTED; - - context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); + NX_PARAMETER_NOT_USED(hub_client_ptr); + NX_PARAMETER_NOT_USED(context); + tx_event_flags_set(&(sample_events), SAMPLE_WRITABLE_PROPERTIES_RECEIVE_EVENT, TX_OR); } -static VOID sample_initialize_iothub(SAMPLE_CONTEXT *context) +static UINT sample_initialize_iothub(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) { UINT status; #ifdef ENABLE_DPS_SAMPLE @@ -559,22 +384,15 @@ UCHAR *iothub_device_id = (UCHAR *)DEVICE_ID; UINT iothub_hostname_length = sizeof(HOST_NAME) - 1; UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; #endif /* ENABLE_DPS_SAMPLE */ -NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); - - if (context -> state != SAMPLE_STATE_INIT) - { - return; - } #ifdef ENABLE_DPS_SAMPLE /* Run DPS. */ - if ((status = sample_dps_entry(&(context -> prov_client), &iothub_hostname, &iothub_hostname_length, + if ((status = sample_dps_entry(&prov_client, &iothub_hostname, &iothub_hostname_length, &iothub_device_id, &iothub_device_id_length))) { printf("Failed on sample_dps_entry!: error code = 0x%08x\r\n", status); - context -> action_result = status; - return; + return(status); } #endif /* ENABLE_DPS_SAMPLE */ @@ -585,7 +403,7 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); if ((status = nx_azure_iot_hub_client_initialize(iothub_client_ptr, &nx_azure_iot, iothub_hostname, iothub_hostname_length, iothub_device_id, iothub_device_id_length, - (UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, + (const UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, _nx_azure_iot_tls_supported_crypto, _nx_azure_iot_tls_supported_crypto_size, _nx_azure_iot_tls_ciphersuite_map, @@ -595,18 +413,35 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); &root_ca_cert))) { printf("Failed on nx_azure_iot_hub_client_initialize!: error code = 0x%08x\r\n", status); - context -> action_result = status; - return; + return(status); + } + + /* Set the model id. */ + if ((status = nx_azure_iot_hub_client_model_id_set(iothub_client_ptr, + (const UCHAR *)SAMPLE_PNP_MODEL_ID, + sizeof(SAMPLE_PNP_MODEL_ID) - 1))) + { + printf("Failed on nx_azure_iot_hub_client_model_id_set!: error code = 0x%08x\r\n", status); + } + + /* Add more CA certificates. */ + else if ((status = nx_azure_iot_hub_client_trusted_cert_add(iothub_client_ptr, &root_ca_cert_2))) + { + printf("Failed on nx_azure_iot_hub_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + else if ((status = nx_azure_iot_hub_client_trusted_cert_add(iothub_client_ptr, &root_ca_cert_3))) + { + printf("Failed on nx_azure_iot_hub_client_trusted_cert_add!: error code = 0x%08x\r\n", status); } #if (USE_DEVICE_CERTIFICATE == 1) /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, - (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, - NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, - DEVICE_KEY_TYPE))) + else if ((status = nx_secure_x509_certificate_initialize(&device_certificate, + (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, + NX_NULL, 0, + (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, + DEVICE_KEY_TYPE))) { printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); } @@ -619,52 +454,59 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); #else /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, - (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) + else if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, + (UCHAR *)DEVICE_SYMMETRIC_KEY, + sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!\r\n"); } #endif /* USE_DEVICE_CERTIFICATE */ - /* Set connection status callback. */ - else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, - connection_status_callback))) +#ifdef NXD_MQTT_OVER_WEBSOCKET + + /* Enable MQTT over WebSocket to connect to IoT Hub */ + else if ((status = nx_azure_iot_hub_client_websocket_enable(iothub_client_ptr))) { - printf("Failed on connection_status_callback!\r\n"); + printf("Failed on nx_azure_iot_hub_client_websocket_enable!\r\n"); } - else if ((status = nx_azure_iot_hub_client_direct_method_enable(iothub_client_ptr))) +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + + /* Enable command and properties features. */ + else if ((status = nx_azure_iot_hub_client_command_enable(iothub_client_ptr))) { - printf("Direct method receive enable failed!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_hub_client_command_enable!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_device_twin_enable(iothub_client_ptr))) + else if ((status = nx_azure_iot_hub_client_properties_enable(iothub_client_ptr))) { - printf("device twin enabled failed!: error code = 0x%08x\r\n", status); + printf("Failed on nx_azure_iot_hub_client_properties_enable!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - message_receive_callback_twin, - (VOID *)context))) + + /* Set connection status callback. */ + else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, + connection_status_callback))) { - printf("device twin callback set!: error code = 0x%08x\r\n", status); + printf("Failed on connection_status_callback!\r\n"); } else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, - message_receive_callback_method, - (VOID *)context))) + NX_AZURE_IOT_HUB_COMMAND, + message_receive_callback_command, + NX_NULL))) { - printf("device method callback set!: error code = 0x%08x\r\n", status); + printf("device command callback set!: error code = 0x%08x\r\n", status); } else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, - message_receive_callback_desire_property, - (VOID *)context))) + NX_AZURE_IOT_HUB_PROPERTIES, + message_receive_callback_properties, + NX_NULL))) { - printf("device twin desired property callback set!: error code = 0x%08x\r\n", status); + printf("device properties callback set!: error code = 0x%08x\r\n", status); } - else if ((status = nx_azure_iot_hub_client_model_id_set(iothub_client_ptr, (UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1))) + else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, + NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES, + message_receive_callback_writable_properties, + NX_NULL))) { - printf("digital twin modelId set!: error code = 0x%08x\r\n", status); + printf("device writable properties callback set!: error code = 0x%08x\r\n", status); } if (status) @@ -672,231 +514,155 @@ NX_AZURE_IOT_HUB_CLIENT* iothub_client_ptr = &(context -> iothub_client); nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); } - context -> action_result = status; - - if (status == NX_AZURE_IOT_SUCCESS) - { - context -> state = SAMPLE_STATE_CONNECT; - } + return(status); } -static VOID sample_connection_error_recover(SAMPLE_CONTEXT *context) +static void sample_command_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { - if (context -> state != SAMPLE_STATE_DISCONNECTED) - { - return; - } +UINT status = 0; +const UCHAR *component_name_ptr; +USHORT component_name_length; +const UCHAR *command_name_ptr; +USHORT command_name_length; +USHORT context_length; +VOID *context_ptr; +UINT dm_status = 404; +UINT response_payload = 0; +NX_PACKET *packet_ptr; +NX_AZURE_IOT_JSON_READER json_reader; +NX_AZURE_IOT_JSON_WRITER json_writer; - switch (sample_connection_status) + /* Loop to receive command message. */ + while (1) { - case NX_AZURE_IOT_SUCCESS: - { - printf("already connected\r\n"); - } - break; - /* Something bad has happened with client state, we need to re-initialize it. */ - case NX_DNS_QUERY_FAILED : - case NXD_MQTT_ERROR_BAD_USERNAME_PASSWORD : - case NXD_MQTT_ERROR_NOT_AUTHORIZED : - { - printf("re-initializing iothub connection, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - nx_azure_iot_hub_client_deinitialize(&(context -> iothub_client)); - context -> state = SAMPLE_STATE_INIT; - } - break; - - default : - { - printf("reconnecting iothub, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - context -> state = SAMPLE_STATE_CONNECT; - } - break; - } -} - -static VOID sample_trigger_action(SAMPLE_CONTEXT *context) -{ - switch (context -> state) - { - case SAMPLE_STATE_INIT: + if (sample_connection_status != NX_SUCCESS) { - tx_event_flags_set(&(context -> sample_events), SAMPLE_INITIALIZATION_EVENT, TX_OR); + return; } - break; - case SAMPLE_STATE_CONNECT: + if ((status = nx_azure_iot_hub_client_command_message_receive(hub_client_ptr, + &component_name_ptr, &component_name_length, + &command_name_ptr, &command_name_length, + &context_ptr, &context_length, + &packet_ptr, NX_NO_WAIT))) { - tx_event_flags_set(&(context -> sample_events), SAMPLE_CONNECT_EVENT, TX_OR); + return; } - break; - case SAMPLE_STATE_CONNECTED: - { - if ((tx_time_get() - context -> last_periodic_action_tick) >= (5 * NX_IP_PERIODIC_RATE)) - { - context -> last_periodic_action_tick = tx_time_get(); - tx_event_flags_set(&(context -> sample_events), SAMPLE_TELEMETRY_SEND_EVENT, TX_OR); - tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT, TX_OR); - } - } - break; + printf("Received command: %.*s", (INT)command_name_length, (CHAR *)command_name_ptr); + printf("\r\n"); - case SAMPLE_STATE_DISCONNECTED: + if ((status = nx_azure_iot_json_reader_init(&json_reader, + packet_ptr))) { - tx_event_flags_set(&(context -> sample_events), SAMPLE_RECONNECT_EVENT, TX_OR); + printf("Failed to initialize json reader \r\n"); + nx_packet_release(packet_ptr); + return; } - break; - } -} - -static void sample_direct_method_action(SAMPLE_CONTEXT *sample_context_ptr) -{ -NX_PACKET *packet_ptr; -UINT status = 0; -USHORT method_name_length; -const UCHAR *method_name_ptr; -USHORT context_length; -VOID *context_ptr; -UINT dm_status = 404; -UINT response_payload = 0; -NX_AZURE_IOT_JSON_READER json_reader; -NX_AZURE_IOT_JSON_READER *json_reader_ptr = NX_NULL; -NX_AZURE_IOT_JSON_WRITER json_builder; - - if (sample_context_ptr -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&(sample_context_ptr -> iothub_client), - &method_name_ptr, &method_name_length, - &context_ptr, &context_length, - &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Direct method receive failed!: error code = 0x%08x\r\n", status); - return; - } - - printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); - printf_packet(packet_ptr); - printf("\r\n"); - - if ((method_name_length == (sizeof(report_method_name) - 1)) && - (memcmp((VOID *)method_name_ptr, (VOID *)report_method_name, sizeof(report_method_name) - 1) == 0)) - { - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, + if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer)))) { - printf("Failed to initalize json builder response \r\n"); + printf("Failed to initialize json writer response \r\n"); nx_packet_release(packet_ptr); return; } - if (packet_ptr ->nx_packet_length != 0) + if ((command_name_length == (sizeof(report_command_name) - 1)) && + (memcmp((VOID *)command_name_ptr, (VOID *)report_command_name, + sizeof(report_command_name) - 1) == 0)) { - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) + if (sample_get_maxmin_report(&json_reader, &json_writer) != NX_AZURE_IOT_SUCCESS) { - printf("Failed to init json reader!: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); + dm_status = SAMPLE_COMMAND_ERROR_STATUS; } else { - json_reader_ptr = &json_reader; + dm_status = SAMPLE_COMMAND_SUCCESS_STATUS; + response_payload = nx_azure_iot_json_writer_get_bytes_used(&json_writer); } } - else - { - nx_packet_release(packet_ptr); - status = NX_AZURE_IOT_SUCCESS; - } - if (status != NX_AZURE_IOT_SUCCESS) - { - dm_status = SAMPLE_COMMAND_ERROR_STATUS; - } - else if (sample_get_maxmin_report(json_reader_ptr, &json_builder) != NX_AZURE_IOT_SUCCESS) - { - dm_status = SAMPLE_COMMAND_ERROR_STATUS; - } - else - { - dm_status = SAMPLE_COMMAND_SUCCESS_STATUS; - response_payload = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - } + nx_packet_release(packet_ptr); - if (json_reader_ptr) + if ((status = nx_azure_iot_hub_client_command_message_response(hub_client_ptr, dm_status, + context_ptr, context_length, scratch_buffer, + response_payload, NX_WAIT_FOREVER))) { - nx_azure_iot_json_reader_deinit(json_reader_ptr); + printf("Command response failed!: error code = 0x%08x\r\n", status); } - - nx_azure_iot_json_writer_deinit(&json_builder); - } - else - { - nx_packet_release(packet_ptr); - } - - if ((status = nx_azure_iot_hub_client_direct_method_message_response(&(sample_context_ptr -> iothub_client), dm_status, - context_ptr, context_length, scratch_buffer, - response_payload, NX_WAIT_FOREVER))) - { - printf("Direct method response failed!: error code = 0x%08x\r\n", status); } } -static void sample_device_twin_desired_property_action(SAMPLE_CONTEXT *context) +static void sample_writable_properties_receive_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -NX_PACKET *packet_ptr; UINT status = 0; +NX_PACKET *packet_ptr; NX_AZURE_IOT_JSON_READER json_reader; +ULONG properties_version; - if (context -> state != SAMPLE_STATE_CONNECTED) + if (sample_connection_status != NX_SUCCESS) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_hub_client_writable_properties_receive(hub_client_ptr, + &packet_ptr, + NX_WAIT_FOREVER))) { - printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); + printf("Receive writable property receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive desired property: "); - printf_packet(packet_ptr); + printf("Received writable property"); printf("\r\n"); - if (nx_azure_iot_json_reader_init(&json_reader, packet_ptr)) + if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) + { + printf("Init json reader failed!: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); + return; + } + + /* Get the version. */ + if ((status = nx_azure_iot_hub_client_properties_version_get(hub_client_ptr, &json_reader, + NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES, + &properties_version))) { - printf("Failed to initialize json reader\r\n"); + printf("Properties version get failed!: error code = 0x%08x\r\n", status); nx_packet_release(packet_ptr); return; } - if (sample_parse_desired_temp_property(context, &json_reader, NX_TRUE) != NX_AZURE_IOT_SUCCESS) + if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) + { + printf("Init json reader failed!: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); + return; + } + + status = sample_parse_writable_temp_property(hub_client_ptr, &json_reader, + NX_AZURE_IOT_HUB_WRITABLE_PROPERTIES, properties_version); + if (status && (status != NX_AZURE_IOT_NOT_FOUND)) { printf("Failed to parse value\r\n"); } - nx_azure_iot_json_reader_deinit(&json_reader); + nx_packet_release(packet_ptr); } -static void sample_device_twin_reported_property_action(SAMPLE_CONTEXT *context) +static void sample_reported_properties_send_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status = 0; UINT response_status; UINT request_id; -UINT reported_properties_length; -NX_AZURE_IOT_JSON_WRITER json_builder; +NX_AZURE_IOT_JSON_WRITER json_writer; +NX_PACKET *packet_ptr; ULONG reported_property_version; - if (context -> state != SAMPLE_STATE_CONNECTED) + if (sample_connection_status != NX_SUCCESS) { return; } @@ -907,125 +673,154 @@ ULONG reported_property_version; return; } - if (nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) + if ((status = nx_azure_iot_hub_client_reported_properties_create(hub_client_ptr, + &packet_ptr, NX_WAIT_FOREVER))) { - printf("Failed to init json writer \r\n"); + printf("Failed create reported properties: error code = 0x%08x\r\n", status); + return; + } + + if ((status = nx_azure_iot_json_writer_init(&json_writer, packet_ptr, NX_WAIT_FOREVER))) + { + printf("Failed init json writer: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); return; } - if ((status = sample_build_reported_property(&json_builder, device_max_temp))) + if ((status = nx_azure_iot_json_writer_append_begin_object(&json_writer)) || + (status = nx_azure_iot_json_writer_append_property_with_double_value(&json_writer, + (const UCHAR *)reported_max_temp_since_last_reboot, + sizeof(reported_max_temp_since_last_reboot) - 1, + device_max_temp, DOUBLE_DECIMAL_PLACE_DIGITS)) || + (status = nx_azure_iot_json_writer_append_end_object(&json_writer))) { printf("Build reported property failed: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + nx_packet_release(packet_ptr); return; } - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(&(context -> iothub_client), - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) + if ((status = nx_azure_iot_hub_client_reported_properties_send(hub_client_ptr, + packet_ptr, + &request_id, &response_status, + &reported_property_version, + (5 * NX_IP_PERIODIC_RATE)))) { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); + printf("Reported properties failed!: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); return; } - nx_azure_iot_json_writer_deinit(&json_builder); - if ((response_status < 200) || (response_status >= 300)) { - printf("device twin report properties failed with code : %d\r\n", response_status); + printf("Reported properties failed with code : %d\r\n", response_status); return; } last_device_max_tem_reported = device_max_temp; } -static void sample_device_twin_get_action(SAMPLE_CONTEXT *context) +static void sample_properties_receive_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status = 0; NX_PACKET *packet_ptr; NX_AZURE_IOT_JSON_READER json_reader; +ULONG writable_properties_version; - if (context -> state != SAMPLE_STATE_CONNECTED) + if (sample_connection_status != NX_SUCCESS) { return; } - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_hub_client_properties_receive(hub_client_ptr, + &packet_ptr, + NX_WAIT_FOREVER))) { - printf("Twin receive failed!: error code = 0x%08x\r\n", status); + printf("Get all properties receive failed!: error code = 0x%08x\r\n", status); return; } - printf("Receive twin properties: "); - printf_packet(packet_ptr); + printf("Received all properties"); printf("\r\n"); - if (nx_azure_iot_json_reader_init(&json_reader, packet_ptr)) + if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) { - printf("Failed to initialize json reader\r\n"); + printf("Init json reader failed!: error code = 0x%08x\r\n", status); nx_packet_release(packet_ptr); return; } - if (sample_parse_desired_temp_property(context, &json_reader, NX_FALSE) != NX_AZURE_IOT_SUCCESS) + if ((status = nx_azure_iot_hub_client_properties_version_get(hub_client_ptr, &json_reader, + NX_AZURE_IOT_HUB_PROPERTIES, + &writable_properties_version))) + { + printf("Properties version get failed!: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); + return; + } + + if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) + { + printf("Init json reader failed!: error code = 0x%08x\r\n", status); + nx_packet_release(packet_ptr); + return; + } + + status = sample_parse_writable_temp_property(hub_client_ptr, &json_reader, + NX_AZURE_IOT_HUB_PROPERTIES, writable_properties_version); + if (status && (status != NX_AZURE_IOT_NOT_FOUND)) { printf("Failed to parse value\r\n"); } - nx_azure_iot_json_reader_deinit(&json_reader); + nx_packet_release(packet_ptr); } -static void sample_telemetry_action(SAMPLE_CONTEXT *context) +static void sample_telemetry_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { UINT status = 0; NX_PACKET *packet_ptr; -NX_AZURE_IOT_JSON_WRITER json_builder; +NX_AZURE_IOT_JSON_WRITER json_writer; UINT buffer_length; - if (context -> state != SAMPLE_STATE_CONNECTED) + if (sample_connection_status != NX_SUCCESS) { return; } /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_hub_client_telemetry_message_create(&(context -> iothub_client), &packet_ptr, NX_WAIT_FOREVER))) + if ((status = nx_azure_iot_hub_client_telemetry_message_create(hub_client_ptr, + &packet_ptr, + NX_WAIT_FOREVER))) { printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); return; } /* Build telemetry JSON payload. */ - if(nx_azure_iot_json_writer_with_buffer_init(&json_builder, scratch_buffer, sizeof(scratch_buffer))) + if(nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) { printf("Telemetry message failed to build message\r\n"); nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); return; } - if (nx_azure_iot_json_writer_append_begin_object(&json_builder) || - nx_azure_iot_json_writer_append_property_with_double_value(&json_builder, + if (nx_azure_iot_json_writer_append_begin_object(&json_writer) || + nx_azure_iot_json_writer_append_property_with_double_value(&json_writer, (UCHAR *)telemetry_name, sizeof(telemetry_name) - 1, current_device_temp, DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_end_object(&json_builder)) + nx_azure_iot_json_writer_append_end_object(&json_writer)) { printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_json_writer_deinit(&json_builder); nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); return; } - buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - nx_azure_iot_json_writer_deinit(&json_builder); - if ((status = nx_azure_iot_hub_client_telemetry_send(&(context -> iothub_client), packet_ptr, - (UCHAR *)scratch_buffer, buffer_length, SAMPLE_WAIT_OPTION))) + buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); + if ((status = nx_azure_iot_hub_client_telemetry_send(hub_client_ptr, packet_ptr, + (UCHAR *)scratch_buffer, buffer_length, + SAMPLE_WAIT_OPTION))) { printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); @@ -1065,11 +860,21 @@ UINT status; *iothub_hostname_length = sizeof(sample_iothub_hostname); *iothub_device_id_length = sizeof(sample_iothub_device_id); + /* Add more CA certificates. */ + if ((status = nx_azure_iot_provisioning_client_trusted_cert_add(prov_client_ptr, &root_ca_cert_2))) + { + printf("Failed on nx_azure_iot_provisioning_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + else if ((status = nx_azure_iot_provisioning_client_trusted_cert_add(prov_client_ptr, &root_ca_cert_3))) + { + printf("Failed on nx_azure_iot_provisioning_client_trusted_cert_add!: error code = 0x%08x\r\n", status); + } + #if (USE_DEVICE_CERTIFICATE == 1) /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) + else if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, + (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) { printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); } @@ -1082,12 +887,22 @@ UINT status; #else /* Set symmetric key. */ - if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(prov_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) + else if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(prov_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, + sizeof(DEVICE_SYMMETRIC_KEY) - 1))) { printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); } #endif /* USE_DEVICE_CERTIFICATE */ + +#ifdef NXD_MQTT_OVER_WEBSOCKET + + /* Enable MQTT over WebSocket. */ + else if ((status = nx_azure_iot_provisioning_client_websocket_enable(prov_client_ptr))) + { + printf("Failed on nx_azure_iot_provisioning_client_websocket_enable!\r\n"); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + else if ((status = nx_azure_iot_provisioning_client_registration_payload_set(prov_client_ptr, (UCHAR *)SAMPLE_PNP_DPS_PAYLOAD, sizeof(SAMPLE_PNP_DPS_PAYLOAD) - 1))) { @@ -1120,115 +935,45 @@ UINT status; } #endif /* ENABLE_DPS_SAMPLE */ -/** - * - * Sample Event loop - * - * - * +--------------+ +--------------+ +--------------+ +--------------+ - * | | INIT | | | | | | - * | | SUCCESS | | | | | +--------+ - * | INIT | | CONNECT | | CONNECTING | | CONNECTED | | (TELEMETRY | - * | +-----------> +----->+ +-------> | | METHOD | - * | | | | | | | <--------+ DEVICETWIN) - * | | | | | | | | - * +-----+--------+ +----+---+-----+ +------+-------+ +--------+-----+ - * ^ ^ | | | - * | | | | | - * | | | | | - * | | | CONNECT | CONNECTING | - * | | | FAIL | FAIL | - * REINITIALIZE| RECONNECT| | | | - * | | | v | DISCONNECT - * | | | +----------+-+ | - * | | | | | | - * | | +------->+ | | - * | | | DISCONNECT | | - * | | | +<---------------------+ - * | +------------+ | - * +--------------------------------------+ | - * +------------+ - * - * - * - */ -static VOID sample_event_loop(SAMPLE_CONTEXT *context) +static VOID sample_connected_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) { -ULONG app_events; -UINT loop = NX_TRUE; - - while (loop) - { - - /* Pickup IP event flags. */ - if (tx_event_flags_get(&(context -> sample_events), SAMPLE_ALL_EVENTS, TX_OR_CLEAR, &app_events, 5 * NX_IP_PERIODIC_RATE)) - { - if (context -> state == SAMPLE_STATE_CONNECTED) - { - sample_trigger_action(context); - } - - continue; - } - - if (app_events & SAMPLE_CONNECT_EVENT) - { - sample_connect_action(context); - } - - if (app_events & SAMPLE_INITIALIZATION_EVENT) - { - sample_initialize_iothub(context); - } - - if (app_events & SAMPLE_DEVICE_TWIN_GET_EVENT) - { - sample_device_twin_get_action(context); - } - - if (app_events & SAMPLE_METHOD_MESSAGE_EVENT) - { - sample_direct_method_action(context); - } - - if (app_events & SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT) - { - sample_device_twin_desired_property_action(context); - } +UINT status; - if (app_events & SAMPLE_TELEMETRY_SEND_EVENT) - { - sample_telemetry_action(context); - } +#ifndef DISABLE_ADU_SAMPLE + /* Start adu agent. */ + sample_adu_start(hub_client_ptr); +#endif /* DISABLE_ADU_SAMPLE */ - if (app_events & SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT) - { - sample_device_twin_reported_property_action(context); - } + /* Request all properties. */ + if ((status = nx_azure_iot_hub_client_properties_request(hub_client_ptr, NX_WAIT_FOREVER))) + { + printf("Properties request failed!: error code = 0x%08x\r\n", status); + } + else + { + printf("Sent properties request.\r\n"); + } +} - if (app_events & SAMPLE_DISCONNECT_EVENT) - { - sample_disconnect_action(context); - } +static VOID sample_periodic_timer_entry(ULONG context) +{ - if (app_events & SAMPLE_CONNECTED_EVENT) - { - sample_connected_action(context); - } + NX_PARAMETER_NOT_USED(context); + tx_event_flags_set(&(sample_events), SAMPLE_PERIODIC_EVENT, TX_OR); +} - if (app_events & SAMPLE_RECONNECT_EVENT) - { - sample_connection_error_recover(context); - } +static VOID sample_periodic_action(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr) +{ + NX_PARAMETER_NOT_USED(hub_client_ptr); + + if ((sample_periodic_counter % 5) == 0) + { - sample_trigger_action(context); + /* Set telemetry send event and reported properties send event. */ + tx_event_flags_set(&(sample_events), (SAMPLE_TELEMETRY_SEND_EVENT | SAMPLE_REPORTED_PROPERTIES_SEND_EVENT), TX_OR); } -} -static VOID sample_context_init(SAMPLE_CONTEXT *context) -{ - memset(context, 0, sizeof(SAMPLE_CONTEXT)); - tx_event_flags_create(&(context->sample_events), (CHAR*)"sample_app"); + sample_periodic_counter++; } static void log_callback(az_log_classification classification, UCHAR *msg, UINT msg_len) @@ -1242,6 +987,8 @@ static void log_callback(az_log_classification classification, UCHAR *msg, UINT void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)) { UINT status = 0; +UINT loop = NX_TRUE; +ULONG app_events; nx_azure_iot_log_init(log_callback); @@ -1254,7 +1001,7 @@ UINT status = 0; return; } - /* Initialize CA certificate. */ + /* Initialize CA certificates. */ if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, (USHORT)_nx_azure_iot_root_cert_size, NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) @@ -1264,13 +1011,76 @@ UINT status = 0; return; } - sample_context_init(&sample_context); + if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert_2, (UCHAR *)_nx_azure_iot_root_cert_2, + (USHORT)_nx_azure_iot_root_cert_size_2, + NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) + { + printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); + nx_azure_iot_delete(&nx_azure_iot); + return; + } + + if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert_3, (UCHAR *)_nx_azure_iot_root_cert_3, + (USHORT)_nx_azure_iot_root_cert_size_3, + NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) + { + printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); + nx_azure_iot_delete(&nx_azure_iot); + return; + } + + tx_timer_create(&(sample_timer), (CHAR*)"sample_app_timer", sample_periodic_timer_entry, 0, + NX_IP_PERIODIC_RATE, NX_IP_PERIODIC_RATE, TX_AUTO_ACTIVATE); + tx_event_flags_create(&sample_events, (CHAR*)"sample_app_event"); + + while (loop) + { + + /* Pickup sample event flags. */ + tx_event_flags_get(&(sample_events), SAMPLE_ALL_EVENTS, TX_OR_CLEAR, &app_events, NX_WAIT_FOREVER); - sample_context.state = SAMPLE_STATE_INIT; - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_INITIALIZATION_EVENT, TX_OR); + if (app_events & SAMPLE_CONNECTED_EVENT) + { + sample_connected_action(&iothub_client); + } + + if (app_events & SAMPLE_PERIODIC_EVENT) + { + sample_periodic_action(&iothub_client); + } - /* Handle event loop. */ - sample_event_loop(&sample_context); + if (app_events & SAMPLE_TELEMETRY_SEND_EVENT) + { + sample_telemetry_action(&iothub_client); + } + + if (app_events & SAMPLE_COMMAND_RECEIVE_EVENT) + { + sample_command_action(&iothub_client); + } + + if (app_events & SAMPLE_PROPERTIES_RECEIVE_EVENT) + { + sample_properties_receive_action(&iothub_client); + } + + if (app_events & SAMPLE_WRITABLE_PROPERTIES_RECEIVE_EVENT) + { + sample_writable_properties_receive_action(&iothub_client); + } + + if (app_events & SAMPLE_REPORTED_PROPERTIES_SEND_EVENT) + { + sample_reported_properties_send_action(&iothub_client); + } + + /* Connection monitor. */ + sample_connection_monitor(ip_ptr, &iothub_client, sample_connection_status, sample_initialize_iothub); + } + /* Cleanup. */ + tx_event_flags_delete(&sample_events); + tx_timer_delete(&sample_timer); + nx_azure_iot_hub_client_deinitialize(&iothub_client); nx_azure_iot_delete(&nx_azure_iot); } diff --git a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c b/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c deleted file mode 100644 index a27d5660..00000000 --- a/addons/azure_iot/samples/sample_azure_iot_embedded_sdk_with_retry.c +++ /dev/null @@ -1,792 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include - -#include "nx_api.h" -#include "nx_azure_iot_hub_client.h" -#include "nx_azure_iot_provisioning_client.h" - -/* These are sample files, user can build their own certificate and ciphersuites. */ -#include "nx_azure_iot_cert.h" -#include "nx_azure_iot_ciphersuites.h" -#include "sample_config.h" - -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC (10 * 60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC (3) -#endif /* SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT (60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT */ - -/* Define Azure RTOS TLS info. */ -static NX_SECURE_X509_CERT root_ca_cert; -static UCHAR nx_azure_iot_tls_metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE]; -static ULONG nx_azure_iot_thread_stack[NX_AZURE_IOT_STACK_SIZE / sizeof(ULONG)]; - -/* Define the prototypes for AZ IoT. */ -static NX_AZURE_IOT nx_azure_iot; - -/* Generally, IoTHub Client and DPS Client do not run at the same time, user can use union as below to - share the memory between IoTHub Client and DPS Client. - - NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ -typedef union SAMPLE_CLIENT_UNION -{ - NX_AZURE_IOT_HUB_CLIENT iothub_client; - -#ifdef ENABLE_DPS_SAMPLE - NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; -#endif /* ENABLE_DPS_SAMPLE */ - -} SAMPLE_CLIENT; - -static SAMPLE_CLIENT client; - -#define iothub_client client.iothub_client -#ifdef ENABLE_DPS_SAMPLE -#define prov_client client.prov_client -#endif /* ENABLE_DPS_SAMPLE */ - -static UINT exponential_retry_count; -static volatile UINT sample_iot_hub_init_status; -static volatile UINT sample_connection_status = NX_NOT_CONNECTED; -static TX_THREAD *sample_thread_ptr; - -/* Using X509 certificate authenticate to connect to IoT Hub, - set the device certificate as your device. */ -#if (USE_DEVICE_CERTIFICATE == 1) -extern const UCHAR sample_device_cert_ptr[]; -extern const UINT sample_device_cert_len; -extern const UCHAR sample_device_private_key_ptr[]; -extern const UINT sample_device_private_key_len; -NX_SECURE_X509_CERT device_certificate; -#endif /* USE_DEVICE_CERTIFICATE */ - -/* Define buffer for IoTHub info. */ -#ifdef ENABLE_DPS_SAMPLE -static UCHAR sample_iothub_hostname[SAMPLE_MAX_BUFFER]; -static UCHAR sample_iothub_device_id[SAMPLE_MAX_BUFFER]; -#endif /* ENABLE_DPS_SAMPLE */ - -/* Define sample threads. */ -#ifndef DISABLE_TELEMETRY_SAMPLE -static TX_THREAD sample_telemetry_thread; -static ULONG sample_telemetry_thread_stack[SAMPLE_STACK_SIZE / sizeof(ULONG)]; -#endif /* DISABLE_TELEMETRY_SAMPLE */ - -#ifndef DISABLE_C2D_SAMPLE -static TX_THREAD sample_c2d_thread; -static ULONG sample_c2d_thread_stack[SAMPLE_STACK_SIZE / sizeof(ULONG)]; -#endif /* DISABLE_C2D_SAMPLE */ - -#if !defined(DISABLE_TELEMETRY_SAMPLE) || !defined(DISABLE_C2D_SAMPLE) -/* Define sample properties. */ -static const CHAR *sample_properties[MAX_PROPERTY_COUNT][2] = {{"propertyA", "valueA"}, - {"propertyB", "valueB"}}; -#endif /* !defined(DISABLE_TELEMETRY_SAMPLE) && !defined(DISABLE_C2D_SAMPLE) */ - -#ifndef DISABLE_DIRECT_METHOD_SAMPLE -static CHAR method_response_payload[] = "{\"status\": \"OK\"}"; -static TX_THREAD sample_direct_method_thread; -static ULONG sample_direct_method_thread_stack[SAMPLE_STACK_SIZE / sizeof(ULONG)]; -#endif /* DISABLE_DIRECT_METHOD_SAMPLE */ - -#ifndef DISABLE_DEVICE_TWIN_SAMPLE -static CHAR fixed_reported_properties[] = "{\"sample_report\": \"OK\"}"; -static TX_THREAD sample_device_twin_thread; -static ULONG sample_device_twin_thread_stack[SAMPLE_STACK_SIZE / sizeof(ULONG)]; -#endif /* DISABLE_DEVICE_TWIN_SAMPLE */ - -void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)); -void sample_shell(ULONG parameter); -static UINT sample_initialize_iothub(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); - -#ifdef ENABLE_DPS_SAMPLE -static UINT sample_dps_entry(UCHAR **iothub_hostname, UINT *iothub_hostname_length, - UCHAR **iothub_device_id, UINT *iothub_device_id_length); -#endif /* ENABLE_DPS_SAMPLE */ -#ifndef DISABLE_TELEMETRY_SAMPLE -static void sample_telemetry_thread_entry(ULONG parameter); -#endif /* DISABLE_TELEMETRY_SAMPLE */ - -#ifndef DISABLE_C2D_SAMPLE -static void sample_c2d_thread_entry(ULONG parameter); -#endif /* DISABLE_C2D_SAMPLE */ - -#ifndef DISABLE_DIRECT_METHOD_SAMPLE -static void sample_direct_method_thread_entry(ULONG parameter); -#endif /* DISABLE_DIRECT_METHOD_SAMPLE */ - -#ifndef DISABLE_DEVICE_TWIN_SAMPLE -static void sample_device_twin_thread_entry(ULONG parameter); -#endif /* DISABLE_DEVICE_TWIN_SAMPLE */ - -static VOID printf_packet(NX_PACKET *packet_ptr) -{ - while (packet_ptr != NX_NULL) - { - printf("%.*s", (INT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr), - (CHAR *)packet_ptr -> nx_packet_prepend_ptr); - packet_ptr = packet_ptr -> nx_packet_next; - } -} - -static UINT exponential_backoff_with_jitter() -{ -double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); -UINT base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; -uint64_t delay; - - if (exponential_retry_count < (sizeof(UINT) * 8)) - { - delay = (uint64_t)((1 << exponential_retry_count) * SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC); - if (delay <= (UINT)(-1)) - { - base_delay = (UINT)delay; - } - } - - if (base_delay >= SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC) - { - base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; - } - else - { - exponential_retry_count++; - } - - return((UINT)(base_delay * (1 + jitter_percent)) * NX_IP_PERIODIC_RATE) ; -} - -static VOID exponential_backoff_reset() -{ - exponential_retry_count = 0; -} - -static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status) -{ - NX_PARAMETER_NOT_USED(hub_client_ptr); - - sample_connection_status = status; - - if (status) - { - printf("Disconnected from IoTHub!: error code = 0x%08x\r\n", status); - tx_thread_wait_abort(sample_thread_ptr); - } - else - { - printf("Connected to IoTHub.\r\n"); - exponential_backoff_reset(); - } -} - -static UINT sample_connection_error_recover(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, UINT error_code) -{ -UINT status; - - nx_azure_iot_hub_client_disconnect(iothub_client_ptr); - - switch (error_code) - { - - /* Something bad has happened with client state, we need to re-initialize it. */ - case NX_DNS_QUERY_FAILED : - case NXD_MQTT_ERROR_BAD_USERNAME_PASSWORD : - case NXD_MQTT_ERROR_NOT_AUTHORIZED : - { - printf("re-initializing iothub connection, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); - status = sample_initialize_iothub(iothub_client_ptr); - sample_iot_hub_init_status = status; - if (status == NX_SUCCESS) - { - status = nx_azure_iot_hub_client_connect(iothub_client_ptr, NX_FALSE, NX_WAIT_FOREVER); - } - } - break; - - default : - { - printf("reconnecting iothub, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - status = nx_azure_iot_hub_client_connect(iothub_client_ptr, NX_FALSE, NX_WAIT_FOREVER); - } - break; - } - - return(status); -} - -static VOID sample_iothub_connection_monitor(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT loop = NX_TRUE; -UINT status = NX_SUCCESS; -UINT old_threshold; - - /* Monitor the connection. */ - while (loop) - { - if (sample_iot_hub_init_status != NX_SUCCESS) - { - tx_thread_sleep(exponential_backoff_with_jitter()); - sample_iot_hub_init_status = sample_initialize_iothub(iothub_client_ptr); - } - - if (sample_connection_status != NX_SUCCESS) - { - status = sample_connection_error_recover(iothub_client_ptr, - sample_connection_status); - if (status != NX_SUCCESS) - { - sample_connection_status = status; - } - } - - /* Disable preemption. */ - tx_thread_preemption_change(tx_thread_identify(), 0, &old_threshold); - - /* Atomically check connection status. */ - if (sample_iot_hub_init_status == NX_SUCCESS && - sample_connection_status == NX_SUCCESS) - { - tx_thread_sleep(NX_WAIT_FOREVER); - } - - /* Restore preemption. */ - tx_thread_preemption_change(tx_thread_identify(), old_threshold, &old_threshold); - } -} - -static UINT sample_initialize_iothub(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT status; -#ifdef ENABLE_DPS_SAMPLE -UCHAR *iothub_hostname = NX_NULL; -UCHAR *iothub_device_id = NX_NULL; -UINT iothub_hostname_length = 0; -UINT iothub_device_id_length = 0; -#else -UCHAR *iothub_hostname = (UCHAR *)HOST_NAME; -UCHAR *iothub_device_id = (UCHAR *)DEVICE_ID; -UINT iothub_hostname_length = sizeof(HOST_NAME) - 1; -UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; -#endif /* ENABLE_DPS_SAMPLE */ - -#ifdef ENABLE_DPS_SAMPLE - - /* Run DPS. */ - if ((status = sample_dps_entry(&iothub_hostname, &iothub_hostname_length, - &iothub_device_id, &iothub_device_id_length))) - { - printf("Failed on sample_dps_entry!: error code = 0x%08x\r\n", status); - return(status); - } -#endif /* ENABLE_DPS_SAMPLE */ - - printf("IoTHub Host Name: %.*s; Device ID: %.*s.\r\n", - iothub_hostname_length, iothub_hostname, iothub_device_id_length, iothub_device_id); - - /* Initialize IoTHub client. */ - if ((status = nx_azure_iot_hub_client_initialize(iothub_client_ptr, &nx_azure_iot, - iothub_hostname, iothub_hostname_length, - iothub_device_id, iothub_device_id_length, - (UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, - _nx_azure_iot_tls_supported_crypto, - _nx_azure_iot_tls_supported_crypto_size, - _nx_azure_iot_tls_ciphersuite_map, - _nx_azure_iot_tls_ciphersuite_map_size, - nx_azure_iot_tls_metadata_buffer, - sizeof(nx_azure_iot_tls_metadata_buffer), - &root_ca_cert))) - { - printf("Failed on nx_azure_iot_hub_client_initialize!: error code = 0x%08x\r\n", status); - return(status); - } - -#if (USE_DEVICE_CERTIFICATE == 1) - - /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, - (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, - NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, - DEVICE_KEY_TYPE))) - { - printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); - } - - /* Set device certificate. */ - else if ((status = nx_azure_iot_hub_client_device_cert_set(iothub_client_ptr, &device_certificate))) - { - printf("Failed on nx_azure_iot_hub_client_device_cert_set!: error code = 0x%08x\r\n", status); - } -#else - - /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, - (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) - { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!\r\n"); - } -#endif /* USE_DEVICE_CERTIFICATE */ - - /* Set connection status callback. */ - else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, - connection_status_callback))) - { - printf("Failed on connection_status_callback!\r\n"); - } -#ifndef DISABLE_C2D_SAMPLE - else if ((status = nx_azure_iot_hub_client_cloud_message_enable(iothub_client_ptr))) - { - printf("C2D receive enable failed!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_C2D_SAMPLE */ -#ifndef DISABLE_DIRECT_METHOD_SAMPLE - else if ((status = nx_azure_iot_hub_client_direct_method_enable(iothub_client_ptr))) - { - printf("Direct method receive enable failed!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_DIRECT_METHOD_SAMPLE */ -#ifndef DISABLE_DEVICE_TWIN_SAMPLE - else if ((status = nx_azure_iot_hub_client_device_twin_enable(iothub_client_ptr))) - { - printf("device twin enabled failed!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_DEVICE_TWIN_SAMPLE */ - - if (status) - { - nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); - } - - return(status); -} - -static void log_callback(az_log_classification classification, UCHAR *msg, UINT msg_len) -{ - if (classification == AZ_LOG_IOT_AZURERTOS) - { - printf("%.*s", msg_len, (CHAR *)msg); - } -} - -void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)) -{ -UINT status = 0; - - sample_thread_ptr = tx_thread_identify(); - - nx_azure_iot_log_init(log_callback); - - /* Create Azure IoT handler. */ - if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, - nx_azure_iot_thread_stack, sizeof(nx_azure_iot_thread_stack), - NX_AZURE_IOT_THREAD_PRIORITY, unix_time_callback))) - { - printf("Failed on nx_azure_iot_create!: error code = 0x%08x\r\n", status); - return; - } - - /* Initialize CA certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, - (USHORT)_nx_azure_iot_root_cert_size, - NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) - { - printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); - nx_azure_iot_delete(&nx_azure_iot); - return; - } - - if ((sample_iot_hub_init_status = sample_initialize_iothub(&iothub_client))) - { - printf("Failed to initialize iothub client: error code = 0x%08x\r\n", sample_iot_hub_init_status); - } - else if (nx_azure_iot_hub_client_connect(&iothub_client, NX_FALSE, NX_WAIT_FOREVER)) - { - printf("Failed on nx_azure_iot_hub_client_connect!\r\n"); - } - -#ifndef DISABLE_TELEMETRY_SAMPLE - - /* Create Telemetry sample thread. */ - if ((status = tx_thread_create(&sample_telemetry_thread, "Sample Telemetry Thread", - sample_shell, (ULONG)sample_telemetry_thread_entry, - (UCHAR *)sample_telemetry_thread_stack, SAMPLE_STACK_SIZE, - SAMPLE_THREAD_PRIORITY, SAMPLE_THREAD_PRIORITY, - 1, TX_AUTO_START))) - { - printf("Failed to create telemetry sample thread!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_TELEMETRY_SAMPLE */ - -#ifndef DISABLE_C2D_SAMPLE - - /* Create C2D sample thread. */ - if ((status = tx_thread_create(&sample_c2d_thread, "Sample C2D Thread", - sample_shell, (ULONG)sample_c2d_thread_entry, - (UCHAR *)sample_c2d_thread_stack, SAMPLE_STACK_SIZE, - SAMPLE_THREAD_PRIORITY, SAMPLE_THREAD_PRIORITY, - 1, TX_AUTO_START))) - { - printf("Failed to create c2d sample thread!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_C2D_SAMPLE */ - -#ifndef DISABLE_DIRECT_METHOD_SAMPLE - - /* Create Direct Method sample thread. */ - if ((status = tx_thread_create(&sample_direct_method_thread, "Sample Direct Method Thread", - sample_shell, (ULONG)sample_direct_method_thread_entry, - (UCHAR *)sample_direct_method_thread_stack, SAMPLE_STACK_SIZE, - SAMPLE_THREAD_PRIORITY, SAMPLE_THREAD_PRIORITY, - 1, TX_AUTO_START))) - { - printf("Failed to create direct method sample thread!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_DIRECT_METHOD_SAMPLE */ - -#ifndef DISABLE_DEVICE_TWIN_SAMPLE - - /* Create Device twin sample thread. */ - if ((status = tx_thread_create(&sample_device_twin_thread, "Sample Device Twin Thread", - sample_shell, (ULONG)sample_device_twin_thread_entry, - (UCHAR *)sample_device_twin_thread_stack, SAMPLE_STACK_SIZE, - SAMPLE_THREAD_PRIORITY, SAMPLE_THREAD_PRIORITY, - 1, TX_AUTO_START))) - { - printf("Failed to create device twin sample thread!: error code = 0x%08x\r\n", status); - } -#endif /* DISABLE_DEVICE_TWIN_SAMPLE */ - - /* Monitor IoTHub connection. */ - sample_iothub_connection_monitor(&iothub_client); - - nx_azure_iot_hub_client_deinitialize(&iothub_client); - nx_azure_iot_delete(&nx_azure_iot); -} - -#ifdef ENABLE_DPS_SAMPLE -static UINT sample_dps_entry(UCHAR **iothub_hostname, UINT *iothub_hostname_length, - UCHAR **iothub_device_id, UINT *iothub_device_id_length) -{ -UINT status; - - printf("Start Provisioning Client...\r\n"); - - /* Initialize IoT provisioning client. */ - if ((status = nx_azure_iot_provisioning_client_initialize(&prov_client, &nx_azure_iot, - (UCHAR *)ENDPOINT, sizeof(ENDPOINT) - 1, - (UCHAR *)ID_SCOPE, sizeof(ID_SCOPE) - 1, - (UCHAR *)REGISTRATION_ID, sizeof(REGISTRATION_ID) - 1, - _nx_azure_iot_tls_supported_crypto, - _nx_azure_iot_tls_supported_crypto_size, - _nx_azure_iot_tls_ciphersuite_map, - _nx_azure_iot_tls_ciphersuite_map_size, - nx_azure_iot_tls_metadata_buffer, - sizeof(nx_azure_iot_tls_metadata_buffer), - &root_ca_cert))) - { - printf("Failed on nx_azure_iot_provisioning_client_initialize!: error code = 0x%08x\r\n", status); - return(status); - } - - /* Initialize length of hostname and device ID. */ - *iothub_hostname_length = sizeof(sample_iothub_hostname); - *iothub_device_id_length = sizeof(sample_iothub_device_id); - -#if (USE_DEVICE_CERTIFICATE == 1) - - /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) - { - printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); - } - - /* Set device certificate. */ - else if ((status = nx_azure_iot_provisioning_client_device_cert_set(&prov_client, &device_certificate))) - { - printf("Failed on nx_azure_iot_provisioning_client_device_cert_set!: error code = 0x%08x\r\n", status); - } -#else - - /* Set symmetric key. */ - if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(&prov_client, (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) - { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); - } -#endif /* USE_DEVICE_CERTIFICATE */ - - /* Register device. */ - else if ((status = nx_azure_iot_provisioning_client_register(&prov_client, NX_WAIT_FOREVER))) - { - printf("Failed on nx_azure_iot_provisioning_client_register!: error code = 0x%08x\r\n", status); - } - - /* Get Device info. */ - else if ((status = nx_azure_iot_provisioning_client_iothub_device_info_get(&prov_client, - sample_iothub_hostname, iothub_hostname_length, - sample_iothub_device_id, iothub_device_id_length))) - { - printf("Failed on nx_azure_iot_provisioning_client_iothub_device_info_get!: error code = 0x%08x\r\n", status); - } - else - { - *iothub_hostname = sample_iothub_hostname; - *iothub_device_id = sample_iothub_device_id; - printf("Registered Device Successfully.\r\n"); - } - - /* Destroy Provisioning Client. */ - nx_azure_iot_provisioning_client_deinitialize(&prov_client); - - return(status); -} -#endif /* ENABLE_DPS_SAMPLE */ - -void sample_shell(ULONG parameter) -{ -UINT (*fn)() = (UINT (*)())parameter; - - while (NX_TRUE) - { - if (sample_connection_status == NX_SUCCESS) - { - fn(); - } - else - { - tx_thread_sleep(5 * NX_IP_PERIODIC_RATE); - } - } -} - -#ifndef DISABLE_TELEMETRY_SAMPLE -void sample_telemetry_thread_entry(ULONG parameter) -{ -UINT i = 0; -UINT status = 0; -CHAR buffer[30]; -UINT buffer_length; -UCHAR loop = NX_TRUE; -NX_PACKET *packet_ptr; - - NX_PARAMETER_NOT_USED(parameter); - - /* Loop to send telemetry message. */ - while (loop) - { - - /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_hub_client_telemetry_message_create(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - break; - } - - /* Add properties to telemetry message. */ - for (int index = 0; index < MAX_PROPERTY_COUNT; index++) - { - if ((status = - nx_azure_iot_hub_client_telemetry_property_add(packet_ptr, - (UCHAR *)sample_properties[index][0], - (USHORT)strlen(sample_properties[index][0]), - (UCHAR *)sample_properties[index][1], - (USHORT)strlen(sample_properties[index][1]), - NX_WAIT_FOREVER))) - { - printf("Telemetry property add failed!: error code = 0x%08x\r\n", status); - break; - } - } - - if (status) - { - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - break; - } - - buffer_length = (UINT)snprintf(buffer, sizeof(buffer), "{\"Message ID\":%u}", i++); - if ((status = nx_azure_iot_hub_client_telemetry_send(&iothub_client, packet_ptr, - (UCHAR *)buffer, buffer_length, NX_WAIT_FOREVER))) - { - printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - break; - } - printf("Telemetry message send: %s.\r\n", buffer); - - tx_thread_sleep(5 * NX_IP_PERIODIC_RATE); - } -} -#endif /* DISABLE_TELEMETRY_SAMPLE */ - -#ifndef DISABLE_C2D_SAMPLE -void sample_c2d_thread_entry(ULONG parameter) -{ -UCHAR loop = NX_TRUE; -NX_PACKET *packet_ptr; -UINT status = 0; -USHORT property_buf_size; -const UCHAR *property_buf; - - NX_PARAMETER_NOT_USED(parameter); - - /* Loop to receive c2d message. */ - while (loop) - { - if ((status = nx_azure_iot_hub_client_cloud_message_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) - { - printf("C2D receive failed!: error code = 0x%08x\r\n", status); - break; - } - - if ((status = nx_azure_iot_hub_client_cloud_message_property_get(&iothub_client, packet_ptr, - (UCHAR *)sample_properties[0][0], - (USHORT)strlen(sample_properties[0][0]), - &property_buf, &property_buf_size))) - { - printf("Property [%s] not found: 0x%08x\r\n", sample_properties[0][0], status); - } - else - { - printf("Receive property: %s = %.*s\r\n", sample_properties[0][0], - (INT)property_buf_size, property_buf); - } - - printf("Receive message:"); - printf_packet(packet_ptr); - printf("\r\n"); - - nx_packet_release(packet_ptr); - } -} -#endif /* DISABLE_C2D_SAMPLE */ - -#ifndef DISABLE_DIRECT_METHOD_SAMPLE -void sample_direct_method_thread_entry(ULONG parameter) -{ -UCHAR loop = NX_TRUE; -NX_PACKET *packet_ptr; -UINT status = 0; -USHORT method_name_length; -const UCHAR *method_name_ptr; -USHORT context_length; -VOID *context_ptr; - - NX_PARAMETER_NOT_USED(parameter); - - /* Loop to receive direct method message. */ - while (loop) - { - if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&iothub_client, - &method_name_ptr, &method_name_length, - &context_ptr, &context_length, - &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Direct method receive failed!: error code = 0x%08x\r\n", status); - break; - } - - printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); - printf_packet(packet_ptr); - printf("\r\n"); - - if ((status = nx_azure_iot_hub_client_direct_method_message_response(&iothub_client, 200 /* method status */, - context_ptr, context_length, - (UCHAR *)method_response_payload, sizeof(method_response_payload) - 1, - NX_WAIT_FOREVER))) - { - printf("Direct method response failed!: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - break; - } - - nx_packet_release(packet_ptr); - } -} -#endif /* DISABLE_DIRECT_METHOD_SAMPLE */ - -#ifndef DISABLE_DEVICE_TWIN_SAMPLE -void sample_device_twin_thread_entry(ULONG parameter) -{ -UCHAR loop = NX_TRUE; -NX_PACKET *packet_ptr; -UINT status = 0; -UINT response_status; -UINT request_id; -ULONG reported_property_version; - - NX_PARAMETER_NOT_USED(parameter); - - if ((status = nx_azure_iot_hub_client_device_twin_properties_request(&iothub_client, NX_WAIT_FOREVER))) - { - printf("device twin document request failed!: error code = 0x%08x\r\n", status); - return; - } - - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&iothub_client, &packet_ptr, NX_WAIT_FOREVER))) - { - printf("device twin document receive failed!: error code = 0x%08x\r\n", status); - return; - } - - printf("Receive twin properties :"); - printf_packet(packet_ptr); - printf("\r\n"); - nx_packet_release(packet_ptr); - - /* Loop to receive device twin message. */ - while (loop) - { - if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&iothub_client, &packet_ptr, - NX_WAIT_FOREVER))) - { - printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); - break; - } - - printf("Receive desired property call: "); - printf_packet(packet_ptr); - printf("\r\n"); - nx_packet_release(packet_ptr); - - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(&iothub_client, - (UCHAR *)fixed_reported_properties, sizeof(fixed_reported_properties) - 1, - &request_id, &response_status, - &reported_property_version, - NX_WAIT_FOREVER))) - { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - break; - } - - if ((response_status < 200) || (response_status >= 300)) - { - printf("device twin report properties failed with code : %d\r\n", response_status); - break; - } - } -} -#endif /* DISABLE_DEVICE_TWIN_SAMPLE */ diff --git a/addons/azure_iot/samples/sample_config.h b/addons/azure_iot/samples/sample_config.h index 5b5ca117..21e9cfe6 100644 --- a/addons/azure_iot/samples/sample_config.h +++ b/addons/azure_iot/samples/sample_config.h @@ -52,6 +52,11 @@ TODO`s: Configure core settings of application for your IoTHub. #define DISABLE_DEVICE_TWIN_SAMPLE */ +/* Defined, ADU is disabled. */ +/* +#define DISABLE_ADU_SAMPLE +*/ + #ifndef ENABLE_DPS_SAMPLE /* Required when DPS is not used. */ @@ -71,7 +76,7 @@ TODO`s: Configure core settings of application for your IoTHub. /* Required when DPS is used. */ #ifndef ENDPOINT -#define ENDPOINT "" +#define ENDPOINT "global.azure-devices-provisioning.net" #endif /* ENDPOINT */ #ifndef ID_SCOPE diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/README.md b/addons/azure_iot/samples/sample_pnp_temperature_controller/README.md deleted file mode 100644 index 60604a97..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Sample IoT Plug and Play Temperature Controller - -This directory contains a sample a temperature controller that implements the model [dtmi:com:example:TemperatureController;1](https://github.com/Azure/opendigitaltwins-dtdl/blob/master/DTDL/v2/samples/TemperatureController.json). - -The model consists of: - -* The `reboot` command, `serialNumber` property, and `workingSet` telemetry that the temperature controller implements on the root interface. - -* Two thermostat subcomponents, `thermostat1` and `thermostat2`. - -* A `deviceInfo` component that reports properties about the device itself. - -Note that the individual components are in separate .c and .h files for easier composition. - -* [sample_pnp_temperature_controller.c](./sample_pnp_temperature_controller.c) implements the root temperature controller component. Because this is the root component, this code also handles routing to the subcomponents. For instance, if a PnP command is intended for `thermostat1`, code in this file first needs to parse this and route to the appropriate logic. - -* [sample_pnp_deviceinfo_component.c](./sample_pnp_deviceinfo_component.c) implements a simple, simulated DeviceInformation component whose DTDL is defined [here](https://repo.azureiotrepository.com/Models/dtmi:azure:DeviceManagement:DeviceInformation;1?api-version=2020-05-01-preview). This component only does a one-time reporting of the device state on program initiation. - -* [sample_pnp_thermostat_component.c](./sample_pnp_thermostat_component.c) implements a thermostat component. The temperature controller can have multiple components of the same type. The components `thermostat1` and `thermostat2` both implement `dtmi:com:example:Thermostat;1` in the temperature controller model. \ No newline at end of file diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c deleted file mode 100644 index bb53737a..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.c +++ /dev/null @@ -1,143 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "sample_pnp_deviceinfo_component.h" - -#include "nx_azure_iot_pnp_helpers.h" - -#define DOUBLE_DECIMAL_PLACE_DIGITS (2) - -/* Reported property keys and values. */ -static const CHAR sample_pnp_device_info_software_version_property_name[] = "swVersion"; -static const CHAR sample_pnp_device_info_software_version_property_value[] = "1.0.0.0"; -static const CHAR sample_pnp_device_info_manufacturer_property_name[] = "manufacturer"; -static const CHAR sample_pnp_device_info_manufacturer_property_value[] = "Sample-Manufacturer"; -static const CHAR sample_pnp_device_info_model_property_name[] = "model"; -static const CHAR sample_pnp_device_info_model_property_value[] = "pnp-sample-Model-123"; -static const CHAR sample_pnp_device_info_os_name_property_name[] = "osName"; -static const CHAR sample_pnp_device_info_os_name_property_value[] = "AzureRTOS"; -static const CHAR sample_pnp_device_info_processor_architecture_property_name[] = "processorArchitecture"; -static const CHAR sample_pnp_device_info_processor_architecture_property_value[] = "Contoso-Arch-64bit"; -static const CHAR sample_pnp_device_info_processor_manufacturer_property_name[] = "processorManufacturer"; -static const CHAR sample_pnp_device_info_processor_manufacturer_property_value[] = "Processor Manufacturer(TM)"; -static const CHAR sample_pnp_device_info_total_storage_property_name[] = "totalStorage"; -static const double sample_pnp_device_info_total_storage_property_value = 1024.0; -static const CHAR sample_pnp_device_info_total_memory_property_name[] = "totalMemory"; -static const double sample_pnp_device_info_total_memory_property_value = 128; - -static UCHAR scratch_buffer[512]; - -static UINT append_properties(NX_AZURE_IOT_JSON_WRITER *json_writer, VOID *context) -{ -UINT status; - - NX_PARAMETER_NOT_USED(context); - - if (nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_manufacturer_property_name, - sizeof(sample_pnp_device_info_manufacturer_property_name) - 1, - (UCHAR *)sample_pnp_device_info_manufacturer_property_value, - sizeof(sample_pnp_device_info_manufacturer_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_model_property_name, - sizeof(sample_pnp_device_info_model_property_name) - 1, - (UCHAR *)sample_pnp_device_info_model_property_value, - sizeof(sample_pnp_device_info_model_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_software_version_property_name, - sizeof(sample_pnp_device_info_software_version_property_name) - 1, - (UCHAR *)sample_pnp_device_info_software_version_property_value, - sizeof(sample_pnp_device_info_software_version_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_os_name_property_name, - sizeof(sample_pnp_device_info_os_name_property_name) - 1, - (UCHAR *)sample_pnp_device_info_os_name_property_value, - sizeof(sample_pnp_device_info_os_name_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_processor_architecture_property_name, - sizeof(sample_pnp_device_info_processor_architecture_property_name) - 1, - (UCHAR *)sample_pnp_device_info_processor_architecture_property_value, - sizeof(sample_pnp_device_info_processor_architecture_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_string_value(json_writer, - (UCHAR *)sample_pnp_device_info_processor_manufacturer_property_name, - sizeof(sample_pnp_device_info_processor_manufacturer_property_name) - 1, - (UCHAR *)sample_pnp_device_info_processor_manufacturer_property_value, - sizeof(sample_pnp_device_info_processor_manufacturer_property_value) - 1) || - nx_azure_iot_json_writer_append_property_with_double_value(json_writer, - (UCHAR *)sample_pnp_device_info_total_storage_property_name, - sizeof(sample_pnp_device_info_total_storage_property_name) - 1, - sample_pnp_device_info_total_storage_property_value, - DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(json_writer, - (UCHAR *)sample_pnp_device_info_total_memory_property_name, - sizeof(sample_pnp_device_info_total_memory_property_name) - 1, - sample_pnp_device_info_total_memory_property_value, DOUBLE_DECIMAL_PLACE_DIGITS)) - { - status = NX_NOT_SUCCESSFUL; - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -UINT sample_pnp_deviceinfo_report_all_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT reported_properties_length; -UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; - - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) - { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((status = nx_azure_iot_pnp_helper_build_reported_property(component_name_ptr, component_name_len, - append_properties, NX_NULL, - &json_builder))) - { - printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) - { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - nx_azure_iot_json_writer_deinit(&json_builder); - - if ((response_status < 200) || (response_status >= 300)) - { - printf("device twin report properties failed with code : %d\r\n", response_status); - return(NX_NOT_SUCCESSFUL); - } - - return(status); -} diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h deleted file mode 100644 index 2de2bbe5..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_deviceinfo_component.h +++ /dev/null @@ -1,28 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef SAMPLE_PNP_DEVICEINFO_COMPONENT_H -#define SAMPLE_PNP_DEVICEINFO_COMPONENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nx_azure_iot_hub_client.h" -#include "nx_api.h" - -UINT sample_pnp_deviceinfo_report_all_properties(UCHAR *component_name_ptr, UINT component_name_len, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); - -#ifdef __cplusplus -} -#endif -#endif /* SAMPLE_PNP_DEVICEINFO_COMPONENT_H */ diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c deleted file mode 100644 index 54d245e8..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_temperature_controller.c +++ /dev/null @@ -1,1297 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include - -#include "nx_api.h" -#include "nx_azure_iot_hub_client.h" -#include "nx_azure_iot_provisioning_client.h" - -/* These are sample files, user can build their own certificate and ciphersuites. */ -#include "nx_azure_iot_cert.h" -#include "nx_azure_iot_ciphersuites.h" -#include "sample_config.h" -#include "sample_pnp_deviceinfo_component.h" -#include "nx_azure_iot_pnp_helpers.h" -#include "sample_pnp_thermostat_component.h" - -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC (10 * 60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC -#define SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC (3) -#endif /* SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC */ - -#ifndef SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT -#define SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT (60) -#endif /* SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT */ - -#ifndef SAMPLE_WAIT_OPTION -#define SAMPLE_WAIT_OPTION (NX_NO_WAIT) -#endif /* SAMPLE_WAIT_OPTION */ - -/* Sample events. */ -#define SAMPLE_ALL_EVENTS ((ULONG)0xFFFFFFFF) -#define SAMPLE_CONNECT_EVENT ((ULONG)0x00000001) -#define SAMPLE_INITIALIZATION_EVENT ((ULONG)0x00000002) -#define SAMPLE_METHOD_MESSAGE_EVENT ((ULONG)0x00000004) -#define SAMPLE_DEVICE_TWIN_GET_EVENT ((ULONG)0x00000008) -#define SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT ((ULONG)0x00000010) -#define SAMPLE_TELEMETRY_SEND_EVENT ((ULONG)0x00000020) -#define SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT ((ULONG)0x00000040) -#define SAMPLE_DISCONNECT_EVENT ((ULONG)0x00000080) -#define SAMPLE_RECONNECT_EVENT ((ULONG)0x00000100) -#define SAMPLE_CONNECTED_EVENT ((ULONG)0x00000200) - -/* Sample states. */ -#define SAMPLE_STATE_NONE (0) -#define SAMPLE_STATE_INIT (1) -#define SAMPLE_STATE_CONNECTING (2) -#define SAMPLE_STATE_CONNECT (3) -#define SAMPLE_STATE_CONNECTED (4) -#define SAMPLE_STATE_DISCONNECTED (5) - -#define SAMPLE_DEFAULT_START_TEMP_CELSIUS (22) -#define DOUBLE_DECIMAL_PLACE_DIGITS (2) -#define SAMPLE_COMMAND_SUCCESS_STATUS (200) -#define SAMPLE_COMMAND_ERROR_STATUS (500) -#define SAMPLE_COMMAND_NOT_FOUND_STATUS (404) - -#define SAMPLE_PNP_MODEL_ID "dtmi:com:example:TemperatureController;1" -#define SAMPLE_PNP_DPS_PAYLOAD "{\"modelId\":\"" SAMPLE_PNP_MODEL_ID "\"}" - -/* Define Sample context. */ -typedef struct SAMPLE_CONTEXT_STRUCT -{ - UINT state; - UINT action_result; - ULONG last_periodic_action_tick; - - TX_EVENT_FLAGS_GROUP sample_events; - - /* Generally, IoTHub Client and DPS Client do not run at the same time, user can use union as below to - share the memory between IoTHub Client and DPS Client. - - NOTE: If user can not make sure sharing memory is safe, IoTHub Client and DPS Client must be defined seperately. */ - union SAMPLE_CLIENT_UNION - { - NX_AZURE_IOT_HUB_CLIENT iothub_client; -#ifdef ENABLE_DPS_SAMPLE - NX_AZURE_IOT_PROVISIONING_CLIENT prov_client; -#endif /* ENABLE_DPS_SAMPLE */ - } client; - -#define iothub_client client.iothub_client -#ifdef ENABLE_DPS_SAMPLE -#define prov_client client.prov_client -#endif /* ENABLE_DPS_SAMPLE */ - -} SAMPLE_CONTEXT; - -VOID sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)); - -#ifdef ENABLE_DPS_SAMPLE -static UINT sample_dps_entry(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, - UCHAR **iothub_hostname, UINT *iothub_hostname_length, - UCHAR **iothub_device_id, UINT *iothub_device_id_length); -#endif /* ENABLE_DPS_SAMPLE */ - -/* Define Azure RTOS TLS info. */ -static NX_SECURE_X509_CERT root_ca_cert; -static UCHAR nx_azure_iot_tls_metadata_buffer[NX_AZURE_IOT_TLS_METADATA_BUFFER_SIZE]; -static ULONG nx_azure_iot_thread_stack[NX_AZURE_IOT_STACK_SIZE / sizeof(ULONG)]; - -/* Using X509 certificate authenticate to connect to IoT Hub, - set the device certificate as your device. */ -#if (USE_DEVICE_CERTIFICATE == 1) -extern const UCHAR sample_device_cert_ptr[]; -extern const UINT sample_device_cert_len; -extern const UCHAR sample_device_private_key_ptr[]; -extern const UINT sample_device_private_key_len; -NX_SECURE_X509_CERT device_certificate; -#endif /* USE_DEVICE_CERTIFICATE */ - -/* Define buffer for IoTHub info. */ -#ifdef ENABLE_DPS_SAMPLE -static UCHAR sample_iothub_hostname[SAMPLE_MAX_BUFFER]; -static UCHAR sample_iothub_device_id[SAMPLE_MAX_BUFFER]; -#endif /* ENABLE_DPS_SAMPLE */ - -/* Define the prototypes for AZ IoT. */ -static NX_AZURE_IOT nx_azure_iot; - -static SAMPLE_CONTEXT sample_context; -static volatile UINT sample_connection_status = NX_NOT_CONNECTED; -static UINT exponential_retry_count; - -/* PNP model id. */ -static SAMPLE_PNP_THERMOSTAT_COMPONENT sample_thermostat_1; -static const CHAR sample_thermostat_1_component[] = "thermostat1"; -static double sample_thermostat_1_last_device_max_temp_reported; -static SAMPLE_PNP_THERMOSTAT_COMPONENT sample_thermostat_2; -static const CHAR sample_thermostat_2_component[] = "thermostat2"; -static double sample_thermostat_2_last_device_max_tem_reported; -static const CHAR sample_device_info_component[] = "deviceInformation"; -static UINT sample_device_info_sent; -static UINT sample_device_serial_info_sent; -static const CHAR *sample_components[] = { sample_thermostat_1_component, - sample_thermostat_2_component, - sample_device_info_component }; -static UINT sample_components_num = sizeof(sample_components) / sizeof(sample_components[0]); - -/* Name of the serial number property as defined in this component's DTML. */ -static const CHAR sample_serial_number_property_name[] = "serialNumber"; - -/* Value of the serial number. NOTE: This must be a legal JSON string which requires value to be in "..." */ -static const CHAR sample_serial_number_property_value[] = "serial-no-123-abc"; - -static const CHAR working_set[] = "workingSet"; - -/* PnP command supported. */ -static const CHAR rebootCommand[] = "reboot"; - -static const INT working_set_minimum = 1000; -static const INT working_set_random_modulo = 500; - -static UCHAR scratch_buffer[512]; - -static UINT sample_pnp_temp_controller_reboot_command(NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) -{ -INT delay; - - NX_PARAMETER_NOT_USED(out_json_builder_ptr); - - if (json_reader_ptr == NX_NULL) - { - printf("Payload found to be null for reboot command\r\n"); - return(NX_NOT_SUCCESSFUL); - } - else - { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_int32_get(json_reader_ptr, (int32_t *)&delay)) - { - return(NX_NOT_SUCCESSFUL); - } - } - - return(NX_AZURE_IOT_SUCCESS); -} - -static UINT sample_pnp_temp_controller_telemetry_send(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT status; -NX_PACKET *packet_ptr; -NX_AZURE_IOT_JSON_WRITER json_writer; -UINT buffer_length; -INT working_set_value; - - working_set_value = working_set_minimum + (rand() % working_set_random_modulo); - - /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_pnp_helper_telemetry_message_create(iothub_client_ptr, NX_NULL, 0, - &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - return(status); - } - - /* Build telemetry JSON payload. */ - if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) - { - printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(NX_NOT_SUCCESSFUL); - } - - if(nx_azure_iot_json_writer_append_begin_object(&json_writer) || - nx_azure_iot_json_writer_append_property_with_int32_value(&json_writer, - (UCHAR *)working_set, - sizeof(working_set) - 1, - working_set_value) || - nx_azure_iot_json_writer_append_end_object(&json_writer)) - { - printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(NX_NOT_SUCCESSFUL); - } - - buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if ((status = nx_azure_iot_hub_client_telemetry_send(iothub_client_ptr, packet_ptr, - (UCHAR *)scratch_buffer, buffer_length, NX_WAIT_FOREVER))) - { - printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(status); - } - - nx_azure_iot_json_writer_deinit(&json_writer); - printf("Temp Controller Telemetry message send: %.*s.\r\n", buffer_length, scratch_buffer); - - return(status); -} - -static UINT sample_pnp_temp_controller_process_command(const UCHAR *component_name_ptr, UINT component_name_length, - const UCHAR *pnp_command_name_ptr, UINT pnp_command_name_length, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *json_response_ptr, UINT *status_code) -{ -UINT dm_status; - - if (component_name_ptr != NX_NULL || component_name_length != 0) - { - return(NX_NOT_SUCCESSFUL); - } - - if (pnp_command_name_length != (sizeof(rebootCommand) - 1) || - strncmp((CHAR *)pnp_command_name_ptr, (CHAR *)rebootCommand, pnp_command_name_length) != 0) - { - printf("PnP command=%.*s is not supported on thermostat component", pnp_command_name_length, pnp_command_name_ptr); - dm_status = SAMPLE_COMMAND_NOT_FOUND_STATUS; - } - else - { - if (sample_pnp_temp_controller_reboot_command(json_reader_ptr, json_response_ptr)) - { - dm_status = SAMPLE_COMMAND_ERROR_STATUS; - } - else - { - dm_status = SAMPLE_COMMAND_SUCCESS_STATUS; - } - } - - *status_code = dm_status; - - return(NX_AZURE_IOT_SUCCESS); -} - -static UINT append_serial_number(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) -{ - NX_PARAMETER_NOT_USED(context); - - return(nx_azure_iot_json_writer_append_property_with_string_value(json_writer_ptr, - (UCHAR *)sample_serial_number_property_name, - sizeof(sample_serial_number_property_name) - 1, - (UCHAR *)sample_serial_number_property_value, - sizeof(sample_serial_number_property_value) - 1)); -} - -static UINT sample_pnp_temp_controller_report_serial_number_property(NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT reported_properties_length; -UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; - - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) - { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((status = nx_azure_iot_pnp_helper_build_reported_property(NX_NULL, 0, append_serial_number, NX_NULL, - &json_builder))) - { - printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) - { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - nx_azure_iot_json_writer_deinit(&json_builder); - - if ((response_status < 200) || (response_status >= 300)) - { - printf("device twin report properties failed with code : %d\r\n", response_status); - return(NX_NOT_SUCCESSFUL); - } - - return(status); -} - -static VOID printf_packet(NX_PACKET *packet_ptr) -{ - while (packet_ptr != NX_NULL) - { - printf("%.*s", (INT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr), - (CHAR *)packet_ptr -> nx_packet_prepend_ptr); - packet_ptr = packet_ptr -> nx_packet_next; - } -} - -static UINT exponential_backoff_with_jitter() -{ -double jitter_percent = (SAMPLE_MAX_EXPONENTIAL_BACKOFF_JITTER_PERCENT / 100.0) * (rand() / ((double)RAND_MAX)); -UINT base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; -uint64_t delay; - - if (exponential_retry_count < (sizeof(UINT) * 8)) - { - delay = (uint64_t)((1 << exponential_retry_count) * SAMPLE_INITIAL_EXPONENTIAL_BACKOFF_IN_SEC); - if (delay <= (UINT)(-1)) - { - base_delay = (UINT)delay; - } - } - - if (base_delay > SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC) - { - base_delay = SAMPLE_MAX_EXPONENTIAL_BACKOFF_IN_SEC; - } - else - { - exponential_retry_count++; - } - - return((UINT)(base_delay * (1 + jitter_percent)) * NX_IP_PERIODIC_RATE) ; -} - -static VOID exponential_backoff_reset() -{ - exponential_retry_count = 0; -} - -static VOID connection_status_callback(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, UINT status) -{ - NX_PARAMETER_NOT_USED(hub_client_ptr); - - sample_connection_status = status; - - if (status) - { - printf("Disconnected from IoTHub!: error code = 0x%08x\r\n", status); - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_DISCONNECT_EVENT, TX_OR); - } - else - { - printf("Connected to IoTHub.\r\n"); - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_CONNECTED_EVENT, TX_OR); - exponential_backoff_reset(); - } -} - -static VOID message_receive_callback_twin(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) -{ -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; - - NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_GET_EVENT, TX_OR); -} - -static VOID message_receive_callback_method(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) -{ -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; - - NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_METHOD_MESSAGE_EVENT, TX_OR); -} - -static VOID message_receive_callback_desired_property(NX_AZURE_IOT_HUB_CLIENT *hub_client_ptr, VOID *context) -{ -SAMPLE_CONTEXT *sample_ctx = (SAMPLE_CONTEXT *)context; - - NX_PARAMETER_NOT_USED(hub_client_ptr); - tx_event_flags_set(&(sample_ctx -> sample_events), - SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT, TX_OR); -} - -static VOID sample_connect_action(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_CONNECT) - { - return; - } - - context -> action_result = nx_azure_iot_hub_client_connect(&(context -> iothub_client), NX_FALSE, SAMPLE_WAIT_OPTION); - - if (context -> action_result == NX_AZURE_IOT_CONNECTING) - { - context -> state = SAMPLE_STATE_CONNECTING; - } - else if (context -> action_result != NX_SUCCESS) - { - sample_connection_status = context -> action_result; - context -> state = SAMPLE_STATE_DISCONNECTED; - } - else - { - context -> state = SAMPLE_STATE_CONNECTED; - - context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); - } -} - -static VOID sample_disconnect_action(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_CONNECTED && - context -> state != SAMPLE_STATE_CONNECTING) - { - return; - } - - context -> action_result = nx_azure_iot_hub_client_disconnect(&(context -> iothub_client)); - context -> state = SAMPLE_STATE_DISCONNECTED; -} - -static VOID sample_connected_action(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_CONNECTING) - { - return; - } - - context -> state = SAMPLE_STATE_CONNECTED; - - context -> action_result = - nx_azure_iot_hub_client_device_twin_properties_request(&(context -> iothub_client), NX_WAIT_FOREVER); -} - -static VOID sample_initialize_iothub(SAMPLE_CONTEXT *context) -{ -UINT status; -#ifdef ENABLE_DPS_SAMPLE -UCHAR *iothub_hostname = NX_NULL; -UCHAR *iothub_device_id = NX_NULL; -UINT iothub_hostname_length = 0; -UINT iothub_device_id_length = 0; -#else -UCHAR *iothub_hostname = (UCHAR *)HOST_NAME; -UCHAR *iothub_device_id = (UCHAR *)DEVICE_ID; -UINT iothub_hostname_length = sizeof(HOST_NAME) - 1; -UINT iothub_device_id_length = sizeof(DEVICE_ID) - 1; -#endif /* ENABLE_DPS_SAMPLE */ -NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr = &(context -> iothub_client); - - if (context -> state != SAMPLE_STATE_INIT) - { - return; - } - -#ifdef ENABLE_DPS_SAMPLE - - /* Run DPS. */ - if ((status = sample_dps_entry(&(context -> prov_client), &iothub_hostname, &iothub_hostname_length, - &iothub_device_id, &iothub_device_id_length))) - { - printf("Failed on sample_dps_entry!: error code = 0x%08x\r\n", status); - context -> action_result = status; - return; - } -#endif /* ENABLE_DPS_SAMPLE */ - - printf("IoTHub Host Name: %.*s; Device ID: %.*s.\r\n", - iothub_hostname_length, iothub_hostname, iothub_device_id_length, iothub_device_id); - - /* Initialize IoTHub client. */ - if ((status = nx_azure_iot_hub_client_initialize(iothub_client_ptr, &nx_azure_iot, - iothub_hostname, iothub_hostname_length, - iothub_device_id, iothub_device_id_length, - (UCHAR *)MODULE_ID, sizeof(MODULE_ID) - 1, - _nx_azure_iot_tls_supported_crypto, - _nx_azure_iot_tls_supported_crypto_size, - _nx_azure_iot_tls_ciphersuite_map, - _nx_azure_iot_tls_ciphersuite_map_size, - nx_azure_iot_tls_metadata_buffer, - sizeof(nx_azure_iot_tls_metadata_buffer), - &root_ca_cert))) - { - printf("Failed on nx_azure_iot_hub_client_initialize!: error code = 0x%08x\r\n", status); - context -> action_result = status; - return; - } - -#if (USE_DEVICE_CERTIFICATE == 1) - - /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, - (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, - NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, - DEVICE_KEY_TYPE))) - { - printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); - } - - /* Set device certificate. */ - else if ((status = nx_azure_iot_hub_client_device_cert_set(iothub_client_ptr, &device_certificate))) - { - printf("Failed on nx_azure_iot_hub_client_device_cert_set!: error code = 0x%08x\r\n", status); - } -#else - - /* Set symmetric key. */ - if ((status = nx_azure_iot_hub_client_symmetric_key_set(iothub_client_ptr, - (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) - { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set! error: 0x%08x\r\n", status); - } -#endif /* USE_DEVICE_CERTIFICATE */ - - /* Set connection status callback. */ - else if ((status = nx_azure_iot_hub_client_connection_status_callback_set(iothub_client_ptr, - connection_status_callback))) - { - printf("Failed on connection_status_callback!\r\n"); - } - else if ((status = nx_azure_iot_hub_client_direct_method_enable(iothub_client_ptr))) - { - printf("Direct method receive enable failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_device_twin_enable(iothub_client_ptr))) - { - printf("device twin enabled failed!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_PROPERTIES, - message_receive_callback_twin, - (VOID *)context))) - { - printf("device twin callback set!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DIRECT_METHOD, - message_receive_callback_method, - (VOID *)context))) - { - printf("device method callback set!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_receive_callback_set(iothub_client_ptr, - NX_AZURE_IOT_HUB_DEVICE_TWIN_DESIRED_PROPERTIES, - message_receive_callback_desired_property, - (VOID *)context))) - { - printf("device twin desired property callback set!: error code = 0x%08x\r\n", status); - } - else if ((status = nx_azure_iot_hub_client_model_id_set(iothub_client_ptr, (UCHAR *)SAMPLE_PNP_MODEL_ID, sizeof(SAMPLE_PNP_MODEL_ID) - 1))) - { - printf("digital twin modelId set!: error code = 0x%08x\r\n", status); - } - - if (status) - { - nx_azure_iot_hub_client_deinitialize(iothub_client_ptr); - } - - context -> action_result = status; - - if (status == NX_AZURE_IOT_SUCCESS) - { - context -> state = SAMPLE_STATE_CONNECT; - } -} - -static VOID sample_connection_error_recover(SAMPLE_CONTEXT *context) -{ - if (context -> state != SAMPLE_STATE_DISCONNECTED) - { - return; - } - - switch (sample_connection_status) - { - case NX_AZURE_IOT_SUCCESS: - { - printf("already connected\r\n"); - } - break; - - /* Something bad has happened with client state, we need to re-initialize it. */ - case NX_DNS_QUERY_FAILED : - case NXD_MQTT_ERROR_BAD_USERNAME_PASSWORD : - case NXD_MQTT_ERROR_NOT_AUTHORIZED : - { - printf("re-initializing iothub connection, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - nx_azure_iot_hub_client_deinitialize(&(context -> iothub_client)); - context -> state = SAMPLE_STATE_INIT; - } - break; - - default : - { - printf("reconnecting iothub, after backoff\r\n"); - - tx_thread_sleep(exponential_backoff_with_jitter()); - context -> state = SAMPLE_STATE_CONNECT; - } - break; - } -} - -static VOID sample_trigger_action(SAMPLE_CONTEXT *context) -{ - switch (context -> state) - { - case SAMPLE_STATE_INIT: - { - tx_event_flags_set(&(context -> sample_events), SAMPLE_INITIALIZATION_EVENT, TX_OR); - } - break; - - case SAMPLE_STATE_CONNECT: - { - tx_event_flags_set(&(context -> sample_events), SAMPLE_CONNECT_EVENT, TX_OR); - } - break; - - case SAMPLE_STATE_CONNECTED: - { - if ((tx_time_get() - context -> last_periodic_action_tick) >= (5 * NX_IP_PERIODIC_RATE)) - { - context -> last_periodic_action_tick = tx_time_get(); - tx_event_flags_set(&(context -> sample_events), SAMPLE_TELEMETRY_SEND_EVENT, TX_OR); - tx_event_flags_set(&(context -> sample_events), SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT, TX_OR); - } - } - break; - - case SAMPLE_STATE_DISCONNECTED: - { - tx_event_flags_set(&(context -> sample_events), SAMPLE_RECONNECT_EVENT, TX_OR); - } - break; - } -} - -static VOID sample_direct_method_action(SAMPLE_CONTEXT *sample_context_ptr) -{ -NX_PACKET *packet_ptr; -UINT status; -USHORT method_name_length; -const UCHAR *method_name_ptr; -USHORT context_length; -VOID *context_ptr; -UINT component_name_length; -const UCHAR *component_name_ptr; -UINT pnp_command_name_length; -const UCHAR *pnp_command_name_ptr; -NX_AZURE_IOT_JSON_WRITER json_writer; -NX_AZURE_IOT_JSON_READER json_reader; -NX_AZURE_IOT_JSON_READER *json_reader_ptr; -UINT status_code; -UINT response_length; - - if (sample_context_ptr -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - - if ((status = nx_azure_iot_hub_client_direct_method_message_receive(&(sample_context_ptr -> iothub_client), - &method_name_ptr, &method_name_length, - &context_ptr, &context_length, - &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Direct method receive failed!: error code = 0x%08x\r\n", status); - return; - } - - printf("Receive method call: %.*s, with payload:", (INT)method_name_length, (CHAR *)method_name_ptr); - printf_packet(packet_ptr); - printf("\r\n"); - - if ((status = nx_azure_iot_pnp_helper_command_name_parse(method_name_ptr, method_name_length, - &component_name_ptr, &component_name_length, - &pnp_command_name_ptr, - &pnp_command_name_length)) != NX_AZURE_IOT_SUCCESS) - { - printf("Failed to parse command name: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_writer, - scratch_buffer, - sizeof(scratch_buffer)))) - { - printf("Failed to initialize json writer: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else if ((packet_ptr ->nx_packet_length != 0) && - (status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - if (packet_ptr ->nx_packet_length == 0) - { - nx_packet_release(packet_ptr); - json_reader_ptr = NX_NULL; - } - else - { - json_reader_ptr = &json_reader; - } - - if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_1, component_name_ptr, - component_name_length, pnp_command_name_ptr, - pnp_command_name_length, json_reader_ptr, - &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) - { - printf("Successfully executed command %.*s on thermostat 1\r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - } - else if ((status = sample_pnp_thermostat_process_command(&sample_thermostat_2, component_name_ptr, - component_name_length, pnp_command_name_ptr, - pnp_command_name_length, json_reader_ptr, - &json_writer, &status_code)) == NX_AZURE_IOT_SUCCESS) - { - printf("Successfully executed command %.*s on thermostat 2\r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - } - else if((status = sample_pnp_temp_controller_process_command(component_name_ptr, component_name_length, - pnp_command_name_ptr, pnp_command_name_length, - json_reader_ptr, &json_writer, - &status_code)) == NX_AZURE_IOT_SUCCESS) - { - printf("Successfully executed command %.*s controller \r\n", method_name_length, method_name_ptr); - response_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - } - else - { - printf("Failed to find any handler for method %.*s\r\n", method_name_length, method_name_ptr); - status_code = SAMPLE_COMMAND_NOT_FOUND_STATUS; - response_length = 0; - } - - if (json_reader_ptr) - { - nx_azure_iot_json_reader_deinit(json_reader_ptr); - } - - if ((status = nx_azure_iot_hub_client_direct_method_message_response(&(sample_context_ptr -> iothub_client), - status_code, context_ptr, context_length, - scratch_buffer, response_length, NX_WAIT_FOREVER))) - { - printf("Direct method response failed!: error code = 0x%08x\r\n", status); - } - - nx_azure_iot_json_writer_deinit(&json_writer); - } -} - -static VOID sample_desired_property_callback(UCHAR *component_name_ptr, UINT component_name_len, - UCHAR *property_name_ptr, UINT property_name_len, - NX_AZURE_IOT_JSON_READER property_value_reader, UINT version, - VOID *userContextCallback) -{ - if (component_name_ptr == NULL || component_name_len == 0) - { - - /* The PnP protocol does not define a mechanism to report errors such as this to IoTHub, so - the best we can do here is to log for diagnostics purposes. */ - printf("Property=%.*s arrived for Control component itself. This does not support\ - writeable properties on it (all properties are on subcomponents)", property_name_len, property_name_ptr); - } - else if (sample_pnp_thermostat_process_property_update(&sample_thermostat_1, - (NX_AZURE_IOT_HUB_CLIENT *)userContextCallback, - component_name_ptr, component_name_len, - property_name_ptr, property_name_len, - &property_value_reader, version) == NX_AZURE_IOT_SUCCESS) - { - printf("property updated of thermostat 1\r\n"); - } - else if (sample_pnp_thermostat_process_property_update(&sample_thermostat_2, - (NX_AZURE_IOT_HUB_CLIENT *)userContextCallback, - component_name_ptr, component_name_len, - property_name_ptr, property_name_len, - &property_value_reader, version) == NX_AZURE_IOT_SUCCESS) - { - printf("property updated of thermostat 2\r\n"); - } - else - { - printf("Component=%.*s is not implemented by the Controller\r\n", component_name_len, component_name_ptr); - } -} - -static VOID sample_device_twin_desired_property_action(SAMPLE_CONTEXT *context) -{ -NX_PACKET *packet_ptr; -UINT status; -NX_AZURE_IOT_JSON_READER json_reader; - - if (context -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - - if ((status = nx_azure_iot_hub_client_device_twin_desired_properties_receive(&(context -> iothub_client), - &packet_ptr, - NX_WAIT_FOREVER))) - { - printf("Receive desired property receive failed!: error code = 0x%08x\r\n", status); - return; - } - - printf("Receive desired property: "); - printf_packet(packet_ptr); - printf("\r\n"); - - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - if ((status = nx_azure_iot_pnp_helper_twin_data_parse(&json_reader, NX_TRUE, - (CHAR **)sample_components, - sample_components_num, - scratch_buffer, sizeof(scratch_buffer), - sample_desired_property_callback, - (VOID *)&(context -> iothub_client)))) - { - printf("Failed to parse twin data!: error code = 0x%08x\r\n", status); - } - - nx_azure_iot_json_reader_deinit(&json_reader); - } -} - -static VOID sample_device_twin_reported_property_action(SAMPLE_CONTEXT *context) -{ -UINT status; - - if (context -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - - /* Only report once. */ - if (sample_device_serial_info_sent == 0) - { - if ((status = sample_pnp_temp_controller_report_serial_number_property(&(context -> iothub_client)))) - { - printf("Failed sample_pnp_temp_controller_report_serial_number_property: error code = 0x%08x\r\n", status); - } - else - { - sample_device_serial_info_sent = 1; - } - } - - - /* Only report once. */ - if (sample_device_info_sent == 0) - { - if ((status = sample_pnp_deviceinfo_report_all_properties((UCHAR *)sample_device_info_component, - sizeof(sample_device_info_component) - 1, - &(context -> iothub_client)))) - { - printf("Failed sample_pnp_deviceinfo_report_all_properties: error code = 0x%08x\r\n", status); - } - else - { - sample_device_info_sent = 1; - } - } - - /* Only report when changed. */ - if (!(((sample_thermostat_1_last_device_max_temp_reported - 0.01) < sample_thermostat_1.maxTemperature) && - ((sample_thermostat_1_last_device_max_temp_reported + 0.01) > sample_thermostat_1.maxTemperature))) - { - if ((status = sample_pnp_thermostat_report_max_temp_since_last_reboot_property(&sample_thermostat_1, - &(context -> iothub_client)))) - { - printf("Failed sample_pnp_thermostat_report_max_temp_since_last_reboot_property: error code = 0x%08x\r\n", status); - } - else - { - sample_thermostat_1_last_device_max_temp_reported = sample_thermostat_1.maxTemperature; - } - } - - /* Only report when changed. */ - if (!(((sample_thermostat_2_last_device_max_tem_reported - 0.01) < sample_thermostat_2.maxTemperature) && - ((sample_thermostat_2_last_device_max_tem_reported + 0.01) > sample_thermostat_2.maxTemperature))) - { - if ((status = sample_pnp_thermostat_report_max_temp_since_last_reboot_property(&sample_thermostat_2, - &(context -> iothub_client)))) - { - printf("Failed sample_pnp_thermostat_report_max_temp_since_last_reboot_property: error code = 0x%08x\r\n", status); - } - else - { - sample_thermostat_2_last_device_max_tem_reported = sample_thermostat_2.maxTemperature; - } - } -} - -static VOID sample_device_twin_get_action(SAMPLE_CONTEXT *context) -{ -NX_PACKET *packet_ptr; -UINT status; -NX_AZURE_IOT_JSON_READER json_reader; - - if (context -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - - if ((status = nx_azure_iot_hub_client_device_twin_properties_receive(&(context -> iothub_client), &packet_ptr, - NX_WAIT_FOREVER))) - { - printf("Twin receive failed!: error code = 0x%08x\r\n", status); - return; - } - - printf("Received twin properties: "); - printf_packet(packet_ptr); - printf("\r\n"); - - if ((status = nx_azure_iot_json_reader_init(&json_reader, packet_ptr))) - { - printf("Failed to initialize json reader: error code = 0x%08x\r\n", status); - nx_packet_release(packet_ptr); - } - else - { - if ((status = nx_azure_iot_pnp_helper_twin_data_parse(&json_reader, NX_FALSE, - (CHAR **)sample_components, sample_components_num, - scratch_buffer, sizeof(scratch_buffer), - sample_desired_property_callback, - (VOID *)&(context -> iothub_client)))) - { - printf("Failed to parse twin data!: error code = 0x%08x\r\n", status); - } - - nx_azure_iot_json_reader_deinit(&json_reader); - } -} - -static VOID sample_telemetry_action(SAMPLE_CONTEXT *context) -{ -UINT status; - - if (context -> state != SAMPLE_STATE_CONNECTED) - { - return; - } - - if ((status = sample_pnp_temp_controller_telemetry_send(&(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) - { - printf("Failed to send sample_pnp__telemetry_send, error: %d", status); - } - - if ((status = sample_pnp_thermostat_telemetry_send(&sample_thermostat_1, - &(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) - { - printf("Failed to send sample_pnp_thermostat_telemetry_send, error: %d", status); - } - - if ((status = sample_pnp_thermostat_telemetry_send(&sample_thermostat_2, - &(context -> iothub_client))) != NX_AZURE_IOT_SUCCESS) - { - printf("Failed to send sample_pnp_thermostat_telemetry_send, error: %d", status); - } -} - -#ifdef ENABLE_DPS_SAMPLE -static UINT sample_dps_entry(NX_AZURE_IOT_PROVISIONING_CLIENT *prov_client_ptr, - UCHAR **iothub_hostname, UINT *iothub_hostname_length, - UCHAR **iothub_device_id, UINT *iothub_device_id_length) -{ -UINT status; - - printf("Start Provisioning Client...\r\n"); - - /* Initialize IoT provisioning client. */ - if ((status = nx_azure_iot_provisioning_client_initialize(prov_client_ptr, &nx_azure_iot, - (UCHAR *)ENDPOINT, sizeof(ENDPOINT) - 1, - (UCHAR *)ID_SCOPE, sizeof(ID_SCOPE) - 1, - (UCHAR *)REGISTRATION_ID, sizeof(REGISTRATION_ID) - 1, - _nx_azure_iot_tls_supported_crypto, - _nx_azure_iot_tls_supported_crypto_size, - _nx_azure_iot_tls_ciphersuite_map, - _nx_azure_iot_tls_ciphersuite_map_size, - nx_azure_iot_tls_metadata_buffer, - sizeof(nx_azure_iot_tls_metadata_buffer), - &root_ca_cert))) - { - printf("Failed on nx_azure_iot_provisioning_client_initialize!: error code = 0x%08x\r\n", status); - return(status); - } - - /* Initialize length of hostname and device ID. */ - *iothub_hostname_length = sizeof(sample_iothub_hostname); - *iothub_device_id_length = sizeof(sample_iothub_device_id); - -#if (USE_DEVICE_CERTIFICATE == 1) - - /* Initialize the device certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&device_certificate, (UCHAR *)sample_device_cert_ptr, (USHORT)sample_device_cert_len, NX_NULL, 0, - (UCHAR *)sample_device_private_key_ptr, (USHORT)sample_device_private_key_len, DEVICE_KEY_TYPE))) - { - printf("Failed on nx_secure_x509_certificate_initialize!: error code = 0x%08x\r\n", status); - } - - /* Set device certificate. */ - else if ((status = nx_azure_iot_provisioning_client_device_cert_set(prov_client_ptr, &device_certificate))) - { - printf("Failed on nx_azure_iot_provisioning_client_device_cert_set!: error code = 0x%08x\r\n", status); - } -#else - - /* Set symmetric key. */ - if ((status = nx_azure_iot_provisioning_client_symmetric_key_set(prov_client_ptr, (UCHAR *)DEVICE_SYMMETRIC_KEY, - sizeof(DEVICE_SYMMETRIC_KEY) - 1))) - { - printf("Failed on nx_azure_iot_hub_client_symmetric_key_set!: error code = 0x%08x\r\n", status); - } -#endif /* USE_DEVICE_CERTIFICATE */ - else if ((status = nx_azure_iot_provisioning_client_registration_payload_set(prov_client_ptr, (UCHAR *)SAMPLE_PNP_DPS_PAYLOAD, - sizeof(SAMPLE_PNP_DPS_PAYLOAD) - 1))) - { - printf("Failed on nx_azure_iot_provisioning_client_registration_payload_set!: error code = 0x%08x\r\n", status); - } - - /* Register device */ - else if ((status = nx_azure_iot_provisioning_client_register(prov_client_ptr, NX_WAIT_FOREVER))) - { - printf("Failed on nx_azure_iot_provisioning_client_register!: error code = 0x%08x\r\n", status); - } - - /* Get Device info */ - else if ((status = nx_azure_iot_provisioning_client_iothub_device_info_get(prov_client_ptr, - sample_iothub_hostname, iothub_hostname_length, - sample_iothub_device_id, iothub_device_id_length))) - { - printf("Failed on nx_azure_iot_provisioning_client_iothub_device_info_get!: error code = 0x%08x\r\n", status); - } - else - { - *iothub_hostname = sample_iothub_hostname; - *iothub_device_id = sample_iothub_device_id; - printf("Registered Device Successfully.\r\n"); - } - - /* Destroy Provisioning Client. */ - nx_azure_iot_provisioning_client_deinitialize(prov_client_ptr); - - return(status); -} -#endif /* ENABLE_DPS_SAMPLE */ - -/** - * - * Sample Event loop - * - * - * +--------------+ +--------------+ +--------------+ +--------------+ - * | | INIT | | | | | | - * | | SUCCESS | | | | | +--------+ - * | INIT | | CONNECT | | CONNECTING | | CONNECTED | | (TELEMETRY | - * | +-----------> +----->+ +-------> | | METHOD | - * | | | | | | | <--------+ DEVICETWIN) - * | | | | | | | | - * +-----+--------+ +----+---+-----+ +------+-------+ +--------+-----+ - * ^ ^ | | | - * | | | | | - * | | | | | - * | | | CONNECT | CONNECTING | - * | | | FAIL | FAIL | - * REINITIALIZE| RECONNECT| | | | - * | | | v | DISCONNECT - * | | | +----------+-+ | - * | | | | | | - * | | +------->+ | | - * | | | DISCONNECT | | - * | | | +<---------------------+ - * | +------------+ | - * +--------------------------------------+ | - * +------------+ - * - * - * - */ -static VOID sample_event_loop(SAMPLE_CONTEXT *context) -{ -ULONG app_events; -UINT loop = NX_TRUE; - - while (loop) - { - - /* Pickup IP event flags. */ - if (tx_event_flags_get(&(context -> sample_events), SAMPLE_ALL_EVENTS, TX_OR_CLEAR, &app_events, 5 * NX_IP_PERIODIC_RATE)) - { - if (context -> state == SAMPLE_STATE_CONNECTED) - { - sample_trigger_action(context); - } - - continue; - } - - if (app_events & SAMPLE_CONNECT_EVENT) - { - sample_connect_action(context); - } - - if (app_events & SAMPLE_INITIALIZATION_EVENT) - { - sample_initialize_iothub(context); - } - - if (app_events & SAMPLE_DEVICE_TWIN_GET_EVENT) - { - sample_device_twin_get_action(context); - } - - if (app_events & SAMPLE_METHOD_MESSAGE_EVENT) - { - sample_direct_method_action(context); - } - - if (app_events & SAMPLE_DEVICE_TWIN_DESIRED_PROPERTY_EVENT) - { - sample_device_twin_desired_property_action(context); - } - - if (app_events & SAMPLE_TELEMETRY_SEND_EVENT) - { - sample_telemetry_action(context); - } - - if (app_events & SAMPLE_DEVICE_TWIN_REPORTED_PROPERTY_EVENT) - { - sample_device_twin_reported_property_action(context); - } - - if (app_events & SAMPLE_DISCONNECT_EVENT) - { - sample_disconnect_action(context); - } - - if (app_events & SAMPLE_CONNECTED_EVENT) - { - sample_connected_action(context); - } - - if (app_events & SAMPLE_RECONNECT_EVENT) - { - sample_connection_error_recover(context); - } - - sample_trigger_action(context); - } -} - -static VOID sample_context_init(SAMPLE_CONTEXT *context) -{ - memset(context, 0, sizeof(SAMPLE_CONTEXT)); - tx_event_flags_create(&(context->sample_events), (CHAR*)"sample_app"); -} - -static VOID log_callback(az_log_classification classification, UCHAR *msg, UINT msg_len) -{ - if (classification == AZ_LOG_IOT_AZURERTOS) - { - printf("%.*s", msg_len, (CHAR *)msg); - } -} - -static UINT sample_components_init() -{ -UINT status; - - if ((status = sample_pnp_thermostat_init(&sample_thermostat_1, - (UCHAR *)sample_thermostat_1_component, - sizeof(sample_thermostat_1_component) - 1, - SAMPLE_DEFAULT_START_TEMP_CELSIUS))) - { - printf("Failed to initialize %s: error code = 0x%08x\r\n", - sample_thermostat_1_component, status); - } - else if ((status = sample_pnp_thermostat_init(&sample_thermostat_2, - (UCHAR *)sample_thermostat_2_component, - sizeof(sample_thermostat_2_component) - 1, - SAMPLE_DEFAULT_START_TEMP_CELSIUS))) - { - printf("Failed to initialize %s: error code = 0x%08x\r\n", - sample_thermostat_2_component, status); - } - - sample_thermostat_1_last_device_max_temp_reported = 0; - sample_thermostat_2_last_device_max_tem_reported = 0; - sample_device_info_sent = 0; - sample_device_serial_info_sent = 0; - - return(status); -} - -VOID sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, NX_DNS *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time)) -{ -UINT status; - - nx_azure_iot_log_init(log_callback); - - if ((status = sample_components_init())) - { - printf("Failed on initialize sample components!: error code = 0x%08x\r\n", status); - return; - } - - /* Create Azure IoT handler. */ - if ((status = nx_azure_iot_create(&nx_azure_iot, (UCHAR *)"Azure IoT", ip_ptr, pool_ptr, dns_ptr, - nx_azure_iot_thread_stack, sizeof(nx_azure_iot_thread_stack), - NX_AZURE_IOT_THREAD_PRIORITY, unix_time_callback))) - { - printf("Failed on nx_azure_iot_create!: error code = 0x%08x\r\n", status); - return; - } - - /* Initialize CA certificate. */ - if ((status = nx_secure_x509_certificate_initialize(&root_ca_cert, (UCHAR *)_nx_azure_iot_root_cert, - (USHORT)_nx_azure_iot_root_cert_size, - NX_NULL, 0, NULL, 0, NX_SECURE_X509_KEY_TYPE_NONE))) - { - printf("Failed to initialize ROOT CA certificate!: error code = 0x%08x\r\n", status); - nx_azure_iot_delete(&nx_azure_iot); - return; - } - - sample_context_init(&sample_context); - - sample_context.state = SAMPLE_STATE_INIT; - tx_event_flags_set(&(sample_context.sample_events), SAMPLE_INITIALIZATION_EVENT, TX_OR); - - /* Handle event loop. */ - sample_event_loop(&sample_context); - - nx_azure_iot_delete(&nx_azure_iot); -} diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c deleted file mode 100644 index 79ce96d6..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.c +++ /dev/null @@ -1,399 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#include "sample_pnp_thermostat_component.h" - -#include "nx_azure_iot_pnp_helpers.h" - -#define SAMPLE_DEAFULT_START_TEMP_CELSIUS (22) -#define DOUBLE_DECIMAL_PLACE_DIGITS (2) -#define SAMPLE_COMMAND_SUCCESS_STATUS (200) -#define SAMPLE_COMMAND_ERROR_STATUS (500) - -/* Telemetry key */ -static const CHAR telemetry_name[] = "temperature"; - -/* Pnp command supported */ -static const CHAR get_max_min_report[] = "getMaxMinReport"; - -/* Names of properties for desired/reporting */ -static const CHAR reported_max_temp_since_last_reboot[] = "maxTempSinceLastReboot"; -static const CHAR report_max_temp_name[] = "maxTemp"; -static const CHAR report_min_temp_name[] = "minTemp"; -static const CHAR report_avg_temp_name[] = "avgTemp"; -static const CHAR report_start_time_name[] = "startTime"; -static const CHAR report_end_time_name[] = "endTime"; -static const CHAR target_temp_property_name[] = "targetTemperature"; -static const CHAR temp_response_description_success[] = "success"; -static const CHAR temp_response_description_failed[] = "failed"; - -/* Fake device data */ -static const CHAR fake_start_report_time[] = "2020-01-10T10:00:00Z"; -static const CHAR fake_end_report_time[] = "2023-01-10T10:00:00Z"; - -static UCHAR scratch_buffer[256]; - -/* sample direct method implementation */ -static UINT sample_get_maxmin_report(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *out_json_builder_ptr) -{ -UINT status; -UCHAR *start_time = (UCHAR *)fake_start_report_time; -UINT start_time_len = sizeof(fake_start_report_time) - 1; -UCHAR time_buf[32]; - - if (json_reader_ptr != NX_NULL) - { - if (nx_azure_iot_json_reader_next_token(json_reader_ptr) || - nx_azure_iot_json_reader_token_string_get(json_reader_ptr, time_buf, - sizeof(time_buf), &start_time_len)) - { - return(NX_NOT_SUCCESSFUL); - } - - start_time = time_buf; - } - - /* Build the method response payload */ - if (nx_azure_iot_json_writer_append_begin_object(out_json_builder_ptr) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, - (UCHAR *)report_max_temp_name, - sizeof(report_max_temp_name) - 1, - handle -> maxTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, - (UCHAR *)report_min_temp_name, - sizeof(report_min_temp_name) - 1, - handle -> minTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_double_value(out_json_builder_ptr, - (UCHAR *)report_avg_temp_name, - sizeof(report_avg_temp_name) - 1, - handle -> avgTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, - (UCHAR *)report_start_time_name, - sizeof(report_start_time_name) - 1, - (UCHAR *)start_time, start_time_len) || - nx_azure_iot_json_writer_append_property_with_string_value(out_json_builder_ptr, - (UCHAR *)report_end_time_name, - sizeof(report_end_time_name) - 1, - (UCHAR *)fake_end_report_time, - sizeof(fake_end_report_time) - 1) || - nx_azure_iot_json_writer_append_end_object(out_json_builder_ptr)) - { - status = NX_NOT_SUCCESSFUL; - } - else - { - status = NX_AZURE_IOT_SUCCESS; - } - - return(status); -} - -static UINT append_temp(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) -{ - return(nx_azure_iot_json_writer_append_double(json_writer_ptr, - *(double *)context, - DOUBLE_DECIMAL_PLACE_DIGITS)); -} - -static UINT append_max_temp(NX_AZURE_IOT_JSON_WRITER *json_writer_ptr, VOID *context) -{ -SAMPLE_PNP_THERMOSTAT_COMPONENT *handle = (SAMPLE_PNP_THERMOSTAT_COMPONENT *)context; - - return(nx_azure_iot_json_writer_append_property_with_double_value(json_writer_ptr, - (UCHAR *)reported_max_temp_since_last_reboot, - sizeof(reported_max_temp_since_last_reboot) - 1, - handle -> maxTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS)); -} - -static VOID sample_send_target_temperature_report(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, double temp, - INT status_code, UINT version, const CHAR *description) -{ -UINT bytes_copied; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_writer; -ULONG reported_property_version; - - /* Build telemetry JSON payload */ - if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) - { - printf("Failed to create json writer\r\n"); - return; - } - - if (nx_azure_iot_pnp_helper_build_reported_property_with_status(handle -> component_name_ptr, handle -> component_name_length, - (UCHAR *)target_temp_property_name, - sizeof(target_temp_property_name) - 1, - append_temp, (VOID *)&temp, status_code, - (UCHAR *)description, - strlen(description), version, &json_writer)) - { - printf("Failed to create reported response\r\n"); - } - else - { - bytes_copied = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if (nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, bytes_copied, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE))) - { - printf("Failed to send reported response\r\n"); - } - } - - nx_azure_iot_json_writer_deinit(&json_writer); -} - -UINT sample_pnp_thermostat_init(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - UCHAR *component_name_ptr, UINT component_name_length, - double default_temp) -{ - if (handle == NX_NULL) - { - return(NX_NOT_SUCCESSFUL); - } - - handle -> component_name_ptr = component_name_ptr; - handle -> component_name_length = component_name_length; - handle -> currentTemperature = default_temp; - handle -> minTemperature = default_temp; - handle -> maxTemperature = default_temp; - handle -> allTemperatures = default_temp; - handle -> numTemperatureUpdates = 1; - handle -> avgTemperature = default_temp; - - return(NX_AZURE_IOT_SUCCESS); -} - -UINT sample_pnp_thermostat_process_command(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - const UCHAR *component_name_ptr, UINT component_name_length, - const UCHAR *pnp_command_name_ptr, UINT pnp_command_name_length, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *json_response_ptr, UINT *status_code) -{ -UINT dm_status; - - if (handle == NX_NULL) - { - return(NX_NOT_SUCCESSFUL); - } - - if (handle -> component_name_length != component_name_length || - strncmp((CHAR *)handle -> component_name_ptr, (CHAR *)component_name_ptr, component_name_length) != 0) - { - return(NX_NOT_SUCCESSFUL); - } - - if (pnp_command_name_length != (sizeof(get_max_min_report) - 1) || - strncmp((CHAR *)pnp_command_name_ptr, (CHAR *)get_max_min_report, pnp_command_name_length) != 0) - { - printf("PnP command=%.*s is not supported on thermostat component\r\n", pnp_command_name_length, pnp_command_name_ptr); - dm_status = 404; - } - else - { - if (sample_get_maxmin_report(handle, json_reader_ptr, json_response_ptr)) - { - dm_status = SAMPLE_COMMAND_ERROR_STATUS; - } - else - { - dm_status = SAMPLE_COMMAND_SUCCESS_STATUS; - } - } - - *status_code = dm_status; - - return(NX_AZURE_IOT_SUCCESS); -} - -UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT status; -NX_PACKET *packet_ptr; -NX_AZURE_IOT_JSON_WRITER json_writer; -UINT buffer_length; - - if (handle == NX_NULL) - { - return(NX_NOT_SUCCESSFUL); - } - - /* Create a telemetry message packet. */ - if ((status = nx_azure_iot_pnp_helper_telemetry_message_create(iothub_client_ptr, handle -> component_name_ptr, - handle -> component_name_length, - &packet_ptr, NX_WAIT_FOREVER))) - { - printf("Telemetry message create failed!: error code = 0x%08x\r\n", status); - return(status); - } - - /* Build telemetry JSON payload */ - if (nx_azure_iot_json_writer_with_buffer_init(&json_writer, scratch_buffer, sizeof(scratch_buffer))) - { - printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(NX_NOT_SUCCESSFUL); - } - - if(nx_azure_iot_json_writer_append_begin_object(&json_writer) || - nx_azure_iot_json_writer_append_property_with_double_value(&json_writer, - (UCHAR *)telemetry_name, - sizeof(telemetry_name) - 1, - handle -> currentTemperature, - DOUBLE_DECIMAL_PLACE_DIGITS) || - nx_azure_iot_json_writer_append_end_object(&json_writer)) - { - printf("Telemetry message failed to build message\r\n"); - nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(NX_NOT_SUCCESSFUL); - } - - buffer_length = nx_azure_iot_json_writer_get_bytes_used(&json_writer); - if ((status = nx_azure_iot_hub_client_telemetry_send(iothub_client_ptr, packet_ptr, - (UCHAR *)scratch_buffer, buffer_length, NX_WAIT_FOREVER))) - { - printf("Telemetry message send failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_writer); - nx_azure_iot_hub_client_telemetry_message_delete(packet_ptr); - return(status); - } - - nx_azure_iot_json_writer_deinit(&json_writer); - printf("Thermostat %.*s Telemetry message send: %.*s.\r\n", handle -> component_name_length, - handle -> component_name_ptr, buffer_length, scratch_buffer); - - return(status); -} - -UINT sample_pnp_thermostat_report_max_temp_since_last_reboot_property(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr) -{ -UINT reported_properties_length; -UINT status; -UINT response_status; -UINT request_id; -NX_AZURE_IOT_JSON_WRITER json_builder; -ULONG reported_property_version; - - if ((status = nx_azure_iot_json_writer_with_buffer_init(&json_builder, - scratch_buffer, - sizeof(scratch_buffer)))) - { - printf("Failed to initialize json writer\r\n"); - return(NX_NOT_SUCCESSFUL); - } - - if ((status = nx_azure_iot_pnp_helper_build_reported_property(handle -> component_name_ptr, - handle -> component_name_length, - append_max_temp, (VOID *)handle, - &json_builder))) - { - printf("Failed to build reported property!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - reported_properties_length = nx_azure_iot_json_writer_get_bytes_used(&json_builder); - if ((status = nx_azure_iot_hub_client_device_twin_reported_properties_send(iothub_client_ptr, - scratch_buffer, - reported_properties_length, - &request_id, &response_status, - &reported_property_version, - (5 * NX_IP_PERIODIC_RATE)))) - { - printf("Device twin reported properties failed!: error code = 0x%08x\r\n", status); - nx_azure_iot_json_writer_deinit(&json_builder); - return(status); - } - - nx_azure_iot_json_writer_deinit(&json_builder); - - if ((response_status < 200) || (response_status >= 300)) - { - printf("device twin report properties failed with code : %d\r\n", response_status); - return(NX_NOT_SUCCESSFUL); - } - - return(status); -} - -UINT sample_pnp_thermostat_process_property_update(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name_ptr, UINT component_name_length, - UCHAR *property_name_ptr, UINT property_name_length, - NX_AZURE_IOT_JSON_READER *property_value_reader_ptr, UINT version) -{ -double parsed_value = 0; -INT status_code; -const CHAR *description; - - if (handle == NX_NULL) - { - return(NX_NOT_SUCCESSFUL); - } - - if (handle -> component_name_length != component_name_length || - strncmp((CHAR *)handle -> component_name_ptr, (CHAR *)component_name_ptr, component_name_length) != 0) - { - return(NX_NOT_SUCCESSFUL); - } - - if (property_name_length != (sizeof(target_temp_property_name) - 1) || - strncmp((CHAR *)property_name_ptr, (CHAR *)target_temp_property_name, property_name_length) != 0) - { - printf("PnP property=%.*s is not supported on thermostat component\r\n", - property_name_length, property_name_ptr); - status_code = 404; - description = temp_response_description_failed; - } - else if (nx_azure_iot_json_reader_token_double_get(property_value_reader_ptr, &parsed_value)) - { - status_code = 401; - description = temp_response_description_failed; - } - else - { - status_code = 200; - description = temp_response_description_success; - - handle -> currentTemperature = parsed_value; - if (handle -> currentTemperature > handle -> maxTemperature) - { - handle -> maxTemperature = handle -> currentTemperature; - } - - if (handle -> currentTemperature < handle -> minTemperature) - { - handle -> minTemperature = handle -> currentTemperature; - } - - /* Increment the avg count, add the new temp to the total, and calculate the new avg */ - handle -> numTemperatureUpdates++; - handle -> allTemperatures += handle -> currentTemperature; - handle -> avgTemperature = handle -> allTemperatures / handle -> numTemperatureUpdates; - } - - sample_send_target_temperature_report(handle, iothub_client_ptr, parsed_value, - status_code, version, description); - - return(NX_AZURE_IOT_SUCCESS); -} diff --git a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h b/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h deleted file mode 100644 index ffa2906f..00000000 --- a/addons/azure_iot/samples/sample_pnp_temperature_controller/sample_pnp_thermostat_component.h +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - -#ifndef SAMPLE_PNP_THERMOSTAT_COMPONENT_H -#define SAMPLE_PNP_THERMOSTAT_COMPONENT_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "nx_azure_iot_hub_client.h" -#include "nx_azure_iot_json_reader.h" -#include "nx_azure_iot_json_writer.h" -#include "nx_api.h" - -typedef struct SAMPLE_PNP_THERMOSTAT_COMPONENT_TAG -{ - /* Name of this component */ - UCHAR *component_name_ptr; - - UINT component_name_length; - - /* Current temperature of this thermostat component */ - double currentTemperature; - - /* Minimum temperature this thermostat has been at during current execution run of this thermostat component */ - double minTemperature; - - /* Maximum temperature thermostat has been at during current execution run of this thermostat component */ - double maxTemperature; - - /* Number of times temperature has been updated, counting the initial setting as 1. Used to determine average temperature of this thermostat component */ - UINT numTemperatureUpdates; - - /* Total of all temperature updates during current exceution run. Used to determine average temperature of this thermostat component */ - double allTemperatures; - - double avgTemperature; -} SAMPLE_PNP_THERMOSTAT_COMPONENT; - -UINT sample_pnp_thermostat_init(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - UCHAR *component_name_ptr, UINT component_name_length, - double default_temp); - -UINT sample_pnp_thermostat_process_command(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - const UCHAR *component_name_ptr, UINT component_name_length, - const UCHAR *pnp_command_name_ptr, UINT pnp_command_name_length, - NX_AZURE_IOT_JSON_READER *json_reader_ptr, - NX_AZURE_IOT_JSON_WRITER *json_response_ptr, UINT *status_code); - -UINT sample_pnp_thermostat_telemetry_send(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); - -UINT sample_pnp_thermostat_report_max_temp_since_last_reboot_property(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr); - - -UINT sample_pnp_thermostat_process_property_update(SAMPLE_PNP_THERMOSTAT_COMPONENT *handle, - NX_AZURE_IOT_HUB_CLIENT *iothub_client_ptr, - UCHAR *component_name_ptr, UINT component_name_length, - UCHAR *property_name_ptr, UINT property_name_length, - NX_AZURE_IOT_JSON_READER *property_value_reader_ptr, UINT version); - -#ifdef __cplusplus -} -#endif -#endif /* SAMPLE_PNP_THERMOSTAT_COMPONENT_H */ diff --git a/addons/cloud/nx_cloud.c b/addons/cloud/nx_cloud.c index 703e7e27..928fde05 100644 --- a/addons/cloud/nx_cloud.c +++ b/addons/cloud/nx_cloud.c @@ -892,7 +892,7 @@ ULONG registered_event; /* FUNCTION RELEASE */ /* */ /* _nxe_cloud_module_event_clear PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -914,7 +914,7 @@ ULONG registered_event; /* */ /* CALLS */ /* */ -/* _nx_cloud_module_event_set Actual cloud module event */ +/* _nx_cloud_module_event_clear Actual cloud module event */ /* clear function */ /* */ /* CALLED BY */ @@ -926,6 +926,9 @@ ULONG registered_event; /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* xx-xx-xxxx Bo Chen Modified comment(s), fixed */ +/* event clear function, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ UINT _nxe_cloud_module_event_clear(NX_CLOUD_MODULE *cloud_module, ULONG module_own_event) @@ -945,8 +948,8 @@ UINT status; return(NX_CLOUD_MODULE_EVENT_INVALID); } - /* Call actual cloud module event set function. */ - status = _nx_cloud_module_event_set(cloud_module, module_own_event); + /* Call actual cloud module event clear function. */ + status = _nx_cloud_module_event_clear(cloud_module, module_own_event); /* Return completion status. */ return(status); diff --git a/addons/dhcp/nxd_dhcp_client.c b/addons/dhcp/nxd_dhcp_client.c index 4944b179..e7131477 100644 --- a/addons/dhcp/nxd_dhcp_client.c +++ b/addons/dhcp/nxd_dhcp_client.c @@ -46,6 +46,7 @@ static UINT _nx_dhcp_extract_information(NX_DHCP *dhcp_ptr, NX_DHCP_INTER static UINT _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length); static UINT _nx_dhcp_add_option_value(UCHAR *bootp_message, UINT option, UINT size, ULONG value, UINT *index); static UINT _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT size, UCHAR *value, UINT *index); +static UINT _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index); static ULONG _nx_dhcp_update_timeout(ULONG timeout); static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout); static UCHAR *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length); @@ -69,8 +70,8 @@ static VOID _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT interface_index, ULO /* Define the Request string that specifies which options are to be added - to the DHCP Client discover request to the server. Additional options - (found in nx_dhcp.h) may be added after the last option. */ + to the DHCP Client discover request to the server. Additional options + (found in nx_dhcp.h) may be added by calling nx_dhcp_user_option_request(). */ UCHAR _nx_dhcp_request_parameters[] = { NX_DHCP_OPTION_SUBNET_MASK, NX_DHCP_OPTION_GATEWAYS, @@ -153,7 +154,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_create PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -203,11 +204,23 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the code, */ +/* resulting in version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* multiple client instances, */ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), cleaned */ +/* up error check logic, and */ +/* properly terminated thread, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcp_create(NX_DHCP *dhcp_ptr, NX_IP *ip_ptr, CHAR *name_ptr) { +TX_INTERRUPT_SAVE_AREA + UINT status; #ifdef NX_DHCP_CLIENT_ENABLE_HOST_NAME_CHECK CHAR *temp_ptr; @@ -318,16 +331,8 @@ UINT label_length = 0; } /* Create the pool and check the status */ - status = nx_packet_pool_create(&dhcp_ptr -> nx_dhcp_pool, "NetX DHCP Client", NX_DHCP_PACKET_PAYLOAD, - dhcp_ptr -> nx_dhcp_pool_area, NX_DHCP_PACKET_POOL_SIZE); - - /* Determine if it was successful. */ - if (status != NX_SUCCESS) - { - - /* No, return error status. */ - return(status); - } + nx_packet_pool_create(&dhcp_ptr -> nx_dhcp_pool, "NetX DHCP Client", NX_DHCP_PACKET_PAYLOAD, + dhcp_ptr -> nx_dhcp_pool_area, NX_DHCP_PACKET_POOL_SIZE); /* Set an internal packet pool pointer to the newly created packet pool. */ dhcp_ptr -> nx_dhcp_packet_pool_ptr = &dhcp_ptr -> nx_dhcp_pool; @@ -341,39 +346,13 @@ UINT label_length = 0; #endif /* NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL */ /* Create the Socket and check the status */ - status = nx_udp_socket_create(ip_ptr, &(dhcp_ptr -> nx_dhcp_socket), "NetX DHCP Client", - NX_DHCP_TYPE_OF_SERVICE, NX_DHCP_FRAGMENT_OPTION, NX_DHCP_TIME_TO_LIVE, NX_DHCP_QUEUE_DEPTH); - - /* Was the socket creation successful? */ - if (status != NX_SUCCESS) - { - -#ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL - /* Delete the packet pool. */ - nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr); -#endif - - /* No, return error status. */ - return(status); - } - + nx_udp_socket_create(ip_ptr, &(dhcp_ptr -> nx_dhcp_socket), "NetX DHCP Client", + NX_DHCP_TYPE_OF_SERVICE, NX_DHCP_FRAGMENT_OPTION, NX_DHCP_TIME_TO_LIVE, NX_DHCP_QUEUE_DEPTH); /* Set the UDP socket receive callback function. */ - status = nx_udp_socket_receive_notify(&(dhcp_ptr -> nx_dhcp_socket), _nx_dhcp_udp_receive_notify); - - /* Check status. */ - if (status != NX_SUCCESS) - { - - -#ifndef NX_DHCP_CLIENT_USER_CREATE_PACKET_POOL - /* Delete the packet pool. */ - nx_packet_pool_delete(dhcp_ptr -> nx_dhcp_packet_pool_ptr); -#endif + nx_udp_socket_receive_notify(&(dhcp_ptr -> nx_dhcp_socket), _nx_dhcp_udp_receive_notify); - /* Delete the UDP socket. */ - nx_udp_socket_delete(&(dhcp_ptr -> nx_dhcp_socket)); - } + dhcp_ptr -> nx_dhcp_socket.nx_udp_socket_reserved_ptr = (VOID*)dhcp_ptr; /* Create the ThreadX activity timeout timer. This will be used to periodically check to see if a client connection has gone silent and needs to be terminated. */ @@ -384,7 +363,7 @@ UINT label_length = 0; NX_TIMER_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_timer), dhcp_ptr) /* Determine if the semaphore creation was successful. */ - if (status != NX_SUCCESS) + if (status != TX_SUCCESS) { /* Delete the UDP socket. */ @@ -403,7 +382,7 @@ UINT label_length = 0; status = tx_mutex_create(&(dhcp_ptr -> nx_dhcp_mutex), "NetX DHCP Client", TX_NO_INHERIT); /* Determine if the semaphore creation was successful. */ - if (status != NX_SUCCESS) + if (status != TX_SUCCESS) { /* Delete the UDP socket. */ @@ -429,7 +408,7 @@ UINT label_length = 0; NX_THREAD_EXTENSION_PTR_SET(&(dhcp_ptr -> nx_dhcp_thread), dhcp_ptr) /* Determine if the thread creation was successful. */ - if (status != NX_SUCCESS) + if (status != TX_SUCCESS) { /* Delete the mutex. */ @@ -457,6 +436,9 @@ UINT label_length = 0; if (status != TX_SUCCESS) { + /* First put the thread into TERMINATE state. */ + tx_thread_terminate(&(dhcp_ptr -> nx_dhcp_thread)); + /* Delete the thread. */ tx_thread_delete(&(dhcp_ptr -> nx_dhcp_thread)); @@ -478,12 +460,22 @@ UINT label_length = 0; return(status); } + /* Otherwise, the DHCP initialization was successful. Place the + DHCP control block on the list of created DHCP instances. */ + TX_DISABLE + /* Update the dhcp structure ID. */ dhcp_ptr -> nx_dhcp_id = NX_DHCP_ID; - /* Save the DHCP instance. */ + /* Setup this DHCP's created links. */ + dhcp_ptr -> nx_dhcp_created_next = _nx_dhcp_created_ptr; + + /* Place the new DHCP control block on the head of created DHCPs. */ _nx_dhcp_created_ptr = dhcp_ptr; + /* Restore previous interrupt posture. */ + TX_RESTORE + /* Default enable DHCP on the primary interface (0). */ _nx_dhcp_interface_enable(dhcp_ptr, 0); @@ -1152,7 +1144,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_interface_reinitialize PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1198,6 +1190,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcp_interface_reinitialize(NX_DHCP *dhcp_ptr, UINT iface_index) @@ -1229,10 +1224,10 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; { /* Get the IP address. */ - status = nx_ip_interface_address_get(dhcp_ptr -> nx_dhcp_ip_ptr, iface_index, &ip_address, &network_mask); + nx_ip_interface_address_get(dhcp_ptr -> nx_dhcp_ip_ptr, iface_index, &ip_address, &network_mask); /* Check if the IP address is set by DHCP. */ - if ((status == NX_SUCCESS) && (ip_address == interface_record -> nx_dhcp_ip_address)) + if (ip_address == interface_record -> nx_dhcp_ip_address) { /* Clear the IP address. */ @@ -1666,7 +1661,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_delete PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1710,12 +1705,18 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* multiple client instances, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_dhcp_delete(NX_DHCP *dhcp_ptr) { +TX_INTERRUPT_SAVE_AREA + UINT i; +NX_DHCP *dhcp_previous; /* Get the DHCP mutex. */ tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER); @@ -1765,9 +1766,34 @@ UINT i; /* Delete the DHCP mutex. */ tx_mutex_delete(&(dhcp_ptr -> nx_dhcp_mutex)); + /* Disable interrupts. */ + TX_DISABLE + /* Clear the dhcp structure ID. */ dhcp_ptr -> nx_dhcp_id = 0; + /* Remove the DHCP instance from the created list. */ + if (_nx_dhcp_created_ptr == dhcp_ptr) + { + _nx_dhcp_created_ptr = _nx_dhcp_created_ptr -> nx_dhcp_created_next; + } + else + { + for (dhcp_previous = _nx_dhcp_created_ptr; + dhcp_previous -> nx_dhcp_created_next; + dhcp_previous = dhcp_previous -> nx_dhcp_created_next) + { + if (dhcp_previous -> nx_dhcp_created_next == dhcp_ptr) + { + dhcp_previous -> nx_dhcp_created_next = dhcp_ptr -> nx_dhcp_created_next; + break; + } + } + } + + /* Restore interrupts. */ + TX_RESTORE + /* Return a successful status. */ return(NX_SUCCESS); } @@ -2300,7 +2326,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_interface_decline PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2340,13 +2366,15 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcp_interface_decline(NX_DHCP *dhcp_ptr, UINT iface_index) { UINT status; -UINT original_state; NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; @@ -2374,9 +2402,6 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; return(NX_DHCP_NOT_BOUND); } - /* Get the original state. */ - original_state = interface_record -> nx_dhcp_state; - /* Send the decline DHCP request. */ _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPDECLINE); @@ -2392,25 +2417,20 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* Set the retransmission interval. */ interface_record -> nx_dhcp_rtr_interval = 0; - /* Check if the state is changed. */ - if (original_state != interface_record -> nx_dhcp_state) + /* Determine if the application has specified a routine for DHCP state change notification. */ + if (dhcp_ptr -> nx_dhcp_state_change_callback) { - /* Determine if the application has specified a routine for DHCP state change notification. */ - if (dhcp_ptr -> nx_dhcp_state_change_callback) - { - - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); + } - /* Determine if the application has specified a routine for DHCP interface state change notification. */ - if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) - { + /* Determine if the application has specified a routine for DHCP interface state change notification. */ + if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) + { - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state); } /* Release the DHCP mutex. */ @@ -2628,7 +2648,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_interface_release PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2669,13 +2689,16 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcp_interface_release(NX_DHCP *dhcp_ptr, UINT iface_index) { UINT i; -UINT status, original_state; +UINT status; NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; @@ -2706,34 +2729,26 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; return(NX_DHCP_NOT_BOUND); } - /* Get the original state. */ - original_state = interface_record -> nx_dhcp_state; - /* Send the release DHCP request. */ _nx_dhcp_send_request_internal(dhcp_ptr, interface_record, NX_DHCP_TYPE_DHCPRELEASE); - /* Reinitialize DHCP. */ + /* Reinitialize DHCP. Note: the state is changed to NX_DHCP_STATE_NOT_STARTED in this function. */ _nx_dhcp_interface_reinitialize(dhcp_ptr, iface_index); - /* Check if the state is changed. */ - if (original_state != interface_record -> nx_dhcp_state) + /* Determine if the application has specified a routine for DHCP state change notification. */ + if (dhcp_ptr -> nx_dhcp_state_change_callback) { - /* Determine if the application has specified a routine for DHCP state change notification. */ - if (dhcp_ptr -> nx_dhcp_state_change_callback) - { - - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); + } - /* Determine if the application has specified a routine for DHCP interface state change notification. */ - if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) - { + /* Determine if the application has specified a routine for DHCP interface state change notification. */ + if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) + { - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record -> nx_dhcp_state); } /* Check if other interfaces are running DHCP. */ @@ -2753,20 +2768,15 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; return(NX_SUCCESS); } } - - /* Has DHCP stopped on all interfaces? */ - if (i == NX_DHCP_CLIENT_MAX_RECORDS) - { - - /* Yes, stop DHCP Thread. */ - tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread)); + + /* Yes, stop DHCP Thread. */ + tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread)); - /* Deactivate DHCP Timer. */ - tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer)); + /* Deactivate DHCP Timer. */ + tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer)); - /* Unbind UDP socket. */ - nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket)); - } + /* Unbind UDP socket. */ + nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket)); /* Release the DHCP mutex. */ tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex)); @@ -4009,7 +4019,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_interface_stop PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4055,6 +4065,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index) @@ -4062,7 +4075,6 @@ UINT _nx_dhcp_interface_stop(NX_DHCP *dhcp_ptr, UINT iface_index) UINT i; UINT status; -UINT original_state; NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; @@ -4081,9 +4093,6 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; return(status); } - /* Get the original state. */ - original_state = interface_record -> nx_dhcp_state; - /* Determine if DHCP is started. */ if (interface_record -> nx_dhcp_state == NX_DHCP_STATE_NOT_STARTED) { @@ -4098,25 +4107,20 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* Set the state to NX_DHCP_STATE_NOT_STARTED. */ interface_record -> nx_dhcp_state = NX_DHCP_STATE_NOT_STARTED; - /* Check if the state is changed. */ - if (original_state != interface_record -> nx_dhcp_state) + /* Determine if the application has specified a routine for DHCP state change notification. */ + if (dhcp_ptr -> nx_dhcp_state_change_callback) { - /* Determine if the application has specified a routine for DHCP state change notification. */ - if (dhcp_ptr -> nx_dhcp_state_change_callback) - { - - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_state); + } - /* Determine if the application has specified a routine for DHCP interface state change notification. */ - if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) - { + /* Determine if the application has specified a routine for DHCP interface state change notification. */ + if (dhcp_ptr -> nx_dhcp_interface_state_change_callback) + { - /* Yes, call the application's state change notify function with the new state. */ - (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record->nx_dhcp_state); - } + /* Yes, call the application's state change notify function with the new state. */ + (dhcp_ptr -> nx_dhcp_interface_state_change_callback)(dhcp_ptr, interface_record -> nx_dhcp_interface_index, interface_record->nx_dhcp_state); } /* Check if other interfaces are running DHCP. */ @@ -4136,20 +4140,15 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; return(NX_SUCCESS); } } - - /* Has DHCP stopped on all interfaces? */ - if (i == NX_DHCP_CLIENT_MAX_RECORDS) - { - /* Yes, stop DHCP Thread. */ - tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread)); + /* Yes, stop DHCP Thread. */ + tx_thread_suspend(&(dhcp_ptr -> nx_dhcp_thread)); - /* Deactivate DHCP Timer. */ - tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer)); + /* Deactivate DHCP Timer. */ + tx_timer_deactivate(&(dhcp_ptr -> nx_dhcp_timer)); - /* Unbind UDP socket. */ - nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket)); - } + /* Unbind UDP socket. */ + nx_udp_socket_unbind(&(dhcp_ptr -> nx_dhcp_socket)); /* Release the DHCP mutex. */ tx_mutex_put(&(dhcp_ptr->nx_dhcp_mutex)); @@ -4313,6 +4312,153 @@ UINT status; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_dhcp_user_option_request PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the DHCP user option function */ +/* call. */ +/* */ +/* INPUT */ +/* */ +/* dhcp_ptr Pointer to DHCP instance */ +/* option_code Option code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* NX_PTR_ERROR Invalid pointer input */ +/* */ +/* CALLS */ +/* */ +/* _nx_dhcp_user_option_request Actual DHCP user option */ +/* request function call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code) +{ + +UINT status; + + + /* Check for invalid input pointer. */ + if ((dhcp_ptr == NX_NULL) || (dhcp_ptr -> nx_dhcp_id != NX_DHCP_ID)) + return(NX_PTR_ERROR); + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call actual DHCP interface user option request service. */ + status = _nx_dhcp_user_option_request(dhcp_ptr, option_code); + + /* Return status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_dhcp_user_option_request PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function requests the additional user option. */ +/* */ +/* INPUT */ +/* */ +/* dhcp_ptr Pointer to DHCP instance */ +/* option_code Option code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Get the DHCP mutex */ +/* tx_mutex_put Release the DHCP mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code) +{ +UINT i; + + + /* Obtain DHCP Client protection mutex. */ + tx_mutex_get(&(dhcp_ptr -> nx_dhcp_mutex), TX_WAIT_FOREVER); + + /* Check if the default option array already has it. */ + for (i = 0; i < NX_DHCP_REQUEST_PARAMETER_SIZE; i++) + { + if (_nx_dhcp_request_parameters[i] == option_code) + { + tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex)); + return(NX_DUPLICATED_ENTRY); + } + } + + /* Check if the user option array already has it. */ + for (i = 0; i < dhcp_ptr -> nx_dhcp_user_request_parameter_size; i++) + { + if (dhcp_ptr -> nx_dhcp_user_request_parameter[i] == option_code) + { + tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex)); + return(NX_DUPLICATED_ENTRY); + } + } + + /* Check if there is space to add option. */ + if (dhcp_ptr -> nx_dhcp_user_request_parameter_size >= NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER) + { + tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex)); + return(NX_NO_MORE_ENTRIES); + } + + /* Add the option. */ + dhcp_ptr -> nx_dhcp_user_request_parameter[dhcp_ptr -> nx_dhcp_user_request_parameter_size++] = (UCHAR)option_code; + + /* Release the DHCP mutex. */ + tx_mutex_put(&(dhcp_ptr -> nx_dhcp_mutex)); + + /* Return success. */ + return(NX_SUCCESS); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -4810,7 +4956,7 @@ UINT _nx_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_ /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_udp_receive_notify PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4844,15 +4990,20 @@ UINT _nx_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* multiple client instances, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_dhcp_udp_receive_notify(NX_UDP_SOCKET *socket_ptr) { - NX_PARAMETER_NOT_USED(socket_ptr); +NX_DHCP *dhcp_ptr; + + dhcp_ptr = (NX_DHCP *)(socket_ptr -> nx_udp_socket_reserved_ptr); /* Set the data received event flag. */ - tx_event_flags_set(&(_nx_dhcp_created_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_RECEIVE_EVENT, TX_OR); + tx_event_flags_set(&(dhcp_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_RECEIVE_EVENT, TX_OR); } @@ -5086,7 +5237,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5136,6 +5287,9 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ VOID _nx_dhcp_packet_process(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, NX_PACKET *packet_ptr) @@ -5203,20 +5357,7 @@ ULONG probing_delay; /* Initialize the offset to the beginning of the packet buffer. */ offset = 0; status = nx_packet_data_extract_offset(packet_ptr, offset, (VOID *)new_packet_ptr -> nx_packet_prepend_ptr, (packet_ptr) -> nx_packet_length, &bytes_copied); - - /* Check status. */ - if ((status != NX_SUCCESS) || (bytes_copied == 0)) - { - - /* Release the allocated packet we'll never send. */ - nx_packet_release(new_packet_ptr); - - /* Release the original packet. */ - nx_packet_release(packet_ptr); - - /* Error extracting packet buffer, return error status. */ - return; - } + NX_ASSERT((status == NX_SUCCESS) && (bytes_copied > 0)); /* Update the new packet with the bytes copied. For chained packets, this will reflect the total 'datagram' length. */ @@ -5299,10 +5440,6 @@ ULONG probing_delay; /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */ interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout); - /* Check if the timeout is zero. */ - if (interface_record -> nx_dhcp_timeout == 0) - interface_record -> nx_dhcp_timeout = 1; - /* Update the state to Requesting state. */ interface_record -> nx_dhcp_state = NX_DHCP_STATE_REQUESTING; } @@ -5420,10 +5557,6 @@ ULONG probing_delay; /* Use the minimum value, Wait one second to begain in INIT state and forms a DHCP Discovery message. */ interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE; interface_record -> nx_dhcp_rtr_interval = 0; - - /* Check if the timeout is less than 1 second. */ - if (interface_record -> nx_dhcp_timeout < NX_IP_PERIODIC_RATE) - interface_record -> nx_dhcp_timeout = NX_IP_PERIODIC_RATE; } } break; @@ -5616,7 +5749,7 @@ ULONG probing_delay; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_timeout_process PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5660,6 +5793,9 @@ ULONG probing_delay; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ VOID _nx_dhcp_timeout_process(NX_DHCP *dhcp_ptr) @@ -5775,10 +5911,6 @@ NX_IP *ip_ptr; /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */ interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout); - /* Check if the timeout is zero. */ - if (interface_record -> nx_dhcp_timeout == 0) - interface_record -> nx_dhcp_timeout = 1; - break; } @@ -5802,10 +5934,6 @@ NX_IP *ip_ptr; /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */ interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout); - /* Check if the timeout is zero. */ - if (interface_record -> nx_dhcp_timeout == 0) - interface_record -> nx_dhcp_timeout = 1; - break; } @@ -5829,10 +5957,6 @@ NX_IP *ip_ptr; /* This will modify the timeout by up to +/- 1 second as recommended by RFC 2131, Section 4.1, Page 24. */ interface_record -> nx_dhcp_timeout = _nx_dhcp_add_randomize(interface_record -> nx_dhcp_timeout); - /* Check if the timeout is zero. */ - if (interface_record -> nx_dhcp_timeout == 0) - interface_record -> nx_dhcp_timeout = 1; - break; } @@ -6400,7 +6524,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_send_request_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6430,6 +6554,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* _nx_dhcp_add_option_value Add an option to the request */ /* _nx_dhcp_add_option_string Add an option string to the */ /* request */ +/* _nx_dhcp_add_option_parameter_request Add a parameter request option*/ /* nx_udp_socket_interface_send Send packet out on interface */ /* _nx_dhcp_client_send_with_zero_source_address */ /* Send broadcast packet with */ @@ -6455,6 +6580,14 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), supported*/ +/* adding additional request */ +/* option in parameter request,*/ +/* resulting in version 6.1.8 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), corrected*/ +/* the logic of adding server */ +/* identifier option, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UINT _nx_dhcp_send_request_internal(NX_DHCP *dhcp_ptr, NX_DHCP_INTERFACE_RECORD *interface_record, UINT dhcp_message_type) @@ -6619,8 +6752,8 @@ UINT name_length; (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index); } - /* Add an option request for DHCP parameters (gateway, subnet mask, etc.). */ - _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, NX_DHCP_REQUEST_PARAMETER_SIZE, _nx_dhcp_request_parameters, &index); + /* Add parameter request option. */ + _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index); #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION @@ -6673,7 +6806,8 @@ UINT name_length; /* Should add server ID if not renewing. */ if ((interface_record -> nx_dhcp_state != NX_DHCP_STATE_RENEWING) && (interface_record -> nx_dhcp_state != NX_DHCP_STATE_REBINDING) && - (interface_record -> nx_dhcp_server_ip != NX_BOOTP_BC_ADDRESS) + (interface_record -> nx_dhcp_server_ip != NX_BOOTP_BC_ADDRESS) && + (interface_record -> nx_dhcp_server_ip != NX_BOOTP_NO_ADDRESS) ) { @@ -6690,9 +6824,9 @@ UINT name_length; _nx_dhcp_store_data(buffer + NX_BOOTP_OFFSET_CLIENT_IP, 4, interface_record -> nx_dhcp_ip_address); } - /* Add the request for the DHCP parameters (gateway, subnet mask, etc.) if not renewing. */ - _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, NX_DHCP_REQUEST_PARAMETER_SIZE, _nx_dhcp_request_parameters, &index); - + /* Add parameter request option. */ + _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index); + #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION /* Add an option to specify the maximum length DHCP message that DHCP Client is willing to accept. @@ -6751,8 +6885,8 @@ UINT name_length; _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_HOST_NAME, name_length, (UCHAR *) dhcp_ptr -> nx_dhcp_name, &index); } - /* Add an option request for DHCP parameters (gateway, subnet mask, etc.). */ - _nx_dhcp_add_option_string(buffer, NX_DHCP_OPTION_DHCP_PARAMETERS, 1, &(interface_record -> nx_dhcp_user_option), &index); + /* Add parameter request option. */ + _nx_dhcp_add_option_parameter_request(dhcp_ptr, buffer, &index); /* Increment the number of Inform messages sent. */ interface_record -> nx_dhcp_informs_sent++; @@ -6858,7 +6992,7 @@ UINT name_length; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_client_send_with_zero_source_address PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6893,6 +7027,18 @@ UINT name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported new ip filter, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* set the IP header pointer, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* and solve inconformity with */ +/* udp socket send and ip */ +/* header add, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UINT _nx_dhcp_client_send_with_zero_source_address(NX_DHCP *dhcp_ptr, UINT iface_index, NX_PACKET *packet_ptr) @@ -6904,7 +7050,9 @@ NX_UDP_HEADER *udp_header_ptr; NX_IPV4_HEADER *ip_header_ptr; NX_INTERFACE *interface_ptr; ULONG ip_src_addr, ip_dest_addr; -UINT compute_checksum; +#if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) +UINT compute_checksum = 1; +#endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */ ULONG checksum; ULONG val; NX_IP_DRIVER driver_request; @@ -6972,18 +7120,16 @@ NX_IP_DRIVER driver_request; #ifdef NX_DISABLE_UDP_TX_CHECKSUM compute_checksum = 0; -#else /* NX_DISABLE_UDP_TX_CHECKSUM */ - compute_checksum = 1; #endif /* NX_DISABLE_UDP_TX_CHECKSUM */ #ifdef NX_ENABLE_INTERFACE_CAPABILITY if (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM) compute_checksum = 0; - else - compute_checksum = 1; #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#if defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) if (compute_checksum) +#endif /* defined(NX_DISABLE_UDP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */ { /* Yes, we need to compute the UDP checksum. */ checksum = _nx_ip_checksum_compute(packet_ptr, @@ -7024,6 +7170,8 @@ NX_IP_DRIVER driver_request; /* Setup the IP header pointer. */ ip_header_ptr = (NX_IPV4_HEADER *) packet_ptr -> nx_packet_prepend_ptr; + packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr; + packet_ptr -> nx_packet_ip_header_length = sizeof(NX_IPV4_HEADER); /* Build the first 32-bit word of the IP header. */ ip_header_ptr -> nx_ip_header_word_0 = (NX_IP_VERSION | socket_ptr -> nx_udp_socket_type_of_service | (0xFFFF & packet_ptr -> nx_packet_length)); @@ -7047,21 +7195,22 @@ NX_IP_DRIVER driver_request; NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_word_2); NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip); NX_CHANGE_ULONG_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip); - + #ifdef NX_DISABLE_IP_TX_CHECKSUM compute_checksum = 0; -#else /* NX_DISABLE_IP_TX_CHECKSUM */ +#elif defined(NX_ENABLE_INTERFACE_CAPABILITY) + /* Re-initialize the value back to the default initial value (i.e. 1) */ compute_checksum = 1; -#endif /* NX_DISABLE_IP_TX_CHECKSUM */ +#endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) */ #ifdef NX_ENABLE_INTERFACE_CAPABILITY if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM) compute_checksum = 0; - else - compute_checksum = 1; #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#if defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) if (compute_checksum) +#endif /* defined(NX_DISABLE_IP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) */ { checksum = _nx_ip_checksum_compute(packet_ptr, NX_IP_VERSION_V4, 20, NULL, NULL); @@ -7097,6 +7246,22 @@ NX_IP_DRIVER driver_request; return(NX_NOT_SUCCESSFUL); } } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Release mutex protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Return a not successful status. */ + return(NX_NOT_SUCCESSFUL); + } + } #endif /* NX_ENABLE_IP_PACKET_FILTER */ /* Build the driver request. */ @@ -7457,7 +7622,7 @@ ULONG value; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_get_option_value PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7497,6 +7662,9 @@ ULONG value; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UINT _nx_dhcp_get_option_value(UCHAR *bootp_message, UINT option, ULONG *value, UINT length) @@ -7511,46 +7679,44 @@ UINT option_length; option_message = &bootp_message[NX_BOOTP_OFFSET_OPTIONS]; option_length = length - NX_BOOTP_OFFSET_OPTIONS; - /* Find the option. */ - if ((option != NX_DHCP_OPTION_PAD) && (option != NX_DHCP_OPTION_END)) - { + /* There is no need to check whether the option is PAD or END here since no caller will pass these 2 options + and for denfensive purpose, the function below could check them and guarantee appropriate behaviour */ - /* Search the buffer for the option. */ - data = _nx_dhcp_search_buffer(option_message, option, option_length); + /* Search the buffer for the option. */ + data = _nx_dhcp_search_buffer(option_message, option, option_length); - /* Check to see if the option was found. */ - if (data != NX_NULL) + /* Check to see if the option was found. */ + if (data != NX_NULL) + { + + /* Check for the proper size. */ + if (*data > 4) { - /* Check for the proper size. */ - if (*data > 4) + /* Check for the gateway option. */ + if (option == NX_DHCP_OPTION_GATEWAYS) { - /* Check for the gateway option. */ - if (option == NX_DHCP_OPTION_GATEWAYS) - { - - /* Pickup the first gateway address. */ - *value = _nx_dhcp_get_data(data + 1, 4); - - /* For now, just disregard any additional gateway addresses. */ - return(NX_SUCCESS); - } - else - { + /* Pickup the first gateway address. */ + *value = _nx_dhcp_get_data(data + 1, 4); - /* Invalid size, return error. */ - return(NX_SIZE_ERROR); - } + /* For now, just disregard any additional gateway addresses. */ + return(NX_SUCCESS); } else { - /* Get the actual value. */ - *value = _nx_dhcp_get_data(data + 1, *data); - return(NX_SUCCESS); + /* Invalid size, return error. */ + return(NX_SIZE_ERROR); } } + else + { + + /* Get the actual value. */ + *value = _nx_dhcp_get_data(data + 1, *data); + return(NX_SUCCESS); + } } /* Return an error if not found. */ @@ -7686,12 +7852,80 @@ static UINT _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_dhcp_add_option_parameter_request PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This routine adds a DHCP parameter request option to the BootP */ +/* message in supplied buffer. Adding the option includes adding the */ +/* option code, length and option value. */ +/* */ +/* INPUT */ +/* */ +/* dhcp_ptr Pointer to DHCP instance */ +/* bootp_message Pointer to message buffer */ +/* index Index to write data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_dhcp_move_string Store option string */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_dhcp_send_request_internal Internal DHCP message send */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_dhcp_add_option_parameter_request(NX_DHCP *dhcp_ptr, UCHAR *bootp_message, UINT *index) +{ + + /* Store the option. */ + *(bootp_message + (*index)) = NX_DHCP_OPTION_DHCP_PARAMETERS; + (*index) ++; + + /* Store the option size. */ + *(bootp_message + (*index)) = (UCHAR)(NX_DHCP_REQUEST_PARAMETER_SIZE + dhcp_ptr -> nx_dhcp_user_request_parameter_size); + (*index) ++; + + /* Store the option value. */ + _nx_dhcp_move_string(bootp_message + (*index), _nx_dhcp_request_parameters, NX_DHCP_REQUEST_PARAMETER_SIZE); + (*index) += (UINT)NX_DHCP_REQUEST_PARAMETER_SIZE; + + /* Check if there are additional user options. */ + if (dhcp_ptr -> nx_dhcp_user_request_parameter_size) + { + _nx_dhcp_move_string(bootp_message + (*index), dhcp_ptr -> nx_dhcp_user_request_parameter, dhcp_ptr -> nx_dhcp_user_request_parameter_size); + (*index) += (UCHAR)dhcp_ptr -> nx_dhcp_user_request_parameter_size; + } + + /* Return a successful completion. */ + return(NX_SUCCESS); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_add_randomize PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7725,6 +7959,9 @@ static UINT _nx_dhcp_add_option_string(UCHAR *bootp_message, UINT option, UINT /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static ULONG _nx_dhcp_add_randomize(ULONG timeout) @@ -7747,7 +7984,7 @@ ULONG adjustment; if (timeout > (NX_IP_PERIODIC_RATE - adjustment)) timeout -= (ULONG)(NX_IP_PERIODIC_RATE - adjustment); else - timeout = 0; + timeout = 1; /* Set 1 here since the minmum tick for timeout shall be larger than 0 */ } else { @@ -7905,7 +8142,7 @@ static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout) /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_search_buffer PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7945,6 +8182,9 @@ static ULONG _nx_dhcp_update_renewal_timeout(ULONG timeout) /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UCHAR *_nx_dhcp_search_buffer(UCHAR *option_message, UINT option, UINT length) @@ -7961,9 +8201,14 @@ UINT size; /* Search as long as there are valid options. */ while (i < length - 1) { + /* Jump out when it reaches END option */ + if (*data == NX_DHCP_OPTION_END) + { + break; + } /* Simply skip any padding */ - if (*data == NX_DHCP_OPTION_PAD) + else if (*data == NX_DHCP_OPTION_PAD) { data++; @@ -8071,7 +8316,7 @@ ULONG value = 0; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_store_data PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8109,41 +8354,18 @@ ULONG value = 0; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static VOID _nx_dhcp_store_data(UCHAR *data, UINT size, ULONG value) { - - /* Make sure that data is left justified. */ - switch (size) - { - - case 1: - - value <<= 24; - break; - - case 2: - - value <<= 16; - break; - - case 3: - - value <<= 8; - break; - - default: - break; - } - /* Store the value. */ while (size-- > 0) { - - *data = (UCHAR) ((value >> 24) & 0xff); - data++; - value <<= 8; + *(data + size) = (UCHAR)(value & 0xff); + value >>= 8; } } @@ -8515,7 +8737,7 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_ip_conflict PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8552,21 +8774,44 @@ NX_DHCP_INTERFACE_RECORD *interface_record = NX_NULL; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* multiple client instances, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_dhcp_ip_conflict(NX_IP *ip_ptr, UINT iface_index, ULONG ip_address, ULONG physical_msw, ULONG physical_lsw) { - NX_PARAMETER_NOT_USED(ip_ptr); +TX_INTERRUPT_SAVE_AREA + +NX_DHCP *dhcp_ptr; + NX_PARAMETER_NOT_USED(ip_address); NX_PARAMETER_NOT_USED(physical_msw); NX_PARAMETER_NOT_USED(physical_lsw); - /* Set the interface index. */ - _nx_dhcp_created_ptr -> nx_dhcp_interface_conflict_flag |= (UINT)(1 << iface_index); + /* Disable interrupts. */ + TX_DISABLE + + /* Find the DHCP client. */ + for (dhcp_ptr = _nx_dhcp_created_ptr; dhcp_ptr; dhcp_ptr = dhcp_ptr -> nx_dhcp_created_next) + { + if (dhcp_ptr -> nx_dhcp_ip_ptr == ip_ptr) + { + + /* Set the interface index. */ + dhcp_ptr -> nx_dhcp_interface_conflict_flag |= (UINT)(1 << iface_index); + + /* Set the address conflict event flag. */ + tx_event_flags_set(&(_nx_dhcp_created_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_CONFLICT_EVENT, TX_OR); + + break; + } + } + + /* Restore interrupts. */ + TX_RESTORE - /* Set the address conflict event flag. */ - tx_event_flags_set(&(_nx_dhcp_created_ptr -> nx_dhcp_events), NX_DHCP_CLIENT_CONFLICT_EVENT, TX_OR); } #endif diff --git a/addons/dhcp/nxd_dhcp_client.h b/addons/dhcp/nxd_dhcp_client.h index 8ace0784..42c91e2b 100644 --- a/addons/dhcp/nxd_dhcp_client.h +++ b/addons/dhcp/nxd_dhcp_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dhcp_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,13 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), supported*/ +/* adding additional request */ +/* option in parameter request,*/ +/* resulting in version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* multiple client instances, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -129,6 +136,13 @@ extern "C" { #endif +/* Define the max number of user request parameter. + Subnet mask, gateway and dns server options are added in _nx_dhcp_request_parameters arrary by default. */ +#ifndef NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER +#define NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER 4 +#endif /* NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER */ + + /* Define the size of DHCP options buffer. */ /* A DHCP client must be prepared to receive DHCP messages with an 'options' field of at least length 312 octets. RFC 2131; Section 2. Protocol Summary. */ @@ -466,6 +480,10 @@ typedef struct NX_DHCP_STRUCT NX_DHCP_INTERFACE_RECORD nx_dhcp_interface_record[NX_DHCP_CLIENT_MAX_RECORDS]; /* Record of DHCP Client state on specific interface */ + UCHAR nx_dhcp_user_request_parameter[NX_DHCP_CLIENT_MAX_USER_REQUEST_PARAMETER]; + /* User request parameter */ + UINT nx_dhcp_user_request_parameter_size; + /* User request parameter size */ #ifdef NX_DHCP_CLIENT_SEND_MAX_DHCP_MESSAGE_OPTION ULONG nx_dhcp_max_dhcp_message_size; @@ -495,6 +513,9 @@ typedef struct NX_DHCP_STRUCT /* Define the callback function for adding specific DHCP user option. */ UINT (*nx_dhcp_user_option_add)(struct NX_DHCP_STRUCT *dhcp_ptr, UINT iface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length); + /* Define the link between other DHCP structures created by the application. */ + struct NX_DHCP_STRUCT *nx_dhcp_created_next; + /* This pointer is reserved for application specific use. */ void *nx_dhcp_reserved_ptr; @@ -525,6 +546,7 @@ typedef struct NX_DHCP_STRUCT #define nx_dhcp_stop _nx_dhcp_stop #define nx_dhcp_server_address_get _nx_dhcp_server_address_get #define nx_dhcp_state_change_notify _nx_dhcp_state_change_notify +#define nx_dhcp_user_option_request _nx_dhcp_user_option_request #define nx_dhcp_user_option_retrieve _nx_dhcp_user_option_retrieve #define nx_dhcp_user_option_convert _nx_dhcp_user_option_convert #define nx_dhcp_user_option_add_callback_set _nx_dhcp_user_option_add_callback_set @@ -572,6 +594,7 @@ typedef struct NX_DHCP_STRUCT #define nx_dhcp_stop _nxe_dhcp_stop #define nx_dhcp_server_address_get _nxe_dhcp_server_address_get #define nx_dhcp_state_change_notify _nxe_dhcp_state_change_notify +#define nx_dhcp_user_option_request _nxe_dhcp_user_option_request #define nx_dhcp_user_option_retrieve _nxe_dhcp_user_option_retrieve #define nx_dhcp_user_option_convert _nxe_dhcp_user_option_convert #define nx_dhcp_user_option_add_callback_set _nxe_dhcp_user_option_add_callback_set @@ -619,6 +642,7 @@ UINT nx_dhcp_start(NX_DHCP *dhcp_ptr); UINT nx_dhcp_stop(NX_DHCP *dhcp_ptr); UINT nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address); UINT nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state)); +UINT nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code); UINT nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size); ULONG nx_dhcp_user_option_convert(UCHAR *source_ptr); UINT nx_dhcp_user_option_add_callback_set(NX_DHCP *dhcp_ptr, UINT (*dhcp_user_option_add)(NX_DHCP *dhcp_ptr, UINT iface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length)); @@ -678,6 +702,8 @@ UINT _nxe_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_addres UINT _nx_dhcp_server_address_get(NX_DHCP *dhcp_ptr, ULONG *server_address); UINT _nxe_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state)); UINT _nx_dhcp_state_change_notify(NX_DHCP *dhcp_ptr, VOID (*dhcp_state_change_notify)(NX_DHCP *dhcp_ptr, UCHAR new_state)); +UINT _nxe_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code); +UINT _nx_dhcp_user_option_request(NX_DHCP *dhcp_ptr, UINT option_code); UINT _nxe_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size); UINT _nx_dhcp_user_option_retrieve(NX_DHCP *dhcp_ptr, UINT request_option, UCHAR *destination_ptr, UINT *destination_size); ULONG _nxe_dhcp_user_option_convert(UCHAR *source_ptr); diff --git a/addons/dhcp/nxd_dhcp_server.c b/addons/dhcp/nxd_dhcp_server.c index 4c02ad5f..90143562 100644 --- a/addons/dhcp/nxd_dhcp_server.c +++ b/addons/dhcp/nxd_dhcp_server.c @@ -2558,7 +2558,7 @@ CHAR *work_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_dhcp_parse_next_option PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2581,7 +2581,7 @@ CHAR *work_ptr; /* */ /* CALLS */ /* */ -/* atoi Convert ascii number to integer*/ +/* _nx_utility_string_to_uint Convert ascii number to integer*/ /* */ /* CALLED BY */ /* */ @@ -2594,6 +2594,9 @@ CHAR *work_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), fixed */ +/* obsolescent functions, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dhcp_parse_next_option(CHAR **option_list, UINT *option, UINT length) @@ -2656,10 +2659,8 @@ CHAR *buffer; *option_list += j; - /* Convert the number string to an actual integer. */ - *option = (UINT) atoi(num_string); - - return(NX_SUCCESS); + /* Convert the number string to an actual unsigned integer. */ + return(_nx_utility_string_to_uint(num_string, buffer_index, option)); } diff --git a/addons/dhcp/nxd_dhcp_server.h b/addons/dhcp/nxd_dhcp_server.h index 6b2a903e..6880f0d0 100644 --- a/addons/dhcp/nxd_dhcp_server.h +++ b/addons/dhcp/nxd_dhcp_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dhcp_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -49,6 +49,9 @@ /* improved buffer length */ /* verification, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -65,6 +68,7 @@ extern "C" { #endif +#include "nx_api.h" /* Define the DHCP Server ID that is used to mark the DHCP Server structure as created. */ diff --git a/addons/dhcp/nxd_dhcpv6_client.c b/addons/dhcp/nxd_dhcpv6_client.c index 26da0207..e88bf550 100644 --- a/addons/dhcp/nxd_dhcpv6_client.c +++ b/addons/dhcp/nxd_dhcpv6_client.c @@ -8315,7 +8315,7 @@ UCHAR original_state; /* FUNCTION RELEASE */ /* */ /* _nx_dhcpv6_send_request PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8374,6 +8374,9 @@ UCHAR original_state; /* verified memcpy use cases, */ /* fixed compiler warnings, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), supported*/ +/* adding user options, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dhcpv6_send_request(NX_DHCPV6 *dhcpv6_ptr) @@ -8387,6 +8390,8 @@ UINT index; NX_INTERFACE *interface_ptr; NXD_IPV6_ADDRESS *ipv6_address; ULONG available_payload; +UCHAR *user_option_ptr; +UINT user_option_length; /* Initialize local variables. */ @@ -9020,12 +9025,37 @@ ULONG available_payload; } } + /* Add any user supplied options to the buffer. */ + if (dhcpv6_ptr -> nx_dhcpv6_user_option_add) + { + + /* Set the pointer for adding user option. */ + user_option_ptr = buffer + index; + + /* Calculate the available length for user options. */ + user_option_length = (UINT)(packet_ptr -> nx_packet_data_end - user_option_ptr); + + /* Add the specific DHCP option user wanted. */ + if (dhcpv6_ptr -> nx_dhcpv6_user_option_add(dhcpv6_ptr, dhcpv6_ptr -> nx_dhcpv6_client_interface_index, dhcpv6_ptr -> nx_dhcpv6_message_hdr.nx_message_type, user_option_ptr, &user_option_length) == NX_TRUE) + { + + /* Update the index to include the user options. */ + index += user_option_length; + } + else + { + + /* Invalid user options. Release the packet. */ + nx_packet_release(packet_ptr); + return(NX_DHCPV6_UNKNOWN_OPTION); + } + } + /* Setup the packet pointers. */ packet_ptr -> nx_packet_length = index; packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + index; - /* Select Client Source address: 1. When a client sends a DHCP message to the All_DHCP_Relay_Agents_and_Servers address, the client must use a link-local address assigned to the interface for which it @@ -12082,6 +12112,124 @@ UINT _nx_dhcpv6_update_retransmit_info(NX_DHCPV6 *dhcpv6_ptr) } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_dhcpv6_user_option_add_callback_set PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs error checking on the user option add */ +/* callback set service. */ +/* */ +/* INPUT */ +/* */ +/* dhcpv6_ptr Pointer to DHCPv6 instance */ +/* dhcpv6_user_option_add Pointer to application's */ +/* option add function */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_dhcpv6_user_option_add_callback_set Actual user option callback */ +/* set service */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 07-29-2022 Yuxin Zhou Initial Version 6.1.12 */ +/* */ +/**************************************************************************/ +UINT _nxe_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type, + UCHAR *user_option_ptr, UINT *user_option_length)) +{ + +UINT status; + + /* Check for invalid input. */ + if ((dhcpv6_ptr == NX_NULL) || (dhcpv6_user_option_add == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual DHCPv6 user option callback set service. */ + status = _nx_dhcpv6_user_option_add_callback_set(dhcpv6_ptr, dhcpv6_user_option_add); + + /* Return status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_dhcpv6_user_option_add_callback_set PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the user option add callback. */ +/* */ +/* INPUT */ +/* */ +/* dhcpv6_ptr Pointer to DHCPv6 instance */ +/* dhcpv6_user_option_add Pointer to application's */ +/* option add function */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 07-29-2022 Yuxin Zhou Initial Version 6.1.12 */ +/* */ +/**************************************************************************/ +UINT _nx_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type, + UCHAR *user_option_ptr, UINT *user_option_length)) +{ + + /* Obtain DHCPv6 Client protection mutex. */ + tx_mutex_get(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex), TX_WAIT_FOREVER); + + /* Set the callback. */ + dhcpv6_ptr -> nx_dhcpv6_user_option_add = dhcpv6_user_option_add; + + /* Release the mutex. */ + tx_mutex_put(&(dhcpv6_ptr -> nx_dhcpv6_client_mutex)); + + /* Return a successful status. */ + return(NX_SUCCESS); +} + + #if !defined (NX_DISABLE_IPV6_DAD) && defined (NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY) /**************************************************************************/ /* */ diff --git a/addons/dhcp/nxd_dhcpv6_client.h b/addons/dhcp/nxd_dhcpv6_client.h index ad709eb8..56c1dda6 100644 --- a/addons/dhcp/nxd_dhcpv6_client.h +++ b/addons/dhcp/nxd_dhcpv6_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dhcpv6_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,12 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* packet length verification, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), supported*/ +/* adding user options, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -61,7 +67,8 @@ extern "C" { #endif - + +#include "nx_api.h" /* Enable support for DHCPv6 client state preserved between reboots */ /* @@ -753,6 +760,9 @@ typedef struct NX_DHCPV6_STRUCT option the status is referring to e.g. IA Address. */ VOID (*nx_dhcpv6_server_error_handler)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT op_code, UINT status_code, UINT message_type); + /* Define the callback function for adding specific DHCPv6 user option. */ + UINT (*nx_dhcpv6_user_option_add)(struct NX_DHCPV6_STRUCT *dhcpv6_ptr, UINT interface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length); + } NX_DHCPV6; @@ -829,6 +839,7 @@ typedef struct NX_DHCPV6_CLIENT_RECORD_STRUCT #define nx_dhcpv6_stop _nx_dhcpv6_stop #define nx_dhcpv6_suspend _nx_dhcpv6_suspend #define nx_dhcpv6_resume _nx_dhcpv6_resume +#define nx_dhcpv6_user_option_add_callback_set _nx_dhcpv6_user_option_add_callback_set #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE #define nx_dhcpv6_client_get_record _nx_dhcpv6_client_get_record #define nx_dhcpv6_client_restore_record _nx_dhcpv6_client_restore_record @@ -872,6 +883,7 @@ typedef struct NX_DHCPV6_CLIENT_RECORD_STRUCT #define nx_dhcpv6_stop _nxe_dhcpv6_stop #define nx_dhcpv6_suspend _nxe_dhcpv6_suspend #define nx_dhcpv6_resume _nxe_dhcpv6_resume +#define nx_dhcpv6_user_option_add_callback_set _nxe_dhcpv6_user_option_add_callback_set #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE #define nx_dhcpv6_client_get_record _nxe_dhcpv6_client_get_record #define nx_dhcpv6_client_restore_record _nxe_dhcpv6_client_restore_record @@ -916,6 +928,7 @@ UINT nx_dhcpv6_start(NX_DHCPV6 *dhcpv6_ptr); UINT nx_dhcpv6_stop(NX_DHCPV6 *dhcpv6_ptr); UINT nx_dhcpv6_suspend(NX_DHCPV6 *dhcpv6_ptr); UINT nx_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr); +UINT nx_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length)); #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE UINT nx_dhcpv6_client_get_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr); UINT nx_dhcpv6_client_restore_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr, ULONG time_elapsed); @@ -995,7 +1008,9 @@ UINT _nx_dhcpv6_stop(NX_DHCPV6 *dhcpv6_ptr); UINT _nxe_dhcpv6_suspend(NX_DHCPV6 *dhcpv6_ptr); UINT _nx_dhcpv6_suspend(NX_DHCPV6 *dhcpv6_ptr); UINT _nxe_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr); -UINT _nx_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr); +UINT _nx_dhcpv6_resume(NX_DHCPV6 *dhcpv6_ptr); +UINT _nxe_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length)); +UINT _nx_dhcpv6_user_option_add_callback_set(NX_DHCPV6 *dhcpv6_ptr, UINT (*dhcpv6_user_option_add)(NX_DHCPV6 *dhcpv6_ptr, UINT interface_index, UINT message_type, UCHAR *user_option_ptr, UINT *user_option_length)); #ifdef NX_DHCPV6_CLIENT_RESTORE_STATE UINT _nxe_dhcpv6_client_get_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr); UINT _nx_dhcpv6_client_get_record(NX_DHCPV6 *dhcpv6_ptr, NX_DHCPV6_CLIENT_RECORD *client_record_ptr); diff --git a/addons/dhcp/nxd_dhcpv6_server.c b/addons/dhcp/nxd_dhcpv6_server.c index a70a5575..b84c8072 100644 --- a/addons/dhcp/nxd_dhcpv6_server.c +++ b/addons/dhcp/nxd_dhcpv6_server.c @@ -5204,7 +5204,7 @@ ULONG bytes_copied = 0; /* FUNCTION RELEASE */ /* */ /* _nx_dhcpv6_send_response_to_client PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5243,6 +5243,9 @@ ULONG bytes_copied = 0; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_dhcpv6_send_response_to_client(NX_DHCPV6_SERVER *dhcpv6_server_ptr, NX_DHCPV6_CLIENT *dhcpv6_client_ptr) @@ -5412,8 +5415,7 @@ ULONG message_word; /* It does. Did the Client ask for a requested option? Only provide information if there are no status errors from the server. */ - if ((dhcpv6_client_ptr -> nx_dhcpv6_option_request.nx_op_request) && - (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS)) + if (dhcpv6_client_ptr -> nx_dhcpv6_iana_status.nx_status_code == NX_DHCPV6_STATUS_SUCCESS) { /* Add the option request. */ diff --git a/addons/dhcp/nxd_dhcpv6_server.h b/addons/dhcp/nxd_dhcpv6_server.h index ba6c8737..c72f24bc 100644 --- a/addons/dhcp/nxd_dhcpv6_server.h +++ b/addons/dhcp/nxd_dhcpv6_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dhcpv6_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,9 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* packet length verification, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -62,6 +65,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the DHCPv6 ID to mark the DHCPV6_CLIENT and DHCPV6_SERVER structures as created. */ #define NX_DHCPV6_CLIENT_ID 0x44484336UL diff --git a/addons/dns/nxd_dns.c b/addons/dns/nxd_dns.c index 9726beff..dc4cded7 100644 --- a/addons/dns/nxd_dns.c +++ b/addons/dns/nxd_dns.c @@ -45,7 +45,7 @@ /* Internal DNS functions. */ static UINT _nx_dns_header_create(UCHAR *buffer_ptr, USHORT id, USHORT flags); -static UINT _nx_dns_new_packet_create(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, USHORT id, UCHAR *name, USHORT type); +static UINT _nx_dns_new_packet_create(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *name, USHORT type); static UINT _nx_dns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr); static UINT _nx_dns_name_string_encode(UCHAR *ptr, UCHAR *name); static UINT _nx_dns_name_string_unencode(NX_PACKET *packet_ptr, UCHAR *data, UCHAR *buffer, UINT buffer_size); @@ -62,12 +62,13 @@ static UINT _nx_dns_number_to_ascii_convert(UINT number, CHAR *buffstring #endif /* NX_DISABLE_IPV4 */ static UINT _nx_dns_host_resource_data_by_name_get(NX_DNS *dns_ptr, UCHAR *host_name, UCHAR *record_buffer, UINT buffer_size, UINT *record_count, UINT lookup_type, ULONG wait_option); -static UINT _nx_dns_response_process(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); +static UINT _nx_dns_response_receive(NX_DNS *dns_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +static UINT _nx_dns_response_process(NX_DNS *dns_ptr, UCHAR *host_name, NX_PACKET *packet_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); static UINT _nx_dns_process_a_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count, UINT rr_location); static UINT _nx_dns_process_aaaa_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count, UINT rr_location); #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES -static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start); +static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length); static UINT _nx_dns_process_cname_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); static UINT _nx_dns_process_txt_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR *record_buffer, UINT buffer_size, UINT *record_count); static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, UCHAR **buffer_append_ptr, UINT *record_count); @@ -114,10 +115,8 @@ UCHAR lookup_end[] = "IN-ADDR.ARPA"; #ifdef NX_DNS_CACHE_ENABLE static NX_DNS_RR temp_rr; #endif /* NX_DNS_CACHE_ENABLE */ - -#if defined(NX_DNS_ENABLE_EXTENDED_RR_TYPES) || defined(NX_DNS_CACHE_ENABLE) + static UCHAR temp_string_buffer[NX_DNS_NAME_MAX + 1]; -#endif /* Record the temp host name,*/ #ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES @@ -193,7 +192,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dns_create PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -218,8 +217,6 @@ UINT status; /* */ /* nx_udp_socket_create Create DNS UDP socket */ /* nx_udp_socket_delete Delete DNS UDP socket */ -/* nx_udp_socket_bind Bind DNS UDP socket to port */ -/* nx_udp_socket_unbind Unbind DNS UDP socket */ /* tx_mutex_create Create a ThreadX mutex */ /* */ /* CALLED BY */ @@ -233,6 +230,12 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* randomized the source port, */ +/* resulting in version 6.1.4 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dns_create(NX_DNS *dns_ptr, NX_IP *ip_ptr, UCHAR *domain_name) @@ -261,42 +264,8 @@ UINT status; #endif /* Create the DNS UDP socket. */ - status = nx_udp_socket_create(ip_ptr, &(dns_ptr -> nx_dns_socket), "DNS Socket", - NX_DNS_TYPE_OF_SERVICE, NX_DNS_FRAGMENT_OPTION, NX_DNS_TIME_TO_LIVE, NX_DNS_QUEUE_DEPTH); - - /* Check status of socket create. */ - if (status != NX_SUCCESS) - { - -#ifndef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL - - /* Delete the packet pool. */ - nx_packet_pool_delete(dns_ptr -> nx_dns_packet_pool_ptr); -#endif - - /* Return the NetX error. */ - return(status); - } - - /* Bind the UDP socket to the DNS Client port. */ - status = nx_udp_socket_bind(&(dns_ptr -> nx_dns_socket), NX_ANY_PORT, TX_WAIT_FOREVER); - - /* Check status of socket bind. */ - if (status != NX_SUCCESS) - { - -#ifndef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL - - /* Delete the packet pool. */ - nx_packet_pool_delete(dns_ptr -> nx_dns_packet_pool_ptr); -#endif - - /* Delete the socket. */ - nx_udp_socket_delete(&(dns_ptr -> nx_dns_socket)); - - /* Return the NetX error. */ - return(status); - } + nx_udp_socket_create(ip_ptr, &(dns_ptr -> nx_dns_socket), "DNS Socket", + NX_DNS_TYPE_OF_SERVICE, NX_DNS_FRAGMENT_OPTION, NX_DNS_TIME_TO_LIVE, NX_DNS_QUEUE_DEPTH); /* Create a DNS mutex for multi-thread access protection. */ status = tx_mutex_create(&dns_ptr -> nx_dns_mutex, "DNS Mutex", TX_NO_INHERIT); @@ -311,9 +280,6 @@ UINT status; nx_packet_pool_delete(dns_ptr -> nx_dns_packet_pool_ptr); #endif - /* Unbind the socket. */ - nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); - /* Delete the socket. */ nx_udp_socket_delete(&(dns_ptr -> nx_dns_socket)); @@ -562,7 +528,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_dns_delete PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -583,7 +549,6 @@ UINT status; /* CALLS */ /* */ /* nx_udp_socket_delete Delete DNS UDP socket */ -/* nx_udp_socket_unbind Unbind DNS UDP socket */ /* tx_mutex_delete Delete DNS mutex */ /* */ /* CALLED BY */ @@ -597,6 +562,13 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* randomized the source port, */ +/* resulting in version 6.1.4 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s), */ +/* removed error checking for */ +/* nx_packet_pool_delete, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dns_delete(NX_DNS *dns_ptr) @@ -605,14 +577,6 @@ UINT _nx_dns_delete(NX_DNS *dns_ptr) UINT status; - /* Unbind the UDP socket. */ - status = nx_udp_socket_unbind(&dns_ptr -> nx_dns_socket); - - if (status != NX_SUCCESS) - { - /* Return the socket unbind error. */ - return status; - } /* Delete the DNS UDP socket. */ status = nx_udp_socket_delete(&dns_ptr -> nx_dns_socket); @@ -625,13 +589,8 @@ UINT status; #ifndef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL /* Delete the DNS packet pool. */ - status = nx_packet_pool_delete(dns_ptr -> nx_dns_packet_pool_ptr); + nx_packet_pool_delete(dns_ptr -> nx_dns_packet_pool_ptr); - if (status != NX_SUCCESS) - { - /* Return the packet pool delete error. */ - return status; - } #endif /* Delete the DNS mutex. */ @@ -799,7 +758,7 @@ NXD_ADDRESS dns_server_address; /* FUNCTION RELEASE */ /* */ /* _nxde_dns_server_add PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -833,6 +792,9 @@ NXD_ADDRESS dns_server_address; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s) and */ +/* simplified some branches, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nxde_dns_server_add(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) @@ -855,14 +817,6 @@ UINT status; return NX_DNS_PARAM_ERROR; } - /* Check for an invalid address type. */ - if ((server_address -> nxd_ip_version != NX_IP_VERSION_V4) && - (server_address -> nxd_ip_version != NX_IP_VERSION_V6)) - { - - return NX_DNS_INVALID_ADDRESS_TYPE; - } - /* Check if the server address is unspecified (::). */ if (server_address -> nxd_ip_version == NX_IP_VERSION_V6) { @@ -898,6 +852,10 @@ UINT status; return NX_DNS_INVALID_ADDRESS_TYPE; #endif /* NX_DISABLE_IPV4 */ } + else + { + return NX_DNS_INVALID_ADDRESS_TYPE; + } /* Check for appropriate caller. */ NX_THREADS_ONLY_CALLER_CHECKING @@ -966,7 +924,7 @@ UINT _nxd_dns_server_add(NX_DNS *dns_ptr, NXD_ADDRESS *dns_server_address) /* FUNCTION RELEASE */ /* */ /* _nx_dns_server_add_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1001,6 +959,9 @@ UINT _nxd_dns_server_add(NX_DNS *dns_ptr, NXD_ADDRESS *dns_server_address) /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s) and */ +/* simplified branches, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_dns_server_add_internal(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) @@ -1033,15 +994,17 @@ UINT i; #ifndef NX_DISABLE_IPV4 /* Is there a match? */ - if ((server_address -> nxd_ip_version == NX_IP_VERSION_V4) && - (dns_ptr -> nx_dns_server_ip_array[i].nxd_ip_address.v4 == server_address -> nxd_ip_address.v4)) + if (server_address -> nxd_ip_version == NX_IP_VERSION_V4) { + if (dns_ptr -> nx_dns_server_ip_array[i].nxd_ip_address.v4 == server_address -> nxd_ip_address.v4) + { - /* Error, release the mutex and return. */ - tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); + /* Error, release the mutex and return. */ + tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); - /* Yes, no need to add to the table, just return the 'error' status. */ - return NX_DNS_DUPLICATE_ENTRY; + /* Yes, no need to add to the table, just return the 'error' status. */ + return NX_DNS_DUPLICATE_ENTRY; + } } #else /* Error, release the mutex and return. */ @@ -1057,16 +1020,18 @@ UINT i; #ifdef FEATURE_NX_IPV6 /* Is there a match? */ - if ((server_address -> nxd_ip_version == NX_IP_VERSION_V6) && - CHECK_IPV6_ADDRESSES_SAME(&dns_ptr -> nx_dns_server_ip_array[i].nxd_ip_address.v6[0], - &(server_address -> nxd_ip_address.v6[0]))) + if (server_address -> nxd_ip_version == NX_IP_VERSION_V6) { + if (CHECK_IPV6_ADDRESSES_SAME(&dns_ptr -> nx_dns_server_ip_array[i].nxd_ip_address.v6[0], + &(server_address -> nxd_ip_address.v6[0]))) + { - /* Error, release the mutex and return. */ - tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); + /* Error, release the mutex and return. */ + tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); - /* Yes, no need to add to the table, just return the 'error' status. */ - return NX_DNS_DUPLICATE_ENTRY; + /* Yes, no need to add to the table, just return the 'error' status. */ + return NX_DNS_DUPLICATE_ENTRY; + } } #else /* Error, release the mutex and return. */ @@ -1273,7 +1238,7 @@ NXD_ADDRESS dns_server_address; /* FUNCTION RELEASE */ /* */ /* _nxde_dns_server_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1308,6 +1273,10 @@ NXD_ADDRESS dns_server_address; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s) and */ +/* simplified check for */ +/* invalid address types, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nxde_dns_server_remove(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) @@ -1321,14 +1290,6 @@ UINT status; return(NX_PTR_ERROR); } - /* Check for an invalid address type. */ - if ((server_address -> nxd_ip_version != NX_IP_VERSION_V4) && - (server_address -> nxd_ip_version != NX_IP_VERSION_V6)) - { - - return NX_DNS_INVALID_ADDRESS_TYPE; - } - /* Check if the server address is unspecified (::). */ if (server_address -> nxd_ip_version == NX_IP_VERSION_V6) { @@ -1364,6 +1325,10 @@ UINT status; return NX_DNS_INVALID_ADDRESS_TYPE; #endif /* NX_DISABLE_IPV4 */ } + else + { + return NX_DNS_INVALID_ADDRESS_TYPE; + } /* Check for appropriate caller. */ NX_THREADS_ONLY_CALLER_CHECKING @@ -1435,7 +1400,7 @@ UINT _nxd_dns_server_remove(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) /* FUNCTION RELEASE */ /* */ /* _nx_dns_server_remove_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1473,6 +1438,9 @@ UINT _nxd_dns_server_remove(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Jidesh Veeramachaneni Modified comment(s) and */ +/* removed null IP checks, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UINT _nx_dns_server_remove_internal(NX_DNS *dns_ptr, NXD_ADDRESS *server_address) @@ -1517,50 +1485,24 @@ UINT found_match; } #else { - /* Check for a null address. */ - if (!CHECK_UNSPECIFIED_ADDRESS(&DNSserver_array[i].nxd_ip_address.v6[0])) + /* Determine if this entry matches the specified DNS server. */ + if (CHECK_IPV6_ADDRESSES_SAME(&DNSserver_array[i].nxd_ip_address.v6[0], &(server_address -> nxd_ip_address.v6[0]))) { - /* No null; Determine if this entry matches the specified DNS server. */ - if (CHECK_IPV6_ADDRESSES_SAME(&DNSserver_array[i].nxd_ip_address.v6[0], &(server_address -> nxd_ip_address.v6[0]))) - { - - found_match = NX_TRUE; - break; - } - } - /* Check for a null address. */ - else - { - - /* Error, release the mutex and return. */ - tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); - return NX_DNS_BAD_ADDRESS_ERROR; + found_match = NX_TRUE; + break; } } #endif else if (DNSserver_array[i].nxd_ip_version == NX_IP_VERSION_V4) #ifndef NX_DISABLE_IPV4 { - - /* Check for a null address. */ - if (DNSserver_array[i].nxd_ip_address.v4 != IP_ADDRESS(0, 0, 0, 0)) + /* Determine if this entry matches the specified DNS server. */ + if (DNSserver_array[i].nxd_ip_address.v4 == server_address -> nxd_ip_address.v4) { - - /* Determine if this entry matches the specified DNS server. */ - if (DNSserver_array[i].nxd_ip_address.v4 == server_address -> nxd_ip_address.v4) - { - found_match = NX_TRUE; - break; - } - } - else - { - - /* Error, release the mutex and return. */ - tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); - return NX_DNS_INVALID_ADDRESS_TYPE; + found_match = NX_TRUE; + break; } } #else @@ -3909,7 +3851,7 @@ UINT record_count = 0; /* FUNCTION RELEASE */ /* */ /* _nx_dns_host_resource_data_by_name_get PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3943,6 +3885,8 @@ UINT record_count = 0; /* query on supplied host name */ /* tx_mutex_get Get DNS protection mutex */ /* tx_mutex_put Release DNS protection mutex */ +/* nx_udp_socket_bind Bind DNS UDP socket to port */ +/* nx_udp_socket_unbind Unbind DNS UDP socket */ /* */ /* CALLED BY */ /* */ @@ -3955,6 +3899,13 @@ UINT record_count = 0; /* 09-30-2020 Yuxin Zhou Modified comment(s), corrected*/ /* the timeout of first query, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* randomized the source port, */ +/* resulting in version 6.1.4 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ static UINT _nx_dns_host_resource_data_by_name_get(NX_DNS *dns_ptr, UCHAR *host_name, @@ -4007,7 +3958,19 @@ UINT i; /* At least one DNS server is required - return an error. */ return(NX_DNS_NO_SERVER); - } + } + + /* Bind the UDP socket to random port for each query. */ + status = nx_udp_socket_bind(&(dns_ptr -> nx_dns_socket), NX_ANY_PORT, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Release the DNS Client lock. */ + tx_mutex_put(&dns_ptr -> nx_dns_mutex); + return(status); + } /* Limit the timeout to NX_DNS_MAX_RETRANS_TIMEOUT. */ if (wait_option > NX_DNS_MAX_RETRANS_TIMEOUT) @@ -4033,12 +3996,43 @@ UINT i; if (status == NX_SUCCESS) { + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + /* Release the mutex */ tx_mutex_put(&dns_ptr -> nx_dns_mutex); /* Yes, have done, just return success. */ return NX_SUCCESS; - } + } + else + { + + /* Let application controls query retransmission for non-blocking. */ + if (wait_option == NX_NO_WAIT) + { + + /* Check if the query is sent out. */ + if (status == NX_IN_PROGRESS) + { + + /* No need to release mutex and unbind the socket for non-blocking since + _nx_dns_response_get will receive the response and release the resource. */ + return(status); + } + else + { + + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + + /* Release the mutex */ + tx_mutex_put(&dns_ptr -> nx_dns_mutex); + + return(status); + } + } + } } /* Timed out for querying all DNS servers in this cycle, double the timeout, limited to NX_DNS_MAX_RETRANS_TIMEOUT. */ @@ -4048,6 +4042,9 @@ UINT i; wait_option = NX_DNS_MAX_RETRANS_TIMEOUT; } + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + /* Release protection. */ tx_mutex_put(&dns_ptr -> nx_dns_mutex); @@ -4061,7 +4058,7 @@ UINT i; /* FUNCTION RELEASE */ /* */ /* _nx_dns_send_query_by_address PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4114,6 +4111,12 @@ UINT i; /* status check to improve */ /* buffer bound check, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* improved id generation, */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_send_query_by_address(NX_DNS *dns_ptr, NXD_ADDRESS *dns_server, UCHAR *ip_question, UCHAR *host_name_ptr, @@ -4124,18 +4127,11 @@ UINT status; USHORT answerCount; UCHAR *data_ptr; NX_PACKET *packet_ptr; -NX_PACKET *receive_packet_ptr; -USHORT id; +NX_PACKET *receive_packet_ptr; UINT ip_question_size; UINT name_size; UINT resource_type; UINT resource_size; -#ifdef NX_DNS_CLIENT_CLEAR_QUEUE -ULONG start_time; -ULONG current_time; -ULONG elapsed_time; -ULONG time_remaining; -#endif #ifdef NX_DNS_CACHE_ENABLE ULONG rr_ttl; #endif /* NX_DNS_CACHE_ENABLE */ @@ -4148,26 +4144,6 @@ ULONG rr_ttl; return(NX_DNS_SIZE_ERROR); } - /* Create a random DNS query ID based on the first word of an IP address (or only - word for IPv4 addresses). */ - if (dns_server -> nxd_ip_version == NX_IP_VERSION_V6) - { - -#ifdef FEATURE_NX_IPV6 - id = (USHORT)(dns_server -> nxd_ip_address.v6[0] ^ tx_time_get()); -#else - return NX_DNS_IPV6_NOT_SUPPORTED; -#endif - } - else - { -#ifndef NX_DISABLE_IPV4 - id = (USHORT)(dns_server -> nxd_ip_address.v4 ^ tx_time_get()); -#else - return NX_DNS_BAD_ADDRESS_ERROR; -#endif - } - /* Allocate a packet. */ status = nx_packet_allocate(dns_ptr -> nx_dns_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_DNS_PACKET_ALLOCATE_TIMEOUT); @@ -4180,7 +4156,7 @@ ULONG rr_ttl; } /* Create a request */ - status = _nx_dns_new_packet_create(dns_ptr, packet_ptr, id, ip_question, NX_DNS_RR_TYPE_PTR); + status = _nx_dns_new_packet_create(dns_ptr, packet_ptr, ip_question, NX_DNS_RR_TYPE_PTR); /* Check the DNS packet create status. */ if (status != NX_SUCCESS) @@ -4192,25 +4168,16 @@ ULONG rr_ttl; return(status); } - /* First clear off any 'old' DNS packets. */ - -#ifdef NX_DNS_CLIENT_CLEAR_QUEUE - /* We will use the time spent sleeping to clear broadcast DNS packets from a previous query - from the DNS receive queue. This will prevent ensure the most recent DNS response is - processed and avoid the situation of valid DNS response packets overflowing the DNS socket - queue. */ - - receive_packet_ptr = NX_NULL; - - - /* Remove all packets from the DNS Client receive queue. */ - status = NX_SUCCESS;; + from the DNS receive queue. This will prevent ensure the most recent DNS response is + processed and avoid the situation of valid DNS response packets overflowing the DNS socket + queue. */ +#ifdef NX_DNS_CLIENT_CLEAR_QUEUE do { /* Is there any packets on the queue? */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, 1 ); + status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, NX_NO_WAIT); /* Yes, we received a packet on the DNS port! */ if (status == NX_SUCCESS) @@ -4221,15 +4188,12 @@ ULONG rr_ttl; } /* Keep checking till the queue becomes empty. */ - - } while(status == NX_SUCCESS); - -#endif + } while(status == NX_SUCCESS); +#endif /* NX_DNS_CLIENT_CLEAR_QUEUE */ /* Send the DNS packet out. */ status = nxd_udp_socket_send(&dns_ptr -> nx_dns_socket, packet_ptr, dns_server, NX_DNS_PORT); - /* Check the completion of the send. */ if (status != NX_SUCCESS) { @@ -4240,69 +4204,8 @@ ULONG rr_ttl; return status; } -#ifdef NX_DNS_CLIENT_CLEAR_QUEUE - - /* Initialize the value. */ - elapsed_time = 0; - time_remaining = wait_option; - - /* If waiting for the DNS 'sleep' interval, check for packets arriving on the queue. */ - while(time_remaining > 0) - { - - start_time = tx_time_get(); - - /* Check if some of these packet are intended for other hosts. */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, time_remaining); - - /* Determine if this one is for us. */ - if (status == NX_SUCCESS) - { - - /* Check the ID from the Client query matches the ID in the received DNS packet. */ - if (_nx_dns_network_to_short_convert(receive_packet_ptr -> nx_packet_prepend_ptr + NX_DNS_ID_OFFSET) == id) - { - /* They do. We can stop receiving packets and process this one. */ - break; - } - else - { - /* They do not. Discard the packet! */ - nx_packet_release(receive_packet_ptr); - } - } - - /* Get the current time. */ - current_time = tx_time_get(); - - /* Has the time wrapped? */ - if (current_time >= start_time) - { - /* No, simply subtract to get the elapsed time. */ - elapsed_time = current_time - start_time; - } - else - { - /* Yes it has. Time has rolled over the 32-bit boundary. */ - elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time; - } - - /* Update the time remaining by subtracting the elapsed time. */ - if (time_remaining > elapsed_time) - { - time_remaining -= elapsed_time; - } - else - { - time_remaining = 0; - } - } - -#else - - /* Otherwise, wait for a DNS response UDP packet. */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, wait_option); -#endif + /* Wait for a DNS response. */ + status = _nx_dns_response_receive(dns_ptr, &receive_packet_ptr, wait_option); /* Check status. */ if (status == NX_SUCCESS) @@ -4329,7 +4232,7 @@ ULONG rr_ttl; } /* Packet is long enough. Check the IDs in the DNS header match. */ - if (_nx_dns_network_to_short_convert(receive_packet_ptr -> nx_packet_prepend_ptr + NX_DNS_ID_OFFSET) != id) + if (_nx_dns_network_to_short_convert(receive_packet_ptr -> nx_packet_prepend_ptr + NX_DNS_ID_OFFSET) != dns_ptr -> nx_dns_transmit_id) { /* No; Release the packet. */ @@ -4562,7 +4465,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_send_query_get_rdata_by_name PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4577,6 +4480,7 @@ ULONG rr_ttl; /* */ /* dns_ptr Pointer to DNS instance */ /* server_address The DNS server address */ +/* host_name Name of host to resolve */ /* record_buffer Buffer for resource data */ /* buffer_size Buffer size for resource data */ /* record_count The count of resource data */ @@ -4592,8 +4496,7 @@ ULONG rr_ttl; /* _nx_dns_new_packet_create Create new DNS packet */ /* nx_packet_release Release packet */ /* nxd_udp_socket_send Send DNS UDP packet */ -/* nx_udp_socket_receive Receive DNS UDP packet */ -/* _nx_dns_response_process Process the DNS respondse */ +/* _nx_dns_response_get Get DNS response */ /* */ /* CALLED BY */ /* */ @@ -4607,6 +4510,15 @@ ULONG rr_ttl; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.4 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ static UINT _nx_dns_send_query_get_rdata_by_name(NX_DNS *dns_ptr, NXD_ADDRESS *dns_server_address, @@ -4616,18 +4528,10 @@ static UINT _nx_dns_send_query_get_rdata_by_name(NX_DNS *dns_ptr, NXD_ADDRESS *d UINT status; NX_PACKET *packet_ptr; -NX_PACKET *receive_packet_ptr; -USHORT id; #ifdef NX_DNS_CLIENT_CLEAR_QUEUE -ULONG start_time; -ULONG current_time; -ULONG elapsed_time; -ULONG time_remaining; -#endif +NX_PACKET *receive_packet_ptr; +#endif /* NX_DNS_CLIENT_CLEAR_QUEUE */ - /* Generate a random ID based on host name. */ - id = (USHORT)((ALIGN_TYPE) host_name ^ tx_time_get()); - /* Allocate a packet. */ status = nx_packet_allocate(dns_ptr -> nx_dns_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_DNS_PACKET_ALLOCATE_TIMEOUT); @@ -4640,7 +4544,7 @@ ULONG time_remaining; } /* Create a request */ - status = _nx_dns_new_packet_create(dns_ptr, packet_ptr, id, host_name, (USHORT)dns_record_type); + status = _nx_dns_new_packet_create(dns_ptr, packet_ptr, host_name, (USHORT)dns_record_type); /* Check the DNS packet create status. */ if (status != NX_SUCCESS) @@ -4652,21 +4556,16 @@ ULONG time_remaining; return(status); } - /* First clear off any 'old' DNS packets. */ -#ifdef NX_DNS_CLIENT_CLEAR_QUEUE - - /* Initialize the value */ - receive_packet_ptr = NX_NULL; - - /* Remove all packets from the DNS Client receive queue. */ - status = NX_SUCCESS;; + /* We will use the time spent sleeping to clear broadcast DNS packets from a previous query + from the DNS receive queue. This will prevent ensure the most recent DNS response is + processed and avoid the situation of valid DNS response packets overflowing the DNS socket + queue. */ +#ifdef NX_DNS_CLIENT_CLEAR_QUEUE do { - start_time = tx_time_get(); - /* Is there any packets on the queue? */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, 1 ); + status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, NX_NO_WAIT); /* Yes, we received a packet on the DNS port! */ if (status == NX_SUCCESS) @@ -4677,9 +4576,8 @@ ULONG time_remaining; } /* Keep checking till the queue becomes empty. */ - - } while(status == NX_SUCCESS); -#endif + } while(status == NX_SUCCESS); +#endif /* NX_DNS_CLIENT_CLEAR_QUEUE */ /* Send the DNS packet out. */ status = nxd_udp_socket_send(&dns_ptr -> nx_dns_socket, packet_ptr, dns_server_address, NX_DNS_PORT); @@ -4694,27 +4592,182 @@ ULONG time_remaining; return status; } -#ifdef NX_DNS_CLIENT_CLEAR_QUEUE + /* Check for non-blocking. */ + if (wait_option == NX_NO_WAIT) + { + return(NX_IN_PROGRESS); + } + + /* Wait for a DNS response. */ + status = _nx_dns_response_get(dns_ptr, host_name, record_buffer, buffer_size, record_count, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_dns_response_get PORTABLE C */ +/* 6.1.5 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets dns response. */ +/* */ +/* INPUT */ +/* */ +/* dns_ptr Pointer to DNS instance */ +/* host_name Name of host to resolve */ +/* record_buffer Buffer for resource data */ +/* buffer_size Buffer size for resource data */ +/* record_count The count of resource data */ +/* wait_option Timeout value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_dns_response_receive Receive DNS response */ +/* _nx_dns_response_process Process the DNS respondse */ +/* nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_dns_send_query_get_rdata_by_name Get the resource data by name */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 03-02-2021 Yuxin Zhou Initial Version 6.1.5 */ +/* */ +/**************************************************************************/ +UINT _nx_dns_response_get(NX_DNS *dns_ptr, UCHAR *host_name, UCHAR *record_buffer, + UINT buffer_size, UINT *record_count, ULONG wait_option) +{ +UINT status; +NX_PACKET *packet_ptr; + + + /* Wait for a DNS response. */ + status = _nx_dns_response_receive(dns_ptr, &packet_ptr, wait_option); + + /* Check status. */ + if (status == NX_SUCCESS) + { + +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) + { + + /* Chained packet is not supported. */ + nx_packet_release(packet_ptr); + + /* Release the resource obtained in _nx_dns_host_resource_data_by_name_get for non-blocking. */ + if (wait_option == NX_NO_WAIT) + { + + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + tx_mutex_put(&dns_ptr -> nx_dns_mutex); + } + + return(NX_INVALID_PACKET); + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* Call the function to process the DNS packet. */ + status = _nx_dns_response_process(dns_ptr, host_name, packet_ptr, record_buffer, buffer_size, record_count); + } + + /* Release the resource obtained in _nx_dns_host_resource_data_by_name_get for non-blocking. */ + if (wait_option == NX_NO_WAIT) + { + + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + tx_mutex_put(&dns_ptr -> nx_dns_mutex); + } + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_dns_response_receive PORTABLE C */ +/* 6.1.4 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives dns response. */ +/* */ +/* INPUT */ +/* */ +/* dns_ptr Pointer to DNS instance */ +/* packet_ptr Pointer to UDP packet pointer */ +/* wait_option Timeout value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_time_get Get the system time */ +/* nx_udp_socket_receive Receive DNS UDP packet */ +/* nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_dns_send_query_get_rdata_by_name Get the resource data by name */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 02-02-2021 Yuxin Zhou Initial Version 6.1.4 */ +/* */ +/**************************************************************************/ +static UINT _nx_dns_response_receive(NX_DNS *dns_ptr, NX_PACKET **packet_ptr, ULONG wait_option) +{ + +UINT status; +ULONG start_time; +ULONG current_time; +ULONG elapsed_time; +ULONG time_remaining; + /* Initialize the value. */ + start_time = tx_time_get(); elapsed_time = 0; time_remaining = wait_option; - /* If waiting for the DNS 'sleep' interval, check for packets arriving on the queue. */ - while(time_remaining > 0) + do { - start_time = tx_time_get(); - - /* Check if some of these packet are intended for other hosts. */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, time_remaining); + /* Receive udp packet. */ + status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), packet_ptr, time_remaining); /* Determine if this one is for us. */ if (status == NX_SUCCESS) { /* Check the IDs in the DNS header match. */ - if (_nx_dns_network_to_short_convert(receive_packet_ptr -> nx_packet_prepend_ptr + NX_DNS_ID_OFFSET) == id) + if (((*packet_ptr) -> nx_packet_length >= sizeof(USHORT)) && + (_nx_dns_network_to_short_convert((*packet_ptr) -> nx_packet_prepend_ptr + NX_DNS_ID_OFFSET) == dns_ptr -> nx_dns_transmit_id)) { /* They do. We can stop receiving packets and process this one. */ @@ -4724,24 +4777,31 @@ ULONG time_remaining; { /* They do not. Discard the packet! */ - nx_packet_release(receive_packet_ptr); + nx_packet_release((*packet_ptr)); + + /* Continue to receive next packet. */ + if (time_remaining == 0) + { + continue; + } } } /* Get the current time. */ - current_time = tx_time_get(); + current_time = tx_time_get(); /* Has the time wrapped? */ if (current_time >= start_time) { + /* No, simply subtract to get the elapsed time. */ - elapsed_time = current_time - start_time; + elapsed_time = current_time - start_time; } else { /* Yes it has. Time has rolled over the 32-bit boundary. */ - elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time; + elapsed_time = (((ULONG) 0xFFFFFFFF) - start_time) + current_time; } /* Update the time remaining with the elapsed time. */ @@ -4750,45 +4810,22 @@ ULONG time_remaining; time_remaining -= elapsed_time; } else - time_remaining = 0; - - } - -#else - - /* Otherwise, wait for a DNS response UDP packet. */ - status = nx_udp_socket_receive(&(dns_ptr -> nx_dns_socket), &receive_packet_ptr, wait_option); -#endif - - /* Check status. */ - if (status == NX_SUCCESS) - { - -#ifndef NX_DISABLE_PACKET_CHAIN - if (receive_packet_ptr -> nx_packet_next) { - - /* Chained packet is not supported. */ - nx_packet_release(receive_packet_ptr); - return(NX_INVALID_PACKET); + time_remaining = 0; } -#endif /* NX_DISABLE_PACKET_CHAIN */ - /* Call the function to process the DNS packet. */ - status = _nx_dns_response_process(dns_ptr, receive_packet_ptr, record_buffer, buffer_size, record_count); - } + } while(time_remaining > 0); /* Return completion status. */ return(status); } - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_dns_response_process PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4802,6 +4839,7 @@ ULONG time_remaining; /* INPUT */ /* */ /* dns_ptr Pointer to DNS instance */ +/* host_name Name of host to resolve */ /* packet_ptr Pointer to received packet */ /* record_buffer Buffer for resource data */ /* buffer_size Buffer size for resource data */ @@ -4841,10 +4879,14 @@ ULONG time_remaining; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ -static UINT _nx_dns_response_process(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *record_buffer, - UINT buffer_size, UINT *record_count) +static UINT _nx_dns_response_process(NX_DNS *dns_ptr, UCHAR *host_name, NX_PACKET *packet_ptr, + UCHAR *record_buffer, UINT buffer_size, UINT *record_count) { UINT status; @@ -4861,6 +4903,7 @@ UINT rr_location; UINT answer_found = NX_FALSE; UINT resource_size; UINT name_size; +UINT host_name_size; /* Set the buffer pointer. */ buffer_prepend_ptr = record_buffer; @@ -4930,7 +4973,7 @@ UINT name_size; { /* Get name size */ - name_size = _nx_dns_name_size_calculate(data_ptr, packet_ptr); + name_size = _nx_dns_name_string_unencode(packet_ptr, data_ptr, temp_string_buffer, NX_DNS_NAME_MAX); if (!name_size) { @@ -4941,6 +4984,44 @@ UINT name_size; return NX_DNS_MALFORMED_PACKET; } + /* Check for name. */ + if (_nx_utility_string_length_check((CHAR *)host_name, &host_name_size, name_size) || + (name_size != host_name_size) || + (memcmp(host_name, temp_string_buffer, name_size) != 0)) + { + + /* Release the source packet. */ + nx_packet_release(packet_ptr); + + /* This was not what the Client requested. Return error status. */ + return(NX_DNS_MISMATCHED_RESPONSE); + } + + /* Get the length of name field. */ + name_size = _nx_dns_name_size_calculate(data_ptr, packet_ptr); + + /* Check if the data pointer is valid. */ + if (data_ptr + name_size + 4 >= packet_ptr -> nx_packet_append_ptr) + { + + /* Release the source packet. */ + nx_packet_release(packet_ptr); + + return(NX_DNS_MALFORMED_PACKET); + } + + /* Check the type and class. */ + if ((_nx_dns_network_to_short_convert(data_ptr + name_size) != dns_ptr -> nx_dns_lookup_type) || + (_nx_dns_network_to_short_convert(data_ptr + name_size + 2) != NX_DNS_RR_CLASS_IN)) + { + + /* Release the source packet. */ + nx_packet_release(packet_ptr); + + /* This was not what the Client requested. Return error status. */ + return(NX_DNS_MISMATCHED_RESPONSE); + } + /* Yes, the question is present in the response, skip it! */ data_ptr += name_size + 4; } @@ -5096,7 +5177,7 @@ UINT name_size; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_a_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5145,6 +5226,9 @@ UINT name_size; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_a_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -5233,7 +5317,7 @@ ULONG rr_ttl; /* Get data address and check if it is valid. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + sizeof(ULONG)) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -5346,7 +5430,12 @@ ULONG rr_ttl; continue; } - if((memcmp(ns_entry -> nx_dns_ns_hostname_ptr, &temp_string_buffer[0], name_size)) == 0) + /* The nx_dns_ns_hostname_ptr is set internally with null termination. */ + status = _nx_utility_string_length_check((CHAR *)(ns_entry -> nx_dns_ns_hostname_ptr), &data_length, name_size); + + if((status == NX_SUCCESS) && + (data_length == name_size) && + ((memcmp(ns_entry -> nx_dns_ns_hostname_ptr, &temp_string_buffer[0], name_size)) == 0)) { /* This A type record contains the IPv4 address for the NS entry. */ @@ -5365,7 +5454,7 @@ ULONG rr_ttl; /* Get data address and check if it is valid. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + sizeof(ULONG)) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -5432,7 +5521,12 @@ ULONG rr_ttl; continue; } - if((memcmp(mx_entry -> nx_dns_mx_hostname_ptr, &temp_string_buffer[0], name_size)) == 0) + /* The nx_dns_mx_hostname_ptr is set internally with null termination. */ + status = _nx_utility_string_length_check((CHAR *)(mx_entry -> nx_dns_mx_hostname_ptr), &data_length, name_size); + + if((status == NX_SUCCESS) && + (data_length == name_size) && + ((memcmp(mx_entry -> nx_dns_mx_hostname_ptr, &temp_string_buffer[0], name_size)) == 0)) { /* This A type record contains the IPv4 address for the MX entry. */ @@ -5451,7 +5545,7 @@ ULONG rr_ttl; /* Get data address and check if it is valid. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + sizeof(ULONG)) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -5517,7 +5611,12 @@ ULONG rr_ttl; continue; } - if((memcmp(srv_entry -> nx_dns_srv_hostname_ptr, &temp_string_buffer[0], name_size)) == 0) + /* The nx_dns_srv_hostname_ptr is set internally with null termination. */ + status = _nx_utility_string_length_check((CHAR *)(srv_entry -> nx_dns_srv_hostname_ptr), &data_length, name_size); + + if((status == NX_SUCCESS) && + (data_length == name_size) && + ((memcmp(srv_entry -> nx_dns_srv_hostname_ptr, &temp_string_buffer[0], name_size)) == 0)) { /* This A type record contains the IPv4 address for the MX entry. */ @@ -5536,7 +5635,7 @@ ULONG rr_ttl; /* Get data address and check if it is valid. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + sizeof(ULONG)) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -5574,7 +5673,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_aaaa_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5620,6 +5719,9 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_aaaa_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, @@ -5716,7 +5818,7 @@ ULONG rr_ttl; /* Update the pointer to the ipv6 address. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + (4 * sizeof(ULONG))) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -5991,7 +6093,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_txt_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6034,6 +6136,9 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_txt_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -6107,7 +6212,7 @@ ULONG rr_ttl; text_data_length = (UINT) (*data_ptr++); /* Judge the resource data buffer space. */ - if(text_data_length > buffer_size - 1) + if ((text_data_length > buffer_size - 1) || ((data_ptr + text_data_length) > packet_ptr -> nx_packet_append_ptr)) { /* Return error, and release the packet in repsonse*/ @@ -6175,7 +6280,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_ns_type PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6222,6 +6327,11 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), updated */ +/* input parameter of the API */ +/* to get the real size of */ +/* resource name, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_ns_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -6291,7 +6401,7 @@ ULONG rr_ttl; } /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_NS_ENTRY))) @@ -6378,7 +6488,7 @@ ULONG rr_ttl; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_mx_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6426,6 +6536,14 @@ ULONG rr_ttl; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), updated */ +/* input parameter of the API */ +/* to get the real size of */ +/* resource name, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_mx_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -6490,7 +6608,7 @@ UINT size; /* Update the pointer to point at the resource data. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + if ((!data_ptr) || ((data_ptr + sizeof(USHORT)) >= packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -6504,7 +6622,7 @@ UINT size; data_ptr += 2; /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY))) @@ -6609,7 +6727,7 @@ UINT size; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_srv_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6657,6 +6775,14 @@ UINT size; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), updated */ +/* input parameter of the API */ +/* to get the real size of */ +/* resource name, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_srv_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UCHAR **buffer_prepend_ptr, @@ -6722,7 +6848,9 @@ UINT size; /* Update the pointer to point at the resource data. */ data_ptr = _nx_dns_resource_data_address_get(data_ptr, packet_ptr); - if (!data_ptr) + + /* Plus 6 for 2 bytes priority, 2 bytes weight and 2 bytes port. */ + if ((!data_ptr) || ((data_ptr + 6) >= packet_ptr -> nx_packet_append_ptr)) { /* Return! */ @@ -6748,7 +6876,7 @@ UINT size; data_ptr += 2; /* Get the real size of the name, and set the name buffer size.*/ - name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr)); + name_buffer_size = _nx_dns_resource_name_real_size_calculate(packet_ptr -> nx_packet_prepend_ptr, (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), packet_ptr -> nx_packet_length); /* Check the buffer space. */ if ((*buffer_append_ptr - name_buffer_size - 1 ) < (*buffer_prepend_ptr + sizeof(NX_DNS_MX_ENTRY))) @@ -6857,7 +6985,7 @@ UINT size; /* FUNCTION RELEASE */ /* */ /* _nx_dns_process_soa_type PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6904,6 +7032,9 @@ UINT size; /* updated resource get APIs to*/ /* improve buffer bound check, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_process_soa_type(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, @@ -7038,7 +7169,8 @@ ULONG rr_ttl; /* Get name size */ name_size = _nx_dns_name_size_calculate(data_ptr, packet_ptr); - if (!name_size) + /* 20 bytes for 4 bytes serial, 4 bytes refresh, 4 bytes retry, 4 bytes expire and 4 bytes minmum. */ + if ((!name_size) || ((data_ptr + name_size + 20) > packet_ptr -> nx_packet_append_ptr)) { /* Return! */ return(NX_DNS_MALFORMED_PACKET); @@ -7433,7 +7565,7 @@ UINT _nxd_dns_host_by_address_get(NX_DNS *dns_ptr, NXD_ADDRESS *host_address_pt /* FUNCTION RELEASE */ /* */ /* _nx_dns_host_by_address_get_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7463,6 +7595,8 @@ UINT _nxd_dns_host_by_address_get(NX_DNS *dns_ptr, NXD_ADDRESS *host_address_pt /* query packet */ /* tx_mutex_get Get DNS protection mutex */ /* tx_mutex_put Release DNS protection mutex */ +/* nx_udp_socket_bind Bind DNS UDP socket to port */ +/* nx_udp_socket_unbind Unbind DNS UDP socket */ /* */ /* CALLED BY */ /* */ @@ -7477,6 +7611,9 @@ UINT _nxd_dns_host_by_address_get(NX_DNS *dns_ptr, NXD_ADDRESS *host_address_pt /* the timeout of first query, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* randomized the source port, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_host_by_address_get_internal(NX_DNS *dns_ptr, NXD_ADDRESS *host_address_ptr, UCHAR *host_name_ptr, @@ -7627,6 +7764,18 @@ UINT length, index; } #endif /*NX_DNS_CACHE_ENABLE. */ + /* Bind the UDP socket to random port for each query. */ + status = nx_udp_socket_bind(&(dns_ptr -> nx_dns_socket), NX_ANY_PORT, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + /* Release the DNS Client lock. */ + tx_mutex_put(&dns_ptr -> nx_dns_mutex); + return(status); + } + /* Limit the timeout to NX_DNS_MAX_RETRANS_TIMEOUT. */ if (wait_option > NX_DNS_MAX_RETRANS_TIMEOUT) { @@ -7651,6 +7800,9 @@ UINT length, index; if (status == NX_SUCCESS) { + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + /* Release the mutex */ tx_mutex_put(&dns_ptr -> nx_dns_mutex); @@ -7666,6 +7818,9 @@ UINT length, index; wait_option = NX_DNS_MAX_RETRANS_TIMEOUT; } + /* Unbind the socket. */ + nx_udp_socket_unbind(&(dns_ptr -> nx_dns_socket)); + /* Release protection. */ tx_mutex_put(&(dns_ptr -> nx_dns_mutex)); @@ -7679,7 +7834,7 @@ UINT length, index; /* FUNCTION RELEASE */ /* */ /* _nx_dns_new_packet_create PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7693,7 +7848,6 @@ UINT length, index; /* */ /* dns_ptr Pointer to DNS instance */ /* packet_ptr Packet allocated for message */ -/* id DNS Client Identification */ /* name Question e.g. host name */ /* type DNS message type e.g. A, AAAA */ /* */ @@ -7721,12 +7875,18 @@ UINT length, index; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved id generation, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ -static UINT _nx_dns_new_packet_create(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, USHORT id, UCHAR *name, USHORT type) +static UINT _nx_dns_new_packet_create(NX_DNS *dns_ptr, NX_PACKET *packet_ptr, UCHAR *name, USHORT type) { +USHORT id; +UINT size; -UINT size; + /* Generate a random ID based on name. */ + id = (USHORT)NX_RAND(); /* Add the DNS header. */ size = _nx_dns_header_create(packet_ptr -> nx_packet_append_ptr, id, NX_DNS_QUERY_FLAGS); @@ -8108,7 +8268,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_dns_name_string_unencode PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8146,6 +8306,13 @@ UINT count = 1; /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* compression pointer check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_dns_name_string_unencode(NX_PACKET *packet_ptr, UCHAR *data, UCHAR *buffer, UINT buffer_size) @@ -8156,7 +8323,8 @@ UCHAR *message_start; UINT label_size; UINT offset; UINT length; - +UINT pointer_count = 0; + /* Initialize the value. */ character = data; message_start = packet_ptr -> nx_packet_prepend_ptr; @@ -8164,9 +8332,19 @@ UINT length; /* As long as there is space in the buffer and we haven't found a zero terminating label */ - while (*character != '\0') + while (1) { + if (character >= packet_ptr -> nx_packet_append_ptr) + { + return(0); + } + + if (*character == '\0') + { + break; + } + /* Check the buffer size. */ if (buffer_size > length) { @@ -8182,6 +8360,11 @@ UINT length; while ((buffer_size > length) && (label_size > 0)) { + if ((character >= packet_ptr -> nx_packet_append_ptr) || (*character == '\0')) + { + return(0); + } + *buffer++ = *character++; length++; label_size--; @@ -8195,6 +8378,10 @@ UINT length; { /* Message compression. */ + if (character >= packet_ptr -> nx_packet_append_ptr) + { + return(0); + } /* Get the offset. */ offset = ((label_size & NX_DNS_LABEL_MAX) << 8) + *character; @@ -8218,6 +8405,14 @@ UINT length; } else { + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS) + { + + /* This is malformed packet. */ + return(0); + } /* update valid pointer */ character = message_start + offset; } @@ -8354,7 +8549,7 @@ UINT size = 0; /* FUNCTION RELEASE */ /* */ /* _nx_dns_resource_name_real_size_calculate PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8367,6 +8562,7 @@ UINT size = 0; /* */ /* data Pointer to buffer to decode */ /* start Location of start of data */ +/* data_length Data buffer length */ /* */ /* OUTPUT */ /* */ @@ -8388,21 +8584,41 @@ UINT size = 0; /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* compression pointer check, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* pointer check, prevented */ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ -static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start) +static UINT _nx_dns_resource_name_real_size_calculate(UCHAR *data, UINT start, UINT data_length) { UCHAR *character = data + start; UINT length = 0; - +UINT offset; +UINT pointer_count = 0; +UINT labelSize; /* As long as there is space in the buffer and we haven't found a zero terminating label */ - while (*character != '\0') + while (1) { - UINT labelSize = *character++; + if (character >= (data + data_length)) + { + return(0); + } + + if (*character == '\0') + { + break; + } + + labelSize = *character++; /* Is this a compression pointer or a count. */ if (labelSize <= NX_DNS_LABEL_MAX) @@ -8411,6 +8627,12 @@ UINT length = 0; /* Simple count, check for space and copy the label. */ while (labelSize > 0) { + + if (character >= (data + data_length)) + { + return(0); + } + character++; length++; labelSize--; @@ -8422,8 +8644,23 @@ UINT length = 0; else if ((labelSize & NX_DNS_COMPRESS_MASK) == NX_DNS_COMPRESS_VALUE) { + if (character >= (data + data_length)) + { + return(0); + } + + /* Get the offset. */ + offset = ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character; + + /* Check the offset. */ + if (offset >= data_length) + { + + return(0); + } + /* This is a pointer, just adjust the source. */ - if (character == data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character) + if (character == data + offset) { /* If compression pointer equals the same offset currently being parsed, it could lead to an infinite loop. */ @@ -8431,8 +8668,19 @@ UINT length = 0; } else { + + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + + if (pointer_count > NX_DNS_MAX_COMPRESSION_POINTERS) + { + + /* This is malformed packet. */ + return(0); + } + /* update valid pointer */ - character = data + ((labelSize & NX_DNS_LABEL_MAX) << 8) + *character; + character = data + offset; } } else @@ -8442,9 +8690,12 @@ UINT length = 0; return(0); } } - + /* Reduce the last '.' string, update the length. */ - length --; + if (length) + { + length --; + } /* Return name size. */ return(length); @@ -10100,7 +10351,7 @@ ALIGN_TYPE *head; /* FUNCTION RELEASE */ /* */ /* _nx_dns_cache_delete_rr_string PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -10129,13 +10380,18 @@ ALIGN_TYPE *head; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ static UINT _nx_dns_cache_delete_rr_string(NX_DNS *dns_ptr, VOID *cache_ptr, UINT cache_size, NX_DNS_RR *record_ptr) { +#ifdef NX_DNS_ENABLE_EXTENDED_RR_TYPES UINT string_len; UINT size; +#endif /* NX_DNS_ENABLE_EXTENDED_RR_TYPES */ /* Check the cache. */ diff --git a/addons/dns/nxd_dns.h b/addons/dns/nxd_dns.h index c529db8d..791cbcd9 100644 --- a/addons/dns/nxd_dns.h +++ b/addons/dns/nxd_dns.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_dns.h PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,14 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), prevented*/ +/* infinite loop in name */ +/* compression, resulting in */ +/* version 6.1.3 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* receiving dns response, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ @@ -221,7 +229,7 @@ extern "C" { */ /* Enable the cache to store the resource record. */ -/* +/* #define NX_DNS_CACHE_ENABLE */ @@ -295,6 +303,10 @@ extern "C" { #define NX_DNS_PACKET_ALLOCATE_TIMEOUT NX_IP_PERIODIC_RATE #endif +/* Define the maximum number of pointers allowed in name compression. */ +#ifndef NX_DNS_MAX_COMPRESSION_POINTERS +#define NX_DNS_MAX_COMPRESSION_POINTERS 16 +#endif /* Define the basic DNS data structure. */ @@ -1005,6 +1017,10 @@ UINT _nx_dns_cache_notify_clear(NX_DNS *dns_ptr); #endif +/* Internal DNS response getting function. */ +UINT _nx_dns_response_get(NX_DNS *dns_ptr, UCHAR *host_name, UCHAR *record_buffer, UINT buffer_size, + UINT *record_count, ULONG wait_option); + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/addons/ftp/nxd_ftp_client.c b/addons/ftp/nxd_ftp_client.c index 3198edb3..b16d2750 100644 --- a/addons/ftp/nxd_ftp_client.c +++ b/addons/ftp/nxd_ftp_client.c @@ -1106,7 +1106,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_client_delete PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1140,6 +1140,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Wenhui Xie Modified comment(s), */ +/* cleared the client ID, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ UINT _nx_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr) @@ -1153,6 +1156,9 @@ UINT _nx_ftp_client_delete(NX_FTP_CLIENT *ftp_client_ptr) return(NX_FTP_NOT_DISCONNECTED); } + /* Clear the client ID . */ + ftp_client_ptr -> nx_ftp_client_id = 0; + /* Delete the control and data sockets. */ nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_control_socket)); nx_tcp_socket_delete(&(ftp_client_ptr -> nx_ftp_client_data_socket)); @@ -5516,7 +5522,7 @@ ULONG temp = 0; /* Skip non numeric text and whitespace. */ i = 3; - while (((buffer_ptr[i] > '9') || (buffer_ptr[i] < '0')) && (i < packet_ptr -> nx_packet_length)) + while ((i < packet_ptr -> nx_packet_length) && ((buffer_ptr[i] > '9') || (buffer_ptr[i] < '0'))) { i++; } diff --git a/addons/ftp/nxd_ftp_client.h b/addons/ftp/nxd_ftp_client.h index 1935f5eb..1a4e0d5d 100644 --- a/addons/ftp/nxd_ftp_client.h +++ b/addons/ftp/nxd_ftp_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_ftp_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -61,6 +64,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the FTP Client ID. */ diff --git a/addons/ftp/nxd_ftp_server.c b/addons/ftp/nxd_ftp_server.c index 6bedfa4c..5b43e940 100644 --- a/addons/ftp/nxd_ftp_server.c +++ b/addons/ftp/nxd_ftp_server.c @@ -80,7 +80,7 @@ NX_CALLER_CHECKING_EXTERNS #define NX_FTP_CODE_NO_SPACE "552" /* Requested file action aborted, no space. */ #define NX_FTP_CODE_BAD_NAME "553" /* Requested action not taken, File name not allowed. */ -static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number); +static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number, UCHAR pad); /**************************************************************************/ /* */ @@ -660,7 +660,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_delete PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -682,7 +682,6 @@ UINT status; /* CALLS */ /* */ /* fx_file_close Close file */ -/* nx_tcp_client_socket_unbind Unbind client socket */ /* nx_tcp_server_socket_unaccept Unaccept server socket */ /* nx_tcp_server_socket_unlisten Unlisten on server */ /* nx_tcp_socket_delete Delete socket */ @@ -693,6 +692,7 @@ UINT status; /* tx_thread_terminate Terminate thread */ /* tx_timer_deactivate Deactivate timer */ /* tx_timer_delete Delete timer */ +/* _nx_ftp_server_data_socket_cleanup Clean up data socket */ /* */ /* CALLED BY */ /* */ @@ -705,6 +705,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of clearing */ +/* data socket, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_ftp_server_delete(NX_FTP_SERVER *ftp_server_ptr) @@ -744,30 +748,10 @@ NX_FTP_CLIENT_REQUEST *client_request_ptr; if (client_request_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) { - /* Disconnect data socket. */ - nx_tcp_socket_disconnect(&(client_request_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT); - - /* Unbind/unaccept the data socket. */ - if (client_request_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_request_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_request_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_request_ptr -> nx_ftp_client_request_data_socket)); - } - - /* Delete data socket. */ - nx_tcp_socket_delete(&(client_request_ptr -> nx_ftp_client_request_data_socket)); - - /* Close file. */ - fx_file_close(&(client_request_ptr -> nx_ftp_client_request_file)); + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_request_ptr); } - /* Clear the passive transfer enabled flag. */ - client_request_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; - /* Reset the transfer mode as stream mode. */ client_request_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM; @@ -1523,7 +1507,7 @@ ULONG events; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_command_process PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1576,11 +1560,10 @@ ULONG events; /* nx_tcp_socket_disconnect Disconnect socket */ /* nx_tcp_socket_receive Receive from command socket */ /* nx_tcp_socket_send Send packet */ -/* nx_tcp_client_socket_unbind Unbind client socket */ -/* nx_tcp_socket_delete Delete socket */ -/* nx_tcp_socket_receive Receive packet */ /* nx_tcp_socket_receive_notify Register notification routine */ /* nx_tcp_socket_transmit_configure Configure data transer socket */ +/* _nx_utility_uint_to_string Convert number to string */ +/* _nx_ftp_server_data_socket_cleanup Clean up data socket */ /* */ /* CALLED BY */ /* */ @@ -1595,6 +1578,22 @@ ULONG events; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.3 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* corrected the pad character,*/ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of clearing */ +/* data socket and processing */ +/* disconnection event, */ +/* improved the PASV response, */ +/* fixed the bug of processing */ +/* STOR in passive mode, */ +/* reset the packet prepend */ +/* pointer for alignment, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ VOID _nx_ftp_server_command_process(NX_FTP_SERVER *ftp_server_ptr) @@ -1903,6 +1902,14 @@ ULONG block_size; _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, NX_FTP_CODE_CLOSE, "Logging Off"); + /* If create, cleanup the associated data socket. */ + if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) + { + + /* Clean up the client socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); + } + /* Now disconnect the command socket. */ nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_control_socket), NX_FTP_SERVER_TIMEOUT); @@ -1942,6 +1949,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "File Open Fail"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -1990,16 +2009,6 @@ ULONG block_size; nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); } - else - { - - /* Setup the data port with a specific packet transmit retry logic. */ - nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket), - NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH, - NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE, - NX_FTP_SERVER_RETRY_MAX, - NX_FTP_SERVER_RETRY_SHIFT); - } } else { @@ -2152,28 +2161,12 @@ ULONG block_size; _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0); } - /* Disconnect the data socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_TIMEOUT); - - /* Tear down the client data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); /* Clear the open type in the client request structure. */ client_req_ptr -> nx_ftp_client_request_open_type = 0; - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; - /* Allocate a new packet. */ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); @@ -2223,6 +2216,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "File Open Failed"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2272,45 +2277,7 @@ ULONG block_size; { /* Check if passive transfer enabled. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - - /* Set the disconnect callback. */ - client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_disconnect_callback = _nx_ftp_server_data_disconnect; - - /* Register the receive function. */ - nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket), _nx_ftp_server_data_present); - - /* Now wait for the data connection to connect. */ - status = nx_tcp_socket_state_wait(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_TCP_ESTABLISHED, NX_FTP_SERVER_TIMEOUT); - - /* Check for connect error. */ - if (status) - { - - /* Yes, a connect error is present. Tear everything down. */ - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); -#ifdef NX_FTP_FAULT_TOLERANT - - /* Flush the media. */ - fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr); -#endif - } - else - { - - /* Setup the data port with a specific packet transmit retry logic. */ - nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket), - NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH, - NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE, - NX_FTP_SERVER_RETRY_MAX, - NX_FTP_SERVER_RETRY_SHIFT); - } - } - else + if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_FALSE) { /* Create an FTP client data socket. */ @@ -2401,6 +2368,18 @@ ULONG block_size; case NX_FTP_RNFR: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Rename File not found"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2467,6 +2446,18 @@ ULONG block_size; case NX_FTP_RNTO: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Rename failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2537,6 +2528,18 @@ ULONG block_size; case NX_FTP_DELE: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Delete Failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2593,6 +2596,18 @@ ULONG block_size; case NX_FTP_RMD: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Delete Directory Fail"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2655,6 +2670,18 @@ ULONG block_size; case NX_FTP_MKD: { + + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Directory Create failed"); + break; + } /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2761,6 +2788,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "List bad Directory"); + break; + } + /* Change to the default directory of this connection. */ fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -2828,16 +2867,6 @@ ULONG block_size; nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); } - else - { - - /* Setup the data port with a specific packet transmit retry logic. */ - nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket), - NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH, - NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE, - NX_FTP_SERVER_RETRY_MAX, - NX_FTP_SERVER_RETRY_SHIFT); - } } else { @@ -3065,24 +3094,8 @@ ULONG block_size; _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0); } - /* Disconnect the data socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_TIMEOUT); - - /* Tear down the client data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); - - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); /* Allocate a new packet. */ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); @@ -3134,6 +3147,18 @@ ULONG block_size; break; } + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Bad Directory"); + break; + } + /* Change to the default directory of this connection. */ status = fx_directory_local_path_restore(ftp_server_ptr -> nx_ftp_server_media_ptr, &(client_req_ptr -> nx_ftp_client_local_path)); @@ -3246,16 +3271,6 @@ ULONG block_size; nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); } - else - { - - /* Setup the data port with a specific packet transmit retry logic. */ - nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket), - NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH, - NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE, - NX_FTP_SERVER_RETRY_MAX, - NX_FTP_SERVER_RETRY_SHIFT); - } } else { @@ -3471,17 +3486,17 @@ ULONG block_size; memcpy(&buffer_ptr[1], "rw-rw-rw-", 9); /* Use case of memcpy is verified. */ } memcpy(&buffer_ptr[10], " 1 owner group ", 16); /* Use case of memcpy is verified. */ - _nx_ftp_server_number_to_ascii(&buffer_ptr[26], 10, size); + _nx_ftp_server_number_to_ascii(&buffer_ptr[26], 10, size, ' '); buffer_ptr[36] = ' '; buffer_ptr[37] = (UCHAR)months[month - 1][0]; buffer_ptr[38] = (UCHAR)months[month - 1][1]; buffer_ptr[39] = (UCHAR)months[month - 1][2]; buffer_ptr[40] = ' '; - _nx_ftp_server_number_to_ascii(&buffer_ptr[41], 2, day); + _nx_ftp_server_number_to_ascii(&buffer_ptr[41], 2, day, '0'); buffer_ptr[43] = ' '; - _nx_ftp_server_number_to_ascii(&buffer_ptr[44], 2, hour); + _nx_ftp_server_number_to_ascii(&buffer_ptr[44], 2, hour, '0'); buffer_ptr[46] = ':'; - _nx_ftp_server_number_to_ascii(&buffer_ptr[47], 2, minute); + _nx_ftp_server_number_to_ascii(&buffer_ptr[47], 2, minute, '0'); buffer_ptr[49] = ' '; memcpy(&buffer_ptr[50], filename, length); /* Use case of memcpy is verified. */ length += 50; @@ -3537,24 +3552,8 @@ ULONG block_size; _nx_ftp_server_block_header_send(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, 0); } - /* Disconnect the data socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_TIMEOUT); - - /* Tear down the client data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); - - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); /* Allocate a new packet. */ _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); @@ -3751,6 +3750,14 @@ ULONG block_size; case NX_FTP_PASV: { + /* If create, cleanup the data socket. */ + if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) + { + + /* Clean up the data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); + } + /* Try to find the data port. */ status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr, ftp_server_ptr -> nx_ftp_server_data_port++, &port); @@ -3771,7 +3778,7 @@ ULONG block_size; /* Create an FTP client data socket. */ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket", - NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL); + NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect); /* Determine if the listen is successful. */ if (status != NX_SUCCESS) @@ -3787,6 +3794,16 @@ ULONG block_size; break; } + /* Register the receive function. */ + nx_tcp_socket_receive_notify(&(client_req_ptr -> nx_ftp_client_request_data_socket), _nx_ftp_server_data_present); + + /* Setup the data port with a specific packet transmit retry logic. */ + nx_tcp_socket_transmit_configure(&(client_req_ptr -> nx_ftp_client_request_data_socket), + NX_FTP_SERVER_TRANSMIT_QUEUE_DEPTH, + NX_FTP_SERVER_RETRY_SECONDS*NX_IP_PERIODIC_RATE, + NX_FTP_SERVER_RETRY_MAX, + NX_FTP_SERVER_RETRY_SHIFT); + /* Make sure each socket points to the corresponding FTP server. */ client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_reserved_ptr = ftp_server_ptr; @@ -3816,12 +3833,15 @@ ULONG block_size; /* Pickup the IPv4 address of this IP instance. */ ip_address = client_req_ptr -> nx_ftp_client_request_control_socket.nx_tcp_socket_connect_interface -> nx_interface_ip_address; + /* Reset the packet prepend pointer for alignment. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET; + /* Setup pointer to packet buffer area. */ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; /* Now build PASV response. "227 Entering Passive Mode (h1,h2,h3,h4,p1,p2)." */ - /* Verify packet payload. */ + /* Verify packet payload. The max size of this message is 54. */ if ((packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr) < 54) { @@ -3838,46 +3858,28 @@ ULONG block_size; memcpy(buffer_ptr, "227 Entering Passive Mode ", 26); /* Use case of memcpy is verified. */ /* Build the IP address and port. */ - buffer_ptr[26] = '('; - - buffer_ptr[27] = (UCHAR)('0' + (ip_address >> 24)/100); - buffer_ptr[28] = (UCHAR)('0' + ((ip_address >> 24)/10)%10); - buffer_ptr[29] = (UCHAR)('0' + (ip_address >> 24)%10); - buffer_ptr[30] = ','; - - buffer_ptr[31] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)/100); - buffer_ptr[32] = (UCHAR)('0' + (((ip_address >> 16) & 0xFF)/10)%10); - buffer_ptr[33] = (UCHAR)('0' + ((ip_address >> 16) & 0xFF)%10); - buffer_ptr[34] = ','; - - buffer_ptr[35] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)/100); - buffer_ptr[36] = (UCHAR)('0' + (((ip_address >> 8) & 0xFF)/10)%10); - buffer_ptr[37] = (UCHAR)('0' + ((ip_address >> 8) & 0xFF)%10); - buffer_ptr[38] = ','; - - buffer_ptr[39] = (UCHAR)('0' + (ip_address & 0xFF)/100); - buffer_ptr[40] = (UCHAR)('0' + ((ip_address & 0xFF)/10)%10); - buffer_ptr[41] = (UCHAR)('0' + (ip_address & 0xFF)%10); - buffer_ptr[42] = ','; - - buffer_ptr[43] = (UCHAR)('0' + (port >> 8)/100); - buffer_ptr[44] = (UCHAR)('0' + ((port >> 8)/10)%10); - buffer_ptr[45] = (UCHAR)('0' + ((port >> 8)%10)); - buffer_ptr[46] = ','; - - buffer_ptr[47] = (UCHAR)('0' + (port & 255)/100); - buffer_ptr[48] = (UCHAR)('0' + ((port & 255)/10)%10); - buffer_ptr[49] = (UCHAR)('0' + ((port & 255)%10)); - - buffer_ptr[50] = ')'; - buffer_ptr[51] = '.'; + j = 26; + buffer_ptr[j++] = '('; + j += _nx_utility_uint_to_string((ip_address >> 24), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ','; + j += _nx_utility_uint_to_string(((ip_address >> 16) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ','; + j += _nx_utility_uint_to_string(((ip_address >> 8) & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ','; + j += _nx_utility_uint_to_string((ip_address & 0xFF), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ','; + j += _nx_utility_uint_to_string((port >> 8), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ','; + j += _nx_utility_uint_to_string((port & 0XFF), 10, (CHAR *)(buffer_ptr + j), 54 - j); + buffer_ptr[j++] = ')'; + buffer_ptr[j++] = '.'; /* Set the CR/LF. */ - buffer_ptr[52] = 13; - buffer_ptr[53] = 10; + buffer_ptr[j++] = 13; + buffer_ptr[j++] = 10; /* Set the packet length. */ - packet_ptr -> nx_packet_length = 54; + packet_ptr -> nx_packet_length = j; /* Setup the packet append pointer. */ packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + packet_ptr -> nx_packet_length; @@ -3970,6 +3972,14 @@ ULONG block_size; case NX_FTP_EPSV: { + /* If create, cleanup the data socket. */ + if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) + { + + /* Clean up the client socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); + } + /* Try to find the data port. */ status = nx_tcp_free_port_find(ftp_server_ptr -> nx_ftp_server_ip_ptr, ftp_server_ptr -> nx_ftp_server_data_port++, &port); @@ -3990,7 +4000,7 @@ ULONG block_size; /* Create an FTP client data socket. */ status = nx_tcp_socket_create(ftp_server_ptr -> nx_ftp_server_ip_ptr, &(client_req_ptr -> nx_ftp_client_request_data_socket), "FTP Server Data Socket", - NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, NX_NULL); + NX_FTP_DATA_TOS, NX_FTP_FRAGMENT_OPTION, NX_FTP_TIME_TO_LIVE, NX_FTP_DATA_WINDOW_SIZE, NX_NULL, _nx_ftp_server_data_disconnect); /* Determine if the listen is successful. */ if (status != NX_SUCCESS) @@ -4032,6 +4042,9 @@ ULONG block_size; /* Wait for the data connection to connect. */ nx_tcp_server_socket_accept(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT); + /* Reset the packet prepend pointer for alignment. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_data_start + NX_TCP_PACKET; + /* Setup pointer to packet buffer area. */ buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; @@ -4113,6 +4126,9 @@ ULONG block_size; /* If CDUP command, create the "up one directory" pathname string. */ if (ftp_command == NX_FTP_CDUP) { + + /* Move the pointer to make sure there is enough memory to store the data. */ + buffer_ptr -= 3; buffer_ptr[0] = '.'; buffer_ptr[1] = '.'; buffer_ptr[2] = NX_NULL; @@ -4122,6 +4138,18 @@ ULONG block_size; else { + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message. */ + + /* Now send an error response to the client. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "Change Dir Fail"); + break; + } + /* Find the end of the message. */ j = 0; while (j < packet_ptr -> nx_packet_length - 1) @@ -4633,7 +4661,7 @@ NX_FTP_SERVER *server_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_data_disconnect_process PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4656,9 +4684,7 @@ NX_FTP_SERVER *server_ptr; /* */ /* fx_file_close Close file */ /* nx_ftp_packet_allocate Allocate a packet */ -/* nx_tcp_client_socket_unbind Unbind client socket */ -/* nx_tcp_socket_delete Delete socket */ -/* nx_tcp_socket_disconnect Disconnect socket */ +/* _nx_ftp_server_data_socket_cleanup Clean up data socket */ /* */ /* CALLED BY */ /* */ @@ -4671,13 +4697,16 @@ NX_FTP_SERVER *server_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), fixed */ +/* the issue of processing */ +/* disconnection event, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ VOID _nx_ftp_server_data_disconnect_process(NX_FTP_SERVER *ftp_server_ptr) { UINT i; -UINT status; UINT block_status; ULONG length; NX_PACKET *packet_ptr; @@ -4700,25 +4729,8 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* Yes, a disconnect is present, which signals an end of file of a client FTP write request. */ - /* First, cleanup this data socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_TIMEOUT); - - /* Unbind/unaccept the data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - - /* And finally delete the data socket. */ - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; + /* Cleanup this data socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); /* Determine if the block mode is enabled. */ if (client_req_ptr -> nx_ftp_client_request_transfer_mode == NX_FTP_TRANSFER_MODE_BLOCK) @@ -4738,43 +4750,39 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* Reset the client request activity timeout. */ client_req_ptr -> nx_ftp_client_request_activity_timeout = NX_FTP_ACTIVITY_TIMEOUT; - /* Pickup the file length. */ - length = (ULONG)client_req_ptr -> nx_ftp_client_request_file.fx_file_current_file_size; + /* Check if file is open. */ + if (client_req_ptr -> nx_ftp_client_request_open_type == NX_FTP_OPEN_FOR_WRITE) + { - /* Close the file. */ - status = fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); + /* Pickup the file length. */ + length = (ULONG)client_req_ptr -> nx_ftp_client_request_file.fx_file_current_file_size; -#ifdef NX_FTP_FAULT_TOLERANT + /* Allocate a packet for sending the file write response. */ + _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); - /* Flush the media. */ - fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr); -#endif + /* Now determine if the operation was successful. */ + if ((length == client_req_ptr -> nx_ftp_client_request_total_bytes) && (block_status == NX_TRUE)) + { - /* Allocate a packet for sending the file write response. */ - _nx_ftp_packet_allocate(ftp_server_ptr -> nx_ftp_server_packet_pool_ptr, client_req_ptr, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + /* Successful client file write. */ - /* Now determine if the operation was successful. */ - if ((status == FX_SUCCESS) && (length == client_req_ptr -> nx_ftp_client_request_total_bytes) && (block_status == NX_TRUE)) - { + /* Now send "250" message to indicate successful file write. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_COMPLETED, "File Written"); + } + else + { - /* Successful client file write. */ + /* Unsuccessful client file write. */ - /* Now send "250" message to indicate successful file write. */ - _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, - NX_FTP_CODE_COMPLETED, "File Written"); - } - else - { - - /* Unsuccessful client file write. */ + /* Now send "550" message to indicate unsuccessful file write. */ + _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, + NX_FTP_CODE_BAD_FILE, "File Write Failed"); + } - /* Now send "550" message to indicate unsuccessful file write. */ - _nx_ftp_server_response(&(client_req_ptr -> nx_ftp_client_request_control_socket), packet_ptr, - NX_FTP_CODE_BAD_FILE, "File Write Failed"); + /* Clear the open type. */ + client_req_ptr -> nx_ftp_client_request_open_type = 0; } - - /* Clear the open type. */ - client_req_ptr -> nx_ftp_client_request_open_type = 0; } } } @@ -4993,7 +5001,7 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_parse_command PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5027,6 +5035,9 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ftp_server_parse_command(NX_PACKET *packet_ptr) @@ -5036,6 +5047,14 @@ UINT i; char *buffer_ptr; + /* Check packet length. */ + if (packet_ptr -> nx_packet_length == 0) + { + + /* Empty message, just return INVALID. */ + return(NX_FTP_INVALID); + } + /* Setup pointer to command buffer area. */ buffer_ptr = (char *) packet_ptr -> nx_packet_prepend_ptr; @@ -5263,7 +5282,7 @@ NX_FTP_SERVER *server_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_timeout_processing PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5289,10 +5308,9 @@ NX_FTP_SERVER *server_ptr; /* fx_file_close Close file */ /* nx_packet_release Release saved packet */ /* nx_tcp_server_socket_relisten Relisten for another connect */ -/* nx_tcp_client_socket_unbind Unbind data socket */ /* nx_tcp_server_socket_unaccept Unaccept server connection */ -/* nx_tcp_socket_delete Delete data socket */ /* nx_tcp_socket_disconnect Disconnect socket */ +/* _nx_ftp_server_data_socket_cleanup Clean up data socket */ /* */ /* CALLED BY */ /* */ @@ -5305,6 +5323,10 @@ NX_FTP_SERVER *server_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of clearing */ +/* data socket, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ VOID _nx_ftp_server_timeout_processing(NX_FTP_SERVER *ftp_server_ptr) @@ -5345,36 +5367,10 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) { - /* Disconnect client socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT); - - /* Unbind/unaccept the data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - - /* Delete the data socket. */ - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - - /* Ensure the file is closed. */ - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); - -#ifdef NX_FTP_FAULT_TOLERANT - - /* Flush the media. */ - fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr); -#endif + /* Clean up the client socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); } - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; - /* Reset the transfer mode as stream mode. */ client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM; @@ -5465,7 +5461,7 @@ NX_FTP_SERVER *server_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_control_disconnect_processing PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5490,10 +5486,9 @@ NX_FTP_SERVER *server_ptr; /* fx_file_close Close file */ /* nx_packet_release Release saved packet */ /* nx_tcp_server_socket_relisten Relisten for another connect */ -/* nx_tcp_client_socket_unbind Unbind data socket */ /* nx_tcp_server_socket_unaccept Unaccept server connection */ -/* nx_tcp_socket_delete Delete data socket */ /* nx_tcp_socket_disconnect Disconnect socket */ +/* _nx_ftp_server_data_socket_cleanup Clean up data socket */ /* */ /* CALLED BY */ /* */ @@ -5506,6 +5501,10 @@ NX_FTP_SERVER *server_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of clearing */ +/* data socket, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ VOID _nx_ftp_server_control_disconnect_processing(NX_FTP_SERVER *ftp_server_ptr) @@ -5544,36 +5543,10 @@ NX_FTP_CLIENT_REQUEST *client_req_ptr; if (client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_id) { - /* Disconnect client socket. */ - nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_NO_WAIT); - - /* Unbind/unaccept the data socket. */ - if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) - { - nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); - } - else - { - nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - } - - /* Delete the data socket. */ - nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); - - /* Ensure the file is closed. */ - fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); - -#ifdef NX_FTP_FAULT_TOLERANT - - /* Flush the media. */ - fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr); -#endif + /* Clean up the client socket. */ + _nx_ftp_server_data_socket_cleanup(ftp_server_ptr, client_req_ptr); } - /* Clear the passive transfer enabled flag. */ - client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; - /* Reset the transfer mode as stream mode. */ client_req_ptr -> nx_ftp_client_request_transfer_mode = NX_FTP_TRANSFER_MODE_STREAM; @@ -5719,7 +5692,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_utility_parse_IPv6_address PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5763,6 +5736,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* colons count verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ftp_utility_parse_IPv6_address(CHAR *buffer_ptr, UINT buffer_length, NXD_ADDRESS *ipduo_address) @@ -5898,6 +5874,12 @@ ULONG temp; else if (buffer_ptr[j] == ':') { + /* Check if colons is valid. */ + if (colons >= 7) + { + return NX_FTP_INVALID_ADDRESS; + } + /* Increment the colon count. */ colons++; @@ -5963,6 +5945,12 @@ ULONG temp; m++; } + /* Check if colons is valid. */ + if (actual_colons_left >= remaining_colons) + { + return NX_FTP_INVALID_ADDRESS; + } + /* Compute the number of zeros to insert into the NXD_ADDRESS IPv6 ULONG array. */ number_consecutive_zeros_to_add = remaining_colons - actual_colons_left; @@ -6714,7 +6702,7 @@ NX_PACKET *last_packet; /* FUNCTION RELEASE */ /* */ /* _nx_ftp_server_number_to_ascii PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6750,9 +6738,15 @@ NX_PACKET *last_packet; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Yuxin Zhou Modified comment(s), and */ +/* corrected the size check, */ +/* resulting in version 6.1.7 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* corrected the pad character,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ -static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number) +static VOID _nx_ftp_server_number_to_ascii(UCHAR *buffer_ptr, UINT buffer_size, UINT number, UCHAR pad) { UINT digit; UINT size; @@ -6760,11 +6754,11 @@ UINT size; /* Initialize counters. */ size = 1; - /* Initialize buffer with spaces. */ - memset(buffer_ptr, ' ', buffer_size); + /* Initialize buffer with pad character. */ + memset(buffer_ptr, pad, buffer_size); /* Loop to convert the number to ASCII. */ - while (size < buffer_size) + while (size <= buffer_size) { /* Compute the next decimal digit. */ @@ -6784,3 +6778,81 @@ UINT size; break; } } + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ftp_server_data_socket_cleanup PORTABLE C */ +/* 6.1.9 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans up the data socket. */ +/* */ +/* INPUT */ +/* */ +/* ftp_server_ptr Pointer to FTP server */ +/* client_req_ptr Pointer to client request */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* fx_file_close Close file */ +/* nx_tcp_socket_disconnect Disconnect a socket */ +/* nx_tcp_client_socket_unbind Release the data socket port */ +/* nx_tcp_server_socket_unaccept Unaccept server connection */ +/* nx_tcp_server_socket_unlisten Unlisten on server socket */ +/* nx_tcp_socket_delete Delete socket */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ftp_server_command_process Process command */ +/* _nx_ftp_server_data_disconnect_process */ +/* Disconnect data socket */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-15-2021 Yuxin Zhou Initial Version 6.1.9 */ +/* */ +/**************************************************************************/ +VOID _nx_ftp_server_data_socket_cleanup(NX_FTP_SERVER *ftp_server_ptr, NX_FTP_CLIENT_REQUEST *client_req_ptr) +{ + + /* First, cleanup this data socket. */ + nx_tcp_socket_disconnect(&(client_req_ptr -> nx_ftp_client_request_data_socket), NX_FTP_SERVER_TIMEOUT); + + /* Unbind/unaccept the data socket. */ + if (client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled == NX_TRUE) + { + nx_tcp_server_socket_unaccept(&(client_req_ptr -> nx_ftp_client_request_data_socket)); + nx_tcp_server_socket_unlisten(ftp_server_ptr -> nx_ftp_server_ip_ptr, client_req_ptr -> nx_ftp_client_request_data_socket.nx_tcp_socket_port); + } + else + { + nx_tcp_client_socket_unbind(&(client_req_ptr -> nx_ftp_client_request_data_socket)); + } + + /* And finally delete the data socket. */ + nx_tcp_socket_delete(&(client_req_ptr -> nx_ftp_client_request_data_socket)); + + fx_file_close(&(client_req_ptr -> nx_ftp_client_request_file)); + +#ifdef NX_FTP_FAULT_TOLERANT + + /* Flush the media. */ + fx_media_flush(ftp_server_ptr -> nx_ftp_server_media_ptr); +#endif + + /* Clear the passive transfer enabled flag. */ + client_req_ptr -> nx_ftp_client_request_passive_transfer_enabled = NX_FALSE; +} \ No newline at end of file diff --git a/addons/ftp/nxd_ftp_server.h b/addons/ftp/nxd_ftp_server.h index 2975630b..80926f63 100644 --- a/addons/ftp/nxd_ftp_server.h +++ b/addons/ftp/nxd_ftp_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_ftp_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,11 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of clearing */ +/* data socket, included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -61,6 +66,8 @@ extern "C" { #endif +#include "nx_api.h" + #ifndef NX_FTP_NO_FILEX #include "fx_api.h" @@ -415,6 +422,7 @@ VOID _nx_ftp_server_timeout(ULONG ftp_server_address); VOID _nx_ftp_server_timeout_processing(NX_FTP_SERVER *ftp_server_ptr); VOID _nx_ftp_server_control_disconnect(NX_TCP_SOCKET *control_socket_ptr); VOID _nx_ftp_server_control_disconnect_processing(NX_FTP_SERVER *ftp_server_ptr); +VOID _nx_ftp_server_data_socket_cleanup(NX_FTP_SERVER *ftp_server_ptr, NX_FTP_CLIENT_REQUEST *client_req_ptr); #endif /* NX_FTP_SOURCE_CODE */ diff --git a/addons/http/nxd_http_client.c b/addons/http/nxd_http_client.c index a640dff8..86e82002 100644 --- a/addons/http/nxd_http_client.c +++ b/addons/http/nxd_http_client.c @@ -42,13 +42,6 @@ /* Define global HTTP variables and strings. */ - -/* Define the Base64 array that is used to build username and passwords for Basic authentication. Indexing - into this array yields the base64 representation of the 6bit number. */ - -CHAR _nx_http_client_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - /* Bring in externs for caller checking code. */ NX_CALLER_CHECKING_EXTERNS @@ -1054,7 +1047,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_http_client_get_start_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1118,6 +1111,14 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* correted the status when */ +/* received error code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nxd_http_client_get_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource, UINT resource_length, @@ -1305,10 +1306,7 @@ UINT temp_password_length = 0; string1[username_length + password_length + 1] = NX_NULL; /* Now encode the username:password string. */ - _nx_http_client_base64_encode(string1, username_length + password_length + 1, string2); - - /* Check string length. */ - _nx_utility_string_length_check(string2, &string2_length, NX_HTTP_MAX_STRING); + _nx_utility_base64_encode((UCHAR *)string1, username_length + password_length + 1, (UCHAR *)string2, sizeof(string2), &string2_length); nx_packet_data_append(packet_ptr, string2, string2_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER); nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER); } @@ -1422,6 +1420,9 @@ UINT temp_password_length = 0; /* Release the packet. */ nx_packet_release(response_packet_ptr); + + /* Received error code. */ + status = NX_HTTP_REQUEST_UNSUCCESSFUL_CODE; } } @@ -2294,7 +2295,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_http_client_put_start_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2355,6 +2356,10 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxd_http_client_put_start_extended(NX_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, CHAR *resource, @@ -2533,10 +2538,7 @@ UINT temp_password_length = 0; string1[username_length + password_length + 1] = NX_NULL; /* Now encode the username:password string. */ - _nx_http_client_base64_encode(string1, username_length + password_length + 1, string2); - - /* Check string length. */ - _nx_utility_string_length_check(string2, &string2_length, NX_HTTP_MAX_STRING); + _nx_utility_base64_encode((UCHAR *)string1, username_length + password_length + 1, (UCHAR *)string2, sizeof(string2), &string2_length); nx_packet_data_append(packet_ptr, string2, string2_length, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER); nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_http_client_packet_pool_ptr, NX_WAIT_FOREVER); @@ -3347,136 +3349,3 @@ UINT size; /* Return size to caller. */ return(size); } - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_http_client_base64_encode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function encodes the input string into a base64 */ -/* representation. */ -/* */ -/* INPUT */ -/* */ -/* name Name string */ -/* length Length of name */ -/* base64name Encoded base64 name string */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _nx_utility_string_length_check Check string length */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_http_client_get_start_extended Start GET processing */ -/* _nx_http_client_put_start_extended Start PUT processing */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_http_client_base64_encode(CHAR *name, UINT length, CHAR *base64name) -{ - -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - - /* Default padding to none. */ - pad = 0; - - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) - { - - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; - } - - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) - { - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first 6 bits of name character for index. */ - base64name[j++] = _nx_http_client_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) - { - - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = _nx_http_client_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; - } - else if (step == 2) - { - - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = _nx_http_client_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ - { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = _nx_http_client_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; - } - } - - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < NX_HTTP_MAX_STRING)) - { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; - } - - /* Put a NULL character in. */ - base64name[j] = NX_NULL; -} - diff --git a/addons/http/nxd_http_client.h b/addons/http/nxd_http_client.h index 0c19fe06..93910583 100644 --- a/addons/http/nxd_http_client.h +++ b/addons/http/nxd_http_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_http_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -107,8 +111,8 @@ extern "C" { #define NX_HTTP_CLIENT_MIN_PACKET_SIZE 600 #endif -/* NX_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed. */ -#define NX_HTTP_MAX_STRING ((NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 1) * 4 / 3 + 1) +/* NX_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed and plus 2 pad if needed. */ +#define NX_HTTP_MAX_STRING ((NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 1) * 4 / 3 + 1 + 2) #define NX_HTTP_MAX_BINARY_MD5 16 #define NX_HTTP_MAX_ASCII_MD5 32 @@ -282,7 +286,6 @@ UINT _nx_http_client_type_get(CHAR *name, CHAR *http_type_string); UINT _nx_http_client_content_length_get(NX_PACKET *packet_ptr); UINT _nx_http_client_calculate_content_offset(NX_PACKET *packet_ptr); UINT _nx_http_client_number_convert(UINT number, CHAR *string); -VOID _nx_http_client_base64_encode(CHAR *name, UINT length, CHAR *base64name); #endif /* NX_HTTP_SOURCE_CODE */ diff --git a/addons/http/nxd_http_server.c b/addons/http/nxd_http_server.c index 01add756..c015ebec 100644 --- a/addons/http/nxd_http_server.c +++ b/addons/http/nxd_http_server.c @@ -40,18 +40,10 @@ #include "nx_md5.h" #endif - -/* Define the Base64 array that is used to build username and passwords for Basic authentication. Indexing - into this array yields the base64 representation of the 6bit number. */ - -CHAR _nx_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - #ifdef NX_HTTP_DIGEST_ENABLE -/* Define the default nonce, used only for MD5 authentication. For security reasons, this ASCII value should - change over time. */ -CHAR _nx_http_server_nonce[] = "a4b8c8d7e0f6a7b2c3d2e4f5a4b7c5d2e7f"; +/* Use for mapping random nonces to printable characters. */ +static CHAR _nx_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #endif /* Define date strings. */ @@ -1546,7 +1538,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_delete PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1568,9 +1560,8 @@ UINT status; /* CALLS */ /* */ /* nx_tcp_socket_delete Delete the HTTP server socket */ -/* nx_tcp_socket_disconnect Disconnect HTTP server socket */ -/* nx_tcp_socket_unaccept Unaccept HTTP server connect */ -/* nx_tcp_socket_unlisten Unlisten on the HTTP port */ +/* _nx_http_server_disconnect Disconnect HTTP server socket */ +/* nx_tcp_server_socket_unlisten Unlisten on the HTTP port */ /* tx_thread_delete Delete the HTTP server thread */ /* tx_thread_suspend Suspend the HTTP server thread*/ /* tx_thread_terminate Terminate the HTTP server */ @@ -1587,6 +1578,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_http_server_delete(NX_HTTP_SERVER *http_server_ptr) @@ -1597,10 +1591,7 @@ UINT _nx_http_server_delete(NX_HTTP_SERVER *http_server_ptr) http_server_ptr -> nx_http_server_id = 0; /* Disconnect the TCP socket. */ - nx_tcp_socket_disconnect(&(http_server_ptr -> nx_http_server_socket), NX_HTTP_SERVER_TIMEOUT_DISCONNECT); - - /* Unaccept any remaining connection on the TCP socket. */ - nx_tcp_server_socket_unaccept(&(http_server_ptr -> nx_http_server_socket)); + _nx_http_server_disconnect(http_server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT); /* Delete the TCP socket. */ nx_tcp_socket_delete(&(http_server_ptr -> nx_http_server_socket)); @@ -2254,7 +2245,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_stop PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2275,6 +2266,8 @@ UINT status; /* */ /* CALLS */ /* */ +/* _nx_http_server_disconnect Disconnect HTTP server socket */ +/* nx_tcp_server_socket_unlisten Unlisten on the HTTP port */ /* tx_thread_suspend Suspend the HTTP server thread*/ /* */ /* CALLED BY */ @@ -2288,20 +2281,91 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_http_server_stop(NX_HTTP_SERVER *http_server_ptr) { /* Disconnect the TCP socket. */ - nx_tcp_socket_disconnect(&(http_server_ptr -> nx_http_server_socket), NX_NO_WAIT); - - /* Unaccept any remaining connection on the TCP socket. */ - nx_tcp_server_socket_unaccept(&(http_server_ptr -> nx_http_server_socket)); + _nx_http_server_disconnect(http_server_ptr, NX_NO_WAIT); /* Unlisten on the HTTP server port. */ nx_tcp_server_socket_unlisten(http_server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT); + /* Suspend the HTTP server thread. */ + tx_thread_suspend(&(http_server_ptr -> nx_http_server_thread)); + + /* Return successful completion. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_server_disconnect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function disconnects the HTTP server socket. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* http_server_ptr Pointer to HTTP server */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_tcp_socket_disconnect Disconnect HTTP server socket */ +/* nx_tcp_socket_unaccept Unaccept HTTP server connect */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_http_server_disconnect(NX_HTTP_SERVER *http_server_ptr, UINT wait_option) +{ + +#ifdef NX_HTTP_DIGEST_ENABLE +UINT i; + + /* Once the nonce has been accepted, set the state as invalid. */ + for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++) + { + if (http_server_ptr -> nx_http_server_nonces[i].nonce_state == NX_HTTP_SERVER_NONCE_ACCEPTED) + { + http_server_ptr -> nx_http_server_nonces[i].nonce_state = NX_HTTP_SERVER_NONCE_INVALID; + break; + } + } +#endif /* NX_HTTP_DIGEST_ENABLE */ + + /* Disconnect the TCP socket. */ + nx_tcp_socket_disconnect(&(http_server_ptr -> nx_http_server_socket), wait_option); + + /* Unaccept any remaining connection on the TCP socket. */ + nx_tcp_server_socket_unaccept(&(http_server_ptr -> nx_http_server_socket)); + /* Return successful completion. */ return(NX_SUCCESS); } @@ -2836,7 +2900,7 @@ NX_HTTP_SERVER *server_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2864,10 +2928,9 @@ NX_HTTP_SERVER *server_ptr; /* _nx_http_server_response_send Send HTTP Server response */ /* nx_packet_release Release request packet */ /* nx_tcp_server_socket_accept Accept HTTP client connect */ -/* nx_tcp_socket_disconnect Disconnect from HTTP client */ +/* _nx_http_server_disconnect Disconnect HTTP server socket */ /* nx_tcp_server_socket_relisten Relisten for another HTTP */ /* client connection */ -/* nx_tcp_server_socket_unaccept Unaccept HTTP client connect */ /* tx_thread_preemption_change Disable/restore preemption */ /* tx_thread_suspend Self suspend HTTP thread */ /* */ @@ -2882,6 +2945,9 @@ NX_HTTP_SERVER *server_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_http_server_thread_entry(ULONG http_server) @@ -2967,10 +3033,7 @@ UINT loop_endlessly = NX_TRUE; } /* Disconnect from the current connection. */ - nx_tcp_socket_disconnect(&(server_ptr -> nx_http_server_socket), NX_HTTP_SERVER_TIMEOUT_DISCONNECT); - - /* Unaccept the connection. */ - nx_tcp_server_socket_unaccept(&(server_ptr -> nx_http_server_socket)); + _nx_http_server_disconnect(server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT); /* Relisten on the HTTP Server port. */ nx_tcp_server_socket_relisten(server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT, @@ -3094,10 +3157,7 @@ UINT loop_endlessly = NX_TRUE; nx_packet_release(packet_ptr); /* Disconnect from the current connection. */ - nx_tcp_socket_disconnect(&(server_ptr -> nx_http_server_socket), NX_HTTP_SERVER_TIMEOUT_DISCONNECT); - - /* Unaccept the connection. */ - nx_tcp_server_socket_unaccept(&(server_ptr -> nx_http_server_socket)); + _nx_http_server_disconnect(server_ptr, NX_HTTP_SERVER_TIMEOUT_DISCONNECT); /* Relisten on the HTTP Server port. */ nx_tcp_server_socket_relisten(server_ptr -> nx_http_server_ip_ptr, NX_HTTP_SERVER_PORT, @@ -4708,7 +4768,7 @@ NX_PACKET *packet_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_basic_authenticate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4757,6 +4817,14 @@ NX_PACKET *packet_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the issue of processing */ +/* empty password, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_http_server_basic_authenticate(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT realm_length, UINT *auth_request_present) @@ -4768,6 +4836,7 @@ CHAR quote[2] = {0x22, 0}; CHAR crlf[2] = {13,10}; UINT match; UINT length; +UINT authorization_decoded_size; /* Default to no authentication request detected. */ *auth_request_present = NX_FALSE; @@ -4788,14 +4857,14 @@ UINT length; *auth_request_present = NX_TRUE; /* Convert the request from Base64 representation to ASCII. */ - _nx_http_base64_decode(authorization_request, length, authorization_decoded); + _nx_utility_base64_decode((UCHAR *)authorization_request, length, (UCHAR *)authorization_decoded, sizeof(authorization_decoded), &authorization_decoded_size); /* See if it is valid. */ /* Compare the name. */ i = 0; match = NX_TRUE; - while (name_ptr[i] && (i < sizeof(authorization_decoded))) + while (name_ptr[i] && (i < authorization_decoded_size)) { /* Is there a mismatch? */ @@ -4811,7 +4880,7 @@ UINT length; } /* Determine if everything matches. */ - if (match && (i < sizeof(authorization_decoded)) && (authorization_decoded[i] == ':')) + if (match && (i < authorization_decoded_size) && (authorization_decoded[i] == ':')) { /* Move the authorization index past the semicolon. */ @@ -4820,7 +4889,7 @@ UINT length; /* Now compare the passwords. */ j = 0; match = NX_TRUE; - while (password_ptr[j] && (i < sizeof(authorization_decoded))) + while (password_ptr[j] && (i < authorization_decoded_size)) { /* Is there a mismatch? */ @@ -4837,7 +4906,9 @@ UINT length; } /* Determine if we have a match. */ - if (match && (i < sizeof(authorization_decoded)) && (authorization_decoded[i] == (CHAR) NX_NULL)) + if (match && (i == authorization_decoded_size) && + (authorization_decoded[i] == (CHAR) NX_NULL) && + (password_ptr[j] == (CHAR) NX_NULL)) { /* Yes, we have successful authorization!! */ @@ -4926,7 +4997,7 @@ UINT length; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_retrieve_basic_authorization PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4962,6 +5033,10 @@ UINT length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the HTTP Server state issue */ +/* with basic authorization, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr) @@ -5027,6 +5102,9 @@ CHAR *buffer_ptr; return(length); } + /* Set the found flag back to false. */ + found = NX_FALSE; + /* Now remove any extra blanks. */ while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' ')) { @@ -5362,105 +5440,6 @@ CHAR *buffer_ptr; } -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_http_server_number_convert PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function converts a number into an ASCII string. */ -/* */ -/* INPUT */ -/* */ -/* number Unsigned integer number */ -/* string Destination string */ -/* */ -/* OUTPUT */ -/* */ -/* Size Number of bytes in string */ -/* (0 implies an error) */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_http_server_get_process Process GET request */ -/* _nx_http_server_response_send Send response to client */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -UINT _nx_http_server_number_convert(UINT number, CHAR *string) -{ - -UINT j; -UINT digit; -UINT size; - - - /* Initialize counters. */ - size = 0; - - /* Loop to convert the number to ASCII. */ - while (size < 10) - { - - /* Shift the current digits over one. */ - for (j = size; j != 0; j--) - { - - /* Move each digit over one place. */ - string[j] = string[j-1]; - } - - /* Compute the next decimal digit. */ - digit = number % 10; - - /* Update the input number. */ - number = number / 10; - - /* Store the new digit in ASCII form. */ - string[0] = (CHAR) (digit + 0x30); - - /* Increment the size. */ - size++; - - /* Determine if the number is now zero. */ - if (number == 0) - break; - } - - /* Make the string NULL terminated. */ - string[size] = (CHAR) NX_NULL; - - /* Determine if there is an overflow error. */ - if (number) - { - - /* Error, return bad values to user. */ - size = 0; - string[0] = '0'; - } - - /* Return size to caller. */ - return(size); -} - - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -5800,27 +5779,25 @@ UINT temp_name_length; return(sizeof(NX_HTTP_SERVER_DEFAULT_MIME) - 1); } - +#ifdef NX_HTTP_DIGEST_ENABLE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_http_base64_encode PORTABLE C */ -/* 6.1 */ +/* _nx_http_server_nonce_allocate PORTABLE C */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function encodes the input string into a base64 */ -/* representation. */ +/* This function allocate a new nonce for digest authentication. */ /* */ /* INPUT */ /* */ -/* name Name string */ -/* length Length of name */ -/* base64name Encoded base64 name string */ +/* server_ptr HTTP Server pointer */ +/* nonce_ptr Allocated nonce pointer */ /* */ /* OUTPUT */ /* */ @@ -5828,240 +5805,81 @@ UINT temp_name_length; /* */ /* CALLS */ /* */ -/* _nx_utility_string_length_check Check string length */ +/* tx_time_get Get system time */ /* */ /* CALLED BY */ /* */ -/* None */ +/* _nx_http_server_digest_authenticate Digest authentication */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ /* */ /**************************************************************************/ -VOID _nx_http_base64_encode(CHAR *name, UINT length, CHAR *base64name) +UINT _nx_http_server_nonce_allocate(NX_HTTP_SERVER *server_ptr, NX_HTTP_SERVER_NONCE **nonce_ptr) { +UINT i; +UCHAR random_value; +NX_HTTP_SERVER_NONCE *nonces_list = server_ptr -> nx_http_server_nonces; -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - /* Default padding to none. */ - pad = 0; - - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) + /* Search if there is free entry for new nonce. */ + for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++) { - - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; + if (nonces_list[i].nonce_state == NX_HTTP_SERVER_NONCE_INVALID) + { + *nonce_ptr = &(nonces_list[i]); + break; + } } - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) + if (i == NX_HTTP_SERVER_NONCE_MAX) { - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first 6 bits of name character for index. */ - base64name[j++] = _nx_http_server_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) + /* If no free entry, check the timeout of allocated nonces. */ + for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++) { + if (nonces_list[i].nonce_state == NX_HTTP_SERVER_NONCE_VALID) + { + if (tx_time_get() > nonces_list[i].nonce_timestamp + NX_HTTP_SERVER_NONCE_TIMEOUT) + { - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = _nx_http_server_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; + /* If this nonce is timed out, free up this entry for new nonce. */ + *nonce_ptr = &(nonces_list[i]); + break; + } + } } - else if (step == 2) - { - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = _nx_http_server_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ + /* If no entry can be allocated, return error. */ + if (i == NX_HTTP_SERVER_NONCE_MAX) { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = _nx_http_server_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; + return(NX_NOT_FOUND); } } - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < NX_HTTP_MAX_STRING)) + /* Generate new nonce for digest authentication. */ + for (i = 0; i < NX_HTTP_SERVER_NONCE_SIZE; i++) { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; + random_value = (UCHAR)NX_RAND() % (sizeof(_nx_http_server_base64_array) - 1); + (*nonce_ptr) -> nonce_buffer[i] = (UCHAR)_nx_http_server_base64_array[random_value]; } - /* Put a NULL character in. */ - base64name[j] = NX_NULL; -} - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_http_base64_decode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function decodes the input base64 ASCII string and converts */ -/* it into a standard ASCII representation. */ -/* */ -/* INPUT */ -/* */ -/* base64name Encoded base64 name string */ -/* length Length of encoded base64 name */ -/* name Name string */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _nx_utility_string_length_check Check string length */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_http_server_basic_authenticate Basic authentication */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_http_base64_decode(CHAR *base64name, UINT length, CHAR *name) -{ - -UINT i, j; -UINT value1, value2; -UINT step; - - - /* Adjust the length to represent the ASCII name. */ - length = ((length * 6) / 8); - - /* Setup index into the ASCII name. */ - j = 0; - - /* Compute the ASCII name. */ - step = 0; - i = 0; - while ((j < length) && (base64name[i]) && (base64name[i] != '=')) - { - - /* Derive values of the Base64 name. */ - if ((base64name[i] >= 'A') && (base64name[i] <= 'Z')) - value1 = (UINT) (base64name[i] - 'A'); - else if ((base64name[i] >= 'a') && (base64name[i] <= 'z')) - value1 = (UINT) (base64name[i] - 'a') + 26; - else if ((base64name[i] >= '0') && (base64name[i] <= '9')) - value1 = (UINT) (base64name[i] - '0') + 52; - else if (base64name[i] == '+') - value1 = 62; - else if (base64name[i] == '/') - value1 = 63; - else - value1 = 0; - - /* Derive value for the next character. */ - if ((base64name[i+1] >= 'A') && (base64name[i+1] <= 'Z')) - value2 = (UINT) (base64name[i+1] - 'A'); - else if ((base64name[i+1] >= 'a') && (base64name[i+1] <= 'z')) - value2 = (UINT) (base64name[i+1] - 'a') + 26; - else if ((base64name[i+1] >= '0') && (base64name[i+1] <= '9')) - value2 = (UINT) (base64name[i+1] - '0') + 52; - else if (base64name[i+1] == '+') - value2 = 62; - else if (base64name[i+1] == '/') - value2 = 63; - else - value2 = 0; - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first value and first 2 bits of second value. */ - name[j++] = (CHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3)); - i++; - step++; - } - else if (step == 1) - { - - /* Use last 4 bits of first value and first 4 bits of next value. */ - name[j++] = (CHAR) (((value1 & 0xF) << 4) | (value2 >> 2)); - i++; - step++; - } - else if (step == 2) - { - - /* Use first 2 bits and following 6 bits of next value. */ - name[j++] = (CHAR) (((value1 & 3) << 6) | (value2 & 0x3f)); - i++; - i++; - step = 0; - } - } + /* Reset the timestamp and state for the new nonce. */ + (*nonce_ptr) -> nonce_timestamp = tx_time_get(); + (*nonce_ptr) -> nonce_state = NX_HTTP_SERVER_NONCE_VALID; - /* Put a NULL character in. */ - name[j] = NX_NULL; + return(NX_SUCCESS); } - -#ifdef NX_HTTP_DIGEST_ENABLE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_http_server_digest_authenticate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6112,6 +5930,9 @@ UINT step; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_http_server_digest_authenticate(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, UINT name_length, CHAR *password_ptr, UINT password_length, CHAR *realm_ptr, UINT realm_length, UINT *auth_request_present) @@ -6128,6 +5949,8 @@ UINT status, status1, callback_status; CHAR crlf[2] = {13,10}; CHAR authorization_nc[NX_HTTP_MAX_RESOURCE + 1]; CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; +NX_HTTP_SERVER_NONCE *nonce_ptr = NX_NULL; + /* Default to no authentication request detected. */ *auth_request_present = NX_FALSE; @@ -6136,7 +5959,7 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; status = NX_HTTP_DIGEST_AUTHENTICATE; /* Is the authorization request present? */ - if (_nx_http_server_retrieve_digest_authorization(packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce)) + if (_nx_http_server_retrieve_digest_authorization(server_ptr, packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce, &nonce_ptr)) { /* Yes, an authorization request is present. */ @@ -6171,7 +5994,7 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; /* Calculate what the MD5 should be. */ - _nx_http_server_digest_response_calculate(server_ptr, name_ptr, name_length, realm_ptr, realm_length, password_ptr, password_length, _nx_http_server_nonce, method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response); + _nx_http_server_digest_response_calculate(server_ptr, name_ptr, name_length, realm_ptr, realm_length, password_ptr, password_length, (CHAR *)(nonce_ptr -> nonce_buffer), method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response); /* Determine if the calculated response is the same as the received response. */ i = 0; @@ -6189,6 +6012,17 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; /* Otherwise, look at next character. */ i++; } + + /* If the response is authenticated, mark the nonce as accepted. */ + if (status == NX_SUCCESS) + { + nonce_ptr -> nonce_state = NX_HTTP_SERVER_NONCE_ACCEPTED; + } + else + { + nonce_ptr -> nonce_state = NX_HTTP_SERVER_NONCE_INVALID; + } + /* If digest authenticate callback function returns non-success value, the request is considered unauthenticated. */ if(callback_status != NX_SUCCESS) @@ -6199,6 +6033,24 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; if (status == NX_HTTP_DIGEST_AUTHENTICATE) { + /* Allocate a new nonce for digest authentication. */ + status1 = _nx_http_server_nonce_allocate(server_ptr, &nonce_ptr); + + /* Determine if an error occurred in the packet allocation. */ + if (status1) + { + + /* Send response back to HTTP Client. */ + _nx_http_server_response_send(server_ptr, NX_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_HTTP_STATUS_INTERNAL_ERROR) - 1, + "NetX HTTP Server Internal Error", sizeof("NetX HTTP Server Internal Error") - 1, NX_NULL, 0); + + /* Indicate an allocation error occurred. */ + server_ptr -> nx_http_server_allocation_errors++; + + /* Return the internal NetX error. */ + return(status1); + } + /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */ /* Allocate a packet for sending the response back. */ @@ -6275,7 +6127,7 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Place the nonce string into the buffer. */ - nx_packet_data_append(packet_ptr, _nx_http_server_nonce, sizeof(_nx_http_server_nonce) - 1, + nx_packet_data_append(packet_ptr, nonce_ptr -> nonce_buffer, NX_HTTP_SERVER_NONCE_SIZE, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Insert the double quote. */ @@ -6290,6 +6142,14 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + /* Set Content-Length as 0. */ + nx_packet_data_append(packet_ptr, "Content-Length: 0", 17, + server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + + /* Place the into the buffer. */ + nx_packet_data_append(packet_ptr, crlf, 2, + server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + /* Place another into the buffer to signal end of FULL HTTP response. */ nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); @@ -6319,7 +6179,7 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_digest_response_calculate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6365,6 +6225,9 @@ CHAR authorization_cnonce[NX_HTTP_MAX_RESOURCE + 1]; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_http_server_digest_response_calculate(NX_HTTP_SERVER *server_ptr, CHAR *username, UINT username_length, CHAR *realm, UINT realm_length, CHAR *password, UINT password_length, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result) @@ -6375,14 +6238,12 @@ CHAR ha1_string[NX_HTTP_MAX_ASCII_MD5 + 1]; CHAR ha2_string[NX_HTTP_MAX_ASCII_MD5 + 1]; UINT method_length; UINT uri_length; -UINT nonce_length; UINT nc_length; UINT cnonce_length; /* Check string length. */ if (_nx_utility_string_length_check(method, &method_length, 7) || _nx_utility_string_length_check(uri, &uri_length, NX_HTTP_MAX_RESOURCE) || - _nx_utility_string_length_check(nonce, &nonce_length, sizeof(_nx_http_server_nonce) - 1) || _nx_utility_string_length_check(nc, &nc_length, NX_HTTP_MAX_RESOURCE) || _nx_utility_string_length_check(cnonce, &cnonce_length, NX_HTTP_MAX_RESOURCE)) { @@ -6416,7 +6277,7 @@ UINT cnonce_length; _nx_md5_initialize(&(server_ptr -> nx_http_server_md5data)); _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ha1_string, sizeof(ha1_string) - 1); _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1); - _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) nonce, nonce_length); + _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) nonce, NX_HTTP_SERVER_NONCE_SIZE); /* Start of Internet Explorer bug work-around. */ _nx_md5_update(&(server_ptr -> nx_http_server_md5data), (unsigned char *) ":", 1); @@ -6441,7 +6302,7 @@ UINT cnonce_length; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_retrieve_digest_authorization PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6453,11 +6314,13 @@ UINT cnonce_length; /* */ /* INPUT */ /* */ +/* server_ptr HTTP Server pointer */ /* packet_ptr Request packet pointer */ /* response Digest response pointer */ /* uri URI from response pointer */ /* nc Nonce count string */ /* cnonce Client nonce string */ +/* nonce_ptr Server nonce pointer */ /* */ /* OUTPUT */ /* */ @@ -6480,15 +6343,20 @@ UINT cnonce_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -UINT _nx_http_server_retrieve_digest_authorization(NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce) +UINT _nx_http_server_retrieve_digest_authorization(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_HTTP_SERVER_NONCE **nonce_ptr) { UINT length; UINT found; CHAR *buffer_ptr; CHAR *saved_buffer_ptr; +UCHAR *nonce_buffer; +UINT i; /* Set the found flag to false. */ @@ -6608,6 +6476,86 @@ CHAR *saved_buffer_ptr; /* Save current buffer pointer, so each parameter search always starts from here. */ saved_buffer_ptr = buffer_ptr; + while (((buffer_ptr + 6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0)) + { + + /* Check for the uri token. */ + if (((*(buffer_ptr) == 'n') || (*(buffer_ptr) == 'N')) && + ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) && + ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) && + ((*(buffer_ptr+3) == 'c') || (*(buffer_ptr+3) == 'C')) && + ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) && + (*(buffer_ptr+5) == '=')) + { + + /* Move the pointer up to the actual nonce string. */ + buffer_ptr = buffer_ptr + 6; + found = NX_TRUE; + + break; + } + + /* Move the pointer up to the next character. */ + buffer_ptr++; + } + + /* Check if nonce is found. */ + if (!found) + { + return(0); + } + + /* Now remove any extra blanks and quotes. */ + while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22))) + { + + /* Move the pointer up one character. */ + buffer_ptr++; + } + + /* Now pickup the nonce string. */ + length = 0; + nonce_buffer = (UCHAR *)buffer_ptr; + while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13)) + { + + /* Determine if the ending quote is present. */ + if (*buffer_ptr == (CHAR) 0x22) + { + break; + } + + /* Increase the length. */ + length++; + buffer_ptr++; + } + + /* Check the nonce size. */ + if (length != NX_HTTP_SERVER_NONCE_SIZE) + { + return(0); + } + + /* Check if the nonce is valid. */ + for (i = 0; i < NX_HTTP_SERVER_NONCE_MAX; i++) + { + if ((server_ptr -> nx_http_server_nonces[i].nonce_state != NX_HTTP_SERVER_NONCE_INVALID) && + (memcmp(server_ptr -> nx_http_server_nonces[i].nonce_buffer, nonce_buffer, NX_HTTP_SERVER_NONCE_SIZE) == 0)) /* Use case of memcmp is verified. */ + { + *nonce_ptr = &(server_ptr -> nx_http_server_nonces[i]); + break; + } + } + + /* If the nonca is invalid, just return. */ + if (i == NX_HTTP_SERVER_NONCE_MAX) + { + return(0); + } + + /* Get saved buffer pointer. */ + buffer_ptr = saved_buffer_ptr; + /* Now look for the nc in the digest response. */ while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0)) { @@ -6667,9 +6615,9 @@ CHAR *saved_buffer_ptr; if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) && ((*(buffer_ptr+1) == 'n') || (*(buffer_ptr+1) == 'N')) && ((*(buffer_ptr+2) == 'o') || (*(buffer_ptr+2) == 'O')) && - ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+2) == 'N')) && - ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+2) == 'C')) && - ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+2) == 'E')) && + ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+3) == 'N')) && + ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) && + ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+5) == 'E')) && (*(buffer_ptr+6) == '=')) { @@ -6774,11 +6722,11 @@ CHAR *saved_buffer_ptr; if (((*buffer_ptr == 'r') || (*buffer_ptr == 'R')) && ((*(buffer_ptr+1) == 'e') || (*(buffer_ptr+1) == 'E')) && ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) && - ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+2) == 'P')) && - ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+2) == 'O')) && - ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+2) == 'N')) && - ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+2) == 'S')) && - ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+2) == 'E')) && + ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+3) == 'P')) && + ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) && + ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) && + ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+6) == 'S')) && + ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+7) == 'E')) && (*(buffer_ptr+8) == '=')) { @@ -6984,7 +6932,7 @@ UINT _nxe_http_server_get_entity_header(NX_HTTP_SERVER *server_ptr, NX_PACKET * /* FUNCTION RELEASE */ /* */ /* _nx_http_server_get_entity_header PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7026,6 +6974,9 @@ UINT _nxe_http_server_get_entity_header(NX_HTTP_SERVER *server_ptr, NX_PACKET * /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* fixed write underflow, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* verified memmove use cases, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_http_server_get_entity_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size) @@ -7129,7 +7080,7 @@ UINT index; /* Leave boundary string only. */ memmove(&multipart_ptr -> nx_http_server_multipart_boundary[4], &multipart_ptr -> nx_http_server_multipart_boundary[index], - quotation_index - index + 1); + quotation_index - index + 1); /* Use case of memmove is verified. */ } else { @@ -8046,7 +7997,7 @@ UCHAR ch; /* FUNCTION RELEASE */ /* */ /* _nx_http_server_generate_response_header PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8081,7 +8032,7 @@ UCHAR ch; /* nx_packet_data_append */ /* memcmp */ /* _nx_utility_string_length_check */ -/* _nx_http_server_number_convert */ +/* _nx_utility_uint_to_string */ /* _nx_http_server_date_to_string */ /* nx_packet_release */ /* */ @@ -8100,6 +8051,10 @@ UCHAR ch; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_http_server_generate_response_header(NX_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, CHAR *status_code, @@ -8183,7 +8138,7 @@ CHAR status_code_not_modified; { /* Convert the content_length to ASCII representation. */ - temp = _nx_http_server_number_convert(content_length, temp_string); + temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string)); /* Place the "Content-Length" field in the header. */ status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16, @@ -8247,7 +8202,7 @@ CHAR status_code_not_modified; server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Convert the max-age to ASCII representation. */ - temp = _nx_http_server_number_convert(max_age, temp_string); + temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string)); status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_http_server_packet_pool_ptr, NX_WAIT_FOREVER); diff --git a/addons/http/nxd_http_server.h b/addons/http/nxd_http_server.h index 70dd3e2b..ffe9b0e9 100644 --- a/addons/http/nxd_http_server.h +++ b/addons/http/nxd_http_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_http_server.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,18 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ +/* */ /* */ /**************************************************************************/ @@ -172,8 +184,26 @@ extern "C" { #define NX_HTTP_SERVER_RETRY_SHIFT 1 /* Every retry is twice as long */ #endif -/* NX_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed. */ -#define NX_HTTP_MAX_STRING ((NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 1) * 4 / 3 + 1) +#ifndef NX_HTTP_SERVER_NONCE_SIZE +#define NX_HTTP_SERVER_NONCE_SIZE 32 /* The size of nonce for digest authtentication */ +#endif + +#ifndef NX_HTTP_SERVER_NONCE_MAX +#define NX_HTTP_SERVER_NONCE_MAX 2 /* The size of nonce for digest authtentication */ +#endif + +#ifndef NX_HTTP_SERVER_NONCE_TIMEOUT +#define NX_HTTP_SERVER_NONCE_TIMEOUT (10 * NX_IP_PERIODIC_RATE) +#endif + +/* Define the state of the nonce. */ + +#define NX_HTTP_SERVER_NONCE_INVALID 0 +#define NX_HTTP_SERVER_NONCE_VALID 1 +#define NX_HTTP_SERVER_NONCE_ACCEPTED 2 + +/* NX_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed and plus 2 pad if needed. */ +#define NX_HTTP_MAX_STRING ((NX_HTTP_MAX_NAME + NX_HTTP_MAX_PASSWORD + 1) * 4 / 3 + 1 + 2) #define NX_HTTP_MAX_BINARY_MD5 16 #define NX_HTTP_MAX_ASCII_MD5 32 @@ -303,6 +333,17 @@ typedef struct NX_HTTP_SERVER_DATE_STRUCT UCHAR nx_http_server_weekday; /* Weekday */ } NX_HTTP_SERVER_DATE; + +/* Define the nonce structure. */ + +typedef struct NX_HTTP_SERVER_NONCE_STRUCT +{ + UINT nonce_state; /* The state of the nonce */ + UINT nonce_timestamp; /* The time when the nonce is created */ + UCHAR nonce_buffer[NX_HTTP_SERVER_NONCE_SIZE]; /* Nonce for digest authetication */ +} NX_HTTP_SERVER_NONCE; + + /* Define the multipart context data structure. */ typedef struct NX_HTTP_SERVER_MULTIPART_STRUCT @@ -361,6 +402,8 @@ typedef struct NX_HTTP_SERVER_STRUCT TX_THREAD nx_http_server_thread; /* HTTP server thread */ #ifdef NX_HTTP_DIGEST_ENABLE NX_MD5 nx_http_server_md5data; /* HTTP server MD5 work area */ + NX_HTTP_SERVER_NONCE + nx_http_server_nonces[NX_HTTP_SERVER_NONCE_MAX];/* Nonce for digest authetication */ #endif /* NX_HTTP_DIGEST_ENABLE */ #ifdef NX_HTTP_MULTIPART_ENABLE @@ -573,17 +616,16 @@ UINT _nx_http_server_basic_authenticate(NX_HTTP_SERVER *server_ptr, NX_PA UINT _nx_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr); UINT _nx_http_server_retrieve_resource(NX_PACKET *packet_ptr, CHAR *destination, UINT max_size); UINT _nx_http_server_calculate_content_offset(NX_PACKET *packet_ptr); -UINT _nx_http_server_number_convert(UINT number, CHAR *string); UINT _nx_http_server_type_get(NX_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string); UINT _nx_http_server_type_get_extended(NX_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length, CHAR *http_type_string, UINT http_type_string_max_size); -VOID _nx_http_base64_encode(CHAR *name, UINT length, CHAR *base64name); -VOID _nx_http_base64_decode(CHAR *base64name, UINT length, CHAR *name); +UINT _nx_http_server_disconnect(NX_HTTP_SERVER *http_server_ptr, UINT wait_option); #ifdef NX_HTTP_DIGEST_ENABLE UINT _nx_http_server_digest_authenticate(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, UINT name_length, CHAR *password_ptr, UINT password_length, CHAR *realm_ptr, UINT realm_length, UINT *auth_request_present); VOID _nx_http_server_digest_response_calculate(NX_HTTP_SERVER *server_ptr, CHAR *username, UINT username_length, CHAR *realm, UINT realm_length, CHAR *password, UINT password_length, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result); -UINT _nx_http_server_retrieve_digest_authorization(NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce); +UINT _nx_http_server_retrieve_digest_authorization(NX_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_HTTP_SERVER_NONCE **nonce_ptr); VOID _nx_http_server_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination); +UINT _nx_http_server_nonce_allocate(NX_HTTP_SERVER *server_ptr, NX_HTTP_SERVER_NONCE **nonce_ptr); #endif #ifdef NX_HTTP_MULTIPART_ENABLE diff --git a/addons/lwm2m/nx_lwm2m_client.c b/addons/lwm2m/nx_lwm2m_client.c new file mode 100644 index 00000000..6322331a --- /dev/null +++ b/addons/lwm2m/nx_lwm2m_client.c @@ -0,0 +1,20450 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Lightweight M2M Protocol (LWM2M) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#define NX_LWM2M_CLIENT_SOURCE_CODE + +#include "nx_lwm2m_client.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* ip_ptr Pointer to IP instance */ +/* packet_pool_ptr Pointer to packet pool */ +/* name_ptr Endpoint name of LWM2M client */ +/* name_length Length of endpoint name */ +/* msisdn_ptr Optional MSISDN number */ +/* msisdn_length Length of MSISDN number */ +/* binding_mode Supported binding and modes */ +/* stack_ptr Client thread's stack pointer */ +/* stack_size Client thread's stack size */ +/* priority Priority of client thread */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_create */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_create(NX_LWM2M_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool_ptr, + const CHAR *name_ptr, UINT name_length, const CHAR *msisdn_ptr, UINT msisdn_length, + UCHAR binding_modes, VOID *stack_ptr, ULONG stack_size, UINT priority) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || (name_ptr == NX_NULL) || (stack_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Check for a memory size error. */ + if (stack_size < TX_MINIMUM_STACK) + { + return(NX_SIZE_ERROR); + } + + /* Check the priority specified. */ + if (priority >= TX_MAX_PRIORITIES) + { + return(NX_OPTION_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_create(client_ptr, ip_ptr, packet_pool_ptr, name_ptr, name_length, msisdn_ptr, msisdn_length, binding_modes, stack_ptr, stack_size, priority); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_delete(NX_LWM2M_CLIENT *client_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_delete(client_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_device_callback_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function installs the application callback for implementing */ +/* operations on the LWM2M Device Object resources not handled by the */ +/* LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* operation_callback The operation callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_device_callback_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_device_callback_set(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK operation_callback) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (operation_callback == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_device_callback_set(client_ptr, operation_callback); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_device_error_push PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a new instance to the error code resource of */ +/* the Device Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* code The new error code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_device_error_push */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_device_error_push(NX_LWM2M_CLIENT *client_ptr, UCHAR code) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_device_error_push(client_ptr, code); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_device_error_reset PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes all error code resource instances from the */ +/* Device Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_device_error_reset */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_device_error_reset(NX_LWM2M_CLIENT *client_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_device_error_reset(client_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_device_resource_changed PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function signals the LWM2M Client that a resource of the */ +/* Device Object has changed. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* resource_ptr The resource ID and value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nxe_lwm2m_client_device_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_device_resource_changed(NX_LWM2M_CLIENT *client_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (resource_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_device_resource_changed(client_ptr, resource_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_firmware_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions initializes the Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* client_ptr Pointer to LWM2M client */ +/* protocols The supported protocols */ +/* package_callback The package callback */ +/* package_uri_callback The package URI callback */ +/* update_callback The update callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_firmware_create */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_firmware_create(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_CLIENT *client_ptr, UINT protocols, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK package_callback, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK package_uri_callback, NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK update_callback) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((firmware_ptr == NX_NULL) || (client_ptr == NX_NULL) || + ((package_callback == NX_NULL) && (package_uri_callback == NX_NULL)) || (update_callback == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_firmware_create(firmware_ptr, client_ptr, protocols, package_callback, package_uri_callback, update_callback); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_firmware_package_info_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the package information resources of the */ +/* Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* name The name of firmware package */ +/* name_length The length of name */ +/* version The version of firmware */ +/* package */ +/* version_length The length of version */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_firmware_package_info_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_firmware_package_info_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *name, UINT name_length, const CHAR *version, UINT version_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((firmware_ptr == NX_NULL) || (name == NX_NULL) || (version == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_firmware_package_info_set(firmware_ptr, name, name_length, version,version_length); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_firmware_result_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions sets the Update Result resource of the Firmware */ +/* Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* result The Update Result */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_firmware_result_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_firmware_result_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR result) +{ +UINT status; + + /* Check for invalid input pointers */ + if (firmware_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_firmware_result_set(firmware_ptr, result); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_firmware_state_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions sets the State of the Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* state The state of the Firmware */ +/* Object */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_firmware_state_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_firmware_state_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR state) +{ +UINT status; + + /* Check for invalid input pointers */ + if (firmware_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_firmware_state_set(firmware_ptr, state); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_lock PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function locks the LWM2M Client to prevent concurent access. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_lock */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_lock(NX_LWM2M_CLIENT *client_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_lock(client_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a new Object implementation to the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_ptr Pointer to the Object */ +/* object_id The Object ID */ +/* object_operation Object operation function */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_add(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID object_id, + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK object_operation) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (object_ptr == NX_NULL) || (object_operation == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Objects 0-3 are already implemented by the LWM2M Client */ + if (object_id <= NX_LWM2M_CLIENT_DEVICE_OBJECT_ID) + { + + /* Return duplicated ID error */ + return(NX_LWM2M_CLIENT_ALREADY_EXIST); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_add(client_ptr, object_ptr, object_id, object_operation); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id_ptr Pointer to the Instance ID */ +/* num_values Number of values to set */ +/* values Pointer to the values */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_create */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_create(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || ((num_values != 0) && (values == NX_NULL))) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_create(client_ptr, object_id, instance_id_ptr, num_values, values); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_delete(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_delete(client_ptr, object_id, instance_id); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the list of resources implemented by an */ +/* Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_resources Pointer to the number of */ +/* resources */ +/* resources Pointer to the resource info */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_discover */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_discover(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT *num_resources, NX_LWM2M_CLIENT_RESOURCE *resources) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (num_resources == NX_NULL) || (resources == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_discover(client_ptr, object_id, instance_id, num_resources, resources); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the execute operation on an Object resource. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* resource_id The Resource ID */ +/* args_ptr Pointer to the arguments */ +/* args_length Length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_execute */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_execute(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || ((args_length != 0) && (args_ptr == NX_NULL))) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_execute(client_ptr, object_id, instance_id, resource_id, args_ptr, args_length); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_instance_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function add a new Object Instance to the Instance list. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* instance_ptr Pointer to the Object Instance*/ +/* instance_id_ptr Pointer to the Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_instance_add */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_instance_add(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID *instance_id_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_instance_add(object_ptr, instance_ptr, instance_id_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_instance_next_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the next Instance of an Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id_ptr Pointer to the Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nxe_lwm2m_client_object_instance_next_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_instance_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (instance_id_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_instance_next_get(client_ptr, object_id, instance_id_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_instance_remove PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes an Object Instance from Instance list. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to the Object */ +/* instance_ptr Pointer to the Instance */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_instance_remove */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_instance_remove(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_instance_remove(object_ptr, instance_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_next_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the next Object of the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id_ptr Pointer to the Object ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_next_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID *object_id_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (object_id_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_next_get(client_ptr, object_id_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads resources from an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_values The number of resources */ +/* values Pointer to the resources */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_read */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, NX_LWM2M_CLIENT_RESOURCE *values) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || ((num_values != 0) && (values == NX_NULL))) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_read(client_ptr, object_id, instance_id, num_values, values); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_remove PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function remove an Object from the LWM2M Client Object list. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_ptr Pointer to Object */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_remove */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_remove(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (object_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Objects 0-3 are implemented internally, can't be removed by user */ + if (object_ptr -> object_id <= NX_LWM2M_CLIENT_DEVICE_OBJECT_ID) + { + + /* Return duplicated ID error */ + return(NX_LWM2M_CLIENT_FORBIDDEN); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_remove(client_ptr, object_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_resource_changed PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function signals the LWM2M Client that an object resource. */ +/* value has changed */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to the Object */ +/* instance_ptr Pointer to the Object Instance*/ +/* resource_ptr The resource ID and value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_resource_changed(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL) || (resource_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_resource_changed(object_ptr, instance_ptr, resource_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_object_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes resources to an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_values The number of resources */ +/* values Pointer to the resources */ +/* write_op The type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_write */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_object_write(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, UINT write_op) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || ((num_values != 0) && (values == NX_NULL))) + { + return(NX_PTR_ERROR); + } + + /* Check for invalid write operation */ + if (write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE && + write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE && + write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_RESOURCE && + write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) + { + return(NX_OPTION_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_object_write(client_ptr, object_id, instance_id, num_values, values, write_op); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_boolean_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a boolean resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* bool_ptr On return, the boolean value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_boolean_get Get boolean resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_boolean_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_BOOL *bool_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (bool_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_boolean_get(value, bool_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_boolean_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a boolean resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* bool_data The boolean value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_boolean_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_boolean_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_BOOL bool_data) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_boolean_set(resource_ptr, bool_data); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_dim_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the dim of multiple resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* dim Dim of the multiple resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_dim_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_dim_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR *dim) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (dim == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_dim_get(resource_ptr, dim); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_dim_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the dim of multiple resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* dim Dim of the multiple resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_dim_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_dim_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR dim) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_dim_set(resource_ptr, dim); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_float32_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 32-bit floating point resource.*/ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* float32_ptr On return, the floating point */ +/* value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_float32_get Get 32-bit floating point */ +/* resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_float32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT32 *float32_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (float32_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_float32_get(value, float32_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_float32_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 32-bit floating point resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* float32_data The floating data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_float32_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_float32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT32 float32_data) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_float32_set(resource_ptr, float32_data); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_float64_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 64-bit floating point resource.*/ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* float64_ptr On return, the floating point */ +/* value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_float64_get Get 64-bit floating point */ +/* resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_float64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT64 *float64_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (float64_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_float64_get(value, float64_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_float64_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 64-bit floating point resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* float64_data The floating point value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_float64_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_float64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT64 float64_data) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_float64_set(resource_ptr, float64_data); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the information of resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_id ID of the resource */ +/* operation Orperation of the resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_info_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_info_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID *resource_id, ULONG *operation) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (resource_id == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_info_get(resource_ptr, resource_id, operation); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_info_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the information of resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_id ID of the resource */ +/* operation Orperation of the resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_info_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_info_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID resource_id, ULONG operation) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_info_set(resource_ptr, resource_id, operation); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_instances_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the multiple resource instances. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_instances Pointer to the instances */ +/* count Count of the instances */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_instances_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_instances_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT *count) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (resource_instances == NX_NULL) || (count == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_instances_get(resource_ptr, resource_instances, count); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_instances_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets multiple resource instances. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_instances Pointer to the instances */ +/* count Count of the instances */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_instances_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_instances_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT count) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (resource_instances == NX_NULL) || (count == 0)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_instances_set(resource_ptr, resource_instances, count); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_integer32_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 32-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* int32_ptr On return, the integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get Get 32-bit integer resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_integer32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT32 *int32_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (int32_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_integer32_get(value, int32_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_integer32_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 32-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* int32_data The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_integer32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT32 int32_data) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_integer32_set(resource_ptr, int32_data); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_integer64_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 64-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* int64_ptr On return, the integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer64_get Get 64-bit integer resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_integer64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT64 *int64_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (int64_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_integer64_get(value, int64_ptr); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_integer64_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 64-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* int64_data The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer64_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_integer64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT64 int64_data) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_integer64_set(resource_ptr, int64_data); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_objlnk_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of an Object Link resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* object_id On return, the object ID */ +/* instance_id On return, the instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_objlnk_get Get Object Link resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_objlnk_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_ID *object_id, NX_LWM2M_ID *instance_id) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (object_id == NX_NULL) || (instance_id == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_objlnk_get(value, object_id, instance_id); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_objlnk_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of an Object Link resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* object_id The object ID */ +/* instance_id The instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_objlnk_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_objlnk_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id) +{ +UINT status; + + /* Check for invalid input pointers */ + if (resource_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_objlnk_set(resource_ptr, object_id, instance_id); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_opaque_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of an opaque resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* opaque_ptr On return, a pointer to the */ +/* opaque data */ +/* opaque_length On return, the length of the */ +/* opaque data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_opaque_get Get opaque resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_opaque_get(NX_LWM2M_CLIENT_RESOURCE *value, const VOID **opaque_ptr, UINT *opaque_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (opaque_ptr == NX_NULL) || (opaque_length == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_opaque_get(value, opaque_ptr, opaque_length); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_opaque_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of an opaque resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* opaque_ptr Apointer to the opaque data */ +/* opaque_length The length of the opaque data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_opaque_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_opaque_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, VOID *opaque_ptr, UINT opaque_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (opaque_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_opaque_set(resource_ptr, opaque_ptr, opaque_length); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_string_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a string resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* string_ptr On return, a pointer to the */ +/* string */ +/* string_length On return, the length of the */ +/* string */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_string_get Get string resource */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_string_get(NX_LWM2M_CLIENT_RESOURCE *value, const CHAR **string_ptr, UINT *string_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((value == NX_NULL) || (string_ptr == NX_NULL) || (string_length == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_string_get(value, string_ptr, string_length); + + /* Return completion status */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_resource_string_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a string resource. */ +/* */ +/* INPUT */ +/* */ +/* Resource_ptr Pointer to the resource */ +/* string_ptr A pointer to the string */ +/* string_length Length of the string */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_string_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_resource_string_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, CHAR *string_ptr, UINT string_length) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((resource_ptr == NX_NULL) || (string_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_resource_string_set(resource_ptr, string_ptr, string_length); + + /* Return completion status */ + return(status); +} + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_bootstrap PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a session with a Bootstrap server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_id The Security Instance ID of */ +/* the bootstrap server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nxe_lwm2m_client_session_bootstrap */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_bootstrap(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (ip_address == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_bootstrap(session_ptr, security_id, ip_address, port); + + /* Return completion status */ + return(status); +} + +#ifdef NX_SECURE_ENABLE_DTLS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_bootstrap_dtls PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a session with a Bootstrap server using a */ +/* secure channel. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_id The Security Instance ID of */ +/* the bootstrap server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* dtls_session_ptr The pointer to the DTLS */ +/* session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_bootstrap_dtls */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_bootstrap_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (ip_address == NX_NULL) || (dtls_session_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_bootstrap_dtls(session_ptr, security_id, ip_address, port, dtls_session_ptr); + + /* Return completion status */ + return(status); +} +#endif /* NX_SECURE_ENABLE_DTLS */ +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions creates a LWM2M Client Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* client_ptr Pointer to LWM2M Client */ +/* state_callback The session state callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_create */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_create(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK state_callback) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (client_ptr == NX_NULL) || (state_callback == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_create(session_ptr, client_ptr, state_callback); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a LWM2M Client Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_delete(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (session_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_delete(session_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_deregister PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deregisters the Client from a LWM2M Server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_deregister */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_deregister(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (session_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_deregister(session_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_error_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the error code of a LWM2M Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status The error code */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_error_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_error_get(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (session_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_error_get(session_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_register PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers the Client to a LWM2M server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* server_id The Short Server ID of the */ +/* LWM2M server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_register */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_register(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (ip_address == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_register(session_ptr, server_id, ip_address, port); + + /* Return completion status */ + return(status); +} + +#ifdef NX_SECURE_ENABLE_DTLS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_register_dtls PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers the Client to a LWM2M server using a */ +/* secure channel. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* server_id The Short Server ID of the */ +/* LWM2M server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* dtls_session_ptr The pointer to the DTLS */ +/* session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_register_dtls */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_register_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (ip_address == NX_NULL) || (dtls_session_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_register_dtls(session_ptr, server_id, ip_address, port, dtls_session_ptr); + + /* Return completion status */ + return(status); +} + +#endif /* NX_SECURE_ENABLE_DTLS */ + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_register_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the server and security information for the next */ +/* registration step. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_instance_id Security instance ID */ +/* server_id Server ID */ +/* server_uri Server URI */ +/* server_uri_len Length of server URI */ +/* security_mode Security Mode */ +/* pub_key_or_id Public key or ID */ +/* pub_key_or_id_len Length of public key or ID */ +/* server_pub_key Server public key */ +/* server_pub_key_len Length of server public key */ +/* secret_key Secret key */ +/* secret_key_len Length of secret key */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_register_info_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_register_info_get(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT security_instance_id, NX_LWM2M_ID *server_id, CHAR **server_uri, UINT *server_uri_len, UCHAR *security_mode, + UCHAR **pub_key_or_id, UINT *pub_key_or_id_len, UCHAR **server_pub_key, UINT *server_pub_key_len, UCHAR **secret_key, UINT *secret_key_len) +{ +UINT status; + + /* Check for invalid input pointers */ + if ((session_ptr == NX_NULL) || (server_id == NX_NULL) || (server_uri == NX_NULL) || (server_uri_len == NX_NULL) || (security_mode == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_register_info_get(session_ptr, security_instance_id, server_id, server_uri, server_uri_len, security_mode, + pub_key_or_id, pub_key_or_id_len, server_pub_key, server_pub_key_len, secret_key, secret_key_len); + + /* Return completion status */ + return(status); +} +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_session_update PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the Client to a LWM2M Server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_update */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_session_update(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (session_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_session_update(session_ptr); + + /* Return completion status */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_lwm2m_client_unlock PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unlocks the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_unlock */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_lwm2m_client_unlock(NX_LWM2M_CLIENT *client_ptr) +{ +UINT status; + + /* Check for invalid input pointers */ + if (client_ptr == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Call actual function */ + status = _nx_lwm2m_client_unlock(client_ptr); + + /* Return completion status */ + return(status); +} + + + +#if NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the read operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +UINT i, j; +NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *) object_instance_ptr; +NX_LWM2M_CLIENT_RESOURCE *resource_instances = object_ptr -> object_client_ptr -> nx_lwm2m_client_mulitple_temp_resources; + + NX_PARAMETER_NOT_USED(object_ptr); + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> access_control_instance_object_id; + break; + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_INSTANCE_ID_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> access_control_instance_object_instance_id; + break; + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_ACL_ID: + + if (instance_ptr -> access_control_instance_acl_count == 0) + { + + /* No ACL defined */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + + for (j = 0; j < instance_ptr -> access_control_instance_acl_count; j++) + { + + _nx_lwm2m_client_resource_info_set(&resource_instances[j], instance_ptr -> access_control_instance_acl[j].acl_server_id, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resource_instances[j], instance_ptr -> access_control_instance_acl[j].acl_flags); + } + + _nx_lwm2m_client_resource_instances_set(&resource[i], resource_instances, instance_ptr -> access_control_instance_acl_count); + break; + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OWNER_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> access_control_instance_owner; + break; + + /* Unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the discover operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* num_resources_ptr Pointer to number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *num_resources_ptr) +{ + +NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *) object_instance_ptr; +UINT resource_count; + + NX_PARAMETER_NOT_USED(object_ptr); + + if (instance_ptr -> access_control_instance_acl_count != 0) + { + resource_count = 4; + } + else + { + resource_count = 3; + } + if (*num_resources_ptr < resource_count) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + resources[0].resource_id = NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID_ID; + resources[0].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[1].resource_id = NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_INSTANCE_ID_ID; + resources[1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + if (instance_ptr -> access_control_instance_acl_count != 0) + { + resources[2].resource_id = NX_LWM2M_CLIENT_ACCESS_CONTROL_ACL_ID; + resources[2].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[2].resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + resources[2].resource_dim = (UCHAR)instance_ptr -> access_control_instance_acl_count; + } + resources[resource_count-1].resource_id = NX_LWM2M_CLIENT_ACCESS_CONTROL_OWNER_ID; + resources[resource_count-1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + + *num_resources_ptr = resource_count; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the write operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* write_op Type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* _nx_lwm2m_client_resource_instances_get */ +/* _nx_lwm2m_client_resource_info_get */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, UINT write_op) +{ +NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *) object_instance_ptr; +UINT i, j; +UINT status; +ULONG flags; +NX_LWM2M_INT32 object_id; +NX_LWM2M_INT32 instance_id; +NX_LWM2M_INT32 owner; +UINT acl_count; +NX_LWM2M_CLIENT_RESOURCE resource_instance[NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS]; +NX_LWM2M_CLIENT_ACL acl[NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS]; +NX_LWM2M_INT32 acl_flags; + + NX_PARAMETER_NOT_USED(object_ptr); + + /* XXX replace not supported? */ + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Check validity of values before updating instance */ + flags = 0; + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID_ID: + + /* Resource is read-only, can only be set during boostrap or instance creation */ + if (write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP && write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + status = _nx_lwm2m_client_resource_integer32_get(&resource[i], &object_id); + if (status != NX_SUCCESS) + { + return(status); + } + /* Object ID must be in range 1-65534 */ + if (object_id < 1 || object_id > 65534) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + flags |= 1< 65535) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + flags |= 1< 65535) + { + + /* Flag must fit in 16-bit */ + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + acl[j].acl_flags = (USHORT) acl_flags; + } + + /* Check we have enought space for update */ + if (instance_ptr -> access_control_instance_acl_count != 0 && write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE) + { + UINT acl_total; + acl_total = instance_ptr -> access_control_instance_acl_count; + for (j=0; j access_control_instance_acl_count; k++) + { + if (instance_ptr -> access_control_instance_acl[k].acl_server_id == acl[j].acl_server_id) + { + + /* Instance already exists */ + break; + } + } + if (k >= instance_ptr -> access_control_instance_acl_count) + { + + /* New instance */ + acl_total++; + } + } + if (acl_total > NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS) + { + + /* Too many instances */ + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + } + flags |= 1< 65535) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + flags |= 1< access_control_instance_object_id = (NX_LWM2M_ID) object_id; + } + if (flags & 1< access_control_instance_object_instance_id = (NX_LWM2M_ID) instance_id; + } + if (flags & 1< access_control_instance_acl_count != 0 && write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE) + { + UINT current_count; + + /* Update existing resource */ + current_count = instance_ptr -> access_control_instance_acl_count; + for (j=0; j access_control_instance_acl[k].acl_server_id == acl[j].acl_server_id) + { + + /* Instance already exists */ + break; + } + } + if (k < current_count) + { + + /* Update existing instance */ + instance_ptr -> access_control_instance_acl[k].acl_flags = acl[j].acl_flags; + } + else + { + + /* Add new instance */ + instance_ptr -> access_control_instance_acl[instance_ptr -> access_control_instance_acl_count] = acl[j]; + instance_ptr -> access_control_instance_acl_count++; + } + } + } + else + { + + /* Replace resource */ + instance_ptr -> access_control_instance_acl_count = (USHORT)acl_count; + if (acl_count != 0) + { + memcpy(instance_ptr -> access_control_instance_acl, acl, acl_count*sizeof(acl[0])); /* Use case of memcpy is verified. */ + } + } + } + if (flags & 1< access_control_instance_owner = (NX_LWM2M_ID) owner; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the execute operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id The ID of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ + + NX_PARAMETER_NOT_USED(object_ptr); + NX_PARAMETER_NOT_USED(instance_ptr); + NX_PARAMETER_NOT_USED(args_ptr); + NX_PARAMETER_NOT_USED(args_length); + + switch (resource_id) + { + + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID_ID: + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_INSTANCE_ID_ID: + case NX_LWM2M_CLIENT_ACCESS_CONTROL_ACL_ID: + case NX_LWM2M_CLIENT_ACCESS_CONTROL_OWNER_ID: + + /* Non-executable resources */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + default: + + /* Unkown resource */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the create operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_id Pointer to object instance ID */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* bootstrap Flag of bootstrap step */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_access_control_write */ +/* _nx_lwm2m_client_object_instance_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_create(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, NX_LWM2M_BOOL bootstrap) +{ + NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT *access_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT *) object_ptr; + NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *instance_ptr; + UINT status; + + /* Allocate a new instance */ + instance_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE *) access_ptr -> access_control_object_instances_free_list; + if (instance_ptr == NX_NULL) + { + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* Initialize resources with default values */ + instance_ptr -> access_control_instance_object_id = NX_LWM2M_CLIENT_RESERVED_ID; + instance_ptr -> access_control_instance_object_instance_id = NX_LWM2M_CLIENT_RESERVED_ID; + instance_ptr -> access_control_instance_owner = NX_LWM2M_CLIENT_RESERVED_ID; + instance_ptr -> access_control_instance_acl_count = 0; + + /* Write the provided resources */ + status = _nx_lwm2m_client_access_control_write((NX_LWM2M_CLIENT_OBJECT *) access_ptr, (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) instance_ptr, resource, resource_count, bootstrap ? NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP : NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Update free instance list */ + access_ptr -> access_control_object_instances_free_list = instance_ptr -> access_control_instance.object_instance_next; + + /* Add new instance to the instance list */ + status = _nx_lwm2m_client_object_instance_add(object_ptr, &(instance_ptr -> access_control_instance), instance_id); + if (status != NX_SUCCESS) + { + + /* Revert the free instance list */ + access_ptr -> access_control_object_instances_free_list = &(instance_ptr -> access_control_instance); + return(status); + } + + /* Return success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the delete operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_instance_remove */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_access_control_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_delete(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ + NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT *access_ptr = (NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT *) object_ptr; + UINT status; + + /* Remove the instance from instance list */ + status = _nx_lwm2m_client_object_instance_remove(object_ptr, instance_ptr); + if (status) + { + return(status); + } + + /* Release the instance */ + instance_ptr -> object_instance_next = access_ptr -> access_control_object_instances_free_list; + access_ptr -> access_control_object_instances_free_list = instance_ptr; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_operation PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the object operation. */ +/* */ +/* INPUT */ +/* */ +/* operation The operation type */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_access_control_read */ +/* _nx_lwm2m_client_access_control_discover */ +/* _nx_lwm2m_client_access_control_write */ +/* _nx_lwm2m_client_access_control_execute */ +/* _nx_lwm2m_client_access_control_write */ +/* _nx_lwm2m_client_access_control_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_access_control_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +UINT *write_op; +NX_LWM2M_CLIENT_OPERATION_ARGUMENT *arguments; + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return(_nx_lwm2m_client_access_control_read(object_ptr, object_instance_ptr, resource, *resource_count)); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return(_nx_lwm2m_client_access_control_discover(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Get the type of write operation */ + write_op = (UINT *)args_ptr; + + /* Call write function */ + return(_nx_lwm2m_client_access_control_write(object_ptr, object_instance_ptr, resource, *resource_count, *write_op)); + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return(_nx_lwm2m_client_access_control_execute(object_ptr, object_instance_ptr, resource -> resource_id, args_ptr, args_length)); + case NX_LWM2M_CLIENT_OBJECT_CREATE: + + /* Get arguments */ + arguments = (NX_LWM2M_CLIENT_OPERATION_ARGUMENT *)args_ptr; + + /* Call create function */ + return(_nx_lwm2m_client_access_control_create(object_ptr, &(arguments -> instance_id), resource, *resource_count, arguments -> bootstrap)); + case NX_LWM2M_CLIENT_OBJECT_DELETE: + + /* Call delete function */ + return(_nx_lwm2m_client_access_control_delete(object_ptr, object_instance_ptr)); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_access_control_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the Access Control Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_create */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_access_control_object_create(NX_LWM2M_CLIENT *client_ptr) +{ +int i; +NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT *access_ptr = &(client_ptr -> nx_lwm2m_client_access_control); + + /* Add Access Control Object to the LWM2M Client */ + _nx_lwm2m_client_object_add(client_ptr, &(access_ptr -> access_control_object), NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID, _nx_lwm2m_client_access_control_operation); + + /* Initialize the list of free instances */ + access_ptr -> access_control_object_instances_free_list = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &access_ptr -> access_control_object_instances[0]; + for (i = 0; i < NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES - 1; i++) + { + access_ptr -> access_control_object_instances[i].access_control_instance.object_instance_next = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &access_ptr -> access_control_object_instances[i + 1]; + } + access_ptr -> access_control_object_instances[NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES - 1].access_control_instance.object_instance_next = NX_NULL; +} + +#endif /* NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_binding_mode_string_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the string corresponding to the given */ +/* binding mode. */ +/* */ +/* INPUT */ +/* */ +/* binding_mode The binding mode */ +/* length The length of binding mode */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to binding mode string */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_read */ +/* _nx_lwm2m_client_server_read */ +/* _nx_lwm2m_client_session_send_request */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +const CHAR *_nx_lwm2m_client_binding_mode_string_get(UCHAR binding_mode, UINT *length) +{ + switch (binding_mode) + { + + case NX_LWM2M_CLIENT_BINDING_U: + + *length = 1; + return("U"); + + case NX_LWM2M_CLIENT_BINDING_UQ: + + *length = 2; + return("UQ"); + + case NX_LWM2M_CLIENT_BINDING_S: + + *length = 1; + return("S"); + + case NX_LWM2M_CLIENT_BINDING_SQ: + + *length = 2; + return("SQ"); + + case NX_LWM2M_CLIENT_BINDING_US: + + *length = 2; + return("US"); + + case NX_LWM2M_CLIENT_BINDING_UQS: + + *length = 3; + return("UQS"); + + case NX_LWM2M_CLIENT_BINDING_USQ: + + *length = 3; + return("USQ"); + + case NX_LWM2M_CLIENT_BINDING_UQSQ: + + *length = 4; + return("UQSQ"); + + default: + + /* Invalid mode */ + *length = 1; + return("X"); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_binding_mode_string_parse PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a string representing a binding mode. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr The binding mode string */ +/* string_length The length of the string */ +/* */ +/* OUTPUT */ +/* */ +/* The binding mode */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_write */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UCHAR _nx_lwm2m_client_binding_mode_string_parse(const CHAR *string_ptr, UINT string_length) +{ +const CHAR *string_ptr_max; +UCHAR binding; +CHAR c; + + if (string_length == 0) + { + return(0); + } + + string_ptr_max = string_ptr + string_length; + c = *string_ptr++; + if (c == 'U') + { + if (string_ptr == string_ptr_max) + { + return(NX_LWM2M_CLIENT_BINDING_U); + } + c = *string_ptr++; + if (c == 'Q') + { + if (string_ptr == string_ptr_max) + { + return(NX_LWM2M_CLIENT_BINDING_UQ); + } + binding = NX_LWM2M_CLIENT_BINDING_UQ; + c = *string_ptr++; + } + else + { + binding = NX_LWM2M_CLIENT_BINDING_U; + } + } + else + { + binding = 0; + } + if (c != 'S') + { + return(0); + } + if (string_ptr == string_ptr_max) + { + return(binding | NX_LWM2M_CLIENT_BINDING_S); + } + c = *string_ptr++; + if (c != 'Q' || string_ptr != string_ptr_max) + { + return(0); + } + return(binding | NX_LWM2M_CLIENT_BINDING_SQ); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_coap_header_parse PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses the header of a CoAP message. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to source buffer */ +/* ptr_max Pointer to the end of buffer */ +/* type_ptr On return, the type of message*/ +/* code_ptr On return, the code value */ +/* id_ptr On return, the message ID */ +/* token_ptr_ptr On return, the pointer to the */ +/* token */ +/* token_length_ptr On return, the token length */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the CoAP header, NULL if the header is invalid*/ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* token and processing */ +/* confirmable response, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +const VOID *_nx_lwm2m_client_coap_header_parse(const VOID *ptr, const VOID *ptr_max, UCHAR *type_ptr, UCHAR *code_ptr, USHORT *id_ptr, const VOID **token_ptr_ptr, UINT *token_length_ptr) +{ +const UCHAR *byte_ptr; +UCHAR type; +UCHAR code; +USHORT id; +const VOID *token_ptr; +UINT token_length; + + /* Pointer to header */ + byte_ptr = (const UCHAR *) ptr; + + /* Check for minimum length */ + if ((const UCHAR *) ptr_max - byte_ptr < NX_LWM2M_CLIENT_COAP_HEADER_LEN) + { + return(NX_NULL); + } + + /* Get first byte */ + type = *byte_ptr++; + + /* Check CoAP version */ + if ((type & NX_LWM2M_CLIENT_COAP_VERSION_MASK) != NX_LWM2M_CLIENT_COAP_VERSION_1) + { + return(NX_NULL); + } + + /* Get token length */ + token_length = type & NX_LWM2M_CLIENT_COAP_TOKEN_LEN_MASK; + if (token_length > NX_LWM2M_CLIENT_COAP_TOKEN_MAXLEN) + { + return(NX_NULL); + } + + /* Get message type */ + type &= NX_LWM2M_CLIENT_COAP_TYPE_MASK; + + /* Get code byte */ + code = *byte_ptr++; + + /* Check for valid code class if not an empty message */ + if (code != 0) + { + UCHAR code_class = code & NX_LWM2M_CLIENT_COAP_CLASS_MASK; + if (code_class != NX_LWM2M_CLIENT_COAP_CLASS_REQUEST && + code_class != NX_LWM2M_CLIENT_COAP_CLASS_SUCCESS && + code_class != NX_LWM2M_CLIENT_COAP_CLASS_CLIENT_ERROR && + code_class != NX_LWM2M_CLIENT_COAP_CLASS_SERVER_ERROR) + { + return(NX_NULL); + } + } + else + { + + /* Ignore empty message */ + return(NX_NULL); + } + + /* Get message ID */ + id = *byte_ptr++; + id = (USHORT)(id << 8); + id |= (USHORT)(*byte_ptr++); + + /* Check token length */ + token_ptr = byte_ptr; + byte_ptr += token_length; + if (byte_ptr > (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + + /* Return header information */ + *type_ptr = type; + *code_ptr = code; + *id_ptr = id; + *token_ptr_ptr = token_ptr; + *token_length_ptr = token_length; + return(byte_ptr); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_coap_option_parse PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parse a CoAP option header. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to source buffer */ +/* ptr_max Pointer to the end of buffer */ +/* option_ptr On return, the option number */ +/* value_ptr_ptr On return, pointer to the */ +/* option value */ +/* value_length_ptr On return, length of the value*/ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the next option, NULL if the option is invalid */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +const VOID *_nx_lwm2m_client_coap_option_parse(const VOID *ptr, const VOID *ptr_max, UINT *option_ptr, const VOID **value_ptr_ptr, UINT *value_length_ptr) +{ +const UCHAR *byte_ptr; +UCHAR option; +UINT delta; +UINT length; +const VOID *value_ptr; + + if (ptr == ptr_max) + { + + /* End of message */ + *option_ptr = NX_LWM2M_CLIENT_COAP_OPTION_NONE; + return(ptr); + } + + /* Read first byte */ + byte_ptr = (const UCHAR *) ptr; + option = *byte_ptr++; + + if (option == NX_LWM2M_CLIENT_COAP_PAYLOAD_MARKER) + { + + /* Begining of payload */ + *option_ptr = NX_LWM2M_CLIENT_COAP_OPTION_NONE; + return(byte_ptr); + } + + /* Get option delta */ + delta = option >> 4; + if (delta == 15) + { + + /* Invalid delta */ + return(NX_NULL); + } + if (delta == 13) + { + + /* 1-byte delta */ + if (byte_ptr == (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + delta = *byte_ptr++ + 13u; + } + else if (delta == 14) + { + + /* 2-byte delta */ + if (byte_ptr + 2 > (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + delta = *byte_ptr++; + delta <<= 8; + delta |= *byte_ptr++; + delta += 269; + } + + /* Get final option number */ + delta += *option_ptr; + if (delta == NX_LWM2M_CLIENT_COAP_OPTION_NONE) + { + + /* Invalid option */ + return(NX_NULL); + } + + /* Get length */ + length = option & 0x0f; + if (length == 15) + { + + /* Invalid length */ + return(NX_NULL); + } + if (length == 13) + { + + /* 1-byte length */ + if (byte_ptr == (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + length = *byte_ptr++ + 13u; + } + else if (length == 14) + { + + /* 2-byte length */ + if (byte_ptr + 2 > (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + length = *byte_ptr++; + length <<= 8; + length |= *byte_ptr++; + length += 269; + } + + /* Pointer to option value */ + value_ptr = byte_ptr; + + /* Advance pointer to next option */ + byte_ptr += length; + if (byte_ptr > (const UCHAR *) ptr_max) + { + return(NX_NULL); + } + + /* Return option information */ + *option_ptr = delta; + *value_ptr_ptr = value_ptr; + *value_length_ptr = length; + return(byte_ptr); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_coap_option_header_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions writes a CoAP option header. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* last_option Pointer to the value of the */ +/* last option, updated on return*/ +/* option The option to write */ +/* length The length of the option value*/ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the option header (start of value) */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_request */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID *_nx_lwm2m_client_coap_option_header_add(VOID *ptr, VOID *ptr_max, UINT *last_option, UINT option, UINT length) +{ +UCHAR *byte_ptr; +UCHAR code; +UINT delta; + + if (ptr >= ptr_max) + { + return(NX_NULL); + } + + /* Option delta */ + delta = option - *last_option; + if (delta >= 269) + { + code = 14 << 4; /* 2-byte option delta */ + } + else if (delta >= 13) + { + code = 13 << 4; /* 1-byte option delta */ + } + else + { + code = (UCHAR) (delta << 4); + } + + /* Option length */ + if (length >= 269) + { + code |= 14; /* 2-byte option length */ + } + else if (length >= 13) + { + code |= 13; /* 1-byte option delta */ + } + else { + code |= (UCHAR) length; + } + + /* Write option header */ + byte_ptr = (UCHAR *) ptr; + *byte_ptr++ = code; + + /* Write Extended option delta */ + if (delta >= 269) + { + if ((byte_ptr + 2) > (UCHAR *)ptr_max) + { + return(NX_NULL); + } + delta -= 269; + *byte_ptr++ = (UCHAR) (delta >> 8); + *byte_ptr++ = (UCHAR) delta; + } + else if (delta >= 13) + { + if ((byte_ptr + 1) > (UCHAR *)ptr_max) + { + return(NX_NULL); + } + delta -= 13; + *byte_ptr++ = (UCHAR) delta; + } + + /* Write extended option length */ + if (length >= 269) + { + if ((byte_ptr + 2) > (UCHAR *)ptr_max) + { + return(NX_NULL); + } + length -= 269; + *byte_ptr++ = (UCHAR) (length >> 8); + *byte_ptr++ = (UCHAR) length; + } + else if (length >= 13) + { + if ((byte_ptr + 1) > (UCHAR *)ptr_max) + { + return(NX_NULL); + } + length -= 13; + *byte_ptr++ = (UCHAR) length; + } + + /* Return updated last option value and pointer */ + *last_option = option; + return(byte_ptr); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_coap_option_uint_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions writes a CoAP option with an integer value. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* last_option Pointer to the value of the */ +/* last option, updated on return*/ +/* option The option to write */ +/* value The option value */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the option */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_coap_option_header_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID *_nx_lwm2m_client_coap_option_uint_add(VOID *ptr, VOID *ptr_max, UINT *last_option_ptr, UINT option, ULONG value) +{ +UCHAR *byte_ptr; +ULONG tmp; +UINT option_length; + + /* Byte pointer to destination buffer */ + byte_ptr = ptr; + + /* Compute length of value */ + option_length = 0; + tmp = value; + while (tmp != 0) + { + option_length++; + tmp >>= 8; + } + + /* Write option header */ + byte_ptr = _nx_lwm2m_client_coap_option_header_add(byte_ptr, ptr_max, last_option_ptr, option, option_length); + if ((byte_ptr == NX_NULL) || ((byte_ptr + option_length) > (UCHAR *)ptr_max)) + { + return(NX_NULL); + } + + /* Write value */ + if (option_length > 3) + { + *byte_ptr++ = (UCHAR) (value >> 24); + } + if (option_length > 2) + { + *byte_ptr++ = (UCHAR) (value >> 16); + } + if (option_length > 1) + { + *byte_ptr++ = (UCHAR) (value >> 8); + } + if (option_length > 0) + { + *byte_ptr++ = (UCHAR) value; + } + + return(byte_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_write_attribute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a single attribute. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to source buffer */ +/* ptr_max Pointer to the end of buffer */ +/* name The name of attribute */ +/* name_length The length of attribute's name*/ +/* is_int32 If it is 32 bit integer */ +/* value_ptr The pointer of value */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the next attribute, NULL if the attribute is invalid */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_strconv_format_int32 */ +/* _nx_lwm2m_client_strconv_format_notify_number */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_corelink_attributes_add */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static CHAR *_nx_lwm2m_client_write_attribute(CHAR *ptr, CHAR *ptr_max, const CHAR *name, UINT name_length, NX_LWM2M_BOOL is_int32, const VOID *value_ptr) +{ +UINT len; + + /* Write attribute name */ + if (ptr_max - ptr < (int) (name_length + 2)) + { + return(NX_NULL); + } + *ptr++ = ';'; + memcpy(ptr, name, name_length); /* Use case of memcpy is verified. */ + ptr += name_length; + *ptr++ = '='; + + /* Write value */ + if (is_int32) + { + len = _nx_lwm2m_client_strconv_format_int32(ptr, (UINT)(ptr_max - ptr), *((const NX_LWM2M_INT32 *) value_ptr)); + } + else + { + len = _nx_lwm2m_client_strconv_format_notify_number(ptr, (UINT)(ptr_max - ptr), *((const NX_LWM2M_CLIENT_NOTIFY_NUMBER *) value_ptr)); + } + if (len == 0) + { + return(NX_NULL); + } + ptr += len; + + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_corelink_attributes_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes the attributes of an object, instance or */ +/* resource using the CoRE Link Format */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* ptr_max Pointer to the end of buffer */ +/* server_id The optional server ID */ +/* resource_ptr Optional resource information */ +/* attr_flags The notify flags indicating */ +/* which attributes are set */ +/* attr_pmin The pmin attribute */ +/* attr_pmax The pmax attribute */ +/* attr_gt The gt attribute */ +/* attr_lt The lt attribute */ +/* attr_stp The stp attribute */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the written attributes, NULL if the */ +/* destination buffer is too small */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_write_attribute */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +CHAR *_nx_lwm2m_client_corelink_attributes_add(CHAR *ptr, CHAR *ptr_max, NX_LWM2M_ID server_id, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UINT attr_flags, NX_LWM2M_INT32 attr_pmin, NX_LWM2M_INT32 attr_pmax, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_gt, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_lt, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_stp) +{ +NX_LWM2M_INT32 value_as_int32; + + /* Write short server ID */ + if (server_id != 0) + { + + value_as_int32 = server_id; + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "ssid", 4, NX_TRUE, &value_as_int32); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + + /* Write dimension of multiple resource */ + if ((resource_ptr != NX_NULL) && (resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_MULTIPLE)) + { + value_as_int32 = resource_ptr -> resource_dim; + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "dim", 3, NX_TRUE, &value_as_int32); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + + /* Write notification attributes */ + if (attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN) + { + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "pmin", 4, NX_TRUE, &attr_pmin); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + if (attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX) + { + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "pmax", 4, NX_TRUE, &attr_pmax); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + if (attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_GT) + { + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "gt", 2, NX_FALSE, &attr_gt); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + if (attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_LT) + { + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "lt", 2, NX_FALSE, &attr_lt); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + if (attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_STP) + { + ptr = _nx_lwm2m_client_write_attribute(ptr, ptr_max, "st", 2, NX_FALSE, &attr_stp); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_corelink_path_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes the path of an object, instance or */ +/* resource using the CoRE Link Format. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* ptr_max Pointer to the end of buffer */ +/* object_id The ID of the object */ +/* instance_id The optional instance ID */ +/* resource_id The optional resource ID */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the written path, NULL if the */ +/* destination buffer is too small */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_strconv_format_id */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_request */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +CHAR *_nx_lwm2m_client_corelink_path_add(CHAR *ptr, CHAR *ptr_max, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id) +{ +UINT len; + + if (ptr_max - ptr < 2) + { + return(NX_NULL); + } + *ptr++ = '<'; + *ptr++ = '/'; + + len = _nx_lwm2m_client_strconv_format_id(ptr, (UINT)(ptr_max - ptr), object_id); + if (len == 0) + { + return(NX_NULL); + } + ptr += len; + + if (instance_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + if (ptr >= ptr_max) + { + return(NX_NULL); + } + *ptr++ = '/'; + + len = _nx_lwm2m_client_strconv_format_id(ptr, (UINT)(ptr_max - ptr), instance_id); + if (len == 0) + { + return(NX_NULL); + } + ptr += len; + + if (resource_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + if (ptr >= ptr_max) + { + return(NX_NULL); + } + *ptr++ = '/'; + + len = _nx_lwm2m_client_strconv_format_id(ptr, (UINT)(ptr_max - ptr), resource_id); + if (len == 0) + { + return(NX_NULL); + } + ptr += len; + } + } + + if (ptr >= ptr_max) + { + return(NX_NULL); + } + *ptr++ = '>'; + + return(ptr); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* coap_message_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes CoAP socket receive notification. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to the CoAP socket */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set */ +/* */ +/* CALLED BY */ +/* */ +/* UDP stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID coap_message_notify(NX_UDP_SOCKET *socket_ptr) +{ + + /* Get pointer to LWM2M Client */ + NX_LWM2M_CLIENT *client_ptr = ((NX_LWM2M_CLIENT_SOCKET *) socket_ptr) -> client_ptr; + + /* Set CoAP Message event flag */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_COAP_MESSAGE, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* ip_ptr Pointer to IP instance */ +/* packet_pool_ptr Pointer to packet pool */ +/* name_ptr Name of LWM2M client */ +/* name_length Length of endpoint name */ +/* msisdn_ptr Optional MSISDN number */ +/* msisdn_length Length of MSISDN number */ +/* binding_mode Supported binding and modes */ +/* stack_ptr Client thread's stack pointer */ +/* stack_size Client thread's stack size */ +/* priority Priority of client thread */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_create */ +/* tx_mutex_delete */ +/* tx_event_flags_create */ +/* tx_event_flags_delete */ +/* nx_udp_socket_create */ +/* nx_udp_socket_delete */ +/* nx_udp_socket_bind */ +/* nx_udp_socket_ubind */ +/* nx_udp_socket_receive_notify */ +/* _nx_lwm2m_client_security_object_create */ +/* _nx_lwm2m_client_server_object_create */ +/* _nx_lwm2m_client_access_control_object_create */ +/* _nx_lwm2m_client_device_object_create */ +/* memset */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_create(NX_LWM2M_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool_ptr, + const CHAR *name_ptr, UINT name_length, const CHAR *msisdn_ptr, UINT msisdn_length, + UCHAR binding_modes, VOID *stack_ptr, ULONG stack_size, UINT priority) +{ +UINT status; +int i; + + /* Initialize the client control block to zero. */ + memset(client_ptr, 0, sizeof(NX_LWM2M_CLIENT)); + + /* Create the mutex */ + status = tx_mutex_create(&client_ptr -> nx_lwm2m_client_mutex, "LWM2M Client Mutex", TX_INHERIT); + if (status != TX_SUCCESS) + { + + /* Failed to create the mutex, return Failure */ + return(NX_LWM2M_CLIENT_ERROR); + } + + /* Create the event flags */ + status = tx_event_flags_create(&client_ptr -> nx_lwm2m_client_event_flags, "LWM2M Client Flags"); + if (status != TX_SUCCESS) + { + + /* Failed to create the event flags, delete all resources */ + tx_mutex_delete(&client_ptr -> nx_lwm2m_client_mutex); + + /* return Failure */ + return(NX_LWM2M_CLIENT_ERROR); + } + + /* Create the CoAP socket */ + status = nx_udp_socket_create(ip_ptr, (NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket, "LWM2M Client CoAP Socket", NX_LWM2M_CLIENT_SOCKET_TOS, NX_DONT_FRAGMENT, NX_LWM2M_CLIENT_SOCKET_TTL, NX_LWM2M_CLIENT_SOCKET_QUEUE_MAX); + if (status != NX_SUCCESS) + { + + /* Failed to create the socket, delete all resources */ + tx_event_flags_delete(&client_ptr -> nx_lwm2m_client_event_flags); + tx_mutex_delete(&client_ptr -> nx_lwm2m_client_mutex); + + /* return Failure */ + return(NX_LWM2M_CLIENT_ERROR); + } + + /* Bind the CoAP port */ + status = nx_udp_socket_bind((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket, NX_ANY_PORT, NX_NO_WAIT); + if (status != NX_SUCCESS) + { + + /* Failed to bind the socket, delete all resources */ + nx_udp_socket_delete((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket); + tx_event_flags_delete(&client_ptr -> nx_lwm2m_client_event_flags); + tx_mutex_delete(&client_ptr -> nx_lwm2m_client_mutex); + + /* return port unavailable error */ + return(NX_LWM2M_CLIENT_PORT_UNAVAILABLE); + } + + /* Set the CoAP receive notify callback */ + client_ptr -> nx_lwm2m_client_coap_socket.client_ptr = client_ptr; + nx_udp_socket_receive_notify((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket, coap_message_notify); + + /* Store the endpoint name */ + client_ptr -> nx_lwm2m_client_name = name_ptr; + client_ptr -> nx_lwm2m_client_name_length = name_length; + + /* Store the MSISDN */ + if (msisdn_length) + { + client_ptr -> nx_lwm2m_client_msisdn = msisdn_ptr; + client_ptr -> nx_lwm2m_client_msisdn_length = msisdn_length; + } + + /* Store the IP instance */ + client_ptr -> nx_lwm2m_client_ip_ptr = ip_ptr; + + /* Store the IP Packet Pool */ + client_ptr -> nx_lwm2m_client_pool_ptr = packet_pool_ptr; + + /* Initialize the Security Object (0) */ +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + _nx_lwm2m_client_security_object_create(client_ptr); +#endif + + /* Initialize the Server Object (1) */ + _nx_lwm2m_client_server_object_create(client_ptr); + + /* Initialize the Access Control Object (2) */ +#if NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES + _nx_lwm2m_client_access_control_object_create(client_ptr); +#endif + + /* Initialize the Device Object (3) */ + _nx_lwm2m_client_device_object_create(client_ptr, binding_modes); + + /* Initialize the linked list of free notifications */ + client_ptr -> nx_lwm2m_client_notifications_free_list = &client_ptr -> nx_lwm2m_client_notifications[0]; + for (i = 0; i < NX_LWM2M_CLIENT_MAX_NOTIFICATIONS-1; i++) + { + client_ptr -> nx_lwm2m_client_notifications[i].notify_next = &client_ptr -> nx_lwm2m_client_notifications[i + 1]; + } + client_ptr -> nx_lwm2m_client_notifications[NX_LWM2M_CLIENT_MAX_NOTIFICATIONS-1].notify_next = NX_NULL; + + /* Initialize empty list of sessions */ + client_ptr -> nx_lwm2m_client_sessions = NX_NULL; + + /* Reset request ID generator */ + /* XXX should be random */ + client_ptr -> nx_lwm2m_client_request_id = 0; + + /* Create the LWM2M Client thread */ + status = tx_thread_create(&client_ptr -> nx_lwm2m_client_thread, "LWM2M Client Thread", _nx_lwm2m_client_thread_entry, + (ULONG) client_ptr, stack_ptr, stack_size, + priority, priority, TX_NO_TIME_SLICE, TX_AUTO_START); + if (status != TX_SUCCESS) + { + + /* Failed to create the thread, delete all resources */ + nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_lwm2m_client_coap_socket); + nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_lwm2m_client_coap_socket); + tx_event_flags_delete(&client_ptr -> nx_lwm2m_client_event_flags); + tx_mutex_delete(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return Failure */ + return(NX_LWM2M_CLIENT_ERROR); + } + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set */ +/* tx_event_flags_get */ +/* tx_thread_terminate */ +/* tx_thread_delete */ +/* nx_udp_socket_unbind */ +/* nx_udp_socket_delete */ +/* tx_event_flags_delete */ +/* tx_mutex_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_delete(NX_LWM2M_CLIENT *client_ptr) +{ +ULONG flags; + + /* Need to terminate the client thread before deleting the LWM2M CLient: */ + + /* Set event to tell the client thread to terminate */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_TERM_REQ, TX_OR); + + /* Wait for client thread termination done event */ + tx_event_flags_get(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_TERM_DONE, TX_OR, &flags, TX_WAIT_FOREVER); + + /* Terminate the thread */ + tx_thread_terminate(&client_ptr -> nx_lwm2m_client_thread); + + /* Delete the thread */ + tx_thread_delete(&client_ptr -> nx_lwm2m_client_thread); + + /* Delete all sessions */ + while (client_ptr -> nx_lwm2m_client_sessions != NX_NULL) + { + _nx_lwm2m_client_session_delete(client_ptr -> nx_lwm2m_client_sessions); + } + + /* Unbind and Delete the CoAP socket */ + nx_udp_socket_unbind((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket); + nx_udp_socket_delete((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket); + + /* Delete the event flags */ + tx_event_flags_delete(&client_ptr -> nx_lwm2m_client_event_flags); + + /* Delete the mutex */ + tx_mutex_delete(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_callback_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function installs the application callbacks for implementing */ +/* operations on the LWM2M Device Object resources not handled by the */ +/* LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* operation_callback The operation callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_device_callback_set(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK operation_callback) +{ + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Set callbacks pointers */ + client_ptr -> nx_lwm2m_client_device.device_object_user_operation = operation_callback; + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_error_push PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a new instance to the error code resource of */ +/* the Device Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* code The new error code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_device_object_error_push */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_device_error_push(NX_LWM2M_CLIENT *client_ptr, UCHAR code) +{ +UINT status; + + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + status = _nx_lwm2m_client_device_object_error_push(&client_ptr -> nx_lwm2m_client_device, code); + + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_error_reset PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes all error code resource instances from the */ +/* Device Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_device_object_error_reset */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_device_error_reset(NX_LWM2M_CLIENT *client_ptr) +{ + + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + _nx_lwm2m_client_device_object_error_reset(&client_ptr -> nx_lwm2m_client_device); + + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the read operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* nx_lwm2m_device_object_user_operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_device_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count) +{ +NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr = (NX_LWM2M_CLIENT_DEVICE_OBJECT *) object_ptr; +NX_LWM2M_CLIENT_RESOURCE *resource_instances = object_ptr -> object_client_ptr -> nx_lwm2m_client_mulitple_temp_resources; +UINT status; +UINT length; +UINT i, j; +UINT num_user_resources; + + NX_PARAMETER_NOT_USED(instance_ptr); + + for (i = 0; i < *resource_count; i++) + { + switch (resource[i].resource_id) + { + + /* Non-readable resources */ + case NX_LWM2M_CLIENT_DEVICE_RESET_ERROR_CODE_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Get Error Code */ + case NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID: + + for (j = 0; j < device_ptr -> device_object_error_count; j++) + { + + _nx_lwm2m_client_resource_info_set(&resource_instances[j], (NX_LWM2M_ID)j, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resource_instances[j], device_ptr -> device_object_error[j]); + } + + _nx_lwm2m_client_resource_instances_set(&resource[i], resource_instances, device_ptr -> device_object_error_count); + break; + + /* Get Supported Binding and Modes */ + case NX_LWM2M_CLIENT_DEVICE_BINDING_MODES_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = _nx_lwm2m_client_binding_mode_string_get(device_ptr -> device_object_binding_modes, &length); + resource[i].resource_value.resource_bufferdata.resource_buffer_length = length; + break; + + /* Resources implemented by the application */ + default: + + if (device_ptr -> device_object_user_operation == NX_NULL) + { + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + num_user_resources = 1; + status = device_ptr -> device_object_user_operation(NX_LWM2M_CLIENT_OBJECT_READ, object_ptr -> object_client_ptr, &resource[i], &num_user_resources, NX_NULL, 0); + if (status != NX_SUCCESS) + { + return(status); + } + break; + } + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the discover operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* num_resources_ptr Pointer to number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* nx_lwm2m_device_object_user_operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_device_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *resource_count) +{ +NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr = (NX_LWM2M_CLIENT_DEVICE_OBJECT *) object_ptr; +UINT num_user_resources; +UINT ret; + + NX_PARAMETER_NOT_USED(instance_ptr); + + /* Return the resources implemented by the LWM2M Client */ + if (*resource_count < 3) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + resources[0].resource_id = NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID; + resources[0].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + resources[0].resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + resources[0].resource_dim = (UCHAR)device_ptr -> device_object_error_count; + resources[1].resource_id = NX_LWM2M_CLIENT_DEVICE_RESET_ERROR_CODE_ID; + resources[1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; + resources[2].resource_id = NX_LWM2M_CLIENT_DEVICE_BINDING_MODES_ID; + resources[2].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + + if (device_ptr -> device_object_user_operation == NX_NULL) + { + + /* No resource implemented by the application */ + num_user_resources = 0; + } + else + { + + /* Add the resources implemented by the application */ + num_user_resources = *resource_count - 3; + ret = device_ptr -> device_object_user_operation(NX_LWM2M_CLIENT_OBJECT_DISCOVER, object_ptr -> object_client_ptr, &resources[3], &num_user_resources, NX_NULL, 0); + if (ret != NX_SUCCESS) + { + return(ret); + } + } + + /* Return total number of resources */ + *resource_count = 3 + num_user_resources; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the write operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* write_op Type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* nx_lwm2m_device_object_user_operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_device_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr = (NX_LWM2M_CLIENT_DEVICE_OBJECT *) object_ptr; +UINT i; +UINT write_op; + + /* Check the length of argument */ + if (args_length < sizeof(UINT)) + return(NX_LWM2M_CLIENT_BAD_REQUEST); + + /* Get the type of write operation */ + write_op = *(UINT *)args_ptr; + + NX_PARAMETER_NOT_USED(instance_ptr); + + /* XXX replace not supported? */ + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Check if resources are valid */ + for (i = 0; i < *resource_count; i++) + { + switch (resource[i].resource_id) + { + + /* Non-writable resources */ + case NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID: + case NX_LWM2M_CLIENT_DEVICE_RESET_ERROR_CODE_ID: + case NX_LWM2M_CLIENT_DEVICE_BINDING_MODES_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Other resources are implemented by the application */ + default: + + break; + } + } + + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) + { + + /* Ignore unknown resources during bootstrap */ + return(NX_SUCCESS); + } + + /* No application resource defined */ + if (device_ptr -> device_object_user_operation == NX_NULL) + { + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + + /* Resources implemented by the application */ + return(device_ptr -> device_object_user_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr -> object_client_ptr, resource, resource_count, args_ptr, args_length)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the execute operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id The ID of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_device_object_error_reset */ +/* nx_lwm2m_device_object_user_operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_device_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, CHAR *args_ptr, UINT args_length) +{ +NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr = (NX_LWM2M_CLIENT_DEVICE_OBJECT *) object_ptr; + + NX_PARAMETER_NOT_USED(instance_ptr); + + switch (resource -> resource_id) + { + + /* Non-executable resources */ + case NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID: + case NX_LWM2M_CLIENT_DEVICE_BINDING_MODES_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Reset error code */ + case NX_LWM2M_CLIENT_DEVICE_RESET_ERROR_CODE_ID: + + _nx_lwm2m_client_device_object_error_reset(device_ptr); + + return(NX_SUCCESS); + + /* Resources implemented by the application */ + default: + + if (device_ptr -> device_object_user_operation == NX_NULL) + { + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + return(device_ptr -> device_object_user_operation(NX_LWM2M_CLIENT_OBJECT_EXECUTE, object_ptr -> object_client_ptr, resource, NX_NULL, args_ptr, args_length)); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_operation PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the object operation. */ +/* */ +/* INPUT */ +/* */ +/* operation The operation type */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_device_read */ +/* _nx_lwm2m_client_device_discover */ +/* _nx_lwm2m_client_device_write */ +/* _nx_lwm2m_client_device_execute */ +/* _nx_lwm2m_client_device_write */ +/* _nx_lwm2m_client_device_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_device_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return(_nx_lwm2m_client_device_read(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return(_nx_lwm2m_client_device_discover(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Call write function */ + return(_nx_lwm2m_client_device_write(object_ptr, object_instance_ptr, resource, resource_count, args_ptr, args_length)); + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return(_nx_lwm2m_client_device_execute(object_ptr, object_instance_ptr, resource, args_ptr, args_length)); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions initializes the Device Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* binding_modes The supported binding modes */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_device_object_create(NX_LWM2M_CLIENT *client_ptr, UCHAR binding_modes) +{ +NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr = &(client_ptr -> nx_lwm2m_client_device); +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = &device_ptr -> device_object_instance; + + /* Add Device Object to the LWM2M Client */ + _nx_lwm2m_client_object_add(client_ptr, &(device_ptr -> device_object), NX_LWM2M_CLIENT_DEVICE_OBJECT_ID, _nx_lwm2m_client_device_operation); + + /* Initialize Object data */ + device_ptr -> device_object.object_instances = instance_ptr; + device_ptr -> device_object_user_operation = NX_NULL; + device_ptr -> device_object_error_count = 1; + device_ptr -> device_object_error[0] = 0; + device_ptr -> device_object_binding_modes = binding_modes; + + /* Initialize the single Instance */ + instance_ptr -> object_instance_next = NX_NULL; + instance_ptr -> object_instance_id = 0; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_object_error_push PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions pushes a new value to the array of device errors. */ +/* */ +/* INPUT */ +/* */ +/* device_ptr Pointer to device object */ +/* code The error code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_error_push */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_device_object_error_push(NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr, UCHAR code) +{ +NX_LWM2M_CLIENT_RESOURCE value; + + if (device_ptr -> device_object_error_count == 1 && device_ptr -> device_object_error[0] == 0) + { + + /* Replace the "no error" code */ + device_ptr -> device_object_error[0] = code; + } + else if (device_ptr -> device_object_error_count < NX_LWM2M_CLIENT_MAX_DEVICE_ERRORS) + { + + /* Push new error code */ + device_ptr -> device_object_error[device_ptr -> device_object_error_count] = code; + device_ptr -> device_object_error_count++; + } + else + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* Handle notifications */ + value.resource_id = NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID; + value.resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) device_ptr, &device_ptr -> device_object_instance, &value); + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_object_error_reset PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets the array of device errors. */ +/* */ +/* INPUT */ +/* */ +/* device_ptr Pointer to device object */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_device_execute */ +/* _nx_lwm2m_client_device_error_reset */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_device_object_error_reset(NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr) +{ + if (device_ptr -> device_object_error_count != 1 || device_ptr -> device_object_error[0] != 0) + { + NX_LWM2M_CLIENT_RESOURCE value; + + /* Reset to no error code */ + device_ptr -> device_object_error_count = 1; + device_ptr -> device_object_error[0] = 0; + + /* Handle notifications */ + value.resource_id = NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID; + value.resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) device_ptr, &device_ptr -> device_object_instance, &value); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_device_resource_changed PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function signals the LWM2M Client that a resource of the */ +/* Device Object has changed. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* resource_ptr The resource ID and value */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_device_resource_changed(NX_LWM2M_CLIENT *client_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ + return(_nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) &client_ptr -> nx_lwm2m_client_device, &client_ptr -> nx_lwm2m_client_device.device_object_instance, resource_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the read operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_firmware_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_firmware_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr = (NX_LWM2M_CLIENT_FIRMWARE *) object_ptr; +NX_LWM2M_CLIENT_RESOURCE *resource_instances = object_ptr -> object_client_ptr -> nx_lwm2m_client_mulitple_temp_resources; +UINT i, j; + + NX_PARAMETER_NOT_USED(instance_ptr); + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_FIRMWARE_STATE_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = firmware_ptr -> firmware_state; + break; + + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_SUPPORTED_OBJECTS_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_BOOLEAN; + resource[i].resource_value.resource_booleandata = firmware_ptr -> firmware_update_supported_objects; + break; + + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_RESULT_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = firmware_ptr -> firmware_result; + break; + + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_NAME_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = firmware_ptr -> firmware_package_name; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = firmware_ptr -> firmware_package_name_length; + break; + + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_VERSION_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = firmware_ptr -> firmware_package_version; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = firmware_ptr -> firmware_package_version_length; + break; + + case NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_SUPPORT_ID: + + for (j = 0; j < firmware_ptr -> firmware_protocols_count; j++) + { + + _nx_lwm2m_client_resource_info_set(&resource_instances[j], (NX_LWM2M_ID)j, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resource_instances[j], firmware_ptr -> firmware_protocols[j]); + } + + _nx_lwm2m_client_resource_instances_set(&resource[i], resource_instances, firmware_ptr -> firmware_protocols_count); + break; + + case NX_LWM2M_CLIENT_FIRMWARE_DELIVERY_METHOD_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + + /* Return which kinds of firmware transfert are supported */ + if ((firmware_ptr -> firmware_package_callback != NX_NULL) && + (firmware_ptr -> firmware_package_uri_callback != NX_NULL)) + { + + /* Both are supported */ + resource[i].resource_value.resource_integer32data = 2; + } + else if (firmware_ptr -> firmware_package_callback != NX_NULL) + { + + /* Push only */ + resource[i].resource_value.resource_integer32data = 1; + } + else + { + + /* Pull only */ + resource[i].resource_value.resource_integer32data = 0; + } + break; + + /* Non-readable resources */ + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ID: + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_ID: + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the discover operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* num_resources_ptr Pointer to number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_firmware_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_firmware_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *num_resources_ptr) +{ +NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr = (NX_LWM2M_CLIENT_FIRMWARE *) object_ptr; +UINT resource_count; + + NX_PARAMETER_NOT_USED(instance_ptr); + + /* Get number of resources */ + if (firmware_ptr -> firmware_protocols_count != 0) + { + resource_count = 10; + } + else + { + resource_count = 9; + } + + /* Check length of output buffer */ + if (*num_resources_ptr < resource_count) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* Return list of resources */ + resources[0].resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ID; + resources[0].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; /* Write only */ + resources[1].resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_ID; + resources[1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; /* Write only */ + resources[2].resource_id = NX_LWM2M_CLIENT_FIRMWARE_UPDATE_ID; + resources[2].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; + resources[3].resource_id = NX_LWM2M_CLIENT_FIRMWARE_STATE_ID; + resources[3].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + resources[4].resource_id = NX_LWM2M_CLIENT_FIRMWARE_UPDATE_SUPPORTED_OBJECTS_ID; + resources[4].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[5].resource_id = NX_LWM2M_CLIENT_FIRMWARE_UPDATE_RESULT_ID; + resources[5].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + resources[6].resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_NAME_ID; + resources[6].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + resources[7].resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_VERSION_ID; + resources[7].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + if (firmware_ptr -> firmware_protocols_count != 0) + { + resources[8].resource_id = NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_SUPPORT_ID; + resources[8].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + resources[8].resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + resources[8].resource_dim = firmware_ptr -> firmware_protocols_count; + } + resources[resource_count-1].resource_id = NX_LWM2M_CLIENT_FIRMWARE_DELIVERY_METHOD_ID; + resources[resource_count-1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ; + + *num_resources_ptr = resource_count; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_write PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the write operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* write_op Type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_string_get */ +/* _nx_lwm2m_client_resource_boolean_get */ +/* nx_lwm2m_firmware_package_uri_callback */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_firmware_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* compiler warnings, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_firmware_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, UINT write_op) +{ +NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr = (NX_LWM2M_CLIENT_FIRMWARE *) object_ptr; +UINT status; +UINT flags; +const CHAR *uri_ptr = NX_NULL; +UINT uri_length; +NX_LWM2M_BOOL update_supported_objects, old_update_value = 0; +UINT i; + + NX_PARAMETER_NOT_USED(instance_ptr); + + /* Replace or create are not supported */ + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE || write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Check validity of values before updating instance */ + flags = 0; + + for (i = 0 ; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ID: + + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) + { + + /* XXX cannot download package during bootstrap? */ + return(NX_LWM2M_CLIENT_BAD_REQUEST); + } + + /* XXX TO DO */ + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_ID: + + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) + { + + /* XXX cannot download package during bootstrap? */ + return(NX_LWM2M_CLIENT_BAD_REQUEST); + } + if (firmware_ptr -> firmware_package_uri_callback == NX_NULL) + { + + /* Not supported */ + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Get URI string */ + status = _nx_lwm2m_client_resource_string_get(&resource[i], &uri_ptr, &uri_length); + if (status != NX_SUCCESS) + { + return(status); + } + flags |= 1< firmware_update_supported_objects; + firmware_ptr -> firmware_update_supported_objects = update_supported_objects; + } + if (flags & 1< firmware_package_uri_callback(firmware_ptr, uri_ptr, uri_length); + + if (status != NX_SUCCESS) + { + if (flags & 1< firmware_update_supported_objects = old_update_value; + } + + return(status); + } + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the execute operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id The ID of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* nx_lwm2m_firmware_update_callback */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_firmware_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_firmware_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ +NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr = (NX_LWM2M_CLIENT_FIRMWARE *) object_ptr; + + NX_PARAMETER_NOT_USED(instance_ptr); + + switch (resource_id) + { + + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_ID: + + return(firmware_ptr -> firmware_update_callback(firmware_ptr, firmware_ptr -> firmware_update_supported_objects, args_ptr, args_length)); + + /* Non-executable resources */ + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ID: + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_ID: + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_SUPPORTED_OBJECTS_ID: + case NX_LWM2M_CLIENT_FIRMWARE_STATE_ID: + case NX_LWM2M_CLIENT_FIRMWARE_UPDATE_RESULT_ID: + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_NAME_ID: + case NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_VERSION_ID: + case NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_SUPPORT_ID: + case NX_LWM2M_CLIENT_FIRMWARE_DELIVERY_METHOD_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_operation PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the object operation. */ +/* */ +/* INPUT */ +/* */ +/* operation The operation type */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_firmware_read */ +/* _nx_lwm2m_client_firmware_discover */ +/* _nx_lwm2m_client_firmware_write */ +/* _nx_lwm2m_client_firmware_execute */ +/* _nx_lwm2m_client_firmware_write */ +/* _nx_lwm2m_client_firmware_delete */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_firmware_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_firmware_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +UINT *write_op; + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return(_nx_lwm2m_client_firmware_read(object_ptr, object_instance_ptr, resource, *resource_count)); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return(_nx_lwm2m_client_firmware_discover(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Check the length of argument */ + if (args_length < sizeof(UINT)) + return(NX_LWM2M_CLIENT_BAD_REQUEST); + + /* Get the type of write operation */ + write_op = (UINT *)args_ptr; + + /* Call write function */ + return(_nx_lwm2m_client_firmware_write(object_ptr, object_instance_ptr, resource, *resource_count, *write_op)); + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return(_nx_lwm2m_client_firmware_execute(object_ptr, object_instance_ptr, resource -> resource_id, args_ptr, args_length)); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* client_ptr Pointer to LWM2M client */ +/* protocols The supported protocols */ +/* package_callback The package callback */ +/* package_uri_callback The package URI callback */ +/* update_callback The update callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_firmware_create(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_CLIENT *client_ptr, UINT protocols, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK package_callback, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK package_uri_callback, NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK update_callback) +{ +int i; +UINT status; + + /* Add Firmware Update Object to the LWM2M Client */ + status = _nx_lwm2m_client_object_add(client_ptr, &(firmware_ptr -> firmware_object), NX_LWM2M_CLIENT_FIRMWARE_OBJECT_ID, _nx_lwm2m_client_firmware_operation); + if (status) + { + return(status); + } + + /* Initialize Object data */ + firmware_ptr -> firmware_object.object_instances = &firmware_ptr -> firmware_instance; + firmware_ptr -> firmware_package_callback = package_callback; + firmware_ptr -> firmware_package_uri_callback = package_uri_callback; + firmware_ptr -> firmware_update_callback = update_callback; + firmware_ptr -> firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE; + firmware_ptr -> firmware_update_supported_objects = NX_FALSE; + firmware_ptr -> firmware_result = NX_LWM2M_CLIENT_FIRMWARE_RESULT_INIT; + firmware_ptr -> firmware_protocols_count = 0; + firmware_ptr -> firmware_package_name = ""; + firmware_ptr -> firmware_package_name_length = 0; + firmware_ptr -> firmware_package_version = ""; + firmware_ptr -> firmware_package_version_length = 0; + + /* Initialize the single Instance */ + firmware_ptr -> firmware_instance.object_instance_next = NX_NULL; + firmware_ptr -> firmware_instance.object_instance_id = 0; + + /* Set the list of supported protocols */ + protocols &= (1< firmware_protocols[firmware_ptr -> firmware_protocols_count] = (UCHAR)i; + firmware_ptr -> firmware_protocols_count++; + } + + /* Check next bit */ + protocols >>= 1; + i++; + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_package_info_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the package information resources of the */ +/* Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* name The name of firmware package */ +/* name_length The length of name */ +/* version The version of firmware */ +/* package */ +/* version_length The length of version */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_firmware_package_info_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *name, UINT name_length, const CHAR *version, UINT version_length) +{ +NX_LWM2M_CLIENT_RESOURCE resource; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Update the name and version of the firmware package */ + firmware_ptr -> firmware_package_name = name; + firmware_ptr -> firmware_package_name_length = name_length; + firmware_ptr -> firmware_package_version = version; + firmware_ptr -> firmware_package_version_length = version_length; + + /* Notify the server of resources changes */ + resource.resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_NAME_ID; + resource.resource_type = NX_LWM2M_CLIENT_RESOURCE_NONE; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr, &firmware_ptr -> firmware_instance, &resource); + resource.resource_id = NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_VERSION_ID; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr, &firmware_ptr -> firmware_instance, &resource); + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex); + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_result_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions sets the Update Result resource of the Firmware */ +/* Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* result The Update Result */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_firmware_result_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR result) +{ + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Set the new value of the update result */ + if (firmware_ptr -> firmware_result != result) + { + NX_LWM2M_CLIENT_RESOURCE resource; + + firmware_ptr -> firmware_result = result; + + resource.resource_id = NX_LWM2M_CLIENT_FIRMWARE_UPDATE_RESULT_ID; + resource.resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource.resource_value.resource_integer32data = result; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr, &firmware_ptr -> firmware_instance, &resource); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex); + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_firmware_state_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions sets the State of the Firmware Update Object. */ +/* */ +/* INPUT */ +/* */ +/* firmware_ptr Pointer to object data */ +/* state The state of the Firmware */ +/* Object */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_firmware_state_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR state) +{ + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Set the new value of the state */ + if (firmware_ptr -> firmware_state != state) + { + NX_LWM2M_CLIENT_RESOURCE resource; + + firmware_ptr -> firmware_state = state; + + resource.resource_id = NX_LWM2M_CLIENT_FIRMWARE_STATE_ID; + resource.resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource.resource_value.resource_integer32data = state; + _nx_lwm2m_client_object_resource_changed((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr, &firmware_ptr -> firmware_instance, &resource); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&((NX_LWM2M_CLIENT_OBJECT *) firmware_ptr) -> object_client_ptr -> nx_lwm2m_client_mutex); + + /* Return NX_SUCCESS */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_lock PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function locks the LWM2M Client to prevent concurent access. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_lock(NX_LWM2M_CLIENT *client_ptr) +{ + + /* Acquire the LWM2M Client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Always return a success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_notify_allocate PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a NX_LWM2M_CLIENT_NOTIFY structure. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the allocated structure */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_notify_get */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_CLIENT_NOTIFY * _nx_lwm2m_client_notify_allocate(NX_LWM2M_CLIENT *client_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* Dequeue notify structure from free list */ + notify_ptr = client_ptr -> nx_lwm2m_client_notifications_free_list; + if (notify_ptr != NX_NULL) + { + client_ptr -> nx_lwm2m_client_notifications_free_list = notify_ptr -> notify_next; + } + + return(notify_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_notify_free PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deallocates a NX_LWM2M_CLIENT_NOTIFY structure. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* notify_ptr Pointer to the structure to */ +/* be deallocated */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_cleanup */ +/* _nx_lwm2m_client_session_notify_free */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_notify_free(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr) +{ + + /* Enqueue the notify structure in free list */ + notify_ptr -> notify_next = client_ptr -> nx_lwm2m_client_notifications_free_list; + client_ptr -> nx_lwm2m_client_notifications_free_list = notify_ptr; +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a new Object to the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_ptr Pointer to the Object */ +/* object_id The Object ID */ +/* object_operation Object operation function */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* _nx_lwm2m_client_security_object_create */ +/* _nx_lwm2m_client_server_object_create */ +/* _nx_lwm2m_client_access_control_object_create */ +/* _nx_lwm2m_client_device_object_create */ +/* _nx_lwm2m_client_firmware_create */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_add(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID object_id, + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK object_operation) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *current_ptr; + + /* Reserved value is not allowed */ + if (object_id == NX_LWM2M_CLIENT_RESERVED_ID) + return(NX_LWM2M_CLIENT_FORBIDDEN); + + /* Set the ID of the new Object */ + object_ptr -> object_id = object_id; + + /* Set operation callback functions */ + object_ptr -> object_operation = object_operation; + + /* Initialize the instances */ + object_ptr -> object_instances = NX_NULL; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Check if this object is the head of object list. */ + if (client_ptr -> nx_lwm2m_client_object_list_head == NX_NULL) + { + object_ptr -> object_client_ptr = client_ptr; + object_ptr -> object_next = NX_NULL; + client_ptr -> nx_lwm2m_client_object_list_head = object_ptr; + status = NX_SUCCESS; + } + else + { + + /* Get pointer to first object */ + current_ptr = client_ptr -> nx_lwm2m_client_object_list_head; + + /* Parse the list of Objects to insert the new object in ID order */ + while (1) + { + if ((current_ptr -> object_next == NX_NULL) || + (current_ptr -> object_next -> object_id > object_id)) + { + + /* Insert new object in list */ + object_ptr -> object_next = current_ptr -> object_next; + current_ptr -> object_next = object_ptr; + + /* Set pointer to client */ + object_ptr -> object_client_ptr = client_ptr; + + /* Return Success */ + status = NX_SUCCESS; + + break; + } + else if (current_ptr -> object_next -> object_id == object_id) + { + + /* Duplicated Object ID */ + status = NX_LWM2M_CLIENT_ALREADY_EXIST; + + break; + } + + /* Get next object */ + current_ptr = current_ptr -> object_next; + } + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id_ptr Pointer to the Instance ID */ +/* num_values Number of values to set */ +/* values Pointer to the values */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_create_internal */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_create(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object implementation */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr == NX_NULL) + { + + /* Object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Create new instance */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, instance_id_ptr, num_values, values, NX_FALSE); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_create_internal PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates a new Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to the Object */ +/* instance_id_ptr Pointer to the Instance ID */ +/* num_values Number of values to set */ +/* values Pointer to the values */ +/* bootstrap Set to NX_TRUE if called */ +/* during bootstrap */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_create */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_create_internal(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, NX_LWM2M_BOOL bootstrap) +{ +UINT status; +NX_LWM2M_CLIENT_OPERATION_ARGUMENT arguments; +UINT args_len = sizeof(NX_LWM2M_ID); + + if (object_ptr -> object_operation == NX_NULL) + { + + /* Creation of Instances is not supported */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Construct the arguments */ + if (instance_id_ptr == NX_NULL) + { + + /* Assign an ID if not provided */ + arguments.instance_id = NX_LWM2M_CLIENT_RESERVED_ID; + } + else + { + + /* Get the instance ID to create */ + arguments.instance_id = *instance_id_ptr; + } + + /* Set bootstrap flag for the internal Objects */ + if (object_ptr -> object_id <= NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID) + { + arguments.bootstrap = bootstrap; + args_len = sizeof(NX_LWM2M_CLIENT_OPERATION_ARGUMENT); + } + + /* Create the new instance */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_CREATE, object_ptr, NX_NULL, (NX_LWM2M_CLIENT_RESOURCE *)values, &num_values, &arguments, args_len); + if (status != NX_SUCCESS) + { + + /* Failed to create the instance */ + return(status); + } + + /* Return assigned ID */ + if (instance_id_ptr != NX_NULL) + { + *instance_id_ptr = arguments.instance_id; + } + + /* Return success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_delete_all PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes all objects instances of the LWM2M client */ +/* excepts the given security instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* del_object_ptr The single object to delete, */ +/* if NULL delete all objects */ +/* bs_id The ID of the security */ +/* instance to preserve */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_object_delete_all(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *del_object_ptr, NX_LWM2M_ID bs_id) +{ +NX_LWM2M_CLIENT_OBJECT *object_ptr; +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +NX_LWM2M_CLIENT_OBJECT_INSTANCE *security_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *prev_ptr; +#else + + NX_PARAMETER_NOT_USED(bs_id); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES*/ + + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + if ((bs_id != NX_LWM2M_CLIENT_RESERVED_ID) && ((del_object_ptr == NX_NULL) || (del_object_ptr == (NX_LWM2M_CLIENT_OBJECT *) &client_ptr -> nx_lwm2m_client_security))) + { + + /* Do not delete the security instance of the bootstrap server */ + prev_ptr = NX_NULL; + security_ptr = ((NX_LWM2M_CLIENT_OBJECT *) &client_ptr -> nx_lwm2m_client_security) -> object_instances; + while (security_ptr != NX_NULL) + { + if (security_ptr -> object_instance_id == bs_id) + { + + /* Detach instance from list */ + if (prev_ptr == NX_NULL) + { + ((NX_LWM2M_CLIENT_OBJECT *) &client_ptr -> nx_lwm2m_client_security) -> object_instances = security_ptr -> object_instance_next; + } + else + { + prev_ptr -> object_instance_next = security_ptr -> object_instance_next; + } + security_ptr -> object_instance_next = NX_NULL; + + break; + } + + /* Check next instance */ + prev_ptr = security_ptr; + security_ptr = security_ptr -> object_instance_next; + } + } + else + { + security_ptr = NX_NULL; + } +#endif + + if (del_object_ptr != NX_NULL) + { + + /* Delete instances of single object */ + object_ptr = del_object_ptr; + } + else + { + + /* Get first object to delete */ + object_ptr = client_ptr -> nx_lwm2m_client_object_list_head; + } + + while (object_ptr != NX_NULL) + { + + /* Delete all instances */ + while (object_ptr -> object_instances != NX_NULL) + { + if (object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DELETE, object_ptr, object_ptr -> object_instances, NX_NULL, NX_NULL, NX_NULL, 0) != NX_SUCCESS) + { + break; + } + } + + if (del_object_ptr != NX_NULL) + { + + /* Delete a single object */ + break; + } + + /* Get next object */ + object_ptr = object_ptr -> object_next; + } + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + + /* Restore the security instance of the bootstrap server */ + if (security_ptr != NX_NULL) + { + ((NX_LWM2M_CLIENT_OBJECT *)&client_ptr -> nx_lwm2m_client_security) -> object_instances = security_ptr; + } +#endif +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_server_session_get */ +/* _nx_lwm2m_client_session_state_update */ +/* nx_lwm2m_client_session_state_callback */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_delete(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = NX_NULL; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *server_instance_ptr; +NX_LWM2M_CLIENT_SESSION *session_ptr; + + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object implementation */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr != NX_NULL) + { + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id); + } + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + + /* Object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* save pointer to instance if it's a server object */ + if (object_ptr -> object_id == NX_LWM2M_CLIENT_SERVER_OBJECT_ID) + { + server_instance_ptr = instance_ptr; + } + else + { + server_instance_ptr = NX_NULL; + } + + /* delete the instance */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DELETE, object_ptr, instance_ptr, NX_NULL, NX_NULL, NX_NULL, 0); + + /* Terminate lwm2m session if it's server instance is deleted */ + if ((server_instance_ptr != NX_NULL) && (status == NX_SUCCESS)) + { + session_ptr = _nx_lwm2m_client_server_session_get(client_ptr, server_instance_ptr); + + if (session_ptr != NX_NULL) + { + + /* Clear pointer to deleted instance */ + session_ptr -> nx_lwm2m_client_session_server_instance_ptr = NX_NULL; + + if (session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_ERROR) + { + + /* Change session state to error */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_SERVER_INSTANCE_DELETED; + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_ERROR); + + /* Report state change to application */ + session_ptr -> nx_lwm2m_client_session_state_callback(session_ptr, session_ptr -> nx_lwm2m_client_session_state); + } + } + } + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the list of resources implemented by an */ +/* Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_resources Pointer to the number of */ +/* resources */ +/* resources Pointer to the resource info */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_discover(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT *num_resources, NX_LWM2M_CLIENT_RESOURCE *resources) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = NX_NULL; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr != NX_NULL) + { + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id); + } + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + + /* Object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Call the object method */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DISCOVER, object_ptr, instance_ptr, resources, num_resources, NX_NULL, 0); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the execute operation on an Object resource. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* resource_id The Resource ID */ +/* args_ptr Pointer to the arguments */ +/* args_length Length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_execute(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = NX_NULL; +NX_LWM2M_CLIENT_RESOURCE resource_ptr; +UINT resource_count; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr != NX_NULL) + { + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id); + } + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + + /* Object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Call the object method */ + resource_ptr.resource_id = resource_id; + resource_count = 1; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_EXECUTE, object_ptr, instance_ptr, &resource_ptr, &resource_count, (VOID *)args_ptr, args_length); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_instance_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds a new Object Instance to the Instance list. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* instance_ptr Pointer to the Object Instance*/ +/* instance_id_ptr Pointer to the Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* _nx_lwm2m_client_object_list_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_instance_add(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID *instance_id_ptr) +{ +NX_LWM2M_CLIENT_OBJECT_INSTANCE *current_ptr; +NX_LWM2M_ID instance_id; +NX_LWM2M_CLIENT *client_ptr = object_ptr -> object_client_ptr; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + if (instance_id_ptr == NX_NULL) + { + + /* Assign an ID if not provided */ + instance_id = NX_LWM2M_CLIENT_RESERVED_ID; + } + else + { + + /* Get the instance ID to create */ + instance_id = *instance_id_ptr; + } + + if (instance_id == NX_LWM2M_CLIENT_RESERVED_ID) + { + + /* Get an unused Instance ID */ + if ((object_ptr -> object_instances == NX_NULL) || + (object_ptr -> object_instances -> object_instance_id != 0)) + { + instance_id = 0; + } + else + { + current_ptr = object_ptr -> object_instances; + while (1) + { + if ((current_ptr -> object_instance_next == NX_NULL) || + ((current_ptr -> object_instance_next -> object_instance_id - current_ptr -> object_instance_id) > 1)) + { + instance_id = (NX_LWM2M_ID)(current_ptr -> object_instance_id + 1); + break; + } + + current_ptr = current_ptr -> object_instance_next; + } + } + } + else if (_nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id) != NX_NULL) + { + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* The instance ID already exists */ + return(NX_LWM2M_CLIENT_ALREADY_EXIST); + } + + if (instance_id == NX_LWM2M_CLIENT_RESERVED_ID) + { + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* All the valid instance ID are used */ + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Store the instance ID */ + instance_ptr -> object_instance_id = instance_id; + + /* Insert the instance in the object list */ + if ((object_ptr -> object_instances == NX_NULL) || + (object_ptr -> object_instances -> object_instance_id > instance_id)) + { + + /* Set as first instance */ + instance_ptr -> object_instance_next = object_ptr -> object_instances; + object_ptr -> object_instances = instance_ptr; + } + else + { + + /* Parse list of Object Instances */ + current_ptr = object_ptr -> object_instances; + while (1) + { + if ((current_ptr -> object_instance_next == NX_NULL) || + (current_ptr -> object_instance_next -> object_instance_id > instance_id)) + { + /* Insert new Instance in list */ + instance_ptr -> object_instance_next = current_ptr -> object_instance_next; + current_ptr -> object_instance_next = instance_ptr; + break; + } + + /* Next instance */ + current_ptr = current_ptr -> object_instance_next; + } + } + + /* send list of objects in next Update message */ + _nx_lwm2m_client_object_list_changed(client_ptr); + + /* Return assigned ID */ + if (instance_id_ptr != NX_NULL) + { + *instance_id_ptr = instance_id; + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_instance_next_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the next Instance of an Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id_ptr Pointer to the Instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_instance_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr; +NX_LWM2M_ID instance_id; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr == NX_NULL) + { + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Get first instance */ + instance_ptr = object_ptr -> object_instances; + + /* Get requested ID */ + instance_id = *instance_id_ptr; + if (instance_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + + /* Find instance just after the requested ID */ + while ((instance_ptr != NX_NULL) && (instance_id >= instance_ptr -> object_instance_id)) + { + + /* Next instance */ + instance_ptr = instance_ptr -> object_instance_next; + } + } + + if (instance_ptr == NX_NULL) + { + + /* Last instance */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Return next instance ID */ + *instance_id_ptr = instance_ptr -> object_instance_id; + + status = NX_SUCCESS; + } + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_instance_ptr_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* The function returns the instance of an object with the given ID. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_id The instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* instance_ptr Pointer to the instance */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_delete */ +/* _nx_lwm2m_client_object_discover */ +/* _nx_lwm2m_client_object_execute */ +/* _nx_lwm2m_client_object_instance_add */ +/* _nx_lwm2m_client_object_read */ +/* _nx_lwm2m_client_object_write */ +/* _nx_lwm2m_client_session_register_info_get */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_start */ +/* _nx_lwm2m_client_session_state_update */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_CLIENT_OBJECT_INSTANCE * _nx_lwm2m_client_object_instance_ptr_get(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID instance_id) +{ +NX_LWM2M_CLIENT_OBJECT_INSTANCE *current_ptr; + + /* Find Instance */ + current_ptr = object_ptr -> object_instances; + while ((current_ptr != NX_NULL) && (instance_id >= current_ptr -> object_instance_id)) + { + if (instance_id == current_ptr -> object_instance_id) + { + + /* Return the pointer to the Instance */ + return(current_ptr); + } + + current_ptr = current_ptr -> object_instance_next; + } + + /* Instance Not Found */ + return(NX_NULL); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_instance_remove PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function removes an Object Instance from Instance list. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to the Object */ +/* instance_ptr Pointer to the Instance */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_list_changed */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_instance_remove(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ +NX_LWM2M_CLIENT_OBJECT_INSTANCE *prev_ptr = NX_NULL; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *next_ptr; +NX_LWM2M_CLIENT_SESSION *session_ptr; +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; +NX_LWM2M_CLIENT *client_ptr = object_ptr -> object_client_ptr; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Save pointer to next instance */ + next_ptr = instance_ptr -> object_instance_next; + + /* Get preceding instance */ + if (object_ptr -> object_instances != instance_ptr) + { + prev_ptr = object_ptr -> object_instances; + while (prev_ptr != NX_NULL) + { + if (prev_ptr -> object_instance_next == instance_ptr) + { + break; + } + + prev_ptr = prev_ptr -> object_instance_next; + } + + if (prev_ptr == NX_NULL) + { + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* XXX should not happen */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + /* Remove deleted instance from linked list */ + if (object_ptr -> object_instances == instance_ptr) + { + object_ptr -> object_instances = next_ptr; + } + else + { + prev_ptr -> object_instance_next = next_ptr; + } + + /* Delete all notifications for this instance */ + if (instance_ptr != NX_NULL) + { + + /* Tell all sessions to delete all notifications */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + + /* Look for existing notification */ + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (notify_ptr != NX_NULL) + { + + if (notify_ptr -> notify_instance_ptr == instance_ptr) + { + + /* Release one notification */ + _nx_lwm2m_client_session_notify_free(session_ptr, notify_ptr); + } + + /* Move to next notification */ + notify_ptr = notify_ptr -> notify_next; + } + + /* Move to next session */ + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + } + + /* Send list of objects in next Update message */ + _nx_lwm2m_client_object_list_changed(client_ptr); + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_list_changed PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function indicates that the list objects has been updated. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_update_flags */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_delete_ptr */ +/* _nx_lwm2m_client_object_instance_add */ +/* _nx_lwm2m_client_object_instance_remove */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_object_list_changed(NX_LWM2M_CLIENT *client_ptr) +{ +NX_LWM2M_CLIENT_SESSION *session_ptr; + + /* Tell all sessions to update the list of objects */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + + /* Update list of object */ + _nx_lwm2m_client_session_update_flags(session_ptr, NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST); + + /* Get next session */ + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_next_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the next Object of the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id_ptr Pointer to the Object ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID *object_id_ptr) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_ID object_id; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to first object */ + object_ptr = client_ptr -> nx_lwm2m_client_object_list_head; + + /* Get requested ID */ + object_id = *object_id_ptr; + if (object_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + + /* Find instance just after the requested ID */ + while ((object_ptr != NX_NULL) && (object_id >= object_ptr -> object_id)) + { + + /* Next object */ + object_ptr = object_ptr -> object_next; + } + } + + if (object_ptr == NX_NULL) + { + + /* Last object */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Return next object ID */ + *object_id_ptr = object_ptr -> object_id; + + status = NX_SUCCESS; + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_ptr_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the object with the given ID. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The ID of the object */ +/* */ +/* OUTPUT */ +/* */ +/* object_ptr Pointer to the object */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_create */ +/* _nx_lwm2m_client_object_delete */ +/* _nx_lwm2m_client_object_discover */ +/* _nx_lwm2m_client_object_execute */ +/* _nx_lwm2m_client_object_instance_next_get */ +/* _nx_lwm2m_client_object_read */ +/* _nx_lwm2m_client_object_write */ +/* _nx_lwm2m_client_session_register_info_get */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_CLIENT_OBJECT * _nx_lwm2m_client_object_ptr_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id) +{ +NX_LWM2M_CLIENT_OBJECT *current_ptr; + + /* Find Object */ + current_ptr = client_ptr -> nx_lwm2m_client_object_list_head; + + while ((current_ptr != NX_NULL) && (object_id >= current_ptr -> object_id)) + { + if (object_id == current_ptr -> object_id) + { + + /* Return the pointer to the Object */ + return(current_ptr); + } + + current_ptr = current_ptr -> object_next; + } + + /* Not found */ + return(NX_NULL); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reads resources from an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_values The number of resources */ +/* values Pointer to the resources */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, NX_LWM2M_CLIENT_RESOURCE *values) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = NX_NULL; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr != NX_NULL) + { + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id); + } + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + + /* Object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Call the object method */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_READ, object_ptr, instance_ptr, values, &num_values, NX_NULL, 0); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_remove PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function remove an Object from the LWM2M Client Object list. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_ptr Pointer to Object */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_remove(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr) +{ +UINT status = NX_LWM2M_CLIENT_NOT_FOUND; +NX_LWM2M_CLIENT_OBJECT *current_ptr; +NX_LWM2M_CLIENT_OBJECT *previous_ptr; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to first object */ + current_ptr = client_ptr -> nx_lwm2m_client_object_list_head; + previous_ptr = current_ptr; + + /* Loop the list of objects to find the corresponding object */ + while (current_ptr) + { + if (current_ptr == object_ptr) + { + + /* Reomve the object from the object list */ + if (current_ptr == client_ptr -> nx_lwm2m_client_object_list_head) + { + client_ptr -> nx_lwm2m_client_object_list_head = current_ptr -> object_next; + } + else + { + previous_ptr -> object_next = current_ptr -> object_next; + } + + /* Found the object */ + status = NX_SUCCESS; + + break; + } + + /* Get next object */ + previous_ptr = current_ptr; + current_ptr = current_ptr -> object_next; + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_number_abs PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the absolute value of a notify number. */ +/* */ +/* INPUT */ +/* */ +/* value The value of notify number */ +/* */ +/* OUTPUT */ +/* */ +/* The absolut value */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static NX_LWM2M_CLIENT_NOTIFY_NUMBER _nx_lwm2m_client_number_abs(NX_LWM2M_CLIENT_NOTIFY_NUMBER value) +{ + return(value >= 0 ? value : -value); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_resource_changed PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function signals the LWM2M Client that an object resource. */ +/* value has changed */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to the Object */ +/* instance_ptr Pointer to the Object Instance*/ +/* resource_ptr The resource ID and value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_session_notify_attributes */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* _nx_lwm2m_client_device_object_error_push */ +/* _nx_lwm2m_client_device_object_error_reset */ +/* _nx_lwm2m_client_device_resource_changed */ +/* _nx_lwm2m_client_firmware_package_info_set */ +/* _nx_lwm2m_client_firmware_result_set */ +/* _nx_lwm2m_client_firmware_state_set */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_resource_changed(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +NX_LWM2M_CLIENT *client_ptr = object_ptr -> object_client_ptr; +NX_LWM2M_CLIENT_SESSION *session_ptr; +NX_LWM2M_BOOL do_wakeup; + + do_wakeup = NX_FALSE; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Check for notifications on all sessions */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (notify_ptr != NX_NULL) + { + if (notify_ptr -> notify_object_ptr == object_ptr && + (notify_ptr -> notify_instance_ptr == NX_NULL || + (notify_ptr -> notify_instance_ptr == instance_ptr && + (notify_ptr -> notify_resource_id == NX_LWM2M_CLIENT_RESERVED_ID || + notify_ptr -> notify_resource_id == resource_ptr -> resource_id))) && + (notify_ptr -> notify_flags & (NX_LWM2M_CLIENT_NOTIFY_OBSERVE|NX_LWM2M_CLIENT_NOTIFY_CHANGED)) == NX_LWM2M_CLIENT_NOTIFY_OBSERVE) + { + UINT flags; + NX_LWM2M_INT32 pmin; + NX_LWM2M_INT32 pmax; + NX_LWM2M_CLIENT_NOTIFY_NUMBER gt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER lt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER stp; + NX_LWM2M_CLIENT_NOTIFY_NUMBER value; + NX_LWM2M_BOOL changed; + + /* Get notify attributes */ + _nx_lwm2m_client_session_notify_attributes(session_ptr, notify_ptr, &flags, &pmin, &pmax, >, <, &stp); + + /* Get the resource number value if we need to check for conditions */ + if ((flags & (NX_LWM2M_CLIENT_NOTIFY_ATTR_GT|NX_LWM2M_CLIENT_NOTIFY_ATTR_LT|NX_LWM2M_CLIENT_NOTIFY_ATTR_STP)) != 0 && _nx_lwm2m_client_resource_notify_number_get(resource_ptr, &value) == NX_SUCCESS) + { + /* Check for gt/lt/stp conditions */ + if (((flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_GT) && notify_ptr -> notify_last_value <= gt && value > gt) || + ((flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_LT) && notify_ptr -> notify_last_value >= lt && value < lt) || + ((flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_STP) && _nx_lwm2m_client_number_abs(notify_ptr -> notify_last_value - value) >= stp)) + { + + /* Conditions are met */ + changed = NX_TRUE; + } + else + { + + /* Conditions are not met */ + changed = NX_FALSE; + } + } + else + { + + /* No condition or value is not a number, always send notification */ + changed = NX_TRUE; + } + + if (changed) + { + + /* Resource has changed, arm minimum period timer */ + if (!(flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN)) + { + + /* Get default minimum period from server object */ + pmin = session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_min_period; + } + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_CHANGED|NX_LWM2M_CLIENT_NOTIFY_TIMER; + notify_ptr -> notify_timer = notify_ptr -> notify_last_time + (ULONG)pmin * NX_IP_PERIODIC_RATE; + + do_wakeup = NX_TRUE; + } + } + + notify_ptr = notify_ptr -> notify_next; + } + + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + if (do_wakeup) + { + + /* Sessions timers have been updated, wakeup client thread */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } + + /* Return success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes resources to an Object Instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* object_id The Object ID */ +/* instance_id The Instance ID */ +/* num_values The number of resources */ +/* values Pointer to the resources */ +/* write_op The type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_object_write(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, UINT write_op) +{ +UINT status; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr = NX_NULL; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, object_id); + if (object_ptr != NX_NULL) + { + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance_id); + } + if ((object_ptr == NX_NULL) || (instance_ptr == NX_NULL)) + { + if ((object_ptr != NX_NULL) && (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) && (instance_id != NX_LWM2M_CLIENT_RESERVED_ID)) + { + + /* Create new instance if it's a Bootstrap Write operation */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, &instance_id, num_values, values, NX_TRUE); + } + else + { + /* Object or Object Instance doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + } + else + { + + /* Call the object method */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, (NX_LWM2M_CLIENT_RESOURCE *)values, &num_values, &write_op, sizeof(UINT)); + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_boolean_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a boolean resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* bool_ptr On return, the boolean value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_boolean_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_BOOL *bool_ptr) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_BOOLEAN: + + /* Direct Value */ + + *bool_ptr = value -> resource_value.resource_booleandata; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding */ + + if (value -> resource_value.resource_bufferdata.resource_buffer_length == NX_LWM2M_CLIENT_TLV_LENGTH_BOOLEAN) + { + *bool_ptr = *((const UCHAR *) value -> resource_value.resource_bufferdata.resource_buffer_ptr) == 0 ? NX_FALSE : NX_TRUE; + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_BOOLEAN; + value -> resource_value.resource_booleandata = *bool_ptr; + + return(NX_SUCCESS); + } + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + default: + + /* Not a boolean value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_boolean_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a boolean resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* bool_data The boolean value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_boolean_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_BOOL bool_data) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_BOOLEAN; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_booleandata = bool_data; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_dim_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the dim of multiple resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* dim Dim of the multiple resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_dim_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR *dim) +{ + + if (!NX_LWM2M_CLIENT_RESOURCE_IS_MULTIPLE(resource_ptr -> resource_type)) + { + + /* Not a multiple resource */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Get dim of multiple resource. */ + *dim = resource_ptr -> resource_dim; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_dim_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the dim of multiple resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* dim Dim of the multiple resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_dim_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR dim) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + + /* Set dim of multiple resource. */ + resource_ptr -> resource_dim = dim; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_float32_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 32-bit floating point resource.*/ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* float32_ptr On return, the floating point */ +/* value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_float32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT32 *float32_ptr) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT32: + + *float32_ptr = value -> resource_value.resource_float32data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding, check value length */ + switch (value -> resource_value.resource_bufferdata.resource_buffer_length) + { + + case NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32: + { + + /* Read 32-bit value */ + NX_LWM2M_INT32 as_integer32; + + _nx_lwm2m_client_resource_integer32_get(value, &as_integer32); + + memcpy(float32_ptr, &as_integer32, sizeof(NX_LWM2M_FLOAT32)); /* Use case of memcpy is verified. */ + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_FLOAT32; + value -> resource_value.resource_float32data = *float32_ptr; + + return(NX_SUCCESS); + } + + default: + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } + + default: + + /* Not a floating point value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_float32_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 32-bit floating point resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* float32_data The floating data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_float32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT32 float32_data) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_FLOAT32; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_float32data = float32_data; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_float64_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 64-bit floating point resource.*/ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* float64_ptr On return, the floating point */ +/* value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* _nx_lwm2m_client_resource_integer64_get */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_float64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT64 *float64_ptr) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT32: + + *float64_ptr = (NX_LWM2M_FLOAT64) value -> resource_value.resource_float32data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT64: + + *float64_ptr = value -> resource_value.resource_float64data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding, check value length */ + switch (value -> resource_value.resource_bufferdata.resource_buffer_length) + { + + case NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32: + { + + /* Read 32-bit value, convert to 64-bit floating point */ + NX_LWM2M_INT32 as_integer32; + NX_LWM2M_FLOAT32 as_float32; + + _nx_lwm2m_client_resource_integer32_get(value, &as_integer32); + + memcpy(&as_float32, &as_integer32, sizeof(NX_LWM2M_FLOAT32)); /* Use case of memcpy is verified. */ + + *float64_ptr = (NX_LWM2M_FLOAT64) as_float32; + + break; + } + + case NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT64: + { + + /* Read 64-bit value, convert to 64-bit floating point */ + NX_LWM2M_INT64 as_integer64; + + _nx_lwm2m_client_resource_integer64_get(value, &as_integer64); + + memcpy(float64_ptr, &as_integer64, sizeof(NX_LWM2M_FLOAT64)); /* Use case of memcpy is verified. */ + + break; + } + + default: + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_FLOAT64; + value -> resource_value.resource_float64data = *float64_ptr; + + return(NX_SUCCESS); + + default: + + /* Not a floating point value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_float64_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 64-bit floating point resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* float64_data The floating point value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_float64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT64 float64_data) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_FLOAT64; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_float64data = float64_data; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the information of resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_id ID of the resource */ +/* operation Orperation of the resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_info_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID *resource_id, ULONG *operation) +{ + + /* Set resource id. */ + *resource_id = resource_ptr -> resource_id; + + /* Set resource operation. */ + if (operation) + { + *operation = resource_ptr -> resource_operation; + } + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_info_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the information of resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_id ID of the resource */ +/* operation Orperation of the resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_info_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID resource_id, ULONG operation) +{ + + /* Set resource type. */ + resource_ptr -> resource_id = resource_id; + + /* Set resource operation. */ + resource_ptr -> resource_operation = operation; + + /* Reset resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_NONE; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_instances_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the multiple resource instances. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_instances Pointer to the instances */ +/* count Count of the instances */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_tlv_header_parse */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_instances_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT *count) +{ +const UCHAR *ptr; +UCHAR resource_type = 0; +UINT i; +UINT buffer_length; + + /* Check type of resource */ + if (!NX_LWM2M_CLIENT_RESOURCE_IS_MULTIPLE(resource_ptr -> resource_type) || resource_ptr -> resource_dim == 0) + { + + /* Not a multiple resource */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Check the size of input buffer */ + if (*count < resource_ptr -> resource_dim) + { + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* Set count for multiple resource */ + *count = resource_ptr -> resource_dim; + + /* Return the instance value */ + switch (resource_ptr -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_MULTIPLE: + + /* Array of NX_LWM2M_CLIENT_RESOURCE structures */ + memcpy(resource_instances, /* Use case of memcpy is verified. */ + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr, + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length); + + break; + + case NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_TLV: + + /* TLV resource array */ + + /* Begin of TLV buffer */ + ptr = resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr; + + /* Walk through the instances until the index is reached */ + for (i = 0 ; i < *count; i++) + { + + /* Parse TLV encoded instance */ + ptr = _nx_lwm2m_client_tlv_header_parse(ptr, NX_NULL, &resource_type, &(resource_instances[i].resource_id), &buffer_length); + + /* The TLV data has already been validated by _nx_lwm2m_tlv_resource_parse */ + if (ptr == NX_NULL || resource_type != NX_LWM2M_CLIENT_TLV_RESOURCE_INSTANCE) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Set the type and value of resource instance */ + resource_instances[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_TLV; + resource_instances[i].resource_value.resource_bufferdata.resource_buffer_ptr = ptr; + resource_instances[i].resource_value.resource_bufferdata.resource_buffer_length = buffer_length; + + /* Adjust pointer to next instance */ + ptr += buffer_length; + } + + break; + + default: + + /* Invalid type */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Return success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_instances_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the multiple resource instances. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* resource_instances Pointer to the instances */ +/* count Count of the instances */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_instances_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT count) +{ + + /* Set resource type */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + + /* Set dim for multiple resource */ + resource_ptr -> resource_dim = (UCHAR)count; + + /* Set value fot multiple resource */ + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = resource_instances; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = count * sizeof(NX_LWM2M_CLIENT_RESOURCE); + + /* Return success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 32-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* int32_ptr On return, the integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_integer32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT32 *int32_ptr) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER32: + + /* 32-bit integer value */ + *int32_ptr = value -> resource_value.resource_integer32data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding */ + + switch (value -> resource_value.resource_bufferdata.resource_buffer_length) + { + + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER8: + + /* Read 8-bit integer value */ + *int32_ptr = *((signed char *) value -> resource_value.resource_bufferdata.resource_buffer_ptr); + + break; + + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER16: + { + + /* Read 16-bit integer value */ + const UCHAR *byte_ptr = (const UCHAR *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + *int32_ptr = (SHORT) ((((USHORT) byte_ptr[0]) << 8) | + ((USHORT) byte_ptr[1])); + + break; + } + + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER32: + { + + /* Read 32-bit integer value */ + const UCHAR *byte_ptr = (const UCHAR *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + *int32_ptr = (LONG) ((((ULONG) byte_ptr[0]) << 24) | + (((ULONG) byte_ptr[1]) << 16) | + (((ULONG) byte_ptr[2]) << 8) | + ((ULONG) byte_ptr[3])); + + break; + } + + default: + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + value -> resource_value.resource_integer32data = *int32_ptr; + return(NX_SUCCESS); + + default: + + /* Not an Integer value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_integer32_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 32-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* int32_data The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_integer32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT32 int32_data) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_integer32data = int32_data; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_integer64_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a 64-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* int64_ptr On return, the integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_integer64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT64 *int64_ptr) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER32: + + *int64_ptr = value -> resource_value.resource_integer32data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER64: + + *int64_ptr = value -> resource_value.resource_integer64data; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding */ + + switch (value -> resource_value.resource_bufferdata.resource_buffer_length) + { + + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER8: + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER16: + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER32: + { + + /* Read 32-bit integer value, convert to 64-bit */ + NX_LWM2M_INT32 as_integer32; + + _nx_lwm2m_client_resource_integer32_get(value, &as_integer32); + + *int64_ptr = as_integer32; + + break; + } + + case NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER64: + { + + /* Read 64-bit integer value */ + const UCHAR *byte_ptr = (const UCHAR *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + *int64_ptr = (NX_LWM2M_INT64) ((((NX_LWM2M_UINT64) byte_ptr[0]) << 56) | + (((NX_LWM2M_UINT64) byte_ptr[1]) << 48) | + (((NX_LWM2M_UINT64) byte_ptr[2]) << 40) | + (((NX_LWM2M_UINT64) byte_ptr[3]) << 32) | + (((NX_LWM2M_UINT64) byte_ptr[4]) << 24) | + (((NX_LWM2M_UINT64) byte_ptr[5]) << 16) | + (((NX_LWM2M_UINT64) byte_ptr[6]) << 8) | + ((NX_LWM2M_UINT64) byte_ptr[7])); + + break; + } + + default: + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER64; + value -> resource_value.resource_integer64data = *int64_ptr; + return(NX_SUCCESS); + + default: + + /* Not an Integer value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_integer64_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a 64-bit integer resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* int64_data The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_integer64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT64 int64_data) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER64; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_integer64data = int64_data; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_notify_number_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a resource as a notify number. */ +/* The resource value must be an integer or a floating point. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* number_ptr On return, the number value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* _nx_lwm2m_client_object_observe */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_notify_number_get(const NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *number_ptr) +{ + + switch (resource_ptr -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER32: + + *number_ptr = (NX_LWM2M_CLIENT_NOTIFY_NUMBER) resource_ptr -> resource_value.resource_integer32data; + break; + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER64: + + *number_ptr = (NX_LWM2M_CLIENT_NOTIFY_NUMBER) resource_ptr -> resource_value.resource_integer64data; + break; + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT32: + + *number_ptr = (NX_LWM2M_CLIENT_NOTIFY_NUMBER) resource_ptr -> resource_value.resource_float32data; + break; + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT64: + + *number_ptr = (NX_LWM2M_CLIENT_NOTIFY_NUMBER) resource_ptr -> resource_value.resource_float64data; + break; + + default: + + /* Not a number */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_objlnk_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of an Object Link resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* object_id On return, the object ID */ +/* instance_id On return, the instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_objlnk_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_ID *object_id, NX_LWM2M_ID *instance_id) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_OBJLNK: + + *object_id = value -> resource_value.resource_objlnkdata.objlnk_object_id; + *instance_id = value -> resource_value.resource_objlnkdata.objlnk_instance_id; + + return(NX_SUCCESS); + + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* TLV Encoding */ + + if (value -> resource_value.resource_bufferdata.resource_buffer_length == NX_LWM2M_CLIENT_TLV_LENGTH_OBJLNK) + { + const UCHAR *byte_ptr = (const UCHAR *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + /* read 2 16-bit integers */ + *object_id = (NX_LWM2M_ID) ((byte_ptr[0] << 8) | byte_ptr[1]); + *instance_id = (NX_LWM2M_ID) ((byte_ptr[2] << 8) | byte_ptr[3]); + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_OBJLNK; + value -> resource_value.resource_objlnkdata.objlnk_object_id = *object_id; + value -> resource_value.resource_objlnkdata.objlnk_instance_id = *instance_id; + return(NX_SUCCESS); + } + + /* Invalid TLV length */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + default: + + /* Not an Objlnk value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_objlnk_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of an Object Link resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* object_id The object ID */ +/* instance_id The instance ID */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_objlnk_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_OBJLNK; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_objlnkdata.objlnk_object_id= object_id; + resource_ptr -> resource_value.resource_objlnkdata.objlnk_instance_id = instance_id; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_opaque_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of an opaque resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* opaque_ptr On return, a pointer to the */ +/* opaque data */ +/* opaque_length On return, the length of the */ +/* opaque data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_opaque_get(NX_LWM2M_CLIENT_RESOURCE *value, const VOID **opaque_ptr, UINT *opaque_length) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_OPAQUE: + case NX_LWM2M_CLIENT_RESOURCE_TLV: + + /* Opaque data stored in resource buffer */ + *opaque_ptr = value -> resource_value.resource_bufferdata.resource_buffer_ptr; + *opaque_length = value -> resource_value.resource_bufferdata.resource_buffer_length; + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + + return(NX_SUCCESS); + + default: + + /* Not an opaque value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_opaque_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of an opaque resource. */ +/* */ +/* INPUT */ +/* */ +/* resource_ptr Pointer to the resource */ +/* opaque_ptr Apointer to the opaque data */ +/* opaque_length The length of the opaque data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_opaque_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, VOID *opaque_ptr, UINT opaque_length) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = opaque_ptr; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = opaque_length; + + /* Return */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_string_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the value of a string resource. */ +/* */ +/* INPUT */ +/* */ +/* value Pointer to the resource */ +/* string_ptr On return, a pointer to the */ +/* string */ +/* string_length On return, the length of the */ +/* string */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_string_get(NX_LWM2M_CLIENT_RESOURCE *value, const CHAR **string_ptr, UINT *string_length) +{ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_STRING: + case NX_LWM2M_CLIENT_RESOURCE_TLV: + case NX_LWM2M_CLIENT_RESOURCE_TEXT: + + /* String stored in resource buffer */ + *string_ptr = value -> resource_value.resource_bufferdata.resource_buffer_ptr; + *string_length = value -> resource_value.resource_bufferdata.resource_buffer_length; + + /* Reset resource to the corresponding type */ + value -> resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + + return(NX_SUCCESS); + + default: + + /* Not a string value */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_resource_string_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the value of a string resource. */ +/* */ +/* INPUT */ +/* */ +/* Resource_ptr Pointer to the resource */ +/* string_ptr A pointer to the string */ +/* string_length Length of the string */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_resource_string_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, CHAR *string_ptr, UINT string_length) +{ + + /* Set resource type. */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + + /* Set resource data. */ + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = string_ptr; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = string_length; + + return(NX_SUCCESS); +} + + + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the read operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +NX_LWM2M_CLIENT_SECURITY_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_SECURITY_INSTANCE *) object_instance_ptr; +UINT i; + + NX_PARAMETER_NOT_USED(object_ptr); + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_SECURITY_URI_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = instance_ptr -> security_instance_server_uri; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = instance_ptr -> security_instance_server_uri_len; + break; + + case NX_LWM2M_CLIENT_SECURITY_BOOTSTRAP_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_BOOLEAN; + resource[i].resource_value.resource_booleandata = instance_ptr -> security_instance_bootstrap; + break; + + case NX_LWM2M_CLIENT_SECURITY_MODE_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> security_instance_mode; + break; + + case NX_LWM2M_CLIENT_SECURITY_SHORT_SERVER_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> security_instance_server_id; + break; + + case NX_LWM2M_CLIENT_SECURITY_HOLD_OFF_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = instance_ptr -> security_instance_hold_off; + break; + + case NX_LWM2M_CLIENT_SECURITY_PUBLIC_KEY_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = instance_ptr -> security_instance_pub_key_or_id; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = instance_ptr -> security_instance_pub_key_or_id_len; + break; + + case NX_LWM2M_CLIENT_SECURITY_SERVER_PUBLIC_KEY_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = instance_ptr -> security_instance_server_pub_key; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = instance_ptr -> security_instance_server_pub_key_len; + break; + + case NX_LWM2M_CLIENT_SECURITY_SECRET_KEY_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = instance_ptr -> security_instance_secret_key; + resource[i].resource_value.resource_bufferdata.resource_buffer_length = instance_ptr -> security_instance_secret_key_len; + break; + + /* Unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the discover operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* num_resources_ptr Pointer to number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *resource_count) +{ + + NX_PARAMETER_NOT_USED(object_ptr); + NX_PARAMETER_NOT_USED(object_instance_ptr); + NX_PARAMETER_NOT_USED(resource_count); + NX_PARAMETER_NOT_USED(resources); + + /* Dont need to implement discover method for security object */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the write operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* write_op Type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* _nx_lwm2m_client_resource_opaque_get */ +/* _nx_lwm2m_client_resource_string_get */ +/* _nx_lwm2m_client_resource_boolean_get */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, UINT write_op) +{ +NX_LWM2M_CLIENT_SECURITY_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_SECURITY_INSTANCE *) object_instance_ptr; +UINT status; +UINT i; +#ifdef NX_SECURE_ENABLE_DTLS +UCHAR *key_ptr; +UINT key_len; +#endif /* NX_SECURE_ENABLE_DTLS */ + + NX_PARAMETER_NOT_USED(object_ptr); + + /* Writing to security object is only allowed during bootstrap */ + if (write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_SECURITY_URI_ID: + { + const CHAR *uri_ptr; + UINT uri_length; + + status = _nx_lwm2m_client_resource_string_get(&resource[i], &uri_ptr, &uri_length); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Check for maximum URI length */ + if (uri_length >= NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_URI) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* Copy URI into instance */ + if (uri_length > 0) + { + memcpy(instance_ptr -> security_instance_server_uri, uri_ptr, uri_length); /* Use case of memcpy is verified. */ + } + + /* Write null at end of string */ + instance_ptr -> security_instance_server_uri[uri_length] = 0; + instance_ptr -> security_instance_server_uri_len = uri_length; + + break; + } + + case NX_LWM2M_CLIENT_SECURITY_BOOTSTRAP_ID: + + status = _nx_lwm2m_client_resource_boolean_get(&resource[i], &instance_ptr -> security_instance_bootstrap); + if (status != NX_SUCCESS) + { + return(status); + } + break; + + case NX_LWM2M_CLIENT_SECURITY_MODE_ID: + { + NX_LWM2M_INT32 security_mode; + + status = _nx_lwm2m_client_resource_integer32_get(&resource[i], &security_mode); + if (status != NX_SUCCESS) + { + return(status); + } + + instance_ptr -> security_instance_mode = (UCHAR) security_mode; + + break; + } + +#ifdef NX_SECURE_ENABLE_DTLS + case NX_LWM2M_CLIENT_SECURITY_PUBLIC_KEY_ID: + + /* Get key opaque data */ + status = _nx_lwm2m_client_resource_opaque_get(&resource[i], (const VOID **)(&key_ptr), &key_len); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Check key length */ + if (key_len > NX_LWM2M_CLIENT_SECURITY_MAX_PUBLIC_KEY_OR_IDENTITY) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Store key data */ + memcpy(instance_ptr -> security_instance_pub_key_or_id, key_ptr, key_len); /* Use case of memcpy is verified. */ + instance_ptr -> security_instance_pub_key_or_id_len = key_len; + + break; + + case NX_LWM2M_CLIENT_SECURITY_SERVER_PUBLIC_KEY_ID: + + /* Get key opaque data */ + status = _nx_lwm2m_client_resource_opaque_get(&resource[i], (const VOID **)(&key_ptr), &key_len); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Check key length */ + if (key_len > NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_PUBLIC_KEY) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Store key data */ + memcpy(instance_ptr -> security_instance_server_pub_key, key_ptr, key_len); /* Use case of memcpy is verified. */ + instance_ptr -> security_instance_server_pub_key_len = key_len; + + break; + + case NX_LWM2M_CLIENT_SECURITY_SECRET_KEY_ID: + + /* Get key opaque data */ + status = _nx_lwm2m_client_resource_opaque_get(&resource[i], (const VOID **)(&key_ptr), &key_len); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Check key length */ + if (key_len > NX_LWM2M_CLIENT_SECURITY_MAX_SECRET_KEY) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Store key data */ + memcpy(instance_ptr -> security_instance_secret_key, key_ptr, key_len); /* Use case of memcpy is verified. */ + instance_ptr -> security_instance_secret_key_len = key_len; + + break; + +#endif /* NX_SECURE_ENABLE_DTLS */ + + case NX_LWM2M_CLIENT_SECURITY_SHORT_SERVER_ID: + { + NX_LWM2M_INT32 short_server_id; + + status = _nx_lwm2m_client_resource_integer32_get(&resource[i], &short_server_id); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Short server ID must be in range 0-65535 */ + if (short_server_id < 0 || short_server_id > 65535) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + instance_ptr -> security_instance_server_id = (NX_LWM2M_ID) short_server_id; + + break; + } + + case NX_LWM2M_CLIENT_SECURITY_HOLD_OFF_ID: + + status = _nx_lwm2m_client_resource_integer32_get(&resource[i], &instance_ptr -> security_instance_hold_off); + if (status != NX_SUCCESS) + { + return(status); + } + break; + + default: + + /* Ignore unknown resources (bootstrap write) */ + break; + } + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the execute operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id The ID of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ + + NX_PARAMETER_NOT_USED(object_ptr); + NX_PARAMETER_NOT_USED(instance_ptr); + NX_PARAMETER_NOT_USED(resource_id); + NX_PARAMETER_NOT_USED(args_ptr); + NX_PARAMETER_NOT_USED(args_length); + + /* cannot execute any resource */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the create operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_id Pointer to object instance ID */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* bootstrap Flag of bootstrap step */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_security_write */ +/* _nx_lwm2m_client_object_instance_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_create(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id, NX_LWM2M_CLIENT_RESOURCE *values_ptr, UINT resource_count, NX_LWM2M_BOOL bootstrap) +{ +NX_LWM2M_CLIENT_SECURITY_OBJECT *security_ptr = (NX_LWM2M_CLIENT_SECURITY_OBJECT *) object_ptr; +NX_LWM2M_CLIENT_SECURITY_INSTANCE *instance_ptr; +UINT status; + + /* Only allow security instance creation during boostrap */ + if (!bootstrap) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + + /* Allocate a new instance */ + instance_ptr = (NX_LWM2M_CLIENT_SECURITY_INSTANCE *) security_ptr -> security_object_instances_free_list; + if (instance_ptr == NX_NULL) + { + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* Initialize resources with default values */ + instance_ptr -> security_instance_server_id = 0; + instance_ptr -> security_instance_bootstrap = NX_FALSE; + instance_ptr -> security_instance_mode = NX_LWM2M_CLIENT_SECURITY_MODE_UNDEFINED; + instance_ptr -> security_instance_server_uri[0] = 0; + instance_ptr -> security_instance_hold_off = 0; + + /* Write the provided resources */ + status = _nx_lwm2m_client_security_write((NX_LWM2M_CLIENT_OBJECT *) security_ptr, (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) instance_ptr, values_ptr, resource_count, NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Update free instance list */ + security_ptr -> security_object_instances_free_list = instance_ptr -> security_instance.object_instance_next; + + /* Add new instance to the instance list */ + status = _nx_lwm2m_client_object_instance_add(object_ptr, &(instance_ptr -> security_instance), instance_id); + if (status != NX_SUCCESS) + { + + /* Revert the free instance list */ + security_ptr -> security_object_instances_free_list = &(instance_ptr -> security_instance); + return(status); + } + + /* Return success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the delete operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_instance_remove */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_security_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_delete(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ +NX_LWM2M_CLIENT_SECURITY_OBJECT *security_ptr = (NX_LWM2M_CLIENT_SECURITY_OBJECT *) object_ptr; +UINT status; + + /* Remove the instance from instance list */ + status = _nx_lwm2m_client_object_instance_remove(object_ptr, instance_ptr); + if (status) + { + return(status); + } + + /* Release the instance */ + instance_ptr -> object_instance_next = security_ptr -> security_object_instances_free_list; + security_ptr -> security_object_instances_free_list = instance_ptr; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_operation PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the object operation. */ +/* */ +/* INPUT */ +/* */ +/* operation The operation type */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_security_read */ +/* _nx_lwm2m_client_security_discover */ +/* _nx_lwm2m_client_security_write */ +/* _nx_lwm2m_client_security_execute */ +/* _nx_lwm2m_client_security_write */ +/* _nx_lwm2m_client_security_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_security_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +UINT *write_op; +NX_LWM2M_CLIENT_OPERATION_ARGUMENT *arguments; + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return(_nx_lwm2m_client_security_read(object_ptr, object_instance_ptr, resource, *resource_count)); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return(_nx_lwm2m_client_security_discover(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Get the type of write operation */ + write_op = (UINT *)args_ptr; + + /* Call write function */ + return(_nx_lwm2m_client_security_write(object_ptr, object_instance_ptr, resource, *resource_count, *write_op)); + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return(_nx_lwm2m_client_security_execute(object_ptr, object_instance_ptr, resource -> resource_id, args_ptr, args_length)); + case NX_LWM2M_CLIENT_OBJECT_CREATE: + + /* Get arguments */ + arguments = (NX_LWM2M_CLIENT_OPERATION_ARGUMENT *)args_ptr; + + /* Call create function */ + return(_nx_lwm2m_client_security_create(object_ptr, &(arguments -> instance_id), resource, *resource_count, arguments -> bootstrap)); + case NX_LWM2M_CLIENT_OBJECT_DELETE: + + /* Call delete function */ + return(_nx_lwm2m_client_security_delete(object_ptr, object_instance_ptr)); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_security_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions initializes the Security Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_create */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_security_object_create(NX_LWM2M_CLIENT *client_ptr) +{ +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES > 1 +int i; +#endif +NX_LWM2M_CLIENT_SECURITY_OBJECT *security_ptr = &(client_ptr -> nx_lwm2m_client_security); + + /* Add Security Object to the LWM2M Client */ + _nx_lwm2m_client_object_add(client_ptr, &(security_ptr -> security_object), NX_LWM2M_CLIENT_SECURITY_OBJECT_ID, _nx_lwm2m_client_security_operation); + + /* Initialize the list of free instances */ + security_ptr -> security_object_instances_free_list = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &security_ptr -> security_object_instances[0]; +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES > 1 + for (i = 0; i < NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES-1; i++) + { + security_ptr -> security_object_instances[i].security_instance.object_instance_next = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &security_ptr -> security_object_instances[i+1]; + } +#endif + security_ptr -> security_object_instances[NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES-1].security_instance.object_instance_next = NX_NULL; +} + +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_read PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the read operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +NX_LWM2M_CLIENT_SERVER_INSTANCE *server_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *) instance_ptr; +UINT length; +UINT i; + + NX_PARAMETER_NOT_USED(object_ptr); + + for (i = 0; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = server_ptr -> server_instance_short_id; + break; + + case NX_LWM2M_CLIENT_SERVER_LIFETIME_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = server_ptr -> server_instance_lifetime; + break; + + case NX_LWM2M_CLIENT_SERVER_MIN_PERIOD_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = server_ptr -> server_instance_min_period; + break; + + case NX_LWM2M_CLIENT_SERVER_MAX_PERIOD_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = server_ptr -> server_instance_max_period; + break; + + case NX_LWM2M_CLIENT_SERVER_DISABLE_TIMEOUT_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_INTEGER32; + resource[i].resource_value.resource_integer32data = server_ptr -> server_instance_disable_timeout; + break; + + case NX_LWM2M_CLIENT_SERVER_STORING_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_BOOLEAN; + resource[i].resource_value.resource_booleandata = server_ptr -> server_instance_storing; + break; + + case NX_LWM2M_CLIENT_SERVER_BINDING_ID: + + resource[i].resource_type = NX_LWM2M_CLIENT_RESOURCE_STRING; + resource[i].resource_value.resource_bufferdata.resource_buffer_ptr = _nx_lwm2m_client_binding_mode_string_get(server_ptr -> server_instance_binding, &length); + resource[i].resource_value.resource_bufferdata.resource_buffer_length = length; + break; + + /* Non-readable resources */ + case NX_LWM2M_CLIENT_SERVER_DISABLE_ID: + case NX_LWM2M_CLIENT_SERVER_UPDATE_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the discover operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* num_resources_ptr Pointer to number of resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *resource_count) +{ + + NX_PARAMETER_NOT_USED(object_ptr); + NX_PARAMETER_NOT_USED(instance_ptr); + + /* Check length of output buffer */ + if (*resource_count < 9) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* Return list of resources */ + resources[0].resource_id = NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID; + resources[0].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[1].resource_id = NX_LWM2M_CLIENT_SERVER_LIFETIME_ID; + resources[1].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[2].resource_id = NX_LWM2M_CLIENT_SERVER_MIN_PERIOD_ID; + resources[2].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[3].resource_id = NX_LWM2M_CLIENT_SERVER_MAX_PERIOD_ID; + resources[3].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[4].resource_id = NX_LWM2M_CLIENT_SERVER_DISABLE_ID; + resources[4].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; + resources[5].resource_id = NX_LWM2M_CLIENT_SERVER_DISABLE_TIMEOUT_ID; + resources[5].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[6].resource_id = NX_LWM2M_CLIENT_SERVER_STORING_ID; + resources[6].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[7].resource_id = NX_LWM2M_CLIENT_SERVER_BINDING_ID; + resources[7].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE; + resources[8].resource_id = NX_LWM2M_CLIENT_SERVER_UPDATE_ID; + resources[8].resource_operation = NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE; + + *resource_count = 9; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_write PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the write operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* write_op Type of write operation */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_resource_integer32_get */ +/* _nx_lwm2m_client_resource_boolean_get */ +/* _nx_lwm2m_client_resource_string_get */ +/* _nx_lwm2m_client_binding_mode_string_parse */ +/* _nx_lwm2m_client_server_session_get */ +/* _nx_lwm2m_client_session_update_flags */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, UINT write_op) +{ +NX_LWM2M_CLIENT_SERVER_INSTANCE *instance_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *) object_instance_ptr; +UINT status; +ULONG flags; +NX_LWM2M_INT32 short_server_id; +NX_LWM2M_INT32 lifetime; +NX_LWM2M_INT32 min_period; +NX_LWM2M_INT32 max_period; +NX_LWM2M_INT32 disable_timeout; +NX_LWM2M_BOOL storing; +UCHAR binding = 0; +UINT i; + + /* XXX replace not supported? */ + if (write_op == NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Check validity of values before updating instance */ + flags = 0; + + for (i = 0 ; i < resource_count; i++) + { + switch (resource[i].resource_id) + { + + case NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID: + + /* Resource is read-only, can only be set during boostrap or instance creation */ + if (write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP && write_op != NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + status = _nx_lwm2m_client_resource_integer32_get(&resource[i], &short_server_id); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Short server ID must be in range 1-65535 */ + if (short_server_id < 1 || short_server_id > 65535) + { + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + flags |= 1< server_instance_short_id = (NX_LWM2M_ID) short_server_id; + } + if (flags & 1< server_instance_storing = storing; + } + if ((flags & 1< server_instance_binding != binding) + { + NX_LWM2M_CLIENT_SESSION *session_ptr; + + instance_ptr -> server_instance_binding = binding; + + /* Update session binding if we are currently registered to the server */ + session_ptr = _nx_lwm2m_client_server_session_get(object_ptr -> object_client_ptr, object_instance_ptr); + if (session_ptr != NX_NULL) + { + _nx_lwm2m_client_session_update_flags(session_ptr, NX_LWM2M_CLIENT_SESSION_UPDATE_BINDING_MODE); + } + } + if ((flags & 1< server_instance_lifetime != lifetime) + { + NX_LWM2M_CLIENT_SESSION *session_ptr; + + instance_ptr -> server_instance_lifetime = lifetime; + + /* Update session lifetime if we are currently registered to the server */ + session_ptr = _nx_lwm2m_client_server_session_get(object_ptr -> object_client_ptr, object_instance_ptr); + if (session_ptr != NX_NULL) + { + _nx_lwm2m_client_session_update_flags(session_ptr, NX_LWM2M_CLIENT_SESSION_UPDATE_LIFETIME); + } + } + if (flags & 1< server_instance_min_period = min_period; + } + if (flags & 1< server_instance_max_period = max_period; + } + if (flags & 1< server_instance_disable_timeout = disable_timeout; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_execute PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the execute operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id The ID of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_server_session_get */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length) +{ +NX_LWM2M_CLIENT_SESSION *session_ptr; + + NX_PARAMETER_NOT_USED(args_ptr); + NX_PARAMETER_NOT_USED(args_length); + + switch (resource_id) + { + + /* Non-executable resources */ + case NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID: + case NX_LWM2M_CLIENT_SERVER_LIFETIME_ID: + case NX_LWM2M_CLIENT_SERVER_MIN_PERIOD_ID: + case NX_LWM2M_CLIENT_SERVER_MAX_PERIOD_ID: + case NX_LWM2M_CLIENT_SERVER_DISABLE_TIMEOUT_ID: + case NX_LWM2M_CLIENT_SERVER_STORING_ID: + case NX_LWM2M_CLIENT_SERVER_BINDING_ID: + + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + /* Executable resources */ + case NX_LWM2M_CLIENT_SERVER_DISABLE_ID: + case NX_LWM2M_CLIENT_SERVER_UPDATE_ID: + { + + /* Disable/update the session if it is actually registered */ + session_ptr = _nx_lwm2m_client_server_session_get(object_ptr -> object_client_ptr, instance_ptr); + if ((session_ptr != NX_NULL) && + ((session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERED) || + (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING))) + { + if (resource_id == NX_LWM2M_CLIENT_SERVER_DISABLE_ID) + { + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE; + } + else + { + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE; + } + + /* Wakeup client thread */ + tx_event_flags_set(&object_ptr -> object_client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } + + /* Return success */ + /* XXX should we return an error if the client is not registered? */ + return(NX_SUCCESS); + } + + /* unknown resource */ + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the create operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_id Pointer to object instance ID */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* bootstrap Flag of bootstrap step */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_server_write */ +/* _nx_lwm2m_client_object_instance_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_create(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id, NX_LWM2M_CLIENT_RESOURCE *values_ptr, UINT resource_count, NX_LWM2M_BOOL bootstrap) +{ +NX_LWM2M_CLIENT_SERVER_OBJECT *server_ptr = (NX_LWM2M_CLIENT_SERVER_OBJECT *) object_ptr; +NX_LWM2M_CLIENT_SERVER_INSTANCE *instance_ptr; +UINT status; + + /* Allocate a new instance */ + instance_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *) server_ptr -> server_object_instances_free_list; + if (instance_ptr == NX_NULL) + { + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* Initialize resources with default values */ + instance_ptr -> server_instance_short_id = 0; + instance_ptr -> server_instance_storing = NX_TRUE; + instance_ptr -> server_instance_binding = NX_LWM2M_CLIENT_BINDING_U; + instance_ptr -> server_instance_lifetime = 86400; + instance_ptr -> server_instance_min_period = 0; + instance_ptr -> server_instance_max_period = 0; + instance_ptr -> server_instance_disable_timeout = 86400; + + /* Write the provided resources */ + status = _nx_lwm2m_client_server_write((NX_LWM2M_CLIENT_OBJECT *) server_ptr, (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) instance_ptr, values_ptr, resource_count, bootstrap ? NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP : NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE); + if (status != NX_SUCCESS) + { + return(status); + } + + /* Update free instance list */ + server_ptr -> server_object_instances_free_list = instance_ptr -> server_instance.object_instance_next; + + /* Add new instance to the instance list */ + status = _nx_lwm2m_client_object_instance_add(object_ptr, &(instance_ptr -> server_instance), instance_id); + if (status != NX_SUCCESS) + { + + /* Revert the free instance list */ + server_ptr -> server_object_instances_free_list = &(instance_ptr -> server_instance); + return(status); + } + + /* Return success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the delete operation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_instance_remove */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_server_operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_delete(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ +NX_LWM2M_CLIENT_SERVER_OBJECT *server_ptr = (NX_LWM2M_CLIENT_SERVER_OBJECT *) object_ptr; +UINT status; + + /* Remove the instance from instance list */ + status = _nx_lwm2m_client_object_instance_remove(object_ptr, instance_ptr); + if (status) + { + return(status); + } + + /* Release the instance */ + instance_ptr -> object_instance_next = server_ptr -> server_object_instances_free_list; + server_ptr -> server_object_instances_free_list = instance_ptr; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_operation PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the object operation. */ +/* */ +/* INPUT */ +/* */ +/* operation The operation type */ +/* object_ptr Pointer to object */ +/* object_instance_ptr Pointer to object instance */ +/* resource Pointer to resource */ +/* resource_count The number of resource */ +/* args_ptr Pointer to arguments */ +/* args_length The length of arguments */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_server_read */ +/* _nx_lwm2m_client_server_discover */ +/* _nx_lwm2m_client_server_write */ +/* _nx_lwm2m_client_server_execute */ +/* _nx_lwm2m_client_server_write */ +/* _nx_lwm2m_client_server_delete */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_server_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +UINT *write_op; +NX_LWM2M_CLIENT_OPERATION_ARGUMENT *arguments; + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return(_nx_lwm2m_client_server_read(object_ptr, object_instance_ptr, resource, *resource_count)); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return(_nx_lwm2m_client_server_discover(object_ptr, object_instance_ptr, resource, resource_count)); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Get the type of write operation */ + write_op = (UINT *)args_ptr; + + /* Call write function */ + return(_nx_lwm2m_client_server_write(object_ptr, object_instance_ptr, resource, *resource_count, *write_op)); + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return(_nx_lwm2m_client_server_execute(object_ptr, object_instance_ptr, resource -> resource_id, args_ptr, args_length)); + case NX_LWM2M_CLIENT_OBJECT_CREATE: + + /* Get arguments */ + arguments = (NX_LWM2M_CLIENT_OPERATION_ARGUMENT *)args_ptr; + + /* Call create function */ + return(_nx_lwm2m_client_server_create(object_ptr, &(arguments -> instance_id), resource, *resource_count, arguments -> bootstrap)); + case NX_LWM2M_CLIENT_OBJECT_DELETE: + + /* Call delete function */ + return(_nx_lwm2m_client_server_delete(object_ptr, object_instance_ptr)); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_object_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions initializes the Server Object. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_create */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_server_object_create(NX_LWM2M_CLIENT *client_ptr) +{ +#if NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES > 1 +int i; +#endif +NX_LWM2M_CLIENT_SERVER_OBJECT *server_ptr = &(client_ptr -> nx_lwm2m_client_server); + + /* Add Server Object to the LWM2M Client */ + _nx_lwm2m_client_object_add(client_ptr, &(server_ptr -> server_object), NX_LWM2M_CLIENT_SERVER_OBJECT_ID, _nx_lwm2m_client_server_operation); + + /* Initialize the list of free instances */ + server_ptr -> server_object_instances_free_list = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &server_ptr -> server_object_instances[0]; +#if NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES > 1 + for (i = 0; i < NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES-1; i++) + { + server_ptr -> server_object_instances[i].server_instance.object_instance_next = (NX_LWM2M_CLIENT_OBJECT_INSTANCE *) &server_ptr -> server_object_instances[i+1]; + } +#endif + server_ptr -> server_object_instances[NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES-1].server_instance.object_instance_next = NX_NULL; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_server_session_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Return the session associated with a server instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* server_instance_ptr Pointer to the server */ +/* instance */ +/* */ +/* OUTPUT */ +/* */ +/* session_ptr The pointer to the session */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_delete */ +/* _nx_lwm2m_client_server_write */ +/* _nx_lwm2m_client_server_execute */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_CLIENT_SESSION *_nx_lwm2m_client_server_session_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *server_instance_ptr) +{ +NX_LWM2M_CLIENT_SESSION *session_ptr; + + /* Look if the instance is attached to a session */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + if (session_ptr -> nx_lwm2m_client_session_server_instance_ptr == (NX_LWM2M_CLIENT_SERVER_INSTANCE *) server_instance_ptr) + { + return(session_ptr); + } + + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + + return(NX_NULL); +} + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_bootstrap PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a session with a Bootstrap server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_id The Security Instance ID of */ +/* the bootstrap server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_bootstrap(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port) +{ + + /* Start bootstrap. */ +#ifdef NX_SECURE_ENABLE_DTLS + return(_nx_lwm2m_client_session_start(session_ptr, NX_TRUE, security_id, ip_address, port, NX_NULL)); +#else + return(_nx_lwm2m_client_session_start(session_ptr, NX_TRUE, security_id, ip_address, port)); +#endif /* NX_SECURE_ENABLE_DTLS */ +} + +#ifdef NX_SECURE_ENABLE_DTLS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_bootstrap_dtls PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a session with a Bootstrap server using a */ +/* secure channel. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_id The Security Instance ID of */ +/* the bootstrap server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* dtls_session_ptr The pointer to the DTLS */ +/* session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_bootstrap_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr) +{ + + /* Start bootstrap. */ + return(_nx_lwm2m_client_session_start(session_ptr, NX_TRUE, security_id, ip_address, port, dtls_session_ptr)); +} + +#endif /* NX_SECURE_ENABLE_DTLS */ +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_cleanup PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans up the LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* nx_secure_dtls_session_end */ +/* nx_secure_dtls_session_reset */ +/* nx_udp_socket_unbind */ +/* nx_udp_socket_delete */ +/* _nx_lwm2m_client_notify_free */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_state_update */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_cleanup(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY * notify_ptr; +UINT state = session_ptr -> nx_lwm2m_client_session_state; + + if ((state == NX_LWM2M_CLIENT_SESSION_DISABLED) && + (session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_disable_timeout > 0)) + { + + /* Arm disable timeout */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + (ULONG)(session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_disable_timeout) * NX_IP_PERIODIC_RATE; + } + else + { + + /* Set session to idle state */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_IDLE; + } + +#ifdef NX_SECURE_ENABLE_DTLS + + /* Close DTLS session */ + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + if (state == NX_LWM2M_CLIENT_SESSION_DISABLED || + state == NX_LWM2M_CLIENT_SESSION_DEREGISTERED || + state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED) + { + + /* We have deregistered from the server, + properly shutdown the DTLS session */ + nx_secure_dtls_session_end(session_ptr -> nx_lwm2m_client_session_dtls_session, NX_LWM2M_CLIENT_DTLS_END_TIMEOUT); + } + else + { + + /* lwm2m session was aborted, just reset the DTLS session */ + nx_secure_dtls_session_reset(session_ptr -> nx_lwm2m_client_session_dtls_session); + } + + /* + * keep the DTLS session and socket if we are disabled so we are + * able to reconnect again to the server when disable timer expires, + * otherwise release all DTLS resources + */ + if ((state != NX_LWM2M_CLIENT_SESSION_DISABLED) || + (session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_disable_timeout == 0)) + { + + /* Delete reference to DTLS session */ + session_ptr -> nx_lwm2m_client_session_dtls_session = NX_NULL; + + /* Unbind the DTLS session socket */ + nx_udp_socket_unbind((NX_UDP_SOCKET *)&session_ptr -> nx_lwm2m_client_session_dtls_socket); + + /* Delete the DTLS session socket */ + nx_udp_socket_delete((NX_UDP_SOCKET *)&session_ptr -> nx_lwm2m_client_session_dtls_socket); + } + } +#endif + + /* Free notifications */ + while (1) + { + + /* Get next notification */ + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + + if (notify_ptr == NX_NULL) + { + + /* All notifications have been deleted */ + break; + } + + /* Detach notification */ + session_ptr -> nx_lwm2m_client_session_notifications = notify_ptr -> notify_next; + + /* Free the structure */ + _nx_lwm2m_client_notify_free(session_ptr -> nx_lwm2m_client_session_client_ptr, notify_ptr); + + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions creates a LWM2M Client Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* client_ptr Pointer to LWM2M Client */ +/* state_callback The session state callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_create(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK state_callback) +{ + + /* Initialize the session control block to zero. */ + memset(session_ptr, 0, sizeof(NX_LWM2M_CLIENT_SESSION)); + + /* Set the pointer to the LWM2M Client */ + session_ptr -> nx_lwm2m_client_session_client_ptr = client_ptr; + + /* Reset the pointer to the server object instance */ + session_ptr -> nx_lwm2m_client_session_server_instance_ptr = NX_NULL; + + /* Set the state callback */ + session_ptr -> nx_lwm2m_client_session_state_callback = state_callback; + + /* Set the initial state */ + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_INIT; + + /* Set the initial sub-state */ + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_SUBSTATE_IDLE; + + /* Reset Uri-Path of server */ + session_ptr -> nx_lwm2m_client_session_uri_path_length = 0; + + /* Reset flags */ + session_ptr -> nx_lwm2m_client_session_flags = 0; + + /* Reset error code */ + session_ptr -> nx_lwm2m_client_session_error = NX_SUCCESS; + + /* Clear list of notifications */ + session_ptr -> nx_lwm2m_client_session_notifications = NX_NULL; + +#ifdef NX_SECURE_ENABLE_DTLS + /* Clear pointer to DTLS session */ + session_ptr -> nx_lwm2m_client_session_dtls_session = NX_NULL; +#endif /* NX_SECURE_ENABLE_DTLS */ + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Attach the new session to the client */ + session_ptr -> nx_lwm2m_client_session_next = client_ptr -> nx_lwm2m_client_sessions; + client_ptr -> nx_lwm2m_client_sessions = session_ptr; + + /* Release the client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Retun success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes a LWM2M Client Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_session_state_update */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_delete(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Clear all resources attached to this session */ + if (session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_INIT) + { + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_INIT); + } + + /* Detach the session from the client */ + if (client_ptr -> nx_lwm2m_client_sessions == session_ptr) + { + + /* First session of the list */ + client_ptr -> nx_lwm2m_client_sessions = session_ptr -> nx_lwm2m_client_session_next; + } + else + { + NX_LWM2M_CLIENT_SESSION *current_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (current_ptr != NX_NULL) + { + + /* Find the preceding session */ + if (current_ptr -> nx_lwm2m_client_session_next == session_ptr) + { + current_ptr -> nx_lwm2m_client_session_next = session_ptr -> nx_lwm2m_client_session_next; + break; + } + + current_ptr = current_ptr -> nx_lwm2m_client_session_next; + } + } + + /* Release mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_deregister PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deregisters the Client from a LWM2M Server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_deregister(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +UINT status = NX_SUCCESS; +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; + + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Check session state */ + if ((session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_REGISTERED && + session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_UPDATING) || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER) + { + status = NX_LWM2M_CLIENT_NOT_REGISTERED; + } + else + { + + /* Tell session to start deregistering */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER; + } + + /* Release the client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + if (status == NX_SUCCESS) + { + + /* Wakeup client thread */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_error_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the error code of a LWM2M Session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status The error code */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_error_get(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; +UINT error; + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get the error code */ + error = session_ptr -> nx_lwm2m_client_session_error; + + /* Release the client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the error code */ + return(error); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_notify_attributes PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the attributes of a notification, including */ +/* the inherited attributes. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* notify_ptr Pointer to the notification */ +/* flags_ptr On return, the attributes set */ +/* pmin_ptr On return, the pmin attribute */ +/* pmax_ptr On return, the pmax attribute */ +/* gt_ptr On return, the gt attribute */ +/* lt_ptr On return, the lt attribute */ +/* stp_ptr On return, the stp attribute */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_resource_changed */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_notify_attributes(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr, UINT *flags_ptr, NX_LWM2M_INT32 *pmin_ptr, NX_LWM2M_INT32 *pmax_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *gt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *lt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *stp_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *current_ptr; +UINT object_flags; + + /* Initialize attributes */ + *flags_ptr = notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + *pmin_ptr = notify_ptr -> notify_attr_pmin; + *pmax_ptr = notify_ptr -> notify_attr_pmax; + *gt_ptr = notify_ptr -> notify_attr_gt; + *lt_ptr = notify_ptr -> notify_attr_lt; + *stp_ptr = notify_ptr -> notify_attr_stp; + + if (notify_ptr -> notify_instance_ptr == NX_NULL) + { + + /* Object notification, no inherited attribute */ + return; + } + + /* Look for inherited attributes from object and object instance */ + object_flags = 0; + current_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (current_ptr != NX_NULL) + { + if ((current_ptr != notify_ptr) && (current_ptr -> notify_object_ptr == notify_ptr -> notify_object_ptr) && + (current_ptr -> notify_resource_id == NX_LWM2M_CLIENT_RESERVED_ID) && + ((current_ptr -> notify_instance_ptr == NX_NULL) || (current_ptr -> notify_instance_ptr== notify_ptr -> notify_instance_ptr))) + { + UINT flags; + if (current_ptr -> notify_instance_ptr == NX_NULL) + { + + /* Object attributes, do not overwrite attributes already set */ + flags = current_ptr -> notify_flags & ~(*flags_ptr) & NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + object_flags = flags; + } + else + { + + /* Instance attributes, can only overwrite object attributes */ + flags = current_ptr -> notify_flags & (~(*flags_ptr) | object_flags) & NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + } + if (flags != 0) + { + *flags_ptr |= flags; + if (flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN) + { + *pmin_ptr = current_ptr -> notify_attr_pmin; + } + if (flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX) + { + *pmax_ptr = current_ptr -> notify_attr_pmax; + } + if (flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_GT) + { + *gt_ptr = current_ptr -> notify_attr_gt; + } + if (flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_LT) + { + *lt_ptr = current_ptr -> notify_attr_lt; + } + if (flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_STP) + { + *stp_ptr = current_ptr -> notify_attr_stp; + } + } + } + + /* Next notification */ + current_ptr = current_ptr -> notify_next; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_notify_free PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function releases a notification from a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* notify_ptr Pointer to the notification */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_notify_free */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_notify_free(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *current_ptr; + + /* Detach the structure from the list */ + current_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + if (current_ptr == notify_ptr) + { + session_ptr -> nx_lwm2m_client_session_notifications = notify_ptr -> notify_next; + } + else + { + while (current_ptr != NX_NULL) + { + if (current_ptr -> notify_next == notify_ptr) + { + current_ptr -> notify_next = notify_ptr -> notify_next; + + break; + } + + current_ptr = current_ptr -> notify_next; + } + } + + /* Free structure */ + _nx_lwm2m_client_notify_free(session_ptr -> nx_lwm2m_client_session_client_ptr, notify_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_notify_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets an existing notification structure or allocates */ +/* a new one if requested. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* object_ptr Pointer to the Object */ +/* instance_ptr Pointer to the Instance, can */ +/* be NULL */ +/* resource_id The resource ID */ +/* create If True, creates the */ +/* notification if it doesnt */ +/* exists */ +/* */ +/* OUTPUT */ +/* */ +/* notify_ptr Pointer to the notification */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_notify_allocate */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_write_attributes */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_CLIENT_NOTIFY * _nx_lwm2m_client_session_notify_get(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, NX_LWM2M_BOOL create) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* Look for existing notification */ + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (notify_ptr != NX_NULL) + { + if (notify_ptr -> notify_object_ptr == object_ptr && notify_ptr -> notify_instance_ptr == instance_ptr && notify_ptr -> notify_resource_id == resource_id) + { + break; + } + + notify_ptr = notify_ptr -> notify_next; + } + + if ((notify_ptr != NX_NULL) || (!create)) + { + + /* Notification found or creation not asked */ + return(notify_ptr); + } + + /* Create a new notification */ + notify_ptr = _nx_lwm2m_client_notify_allocate(session_ptr -> nx_lwm2m_client_session_client_ptr); + + if (notify_ptr == NX_NULL) + { + + /* Failed to allocate notification */ + return(NX_NULL); + } + + /* Initialize structure */ + notify_ptr -> notify_object_ptr = object_ptr; + notify_ptr -> notify_instance_ptr = instance_ptr; + notify_ptr -> notify_resource_id = resource_id; + notify_ptr -> notify_flags = 0; + + /* Insert structure in the list */ + notify_ptr -> notify_next = session_ptr -> nx_lwm2m_client_session_notifications; + session_ptr -> nx_lwm2m_client_session_notifications = notify_ptr; + + return(notify_ptr); +} + +/* size of Physical+IP+UDP headers */ +#ifdef FEATURE_NX_IPV6 +#define LWM2M_PACKET(session_ptr) (session_ptr -> nx_lwm2m_client_session_server_address.nxd_ip_version == NX_IP_VERSION_V4 ? NX_IPv4_UDP_PACKET : NX_IPv6_UDP_PACKET) +#else +#define LWM2M_PACKET(session_ptr) NX_UDP_PACKET +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_packet_allocate PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions allocates and initializes a packet from the IP pool. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* packet_ptr The allocated packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_PACKET *_nx_lwm2m_client_session_packet_allocate(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +NX_PACKET *packet_ptr; +UINT status; + + /* Allocate a packet from the pool */ +#ifdef NX_SECURE_ENABLE_DTLS + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + status = nx_secure_dtls_packet_allocate(session_ptr -> nx_lwm2m_client_session_dtls_session, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_pool_ptr, &packet_ptr, NX_NO_WAIT); + } + else +#endif /* NX_SECURE_ENABLE_DTLS */ + { + status = nx_packet_allocate(session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_pool_ptr, &packet_ptr, LWM2M_PACKET(session_ptr), NX_NO_WAIT); + } + if (status != NX_SUCCESS) + { + + /* Failed to allocate the packet */ + return(NX_NULL); + } + + /* Set nx_packet_append_ptr to the max message length */ + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_end - NX_PHYSICAL_TRAILER; + + /* Check for max LWM2M MTU */ + if ((packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_data_start) > + (NX_PHYSICAL_HEADER + NX_LWM2M_CLIENT_MTU)) + { + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_start + NX_PHYSICAL_HEADER + NX_LWM2M_CLIENT_MTU; + } + + /* Return pointer to the allocated packet */ + return(packet_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_register_options PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses parses the registering response options. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of registering response option */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_coap_option_parse */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static const VOID *_nx_lwm2m_client_get_register_options(NX_LWM2M_CLIENT_SESSION *session_ptr, const VOID *ptr, const VOID *ptr_max) +{ +UINT option; + + option = 0; + while (1) + { + const VOID *value_ptr; + UINT value_length; + + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if ((ptr == NX_NULL) || (option == NX_LWM2M_CLIENT_COAP_OPTION_NONE)) + { + break; + } + + if (option == NX_LWM2M_CLIENT_COAP_OPTION_LOCATION_PATH) + { + + /* Get uri-path of server */ + const CHAR *uri_start; + const CHAR *uri_end; + UINT uri_length; + + /* Path must begin with '/rd' */ + if (value_length != 2 || ((const CHAR *) value_ptr)[0] != 'r' || ((const CHAR *) value_ptr)[1] != 'd') + { + + /* Invalid path */ + return(NX_NULL); + } + + /* Get next part of the path */ + uri_start = ptr; + while (1) + { + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + + /* Invalid option */ + return(NX_NULL); + } + + if (option != NX_LWM2M_CLIENT_COAP_OPTION_LOCATION_PATH) + { + break; + } + } + + /* End of uri-path */ + uri_end = ptr; + + /* Get uri-path length */ + uri_length = (UINT)(uri_end - uri_start); + if (uri_length > NX_LWM2M_CLIENT_MAX_COAP_URI_PATH) + { + + /* XXX path too long */ + return(NX_NULL); + } + + /* Copy uri-path into session structure */ + session_ptr -> nx_lwm2m_client_session_uri_path_length = uri_length; + if (uri_length != 0) + { + memcpy(session_ptr -> nx_lwm2m_client_session_uri_path, uri_start, uri_length); /* Use case of memcpy is verified. */ + } + } + + /* Last option */ + if (option == NX_LWM2M_CLIENT_COAP_OPTION_NONE) + { + break; + } + + /* Ignore other options... */ + } + + return(ptr); +} + + +/* options in request packet */ +#define REQUEST_OPTIONS_INSTANCE_ID (1<<0) +#define REQUEST_OPTIONS_RESOURCE_ID (1<<1) +#define REQUEST_OPTIONS_ACCEPT (1<<2) +#define REQUEST_OPTIONS_CONTENT_FORMAT (1<<3) +#define REQUEST_OPTIONS_ROOT_PATH (1<<4) +#define REQUEST_OPTIONS_BS_PATH (1<<5) +#define REQUEST_OPTIONS_OBSERVE (1<<6) + +/* attributes */ +#define ATTR_FLAG_PMIN (1<<0) +#define ATTR_FLAG_PMAX (1<<1) +#define ATTR_FLAG_GT (1<<2) +#define ATTR_FLAG_LT (1<<3) +#define ATTR_FLAG_STP (1<<4) + +/* list of supported attributes */ +static const struct { + const CHAR * name; + CHAR name_len; + CHAR flag; +} attr_list[] = { + { "pmin", 4, ATTR_FLAG_PMIN }, + { "pmax", 4, ATTR_FLAG_PMAX }, + { "gt", 2, ATTR_FLAG_GT }, + { "lt", 2, ATTR_FLAG_LT }, + { "st", 2, ATTR_FLAG_STP } +}; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_request_options PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses request options. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* options_ptr Pointer to the request option */ +/* status_ptr Returned status */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of request option */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_coap_option_parse */ +/* _nx_lwm2m_client_strconv_parse_id */ +/* _nx_lwm2m_client_strconv_parse_int32 */ +/* _nx_lwm2m_client_strconv_parse_notify_number */ +/* memcmp */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static const VOID *_nx_lwm2m_client_get_request_options(NX_LWM2M_CLIENT_SESSION *session_ptr, const VOID *ptr, const VOID *ptr_max, NX_LWM2M_CLIENT_REQUEST_OPTIONS *options_ptr, UINT *status_ptr) +{ +UINT option; +NX_LWM2M_BOOL has_path; +const VOID *value_ptr; +UINT value_length; + + options_ptr -> flags = 0; + options_ptr -> attr_set = 0; + options_ptr -> attr_unset = 0; + has_path = NX_FALSE; + + option = 0; + while (1) + { + + /* Get next option */ + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + break; + } + + /* Uri-path option, Bootstrap session */ + if ((option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) && (session_ptr -> nx_lwm2m_client_session_server_instance_ptr == NX_NULL)) + { + + /* Look for '/bs' path */ + if (value_length == 2 && ((const CHAR *) value_ptr)[0] == 'b' && ((const CHAR *) value_ptr)[1] == 's') + { + + /* Get next option */ + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + break; + } + + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) + { + + /* Invalid path */ + *status_ptr = NX_LWM2M_CLIENT_NOT_FOUND; + return(NX_NULL); + } + + options_ptr -> flags |= REQUEST_OPTIONS_BS_PATH; + + has_path = NX_TRUE; + } + } + + /* Uri-Path option, Object location path */ + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) + { + + /* Path has the form: /{Object ID}/{Instance ID}/{Resource ID} */ + + /* Get {Object ID} */ + if (_nx_lwm2m_client_strconv_parse_id(value_ptr, value_length, &options_ptr -> object_id) != NX_SUCCESS) + { + + /* Invalid ID */ + *status_ptr = NX_LWM2M_CLIENT_NOT_FOUND; + return(NX_NULL); + } + has_path = NX_TRUE; + + /* Get next option */ + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + break; + } + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) + { + + /* Get {Instance ID} */ + if (_nx_lwm2m_client_strconv_parse_id(value_ptr, value_length, &options_ptr -> instance_id) != NX_SUCCESS) + { + + /* Invalid ID */ + *status_ptr = NX_LWM2M_CLIENT_NOT_FOUND; + return(NX_NULL); + } + options_ptr -> flags |= REQUEST_OPTIONS_INSTANCE_ID; + + /* Get next option */ + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + break; + } + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) + { + + /* Get {Resource ID} */ + if (_nx_lwm2m_client_strconv_parse_id(value_ptr, value_length, &options_ptr -> resource_id) != NX_SUCCESS) + { + + /* Invalid ID */ + *status_ptr = NX_LWM2M_CLIENT_NOT_FOUND; + return(NX_NULL); + } + options_ptr -> flags |= REQUEST_OPTIONS_RESOURCE_ID; + + /* Get next option */ + ptr = _nx_lwm2m_client_coap_option_parse(ptr, ptr_max, &option, &value_ptr, &value_length); + if (ptr == NX_NULL) + { + break; + } + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH) + { + + /* Invalid path */ + *status_ptr = NX_LWM2M_CLIENT_NOT_FOUND; + return(NX_NULL); + } + } + } + } /* NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH */ + + /* Accept / Content-Format / Observe */ + if (option == NX_LWM2M_CLIENT_COAP_OPTION_CONTENT_FORMAT || + option == NX_LWM2M_CLIENT_COAP_OPTION_ACCEPT || + option == NX_LWM2M_CLIENT_COAP_OPTION_OBSERVE) + { + UINT format; + UINT i; + const UCHAR *tmp_ptr; + + /* Read uint option value */ + format = 0; + tmp_ptr = value_ptr; + for (i = 0; i < value_length; i++) + { + format <<= 8; + format |= *tmp_ptr++; + } + + if (option == NX_LWM2M_CLIENT_COAP_OPTION_CONTENT_FORMAT) + { + if (options_ptr -> flags & REQUEST_OPTIONS_CONTENT_FORMAT) + { + + /* Invalid repeated option */ + ptr = NX_NULL; + break; + } + + options_ptr -> flags |= REQUEST_OPTIONS_CONTENT_FORMAT; + options_ptr -> content_format = format; + } + else if (option == NX_LWM2M_CLIENT_COAP_OPTION_ACCEPT) + { + if (options_ptr -> flags & REQUEST_OPTIONS_ACCEPT) + { + + /* Invalid repeated option */ + ptr = NX_NULL; + break; + } + + options_ptr -> flags |= REQUEST_OPTIONS_ACCEPT; + options_ptr -> accept = format; + } + else + { + if (options_ptr -> flags & REQUEST_OPTIONS_OBSERVE) + { + + /* Invalid repeated option */ + ptr = NX_NULL; + break; + } + + options_ptr -> flags |= REQUEST_OPTIONS_OBSERVE; + options_ptr -> observe = format; + } + } + + /* URI Query */ + if (option == NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY) + { + UINT i; + + /* check for known attribute */ + for (i = 0; i < sizeof(attr_list)/sizeof(attr_list[0]); i++) + { + if (value_length >= (UINT) attr_list[i].name_len && memcmp(value_ptr, attr_list[i].name, (UINT)(attr_list[i].name_len)) == 0) + { + + /* Must be of the form 'attr=value' or 'attr' */ + if (value_length > (UINT) attr_list[i].name_len && *((const CHAR *) value_ptr + attr_list[i].name_len) != '=') + { + + /* Ignore */ + continue; + } + + if (options_ptr -> attr_set & attr_list[i].flag || options_ptr -> attr_unset & attr_list[i].flag) + { + + /* Attribute already set */ + ptr = NX_NULL; + } + else + { + if (value_length == (UINT)(attr_list[i].name_len)) + { + + /* Unset attribute */ + options_ptr -> attr_unset |= attr_list[i].flag; + } + else + { + UINT status; + + /* Set attribute */ + options_ptr -> attr_set |= attr_list[i].flag; + + /* Get value */ + value_ptr = (const CHAR *) value_ptr + attr_list[i].name_len + 1; + value_length -= (UINT)(attr_list[i].name_len) + 1; + switch (attr_list[i].flag) + { + + case ATTR_FLAG_PMIN: + + status = _nx_lwm2m_client_strconv_parse_int32(value_ptr, value_length, &options_ptr -> pmin); + break; + + case ATTR_FLAG_PMAX: + + status = _nx_lwm2m_client_strconv_parse_int32(value_ptr, value_length, &options_ptr -> pmax); + break; + + case ATTR_FLAG_GT: + + status = _nx_lwm2m_client_strconv_parse_notify_number(value_ptr, value_length, &options_ptr -> gt); + break; + + case ATTR_FLAG_LT: + + status = _nx_lwm2m_client_strconv_parse_notify_number(value_ptr, value_length, &options_ptr -> lt); + break; + + case ATTR_FLAG_STP: + + status = _nx_lwm2m_client_strconv_parse_notify_number(value_ptr, value_length, &options_ptr -> stp); + break; + + default: + + /* XXX should not happen */ + status = NX_LWM2M_CLIENT_ERROR; + break; + } + + if (status != NX_SUCCESS) + { + + /* Invalid value */ + ptr = NX_NULL; + } + } + } + + break; + } + } + + if (ptr == NX_NULL) + { + break; + } + } + + /* Last option? */ + if (option == NX_LWM2M_CLIENT_COAP_OPTION_NONE) + { + break; + } + + /* Ignore other options... */ + } + + /* Bad request (XXX should we return bad option?) */ + if ((ptr == NX_NULL) || (!has_path && session_ptr -> nx_lwm2m_client_session_server_instance_ptr != NX_NULL)) + { + *status_ptr = NX_LWM2M_CLIENT_BAD_REQUEST; + return(NX_NULL); + } + + /* Root path? */ + if (!has_path) + { + options_ptr -> flags |= REQUEST_OPTIONS_ROOT_PATH; + } + + /* No instance ID ? */ + if (!(options_ptr -> flags & REQUEST_OPTIONS_INSTANCE_ID)) + { + options_ptr -> instance_id = NX_LWM2M_CLIENT_RESERVED_ID; + } + + /* No resource ID ? */ + if (!(options_ptr -> flags & REQUEST_OPTIONS_RESOURCE_ID)) + { + options_ptr -> resource_id = NX_LWM2M_CLIENT_RESERVED_ID; + } + + /* Success, return pointer to payload */ + *status_ptr = NX_SUCCESS; + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_parse_tlv_instance PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses values of a TLV instance. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* num_values_ptr The returned number */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_tlv_resource_parse */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_parse_tlv_instance(NX_LWM2M_CLIENT_SESSION *session_ptr, const UCHAR *ptr, const UCHAR *ptr_max, UINT *num_values_ptr) +{ +NX_LWM2M_CLIENT_RESOURCE *values; +UINT num_values; + + values = session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources; + num_values = 0; + while (ptr < ptr_max) + { + if (num_values >= NX_LWM2M_CLIENT_MAX_RESOURCES) + { + /* XXX too many values */ + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + ptr = _nx_lwm2m_client_tlv_resource_parse(ptr, ptr_max, values++); + if (ptr == NX_NULL) + { + /* invalid TLV encoding */ + return(NX_LWM2M_CLIENT_BAD_REQUEST); + } + + num_values++; + } + + /* return number of values */ + *num_values_ptr = num_values; + + /* return success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_object_observe PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers/deregisters observation. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* options_ptr Pointer to the request option */ +/* token_ptr Pointer to token */ +/* token_length The length of token */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_ptr Pointer to resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_get */ +/* _nx_lwm2m_client_session_notify_free */ +/* _nx_lwm2m_client_resource_notify_number_get */ +/* _nx_lwm2m_client_session_notify_attributes */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static NX_LWM2M_BOOL _nx_lwm2m_client_object_observe(NX_LWM2M_CLIENT_SESSION *session_ptr, const NX_LWM2M_CLIENT_REQUEST_OPTIONS *options_ptr, const VOID *token_ptr, UINT token_length, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; +UINT attr_flags; +NX_LWM2M_INT32 attr_pmin; +NX_LWM2M_INT32 attr_pmax; +NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_gt; +NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_lt; +NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_stp; + + if (!(options_ptr -> flags & REQUEST_OPTIONS_OBSERVE) || (options_ptr -> observe != 0 && options_ptr -> observe != 1)) + { + /* unknown operation */ + return(NX_FALSE); + } + + /* get the notify structure, allocate new one in case of registration */ + notify_ptr = _nx_lwm2m_client_session_notify_get(session_ptr, object_ptr, instance_ptr, resource_ptr == NX_NULL ? NX_LWM2M_CLIENT_RESERVED_ID : resource_ptr -> resource_id, options_ptr -> observe == 0); + + if (notify_ptr == NX_NULL) + { + /* notification doesn't exist, or allocation failure */ + return(NX_FALSE); + } + + /* clear current observer state, keep only attributes */ + notify_ptr -> notify_flags &= NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + + if (options_ptr -> observe != 0) + { + /* deregister, free notification if it doesn't store attributes */ + if (notify_ptr -> notify_flags == 0) + { + _nx_lwm2m_client_session_notify_free(session_ptr, notify_ptr); + } + + return(NX_FALSE); + } + + /* store observer information */ + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_OBSERVE | token_length; + if (token_length != 0) + { + /* save token */ + memcpy(notify_ptr -> notify_token, token_ptr, token_length); /* Use case of memcpy is verified. */ + } + + /* set format of response */ + if ((options_ptr -> flags & REQUEST_OPTIONS_ACCEPT) && options_ptr -> accept == NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ACCEPT_TLV; + } + + /* initialize last message ID with ID of last request (ensure it dosen't correspond to another notify message) */ + notify_ptr -> notify_last_id = session_ptr -> nx_lwm2m_client_session_request_id; + + /* set last response time */ + notify_ptr -> notify_last_time = tx_time_get(); + + /* set last number value */ + if (resource_ptr != NX_NULL) + { + _nx_lwm2m_client_resource_notify_number_get(resource_ptr, ¬ify_ptr -> notify_last_value); + } + + /* enable timer if pmax is defined */ + _nx_lwm2m_client_session_notify_attributes(session_ptr, notify_ptr, &attr_flags, &attr_pmin, &attr_pmax, &attr_gt, &attr_lt, &attr_stp); + if (!(attr_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX)) + { + /* get default maximum period from server object */ + attr_pmax = session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_max_period; + } + + if (attr_pmax > 0) + { + /* arm timer */ + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_TIMER; + notify_ptr -> notify_timer = notify_ptr -> notify_last_time + ((ULONG)attr_pmax * NX_IP_PERIODIC_RATE); + } + + return(NX_TRUE); +} + + +/* XXX */ +#define ACK_TIMEOUT (10 * NX_IP_PERIODIC_RATE) + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_observe_reset PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function resets the observation. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* msg_id The message ID */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_free */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_observe_reset(NX_LWM2M_CLIENT_SESSION *session_ptr, USHORT msg_id) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; +ULONG now; + + /* get current time */ + now = tx_time_get(); + + /* check if the ID corresponds to a previous notify message */ + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (notify_ptr != NX_NULL) + { + if ((notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_OBSERVE) && notify_ptr -> notify_last_id == msg_id && (LONG) (now - notify_ptr -> notify_last_time) < (LONG)ACK_TIMEOUT) + { + /* deregister the observer, clear current observer state, keep only attributes */ + notify_ptr -> notify_flags &= NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + + /* free notification if it doesn't store attributes */ + if (notify_ptr -> notify_flags == 0) + { + _nx_lwm2m_client_session_notify_free(session_ptr, notify_ptr); + } + + return; + } + + notify_ptr = notify_ptr -> notify_next; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_write_attributes PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes the object attributes. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* options_ptr Pointer to the request option */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_ptr Pointer to resource */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_free */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_write_attributes(NX_LWM2M_CLIENT_SESSION *session_ptr, const NX_LWM2M_CLIENT_REQUEST_OPTIONS *options_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* get the notify structure, allocate new one if some attributes are to be set */ + notify_ptr = _nx_lwm2m_client_session_notify_get(session_ptr, object_ptr, instance_ptr, resource_ptr == NX_NULL ? NX_LWM2M_CLIENT_RESERVED_ID : resource_ptr -> resource_id, options_ptr -> attr_set != 0); + + if (notify_ptr == NX_NULL) + { + /* notification doesn't exist, or allocation failure */ + return(options_ptr -> attr_set != 0 ? NX_LWM2M_CLIENT_NO_MEMORY : NX_SUCCESS); + } + + /* set attributes */ + if (options_ptr -> attr_set & ATTR_FLAG_PMIN) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN; + notify_ptr -> notify_attr_pmin = options_ptr -> pmin; + } + if (options_ptr -> attr_set & ATTR_FLAG_PMAX) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX; + notify_ptr -> notify_attr_pmax = options_ptr -> pmax; + } + if (options_ptr -> attr_set & ATTR_FLAG_GT) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ATTR_GT; + notify_ptr -> notify_attr_gt = options_ptr -> gt; + } + if (options_ptr -> attr_set & ATTR_FLAG_LT) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ATTR_LT; + notify_ptr -> notify_attr_lt = options_ptr -> lt; + } + if (options_ptr -> attr_set & ATTR_FLAG_STP) + { + notify_ptr -> notify_flags |= NX_LWM2M_CLIENT_NOTIFY_ATTR_STP; + notify_ptr -> notify_attr_stp = options_ptr -> stp; + } + + /* clear attributes */ + if (options_ptr -> attr_unset & ATTR_FLAG_PMIN) + { + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN); + } + if (options_ptr -> attr_unset & ATTR_FLAG_PMAX) + { + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX); + } + if (options_ptr -> attr_unset & ATTR_FLAG_GT) + { + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_ATTR_GT); + } + if (options_ptr -> attr_unset & ATTR_FLAG_LT) + { + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_ATTR_LT); + } + if (options_ptr -> attr_unset & ATTR_FLAG_STP) + { + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_ATTR_STP); + } + + /* free structure if all attributes and observe flag are cleared */ + if ((notify_ptr -> notify_flags & (NX_LWM2M_CLIENT_NOTIFY_OBSERVE|NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS)) == 0) + { + _nx_lwm2m_client_session_notify_free(session_ptr, notify_ptr); + } + + return(NX_SUCCESS); +} + + +/* Define the LWM2M operations */ +#define LWM2M_OPERATION_BS_WRITE 0 +#define LWM2M_OPERATION_BS_DELETE 1 +#define LWM2M_OPERATION_BS_DELETE_ALL 2 +#define LWM2M_OPERATION_BS_DISCOVER 3 +#define LWM2M_OPERATION_BS_FINISH 4 +#define LWM2M_OPERATION_READ 5 +#define LWM2M_OPERATION_DISCOVER 6 +#define LWM2M_OPERATION_WRITE_UPDATE 7 +#define LWM2M_OPERATION_WRITE_REPLACE 8 +#define LWM2M_OPERATION_WRITE_ATTRS 9 +#define LWM2M_OPERATION_EXECUTE 10 +#define LWM2M_OPERATION_CREATE 11 +#define LWM2M_OPERATION_DELETE 12 + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_receive PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a packet received by a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* packet_ptr Pointer to the received packet*/ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_coap_header_parse */ +/* _nx_lwm2m_client_session_state_update */ +/* _nx_lwm2m_client_get_register_options */ +/* _nx_lwm2m_client_observe_reset */ +/* _nx_lwm2m_client_object_ptr_get */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* _nx_lwm2m_client_tlv_resource_parse */ +/* _nx_lwm2m_client_object_observe */ +/* _nx_lwm2m_client_parse_tlv_instance */ +/* _nx_lwm2m_client_write_attributes */ +/* _nx_lwm2m_client_object_create_internal */ +/* _nx_lwm2m_client_object_delete_all */ +/* _nx_lwm2m_client_server_session_get */ +/* _nx_lwm2m_client_session_send_response */ +/* nx_packet_release */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_thread_entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* token and processing */ +/* confirmable response, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_receive(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_PACKET *packet_ptr) +{ +UCHAR msg_type; +UCHAR msg_code; +USHORT msg_id; +const VOID *token_ptr; +UINT token_length; +const UCHAR *ptr; +const UCHAR *ptr_max; +UINT i; + + /* check if we need to parse the packet */ + if (session_ptr -> nx_lwm2m_client_session_substate <= NX_LWM2M_CLIENT_SESSION_SUBSTATE_REGISTER || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DISABLED) + { + /* Discard packet */ + nx_packet_release(packet_ptr); + + /* End of processing */ + return; + } + +#ifndef NX_DISABLE_PACKET_CHAIN + /* Don't support packet chain. */ + if (packet_ptr -> nx_packet_next != NX_NULL) + { + + /* Discard packet */ + nx_packet_release(packet_ptr); + + /* End of processing */ + return; + } +#endif + + /* start of message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* end of message */ + ptr_max = packet_ptr -> nx_packet_append_ptr; + + /* Decode the CoAP header */ + ptr = _nx_lwm2m_client_coap_header_parse(ptr, ptr_max, &msg_type, &msg_code, &msg_id, &token_ptr, &token_length); + if (ptr != NX_NULL) + { + /* check type of message: */ + if ((msg_type == NX_LWM2M_CLIENT_COAP_TYPE_ACK) || (msg_type == NX_LWM2M_CLIENT_COAP_TYPE_RST) || + (msg_type == NX_LWM2M_CLIENT_COAP_TYPE_CON && (msg_code & NX_LWM2M_CLIENT_COAP_CLASS_MASK) != NX_LWM2M_CLIENT_COAP_CLASS_REQUEST)) + { + /* Response to our last request? */ + if (session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_REQUEST_SENT && + (session_ptr -> nx_lwm2m_client_session_request_id == msg_id || msg_type == NX_LWM2M_CLIENT_COAP_TYPE_CON)) + { + if (msg_type == NX_LWM2M_CLIENT_COAP_TYPE_RST || (msg_code & NX_LWM2M_CLIENT_COAP_CLASS_MASK) != NX_LWM2M_CLIENT_COAP_CLASS_SUCCESS) + { + /* Request failed, set error state */ + /* XXX get coap error code */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_ERROR; + _nx_lwm2m_client_session_state_update(session_ptr, session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING ? NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR : NX_LWM2M_CLIENT_SESSION_ERROR); + } + else if ((token_length == sizeof(session_ptr -> nx_lwm2m_client_session_token)) && + (memcmp(token_ptr, session_ptr -> nx_lwm2m_client_session_token, token_length) == 0)) /* Use case of memcmp is verified. */ + { + /* Success, update client state */ + switch (session_ptr -> nx_lwm2m_client_session_state) + { + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING: + + /* set state to bootstrap initiated */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED); + + break; + + case NX_LWM2M_CLIENT_SESSION_REGISTERING: + + /* get server location */ + ptr = _nx_lwm2m_client_get_register_options(session_ptr, ptr, ptr_max); + if (ptr == NX_NULL) + { + /* Invalid response */ + /* XXX define error code */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_ERROR; + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_ERROR); + + break; + } + + /* fall through */ + + case NX_LWM2M_CLIENT_SESSION_UPDATING: + + /* set state to registered */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_REGISTERED); + + break; + + case NX_LWM2M_CLIENT_SESSION_DISABLING: + + /* set state to disabled */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_DISABLED); + + break; + + case NX_LWM2M_CLIENT_SESSION_DEREGISTERING: + + /* set state to de-registered */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_DEREGISTERED); + + break; + + default: + + /* XXX SHOULD NOY GO HERE */ + NX_ASSERT(0); + + } + + /* Send an empty ACK to the response in confirmable type. */ + if (msg_type == NX_LWM2M_CLIENT_COAP_TYPE_CON) + { + _nx_lwm2m_client_session_send_response(session_ptr, 0, msg_id, NX_TRUE, NX_NULL, 0, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL); + } + } + + /* report new state to state callback */ + session_ptr -> nx_lwm2m_client_session_state_callback(session_ptr, session_ptr -> nx_lwm2m_client_session_state); + } + else if (msg_type == NX_LWM2M_CLIENT_COAP_TYPE_RST) + { + /* Reset notification? */ + _nx_lwm2m_client_observe_reset(session_ptr, msg_id); + } + } + else if ((msg_code >= NX_LWM2M_CLIENT_COAP_REQUEST_GET && msg_code <= NX_LWM2M_CLIENT_COAP_REQUEST_DELETE) && + (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERED || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING)) + { + + /* Handle request */ + NX_LWM2M_CLIENT_REQUEST_OPTIONS *options = &(session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_request_options); + UINT status; + UCHAR response_code; + UINT response_format = 0; + NX_LWM2M_BOOL observe = NX_FALSE; + NX_LWM2M_CLIENT_OBJECT *object_ptr; + NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr; + NX_LWM2M_CLIENT_RESOURCE resource; + NX_LWM2M_CLIENT_RESOURCE *resource_ptr; + UINT lwm2m_operation = 0; + NX_LWM2M_CLIENT_SESSION *state_changed_session_ptr; + UINT write_type; + UINT num_values; + + /* set pointer to session that has changed state */ + state_changed_session_ptr = NX_NULL; + + /* get request options */ + ptr = _nx_lwm2m_client_get_request_options(session_ptr, ptr, ptr_max, options, &status); + + /* Check Object ID/Instance ID/Resource ID */ + if (status == NX_SUCCESS) + { + /* get pointer to object */ + if (options->flags & (REQUEST_OPTIONS_BS_PATH|REQUEST_OPTIONS_ROOT_PATH)) + { + /* bootstrap specific paths, no target object */ + object_ptr = NX_NULL; + instance_ptr = NX_NULL; + resource_ptr = NX_NULL; + } + else + { + object_ptr = _nx_lwm2m_client_object_ptr_get(session_ptr -> nx_lwm2m_client_session_client_ptr, options->object_id); + if (object_ptr == NX_NULL) + { + /* object doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + + /* also clear instance and resource pointers */ + instance_ptr = NX_NULL; + resource_ptr = NX_NULL; + } + else + { + if (options->flags & REQUEST_OPTIONS_INSTANCE_ID) + { + /* get pointer to instance if it exists */ + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, options->instance_id); + + if (options->flags & REQUEST_OPTIONS_RESOURCE_ID) + { + /* get resource */ + resource_ptr = &resource; + if (options->flags & REQUEST_OPTIONS_CONTENT_FORMAT) + { + /* get resource value */ + if (options->content_format == NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN || options->content_format == NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM) + { + /* text/plain or octet-stream (opaque) */ + resource_ptr -> resource_id = options->resource_id; + resource_ptr -> resource_type = options->content_format == NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN ? NX_LWM2M_CLIENT_RESOURCE_TEXT : NX_LWM2M_CLIENT_RESOURCE_OPAQUE; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = ptr; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = (UINT)(ptr_max - ptr); + } + else if (options->content_format == NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) + { + + /* TLV resource value */ + if ((_nx_lwm2m_client_tlv_resource_parse(ptr, ptr_max, resource_ptr) == NX_NULL) || + (resource_ptr -> resource_id != options -> resource_id) || + ((resource_ptr -> resource_type != NX_LWM2M_CLIENT_RESOURCE_TLV) && + (resource_ptr -> resource_type != NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_TLV))) + { + + /* unsupported content format */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else + { + /* unsupported content format */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else + { + /* no content */ + resource_ptr -> resource_id = options->resource_id; + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_NONE; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = NX_NULL; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = 0; + } + } + else + { + resource_ptr = NX_NULL; + } + } + else + { + instance_ptr = NX_NULL; + resource_ptr = NX_NULL; + } + } + } + } + else + { + object_ptr = NX_NULL; + instance_ptr = NX_NULL; + resource_ptr = NX_NULL; + } + + if (status == NX_SUCCESS) + { + /* select the type of LWM2M operation: */ + + if (session_ptr -> nx_lwm2m_client_session_server_instance_ptr == NX_NULL) + { + /* Bootstrap session */ + + if (options->flags & REQUEST_OPTIONS_BS_PATH) + { + if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_POST) + { + /* POST /bs -> Bootstrap Finish */ + lwm2m_operation = LWM2M_OPERATION_BS_FINISH; + } + else + { + /* '/bs' path only allowed with POST method */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else if (options->flags & REQUEST_OPTIONS_ROOT_PATH) + { + if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_DELETE) + { + /* XXX delete / seems to be removed from the final LWM2M spec */ + /* keep it for now in case all servers are not updated */ + + /* DELETE / -> Bootstrap Delete All */ + lwm2m_operation = LWM2M_OPERATION_BS_DELETE_ALL; + } + else + if ((msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_GET) && + (options->flags & REQUEST_OPTIONS_ACCEPT) && + (options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT)) + { + /* DISCOVER / */ + lwm2m_operation = LWM2M_OPERATION_BS_DISCOVER; + } + else + { + /* '/' path only allowed with DELETE and DISCOVER method */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_GET) + { + if ((options->flags & REQUEST_OPTIONS_ACCEPT) && + (options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT) && + !(options->flags & REQUEST_OPTIONS_INSTANCE_ID)) + { + /* Bootstrap Discover */ + lwm2m_operation = LWM2M_OPERATION_BS_DISCOVER; + } + else + { + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_PUT) + { + if (resource_ptr == NX_NULL && + (!(options->flags & REQUEST_OPTIONS_CONTENT_FORMAT) || + options->content_format != NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV)) + { + /* Content format must be TLV */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + else + { + /* Bootstrap Write */ + lwm2m_operation = LWM2M_OPERATION_BS_WRITE; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_DELETE && + resource_ptr == NX_NULL) + { + /* Bootstrap Delete */ + lwm2m_operation = LWM2M_OPERATION_BS_DELETE; + } + else + { + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_GET) + { + if ((options->flags & REQUEST_OPTIONS_ACCEPT) && + (options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT)) + { + /* Discover */ + lwm2m_operation = LWM2M_OPERATION_DISCOVER; + } + else + { + /* Read */ + lwm2m_operation = LWM2M_OPERATION_READ; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_PUT) + { + if (options->flags & REQUEST_OPTIONS_CONTENT_FORMAT) + { + if (!(options->flags & REQUEST_OPTIONS_INSTANCE_ID)) + { + /* missing Instance ID */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + else if (resource_ptr == NX_NULL && options->content_format != NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) + { + /* Invalid content format */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + else + { + /* Write Replace */ + lwm2m_operation = LWM2M_OPERATION_WRITE_REPLACE; + } + } + else + { + /* Write Attributes */ + lwm2m_operation = LWM2M_OPERATION_WRITE_ATTRS; + } + } + else if (msg_code == NX_LWM2M_CLIENT_COAP_REQUEST_POST) + { + if (resource_ptr != NX_NULL) + { + if (resource_ptr -> resource_type != NX_LWM2M_CLIENT_RESOURCE_NONE && + resource_ptr -> resource_type != NX_LWM2M_CLIENT_RESOURCE_TEXT) + { + /* execute arguments must be in text/plain format */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + else + { + /* Execute */ + lwm2m_operation = LWM2M_OPERATION_EXECUTE; + } + } + else if (!(options->flags & REQUEST_OPTIONS_CONTENT_FORMAT) || + options->content_format != NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) + { + /* Invalid content format (must be TLV) */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + else if (options->flags & REQUEST_OPTIONS_INSTANCE_ID) + { + /* Write Update */ + lwm2m_operation = LWM2M_OPERATION_WRITE_UPDATE; + } + else + { + /* Create */ + lwm2m_operation = LWM2M_OPERATION_CREATE; + } + } + else /* NX_LWM2M_CLIENT_COAP_REQUEST_DELETE */ + { + if ((options->flags & REQUEST_OPTIONS_INSTANCE_ID) && + resource_ptr == NX_NULL) + { + /* Delete */ + lwm2m_operation = LWM2M_OPERATION_DELETE; + } + else + { + status = NX_LWM2M_CLIENT_BAD_REQUEST; + } + } + } + + /* Access to Security Object is forbidden except in bootstrap mode */ + if (status == NX_SUCCESS && + session_ptr -> nx_lwm2m_client_session_server_instance_ptr != NX_NULL && + object_ptr -> object_id == NX_LWM2M_CLIENT_SECURITY_OBJECT_ID) + { + status = NX_LWM2M_CLIENT_UNAUTHORIZED; + } + + /* check if the provided instance is valid */ + if (status == NX_SUCCESS && + (options->flags & REQUEST_OPTIONS_INSTANCE_ID) && + instance_ptr == NX_NULL && + (lwm2m_operation == LWM2M_OPERATION_READ || + lwm2m_operation == LWM2M_OPERATION_DISCOVER || + lwm2m_operation == LWM2M_OPERATION_WRITE_UPDATE || + lwm2m_operation == LWM2M_OPERATION_WRITE_REPLACE || + lwm2m_operation == LWM2M_OPERATION_WRITE_ATTRS || + lwm2m_operation == LWM2M_OPERATION_EXECUTE || + lwm2m_operation == LWM2M_OPERATION_DELETE)) + { + /* instance doesn't exist */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + + if (status == NX_SUCCESS) + { + + /* check for server initiated bootstrap */ + if ((lwm2m_operation == LWM2M_OPERATION_BS_WRITE || + lwm2m_operation == LWM2M_OPERATION_BS_DELETE || + lwm2m_operation == LWM2M_OPERATION_BS_DELETE_ALL || + lwm2m_operation == LWM2M_OPERATION_BS_DISCOVER) && + session_ptr -> nx_lwm2m_client_session_state < NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED) + { + /* set state to bootstrap initiated */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED); + + /* call state change callback */ + state_changed_session_ptr = session_ptr; + } + + /* do the LWM2M operation: */ + switch (lwm2m_operation) + { + + /* Read */ + case LWM2M_OPERATION_READ: + + if (resource_ptr != NX_NULL) + { + /* read single value */ + num_values = 1; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_READ, object_ptr, instance_ptr, resource_ptr, &num_values, NX_NULL, 0); + if (status == NX_SUCCESS) + { + /* select the content-format of the response: */ + if (options->flags & REQUEST_OPTIONS_ACCEPT) + { + /* check if format is acceptable: */ + if ((options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) || + (options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN && resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_STRING) || + (options->accept == NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM && resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_OPAQUE)) + { + /* use requested format */ + response_format = options->accept; + } + else + { + /* invalid format */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + } + else if (resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_STRING) + { + /* text value */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN; + } + else if (resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_OPAQUE) + { + /* opaque value */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM; + } + else + { + /* use tlv for other values */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV; + } + } + } + else if ((options->flags & REQUEST_OPTIONS_ACCEPT) && options->accept != NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV) + { + /* invalid format */ + status = NX_LWM2M_CLIENT_NOT_ACCEPTABLE; + } + else + { + /* return instance(s) in tlv format */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV; + } + + /* Observe option */ + if (status == NX_SUCCESS && (options->flags & REQUEST_OPTIONS_OBSERVE)) + { + /* Register */ + observe = _nx_lwm2m_client_object_observe(session_ptr, options, token_ptr, token_length, object_ptr, instance_ptr, resource_ptr); + } + + break; + + /* Discover */ + case LWM2M_OPERATION_BS_DISCOVER: + case LWM2M_OPERATION_DISCOVER: + + if (resource_ptr != NX_NULL) + { + /* return single resource, check if it's exists */ + NX_LWM2M_CLIENT_RESOURCE *resources = session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources; + UINT num_infos; + + /* get list of supported resources */ + num_infos = NX_LWM2M_CLIENT_MAX_RESOURCES; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DISCOVER, object_ptr, instance_ptr, resources, &num_infos, NX_NULL, 0); + if (status == NX_SUCCESS) + { + + /* find resource ID */ + for (i = 0; i < num_infos; i++) + { + if (resources[i].resource_id == resource_ptr -> resource_id) + { + break; + } + } + if (i < num_infos) + { + if (resources[i].resource_type == NX_LWM2M_CLIENT_RESOURCE_MULTIPLE) + { + /* set dimension of multiple resource */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE; + resource_ptr -> resource_dim = resources[i].resource_dim; + } + else + { + /* not a multiple resource */ + resource_ptr -> resource_type = NX_LWM2M_CLIENT_RESOURCE_NONE; + } + } + else + { + /* resource ID not found */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + } + } + + if (status == NX_SUCCESS) + { + /* return list of IDs and attributes in link format */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT; + } + + break; + + /* Write */ + case LWM2M_OPERATION_WRITE_UPDATE: + case LWM2M_OPERATION_WRITE_REPLACE: + + if (resource_ptr != NX_NULL) + { + + /* Set write type */ + if (lwm2m_operation == LWM2M_OPERATION_WRITE_REPLACE) + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_RESOURCE; + else + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE; + + /* write a single value */ + num_values = 1; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, resource_ptr, &num_values, &write_type, sizeof(UINT)); + } + else + { + /* the TLV payload must contains an object instance */ + + /* parse list of TLV values */ + status = _nx_lwm2m_client_parse_tlv_instance(session_ptr, ptr, ptr_max, &num_values); + if (status == NX_SUCCESS) + { + + /* Set write type */ + if (lwm2m_operation == LWM2M_OPERATION_WRITE_REPLACE) + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE; + else + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE; + + /* write resources values */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, + session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, + &num_values, &write_type, sizeof(UINT)); + } + } + + break; + + /* Write Attributes */ + case LWM2M_OPERATION_WRITE_ATTRS: + + if (resource_ptr != NX_NULL) + { + /* check that resource exists and is readable */ + num_values = 1; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_READ, object_ptr, instance_ptr, resource_ptr, &num_values, NX_NULL, 0); + if (status != NX_SUCCESS) + { + break; + } + } + + /* set attributes */ + status = _nx_lwm2m_client_write_attributes(session_ptr, options, object_ptr, instance_ptr, resource_ptr); + break; + + /* Execute */ + case LWM2M_OPERATION_EXECUTE: + + /* call object method */ + num_values = 1; + if (resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_TEXT) + { + /* pass the text arguments to the method */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_EXECUTE, object_ptr, instance_ptr, resource_ptr, &num_values, + (VOID *)resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr, + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length); + } + else + { + /* no arguments */ + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_EXECUTE, object_ptr, instance_ptr, resource_ptr, &num_values, NX_NULL, 0); + } + + break; + + /* Bootstrap Write */ + case LWM2M_OPERATION_BS_WRITE: + + if (resource_ptr != NX_NULL) + { + /* Write a single value */ + if (instance_ptr == NX_NULL) + { + /* Create the instance */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, &(options->instance_id), 1, resource_ptr, NX_TRUE); + } + else + { + /* Replace resource of an existing instance */ + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP; + num_values = 1; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, resource_ptr, &num_values, &write_type, sizeof(UINT)); + } + + break; + } + else if (options->flags & REQUEST_OPTIONS_INSTANCE_ID) + { + /* Write a list of values to an instance */ + + /* parse list of TLV values */ + status = _nx_lwm2m_client_parse_tlv_instance(session_ptr, ptr, ptr_max, &num_values); + if (status == NX_SUCCESS) + { + if (instance_ptr == NX_NULL) + { + /* Create the instance */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, &(options->instance_id), num_values, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, NX_TRUE); + } + else + { + /* Write to an existing instance */ + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, + session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, + &num_values, &write_type, sizeof(UINT)); + } + } + break; + } + + /* fall through */ + + /* Create */ + case LWM2M_OPERATION_CREATE: + /* check if the value contains an instance ID */ + if (ptr == ptr_max) + { + /* empty TLV payload */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + + break; + } + + if ((ptr[0] & NX_LWM2M_CLIENT_TLV_TYPE_ID_TYPE_MASK) != NX_LWM2M_CLIENT_TLV_OBJECT_INSTANCE) + { + /* Create a new instance with an assigned ID */ + + /* get list of values */ + status = _nx_lwm2m_client_parse_tlv_instance(session_ptr, ptr, ptr_max, &num_values); + if (status == NX_SUCCESS) + { + /* create new instance */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, NX_NULL, num_values, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, NX_FALSE); + } + } + else + { + /* create instance(s) */ + while (ptr < ptr_max) + { + NX_LWM2M_CLIENT_RESOURCE instance; + + /* get object instance */ + ptr = _nx_lwm2m_client_tlv_resource_parse(ptr, ptr_max, &instance); + if ((ptr == NX_NULL) || (instance.resource_type != NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE_TLV)) + { + /* Invalid TLV value */ + status = NX_LWM2M_CLIENT_BAD_REQUEST; + + break; + } + + /* get list of values */ + status = _nx_lwm2m_client_parse_tlv_instance(session_ptr, instance.resource_value.resource_bufferdata.resource_buffer_ptr, (const UCHAR *) instance.resource_value.resource_bufferdata.resource_buffer_ptr + instance.resource_value.resource_bufferdata.resource_buffer_length, &num_values); + if (status != NX_SUCCESS) + { + break; + } + + /* check if instance already exists */ + instance_ptr = _nx_lwm2m_client_object_instance_ptr_get(object_ptr, instance.resource_id); + if (instance_ptr != NX_NULL) + { + if (lwm2m_operation == LWM2M_OPERATION_BS_WRITE) + { + /* write to existing instance (Bootstrap Write) */ + write_type = NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP; + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_WRITE, object_ptr, instance_ptr, + session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, + &num_values, &write_type, sizeof(UINT)); + } + else + { + /* instance already exist */ + status = NX_LWM2M_CLIENT_ALREADY_EXIST; + } + } + else + { + /* create new instance */ + status = _nx_lwm2m_client_object_create_internal(object_ptr, &instance.resource_id, num_values, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_temp_resources, NX_FALSE); + } + if (status != NX_SUCCESS) + { + break; + } + } + } + + break; + + /* Delete */ + case LWM2M_OPERATION_BS_DELETE: + if (!(options->flags & REQUEST_OPTIONS_INSTANCE_ID)) { + /* delete all instances of the object, except security instance of bootstrap server */ + _nx_lwm2m_client_object_delete_all(session_ptr -> nx_lwm2m_client_session_client_ptr, object_ptr, session_ptr -> nx_lwm2m_client_session_server_id); + + break; + } + + /* fall through */ + + case LWM2M_OPERATION_DELETE: + { + NX_LWM2M_CLIENT_OBJECT_INSTANCE *server_instance_ptr; + + /* save pointer to instance if it's a server object */ + if (object_ptr -> object_id == NX_LWM2M_CLIENT_SERVER_OBJECT_ID) + { + server_instance_ptr = instance_ptr; + } + else + { + server_instance_ptr = NX_NULL; + } + + /* Delete the instance */ + if (instance_ptr != NX_NULL) + { + status = object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DELETE, object_ptr, instance_ptr, NX_NULL, NX_NULL, NX_NULL, 0); + } + + /* Terminate lwm2m session if it's server instance is deleted */ + if (server_instance_ptr != NX_NULL && status == NX_SUCCESS) + { + NX_LWM2M_CLIENT_SESSION *deleted_session_ptr; + + deleted_session_ptr = _nx_lwm2m_client_server_session_get(session_ptr -> nx_lwm2m_client_session_client_ptr, server_instance_ptr); + + if (deleted_session_ptr != NX_NULL) + { + /* clear pointer to deleted instance */ + deleted_session_ptr -> nx_lwm2m_client_session_server_instance_ptr = NX_NULL; + + if (deleted_session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_ERROR) + { + /* change session state to error */ + deleted_session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_SERVER_INSTANCE_DELETED; + _nx_lwm2m_client_session_state_update(deleted_session_ptr, NX_LWM2M_CLIENT_SESSION_ERROR); + + /* report state change to application */ + state_changed_session_ptr = deleted_session_ptr; + } + } + } + + break; + } + + /* Delete All */ + case LWM2M_OPERATION_BS_DELETE_ALL: + + /* Delete all instances, except security instance of bootstrap server */ + _nx_lwm2m_client_object_delete_all(session_ptr -> nx_lwm2m_client_session_client_ptr, NX_NULL, session_ptr -> nx_lwm2m_client_session_server_id); + + break; + + /* Bootstrap Finish */ + case LWM2M_OPERATION_BS_FINISH: + + break; + + default: + + status = NX_LWM2M_CLIENT_BAD_REQUEST; + + break; + + } + + } + + /* set response code */ + switch (status) + { + + /* Successful operation */ + case NX_SUCCESS: + + /* Return status code corresponding to the operation: */ + switch (lwm2m_operation) + { + + /* Read, Discover -> 2.05 Content */ + case LWM2M_OPERATION_READ: + case LWM2M_OPERATION_DISCOVER: + case LWM2M_OPERATION_BS_DISCOVER: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_CONTENT; + break; + + /* Create -> 2.01 Created */ + case LWM2M_OPERATION_CREATE: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_CREATED; + break; + + /* Delete -> 2.02 Deleted */ + case LWM2M_OPERATION_DELETE: + case LWM2M_OPERATION_BS_DELETE: + case LWM2M_OPERATION_BS_DELETE_ALL: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_DELETED; + break; + + /* Other operations: 2.04 Changed */ + default: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_CHANGED; + break; + + } + + break; + + /* 4.01 Unauthorized */ + case NX_LWM2M_CLIENT_UNAUTHORIZED: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_UNAUTHORIZED; + break; + + /* 4.04 Not Found */ + case NX_LWM2M_CLIENT_NOT_FOUND: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_NOT_FOUND; + break; + + /* 4.05 Method Not Allowed */ + case NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_METHOD_NOT_ALLOWED; + break; + + /* 4.06 Not Acceptable */ + case NX_LWM2M_CLIENT_NOT_ACCEPTABLE: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_NOT_ACCEPTABLE; + break; + + /* 5.00 Internal server error */ + case NX_LWM2M_CLIENT_BUFFER_TOO_SMALL: + case NX_LWM2M_CLIENT_NO_MEMORY: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_INTERNAL_SERVER_ERROR; + break; + + /* Other errors: 4.00 Bad Request */ + case NX_LWM2M_CLIENT_BAD_REQUEST: + default: + + response_code = NX_LWM2M_CLIENT_COAP_STATUS_BAD_REQUEST; + break; + + } + + /* Send response */ + _nx_lwm2m_client_session_send_response(session_ptr, response_code, msg_id, NX_TRUE, token_ptr, token_length, observe, response_format, object_ptr, instance_ptr, resource_ptr); + + if (status == NX_SUCCESS && lwm2m_operation == LWM2M_OPERATION_BS_FINISH) + { + + /* update session state */ + if (session_ptr -> nx_lwm2m_client_session_state < NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED) + { + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED); + + state_changed_session_ptr = session_ptr; + } + } + + /* Rearm bootstrap idle timer if bootstrap is initiated */ + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED) + { + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + NX_LWM2M_CLIENT_BOOTSTRAP_IDLE_TIMER; + } + + /* Report session state changes to application */ + if (state_changed_session_ptr != NX_NULL) + { + state_changed_session_ptr -> nx_lwm2m_client_session_state_callback(state_changed_session_ptr, session_ptr -> nx_lwm2m_client_session_state); + } + } + } + + /* End of message processing, release packet */ + nx_packet_release(packet_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_register PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers the Client to a LWM2M server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* server_id The Short Server ID of the */ +/* LWM2M server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_register(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port) +{ +#ifdef NX_SECURE_ENABLE_DTLS + return(_nx_lwm2m_client_session_start(session_ptr, NX_FALSE, server_id, ip_address, port, NX_NULL)); +#else + return(_nx_lwm2m_client_session_start(session_ptr, NX_FALSE, server_id, ip_address, port)); +#endif /* NX_SECURE_ENABLE_DTLS */ +} + +#ifdef NX_SECURE_ENABLE_DTLS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_register_dtls PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers the Client to a LWM2M server using a */ +/* secure channel. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* server_id The Short Server ID of the */ +/* LWM2M server */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* dtls_session_ptr The pointer to the DTLS */ +/* session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_start */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_register_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr) +{ + return(_nx_lwm2m_client_session_start(session_ptr, NX_FALSE, server_id, ip_address, port, dtls_session_ptr)); +} + +#endif /* NX_SECURE_ENABLE_DTLS */ + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_register_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the server and security information for the next */ +/* registration step. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* security_instance_id Security instance ID */ +/* server_id Server ID */ +/* server_uri Server URI */ +/* server_uri_len Length of server URI */ +/* security_mode Security Mode */ +/* pub_key_or_id Public key or ID */ +/* pub_key_or_id_len Length of public key or ID */ +/* server_pub_key Server public key */ +/* server_pub_key_len Length of server public key */ +/* secret_key Secret key */ +/* secret_key_len Length of secret key */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_object_ptr_get */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_register_info_get(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT security_instance_id, NX_LWM2M_ID *server_id, CHAR **server_uri, UINT *server_uri_len, UCHAR *security_mode, + UCHAR **pub_key_or_id, UINT *pub_key_or_id_len, UCHAR **server_pub_key, UINT *server_pub_key_len, UCHAR **secret_key, UINT *secret_key_len) +{ +UINT status; +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; +NX_LWM2M_CLIENT_OBJECT *object_ptr; +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr; +NX_LWM2M_CLIENT_SECURITY_INSTANCE *security_instance_ptr; + + /* Acquire the LWM2M Client Mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Get pointer to the Object Instance */ + object_ptr = _nx_lwm2m_client_object_ptr_get(client_ptr, NX_LWM2M_CLIENT_SECURITY_OBJECT_ID); + if (object_ptr == NX_NULL) + { + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Get first instance */ + instance_ptr = object_ptr -> object_instances; + + while (instance_ptr != NX_NULL) + { + + /* If instance ID is NX_LWM2M_CLIENT_RESERVED_ID, find the first non-bootstrap server; + If not, find the non-bootstrap server with the corresponded instance ID */ + if (!(((NX_LWM2M_CLIENT_SECURITY_INSTANCE *)instance_ptr) -> security_instance_bootstrap) && + ((security_instance_id == NX_LWM2M_CLIENT_RESERVED_ID) || + (security_instance_id == instance_ptr -> object_instance_id))) + { + break; + } + + /* Next instance */ + instance_ptr = instance_ptr -> object_instance_next; + } + + if (instance_ptr == NX_NULL) + { + + /* Last instance */ + status = NX_LWM2M_CLIENT_NOT_FOUND; + } + else + { + + /* Found the instance of requested ID */ + security_instance_ptr = (NX_LWM2M_CLIENT_SECURITY_INSTANCE *)instance_ptr; + + /* Set server ID */ + *server_id = security_instance_ptr -> security_instance_server_id; + + /* Set server URI */ + *server_uri = security_instance_ptr -> security_instance_server_uri; + *server_uri_len = security_instance_ptr -> security_instance_server_uri_len; + + /* Set security mode */ + *security_mode = security_instance_ptr -> security_instance_mode; + + /* Set security keys */ + if (pub_key_or_id && pub_key_or_id_len) + { + *pub_key_or_id = security_instance_ptr -> security_instance_pub_key_or_id; + *pub_key_or_id_len = security_instance_ptr -> security_instance_pub_key_or_id_len; + } + + if (server_pub_key && server_pub_key_len) + { + *server_pub_key = security_instance_ptr -> security_instance_server_pub_key; + *server_pub_key_len = security_instance_ptr -> security_instance_server_pub_key_len; + } + + if (secret_key && secret_key_len) + { + *secret_key = security_instance_ptr -> security_instance_secret_key; + *secret_key_len = security_instance_ptr -> security_instance_secret_key_len; + } + + status = NX_SUCCESS; + } + } + + /* Release the LWM2M Client Mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Return the status of the operation */ + return(status); +} +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_send PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a packets from a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* packet_ptr Pointer to the packet to send */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_secure_dtls_session_send */ +/* nxd_udp_socket_send */ +/* nx_packet_release */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_request */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_send(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_PACKET *packet_ptr) +{ +UINT status; + +#ifdef NX_SECURE_ENABLE_DTLS + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + + /* Send the packet through the DTLS session */ + status = nx_secure_dtls_session_send(session_ptr -> nx_lwm2m_client_session_dtls_session, packet_ptr, &session_ptr -> nx_lwm2m_client_session_server_address, session_ptr -> nx_lwm2m_client_session_server_port); + } + else +#endif /* NX_SECURE_ENABLE_DTLS */ + { + + /* Send the packet through the CoAP socket */ + status = nxd_udp_socket_send((NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_coap_socket, packet_ptr, &session_ptr -> nx_lwm2m_client_session_server_address, session_ptr -> nx_lwm2m_client_session_server_port); + } + + if (status != NX_SUCCESS) + { + + /* Cannot send packet, discard */ + nx_packet_release(packet_ptr); + + /* Return invalid server address error */ + return(NX_LWM2M_CLIENT_ADDRESS_ERROR); + } + + /* Return success */ + return(NX_SUCCESS); +} + +/* Initial retransmit timer */ +#define RETRANSMIT_TIMER 2*NX_IP_PERIODIC_RATE + +/* Max retransmit timer */ +#define RETRANSMIT_TIMER_MAX 10*NX_IP_PERIODIC_RATE + +/* Max retransmit count */ +#define RETRANSMIT_COUNT 5 + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_send_request PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a request packet from a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* first Set to True if it's not a */ +/* retransmission */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_packet_allocate */ +/* _nx_lwm2m_client_coap_option_header_add */ +/* _nx_lwm2m_client_strconv_format_int32 */ +/* _nx_lwm2m_client_binding_mode_string_get */ +/* _nx_lwm2m_client_corelink_path_add */ +/* _nx_lwm2m_client_session_send */ +/* tx_time_get */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_state_update */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* token and processing */ +/* confirmable response, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_send_request(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL first) +{ +NX_PACKET *packet_ptr; +UINT status; +UINT i; + + /* Check that current state is valid for sending a request */ + NX_ASSERT(session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DISABLING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DEREGISTERING); + + status = NX_SUCCESS; + + if (first) + { + + /* New request */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_REQUEST_SENT; + + /* Initialize retransmission paramters */ + session_ptr -> nx_lwm2m_client_session_retransmit_count = RETRANSMIT_COUNT; + session_ptr -> nx_lwm2m_client_session_retransmit_timer = RETRANSMIT_TIMER; + + /* Get new request ID */ + session_ptr -> nx_lwm2m_client_session_request_id = ++session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_request_id; + } + else + { + + /* Retransmit request */ + + /* Update retransmission counter */ + session_ptr -> nx_lwm2m_client_session_retransmit_count--; + if (session_ptr -> nx_lwm2m_client_session_retransmit_count == 0) + { + + /* Max number of retransmissions reached, */ + /* Report error to application */ + status = NX_LWM2M_CLIENT_TIMED_OUT; + } + else + { + + /* Increase retransmission timer */ + session_ptr -> nx_lwm2m_client_session_retransmit_timer *= 2; + if (session_ptr -> nx_lwm2m_client_session_retransmit_timer > RETRANSMIT_TIMER_MAX) + { + session_ptr -> nx_lwm2m_client_session_retransmit_timer = RETRANSMIT_TIMER_MAX; + } + } + } + + if (status == NX_SUCCESS) + { + UCHAR *ptr; + UINT last_option; + UINT update_flags; + + /* Allocate a pack for the CoAP request message */ + packet_ptr = _nx_lwm2m_client_session_packet_allocate(session_ptr); + if (packet_ptr == NX_NULL) + { + + /* Failed to allocate the packet, will try to retransmited later */ + return(NX_SUCCESS); + } + + /* Start of message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* Check that the packet is large enought for the CoAP header */ + if (ptr + 4 > packet_ptr -> nx_packet_append_ptr) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + + /* Set CoAP header and type of request */ + *ptr++ = NX_LWM2M_CLIENT_COAP_VERSION_1 | NX_LWM2M_CLIENT_COAP_TYPE_CON | NX_LWM2M_CLIENT_COAP_TOKEN_LEN; + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DISABLING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DEREGISTERING) + { + + /* De-register */ + *ptr++ = NX_LWM2M_CLIENT_COAP_REQUEST_DELETE; + } + else + { + + /* Bootstrap request, Register, Update */ + *ptr++ = NX_LWM2M_CLIENT_COAP_REQUEST_POST; + } + *ptr++ = (UCHAR) (session_ptr -> nx_lwm2m_client_session_request_id >> 8); + *ptr++ = (UCHAR) session_ptr -> nx_lwm2m_client_session_request_id; + + /* Set token */ + for (i = 0; i < sizeof(session_ptr -> nx_lwm2m_client_session_token); i++) + { + session_ptr -> nx_lwm2m_client_session_token[i] = (UCHAR) NX_RAND(); + *ptr++ = session_ptr -> nx_lwm2m_client_session_token[i]; + } + + /* Add options */ + last_option = 0; + + /* Uri-Path: always of the form /bs or /rd [/...] */ + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH, 2); + if ((ptr == NX_NULL) || ((ptr + 2) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING) + { + *ptr++ = 'b'; + *ptr++ = 's'; + } + else + { + *ptr++ = 'r'; + *ptr++ = 'd'; + } + } + } + + if ((status == NX_SUCCESS) && + ((session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING) || + (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DISABLING) || + (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DEREGISTERING))) + { + + /* Check packet payload */ + if ((ptr + session_ptr -> nx_lwm2m_client_session_uri_path_length) > packet_ptr -> nx_packet_append_ptr) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + + /* Add server Uri-Path option(s) if we are registered */ + memcpy(ptr, session_ptr -> nx_lwm2m_client_session_uri_path, session_ptr -> nx_lwm2m_client_session_uri_path_length); /* Use case of memcpy is verified. */ + ptr += session_ptr -> nx_lwm2m_client_session_uri_path_length; + } + } + + /* Get Register/Update optional parameters and payload */ + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERING || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING) + { + update_flags = session_ptr -> nx_lwm2m_client_session_flags; + } + else + { + update_flags = 0; + } + + /* Add Content-Format option if we include a payload */ + if ((status == NX_SUCCESS) && (update_flags & NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST)) + { + + /* Check packet payload */ + if ((ptr + NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT) > packet_ptr -> nx_packet_append_ptr) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_CONTENT_FORMAT, 1); + *ptr++ = NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT; + } + } + + /* Uri-Query options: */ + + /* ep={Endpoint Client Name} only in Bootstrap request and Register */ + if ((status == NX_SUCCESS) && + ((session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING) || + (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERING))) + { + UINT client_name_length; + + client_name_length = session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_name_length; + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY, 3 + client_name_length); + if ((ptr == NX_NULL) || ((ptr + 3 + client_name_length) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + *ptr++ = 'e'; + *ptr++ = 'p'; + *ptr++ = '='; + memcpy(ptr, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_name, client_name_length); /* Use case of memcpy is verified. */ + ptr += client_name_length; + } + } + + /* lt={Lifetime} */ + if ((status == NX_SUCCESS) && (update_flags & NX_LWM2M_CLIENT_SESSION_UPDATE_LIFETIME)) + { + CHAR lifetime[NX_LWM2M_CLIENT_STRCONV_INT32_MAXLEN]; + UINT lifetime_length; + + NX_ASSERT(session_ptr -> nx_lwm2m_client_session_server_instance_ptr != NX_NULL); + + /* Format lifetime value */ + lifetime_length = _nx_lwm2m_client_strconv_format_int32(lifetime, sizeof(lifetime), session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_lifetime); + + /* Write option */ + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY, 3 + lifetime_length); + if ((ptr == NX_NULL) || ((ptr + 3 + lifetime_length) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + *ptr++ = 'l'; + *ptr++ = 't'; + *ptr++ = '='; + memcpy(ptr, lifetime, lifetime_length); /* Use case of memcpy is verified. */ + ptr += lifetime_length; + } + } + + /* sms={MSISDN} */ + if ((status == NX_SUCCESS) && (update_flags & NX_LWM2M_CLIENT_SESSION_UPDATE_MSISDN)) + { + UINT msisdn_length; + + /* MSISDN is allowed to be NULL if device has no SMS number */ + msisdn_length = session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_msisdn_length; + + /* Write option */ + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY, 4 + msisdn_length); + if ((ptr == NX_NULL) || ((ptr + 4 + msisdn_length) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + *ptr++ = 's'; + *ptr++ = 'm'; + *ptr++ = 's'; + *ptr++ = '='; + if (msisdn_length != 0) + { + memcpy(ptr, session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_msisdn, msisdn_length); /* Use case of memcpy is verified. */ + ptr += msisdn_length; + } + } + } + + /* lwm2m={version} only in Register */ + if ((status == NX_SUCCESS) && (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERING)) + { + static const CHAR version[] = "lwm2m=1.0"; + UINT version_length = sizeof(version)-1; + + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY, version_length); + if ((ptr == NX_NULL) || ((ptr + 4 + version_length) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + memcpy(ptr, version, version_length); /* Use case of memcpy is verified. */ + ptr += version_length; + } + } + + /* b={binding} */ + if ((status == NX_SUCCESS) && (update_flags & NX_LWM2M_CLIENT_SESSION_UPDATE_BINDING_MODE)) + { + const CHAR *binding; + UINT binding_length; + + NX_ASSERT(session_ptr -> nx_lwm2m_client_session_server_instance_ptr != NX_NULL); + + /* Get binding mode from server object instance */ + binding = _nx_lwm2m_client_binding_mode_string_get(session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_binding, &binding_length); + + /* Write option */ + ptr = _nx_lwm2m_client_coap_option_header_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY, 2 + binding_length); + if ((ptr == NX_NULL) || ((ptr + 2 + binding_length) > packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + *ptr++ = 'b'; + *ptr++ = '='; + memcpy(ptr, binding, binding_length); /* Use case of memcpy is verified. */ + ptr += binding_length; + } + } + + /* Add payload (list of objects) */ + if ((status == NX_SUCCESS) && (update_flags & NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST)) + { + NX_LWM2M_CLIENT_OBJECT *object_ptr; + UINT object_first; + + /* Check packet payload */ + if (ptr >= packet_ptr -> nx_packet_append_ptr) + { + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + else + { + + /* Mark the begining of the payload */ + *ptr++ = NX_LWM2M_CLIENT_COAP_PAYLOAD_MARKER; + + /* Write the list of objects (do not include security object 0) */ + object_first = NX_TRUE; + object_ptr = (NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_server; + while (object_ptr != NX_NULL) + { + if (object_ptr -> object_instances == NX_NULL) + { + + /* Object with no instance */ + + /* Write separator */ + if (!object_first) + { + if (ptr >= packet_ptr -> nx_packet_append_ptr) + { + + /* Not enought space */ + ptr = NX_NULL; + break; + } + *ptr++ = ','; + } + + /* write object path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) packet_ptr -> nx_packet_append_ptr, object_ptr -> object_id, NX_LWM2M_CLIENT_RESERVED_ID, NX_LWM2M_CLIENT_RESERVED_ID); + + } + else + { + NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr; + + /* List object instances */ + instance_ptr = object_ptr -> object_instances; + while (instance_ptr != NX_NULL) + { + + /* Write separator */ + if (!object_first) + { + if (ptr >= packet_ptr -> nx_packet_append_ptr) + { + + /* Not enought space */ + ptr = NX_NULL; + break; + } + *ptr++ = ','; + } + + /* Write object instance path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) packet_ptr -> nx_packet_append_ptr, object_ptr -> object_id, instance_ptr -> object_instance_id, NX_LWM2M_CLIENT_RESERVED_ID); + if (ptr == NX_NULL) + { + break; + } + + /* Reset the flag because an instance was added. */ + object_first = NX_FALSE; + + /* Get next instance */ + instance_ptr = instance_ptr -> object_instance_next; + } + } + + if (ptr == NX_NULL) + { + break; + } + + object_first = NX_FALSE; + object_ptr = object_ptr -> object_next; + } + + if (ptr == NX_NULL) + { + + /* Cannot write payload */ + status = NX_LWM2M_CLIENT_BUFFER_TOO_SMALL; + } + } + } + + if (status == NX_SUCCESS) + { + + /* Set final length of message */ + packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr); + packet_ptr -> nx_packet_append_ptr = ptr; + + /* Transmit packet to UDP/DTLS */ + status = _nx_lwm2m_client_session_send(session_ptr, packet_ptr); + } + else + { + + /* Failed to make request, release packet */ + nx_packet_release(packet_ptr); + } + } + + if (status != NX_SUCCESS) + { + + /* Cannot send the packet to the server due to a network error, abort session */ + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING) + { + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR; + } + else + { + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_ERROR; + } + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_IDLE; + session_ptr -> nx_lwm2m_client_session_error = status; + } + else + { + + /* Rearm retransmission timer */ + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + session_ptr -> nx_lwm2m_client_session_retransmit_timer; + } + + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_attributes PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets attributes. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_id Resource ID */ +/* flags_ptr Returned flags */ +/* pmin_ptr Returned pmin */ +/* pmax_ptr Returned pmax */ +/* gt_ptr Returned gt */ +/* lt_ptr Returned lt */ +/* stp_ptr Returned stp */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_get */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_discover_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_get_attributes(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, UINT *flags_ptr, NX_LWM2M_INT32 *pmin_ptr, NX_LWM2M_INT32 *pmax_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *gt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *lt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *stp_ptr) +{ +NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* Get notifications structure for the object/instance/resource */ + notify_ptr = _nx_lwm2m_client_session_notify_get(session_ptr, object_ptr, instance_ptr, resource_id, NX_FALSE); + + if (notify_ptr == NX_NULL) + { + + /* No attributes */ + return; + } + + /* Update flags */ + *flags_ptr |= notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS; + + /* Update attributes */ + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN) + { + *pmin_ptr = notify_ptr -> notify_attr_pmin; + } + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX) + { + *pmax_ptr = notify_ptr -> notify_attr_pmax; + } + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_GT) + { + *gt_ptr = notify_ptr -> notify_attr_gt; + } + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_LT) + { + *lt_ptr = notify_ptr -> notify_attr_lt; + } + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_STP) + { + *stp_ptr = notify_ptr -> notify_attr_stp; + } +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_discover_resource PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes discover resource. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* resource_ptr Pointer to resource */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of payload */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_corelink_path_add */ +/* _nx_lwm2m_client_get_attributes */ +/* _nx_lwm2m_client_corelink_attributes_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* compiler warnings, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +static UCHAR *_nx_lwm2m_client_discover_resource(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR *ptr, UCHAR *ptr_max, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +UINT flags; +NX_LWM2M_INT32 pmin = 0; +NX_LWM2M_INT32 pmax = 0; +NX_LWM2M_CLIENT_NOTIFY_NUMBER gt = 0; +NX_LWM2M_CLIENT_NOTIFY_NUMBER lt = 0; +NX_LWM2M_CLIENT_NOTIFY_NUMBER stp = 0; + + /* Write resource path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) ptr_max, object_ptr -> object_id, instance_ptr -> object_instance_id, resource_ptr -> resource_id); + if (ptr == NX_NULL) + { + + /* Not enougth space in buffer */ + return(NX_NULL); + } + + /* Reset attributes flags */ + flags = 0; + + /* Get object attributes */ + _nx_lwm2m_client_get_attributes(session_ptr, object_ptr, NX_NULL, NX_LWM2M_CLIENT_RESERVED_ID, &flags, &pmin, &pmax, >, <, &stp); + + /* Get instance attributes */ + _nx_lwm2m_client_get_attributes(session_ptr, object_ptr, instance_ptr, NX_LWM2M_CLIENT_RESERVED_ID, &flags, &pmin, &pmax, >, <, &stp); + + /* Get resource attributes */ + _nx_lwm2m_client_get_attributes(session_ptr, object_ptr, instance_ptr, resource_ptr -> resource_id, &flags, &pmin, &pmax, >, <, &stp); + + /* Write resource attributes */ + return((UCHAR *)_nx_lwm2m_client_corelink_attributes_add((CHAR *) ptr, (CHAR *) ptr_max, 0, resource_ptr, flags, pmin, pmax, gt, lt, stp)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_discover_instance PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes discover single instance. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* show_attributes Flag of show attributes */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of payload */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_get */ +/* _nx_lwm2m_client_corelink_path_add */ +/* _nx_lwm2m_client_corelink_attributes_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_discover_instances */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UCHAR *_nx_lwm2m_client_discover_instance(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR *ptr, UCHAR *ptr_max, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_BOOL show_attributes) +{ +NX_LWM2M_CLIENT_RESOURCE infos[NX_LWM2M_CLIENT_MAX_RESOURCES]; +UINT num_infos; +UINT i; + + /* get list of resources for this instance */ + num_infos = NX_LWM2M_CLIENT_MAX_RESOURCES; + if (object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DISCOVER, object_ptr, instance_ptr, infos, &num_infos, NX_NULL, 0) != NX_SUCCESS) + { + /* cannot get list of resources */ + return(NX_NULL); + } + + for (i = 0; i < num_infos; i++) + { + if (i != 0) + { + /* check buffer space for separator */ + if (ptr >= ptr_max) + { + ptr = NX_NULL; + + break; + } + + /* write separator */ + *ptr++ = ','; + } + + /* write resource path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) ptr_max, object_ptr -> object_id, instance_ptr -> object_instance_id, infos[i].resource_id); + if (ptr == NX_NULL) + { + /* not enougth space in buffer */ + return(NX_NULL); + } + + /* write resource attributes */ + if (show_attributes) + { + NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* get resources attributes */ + notify_ptr = _nx_lwm2m_client_session_notify_get(session_ptr, object_ptr, instance_ptr, infos[i].resource_id, NX_FALSE); + + /* write resource attributes */ + if (notify_ptr != NX_NULL) + { + /* write notification attributes */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_attributes_add((CHAR *) ptr, (CHAR *) ptr_max, 0, &infos[i], notify_ptr -> notify_flags, notify_ptr -> notify_attr_pmin, notify_ptr -> notify_attr_pmax, notify_ptr -> notify_attr_gt, notify_ptr -> notify_attr_lt, notify_ptr -> notify_attr_stp); + } + else + { + /* write only dimension attribute if the resource is multiple */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_attributes_add((CHAR *) ptr, (CHAR *) ptr_max, 0, &infos[i], 0, 0, 0, 0, 0, 0); + } + if (ptr == NX_NULL) + { + /* not enougth space in buffer */ + break; + } + } + } + + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_discover_instances PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes discover object instances. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of payload */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_notify_get */ +/* _nx_lwm2m_client_corelink_path_add */ +/* _nx_lwm2m_client_corelink_attributes_add */ +/* _nx_lwm2m_client_discover_instance */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UCHAR *_nx_lwm2m_client_discover_instances(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR *ptr, UCHAR *ptr_max, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ + NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + /* get object/instance attributes */ + notify_ptr = _nx_lwm2m_client_session_notify_get(session_ptr, object_ptr, instance_ptr, NX_LWM2M_CLIENT_RESERVED_ID, NX_FALSE); + + if (notify_ptr != NX_NULL && (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS) != 0) + { + /* write object/instance path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) ptr_max, object_ptr -> object_id, instance_ptr == NX_NULL ? NX_LWM2M_CLIENT_RESERVED_ID : instance_ptr -> object_instance_id, NX_LWM2M_CLIENT_RESERVED_ID); + + /* write object/instance attributes */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_attributes_add((CHAR *) ptr, (CHAR *) ptr_max, 0, NX_NULL, notify_ptr -> notify_flags, notify_ptr -> notify_attr_pmin, notify_ptr -> notify_attr_pmax, notify_ptr -> notify_attr_gt, notify_ptr -> notify_attr_lt, notify_ptr -> notify_attr_stp); + if ((ptr == NX_NULL) || (ptr >= ptr_max)) + { + /* not enougth space in buffer */ + return(NX_NULL); + } + + /* write separator */ + *ptr++ = ','; + } + + if (instance_ptr != NX_NULL) + { + /* return a single instance */ + return _nx_lwm2m_client_discover_instance(session_ptr, ptr, ptr_max, object_ptr, instance_ptr, NX_TRUE); + } + + /* return all instances */ + instance_ptr = object_ptr -> object_instances; + while (instance_ptr != NX_NULL) + { + /* write instance information */ + ptr = _nx_lwm2m_client_discover_instance(session_ptr, ptr, ptr_max, object_ptr, instance_ptr, NX_FALSE); + + if (ptr == NX_NULL) + { + break; + } + + /* get next instance */ + instance_ptr = instance_ptr -> object_instance_next; + + if (instance_ptr != NX_NULL) + { + /* check buffer space for separator */ + if (ptr >= ptr_max) + { + ptr = NX_NULL; + + break; + } + + /* write separator */ + *ptr++ = ','; + } + } + + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_bootstrap_discover PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes bootstrap discover response. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LwM2M session */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* object_ptr Pointer to object */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of payload */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_corelink_attributes_add */ +/* _nx_lwm2m_client_corelink_path_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UCHAR *_nx_lwm2m_client_bootstrap_discover(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR *ptr, UCHAR *ptr_max, NX_LWM2M_CLIENT_OBJECT *object_ptr) +{ +NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr; + + /* get first instance */ + instance_ptr = object_ptr -> object_instances; + + if (instance_ptr == NX_NULL) + { + /* object with no instance, just report object path */ + + /* write separator */ + if (ptr >= ptr_max) + { + return(NX_NULL); + } + *ptr++ = ','; + + /* write object path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) ptr_max, object_ptr -> object_id, NX_LWM2M_CLIENT_RESERVED_ID, NX_LWM2M_CLIENT_RESERVED_ID); + + return(ptr); + } + + /* write list of instances */ + while (instance_ptr != NX_NULL) + { + NX_LWM2M_ID ssid; + + /* write separator */ + if (ptr >= ptr_max) + { + return(NX_NULL); + } + *ptr++ = ','; + + /* write object/instance path */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_path_add((CHAR *) ptr, (CHAR *) ptr_max, object_ptr -> object_id, instance_ptr -> object_instance_id, NX_LWM2M_CLIENT_RESERVED_ID); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + + /* check for short server id attribute */ +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + if (object_ptr == (NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_security) + { + if (((NX_LWM2M_CLIENT_SECURITY_INSTANCE *) instance_ptr) -> security_instance_bootstrap) + { + ssid = 0; /* bootstrap server */ + } + else + { + ssid = ((NX_LWM2M_CLIENT_SECURITY_INSTANCE *) instance_ptr) -> security_instance_server_id; + } + } + else +#endif + if (object_ptr == (NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_server) + { + ssid = ((NX_LWM2M_CLIENT_SERVER_INSTANCE *) instance_ptr) -> server_instance_short_id; + } + else + { + ssid = 0; + } + if (ssid != 0) + { + /* write attribute */ + ptr = (UCHAR *) _nx_lwm2m_client_corelink_attributes_add((CHAR *) ptr, (CHAR *) ptr_max, ssid, NX_NULL, 0, 0, 0, 0, 0, 0); + if (ptr == NX_NULL) + { + return(NX_NULL); + } + } + + /* get next instance */ + instance_ptr = instance_ptr -> object_instance_next; + } + + return(ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_read_instance PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes reading object instance. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LwM2M client */ +/* ptr Pointer to the start of buffer*/ +/* ptr_max Pointer to the end of buffer */ +/* object_ptr Pointer to object */ +/* instance_ptr Pointer to object instance */ +/* is_object Flag of reading object */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of payload */ +/* */ +/* CALLS */ +/* */ +/* memcpy */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UCHAR *_nx_lwm2m_client_read_instance(NX_LWM2M_CLIENT *client_ptr, UCHAR *ptr, UCHAR *ptr_max, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, UINT is_object) +{ +NX_LWM2M_CLIENT_RESOURCE *resources = client_ptr -> nx_lwm2m_client_temp_resources; +UINT num_resources; +UINT i; +NX_LWM2M_CLIENT_RESOURCE object_resource; + + /* Discover to get info of all the resources */ + num_resources = NX_LWM2M_CLIENT_MAX_RESOURCES; + if (object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_DISCOVER, object_ptr, instance_ptr, resources, &num_resources, NX_NULL, 0) != NX_SUCCESS) + { + return(NX_NULL); + } + + /* Remove unreadble resources */ + for (i = 0; i < num_resources;) + { + if (!(resources[i].resource_operation & NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ)) + { + if (i == (num_resources - 1)) + { + num_resources--; + break; + } + + memcpy(&resources[i], &resources[num_resources - 1], sizeof(NX_LWM2M_CLIENT_RESOURCE)); /* Use case of memcpy is verified. */ + num_resources--; + } + else + { + i++; + } + } + + /* Read resources */ + if ((num_resources == 0) || + (object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_READ, object_ptr, instance_ptr, resources, &num_resources, NX_NULL, 0) != NX_SUCCESS)) + { + return(NX_NULL); + } + + /* Add resources to payload */ + if (is_object) + { + object_resource.resource_id = instance_ptr -> object_instance_id; + object_resource.resource_type = NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE; + object_resource.resource_dim = (UCHAR)num_resources; + object_resource.resource_value.resource_bufferdata.resource_buffer_ptr = resources; + object_resource.resource_value.resource_bufferdata.resource_buffer_length = num_resources * sizeof(NX_LWM2M_CLIENT_RESOURCE); + + ptr = _nx_lwm2m_client_tlv_resource_add(ptr, ptr_max, &object_resource); + } + else + { + for (i = 0; i < num_resources; i++) + { + ptr = _nx_lwm2m_client_tlv_resource_add(ptr, ptr_max, &resources[i]); + } + } + + return(ptr); + +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_send_response PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a response packet from a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* code The response code */ +/* id The message id */ +/* ack Set to True if it's an ACK, */ +/* send a NON otherwise */ +/* token_ptr Pointer to the token */ +/* token_length Length of token */ +/* observe Set to true to include an */ +/* Observe option */ +/* format Format of payload: */ +/* object_ptr Pointer to Object to include */ +/* as payload */ +/* instance_ptr Pointer to Object Instance */ +/* resource_ptr Pointer to Object Resource */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_packet_allocate */ +/* _nx_lwm2m_client_coap_option_uint_add */ +/* _nx_lwm2m_client_bootstrap_discover */ +/* _nx_lwm2m_client_discover_resource */ +/* _nx_lwm2m_client_discover_instances */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_read_instance */ +/* _nx_lwm2m_client_session_send */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_send_response(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR code, USHORT id, NX_LWM2M_BOOL ack, const VOID *token_ptr, UINT token_length, NX_LWM2M_BOOL observe, UINT format, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ + NX_PACKET *packet_ptr; + UCHAR *ptr; + + /* allocate a pack for the CoAP request message */ + packet_ptr = _nx_lwm2m_client_session_packet_allocate(session_ptr); + if (packet_ptr == NX_NULL) + { + /* Failed to allocate the packet */ + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* start of message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* Check that the packet is large enought for the CoAP header */ + if (ptr + 4 + token_length > packet_ptr -> nx_packet_append_ptr) + { + nx_packet_release(packet_ptr); + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* set CoAP header */ + *ptr++ = (UCHAR)((UINT)NX_LWM2M_CLIENT_COAP_VERSION_1 | (UINT)(ack ? NX_LWM2M_CLIENT_COAP_TYPE_ACK : NX_LWM2M_CLIENT_COAP_TYPE_NON) | token_length); + *ptr++ = code; + *ptr++ = (UCHAR) (id >> 8); + *ptr++ = (UCHAR) id; + if (token_length > 0) + { + memcpy(ptr, token_ptr, token_length); /* Use case of memcpy is verified. */ + ptr += token_length; + } + + /* add content */ + if (code == NX_LWM2M_CLIENT_COAP_STATUS_CONTENT) + { + UINT last_option; + UCHAR *coap_header_end_ptr; + + /* save pointer to end of coap header */ + coap_header_end_ptr = ptr; + + /* initialize last option number */ + last_option = 0; + + /* Include Observe option */ + if (observe) + { + ULONG sequence; + + /* generate 24-bit sequence number from system clock */ + sequence = tx_time_get() & 0xffffff; + + /* add option */ + ptr = _nx_lwm2m_client_coap_option_uint_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_OBSERVE, sequence); + if (ptr == NX_NULL) + { + nx_packet_release(packet_ptr); + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + } + + /* Include Content-Format option */ + ptr = _nx_lwm2m_client_coap_option_uint_add(ptr, packet_ptr -> nx_packet_append_ptr, &last_option, NX_LWM2M_CLIENT_COAP_OPTION_CONTENT_FORMAT, format); + if ((ptr == NX_NULL) || (ptr >= packet_ptr -> nx_packet_append_ptr)) + { + nx_packet_release(packet_ptr); + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + /* end of options */ + *ptr++ = NX_LWM2M_CLIENT_COAP_PAYLOAD_MARKER; + + /* write payload */ + switch (format) + { + + case NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT: + + /* Return list of IDs and attributes */ + if (session_ptr -> nx_lwm2m_client_session_server_instance_ptr == NX_NULL) + { + /* Bootstrap Discover */ + + /* Check packet payload */ + if ((ptr + 11) > packet_ptr -> nx_packet_append_ptr) + { + ptr = NX_NULL; + break; + } + + /* write enabler version */ + memcpy(ptr, "lwm2m=\"1.0\"", 11); /* Use case of memcpy is verified. */ + ptr += 11; + + /* write list of object instances */ + if (object_ptr == NX_NULL) + { + /* discover all objects */ + NX_LWM2M_CLIENT_OBJECT *current_ptr; +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + current_ptr = (NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_security; +#else + current_ptr = (NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_server; +#endif + while (current_ptr != NX_NULL) + { + ptr = _nx_lwm2m_client_bootstrap_discover(session_ptr, ptr, packet_ptr -> nx_packet_append_ptr, current_ptr); + if (ptr == NX_NULL) + { + break; + } + + /* get next object */ + current_ptr = current_ptr -> object_next; + } + } + else + { + /* discover single object */ + ptr = _nx_lwm2m_client_bootstrap_discover(session_ptr, ptr, packet_ptr -> nx_packet_append_ptr, object_ptr); + } + } + else if (resource_ptr != NX_NULL) + { + /* return attributes of a single resource */ + ptr = _nx_lwm2m_client_discover_resource(session_ptr, ptr, packet_ptr -> nx_packet_append_ptr, object_ptr, instance_ptr, resource_ptr); + } + else + { + /* return attributes of object instance(s) */ + ptr = _nx_lwm2m_client_discover_instances(session_ptr, ptr, packet_ptr -> nx_packet_append_ptr, object_ptr, instance_ptr); + } + break; + + case NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN: + + /* Return single text string value */ + if (resource_ptr != NX_NULL && + resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_STRING) + { + UINT length; + + length = resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length; + if (ptr + length > packet_ptr -> nx_packet_append_ptr) + { + /* payload too big */ + ptr = NX_NULL; + } + else if (length != 0) + { + memcpy(ptr, resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr, length); /* Use case of memcpy is verified. */ + ptr += length; + } + } + break; + + case NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM: + + /* Return single opaque value */ + if (resource_ptr != NX_NULL && + resource_ptr -> resource_type == NX_LWM2M_CLIENT_RESOURCE_OPAQUE) + { + if (ptr + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length > packet_ptr -> nx_packet_append_ptr) + { + /* payload too big */ + ptr = NX_NULL; + } + else if (resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length != 0) + { + memcpy(ptr, resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr, resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length); /* Use case of memcpy is verified. */ + ptr += resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length; + } + } + break; + + case NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV: + + if (resource_ptr != NX_NULL) + { + /* Return single value */ + ptr = _nx_lwm2m_client_tlv_resource_add(ptr, packet_ptr -> nx_packet_append_ptr, resource_ptr); + } + else if (instance_ptr != NX_NULL) + { + /* Return full instance */ + ptr = _nx_lwm2m_client_read_instance(session_ptr -> nx_lwm2m_client_session_client_ptr, ptr, packet_ptr -> nx_packet_append_ptr, object_ptr, instance_ptr, NX_FALSE); + } + else + { + /* Return all instances */ + instance_ptr = object_ptr -> object_instances; + while (instance_ptr != NX_NULL) + { + ptr = _nx_lwm2m_client_read_instance(session_ptr -> nx_lwm2m_client_session_client_ptr, ptr, packet_ptr -> nx_packet_append_ptr, object_ptr, instance_ptr, NX_TRUE); + + if (ptr == NX_NULL) + { + break; + } + + instance_ptr = instance_ptr -> object_instance_next; + } + } + break; + + default: + + /* Unknown format */ + break; + } + + if (ptr == NX_NULL) + { + /* failed to write payload, change response code */ + /* XXX is there a better error code? */ + packet_ptr -> nx_packet_prepend_ptr[1] = NX_LWM2M_CLIENT_COAP_STATUS_INTERNAL_SERVER_ERROR; + + /* send only coap header */ + ptr = coap_header_end_ptr; + } + } + + /* set final length of message */ + packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr); + packet_ptr -> nx_packet_append_ptr = ptr; + + /* Transmit packet to UDP/DTLS */ + return(_nx_lwm2m_client_session_send(session_ptr, packet_ptr)); +} + +#ifdef NX_SECURE_ENABLE_DTLS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* coaps_message_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes secure CoAP socket receive notification. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to the CoAP socket */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set */ +/* */ +/* CALLED BY */ +/* */ +/* UDP stack */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID coaps_message_notify(NX_UDP_SOCKET *socket_ptr) +{ + + /* Get pointer to LWM2M Client */ + NX_LWM2M_CLIENT *client_ptr = ((NX_LWM2M_CLIENT_SOCKET *) socket_ptr) -> client_ptr; + + /* Set Secure CoAP Message event flag */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_COAPS_MESSAGE, TX_OR); +} +#endif /* NX_SECURE_ENABLE_DTLS */ + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_start PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts a LWM2M session with a Bootstrap server or a */ +/* LWM2M device management server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* bootstrap Set to True if it's a */ +/* bootstrap session */ +/* server_id The Bootstrap Security ID or */ +/* the Short Server ID */ +/* ip_address The IP address of the server */ +/* port The UDP port of the server */ +/* dtls_session_ptr The pointer to the DTLS */ +/* session if COAPS is used */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* tx_event_flags_set */ +/* _nx_lwm2m_client_session_state_update */ +/* _nx_lwm2m_client_resource_info_set */ +/* _nx_lwm2m_client_resource_integer32_set */ +/* _nx_lwm2m_client_object_create_internal */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* _nx_lwm2m_client_object_delete_all */ +/* _nx_lwm2m_client_resource_boolean_set */ +/* nx_udp_socket_create */ +/* nx_udp_socket_bind */ +/* nx_udp_socket_delete */ +/* nx_udp_socket_receive_notify */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +#ifdef NX_SECURE_ENABLE_DTLS +UINT _nx_lwm2m_client_session_start(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL bootstrap, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr) +#else +UINT _nx_lwm2m_client_session_start(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL bootstrap, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port) +#endif /* NX_SECURE_ENABLE_DTLS */ +{ +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; +UINT status; +NX_LWM2M_CLIENT_SERVER_INSTANCE *server_instance_ptr; +NX_LWM2M_ID instance_id; +NX_LWM2M_CLIENT_RESOURCE *resources = client_ptr -> nx_lwm2m_client_temp_resources; + + status = NX_SUCCESS; + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Clear previous state resources */ + if (session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_INIT) + { + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_INIT); + } + + if (!bootstrap) + { + + /* find LWM2M server instance corresponding to the short server ID */ + server_instance_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *) client_ptr -> nx_lwm2m_client_server.server_object.object_instances; + while (server_instance_ptr != NX_NULL) + { + if (server_instance_ptr -> server_instance_short_id == server_id) + { + break; + } + + server_instance_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *) server_instance_ptr -> server_instance.object_instance_next; + } + + if (server_instance_ptr == NX_NULL) + { + + /* Create a server instance */ + /* Setup the info for register server */ + _nx_lwm2m_client_resource_info_set(&resources[0], NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resources[0], server_id); + _nx_lwm2m_client_resource_info_set(&resources[1], NX_LWM2M_CLIENT_SERVER_LIFETIME_ID, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resources[1], NX_LWM2M_CLIENT_LIFE_TIME); + + /* Create a server instance for register server */ + instance_id = NX_LWM2M_CLIENT_RESERVED_ID; + status = _nx_lwm2m_client_object_create_internal(&(client_ptr -> nx_lwm2m_client_server.server_object), + &instance_id, 2, resources, NX_TRUE); + if (status) + { + return(status); + } + + /* Get the pointer of created server instace */ + server_instance_ptr = (NX_LWM2M_CLIENT_SERVER_INSTANCE *)_nx_lwm2m_client_object_instance_ptr_get(&(client_ptr -> nx_lwm2m_client_server.server_object), instance_id); + } + } + else + { + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + /* Clear all the security instances */ + if (client_ptr -> nx_lwm2m_client_security.security_object.object_instances != NX_NULL) + { + _nx_lwm2m_client_object_delete_all(client_ptr, &(client_ptr -> nx_lwm2m_client_security.security_object), NX_LWM2M_CLIENT_RESERVED_ID); + } + + /* Setup the info for bootstrap server */ + _nx_lwm2m_client_resource_info_set(&resources[0], NX_LWM2M_CLIENT_SECURITY_BOOTSTRAP_ID, NX_NULL); + _nx_lwm2m_client_resource_boolean_set(&resources[0], NX_TRUE); + _nx_lwm2m_client_resource_info_set(&resources[1], NX_LWM2M_CLIENT_SECURITY_HOLD_OFF_ID, NX_NULL); + _nx_lwm2m_client_resource_integer32_set(&resources[1], NX_LWM2M_CLIENT_HOLD_OFF); + + /* Create a security instance for bootstrap server */ + instance_id = server_id; + status = _nx_lwm2m_client_object_create_internal(&(client_ptr -> nx_lwm2m_client_security.security_object), + &instance_id, 2, resources, NX_TRUE); + if (status) + { + return(status); + } +#endif + + /* Bootstrap server, no related instance */ + server_instance_ptr = NX_NULL; + } + + if (status == NX_SUCCESS) + { + + /* Set pointer to Server Object Instance */ + session_ptr -> nx_lwm2m_client_session_server_instance_ptr = server_instance_ptr; + + /* Set address of server */ + session_ptr -> nx_lwm2m_client_session_server_address = *ip_address; + + /* Set port number */ + session_ptr -> nx_lwm2m_client_session_server_port = port; + + /* Set security/short server ID */ + session_ptr -> nx_lwm2m_client_session_server_id = server_id; + + /* Set substate to 'bootstrap' or 'register' */ + session_ptr -> nx_lwm2m_client_session_substate = bootstrap ? NX_LWM2M_CLIENT_SESSION_SUBSTATE_BOOTSTRAP : NX_LWM2M_CLIENT_SESSION_SUBSTATE_REGISTER; + + /* Reset error code */ + session_ptr -> nx_lwm2m_client_session_error = NX_SUCCESS; + +#ifdef NX_SECURE_ENABLE_DTLS + if (dtls_session_ptr != NX_NULL) + { + + /* Create UDP socket for the DTLS session */ + status = nx_udp_socket_create(client_ptr -> nx_lwm2m_client_ip_ptr, (NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, "LWM2M Client Secure CoAP Socket", NX_LWM2M_CLIENT_SOCKET_TOS, NX_DONT_FRAGMENT, NX_LWM2M_CLIENT_SOCKET_TTL, NX_LWM2M_CLIENT_SOCKET_QUEUE_MAX); + if (status != NX_SUCCESS) + { + status = NX_LWM2M_CLIENT_ERROR; + } + else + { + + /* Set the local port of the UDP socket*/ + status = nx_udp_socket_bind((NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, NX_ANY_PORT, NX_NO_WAIT); + if (status != NX_SUCCESS) + { + status = NX_LWM2M_CLIENT_PORT_UNAVAILABLE; + + nx_udp_socket_delete((NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket); + } + else + { + + /* Set the COAPS receive notify callback */ + session_ptr -> nx_lwm2m_client_session_dtls_socket.client_ptr = client_ptr; + nx_udp_socket_receive_notify((NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, coaps_message_notify); + + /* Set the DTLS session pointer */ + session_ptr -> nx_lwm2m_client_session_dtls_session = dtls_session_ptr; + } + } + } +#endif /* NX_SECURE_ENABLE_DTLS */ + } + + /* Release the client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + if (status == NX_SUCCESS) + { + + /* Wakeup client thread */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_state_update PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the state of a LWM2M session. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* state The new state of the session */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* nx_secure_dtls_client_session_start */ +/* _nx_lwm2m_client_session_cleanup */ +/* _nx_lwm2m_client_session_send_request */ +/* _nx_lwm2m_client_object_instance_ptr_get */ +/* tx_time_get */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_delete */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_delete */ +/* _nx_lwm2m_client_session_start */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_state_update(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state) +{ +#ifdef NX_SECURE_ENABLE_DTLS +UINT status; +#endif +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +NX_LWM2M_INT32 hold_off = 0; +#endif + + /* Update state and sub-state of session */ + session_ptr -> nx_lwm2m_client_session_state = state; + + switch (state) + { + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING: + +#ifdef NX_SECURE_ENABLE_DTLS + /* DTLS session */ + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + + /* Establish the DTLS session */ + status = nx_secure_dtls_client_session_start(session_ptr -> nx_lwm2m_client_session_dtls_session, (NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, + &(session_ptr -> nx_lwm2m_client_session_server_address), session_ptr -> nx_lwm2m_client_session_server_port, NX_LWM2M_CLIENT_DTLS_START_TIMEOUT); + if (status != NX_SUCCESS) + { + + /* Failed to connect to DTLS server */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_DTLS_ERROR; + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR; + _nx_lwm2m_client_session_cleanup(session_ptr); + return; + } + } +#endif + + /* Send the first request */ + _nx_lwm2m_client_session_send_request(session_ptr, NX_TRUE); + + return; + + case NX_LWM2M_CLIENT_SESSION_REGISTERING: + +#ifdef NX_SECURE_ENABLE_DTLS + /* DTLS session */ + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + + /* Establish the DTLS session */ + status = nx_secure_dtls_client_session_start(session_ptr -> nx_lwm2m_client_session_dtls_session, (NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, + &(session_ptr -> nx_lwm2m_client_session_server_address), session_ptr -> nx_lwm2m_client_session_server_port, NX_LWM2M_CLIENT_DTLS_START_TIMEOUT); + if (status != NX_SUCCESS) + { + + /* Failed to connect to DTLS server */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_DTLS_ERROR; + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_ERROR; + _nx_lwm2m_client_session_cleanup(session_ptr); + return; + } + } +#endif + + /* Send lifetime, binding mode and list of objects in request */ + session_ptr -> nx_lwm2m_client_session_flags |= NX_LWM2M_CLIENT_SESSION_UPDATE_LIFETIME|NX_LWM2M_CLIENT_SESSION_UPDATE_BINDING_MODE|NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST; + + /* Send MSISDN parameter only if defined */ + if (session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_msisdn != NX_NULL) + { + session_ptr -> nx_lwm2m_client_session_flags |= NX_LWM2M_CLIENT_SESSION_UPDATE_MSISDN; + } + else + { + session_ptr -> nx_lwm2m_client_session_flags &= (UINT)(~NX_LWM2M_CLIENT_SESSION_UPDATE_MSISDN); + } + + /* Reset Uri-Path of server */ + session_ptr -> nx_lwm2m_client_session_uri_path_length = 0; + + /* Send the first request */ + _nx_lwm2m_client_session_send_request(session_ptr, NX_TRUE); + + return; + + case NX_LWM2M_CLIENT_SESSION_UPDATING: + case NX_LWM2M_CLIENT_SESSION_DISABLING: + case NX_LWM2M_CLIENT_SESSION_DEREGISTERING: + + /* Send the first request */ + _nx_lwm2m_client_session_send_request(session_ptr, NX_TRUE); + + return; + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING: + { + + /* Set substate for bootstrap */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + + /* Get hold-off timer from security object if it exists */ + if (session_ptr -> nx_lwm2m_client_session_server_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + NX_LWM2M_CLIENT_SECURITY_INSTANCE *security_ptr; + + security_ptr = (NX_LWM2M_CLIENT_SECURITY_INSTANCE *) _nx_lwm2m_client_object_instance_ptr_get((NX_LWM2M_CLIENT_OBJECT *) &session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_security, session_ptr -> nx_lwm2m_client_session_server_id); + if (security_ptr != NX_NULL) + { + hold_off = security_ptr -> security_instance_hold_off; + } + } + + if (hold_off) + { + + /* Start bootstrap after hold-off time */ + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + (ULONG)(hold_off) * NX_IP_PERIODIC_RATE; + + return; + } +#endif + + /* Hold-off timer disabled, start bootstrap after one tick */ + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + 1; + + return; + } + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED: + + /* Arm bootstrap completion timer */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + NX_LWM2M_CLIENT_BOOTSTRAP_IDLE_TIMER; + + return; + + case NX_LWM2M_CLIENT_SESSION_REGISTERED: + + /* Arm update timer at half of the session lifetime */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + + session_ptr -> nx_lwm2m_client_session_timer = tx_time_get() + (ULONG)(session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_lifetime)/2 * NX_IP_PERIODIC_RATE; + + /* Clear list of parameters to report to server */ + session_ptr -> nx_lwm2m_client_session_flags &= (UINT)(~NX_LWM2M_CLIENT_SESSION_UPDATE_ALL); + + return; + + /* NX_LWM2M_CLIENT_SESSION_INIT */ + /* NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED */ + /* NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR */ + /* NX_LWM2M_CLIENT_SESSION_DEREGISTERED */ + /* NX_LWM2M_CLIENT_SESSION_DISABLED */ + /* NX_LWM2M_CLIENT_SESSION_ERROR */ + default: + + /* Reset the session */ + _nx_lwm2m_client_session_cleanup(session_ptr); + + return; + + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_step PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This functions checks if the session state needs to be updated */ +/* due to application request or timer expiration. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* has_timer_ptr On return, set to NX_TRUE if */ +/* the session has active timers */ +/* timer_expire_ptr On return, the expiration */ +/* time of the next active timer */ +/* */ +/* OUTPUT */ +/* */ +/* NX_TRUE The session callback has been */ +/* called, */ +/* NX_FALSE The session callback has not */ +/* been called */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_session_state_update */ +/* _nx_lwm2m_client_session_send_request */ +/* _nx_lwm2m_client_resource_notify_number_get */ +/* _nx_lwm2m_client_session_notify_attributes */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_thread_entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +NX_LWM2M_BOOL _nx_lwm2m_client_session_step(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL *has_timer_ptr, ULONG *timer_expire_ptr) +{ +ULONG now; +ULONG next_timer; + + if (session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_IDLE) + { + + /* Idle session, got nothing to do. */ + return(NX_FALSE); + } + + /* Check for state transition request from application */ + if (session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_BOOTSTRAP || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_REGISTER || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER) + { + + /* Update current state */ + switch (session_ptr -> nx_lwm2m_client_session_substate) + { + + case NX_LWM2M_CLIENT_SESSION_SUBSTATE_BOOTSTRAP: + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING); + break; + + case NX_LWM2M_CLIENT_SESSION_SUBSTATE_REGISTER: + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_REGISTERING); + break; + + case NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE: + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_UPDATING); + break; + + case NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE: + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_DISABLING); + break; + + /* NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER */ + default: + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_DEREGISTERING); + break; + + } + + /* Report new state to state callback */ + session_ptr -> nx_lwm2m_client_session_state_callback(session_ptr, session_ptr -> nx_lwm2m_client_session_state); + + return(NX_TRUE); + } + + /* Check for session timer expiration */ + now = tx_time_get(); + + if ((LONG) (session_ptr -> nx_lwm2m_client_session_timer - now) <= 0) + { + if (session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_REQUEST_SENT) + { + + /* Request retransmission timer expired */ + + /* Re-send the request */ + if (_nx_lwm2m_client_session_send_request(session_ptr, NX_FALSE) != NX_SUCCESS) + { + + /* Report the error to the state callback */ + session_ptr -> nx_lwm2m_client_session_state_callback(session_ptr, session_ptr -> nx_lwm2m_client_session_state); + + return(NX_TRUE); + } + } + else + { + + /* substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT */ + /* Session state timer expired */ + + /* Get type of timer event */ + switch (session_ptr -> nx_lwm2m_client_session_state) + { + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING: + + /* Hold off timer expired, start client initiated bootstrap */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING); + break; + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED: + + /* No request from bootstrap server for too long, report error */ + session_ptr -> nx_lwm2m_client_session_error = NX_LWM2M_CLIENT_TIMED_OUT; + + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR); + break; + + case NX_LWM2M_CLIENT_SESSION_REGISTERED: + + /* Registration timer expired, send update */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_UPDATING); + break; + + case NX_LWM2M_CLIENT_SESSION_DISABLED: + + /* Disabled timer expired, register to server again */ + _nx_lwm2m_client_session_state_update(session_ptr, NX_LWM2M_CLIENT_SESSION_REGISTERING); + break; + + default: + + /* XXX SHOULD NOT GO HERE */ + NX_ASSERT(0); + } + + /* Report new state to state callback */ + session_ptr -> nx_lwm2m_client_session_state_callback(session_ptr, session_ptr -> nx_lwm2m_client_session_state); + + return(NX_TRUE); + } + } + + /* Update the next timer expiration */ + next_timer = *timer_expire_ptr; + if (!(*has_timer_ptr) || (LONG) (session_ptr -> nx_lwm2m_client_session_timer - next_timer) < 0) + { + next_timer = session_ptr -> nx_lwm2m_client_session_timer; + } + + /* Process Notifications */ + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_REGISTERED || session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_UPDATING) + { + NX_LWM2M_CLIENT_NOTIFY *notify_ptr; + + notify_ptr = session_ptr -> nx_lwm2m_client_session_notifications; + while (notify_ptr != NX_NULL) + { + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_TIMER) + { + /* notify timer is active */ + + if ((LONG) (notify_ptr -> notify_timer - now) <= 0) + { + NX_LWM2M_CLIENT_RESOURCE resource; + UINT resource_count; + UINT response_format; + UINT flags; + NX_LWM2M_INT32 pmin; + NX_LWM2M_INT32 pmax; + NX_LWM2M_CLIENT_NOTIFY_NUMBER gt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER lt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER stp; + + /* Timer has expired, send notify message */ + + if (notify_ptr -> notify_resource_id != NX_LWM2M_CLIENT_RESERVED_ID) + { + + /* Send a single value */ + resource.resource_id = notify_ptr -> notify_resource_id; + resource_count = 1; + if (notify_ptr -> notify_object_ptr -> object_operation(NX_LWM2M_CLIENT_OBJECT_READ, notify_ptr -> notify_object_ptr, notify_ptr -> notify_instance_ptr, + &resource, &resource_count, NX_NULL, 0) == NX_SUCCESS) + { + + /* Save value if it's a number */ + _nx_lwm2m_client_resource_notify_number_get(&resource, ¬ify_ptr -> notify_last_value); + } + else + { + + /* XXX should not happen */ + resource.resource_type = NX_LWM2M_CLIENT_RESOURCE_NONE; + } + /* select response format */ + if (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_ACCEPT_TLV) + { + + /* Server wanted TLV */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV; + } + else if (resource.resource_type == NX_LWM2M_CLIENT_RESOURCE_STRING) + { + + /* Text value */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN; + } + else if (resource.resource_type == NX_LWM2M_CLIENT_RESOURCE_OPAQUE) + { + + /* Opaque value */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM; + } + else + { + + /* Use TLV for all other types */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV; + } + } + else + { + + /* Return instance(s) in tlv format */ + response_format = NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV; + } + + /* Get new message id */ + notify_ptr -> notify_last_id = ++session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_request_id; + + /* Save notification time */ + notify_ptr -> notify_last_time = tx_time_get(); + + /* Send notify message */ + _nx_lwm2m_client_session_send_response(session_ptr, NX_LWM2M_CLIENT_COAP_STATUS_CONTENT, notify_ptr -> notify_last_id, + NX_FALSE, notify_ptr -> notify_token, (notify_ptr -> notify_flags & NX_LWM2M_CLIENT_NOTIFY_TOKEN_LEN), + NX_TRUE, response_format, notify_ptr -> notify_object_ptr, notify_ptr -> notify_instance_ptr, + (notify_ptr -> notify_resource_id == NX_LWM2M_CLIENT_RESERVED_ID ? NX_NULL : &resource)); + + /* Clear CHANGED flag */ + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_CHANGED); + + /* We need to rearm timer if pmax is defined */ + _nx_lwm2m_client_session_notify_attributes(session_ptr, notify_ptr, &flags, &pmin, &pmax, >, <, &stp); + if (!(flags & NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX)) + { + + /* Get default maximum period from server object */ + pmax = session_ptr -> nx_lwm2m_client_session_server_instance_ptr -> server_instance_max_period; + } + + if (pmax > 0) + { + + /* Rearm timer */ + notify_ptr -> notify_timer = notify_ptr -> notify_last_time + (ULONG)(pmax) * NX_IP_PERIODIC_RATE; + if ((LONG) (notify_ptr -> notify_timer - next_timer) < 0) + { + + /* Update next timer value if current notify timer expires before */ + next_timer = notify_ptr -> notify_timer; + } + } + else + { + + /* Clear timer flag */ + notify_ptr -> notify_flags &= (UINT)(~NX_LWM2M_CLIENT_NOTIFY_TIMER); + } + } + else if ((LONG) (notify_ptr -> notify_timer - next_timer) < 0) + { + + /* Update next timer value if current notify timer expires before */ + next_timer = notify_ptr -> notify_timer; + } + } + + notify_ptr = notify_ptr -> notify_next; + } + } + + /* Return next timer expiration */ + *has_timer_ptr = NX_TRUE; + *timer_expire_ptr = next_timer; + + return(NX_FALSE); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_update PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the Client to a LWM2M Server. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* tx_event_flags_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_session_update(NX_LWM2M_CLIENT_SESSION *session_ptr) +{ +NX_LWM2M_CLIENT *client_ptr = session_ptr -> nx_lwm2m_client_session_client_ptr; +UINT status; +NX_LWM2M_BOOL do_wakeup; + + status = NX_SUCCESS; + do_wakeup = NX_FALSE; + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Check session state */ + if ((session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_REGISTERED && + session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_UPDATING) || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER) + { + status = NX_LWM2M_CLIENT_NOT_REGISTERED; + } + else if (session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_UPDATING && + session_ptr -> nx_lwm2m_client_session_substate != NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE) + { + + /* Tell session to start updating */ + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE; + do_wakeup = NX_TRUE; + } + + /* Release the client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + if (do_wakeup) + { + + /* Wakeup client thread */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } + + return(status); +} + +/* Define the maximum delay before sending an update message */ +#define MAX_UPDATE_DELAY NX_IP_PERIODIC_RATE + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_session_update_flags PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the information that needs to be sent to the */ +/* the next Client Update message. */ +/* */ +/* INPUT */ +/* */ +/* session_ptr Pointer to LWM2M session */ +/* flags The information that has */ +/* changed since last update */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* tx_time_get */ +/* tx_event_flags_set */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_object_list_changed */ +/* _nx_lwm2m_client_server_write */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_session_update_flags(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT flags) +{ +ULONG now; + + /* Only update registered sessions */ + if ((session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_REGISTERED && + session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_UPDATING) || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE || + session_ptr -> nx_lwm2m_client_session_substate == NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER) + { + + /* Not registered or currently de-registring/disabling */ + return; + } + + /* Set update flags */ + session_ptr -> nx_lwm2m_client_session_flags |= flags; + + /* Schedule the sending of the update message */ + now = tx_time_get(); + if (session_ptr -> nx_lwm2m_client_session_substate != NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT || ((LONG) (session_ptr -> nx_lwm2m_client_session_timer - now)) > (LONG)MAX_UPDATE_DELAY) + { + + /* Arm update timer */ + session_ptr -> nx_lwm2m_client_session_state = NX_LWM2M_CLIENT_SESSION_REGISTERED; + session_ptr -> nx_lwm2m_client_session_substate = NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT; + session_ptr -> nx_lwm2m_client_session_timer = now + MAX_UPDATE_DELAY; + + /* Wakeup client thread */ + tx_event_flags_set(&session_ptr -> nx_lwm2m_client_session_client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_WAKEUP, TX_OR); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_format_id PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts an object ID to a string. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr The destination buffer */ +/* string_length The length of the buffer */ +/* id The object ID */ +/* */ +/* OUTPUT */ +/* */ +/* The length of the returned string */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_strconv_format_int32 */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_corelink_path_add */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_format_id(CHAR *string_ptr, UINT string_length, NX_LWM2M_ID id) +{ + + /* Same format as integer */ + return(_nx_lwm2m_client_strconv_format_int32(string_ptr, string_length, id)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_format_uint32 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function formats unsigned 32-bit integer. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr The destination buffer */ +/* string_length The length of the buffer */ +/* value The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* The length of the returned string */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_strconv_format_int32 */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_format_uint32(CHAR *string_ptr, UINT string_length, ULONG value) +{ +UINT length; +CHAR *ptr; + + /* Fast path for values 0-9 */ + if (value < 10) + { + if (string_length == 0) + { + return(0); + } + *string_ptr = (CHAR)('0' + value); + return(1); + } + + /* Compute length of string representation */ + if (value >= 1000000000UL) + { + length = 10; + } + else if (value >= 100000000UL) + { + length = 9; + } + else if (value >= 10000000UL) + { + length = 8; + } + else if (value >= 1000000UL) + { + length = 7; + } + else if (value >= 100000UL) + { + length = 6; + } + else if (value >= 10000UL) + { + length = 5; + } + else if (value >= 1000UL) + { + length = 4; + } + else if (value >= 100UL) + { + length = 3; + } + else + { + length = 2; + } + + if (length > string_length) + { + + /* Buffer too small */ + return(0); + } + + /* Write digits in reverse order */ + ptr = string_ptr + length - 1; + while (1) + { + *ptr-- = (CHAR)('0' + (value % 10)); + + if (ptr < string_ptr) + { + return(length); + } + + value = value / 10; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_format_int32 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a 32-bit integer to a string */ +/* */ +/* INPUT */ +/* */ +/* string_ptr The destination buffer */ +/* string_length The length of the buffer */ +/* value The integer value */ +/* */ +/* OUTPUT */ +/* */ +/* The length of the returned string */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* _nx_lwm2m_client_access_control_delete */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_write_attribute */ +/* _nx_lwm2m_client_session_send_request */ +/* _nx_lwm2m_client_strconv_format_notify_number */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_format_int32(CHAR *string_ptr, UINT string_length, NX_LWM2M_INT32 value) +{ +UINT ret; + + if (value < 0) + { + + if (string_length < 2) + { + + /* Need at least 2 characters */ + return(0); + } + + /* Write minus sign */ + *string_ptr++ = '-'; + + /* Write absolute value */ + ret = _nx_lwm2m_client_format_uint32(string_ptr, string_length-1, (ULONG) (-value)); + + /* Return total length or error */ + return(ret != 0 ? ret + 1 : 0); + } + + /* Write positive value */ + return(_nx_lwm2m_client_format_uint32(string_ptr, string_length, (ULONG) value)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_format_notify_number PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a notify number to a string. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr The destination buffer */ +/* string_length The length of the buffer */ +/* value The number value */ +/* */ +/* OUTPUT */ +/* */ +/* The length of the returned string */ +/* */ +/* CALLS */ +/* */ +/* memcpy */ +/* sprintf */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_write_attribute */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_format_notify_number(CHAR *string_ptr, UINT string_length, NX_LWM2M_CLIENT_NOTIFY_NUMBER value) +{ +UINT digit_num = 1; +INT integer; +INT decimal[NX_LWM2M_CLIENT_DOUBLE_DECIMAL_PLACE_DIGITS] = {0}; +INT index = 0; +INT precision = NX_LWM2M_CLIENT_DOUBLE_DECIMAL_PLACE_DIGITS; +double temp; +UINT length = 0; +INT exponent = 0; +INT exp = 0; + + /* Check if it's positive or negative */ + if (value < 0) + { + if (string_length < 2) + { + return(0); + } + string_ptr[length++] = '-'; + value *= -1; + } + else if (string_length == 0) + { + return(0); + } + + /* Check if using exponent */ + if (value >= 10000000000000000.) + { + exp = 1; + } + else if (value < 0.001 && value > 0) + { + exp = 2; + } + + if (!exp) + { + + /* Get integer number */ + temp = value; + while (temp >= 10) + { + temp /= 10; + digit_num++; + } + + /* Check string length */ + if (string_length < (digit_num + length)) + { + return(0); + } + + /* Save the integer part to output buffer */ + if (digit_num > 1) + { + for (temp = 1, index = 1; index < (INT)digit_num; index++) + { + temp = temp * 10; + } + for (index = 0; index < (INT)digit_num; index++) + { + integer = (INT)(value / temp); + string_ptr[length++] = (CHAR)(integer + '0'); + value -= integer * temp; + temp /= 10; + } + } + else + { + integer = (INT)value; + string_ptr[length++] = (CHAR)(integer + '0'); + value -= integer; + } + } + else + { + + if (exp == 1) + { + while (value >= 10) + { + value /= 10; + exponent++; + } + } + else + { + while (value < 1) + { + value = value * 10; + exponent++; + } + } + + string_ptr[length++] = (CHAR)((INT)value + '0'); + value -= (INT)value; + } + + /* Save the decimal to 'decimal' array */ + for (index = 0; index < precision; index++) + { + decimal[index] = (INT)(value * 10); + value = value * 10 - decimal[index]; + } + + for (index = precision - 1; index >= 0; index--) + { + if (decimal[index] == 0) + { + precision--; + } + else + { + break; + } + } + + if (precision) + { + + /* Check string length */ + if (string_length < (length + (UINT)precision + 1)) + { + return(0); + } + + string_ptr[length++] = '.'; + } + + /* Save the decimal to output buffer */ + for (index = 0; index < precision; index++) + { + string_ptr[length++] = (CHAR)(decimal[index] + '0'); + } + + /* Save the exponent part */ + if (exp) + { + if (string_length < (length + 2)) + { + return(0); + } + string_ptr[length++] = 'E'; + + if (exp == 1) + { + string_ptr[length++] = '+'; + } + else + { + string_ptr[length++] = '-'; + } + + digit_num = _nx_lwm2m_client_strconv_format_int32(string_ptr + length, string_length - length, exponent); + if (digit_num == 0) + { + return(0); + } + length += digit_num; + } + + return(length); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_parse_id PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a string representing an object ID. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr Pointer to the string */ +/* string_length The length of the string */ +/* id_ptr On return, the parsed value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_get_request_options */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_parse_id(const CHAR *string_ptr, UINT string_length, NX_LWM2M_ID *id_ptr) +{ +const CHAR *string_ptr_max; +CHAR c; +ULONG id; + + /* At least one character */ + if (string_length == 0) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Get pointer to end of string */ + string_ptr_max = string_ptr + string_length; + + /* Get first character */ + c = *string_ptr++; + + /* Convert first character to digit */ + if (c < '0' || c > '9') + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + id = (ULONG) (c - '0'); + + /* Check for invalid leading zero */ + if (id == 0 && string_ptr != string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Parse the rest of the string */ + while (string_ptr < string_ptr_max) + { + if (id > 6553) + { + + /* Max range reached */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Get next character */ + c = *string_ptr++; + + /* Convert to digit */ + if (c < '0' || c > '9') + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + id = id*10 + (ULONG) (c - '0'); + } + + /* ID must be in range 0-65534 (65535 is reserved) */ + if (id > 65534) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Return ID */ + *id_ptr = (NX_LWM2M_ID) id; + + /* Return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_parse_int32 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a string representing a 32-bit integer. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr Pointer to the string */ +/* string_length The length of the string */ +/* value_ptr On return, the parsed value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_get_request_options */ +/* _nx_lwm2m_client_strconv_parse_notify_number */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_parse_int32(const CHAR *string_ptr, UINT string_length, NX_LWM2M_INT32 *value_ptr) +{ +const CHAR *string_ptr_max; +NX_LWM2M_BOOL negative; +CHAR c; +ULONG value; + + /* At least one character */ + if (string_length == 0) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Get pointer to end of string */ + string_ptr_max = string_ptr + string_length; + + /* Get first character */ + c = *string_ptr++; + if (c == '-') + { + + /* Minus sign character, must be followed by digit */ + if (string_ptr >= string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + negative = NX_TRUE; + + value = 0; + } + else if (c >= '0' && c <= '9') + { + negative = NX_FALSE; + + value = (ULONG)(c - '0'); + } + else + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + while (string_ptr < string_ptr_max) + { + + /* Get next character */ + c = *string_ptr++; + + if (c < '0' || c > '9' || value > 214748364UL) + { + + /* Invalid character or number too big */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + value *= 10; + value += (ULONG)(c - '0'); + } + + /* Convert to 32-bit signed integer */ + if (negative) + { + if (value > 2147483648UL) + { + + /* Absolute value too big */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + *value_ptr = (NX_LWM2M_INT32) - (LONG) value; + + return(NX_SUCCESS); + } + if (value > 2147483647UL) + { + + /* Number too big */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + *value_ptr = (NX_LWM2M_INT32) value; + + return(NX_SUCCESS); +} + + +#define EXP_MAX 308 + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_strconv_parse_notify_number PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a string representing a notify number. */ +/* */ +/* INPUT */ +/* */ +/* string_ptr Pointer to the string */ +/* string_length The length of the string */ +/* number_ptr On return, the parsed value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_strconv_parse_int32 */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_get_request_options */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_strconv_parse_notify_number(const CHAR *string_ptr, UINT string_length, NX_LWM2M_CLIENT_NOTIFY_NUMBER *number_ptr) +{ +const CHAR *string_ptr_max; +NX_LWM2M_BOOL negative; +CHAR c; +NX_LWM2M_CLIENT_NOTIFY_NUMBER value; +INT i; + + /* At least one character */ + if (string_length == 0) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* Get pointer to end of string */ + string_ptr_max = string_ptr + string_length; + + /* Get first character */ + c = *string_ptr++; + if (c == '-') + { + + /* Minus sign character, must be followed by digit */ + if (string_ptr >= string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + c = *string_ptr++; + + negative = NX_TRUE; + } + else + { + negative = NX_FALSE; + } + + if (c < '0' || c > '9') + { + + /* Invalid first character, must be a digit */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* First digit */ + value = c - '0'; + + while (string_ptr < string_ptr_max) + { + + /* Get next character */ + c = *string_ptr; + + if (c < '0' || c > '9') + { + + /* End of integer part */ + break; + } + + value *= 10; + value += c - '0'; + string_ptr++; + } + + if (string_ptr < string_ptr_max && c == '.') + { + NX_LWM2M_CLIENT_NOTIFY_NUMBER frac; + + /* Fractional part */ + string_ptr++; + if (string_ptr >= string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + /* First fractional digit */ + c = *string_ptr++; + if (c < '0' || c > '9') + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + value += 0.1*(c - '0'); + frac = 0.1; + + while (string_ptr < string_ptr_max) + { + + /* Get next character */ + c = *string_ptr; + + if (c < '0' || c > '9') + { + + /* End of fractional part */ + break; + } + + frac /= 10.0; + value += frac*(c - '0'); + string_ptr++; + } + } + + if (string_ptr < string_ptr_max) + { + if (c == 'e' || c == 'E') + { + NX_LWM2M_INT32 exp; + + /* Exponent */ + string_ptr++; + if (string_ptr >= string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + if (*string_ptr == '+') + { + + /* Exponent may have positive sign character */ + string_ptr++; + + /* Next character must be a digit */ + if (string_ptr >= string_ptr_max) + { + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + c = *string_ptr; + if (c < '0' || c > '9') + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + } + + /* Get exponent value */ + if (_nx_lwm2m_client_strconv_parse_int32(string_ptr, (UINT)(string_ptr_max - string_ptr), &exp) != NX_SUCCESS || exp < -EXP_MAX || exp > EXP_MAX) + { + + /* Invalid exponent */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + + if (exp >= 0) + { + for (i = 0; i < exp; i++) + { + value = value * 10; + } + } + else + { + exp = -1 * exp; + for (i = 0; i < exp; i++) + { + value = value / 10; + } + } + } + else + { + + /* Invalid character */ + return(NX_LWM2M_CLIENT_BAD_ENCODING); + } + } + + *number_ptr = negative ? -value : value; + + return(NX_SUCCESS); +} + +/* Compare IP addresses */ +#ifdef FEATURE_NX_IPV6 +#ifdef NX_DISABLE_IPV4 +#define IP_ADDRESS_EQ(a1_, a2_) ( \ + (a1_.nxd_ip_version == NX_IP_VERSION_V6 && \ + a1_.nxd_ip_address.v6[0] == a2_.nxd_ip_address.v6[0] && \ + a1_.nxd_ip_address.v6[1] == a2_.nxd_ip_address.v6[1] && \ + a1_.nxd_ip_address.v6[2] == a2_.nxd_ip_address.v6[2] && \ + a1_.nxd_ip_address.v6[3] == a2_.nxd_ip_address.v6[3]) \ + ) +#else +#define IP_ADDRESS_EQ(a1_, a2_) ( \ + a1_.nxd_ip_version == a2_.nxd_ip_version && \ + ((a1_.nxd_ip_version == NX_IP_VERSION_V4 && \ + a1_.nxd_ip_address.v4 == a2_.nxd_ip_address.v4) || \ + (a1_.nxd_ip_version != NX_IP_VERSION_V4 && \ + a1_.nxd_ip_address.v6[0] == a2_.nxd_ip_address.v6[0] && \ + a1_.nxd_ip_address.v6[1] == a2_.nxd_ip_address.v6[1] && \ + a1_.nxd_ip_address.v6[2] == a2_.nxd_ip_address.v6[2] && \ + a1_.nxd_ip_address.v6[3] == a2_.nxd_ip_address.v6[3])) \ + ) +#endif +#else +#define IP_ADDRESS_EQ(a1_, a2_) (a1_.nxd_ip_address.v4 == a2_.nxd_ip_address.v4) +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_packet_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received packet for a non secure session. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* packet_ptr Pointer to packet */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* nxd_udp_packet_info_extract */ +/* _nx_lwm2m_client_session_receive */ +/* nx_packet_release */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_thread_entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_packet_received(NX_LWM2M_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ + NX_LWM2M_CLIENT_SESSION *session_ptr; + NXD_ADDRESS ip_address; + UINT protocol; + UINT port; + UINT index; + + /* Get source address and port */ + nxd_udp_packet_info_extract(packet_ptr, &ip_address, &protocol, &port, &index); + + /* Find the destination session */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + + /* Check IP address and port number of server */ + if ( +#ifdef NX_SECURE_ENABLE_DTLS + session_ptr -> nx_lwm2m_client_session_dtls_session == NX_NULL && +#endif /* NX_SECURE_ENABLE_DTLS */ + session_ptr -> nx_lwm2m_client_session_state != NX_LWM2M_CLIENT_SESSION_INIT && + IP_ADDRESS_EQ(session_ptr -> nx_lwm2m_client_session_server_address, ip_address) && + session_ptr -> nx_lwm2m_client_session_server_port == port) + { + + /* Let the session process the packet */ + _nx_lwm2m_client_session_receive(session_ptr, packet_ptr); + + /* End of packet processing */ + return; + } + + /* Get next session */ + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + + /* No session found, release the packet */ + nx_packet_release(packet_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_thread_entry PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function defines the LWM2M client thread entry point. */ +/* */ +/* INPUT */ +/* */ +/* client_address Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get */ +/* tx_mutex_put */ +/* tx_event_flags_get */ +/* nx_udp_socket_receive */ +/* nx_secure_dtls_session_receive */ +/* _nx_lwm2m_client_session_receive */ +/* _nx_lwm2m_client_session_step */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_lwm2m_client_thread_entry(ULONG client_address) +{ +NX_LWM2M_CLIENT *client_ptr = (NX_LWM2M_CLIENT *) client_address; +NX_LWM2M_BOOL has_timer; +ULONG timer_expire; + + + /* Acquire the client mutex */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* No timer defined yet */ + has_timer = NX_FALSE; + + while(1) + { + ULONG flags; + UINT status; + ULONG timeout; + + /* Release mutex before blocking on event flags */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Compute timeout value */ + if (!has_timer) + { + timeout = TX_WAIT_FOREVER; + } + else + { + timeout = timer_expire - tx_time_get(); + if ((LONG) timeout <= 0) + { + timeout = TX_NO_WAIT; + } + } + + /* Wait for timeout expiration or event */ + status = tx_event_flags_get(&client_ptr -> nx_lwm2m_client_event_flags, (ULONG)(~0), TX_OR_CLEAR, &flags, timeout); + + /* Acquire mutex again */ + tx_mutex_get(&client_ptr -> nx_lwm2m_client_mutex, TX_WAIT_FOREVER); + + /* Check status */ + if (status == TX_NO_EVENTS) + { + + /* Timeout has expired */ + flags = 0; + } + else if (status != TX_SUCCESS) + { + + /* Unexpected Error, terminate thread */ + break; + } + if (flags & NX_LWM2M_CLIENT_EVENT_TERM_REQ) + { + + /* nx_lwm2m_client_delete was called, terminate thread */ + break; + } + + if (flags & NX_LWM2M_CLIENT_EVENT_COAP_MESSAGE) + { + NX_PACKET *packet_ptr; + + /* Process CoAP Messages */ + while (nx_udp_socket_receive((NX_UDP_SOCKET *) &client_ptr -> nx_lwm2m_client_coap_socket, &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + _nx_lwm2m_client_packet_received(client_ptr, packet_ptr); + } + } + +#ifdef NX_SECURE_ENABLE_DTLS + if (flags & NX_LWM2M_CLIENT_EVENT_COAPS_MESSAGE) + { + NX_LWM2M_CLIENT_SESSION *session_ptr; + + /* Process Secure CoAP Messages on all secure sessions */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + if (session_ptr -> nx_lwm2m_client_session_dtls_session != NX_NULL) + { + NX_PACKET *packet_ptr; + if (session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING || + session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_INIT || + session_ptr -> nx_lwm2m_client_session_state == NX_LWM2M_CLIENT_SESSION_DISABLED) + { + + /* DTLS session is not yet connected or lwm2m client is disabled, + * ignore the messages */ + while (nx_udp_socket_receive((NX_UDP_SOCKET *) &session_ptr -> nx_lwm2m_client_session_dtls_socket, &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + nx_packet_release(packet_ptr); + } + } + else + { + + /* Save current session state to detect changes */ + UINT old_state = session_ptr -> nx_lwm2m_client_session_state; + + /* DTLS session is established, get received messages on the secure socket */ + while (nx_secure_dtls_session_receive(session_ptr -> nx_lwm2m_client_session_dtls_session, &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + /* Process the received message */ + _nx_lwm2m_client_session_receive(session_ptr, packet_ptr); + if (old_state != session_ptr -> nx_lwm2m_client_session_state) + { + break; + } + } + if (old_state != session_ptr -> nx_lwm2m_client_session_state) + { + + /* reinitialize session_ptr in case the application */ + /* has updated the sessions in the state change callback */ + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + continue; + } + } + } + + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + + } +#endif /* NX_SECURE_ENABLE_DTLS */ + + /* Update Sessions state and process timers */ + while (1) + { + NX_LWM2M_CLIENT_SESSION *session_ptr; + NX_LWM2M_BOOL again; + + again = NX_FALSE; + has_timer = NX_FALSE; + + session_ptr = client_ptr -> nx_lwm2m_client_sessions; + while (session_ptr != NX_NULL) + { + + again = _nx_lwm2m_client_session_step(session_ptr, &has_timer, &timer_expire); + + if (again) + { + + /* A session callback has been called, need to process session again */ + /* in case the application has updated the sessions */ + break; + } + + session_ptr = session_ptr -> nx_lwm2m_client_session_next; + } + + if (!again) + { + + /* Done with sessions */ + break; + } + } + + } + + /* Release mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Inform nx_lwm2m_client_delete that the thread is terminated */ + tx_event_flags_set(&client_ptr -> nx_lwm2m_client_event_flags, NX_LWM2M_CLIENT_EVENT_TERM_DONE, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_tlv_header_parse PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses a TLV header. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to source buffer */ +/* ptr_max Pointer to the end of buffer */ +/* type_ptr On return, the type of value */ +/* id_ptr On return, the resource ID */ +/* length_ptr On return, the length of value*/ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the TLV value, NULL if the header is invalid */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_resource_instances_get */ +/* _nx_lwm2m_client_tlv_resource_parse */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +const VOID * _nx_lwm2m_client_tlv_header_parse(const VOID *ptr, const VOID *ptr_max, UCHAR *type_ptr, NX_LWM2M_ID *id_ptr, UINT *length_ptr) +{ +UCHAR type; +NX_LWM2M_ID id; +UINT length = 0; +UINT buffer_length; +const UCHAR *byte_ptr; + + /* Pointer to header */ + byte_ptr = (const UCHAR *) ptr; + + if (ptr_max != NX_NULL) + { + + /* Set length of buffer if ptr_max is provided */ + buffer_length = (UINT)((const UCHAR *) ptr_max - byte_ptr); + + /* Check for mimimum length */ + if (buffer_length < 2) + { + return(NX_NULL); + } + } + else + { + + /* Do not check buffer length */ + buffer_length = 0; + } + + /* Get Type field */ + type = *byte_ptr++; + buffer_length--; + + /* Get identifier */ + if (type & NX_LWM2M_CLIENT_TLV_TYPE_ID_LENGTH) + { + + /* 16-bit identifier */ + if ((ptr_max != NX_NULL) && (buffer_length < 2)) + { + return(NX_NULL); + } + id = (NX_LWM2M_ID)((byte_ptr[0] << 8) | byte_ptr[1]); + byte_ptr += 2; + buffer_length -= 2; + } + else + { + + /* 8-bit identifier */ + id = *byte_ptr++; + buffer_length--; + } + + /* Get Length */ + switch (type & NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_TYPE_MASK) + { + + case NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_NONE: + + /* No length field, use bits 2-0 */ + length = type & NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_MASK; + break; + + case NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_8_BIT: + + /* 8-bit length */ + if ((ptr_max != NX_NULL) && (buffer_length == 0)) + { + return(NX_NULL); + } + length = *byte_ptr++; + buffer_length--; + break; + + case NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_16_BIT: + + /* 16-bit length */ + if ((ptr_max != NX_NULL) && (buffer_length < 2)) + { + return(NX_NULL); + } + length = (((UINT) byte_ptr[0]) << 8) | ((UINT) byte_ptr[1]); + byte_ptr += 2; + buffer_length -= 2; + break; + + case NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_24_BIT: + + /* 24-bit length */ + if ((ptr_max != NX_NULL) && (buffer_length < 3)) + { + return(NX_NULL); + } + length = (((UINT) byte_ptr[0]) << 16) | (((UINT) byte_ptr[1]) << 8) | ((UINT) byte_ptr[2]); + byte_ptr += 3; + buffer_length -= 3; + break; + + } + + /* Check that buffer is large enought for the value */ + if ((ptr_max != NX_NULL) && (length > buffer_length)) + { + return(NX_NULL); + } + + /* Return TLV information */ + *type_ptr = type & NX_LWM2M_CLIENT_TLV_TYPE_ID_TYPE_MASK; + *id_ptr = id; + *length_ptr = length; + return(byte_ptr); +} + +/* limits for 32-bit integers */ +#ifndef INT32_MAX +#define INT32_MAX 0x7fffffffL +#endif +#ifndef INT32_MIN +#define INT32_MIN (-INT32_MAX - 1L) +#endif + +/* limits for 16-bit integers */ +#ifndef INT16_MAX +#define INT16_MAX 0x7fff +#endif +#ifndef INT16_MIN +#define INT16_MIN (-INT16_MAX - 1) +#endif + +/* limits for 8-bit integers */ +#ifndef INT8_MAX +#define INT8_MAX 0x7f +#endif +#ifndef INT8_MIN +#define INT8_MIN (-INT8_MAX - 1) +#endif + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_write_integer32 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes 8-bit, 16-bit or 32-bit integer. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* value The resource value to encode */ +/* length The length of resource value */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_write_integer32(UCHAR *ptr, NX_LWM2M_INT32 value, UINT length) +{ + if (length > 2) + { + *ptr++ = (UCHAR) (value >> 24); + *ptr++ = (UCHAR) (value >> 16); + } + if (length > 1) + { + *ptr++ = (UCHAR) (value >> 8); + } + *ptr = (UCHAR) value; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_write_integer64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes 64-bit integer. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* value The resource value to encode */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_write_integer64(UCHAR *ptr, NX_LWM2M_INT64 value) +{ + ptr[0] = (UCHAR) (value >> 56); + ptr[1] = (UCHAR) (value >> 48); + ptr[2] = (UCHAR) (value >> 40); + ptr[3] = (UCHAR) (value >> 32); + ptr[4] = (UCHAR) (value >> 24); + ptr[5] = (UCHAR) (value >> 16); + ptr[6] = (UCHAR) (value >> 8); + ptr[7] = (UCHAR) value; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_tlv_header_length PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the length of the TLV header. */ +/* */ +/* INPUT */ +/* */ +/* value The resource value to encode */ +/* length Total length */ +/* */ +/* OUTPUT */ +/* */ +/* The length of TLV header */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_get_tlv_header_length(const NX_LWM2M_CLIENT_RESOURCE *value, UINT length) +{ +UINT tlv_header_length; + + /* Compute total length */ + tlv_header_length = 2; + if (value -> resource_id > 255) + { + + /* 16-bit ID */ + tlv_header_length++; + } + if (length > 0xffffu) + { + + /* 24-bit length */ + tlv_header_length += 3; + } + else if (length > 0xff) + { + + /* 16-bit length */ + tlv_header_length += 2; + } + else if (length > 7) + { + + /* 8-bit length */ + tlv_header_length += 1; + } + + return(tlv_header_length); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_add_tlv_header PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes the TLV header. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* type Type of the resource */ +/* value The resource value to encode */ +/* length Total length */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_lwm2m_client_add_tlv_header(UCHAR *ptr, UCHAR type, const NX_LWM2M_CLIENT_RESOURCE *value, UINT length) +{ +UCHAR *ptr_type = ptr; + + /* Skip type */ + ptr++; + + /* Write ID */ + if (value -> resource_id > 255) + { + + /* 16-bit ID */ + type |= NX_LWM2M_CLIENT_TLV_TYPE_ID_LENGTH; + *ptr++ = (UCHAR) (value -> resource_id >> 8); + } + *ptr++ = (UCHAR) value -> resource_id; + + /* Set length filed */ + if (length > 0xffffu) + { + + /* 24-bit length */ + type |= NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_24_BIT; + } + else if (length > 0xff) + { + + /* 16-bit length */ + type |= NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_16_BIT; + } + else if (length > 7) + { + + /* 8-bit length */ + type |= NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_8_BIT; + } + else + { + + /* 3-bit length included in type byte */ + type |= (UCHAR)(length); + } + + /* Write length */ + if (length > 0xffffu) + { + *ptr++ = (UCHAR) (length >> 16); + } + if (length > 0xff) + { + *ptr++ = (UCHAR) (length >> 8); + } + if (length > 7) + { + *ptr++ = (UCHAR) length; + } + + /* Write type */ + *ptr_type = type; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_resource_length PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the length of resource. */ +/* */ +/* INPUT */ +/* */ +/* value The resource value to encode */ +/* length Returned total length */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_get_resource_length(const NX_LWM2M_CLIENT_RESOURCE *value, UINT *length) +{ + + /* Compute length of value */ + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_NONE: + + *length = 0; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER32: + + if (value -> resource_value.resource_integer32data > INT16_MAX || + value -> resource_value.resource_integer32data < INT16_MIN) + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER32; + } + else if (value -> resource_value.resource_integer32data > INT8_MAX || + value -> resource_value.resource_integer32data < INT8_MIN) + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER16; + } + else + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER8; + } + + break; + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER64: + + if (value -> resource_value.resource_integer64data > INT32_MAX || + value -> resource_value.resource_integer64data < INT32_MIN) + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER64; + } + else if (value -> resource_value.resource_integer64data > INT16_MAX || + value -> resource_value.resource_integer64data < INT16_MIN) + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER32; + } + else if (value -> resource_value.resource_integer64data > INT8_MAX || + value -> resource_value.resource_integer64data < INT8_MIN) + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER16; + } + else + { + *length = NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER8; + } + + break; + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT32: + + *length = NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT64: + + *length = NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT64; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_BOOLEAN: + + *length = NX_LWM2M_CLIENT_TLV_LENGTH_BOOLEAN; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_STRING: + case NX_LWM2M_CLIENT_RESOURCE_OPAQUE: + + *length = value -> resource_value.resource_bufferdata.resource_buffer_length; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_OBJLNK: + + *length = NX_LWM2M_CLIENT_TLV_LENGTH_OBJLNK; + + break; + + default: + + /* Invalid type */ + return(NX_LWM2M_CLIENT_ERROR); + + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_add_resource PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes single resource value. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* ptr_max Pointer to the end of buffer */ +/* value The resource value to encode */ +/* tlv_length Returned total length */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_get_resource_length */ +/* _nx_lwm2m_client_get_tlv_header_length */ +/* _nx_lwm2m_client_add_tlv_header */ +/* _nx_lwm2m_client_write_integer32 */ +/* _nx_lwm2m_client_write_integer64 */ +/* memcpy */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_add_resource(UCHAR *ptr, UCHAR *ptr_max, UCHAR type, const NX_LWM2M_CLIENT_RESOURCE *value, UINT *tlv_length) +{ +UINT status; +UINT length = 0; +UINT tlv_header_length = 0; + + /* Get the length of value */ + status = _nx_lwm2m_client_get_resource_length(value, &length); + if (status) + { + return(status); + } + + /* Get the length of TLV header */ + tlv_header_length = _nx_lwm2m_client_get_tlv_header_length(value, length); + if (ptr + length + tlv_header_length > ptr_max) + { + return(NX_LWM2M_CLIENT_ERROR); + } + else + { + *tlv_length = length + tlv_header_length; + } + + /* Write TLV header */ + _nx_lwm2m_client_add_tlv_header(ptr, type, value, length); + ptr += tlv_header_length; + + /* Write value */ + if (length != 0) + { + switch (value -> resource_type) + { + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER32: + + _nx_lwm2m_client_write_integer32(ptr, value -> resource_value.resource_integer32data, length); + + break; + + case NX_LWM2M_CLIENT_RESOURCE_INTEGER64: + + if (length != NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER64) + { + _nx_lwm2m_client_write_integer32(ptr, (NX_LWM2M_INT32) value -> resource_value.resource_integer64data, length); + } + else + { + _nx_lwm2m_client_write_integer64(ptr, value -> resource_value.resource_integer64data); + } + + break; + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT32: + { + NX_LWM2M_INT32 as_integer32; + + memcpy(&as_integer32, &value -> resource_value.resource_float32data, NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32); /* Use case of memcpy is verified. */ + + _nx_lwm2m_client_write_integer32(ptr, as_integer32, NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32); + + break; + } + + case NX_LWM2M_CLIENT_RESOURCE_FLOAT64: + { + NX_LWM2M_INT64 as_integer64; + + memcpy(&as_integer64, &value -> resource_value.resource_float64data, NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT64); /* Use case of memcpy is verified. */ + + _nx_lwm2m_client_write_integer64(ptr, as_integer64); + + break; + } + + case NX_LWM2M_CLIENT_RESOURCE_BOOLEAN: + + *ptr = value -> resource_value.resource_booleandata ? 1 : 0; + + break; + + case NX_LWM2M_CLIENT_RESOURCE_STRING: + case NX_LWM2M_CLIENT_RESOURCE_OPAQUE: + + memcpy(ptr, value -> resource_value.resource_bufferdata.resource_buffer_ptr, length); /* Use case of memcpy is verified. */ + + break; + + case NX_LWM2M_CLIENT_RESOURCE_OBJLNK: + + ptr[0] = (UCHAR) (value -> resource_value.resource_objlnkdata.objlnk_object_id >> 8); + ptr[1] = (UCHAR) value -> resource_value.resource_objlnkdata.objlnk_object_id; + ptr[2] = (UCHAR) (value -> resource_value.resource_objlnkdata.objlnk_instance_id >> 8); + ptr[3] = (UCHAR) value -> resource_value.resource_objlnkdata.objlnk_instance_id; + + break; + } + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_get_multiple_resource_length PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the length of multiple resource. */ +/* */ +/* INPUT */ +/* */ +/* value The resource value to encode */ +/* length Returned total length */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_get_resource_length */ +/* _nx_lwm2m_client_get_tlv_header_length */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_get_multiple_resource_length(const NX_LWM2M_CLIENT_RESOURCE *value, UINT *length) +{ +UINT i; +UINT instance_length = 0; +UINT status; +const NX_LWM2M_CLIENT_RESOURCE *array; + + /* Initialize the returned length */ + *length = 0; + + /* Calculate the length of multiple resource */ + array = (const NX_LWM2M_CLIENT_RESOURCE *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + for (i = 0; i < value -> resource_dim; i++) + { + + /* Caculate the length of resource instance */ + status = _nx_lwm2m_client_get_resource_length(&array[i], &instance_length); + if (status) + { + return(status); + } + *length += (instance_length + _nx_lwm2m_client_get_tlv_header_length(value, instance_length)); + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_add_multiple_resource PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes multiple resource value. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* ptr_max Pointer to the end of buffer */ +/* value The resource value to encode */ +/* tlv_length Returned total length */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_get_multiple_resource_length */ +/* _nx_lwm2m_client_get_tlv_header_length */ +/* _nx_lwm2m_client_add_tlv_header */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_lwm2m_client_add_multiple_resource(UCHAR *ptr, UCHAR *ptr_max, const NX_LWM2M_CLIENT_RESOURCE *value, UINT *tlv_length) +{ +UINT status; +UINT i; +UINT length = 0; +UINT tlv_header_length = 0; +const NX_LWM2M_CLIENT_RESOURCE *resource_array; + + + /* Get the length of multiple resource */ + status = _nx_lwm2m_client_get_multiple_resource_length(value, &length); + if (status) + { + return(status); + } + + /* Get the length of TLV header */ + tlv_header_length = _nx_lwm2m_client_get_tlv_header_length(value, length); + if (ptr + length + tlv_header_length > ptr_max) + { + return(NX_LWM2M_CLIENT_ERROR); + } + else + { + *tlv_length = length + tlv_header_length; + } + + /* Write TLV header */ + _nx_lwm2m_client_add_tlv_header(ptr, NX_LWM2M_CLIENT_TLV_RESOURCE_MULTIPLE, value, length); + ptr += tlv_header_length; + + resource_array = (const NX_LWM2M_CLIENT_RESOURCE *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + for (i = 0; i < value -> resource_dim; i++) + { + + /* Write resource isntance */ + status = _nx_lwm2m_client_add_resource(ptr, ptr_max, NX_LWM2M_CLIENT_TLV_RESOURCE_INSTANCE, &resource_array[i], &length); + if (status) + { + return(status); + } + ptr += length; + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_tlv_resource_add PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function writes a TLV encoded resource value. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to destination buffer */ +/* ptr_max Pointer to the end of buffer */ +/* value The resource value to encode */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the encoded value, NULL if the buffer is too */ +/* small */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_get_multiple_resource_length */ +/* _nx_lwm2m_client_get_resource_length */ +/* _nx_lwm2m_client_get_tlv_header_length */ +/* _nx_lwm2m_client_add_tlv_header */ +/* _nx_lwm2m_client_add_multiple_resource */ +/* _nx_lwm2m_client_add_resource */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_read_instance */ +/* _nx_lwm2m_client_session_send_response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID *_nx_lwm2m_client_tlv_resource_add(VOID *ptr, VOID *ptr_max, const NX_LWM2M_CLIENT_RESOURCE *value) +{ +UINT status; +UINT i; +UINT tlv_length = 0; +UINT length = 0; +UINT total_length = 0; +UINT tlv_header_length = 0; +const NX_LWM2M_CLIENT_RESOURCE *resource_array; +UCHAR *buffer_ptr = ptr; + + /* Write resource value and TLV header to the buffer */ + if (value -> resource_type == NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE) + { + + /* Get the resources */ + resource_array = (const NX_LWM2M_CLIENT_RESOURCE *) value -> resource_value.resource_bufferdata.resource_buffer_ptr; + + /* Calculate the length of all the resources */ + for (i = 0; i < value -> resource_dim; i++) + { + if (NX_LWM2M_CLIENT_RESOURCE_IS_MULTIPLE(resource_array[i].resource_type)) + { + status = _nx_lwm2m_client_get_multiple_resource_length(&resource_array[i], &length); + if (status) + { + return(NX_NULL); + } + } + else + { + status = _nx_lwm2m_client_get_resource_length(&resource_array[i], &length); + if (status) + { + return(NX_NULL); + } + } + total_length += (length + _nx_lwm2m_client_get_tlv_header_length(&resource_array[i], length)); + } + + /* Get the length of TLV header */ + tlv_header_length = _nx_lwm2m_client_get_tlv_header_length(value, total_length); + if ((UCHAR *)ptr + total_length + tlv_header_length > (UCHAR *)ptr_max) + { + return(NX_NULL); + } + else + { + tlv_length = total_length + tlv_header_length; + } + + /* Write TLV header */ + _nx_lwm2m_client_add_tlv_header(buffer_ptr, NX_LWM2M_CLIENT_TLV_OBJECT_INSTANCE, value, total_length); + buffer_ptr = buffer_ptr + tlv_header_length; + + /* Write all the resources */ + for (i = 0; i < value -> resource_dim; i++) + { + if (NX_LWM2M_CLIENT_RESOURCE_IS_MULTIPLE(resource_array[i].resource_type)) + { + status = _nx_lwm2m_client_add_multiple_resource(buffer_ptr, ptr_max, &resource_array[i], &length); + if (status) + { + return(NX_NULL); + } + buffer_ptr = buffer_ptr + length; + } + else + { + status = _nx_lwm2m_client_add_resource(buffer_ptr, ptr_max, NX_LWM2M_CLIENT_TLV_RESOURCE_VALUE, &resource_array[i], &length); + if (status) + { + return(NX_NULL); + } + buffer_ptr = buffer_ptr + length; + } + } + } + else if (value -> resource_type == NX_LWM2M_CLIENT_RESOURCE_MULTIPLE) + { + + /* Write multiple resource */ + status = _nx_lwm2m_client_add_multiple_resource(ptr, ptr_max, value, &tlv_length); + if (status) + { + return(NX_NULL); + } + } + else + { + + /* Write resource */ + status = _nx_lwm2m_client_add_resource(ptr, ptr_max, NX_LWM2M_CLIENT_TLV_RESOURCE_VALUE, value, &tlv_length); + if (status) + { + return(NX_NULL); + } + } + + /* Return the updated pointer */ + return((UCHAR *) ptr + tlv_length); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_tlv_resource_parse PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the value of a TLV encoded resource. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to source buffer */ +/* ptr_max Pointer to the end of buffer */ +/* resource_ptr On return, the resource value */ +/* */ +/* OUTPUT */ +/* */ +/* Pointer to the end of the TLV value, NULL if the TLV is not valid */ +/* */ +/* CALLS */ +/* */ +/* _nx_lwm2m_client_tlv_header_parse */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_lwm2m_client_session_receive */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +const VOID *_nx_lwm2m_client_tlv_resource_parse(const VOID *ptr, const VOID *ptr_max, NX_LWM2M_CLIENT_RESOURCE *resource_ptr) +{ +UCHAR type; +NX_LWM2M_ID id; +UINT value_length; +const UCHAR *value_ptr; +const UCHAR *value_max_ptr; +UCHAR value_type; +UCHAR value_count; + + /* Parse header */ + value_ptr = _nx_lwm2m_client_tlv_header_parse(ptr, ptr_max, &type, &id, &value_length); + if (value_ptr == NX_NULL) + { + + /* Invalid TLV header */ + return(NX_NULL); + } + + /* Get type of resource */ + if (type == NX_LWM2M_CLIENT_TLV_RESOURCE_VALUE) + { + + /* Single value */ + value_type = NX_LWM2M_CLIENT_RESOURCE_TLV; + } + else if (type == NX_LWM2M_CLIENT_TLV_RESOURCE_MULTIPLE) + { + + /* Multiple value */ + value_type = NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_TLV; + } + else if (type == NX_LWM2M_CLIENT_TLV_OBJECT_INSTANCE) + { + + /* Object instance */ + value_type = NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE_TLV; + } + else + { + + /* Invalid type */ + return(NX_NULL); + } + + /* Pointer to next TLV value */ + value_max_ptr = value_ptr + value_length; + + /* Number of elements in multiple resource */ + value_count = 0; + + /* Check elements in case of multiple resource: */ + if (value_type == NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_TLV) + { + const UCHAR *el_ptr; + + el_ptr = value_ptr; + while (el_ptr < value_max_ptr) + { + UCHAR el_type; + NX_LWM2M_ID el_id; + UINT el_value_length; + + /* Parse TLV element */ + el_ptr = _nx_lwm2m_client_tlv_header_parse(el_ptr, value_max_ptr, &el_type, &el_id, &el_value_length); + if ((el_ptr == NX_NULL) || (el_type != NX_LWM2M_CLIENT_TLV_RESOURCE_INSTANCE)) + { + + /* Invalid multiple resource instance */ + return(NX_NULL); + } + + /* Next element */ + el_ptr += el_value_length; + + /* Increment elements count */ + value_count++; + } + + /* Set dim for multiple resource */ + resource_ptr -> resource_dim = value_count; + } + + /* Return resource value */ + resource_ptr -> resource_id = id; + resource_ptr -> resource_type = value_type; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_ptr = value_ptr; + resource_ptr -> resource_value.resource_bufferdata.resource_buffer_length = value_length; + + /* Return pointer to next TLV value */ + return(value_max_ptr); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_lwm2m_client_unlock PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unlocks the LWM2M Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to LWM2M client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_put */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_lwm2m_client_unlock(NX_LWM2M_CLIENT *client_ptr) +{ + + /* Release the LWM2M Client mutex */ + tx_mutex_put(&client_ptr -> nx_lwm2m_client_mutex); + + /* Always return a success. */ + return(NX_SUCCESS); +} diff --git a/addons/lwm2m/nx_lwm2m_client.h b/addons/lwm2m/nx_lwm2m_client.h new file mode 100644 index 00000000..f0e1e17a --- /dev/null +++ b/addons/lwm2m/nx_lwm2m_client.h @@ -0,0 +1,1815 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Lightweight M2M Protocol (LWM2M) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nx_lwm2m_client.h PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX LWM2M Client component, including all */ +/* data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), supported*/ +/* token and processing */ +/* confirmable response, */ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler errors when */ +/* TX_SAFETY_CRITICAL is */ +/* enabled, */ +/* resulting in version 6.1.12 */ +/* */ +/**************************************************************************/ + +#ifndef NX_LWM2M_CLIENT_H +#define NX_LWM2M_CLIENT_H + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + +/* Bypass NetX API error checking for internal calls. */ +#include "tx_port.h" + +#ifdef NX_LWM2M_CLIENT_SOURCE_CODE +#ifndef TX_SAFETY_CRITICAL +#ifndef TX_DISABLE_ERROR_CHECKING +#define TX_DISABLE_ERROR_CHECKING +#endif +#endif +#ifndef NX_DISABLE_ERROR_CHECKING +#define NX_DISABLE_ERROR_CHECKING +#endif +#ifndef NX_SECURE_DISABLE_ERROR_CHECKING +#define NX_SECURE_DISABLE_ERROR_CHECKING +#endif +#endif + + +/* Include NetX and ThreadX definitions */ + +#include "nx_api.h" +#ifdef NX_SECURE_ENABLE_DTLS +#include "nx_secure_dtls_api.h" +#endif /* NX_SECURE_ENABLE_DTLS */ + + +/* Define some basic data types used by LWM2M */ + +/* 16-bit unsigned integer */ +typedef USHORT NX_LWM2M_ID; + +/* Boolean */ +typedef CHAR NX_LWM2M_BOOL; + +/* 32-bit signed integer */ +typedef LONG NX_LWM2M_INT32; + +/* 64-bit signed integer */ +typedef long long NX_LWM2M_INT64; + +/* 64-bit unsigned integer */ +typedef unsigned long long NX_LWM2M_UINT64; + +/* 32-bit floating point */ +typedef float NX_LWM2M_FLOAT32; + +/* 64-bit floating point */ +typedef double NX_LWM2M_FLOAT64; + + +/* Define the maximum size of a CoAP message, including IP and UDP headers. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MTU +#define NX_LWM2M_CLIENT_MTU 1280 +#endif /* NX_LWM2M_CLIENT_MTU */ + + +/* Define the Type Of Service for the socket transmission . This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SOCKET_TOS +#define NX_LWM2M_CLIENT_SOCKET_TOS NX_IP_NORMAL +#endif /* NX_LWM2M_CLIENT_SOCKET_TOS */ + + +/* Define the Time To Live for the socket transmission . This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SOCKET_TTL +#define NX_LWM2M_CLIENT_SOCKET_TTL NX_IP_TIME_TO_LIVE +#endif /* NX_LWM2M_CLIENT_SOCKET_TTL */ + + +/* Define the maximum number of dtagrams that can be queued for the socket. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SOCKET_QUEUE_MAX +#define NX_LWM2M_CLIENT_SOCKET_QUEUE_MAX 8 +#endif /* NX_LWM2M_CLIENT_SOCKET_QUEUE_MAX */ + + +/* Define the maximum length of the coap Uri-Path option, not including the '/rd' prefix. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_COAP_URI_PATH +#define NX_LWM2M_CLIENT_MAX_COAP_URI_PATH 32 +#endif /* NX_LWM2M_CLIENT_MAX_COAP_URI_PATH */ + + +/* Define the maximum number of stored device errors. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_DEVICE_ERRORS +#define NX_LWM2M_CLIENT_MAX_DEVICE_ERRORS 8 +#endif /* NX_LWM2M_CLIENT_MAX_DEVICE_ERRORS */ + + +/* Define the maximum number of Security Object Instances. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +#define NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES 2 +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + +/* Define the maximum number of Server Object Instances. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES +#define NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES 1 +#endif /* NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES */ + + +/* Define the maximum number of Access Control Object Instances. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES +#define NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES 0 +#endif /* NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES */ + + +/* Define the maximum number of ACL resources per Access Control Object Instance. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS +#define NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS 4 +#endif /* NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS */ + + +/* Define the maximum number of Notifications. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_NOTIFICATIONS +#define NX_LWM2M_CLIENT_MAX_NOTIFICATIONS 8 +#endif /* NX_LWM2M_CLIENT_MAX_NOTIFICATIONS */ + + +/* Define the maximum number of resources per object. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_RESOURCES +#define NX_LWM2M_CLIENT_MAX_RESOURCES 32 +#endif /* NX_LWM2M_CLIENT_MAX_RESOURCES */ + + +/* Define the maximum number of resource instances for multiple resource. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_MAX_MULTIPLE_RESOURCES +#define NX_LWM2M_CLIENT_MAX_MULTIPLE_RESOURCES 8 +#endif /* NX_LWM2M_CLIENT_MAX_MULTIPLE_RESOURCES */ + + +/* Define the maximum time allowed for the Bootstrap session between messages from the server. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_BOOTSTRAP_IDLE_TIMER +#define NX_LWM2M_CLIENT_BOOTSTRAP_IDLE_TIMER (60 * NX_IP_PERIODIC_RATE) +#endif /* NX_LWM2M_CLIENT_BOOTSTRAP_IDLE_TIMER */ + + +/* Define the maximum time to wait for DTLS handshake completion. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_DTLS_START_TIMEOUT +#define NX_LWM2M_CLIENT_DTLS_START_TIMEOUT (30 * NX_IP_PERIODIC_RATE) +#endif /* NX_LWM2M_CLIENT_DTLS_START_TIMEOUT */ + + +/* Define the maximum time to wait for DTLS shutdown completion. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_DTLS_END_TIMEOUT +#define NX_LWM2M_CLIENT_DTLS_END_TIMEOUT (5 * NX_IP_PERIODIC_RATE) +#endif /* NX_LWM2M_CLIENT_DTLS_END_TIMEOUT */ + + +/* Define the maximum length of the server URI, including terminating nul character. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_URI +#define NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_URI 128 +#endif /* NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_URI */ + + +/* Define the maximum public key or identity length for DTLS. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SECURITY_MAX_PUBLIC_KEY_OR_IDENTITY +#define NX_LWM2M_CLIENT_SECURITY_MAX_PUBLIC_KEY_OR_IDENTITY 128 +#endif /* NX_LWM2M_CLIENT_SECURITY_MAX_PUBLIC_KEY_OR_IDENTITY */ + + +/* Define the maximum server public key length for DTLS. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_PUBLIC_KEY +#define NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_PUBLIC_KEY 128 +#endif /* NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_PUBLIC_KEY */ + + +/* Define the maximum secret key length for DTLS. This value can be replaced by the user as a compilation option. */ + +#ifndef NX_LWM2M_CLIENT_SECURITY_MAX_SECRET_KEY +#define NX_LWM2M_CLIENT_SECURITY_MAX_SECRET_KEY 128 +#endif /* NX_LWM2M_CLIENT_SECURITY_MAX_SECRET_KEY */ + + +/* Define the number of seconds to wait before initiating a Client Initiated Bootstrap. */ + +#ifndef NX_LWM2M_CLIENT_HOLD_OFF +#define NX_LWM2M_CLIENT_HOLD_OFF 1 +#endif /* NX_LWM2M_CLIENT_HOLD_OFF */ + + +/* Define the lifetime of the registration in seconds. */ + +#ifndef NX_LWM2M_CLIENT_LIFE_TIME +#define NX_LWM2M_CLIENT_LIFE_TIME 600 +#endif /* NX_LWM2M_CLIENT_LIFE_TIME */ + + + +/* Error codes */ + +#define NX_LWM2M_CLIENT_ERROR 0x80 +#define NX_LWM2M_CLIENT_ALREADY_EXIST 0x81 +#define NX_LWM2M_CLIENT_BAD_ENCODING 0x82 +#define NX_LWM2M_CLIENT_BUFFER_TOO_SMALL 0x83 +#define NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED 0x84 +#define NX_LWM2M_CLIENT_NO_MEMORY 0x85 +#define NX_LWM2M_CLIENT_NOT_FOUND 0x86 +#define NX_LWM2M_CLIENT_NOT_SUPPORTED 0x87 +#define NX_LWM2M_CLIENT_NOT_ACCEPTABLE 0x88 +#define NX_LWM2M_CLIENT_PORT_UNAVAILABLE 0x89 +#define NX_LWM2M_CLIENT_ADDRESS_ERROR 0x8a +#define NX_LWM2M_CLIENT_DTLS_ERROR 0x8b +#define NX_LWM2M_CLIENT_SERVER_INSTANCE_DELETED 0x8c +#define NX_LWM2M_CLIENT_TIMED_OUT 0x8d +#define NX_LWM2M_CLIENT_NOT_REGISTERED 0x8e +#define NX_LWM2M_CLIENT_BAD_REQUEST 0x8f +#define NX_LWM2M_CLIENT_UNAUTHORIZED 0x90 +#define NX_LWM2M_CLIENT_BAD_OPTION 0x91 +#define NX_LWM2M_CLIENT_FORBIDDEN 0x92 +#define NX_LWM2M_CLIENT_PRECONDITION_FAILED 0x93 +#define NX_LWM2M_CLIENT_UNSUPPORTED_CONTENT_FORMAT 0x94 + + +/* Standard CoAP port number. */ + +#define NX_LWM2M_CLIENT_COAP_PORT 5683 + + +/* Standard Secure CoAP port number. */ + +#define NX_LWM2M_CLIENT_COAPS_PORT 5684 + + +/* Max length of a CoAP token */ + +#define NX_LWM2M_CLIENT_COAP_TOKEN_LEN 8 + + +/* Reserved Object/Instance/Resource ID */ + +#define NX_LWM2M_CLIENT_RESERVED_ID 65535U + + +/* Define the standard OMA Objects IDs implemented by the LWM2M Client */ + +#define NX_LWM2M_CLIENT_SECURITY_OBJECT_ID 0 +#define NX_LWM2M_CLIENT_SERVER_OBJECT_ID 1 +#define NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID 2 +#define NX_LWM2M_CLIENT_DEVICE_OBJECT_ID 3 +#define NX_LWM2M_CLIENT_FIRMWARE_OBJECT_ID 5 + + +/* Define the OMA Security Object Resources IDs */ + +#define NX_LWM2M_CLIENT_SECURITY_URI_ID 0 +#define NX_LWM2M_CLIENT_SECURITY_BOOTSTRAP_ID 1 +#define NX_LWM2M_CLIENT_SECURITY_MODE_ID 2 +#define NX_LWM2M_CLIENT_SECURITY_PUBLIC_KEY_ID 3 +#define NX_LWM2M_CLIENT_SECURITY_SERVER_PUBLIC_KEY_ID 4 +#define NX_LWM2M_CLIENT_SECURITY_SECRET_KEY_ID 5 +#define NX_LWM2M_CLIENT_SECURITY_SMS_SECURITY_ID 6 +#define NX_LWM2M_CLIENT_SECURITY_SMS_KEY_PARAM_ID 7 +#define NX_LWM2M_CLIENT_SECURITY_SMS_SECRET_KEY_ID 8 +#define NX_LWM2M_CLIENT_SECURITY_SMS_SERVER_NUMBER_ID 9 +#define NX_LWM2M_CLIENT_SECURITY_SHORT_SERVER_ID 10 +#define NX_LWM2M_CLIENT_SECURITY_HOLD_OFF_ID 11 + + +/* Define the OMA Server Object Resources IDs */ + +#define NX_LWM2M_CLIENT_SERVER_SHORT_SERVER_ID 0 +#define NX_LWM2M_CLIENT_SERVER_LIFETIME_ID 1 +#define NX_LWM2M_CLIENT_SERVER_MIN_PERIOD_ID 2 +#define NX_LWM2M_CLIENT_SERVER_MAX_PERIOD_ID 3 +#define NX_LWM2M_CLIENT_SERVER_DISABLE_ID 4 +#define NX_LWM2M_CLIENT_SERVER_DISABLE_TIMEOUT_ID 5 +#define NX_LWM2M_CLIENT_SERVER_STORING_ID 6 +#define NX_LWM2M_CLIENT_SERVER_BINDING_ID 7 +#define NX_LWM2M_CLIENT_SERVER_UPDATE_ID 8 + + +/* Define the OMA Access Control Object Resources IDs */ + +#define NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_ID_ID 0 +#define NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_INSTANCE_ID_ID 1 +#define NX_LWM2M_CLIENT_ACCESS_CONTROL_ACL_ID 2 +#define NX_LWM2M_CLIENT_ACCESS_CONTROL_OWNER_ID 3 + + +/* Define the OMA Device Object Resources IDs */ + +#define NX_LWM2M_CLIENT_DEVICE_MANUFACTURER_ID 0 +#define NX_LWM2M_CLIENT_DEVICE_MODEL_NUMBER_ID 1 +#define NX_LWM2M_CLIENT_DEVICE_SERIAL_NUMBER_ID 2 +#define NX_LWM2M_CLIENT_DEVICE_FIRMWARE_VERSION_ID 3 +#define NX_LWM2M_CLIENT_DEVICE_REBOOT_ID 4 +#define NX_LWM2M_CLIENT_DEVICE_FACTORY_RESET_ID 5 +#define NX_LWM2M_CLIENT_DEVICE_AVAILABLE_POWER_SOURCES_ID 6 +#define NX_LWM2M_CLIENT_DEVICE_POWER_SOURCE_VOLTAGE_ID 7 +#define NX_LWM2M_CLIENT_DEVICE_POWER_SOURCE_CURRENT_ID 8 +#define NX_LWM2M_CLIENT_DEVICE_BATTERY_LEVEL_ID 9 +#define NX_LWM2M_CLIENT_DEVICE_MEMORY_FREE_ID 10 +#define NX_LWM2M_CLIENT_DEVICE_ERROR_CODE_ID 11 +#define NX_LWM2M_CLIENT_DEVICE_RESET_ERROR_CODE_ID 12 +#define NX_LWM2M_CLIENT_DEVICE_CURRENT_TIME_ID 13 +#define NX_LWM2M_CLIENT_DEVICE_UTC_OFFSET_ID 14 +#define NX_LWM2M_CLIENT_DEVICE_TIMEZONE_ID 15 +#define NX_LWM2M_CLIENT_DEVICE_BINDING_MODES_ID 16 +#define NX_LWM2M_CLIENT_DEVICE_DEVICE_TYPE_ID 17 +#define NX_LWM2M_CLIENT_DEVICE_HARDWARE_VERSION_ID 18 +#define NX_LWM2M_CLIENT_DEVICE_SOFTWARE_VERSION_ID 19 +#define NX_LWM2M_CLIENT_DEVICE_BATTERY_STATUS_ID 20 +#define NX_LWM2M_CLIENT_DEVICE_MEMORY_TOTAL_ID 21 +#define NX_LWM2M_CLIENT_DEVICE_EXTDEVINFO_ID 22 + + +/* Define the OMA Firmware Update Object Resources IDs */ + +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ID 0 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_ID 1 +#define NX_LWM2M_CLIENT_FIRMWARE_UPDATE_ID 2 +#define NX_LWM2M_CLIENT_FIRMWARE_STATE_ID 3 +#define NX_LWM2M_CLIENT_FIRMWARE_UPDATE_SUPPORTED_OBJECTS_ID 4 +#define NX_LWM2M_CLIENT_FIRMWARE_UPDATE_RESULT_ID 5 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_NAME_ID 6 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_VERSION_ID 7 +#define NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_SUPPORT_ID 8 +#define NX_LWM2M_CLIENT_FIRMWARE_DELIVERY_METHOD_ID 9 + + +/* Define the data types of a LWM2M resource */ + +#define NX_LWM2M_CLIENT_RESOURCE_NONE 0x00 +#define NX_LWM2M_CLIENT_RESOURCE_STRING 0x01 +#define NX_LWM2M_CLIENT_RESOURCE_INTEGER32 0x02 +#define NX_LWM2M_CLIENT_RESOURCE_INTEGER64 0x03 +#define NX_LWM2M_CLIENT_RESOURCE_FLOAT32 0x04 +#define NX_LWM2M_CLIENT_RESOURCE_FLOAT64 0x05 +#define NX_LWM2M_CLIENT_RESOURCE_BOOLEAN 0x06 +#define NX_LWM2M_CLIENT_RESOURCE_OPAQUE 0x07 +#define NX_LWM2M_CLIENT_RESOURCE_OBJLNK 0x08 + +#define NX_LWM2M_CLIENT_RESOURCE_TLV 0x09 +#define NX_LWM2M_CLIENT_RESOURCE_TEXT 0x0a + +#define NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE 0x0b +#define NX_LWM2M_CLIENT_RESOURCE_OBJECT_INSTANCE_TLV 0x0c + +#define NX_LWM2M_CLIENT_RESOURCE_MULTIPLE 0x10 +#define NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_TLV 0x11 +#define NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_UCHAR 0x12 +#define NX_LWM2M_CLIENT_RESOURCE_MULTIPLE_ACL 0x13 + +#define NX_LWM2M_CLIENT_RESOURCE_IS_MULTIPLE(t) ((t) & 0x10) + + +/* Define the event flags of the LWM2M Client */ + +#define NX_LWM2M_CLIENT_EVENT_WAKEUP ((ULONG)0x00000001) +#define NX_LWM2M_CLIENT_EVENT_COAP_MESSAGE ((ULONG)0x00000002) +#define NX_LWM2M_CLIENT_EVENT_COAPS_MESSAGE ((ULONG)0x00000004) +#define NX_LWM2M_CLIENT_EVENT_TERM_REQ ((ULONG)0x00000008) +#define NX_LWM2M_CLIENT_EVENT_TERM_DONE ((ULONG)0x00000010) + +/* Define the sub-state of a session */ + +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_IDLE 0 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_BOOTSTRAP 1 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_REGISTER 2 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_UPDATE 3 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_DISABLE 4 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_DEREGISTER 5 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_REQUEST_SENT 6 +#define NX_LWM2M_CLIENT_SESSION_SUBSTATE_WAIT 7 + +/* Define the session flags */ + +#define NX_LWM2M_CLIENT_SESSION_UPDATE_LIFETIME ((ULONG)0x00000001) +#define NX_LWM2M_CLIENT_SESSION_UPDATE_BINDING_MODE ((ULONG)0x00000002) +#define NX_LWM2M_CLIENT_SESSION_UPDATE_MSISDN ((ULONG)0x00000004) +#define NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST ((ULONG)0x00000008) + +#define NX_LWM2M_CLIENT_SESSION_UPDATE_ALL \ + (NX_LWM2M_CLIENT_SESSION_UPDATE_LIFETIME | \ + NX_LWM2M_CLIENT_SESSION_UPDATE_BINDING_MODE | \ + NX_LWM2M_CLIENT_SESSION_UPDATE_MSISDN | \ + NX_LWM2M_CLIENT_SESSION_UPDATE_OBJECTS_LIST) + +/* Define the resource operation */ + +#define NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ ((ULONG)0x00000001) +#define NX_LWM2M_CLIENT_RESOURCE_OPERATION_WRITE ((ULONG)0x00000002) +#define NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE ((ULONG)0x00000004) + +#define NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE (NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ | NX_LWM2M_CLIENT_RESOURCE_OPERATION_WRITE) + +/* Define the structure of an Object Link */ + +typedef struct NX_LWM2M_OBJLNK_STRUCT +{ + + /* The Object ID */ + NX_LWM2M_ID objlnk_object_id; + + /* The Object Instance ID */ + NX_LWM2M_ID objlnk_instance_id; + +} NX_LWM2M_OBJLNK; + +/* Define the value of a LWM2M Resource */ + +typedef struct NX_LWM2M_CLIENT_RESOURCE_STRUCT +{ + + /* The ID of the resource */ + NX_LWM2M_ID resource_id; + + /* The type of the resource */ + UCHAR resource_type; + + /* The dim for multiple resource */ + UCHAR resource_dim; + + /* The operation of resource */ + ULONG resource_operation; + + /* The value of the resource */ + union + { + struct + { + const VOID *resource_buffer_ptr; + UINT resource_buffer_length; + } resource_bufferdata; + NX_LWM2M_INT32 resource_integer32data; + NX_LWM2M_INT64 resource_integer64data; + NX_LWM2M_FLOAT32 resource_float32data; + NX_LWM2M_FLOAT64 resource_float64data; + NX_LWM2M_BOOL resource_booleandata; + NX_LWM2M_OBJLNK resource_objlnkdata; + } resource_value; + +} NX_LWM2M_CLIENT_RESOURCE; + + +/* Define the operation type */ + +#define NX_LWM2M_CLIENT_OBJECT_READ 0 +#define NX_LWM2M_CLIENT_OBJECT_DISCOVER 1 +#define NX_LWM2M_CLIENT_OBJECT_WRITE 2 +#define NX_LWM2M_CLIENT_OBJECT_EXECUTE 3 +#define NX_LWM2M_CLIENT_OBJECT_CREATE 4 +#define NX_LWM2M_CLIENT_OBJECT_DELETE 5 + +/* Define the type of 'Write' operation */ + +#define NX_LWM2M_CLIENT_OBJECT_WRITE_UPDATE 0 +#define NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_INSTANCE 1 +#define NX_LWM2M_CLIENT_OBJECT_WRITE_REPLACE_RESOURCE 2 +#define NX_LWM2M_CLIENT_OBJECT_WRITE_CREATE 3 +#define NX_LWM2M_CLIENT_OBJECT_WRITE_BOOTSTRAP 4 + + +/* Define the structure of the operation arguments */ + +typedef struct NX_LWM2M_CLIENT_OPERATION_ARGUMENT_STRUCT +{ + + /* The instance ID */ + NX_LWM2M_ID instance_id; + + /* The flag of bootstrap */ + NX_LWM2M_BOOL bootstrap; + + /* Reserved */ + UCHAR reserved; + +} NX_LWM2M_CLIENT_OPERATION_ARGUMENT; + + +/* Define the structure of an instance of a LWM2M Object */ + +typedef struct NX_LWM2M_CLIENT_OBJECT_INSTANCE_STRUCT +{ + /* Pointer to the next instance in the list */ + struct NX_LWM2M_CLIENT_OBJECT_INSTANCE_STRUCT + *object_instance_next; + + /* The instance ID */ + NX_LWM2M_ID object_instance_id; + +} NX_LWM2M_CLIENT_OBJECT_INSTANCE; + + +/* Define the LWM2M Client Object data type */ + +typedef struct NX_LWM2M_CLIENT_OBJECT_STRUCT NX_LWM2M_CLIENT_OBJECT; + + +/* Define the LWM2M Client Object operation callback */ + +typedef UINT (*NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK)(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length); + + +/* Define the structure of a LWM2M Object */ + +struct NX_LWM2M_CLIENT_OBJECT_STRUCT +{ + /* Pointer to the next object in the database */ + struct NX_LWM2M_CLIENT_OBJECT_STRUCT *object_next; + + /* Pointer to the LWM2M Client */ + struct NX_LWM2M_CLIENT_STRUCT *object_client_ptr; + + /* The object ID */ + NX_LWM2M_ID object_id; + + /* The operation callback function */ + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK + object_operation; + + /* Pointer to the list of instances */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instances; + +}; + + +/* Define the internal type used to store floating point values */ +typedef double NX_LWM2M_CLIENT_NOTIFY_NUMBER; + + +/* Define the request options */ + +typedef struct NX_LWM2M_CLIENT_REQUEST_OPTIONS_STRUCT +{ + + /* Option flags */ + UINT flags; + + /* Object ID */ + NX_LWM2M_ID object_id; + + /* Instance ID */ + NX_LWM2M_ID instance_id; + + /* Resource ID */ + NX_LWM2M_ID resource_id; + + /* CoAP options */ + UINT accept; + UINT content_format; + UINT observe; + + /* Set attribute */ + CHAR attr_set; + + /* Unset attribute */ + CHAR attr_unset; + + /* Attributes */ + NX_LWM2M_INT32 pmin; + NX_LWM2M_INT32 pmax; + NX_LWM2M_CLIENT_NOTIFY_NUMBER gt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER lt; + NX_LWM2M_CLIENT_NOTIFY_NUMBER stp; + +} NX_LWM2M_CLIENT_REQUEST_OPTIONS; + + +/* Define the notification structure flags */ + +#define NX_LWM2M_CLIENT_NOTIFY_TOKEN_LEN 0xF +#define NX_LWM2M_CLIENT_NOTIFY_OBSERVE (0x00000010) +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN (0x00000020) +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX (0x00000040) +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_GT (0x00000080) +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_LT (0x00000100) +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_STP (0x00000200) +#define NX_LWM2M_CLIENT_NOTIFY_CHANGED (0x00000400) +#define NX_LWM2M_CLIENT_NOTIFY_TIMER (0x00000800) +#define NX_LWM2M_CLIENT_NOTIFY_ACCEPT_TLV (0x00001000) + +#define NX_LWM2M_CLIENT_NOTIFY_ATTR_FLAGS (NX_LWM2M_CLIENT_NOTIFY_ATTR_PMIN | \ + NX_LWM2M_CLIENT_NOTIFY_ATTR_PMAX | \ + NX_LWM2M_CLIENT_NOTIFY_ATTR_GT | \ + NX_LWM2M_CLIENT_NOTIFY_ATTR_LT | \ + NX_LWM2M_CLIENT_NOTIFY_ATTR_STP) + + +/* Define the maximum length of token */ + +#define NX_LWM2M_CLIENT_NOTIFY_TOKEN_MAX_LEN 8 + + +/* Define the notification structure */ + +typedef struct NX_LWM2M_CLIENT_NOTIFY_STRUCT +{ + /* Pointer to the next notification */ + struct NX_LWM2M_CLIENT_NOTIFY_STRUCT *notify_next; + + /* Pointer to the Object */ + NX_LWM2M_CLIENT_OBJECT *notify_object_ptr; + + /* Pointer to the Object Instance */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE *notify_instance_ptr; + + /* The Resource ID */ + NX_LWM2M_ID notify_resource_id; + + /* The ID of the last message */ + USHORT notify_last_id; + + /* Some flags */ + UINT notify_flags; + + /* Token */ + UCHAR notify_token[NX_LWM2M_CLIENT_NOTIFY_TOKEN_MAX_LEN]; + + /* The last notified number value of the resource */ + NX_LWM2M_CLIENT_NOTIFY_NUMBER notify_last_value; + + /* The time of the last notify message */ + ULONG notify_last_time; + + /* Timer expiration time */ + ULONG notify_timer; + + /* The 'Minimum Period' attribute */ + NX_LWM2M_INT32 notify_attr_pmin; + + /* The 'Maximum Period' attribute */ + NX_LWM2M_INT32 notify_attr_pmax; + + /* The 'Greater Than' attribute */ + NX_LWM2M_CLIENT_NOTIFY_NUMBER notify_attr_gt; + + /* The 'Less Than' attribute */ + NX_LWM2M_CLIENT_NOTIFY_NUMBER notify_attr_lt; + + /* The 'Step' attribute */ + NX_LWM2M_CLIENT_NOTIFY_NUMBER notify_attr_stp; + +} NX_LWM2M_CLIENT_NOTIFY; + + +/* Define the DTLS security mode */ + +#define NX_LWM2M_CLIENT_SECURITY_MODE_PRE_SHARED_KEY 0 +#define NX_LWM2M_CLIENT_SECURITY_MODE_RAW_PUBLIC_KEY 1 +#define NX_LWM2M_CLIENT_SECURITY_MODE_CERTIFICATE 2 +#define NX_LWM2M_CLIENT_SECURITY_MODE_NOSEC 3 +#define NX_LWM2M_CLIENT_SECURITY_MODE_UNDEFINED 255 + + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + + +/* define the structure of an instance of the LWM2M Security Object */ + +typedef struct NX_LWM2M_CLIENT_SECURITY_INSTANCE_STRUCT +{ + /* The LWM2M Object Instance structure */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE security_instance; + + /* The Short Server ID */ + NX_LWM2M_ID security_instance_server_id; + + /* Determine if the instance is a Bootstrap Server */ + NX_LWM2M_BOOL security_instance_bootstrap; + + /* The UDP security mode */ + UCHAR security_instance_mode; + + /* The URI of the server */ + CHAR security_instance_server_uri[NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_URI]; + UINT security_instance_server_uri_len; + + /* Hold-off timer */ + NX_LWM2M_INT32 security_instance_hold_off; + + /* Public Key or Identity */ + UCHAR security_instance_pub_key_or_id[NX_LWM2M_CLIENT_SECURITY_MAX_PUBLIC_KEY_OR_IDENTITY]; + UINT security_instance_pub_key_or_id_len; + + /* Server Public Key */ + UCHAR security_instance_server_pub_key[NX_LWM2M_CLIENT_SECURITY_MAX_SERVER_PUBLIC_KEY]; + UINT security_instance_server_pub_key_len; + + /* Secret Key */ + UCHAR security_instance_secret_key[NX_LWM2M_CLIENT_SECURITY_MAX_SECRET_KEY]; + UINT security_instance_secret_key_len; + +} NX_LWM2M_CLIENT_SECURITY_INSTANCE; + + +/* Define the structure of the LWM2M Security Object */ + +typedef struct NX_LWM2M_CLIENT_SECURITY_OBJECT_STRUCT +{ + /* The LWM2M Object structure */ + NX_LWM2M_CLIENT_OBJECT security_object; + + /* The list of free Security Object Instances */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE *security_object_instances_free_list; + + /* The Security Object Instances data */ + NX_LWM2M_CLIENT_SECURITY_INSTANCE security_object_instances[NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES]; + +} NX_LWM2M_CLIENT_SECURITY_OBJECT; + +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + + +/* Define the Current Transport Binding and Mode */ + +#define NX_LWM2M_CLIENT_BINDING_U 0x1 +#define NX_LWM2M_CLIENT_BINDING_UQ 0x3 +#define NX_LWM2M_CLIENT_BINDING_S 0x4 +#define NX_LWM2M_CLIENT_BINDING_SQ 0xc +#define NX_LWM2M_CLIENT_BINDING_US (NX_LWM2M_CLIENT_BINDING_U | NX_LWM2M_CLIENT_BINDING_S) +#define NX_LWM2M_CLIENT_BINDING_UQS (NX_LWM2M_CLIENT_BINDING_UQ | NX_LWM2M_CLIENT_BINDING_S) +#define NX_LWM2M_CLIENT_BINDING_USQ (NX_LWM2M_CLIENT_BINDING_U | NX_LWM2M_CLIENT_BINDING_SQ) +#define NX_LWM2M_CLIENT_BINDING_UQSQ (NX_LWM2M_CLIENT_BINDING_UQ | NX_LWM2M_CLIENT_BINDING_SQ) + + +/* define the structure of an instance of the LWM2M Server Object */ + +typedef struct NX_LWM2M_CLIENT_SERVER_INSTANCE_STRUCT +{ + /* The LWM2M Object Instance structure */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE server_instance; + + /* Short Server ID */ + NX_LWM2M_ID server_instance_short_id; + + /* Notification Storing When Disabled or Offline */ + NX_LWM2M_BOOL server_instance_storing; + + /* Binding */ + UCHAR server_instance_binding; + + /* Lifetime */ + NX_LWM2M_INT32 server_instance_lifetime; + + /* Default Minimum Period */ + NX_LWM2M_INT32 server_instance_min_period; + + /* Default Maximum Period */ + NX_LWM2M_INT32 server_instance_max_period; + + /* Disable Timeout */ + NX_LWM2M_INT32 server_instance_disable_timeout; + +} NX_LWM2M_CLIENT_SERVER_INSTANCE; + + +/* Define the structure of the LWM2M Server Object */ + +typedef struct NX_LWM2M_CLIENT_SERVER_OBJECT_STRUCT +{ + /* The LWM2M Object structure */ + NX_LWM2M_CLIENT_OBJECT server_object; + + /* The list of free Server Object Instances */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE *server_object_instances_free_list; + + /* The Server Object Instances data */ + NX_LWM2M_CLIENT_SERVER_INSTANCE server_object_instances[NX_LWM2M_CLIENT_MAX_SERVER_INSTANCES]; + +} NX_LWM2M_CLIENT_SERVER_OBJECT; + + +#if NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES + +/* Define the ACL structure */ + +typedef struct NX_LWM2M_CLIENT_ACL_STRUCT +{ + /* The server ID */ + NX_LWM2M_ID acl_server_id; + + /* The ACL flags */ + USHORT acl_flags; + +} NX_LWM2M_CLIENT_ACL; + + +/* Define the structure of an instance of the LWM2M Access Control object */ + +typedef struct NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE_STRUCT +{ + /* The LWM2M Object Instance structure */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE access_control_instance; + + /* The Object ID */ + NX_LWM2M_ID access_control_instance_object_id; + + /* The Object Instance ID */ + NX_LWM2M_ID access_control_instance_object_instance_id; + + /* The Access Control Owner */ + NX_LWM2M_ID access_control_instance_owner; + + /* The number of ACL resources */ + USHORT access_control_instance_acl_count; + + /* The array of ACL resources */ + NX_LWM2M_CLIENT_ACL access_control_instance_acl[NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_ACLS]; + +} NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE; + + +/* Define the structure of the LWM2M Access Control Object */ + +typedef struct NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT_STRUCT +{ + /* The LWM2M Object structure */ + NX_LWM2M_CLIENT_OBJECT access_control_object; + + /* The list of free Access Control Object Instances */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE *access_control_object_instances_free_list; + + /* The Access Control Object Instances data */ + NX_LWM2M_CLIENT_ACCESS_CONTROL_INSTANCE access_control_object_instances[NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES]; + +} NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT; + +#endif + +/* Define the Device operation callback */ + +typedef UINT (*NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK)(UINT operation, struct NX_LWM2M_CLIENT_STRUCT *client_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *num_resources, VOID *args_ptr, UINT args_length); + + +/* Define the structure of the LWM2M Device Object */ + +typedef struct NX_LWM2M_CLIENT_DEVICE_OBJECT_STRUCT +{ + /* The LWM2M Object structure */ + NX_LWM2M_CLIENT_OBJECT device_object; + + /* The callback for the operations implemented by the application */ + NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK + device_object_user_operation; + + /* The number of errors */ + USHORT device_object_error_count; + + /* The stack of errors */ + UCHAR device_object_error[NX_LWM2M_CLIENT_MAX_DEVICE_ERRORS]; + + /* The supported binding modes */ + UCHAR device_object_binding_modes; + + /* The single instance of the object */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE device_object_instance; + +} NX_LWM2M_CLIENT_DEVICE_OBJECT; + + +/* Define the LWM2M Firmware Update Object Data Type */ + +typedef struct NX_LWM2M_CLIENT_FIRMWARE_STRUCT NX_LWM2M_CLIENT_FIRMWARE; + + +/* Define the firmware package commands */ + +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_BEGIN 0 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_BLOCK 1 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_END 2 +#define NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_ABORT 3 + + +/* Define the firmware package callback */ + +typedef UINT (*NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK)(NX_LWM2M_CLIENT_FIRMWARE *firmware, UINT command, ULONG block_offset, const VOID *block_ptr, UINT block_length); + + +/* Define the firmware uri callback */ + +typedef UINT (*NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK)(NX_LWM2M_CLIENT_FIRMWARE *firmware, const CHAR *uri, UINT uri_length); + + +/* Define the firmware update callback */ + +typedef UINT (*NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK)(NX_LWM2M_CLIENT_FIRMWARE *firmware, NX_LWM2M_BOOL update_objects, const CHAR *args_ptr, UINT args_length); + + +/* Define the supported protocols of the Firmware Update Object */ + +#define NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_COAP (0x00000001) +#define NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_COAPS (0x00000002) +#define NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_HTTP (0x00000004) +#define NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_HTTPS (0x00000008) + + +/* The maximum number of supported protocols */ + +#define NX_LWM2M_CLIENT_FIRMWARE_MAX_PROTOCOLS 4 + + +/* Define the state of the Firmware Update */ + +#define NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE 0 +#define NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADING 1 +#define NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADED 2 +#define NX_LWM2M_CLIENT_FIRMWARE_STATE_UPDATING 3 + + +/* Define the result of the Firmware Update */ + +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_INIT 0 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_SUCCESS 1 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_NOT_ENOUGHT_FLASH 2 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_OUT_OF_RAM 3 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_CONNECTION_LOST 4 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_INTEGRITY_CHECK_FAILURE 5 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_UNSUPPORTED_PACKAGE_TYPE 6 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_INVALID_URI 7 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_UPDATE_FAILED 8 +#define NX_LWM2M_CLIENT_FIRMWARE_RESULT_UNSUPPORTED_PROTOCOL 9 + + +/* Define the structure of the LWM2M Firmware Update Object */ + +struct NX_LWM2M_CLIENT_FIRMWARE_STRUCT +{ + + /* The LWM2M Object structure */ + NX_LWM2M_CLIENT_OBJECT firmware_object; + + /* The package callback */ + NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK + firmware_package_callback; + + /* The uri callback */ + NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK + firmware_package_uri_callback; + + /* The update callback */ + NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK + firmware_update_callback; + + /* The state of the firmware update */ + UCHAR firmware_state; + + /* The value of Update Supported Objects resource */ + NX_LWM2M_BOOL firmware_update_supported_objects; + + /* The result of the firmware update */ + UCHAR firmware_result; + + /* The number of supported protocols */ + UCHAR firmware_protocols_count; + + /* The list of supported protocols */ + UCHAR firmware_protocols[NX_LWM2M_CLIENT_FIRMWARE_MAX_PROTOCOLS]; + + /* The name of the firmware package */ + const CHAR * firmware_package_name; + + /* The length of the firmware package name */ + UINT firmware_package_name_length; + + /* The version of the firmware package */ + const CHAR * firmware_package_version; + + /* The length of the firmware package version */ + UINT firmware_package_version_length; + + /* The single instance of the object */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE firmware_instance; +}; + + +/* Define a LWM2M Client socket */ +typedef struct NX_LWM2M_CLIENT_SOCKET_STRUCT +{ + /* The UDP Socket */ + NX_UDP_SOCKET udp_socket; + + /* Pointer to the LWM2M Client */ + struct NX_LWM2M_CLIENT_STRUCT *client_ptr; + +} NX_LWM2M_CLIENT_SOCKET; + + +/* Define the LWM2M Client Session Data Type */ + +typedef struct NX_LWM2M_CLIENT_SESSION_STRUCT NX_LWM2M_CLIENT_SESSION; + + +/* Define the LWM2M Client Session State change callback */ + +typedef VOID (*NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK)(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state); + + +/* Define a LWM2M Client Session structure */ + +struct NX_LWM2M_CLIENT_SESSION_STRUCT +{ + + /* Pointer to the next session in list */ + struct NX_LWM2M_CLIENT_SESSION_STRUCT *nx_lwm2m_client_session_next; + + /* Pointer to LWM2M Client */ + struct NX_LWM2M_CLIENT_STRUCT *nx_lwm2m_client_session_client_ptr; + + /* The LWM2M Server Object Instance, NULL for a Bootstrap Server */ + NX_LWM2M_CLIENT_SERVER_INSTANCE *nx_lwm2m_client_session_server_instance_ptr; + + /* The state change callback */ + NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK nx_lwm2m_client_session_state_callback; + + /* The state of the session */ + UINT nx_lwm2m_client_session_state; + + /* The sub-state of the session */ + UINT nx_lwm2m_client_session_substate; + + /* Timer expiration clock value */ + ULONG nx_lwm2m_client_session_timer; + + /* Retransmission timer */ + UINT nx_lwm2m_client_session_retransmit_timer; + + /* Retransmission counter */ + UCHAR nx_lwm2m_client_session_retransmit_count; + + /* Request ID */ + USHORT nx_lwm2m_client_session_request_id; + + /* Token */ + UCHAR nx_lwm2m_client_session_token[NX_LWM2M_CLIENT_COAP_TOKEN_LEN]; + + /* The error code */ + UINT nx_lwm2m_client_session_error; + + /* The address of the server */ + NXD_ADDRESS nx_lwm2m_client_session_server_address; + + /* The port number of the server */ + UINT nx_lwm2m_client_session_server_port; + + /* The security ID (bootstrap) or Short Server ID (LWM2M) */ + NX_LWM2M_ID nx_lwm2m_client_session_server_id; + + /* The Uri-Path option */ + CHAR nx_lwm2m_client_session_uri_path[NX_LWM2M_CLIENT_MAX_COAP_URI_PATH]; + + /* The length of the Uri-Path option */ + UINT nx_lwm2m_client_session_uri_path_length; + + /* Some flags */ + UINT nx_lwm2m_client_session_flags; + + /* Pointer to the list of notifications for this session */ + NX_LWM2M_CLIENT_NOTIFY *nx_lwm2m_client_session_notifications; + +#ifdef NX_SECURE_ENABLE_DTLS + /* The socket used for the DTLS connection */ + NX_LWM2M_CLIENT_SOCKET nx_lwm2m_client_session_dtls_socket; + + /* The DTLS session */ + NX_SECURE_DTLS_SESSION *nx_lwm2m_client_session_dtls_session; +#endif /* NX_SECURE_ENABLE_DTLS */ + +}; + + +/* Define the state of the LWM2M Client Session */ + +#define NX_LWM2M_CLIENT_SESSION_INIT 0 + +#define NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_WAITING 1 +#define NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING 2 +#define NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED 3 +#define NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED 4 +#define NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR 5 + +#define NX_LWM2M_CLIENT_SESSION_REGISTERING 6 +#define NX_LWM2M_CLIENT_SESSION_REGISTERED 7 +#define NX_LWM2M_CLIENT_SESSION_UPDATING 8 +#define NX_LWM2M_CLIENT_SESSION_DISABLING 9 +#define NX_LWM2M_CLIENT_SESSION_DEREGISTERING 10 +#define NX_LWM2M_CLIENT_SESSION_DEREGISTERED 11 +#define NX_LWM2M_CLIENT_SESSION_DISABLED 12 +#define NX_LWM2M_CLIENT_SESSION_ERROR 13 + + +/* Define the structure of a LWM2M Client */ + +typedef struct NX_LWM2M_CLIENT_STRUCT +{ + /* The mutex used to protect concurrent accesses to the LWM2M Client */ + TX_MUTEX nx_lwm2m_client_mutex; + + /* Pointer to the LWM2M Client endpoint name */ + const CHAR *nx_lwm2m_client_name; + + /* The length of LWM2M Client endpoint name */ + UINT nx_lwm2m_client_name_length; + + /* Pointer to the MSISDN where the LWM2M Client can be reached */ + const CHAR *nx_lwm2m_client_msisdn; + + /* The length of MSISDN */ + UINT nx_lwm2m_client_msisdn_length; + + /* Pointer to IP instance */ + NX_IP *nx_lwm2m_client_ip_ptr; + + /* Pointer to IP Packet Pool */ + NX_PACKET_POOL *nx_lwm2m_client_pool_ptr; + + /* The list of free notifications */ + NX_LWM2M_CLIENT_NOTIFY *nx_lwm2m_client_notifications_free_list; + + /* The notification structures */ + NX_LWM2M_CLIENT_NOTIFY nx_lwm2m_client_notifications[NX_LWM2M_CLIENT_MAX_NOTIFICATIONS]; + + /* The list of sessions of the LWM2M Client*/ + NX_LWM2M_CLIENT_SESSION *nx_lwm2m_client_sessions; + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES + /* The Security Object */ + NX_LWM2M_CLIENT_SECURITY_OBJECT nx_lwm2m_client_security; +#endif + + /* The Server Object */ + NX_LWM2M_CLIENT_SERVER_OBJECT nx_lwm2m_client_server; + +#if NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES + /* The Access Control Object */ + NX_LWM2M_CLIENT_ACCESS_CONTROL_OBJECT nx_lwm2m_client_access_control; +#endif + + /* The Device Object */ + NX_LWM2M_CLIENT_DEVICE_OBJECT nx_lwm2m_client_device; + + /* The head of Object list */ + NX_LWM2M_CLIENT_OBJECT *nx_lwm2m_client_object_list_head; + + /* The events flags */ + TX_EVENT_FLAGS_GROUP nx_lwm2m_client_event_flags; + + /* The CoAP socket */ + NX_LWM2M_CLIENT_SOCKET nx_lwm2m_client_coap_socket; + + /* Request ID generator */ + USHORT nx_lwm2m_client_request_id; + + /* The LWM2M Client thread */ + TX_THREAD nx_lwm2m_client_thread; + + /* Temporary storage for requests resources */ + NX_LWM2M_CLIENT_RESOURCE nx_lwm2m_client_temp_resources[NX_LWM2M_CLIENT_MAX_RESOURCES]; + + /* Temporary storage for multiple resources */ + NX_LWM2M_CLIENT_RESOURCE nx_lwm2m_client_mulitple_temp_resources[NX_LWM2M_CLIENT_MAX_MULTIPLE_RESOURCES]; + + /* Temporary storage for requests options */ + NX_LWM2M_CLIENT_REQUEST_OPTIONS nx_lwm2m_client_request_options; + +} NX_LWM2M_CLIENT; + + +/* TLV Header Type field: */ + +/* Bit 7-6: Indicates the type of Identifier */ +#define NX_LWM2M_CLIENT_TLV_TYPE_ID_TYPE_MASK 0xc0 + +#define NX_LWM2M_CLIENT_TLV_OBJECT_INSTANCE 0x00 +#define NX_LWM2M_CLIENT_TLV_RESOURCE_INSTANCE 0x40 +#define NX_LWM2M_CLIENT_TLV_RESOURCE_MULTIPLE 0x80 +#define NX_LWM2M_CLIENT_TLV_RESOURCE_VALUE 0xc0 + +/* Bit 5: Indicates the Length of the Identifier */ +#define NX_LWM2M_CLIENT_TLV_TYPE_ID_LENGTH 0x20 + +/* Bit 4-3: Indicate the type of Length */ +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_TYPE_MASK 0x18 +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_NONE 0x00 +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_8_BIT 0x08 +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_16_BIT 0x10 +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_24_BIT 0x18 + +/* Bit 2-0: Indicate the Length of the Value */ +#define NX_LWM2M_CLIENT_TLV_TYPE_LENGTH_MASK 0x07 + +/* Length of fixed-size TLV Values */ +#define NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER8 1 +#define NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER16 2 +#define NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER32 4 +#define NX_LWM2M_CLIENT_TLV_LENGTH_INTEGER64 8 +#define NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT32 4 +#define NX_LWM2M_CLIENT_TLV_LENGTH_FLOAT64 8 +#define NX_LWM2M_CLIENT_TLV_LENGTH_BOOLEAN 1 +#define NX_LWM2M_CLIENT_TLV_LENGTH_OBJLNK 4 + + +/* Define the maximum length of a string representing an ID (unsigned 16-bit integer) */ + +#define NX_LWM2M_CLIENT_STRCONV_ID_MAXLEN 5 /* '65535' */ + +/* Define the maximum length of a string representing a 32-bit integer */ + +#define NX_LWM2M_CLIENT_STRCONV_INT32_MAXLEN 11 /* '-2147483647' */ + +/* Define the number of digital placed after decimal */ + +#define NX_LWM2M_CLIENT_DOUBLE_DECIMAL_PLACE_DIGITS 2 + + +/* Define CoAP constants. */ + +#define NX_LWM2M_CLIENT_COAP_HEADER_LEN 4 + +#define NX_LWM2M_CLIENT_COAP_VERSION_1 0x40 +#define NX_LWM2M_CLIENT_COAP_VERSION_MASK 0xc0 + +#define NX_LWM2M_CLIENT_COAP_TYPE_MASK 0x30 +#define NX_LWM2M_CLIENT_COAP_TYPE_CON 0x00 +#define NX_LWM2M_CLIENT_COAP_TYPE_NON 0x10 +#define NX_LWM2M_CLIENT_COAP_TYPE_ACK 0x20 +#define NX_LWM2M_CLIENT_COAP_TYPE_RST 0x30 + +#define NX_LWM2M_CLIENT_COAP_TOKEN_LEN_MASK 0x0f + +#define NX_LWM2M_CLIENT_COAP_TOKEN_MAXLEN 8 + +#define NX_LWM2M_CLIENT_COAP_CLASS_MASK 0xe0 + +#define NX_LWM2M_CLIENT_COAP_CLASS_REQUEST 0x00 +#define NX_LWM2M_CLIENT_COAP_CLASS_SUCCESS 0x40 +#define NX_LWM2M_CLIENT_COAP_CLASS_CLIENT_ERROR 0x80 +#define NX_LWM2M_CLIENT_COAP_CLASS_SERVER_ERROR 0xa0 + +#define NX_LWM2M_CLIENT_COAP_REQUEST_GET 0x01 +#define NX_LWM2M_CLIENT_COAP_REQUEST_POST 0x02 +#define NX_LWM2M_CLIENT_COAP_REQUEST_PUT 0x03 +#define NX_LWM2M_CLIENT_COAP_REQUEST_DELETE 0x04 + +#define NX_LWM2M_CLIENT_COAP_CODE(c,dd) (((c)<<5)|(dd)) + +#define NX_LWM2M_CLIENT_COAP_STATUS_CREATED NX_LWM2M_CLIENT_COAP_CODE(2,1) +#define NX_LWM2M_CLIENT_COAP_STATUS_DELETED NX_LWM2M_CLIENT_COAP_CODE(2,2) +#define NX_LWM2M_CLIENT_COAP_STATUS_CHANGED NX_LWM2M_CLIENT_COAP_CODE(2,4) +#define NX_LWM2M_CLIENT_COAP_STATUS_CONTENT NX_LWM2M_CLIENT_COAP_CODE(2,5) + +#define NX_LWM2M_CLIENT_COAP_STATUS_BAD_REQUEST NX_LWM2M_CLIENT_COAP_CODE(4,0) +#define NX_LWM2M_CLIENT_COAP_STATUS_UNAUTHORIZED NX_LWM2M_CLIENT_COAP_CODE(4,1) +#define NX_LWM2M_CLIENT_COAP_STATUS_NOT_FOUND NX_LWM2M_CLIENT_COAP_CODE(4,4) +#define NX_LWM2M_CLIENT_COAP_STATUS_METHOD_NOT_ALLOWED NX_LWM2M_CLIENT_COAP_CODE(4,5) +#define NX_LWM2M_CLIENT_COAP_STATUS_NOT_ACCEPTABLE NX_LWM2M_CLIENT_COAP_CODE(4,6) + +#define NX_LWM2M_CLIENT_COAP_STATUS_INTERNAL_SERVER_ERROR NX_LWM2M_CLIENT_COAP_CODE(5,0) + +#define NX_LWM2M_CLIENT_COAP_PAYLOAD_MARKER 0xff + +#define NX_LWM2M_CLIENT_COAP_OPTION_NONE 0 +#define NX_LWM2M_CLIENT_COAP_OPTION_OBSERVE 6 +#define NX_LWM2M_CLIENT_COAP_OPTION_LOCATION_PATH 8 +#define NX_LWM2M_CLIENT_COAP_OPTION_URI_PATH 11 +#define NX_LWM2M_CLIENT_COAP_OPTION_CONTENT_FORMAT 12 +#define NX_LWM2M_CLIENT_COAP_OPTION_URI_QUERY 15 +#define NX_LWM2M_CLIENT_COAP_OPTION_ACCEPT 17 + +#define NX_LWM2M_CLIENT_COAP_CONTENT_TEXT_PLAIN 0 +#define NX_LWM2M_CLIENT_COAP_CONTENT_LINK_FORMAT 40 +#define NX_LWM2M_CLIENT_COAP_CONTENT_OCTET_STREAM 42 +#define NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_TLV 11542 +#define NX_LWM2M_CLIENT_COAP_CONTENT_VND_OMA_LWM2M_JSON 11543 + + +#ifndef NX_LWM2M_CLIENT_SOURCE_CODE +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + +#ifdef NX_DISABLE_ERROR_CHECKING + +#define nx_lwm2m_client_create _nx_lwm2m_client_create +#define nx_lwm2m_client_delete _nx_lwm2m_client_delete +#define nx_lwm2m_client_lock _nx_lwm2m_client_lock +#define nx_lwm2m_client_unlock _nx_lwm2m_client_unlock +#define nx_lwm2m_client_object_add _nx_lwm2m_client_object_add +#define nx_lwm2m_client_object_remove _nx_lwm2m_client_object_remove +#define nx_lwm2m_client_object_resource_changed _nx_lwm2m_client_object_resource_changed +#define nx_lwm2m_client_device_callback_set _nx_lwm2m_client_device_callback_set +#define nx_lwm2m_client_device_resource_changed _nx_lwm2m_client_device_resource_changed +#define nx_lwm2m_client_device_error_push _nx_lwm2m_client_device_error_push +#define nx_lwm2m_client_device_error_reset _nx_lwm2m_client_device_error_reset +#define nx_lwm2m_client_object_next_get _nx_lwm2m_client_object_next_get +#define nx_lwm2m_client_object_instance_next_get _nx_lwm2m_client_object_instance_next_get +#define nx_lwm2m_client_object_read _nx_lwm2m_client_object_read +#define nx_lwm2m_client_object_discover _nx_lwm2m_client_object_discover +#define nx_lwm2m_client_object_write _nx_lwm2m_client_object_write +#define nx_lwm2m_client_object_execute _nx_lwm2m_client_object_execute +#define nx_lwm2m_client_object_create _nx_lwm2m_client_object_create +#define nx_lwm2m_client_object_delete _nx_lwm2m_client_object_delete +#define nx_lwm2m_client_object_instance_add _nx_lwm2m_client_object_instance_add +#define nx_lwm2m_client_object_instance_remove _nx_lwm2m_client_object_instance_remove +#define nx_lwm2m_client_session_create _nx_lwm2m_client_session_create +#define nx_lwm2m_client_session_delete _nx_lwm2m_client_session_delete +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +#define nx_lwm2m_client_session_bootstrap _nx_lwm2m_client_session_bootstrap +#define nx_lwm2m_client_session_register_info_get _nx_lwm2m_client_session_register_info_get +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +#define nx_lwm2m_client_session_register _nx_lwm2m_client_session_register +#define nx_lwm2m_client_session_update _nx_lwm2m_client_session_update +#define nx_lwm2m_client_session_deregister _nx_lwm2m_client_session_deregister +#define nx_lwm2m_client_session_error_get _nx_lwm2m_client_session_error_get +#ifdef NX_SECURE_ENABLE_DTLS +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +#define nx_lwm2m_client_session_bootstrap_dtls _nx_lwm2m_client_session_bootstrap_dtls +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +#define nx_lwm2m_client_session_register_dtls _nx_lwm2m_client_session_register_dtls +#endif /* NX_SECURE_ENABLE_DTLS */ +#define nx_lwm2m_client_firmware_create _nx_lwm2m_client_firmware_create +#define nx_lwm2m_client_firmware_state_set _nx_lwm2m_client_firmware_state_set +#define nx_lwm2m_client_firmware_result_set _nx_lwm2m_client_firmware_result_set +#define nx_lwm2m_client_firmware_package_info_set _nx_lwm2m_client_firmware_package_info_set +#define nx_lwm2m_client_resource_info_get _nx_lwm2m_client_resource_info_get +#define nx_lwm2m_client_resource_dim_get _nx_lwm2m_client_resource_dim_get +#define nx_lwm2m_client_resource_instances_get _nx_lwm2m_client_resource_instances_get +#define nx_lwm2m_client_resource_string_get _nx_lwm2m_client_resource_string_get +#define nx_lwm2m_client_resource_integer32_get _nx_lwm2m_client_resource_integer32_get +#define nx_lwm2m_client_resource_integer64_get _nx_lwm2m_client_resource_integer64_get +#define nx_lwm2m_client_resource_float32_get _nx_lwm2m_client_resource_float32_get +#define nx_lwm2m_client_resource_float64_get _nx_lwm2m_client_resource_float64_get +#define nx_lwm2m_client_resource_boolean_get _nx_lwm2m_client_resource_boolean_get +#define nx_lwm2m_client_resource_objlnk_get _nx_lwm2m_client_resource_objlnk_get +#define nx_lwm2m_client_resource_opaque_get _nx_lwm2m_client_resource_opaque_get +#define nx_lwm2m_client_resource_info_set _nx_lwm2m_client_resource_info_set +#define nx_lwm2m_client_resource_dim_set _nx_lwm2m_client_resource_dim_set +#define nx_lwm2m_client_resource_instances_set _nx_lwm2m_client_resource_instances_set +#define nx_lwm2m_client_resource_string_set _nx_lwm2m_client_resource_string_set +#define nx_lwm2m_client_resource_integer32_set _nx_lwm2m_client_resource_integer32_set +#define nx_lwm2m_client_resource_integer64_set _nx_lwm2m_client_resource_integer64_set +#define nx_lwm2m_client_resource_float32_set _nx_lwm2m_client_resource_float32_set +#define nx_lwm2m_client_resource_float64_set _nx_lwm2m_client_resource_float64_set +#define nx_lwm2m_client_resource_boolean_set _nx_lwm2m_client_resource_boolean_set +#define nx_lwm2m_client_resource_objlnk_set _nx_lwm2m_client_resource_objlnk_set +#define nx_lwm2m_client_resource_opaque_set _nx_lwm2m_client_resource_opaque_set + +#else + +#define nx_lwm2m_client_create _nxe_lwm2m_client_create +#define nx_lwm2m_client_delete _nxe_lwm2m_client_delete +#define nx_lwm2m_client_lock _nxe_lwm2m_client_lock +#define nx_lwm2m_client_unlock _nxe_lwm2m_client_unlock +#define nx_lwm2m_client_object_add _nxe_lwm2m_client_object_add +#define nx_lwm2m_client_object_remove _nxe_lwm2m_client_object_remove +#define nx_lwm2m_client_object_resource_changed _nxe_lwm2m_client_object_resource_changed +#define nx_lwm2m_client_device_callback_set _nxe_lwm2m_client_device_callback_set +#define nx_lwm2m_client_device_resource_changed _nxe_lwm2m_client_device_resource_changed +#define nx_lwm2m_client_device_error_push _nxe_lwm2m_client_device_error_push +#define nx_lwm2m_client_device_error_reset _nxe_lwm2m_client_device_error_reset +#define nx_lwm2m_client_object_next_get _nxe_lwm2m_client_object_next_get +#define nx_lwm2m_client_object_instance_next_get _nxe_lwm2m_client_object_instance_next_get +#define nx_lwm2m_client_object_read _nxe_lwm2m_client_object_read +#define nx_lwm2m_client_object_discover _nxe_lwm2m_client_object_discover +#define nx_lwm2m_client_object_write _nxe_lwm2m_client_object_write +#define nx_lwm2m_client_object_execute _nxe_lwm2m_client_object_execute +#define nx_lwm2m_client_object_create _nxe_lwm2m_client_object_create +#define nx_lwm2m_client_object_delete _nxe_lwm2m_client_object_delete +#define nx_lwm2m_client_object_instance_add _nxe_lwm2m_client_object_instance_add +#define nx_lwm2m_client_object_instance_remove _nxe_lwm2m_client_object_instance_remove +#define nx_lwm2m_client_session_create _nxe_lwm2m_client_session_create +#define nx_lwm2m_client_session_delete _nxe_lwm2m_client_session_delete +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +#define nx_lwm2m_client_session_bootstrap _nxe_lwm2m_client_session_bootstrap +#define nx_lwm2m_client_session_register_info_get _nxe_lwm2m_client_session_register_info_get +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +#define nx_lwm2m_client_session_register _nxe_lwm2m_client_session_register +#define nx_lwm2m_client_session_update _nxe_lwm2m_client_session_update +#define nx_lwm2m_client_session_deregister _nxe_lwm2m_client_session_deregister +#define nx_lwm2m_client_session_error_get _nxe_lwm2m_client_session_error_get +#ifdef NX_SECURE_ENABLE_DTLS +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +#define nx_lwm2m_client_session_bootstrap_dtls _nxe_lwm2m_client_session_bootstrap_dtls +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +#define nx_lwm2m_client_session_register_dtls _nxe_lwm2m_client_session_register_dtls +#endif /* NX_SECURE_ENABLE_DTLS */ +#define nx_lwm2m_client_firmware_create _nxe_lwm2m_client_firmware_create +#define nx_lwm2m_client_firmware_state_set _nxe_lwm2m_client_firmware_state_set +#define nx_lwm2m_client_firmware_result_set _nxe_lwm2m_client_firmware_result_set +#define nx_lwm2m_client_firmware_package_info_set _nxe_lwm2m_client_firmware_package_info_set +#define nx_lwm2m_client_resource_info_get _nxe_lwm2m_client_resource_info_get +#define nx_lwm2m_client_resource_dim_get _nxe_lwm2m_client_resource_dim_get +#define nx_lwm2m_client_resource_instances_get _nxe_lwm2m_client_resource_instances_get +#define nx_lwm2m_client_resource_string_get _nxe_lwm2m_client_resource_string_get +#define nx_lwm2m_client_resource_integer32_get _nxe_lwm2m_client_resource_integer32_get +#define nx_lwm2m_client_resource_integer64_get _nxe_lwm2m_client_resource_integer64_get +#define nx_lwm2m_client_resource_float32_get _nxe_lwm2m_client_resource_float32_get +#define nx_lwm2m_client_resource_float64_get _nxe_lwm2m_client_resource_float64_get +#define nx_lwm2m_client_resource_boolean_get _nxe_lwm2m_client_resource_boolean_get +#define nx_lwm2m_client_resource_objlnk_get _nxe_lwm2m_client_resource_objlnk_get +#define nx_lwm2m_client_resource_opaque_get _nxe_lwm2m_client_resource_opaque_get +#define nx_lwm2m_client_resource_info_set _nxe_lwm2m_client_resource_info_set +#define nx_lwm2m_client_resource_dim_set _nxe_lwm2m_client_resource_dim_set +#define nx_lwm2m_client_resource_instances_set _nxe_lwm2m_client_resource_instances_set +#define nx_lwm2m_client_resource_string_set _nxe_lwm2m_client_resource_string_set +#define nx_lwm2m_client_resource_integer32_set _nxe_lwm2m_client_resource_integer32_set +#define nx_lwm2m_client_resource_integer64_set _nxe_lwm2m_client_resource_integer64_set +#define nx_lwm2m_client_resource_float32_set _nxe_lwm2m_client_resource_float32_set +#define nx_lwm2m_client_resource_float64_set _nxe_lwm2m_client_resource_float64_set +#define nx_lwm2m_client_resource_boolean_set _nxe_lwm2m_client_resource_boolean_set +#define nx_lwm2m_client_resource_objlnk_set _nxe_lwm2m_client_resource_objlnk_set +#define nx_lwm2m_client_resource_opaque_set _nxe_lwm2m_client_resource_opaque_set + +#endif + + +/* Define the functions prototypes. */ + +/* Client Management */ +UINT nx_lwm2m_client_create(NX_LWM2M_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool_ptr, + const CHAR *name_ptr, UINT name_length, const CHAR *msisdn_ptr, UINT msisdn_length, + UCHAR binding_modes, VOID *stack_ptr, ULONG stack_size, UINT priority); +UINT nx_lwm2m_client_delete(NX_LWM2M_CLIENT *client_ptr); +UINT nx_lwm2m_client_lock(NX_LWM2M_CLIENT *client_ptr); +UINT nx_lwm2m_client_unlock(NX_LWM2M_CLIENT *client_ptr); +UINT nx_lwm2m_client_object_add(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID object_id, + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK object_operation); +UINT nx_lwm2m_client_object_remove(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr); + +/* Objects Implementation */ +UINT nx_lwm2m_client_object_resource_changed(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); + +/* Device Object Implementation */ +UINT nx_lwm2m_client_device_callback_set(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK operation_callback); +UINT nx_lwm2m_client_device_resource_changed(NX_LWM2M_CLIENT *client_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); +UINT nx_lwm2m_client_device_error_push(NX_LWM2M_CLIENT *client_ptr, UCHAR code); +UINT nx_lwm2m_client_device_error_reset(NX_LWM2M_CLIENT *client_ptr); + +/* Local Device Management */ +UINT nx_lwm2m_client_object_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID *object_id_ptr); +UINT nx_lwm2m_client_object_instance_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr); +UINT nx_lwm2m_client_object_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, NX_LWM2M_CLIENT_RESOURCE *values); +UINT nx_lwm2m_client_object_discover(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT *num_resources, NX_LWM2M_CLIENT_RESOURCE *resources); +UINT nx_lwm2m_client_object_write(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, UINT write_op); +UINT nx_lwm2m_client_object_execute(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length); +UINT nx_lwm2m_client_object_create(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values); +UINT nx_lwm2m_client_object_delete(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT nx_lwm2m_client_object_instance_add(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID *instance_id_ptr); +UINT nx_lwm2m_client_object_instance_remove(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr); + +/* Client Session Management */ +UINT nx_lwm2m_client_session_create(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK state_callback); +UINT nx_lwm2m_client_session_delete(NX_LWM2M_CLIENT_SESSION *session_ptr); +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +UINT nx_lwm2m_client_session_bootstrap(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port); +UINT nx_lwm2m_client_session_register_info_get(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT security_instance_id, NX_LWM2M_ID *server_id, CHAR **server_uri, UINT *server_uri_len, UCHAR *security_mode, + UCHAR **pub_key_or_id, UINT *pub_key_or_id_len, UCHAR **server_pub_key, UINT *server_pub_key_len, UCHAR **secret_key, UINT *secret_key_len); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +UINT nx_lwm2m_client_session_register(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port); +UINT nx_lwm2m_client_session_update(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT nx_lwm2m_client_session_deregister(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT nx_lwm2m_client_session_error_get(NX_LWM2M_CLIENT_SESSION *session_ptr); +#ifdef NX_SECURE_ENABLE_DTLS +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +UINT nx_lwm2m_client_session_bootstrap_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +UINT nx_lwm2m_client_session_register_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +#endif /* NX_SECURE_ENABLE_DTLS */ + +/* Get Resource Value */ +UINT nx_lwm2m_client_resource_info_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID *resource_id, ULONG *operation); +UINT nx_lwm2m_client_resource_dim_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR *dim); +UINT nx_lwm2m_client_resource_string_get(NX_LWM2M_CLIENT_RESOURCE *value, const CHAR **string_ptr, UINT *string_length); +UINT nx_lwm2m_client_resource_integer32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT32 *int32_ptr); +UINT nx_lwm2m_client_resource_integer64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT64 *int64_ptr); +UINT nx_lwm2m_client_resource_float32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT32 *float32_ptr); +UINT nx_lwm2m_client_resource_float64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT64 *float64_ptr); +UINT nx_lwm2m_client_resource_boolean_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_BOOL *bool_ptr); +UINT nx_lwm2m_client_resource_objlnk_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_ID *object_id, NX_LWM2M_ID *instance_id); +UINT nx_lwm2m_client_resource_opaque_get(NX_LWM2M_CLIENT_RESOURCE *value, const VOID **opaque_ptr, UINT *opaque_length); +UINT nx_lwm2m_client_resource_instances_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT *count); + +/* Set Resource Value */ +UINT nx_lwm2m_client_resource_info_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID resource_id, ULONG operation); +UINT nx_lwm2m_client_resource_dim_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR dim); +UINT nx_lwm2m_client_resource_string_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, CHAR *string_ptr, UINT string_length); +UINT nx_lwm2m_client_resource_integer32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT32 int32_data); +UINT nx_lwm2m_client_resource_integer64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT64 int64_data); +UINT nx_lwm2m_client_resource_float32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT32 float32_data); +UINT nx_lwm2m_client_resource_float64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT64 float64_data); +UINT nx_lwm2m_client_resource_boolean_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_BOOL bool_data); +UINT nx_lwm2m_client_resource_objlnk_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT nx_lwm2m_client_resource_opaque_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, VOID *opaque_ptr, UINT opaque_length); +UINT nx_lwm2m_client_resource_instances_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT count); + +/* Firmware Update Object */ +UINT nx_lwm2m_client_firmware_create(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_CLIENT *client_ptr, UINT protocols, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK package_callback, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK package_uri_callback, NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK update_callback); +UINT nx_lwm2m_client_firmware_state_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR state); +UINT nx_lwm2m_client_firmware_result_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR result); +UINT nx_lwm2m_client_firmware_package_info_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *name, UINT name_length, const CHAR *version, UINT version_length); + +#else + +/* Define the functions prototypes. */ + +/* Client Management */ +UINT _nx_lwm2m_client_create(NX_LWM2M_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool_ptr, + const CHAR *name_ptr, UINT name_length, const CHAR *msisdn_ptr, UINT msisdn_length, + UCHAR binding_modes, VOID *stack_ptr, ULONG stack_size, UINT priority); +UINT _nxe_lwm2m_client_create(NX_LWM2M_CLIENT *client_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool_ptr, + const CHAR *name_ptr, UINT name_length, const CHAR *msisdn_ptr, UINT msisdn_length, + UCHAR binding_modes, VOID *stack_ptr, ULONG stack_size, UINT priority); +UINT _nx_lwm2m_client_delete(NX_LWM2M_CLIENT *client_ptr); +UINT _nxe_lwm2m_client_delete(NX_LWM2M_CLIENT *client_ptr); +UINT _nx_lwm2m_client_lock(NX_LWM2M_CLIENT *client_ptr); +UINT _nxe_lwm2m_client_lock(NX_LWM2M_CLIENT *client_ptr); +UINT _nx_lwm2m_client_unlock(NX_LWM2M_CLIENT *client_ptr); +UINT _nxe_lwm2m_client_unlock(NX_LWM2M_CLIENT *client_ptr); +UINT _nx_lwm2m_client_object_add(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID object_id, + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK object_operation); +UINT _nxe_lwm2m_client_object_add(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID object_id, + NX_LWM2M_CLIENT_OBJECT_OPERATION_CALLBACK object_operation); +UINT _nx_lwm2m_client_object_remove(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr); +UINT _nxe_lwm2m_client_object_remove(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr); + +/* Objects Implementation */ +UINT _nx_lwm2m_client_object_resource_changed(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); +UINT _nxe_lwm2m_client_object_resource_changed(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); + +/* Device Object Implementation */ +UINT _nx_lwm2m_client_device_callback_set(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK operation_callback); +UINT _nxe_lwm2m_client_device_callback_set(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_DEVICE_OPERATION_CALLBACK operation_callback); +UINT _nx_lwm2m_client_device_resource_changed(NX_LWM2M_CLIENT *client_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); +UINT _nxe_lwm2m_client_device_resource_changed(NX_LWM2M_CLIENT *client_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource); +UINT _nx_lwm2m_client_device_error_push(NX_LWM2M_CLIENT *client_ptr, UCHAR code); +UINT _nxe_lwm2m_client_device_error_push(NX_LWM2M_CLIENT *client_ptr, UCHAR code); +UINT _nx_lwm2m_client_device_error_reset(NX_LWM2M_CLIENT *client_ptr); +UINT _nxe_lwm2m_client_device_error_reset(NX_LWM2M_CLIENT *client_ptr); + +/* Local Device Management */ +UINT _nx_lwm2m_client_object_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID *object_id_ptr); +UINT _nxe_lwm2m_client_object_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID *object_id_ptr); +UINT _nx_lwm2m_client_object_instance_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr); +UINT _nxe_lwm2m_client_object_instance_next_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr); +UINT _nx_lwm2m_client_object_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, NX_LWM2M_CLIENT_RESOURCE *values); +UINT _nxe_lwm2m_client_object_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, NX_LWM2M_CLIENT_RESOURCE *values); +UINT _nx_lwm2m_client_object_discover(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT *num_resources, NX_LWM2M_CLIENT_RESOURCE *resources); +UINT _nxe_lwm2m_client_object_discover(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT *num_resources, NX_LWM2M_CLIENT_RESOURCE *resources); +UINT _nx_lwm2m_client_object_write(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, UINT write_op); +UINT _nxe_lwm2m_client_object_write(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, UINT write_op); +UINT _nx_lwm2m_client_object_execute(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length); +UINT _nxe_lwm2m_client_object_execute(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id, const CHAR *args_ptr, UINT args_length); +UINT _nx_lwm2m_client_object_create(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values); +UINT _nxe_lwm2m_client_object_create(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values); +UINT _nx_lwm2m_client_object_delete(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT _nxe_lwm2m_client_object_delete(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT _nx_lwm2m_client_object_instance_add(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID *instance_id_ptr); +UINT _nxe_lwm2m_client_object_instance_add(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID *instance_id_ptr); +UINT _nx_lwm2m_client_object_instance_remove(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr); +UINT _nxe_lwm2m_client_object_instance_remove(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr); + +/* Client Session Management */ +UINT _nx_lwm2m_client_session_create(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK state_callback); +UINT _nxe_lwm2m_client_session_create(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_SESSION_STATE_CALLBACK state_callback); +UINT _nx_lwm2m_client_session_delete(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nxe_lwm2m_client_session_delete(NX_LWM2M_CLIENT_SESSION *session_ptr); +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +UINT _nx_lwm2m_client_session_bootstrap(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port); +UINT _nxe_lwm2m_client_session_bootstrap(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port); +UINT _nx_lwm2m_client_session_register_info_get(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT security_instance_id, NX_LWM2M_ID *server_id, CHAR **server_uri, UINT *server_uri_len, UCHAR *security_mode, + UCHAR **pub_key_or_id, UINT *pub_key_or_id_len, UCHAR **server_pub_key, UINT *server_pub_key_len, UCHAR **secret_key, UINT *secret_key_len); +UINT _nxe_lwm2m_client_session_register_info_get(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT security_instance_id, NX_LWM2M_ID *server_id, CHAR **server_uri, UINT *server_uri_len, UCHAR *security_mode, + UCHAR **pub_key_or_id, UINT *pub_key_or_id_len, UCHAR **server_pub_key, UINT *server_pub_key_len, UCHAR **secret_key, UINT *secret_key_len); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +UINT _nx_lwm2m_client_session_register(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port); +UINT _nxe_lwm2m_client_session_register(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port); +UINT _nx_lwm2m_client_session_update(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nxe_lwm2m_client_session_update(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nx_lwm2m_client_session_deregister(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nxe_lwm2m_client_session_deregister(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nx_lwm2m_client_session_error_get(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nxe_lwm2m_client_session_error_get(NX_LWM2M_CLIENT_SESSION *session_ptr); +#ifdef NX_SECURE_ENABLE_DTLS +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +UINT _nx_lwm2m_client_session_bootstrap_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +UINT _nxe_lwm2m_client_session_bootstrap_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID security_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ +UINT _nx_lwm2m_client_session_register_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +UINT _nxe_lwm2m_client_session_register_dtls(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +#endif /* NX_SECURE_ENABLE_DTLS */ + +/* Get Resource Value */ +UINT _nx_lwm2m_client_resource_info_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID *resource_id, ULONG *operation); +UINT _nxe_lwm2m_client_resource_info_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID *resource_id, ULONG *operation); +UINT _nx_lwm2m_client_resource_dim_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR *dim); +UINT _nxe_lwm2m_client_resource_dim_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR *dim); +UINT _nx_lwm2m_client_resource_string_get(NX_LWM2M_CLIENT_RESOURCE *value, const CHAR **string_ptr, UINT *string_length); +UINT _nxe_lwm2m_client_resource_string_get(NX_LWM2M_CLIENT_RESOURCE *value, const CHAR **string_ptr, UINT *string_length); +UINT _nx_lwm2m_client_resource_integer32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT32 *int32_ptr); +UINT _nxe_lwm2m_client_resource_integer32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT32 *int32_ptr); +UINT _nx_lwm2m_client_resource_integer64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT64 *int64_ptr); +UINT _nxe_lwm2m_client_resource_integer64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_INT64 *int64_ptr); +UINT _nx_lwm2m_client_resource_float32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT32 *float32_ptr); +UINT _nxe_lwm2m_client_resource_float32_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT32 *float32_ptr); +UINT _nx_lwm2m_client_resource_float64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT64 *float64_ptr); +UINT _nxe_lwm2m_client_resource_float64_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_FLOAT64 *float64_ptr); +UINT _nx_lwm2m_client_resource_boolean_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_BOOL *bool_ptr); +UINT _nxe_lwm2m_client_resource_boolean_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_BOOL *bool_ptr); +UINT _nx_lwm2m_client_resource_objlnk_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_ID *object_id, NX_LWM2M_ID *instance_id); +UINT _nxe_lwm2m_client_resource_objlnk_get(NX_LWM2M_CLIENT_RESOURCE *value, NX_LWM2M_ID *object_id, NX_LWM2M_ID *instance_id); +UINT _nx_lwm2m_client_resource_opaque_get(NX_LWM2M_CLIENT_RESOURCE *value, const VOID **opaque_ptr, UINT *opaque_length); +UINT _nxe_lwm2m_client_resource_opaque_get(NX_LWM2M_CLIENT_RESOURCE *value, const VOID **opaque_ptr, UINT *opaque_length); +UINT _nx_lwm2m_client_resource_instances_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT *count); +UINT _nxe_lwm2m_client_resource_instances_get(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT *count); + +/* Set Resource Value */ +UINT _nx_lwm2m_client_resource_info_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID resource_id, ULONG operation); +UINT _nxe_lwm2m_client_resource_info_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID resource_id, ULONG operation); +UINT _nx_lwm2m_client_resource_dim_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR dim); +UINT _nxe_lwm2m_client_resource_dim_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UCHAR dim); +UINT _nx_lwm2m_client_resource_string_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, CHAR *string_ptr, UINT string_length); +UINT _nxe_lwm2m_client_resource_string_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, CHAR *string_ptr, UINT string_length); +UINT _nx_lwm2m_client_resource_integer32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT32 int32_data); +UINT _nxe_lwm2m_client_resource_integer32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT32 int32_data); +UINT _nx_lwm2m_client_resource_integer64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT64 int64_data); +UINT _nxe_lwm2m_client_resource_integer64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_INT64 int64_data); +UINT _nx_lwm2m_client_resource_float32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT32 float32_data); +UINT _nxe_lwm2m_client_resource_float32_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT32 float32_data); +UINT _nx_lwm2m_client_resource_float64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT64 float64_data); +UINT _nxe_lwm2m_client_resource_float64_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_FLOAT64 float64_data); +UINT _nx_lwm2m_client_resource_boolean_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_BOOL bool_data); +UINT _nxe_lwm2m_client_resource_boolean_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_BOOL bool_data); +UINT _nx_lwm2m_client_resource_objlnk_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT _nxe_lwm2m_client_resource_objlnk_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id); +UINT _nx_lwm2m_client_resource_opaque_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, VOID *opaque_ptr, UINT opaque_length); +UINT _nxe_lwm2m_client_resource_opaque_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, VOID *opaque_ptr, UINT opaque_length); +UINT _nx_lwm2m_client_resource_instances_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT count); +UINT _nxe_lwm2m_client_resource_instances_set(NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_RESOURCE *resource_instances, UINT count); + +/* Firmware Update Object */ +UINT _nx_lwm2m_client_firmware_create(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_CLIENT *client_ptr, UINT protocols, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK package_callback, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK package_uri_callback, NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK update_callback); +UINT _nxe_lwm2m_client_firmware_create(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_CLIENT *client_ptr, UINT protocols, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_CALLBACK package_callback, NX_LWM2M_CLIENT_FIRMWARE_PACKAGE_URI_CALLBACK package_uri_callback, NX_LWM2M_CLIENT_FIRMWARE_UPDATE_CALLBACK update_callback); +UINT _nx_lwm2m_client_firmware_state_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR state); +UINT _nxe_lwm2m_client_firmware_state_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR state); +UINT _nx_lwm2m_client_firmware_result_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR result); +UINT _nxe_lwm2m_client_firmware_result_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, UCHAR result); +UINT _nx_lwm2m_client_firmware_package_info_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *name, UINT name_length, const CHAR *version, UINT version_length); +UINT _nxe_lwm2m_client_firmware_package_info_set(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *name, UINT name_length, const CHAR *version, UINT version_length); + +#endif /* NX_LWM2M_CLIENT_SOURCE_CODE */ + + +/* Define internal LWM2M Client functions. */ +VOID _nx_lwm2m_client_thread_entry(ULONG client_address); +NX_LWM2M_CLIENT_OBJECT* _nx_lwm2m_client_object_ptr_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_ID object_id); +NX_LWM2M_CLIENT_OBJECT_INSTANCE* _nx_lwm2m_client_object_instance_ptr_get(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID instance_id); +UINT _nx_lwm2m_client_object_create_internal(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id_ptr, UINT num_values, const NX_LWM2M_CLIENT_RESOURCE *values, NX_LWM2M_BOOL bootstrap); +VOID _nx_lwm2m_client_object_delete_all(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT *del_object_ptr, NX_LWM2M_ID bs_id); +VOID _nx_lwm2m_client_object_list_changed(NX_LWM2M_CLIENT *client_ptr); +NX_LWM2M_CLIENT_NOTIFY* _nx_lwm2m_client_notify_allocate(NX_LWM2M_CLIENT *client_ptr); +VOID _nx_lwm2m_client_notify_free(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr); +NX_LWM2M_CLIENT_SESSION *_nx_lwm2m_client_server_session_get(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *server_instance_ptr); + +#ifdef NX_SECURE_ENABLE_DTLS +UINT _nx_lwm2m_client_session_start(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL bootstrap, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port, NX_SECURE_DTLS_SESSION *dtls_session_ptr); +#else +UINT _nx_lwm2m_client_session_start(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL bootstrap, NX_LWM2M_ID server_id, const NXD_ADDRESS *ip_address, UINT port); +#endif /* NX_SECURE_ENABLE_DTLS */ +NX_LWM2M_BOOL _nx_lwm2m_client_session_step(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL *has_timer_ptr, ULONG *timer_expire_ptr); +VOID _nx_lwm2m_client_session_receive(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_PACKET *packet_ptr); +VOID _nx_lwm2m_client_session_state_update(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state); +VOID _nx_lwm2m_client_session_cleanup(NX_LWM2M_CLIENT_SESSION *session_ptr); +NX_PACKET* _nx_lwm2m_client_session_packet_allocate(NX_LWM2M_CLIENT_SESSION *session_ptr); +UINT _nx_lwm2m_client_session_send(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_PACKET *packet_ptr); +UINT _nx_lwm2m_client_session_send_request(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_BOOL first); +UINT _nx_lwm2m_client_session_send_response(NX_LWM2M_CLIENT_SESSION *session_ptr, UCHAR code, USHORT id, NX_LWM2M_BOOL ack, const VOID *token_ptr, UINT token_length, NX_LWM2M_BOOL observe, UINT format, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr); +VOID _nx_lwm2m_client_session_update_flags(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT flags); +NX_LWM2M_CLIENT_NOTIFY* _nx_lwm2m_client_session_notify_get(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_ID resource_id, NX_LWM2M_BOOL create); +VOID _nx_lwm2m_client_session_notify_free(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr); +VOID _nx_lwm2m_client_session_notify_attributes(NX_LWM2M_CLIENT_SESSION *session_ptr, NX_LWM2M_CLIENT_NOTIFY *notify_ptr, UINT *flags_ptr, NX_LWM2M_INT32 *pmin_ptr, NX_LWM2M_INT32 *pmax_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *gt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *lt_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *stp_ptr); + +UINT _nx_lwm2m_client_resource_notify_number_get(const NX_LWM2M_CLIENT_RESOURCE *resource_ptr, NX_LWM2M_CLIENT_NOTIFY_NUMBER *number_ptr); + +/* Binding Modes String Handling functions. */ +const CHAR* _nx_lwm2m_client_binding_mode_string_get(UCHAR binding_mode, UINT *length); +UCHAR _nx_lwm2m_client_binding_mode_string_parse(const CHAR *string_ptr, UINT string_length); + +/* CoAP functions. */ +VOID *_nx_lwm2m_client_coap_option_header_add(VOID *ptr, VOID *ptr_max, UINT *last_option_ptr, UINT option, UINT length); +VOID *_nx_lwm2m_client_coap_option_uint_add(VOID *ptr, VOID *ptr_max, UINT *last_option_ptr, UINT option, ULONG value); +const VOID *_nx_lwm2m_client_coap_header_parse(const VOID *ptr, const VOID *ptr_max, UCHAR *type_ptr, UCHAR *code_ptr, USHORT *id, const VOID **token_ptr, UINT *token_length_ptr); +const VOID *_nx_lwm2m_client_coap_option_parse(const VOID *ptr, const VOID *ptr_max, UINT *option_ptr, const VOID **value_ptr, UINT *value_length_ptr); + +/* Corelink functions. */ +CHAR* _nx_lwm2m_client_corelink_path_add(CHAR *ptr, CHAR *ptr_max, NX_LWM2M_ID object_id, NX_LWM2M_ID instance_id, NX_LWM2M_ID resource_id); +CHAR* _nx_lwm2m_client_corelink_attributes_add(CHAR *ptr, CHAR *ptr_max, NX_LWM2M_ID server_id, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr, UINT attr_flags, NX_LWM2M_INT32 attr_pmin, NX_LWM2M_INT32 attr_pmax, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_gt, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_lt, NX_LWM2M_CLIENT_NOTIFY_NUMBER attr_stp); + +#if NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES +/* Access control object functions. */ +VOID _nx_lwm2m_client_access_control_object_create(NX_LWM2M_CLIENT *client_ptr); +#endif /* NX_LWM2M_CLIENT_MAX_ACCESS_CONTROL_INSTANCES */ + +/* Device object functions. */ +VOID _nx_lwm2m_client_device_object_create(NX_LWM2M_CLIENT *client_ptr, UCHAR binding_modes); +UINT _nx_lwm2m_client_device_object_error_push(NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr, UCHAR code); +VOID _nx_lwm2m_client_device_object_error_reset(NX_LWM2M_CLIENT_DEVICE_OBJECT *device_ptr); + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES +/* Security object functions. */ +VOID _nx_lwm2m_client_security_object_create(NX_LWM2M_CLIENT *client_ptr); +#endif /* NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES */ + +/* Server object functions. */ +VOID _nx_lwm2m_client_server_object_create(NX_LWM2M_CLIENT *client_ptr); + +/* Parse TLV Header */ +const VOID *_nx_lwm2m_client_tlv_header_parse(const VOID *ptr, const VOID *ptr_max, UCHAR *type_ptr, NX_LWM2M_ID *id_ptr, UINT *length_ptr); + +/* Parse TLV resource */ +const VOID *_nx_lwm2m_client_tlv_resource_parse(const VOID *ptr, const VOID *ptr_max, NX_LWM2M_CLIENT_RESOURCE *resource_ptr); + +/* Encode TLV resource value */ +VOID *_nx_lwm2m_client_tlv_resource_add(VOID *ptr, VOID *ptr_max, const NX_LWM2M_CLIENT_RESOURCE *resource_ptr); + +/* Define string conversion functions prototypes */ +UINT _nx_lwm2m_client_strconv_parse_id(const CHAR *string_ptr, UINT string_length, NX_LWM2M_ID *id_ptr); +UINT _nx_lwm2m_client_strconv_parse_int32(const CHAR *string_ptr, UINT string_length, NX_LWM2M_INT32 *value_ptr); +UINT _nx_lwm2m_client_strconv_parse_notify_number(const CHAR *string_ptr, UINT string_length, NX_LWM2M_CLIENT_NOTIFY_NUMBER *number_ptr); +UINT _nx_lwm2m_client_strconv_format_id(CHAR *string_ptr, UINT string_length, NX_LWM2M_ID id); +UINT _nx_lwm2m_client_strconv_format_int32(CHAR *string_ptr, UINT string_length, NX_LWM2M_INT32 value); +UINT _nx_lwm2m_client_strconv_format_notify_number(CHAR *string_ptr, UINT string_length, NX_LWM2M_CLIENT_NOTIFY_NUMBER value); + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus + } +#endif + +#endif /* NX_LWM2M_CLIENT_H */ diff --git a/addons/mdns/nxd_mdns.c b/addons/mdns/nxd_mdns.c index 4439cfe0..3fba6e33 100644 --- a/addons/mdns/nxd_mdns.c +++ b/addons/mdns/nxd_mdns.c @@ -81,11 +81,11 @@ static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr); static UINT _nx_mdns_service_name_assemble(UCHAR *name, UCHAR *type, UCHAR *sub_type, UCHAR *domain, UCHAR *record_buffer, UINT buffer_size, UINT *type_index); static UINT _nx_mdns_service_name_resolve(UCHAR *srv_name, UCHAR **name, UCHAR **type, UCHAR **domain); static UINT _nx_mdns_rr_delete(NX_MDNS *mdns_ptr, NX_MDNS_RR *record_rr); -static UINT _nx_mdns_rr_size_get(UCHAR *resource); +static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr); static UINT _nx_mdns_name_match(UCHAR *src, UCHAR *dst, UINT length); -static UINT _nx_mdns_name_size_calculate(UCHAR *name); +static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr); static UINT _nx_mdns_name_string_encode(UCHAR *ptr, UCHAR *name); -static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size); +static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size); static UINT _nx_mdns_txt_string_encode(UCHAR *ptr, UCHAR *name); static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size); static VOID _nx_mdns_short_to_network_convert(UCHAR *ptr, USHORT value); @@ -113,7 +113,9 @@ static VOID _nx_mdns_additional_a_aaaa_find(NX_MDNS *mdns_ptr, UCHAR *na static VOID _nx_mdns_probing_send(NX_MDNS *mdns_ptr, UINT interface_index); static VOID _nx_mdns_announcing_send(NX_MDNS *mdns_ptr, UINT interface_index); static VOID _nx_mdns_response_send(NX_MDNS *mdns_ptr, UINT interface_index); +#ifndef NX_DISABLE_IPV4 static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_info); +#endif /* NX_DISABLE_IPV4 */ #ifdef NX_MDNS_ENABLE_IPV6 static VOID _nx_mdns_ipv6_address_change_notify(NX_IP *ip_ptr, UINT method, UINT interface_index, UINT index, ULONG *ipv6_address); #endif /* NX_MDNS_ENABLE_IPV6 */ @@ -299,7 +301,7 @@ UCHAR *ptr; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_create PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -359,6 +361,11 @@ UCHAR *ptr; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* used internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_mdns_create(NX_MDNS *mdns_ptr, NX_IP *ip_ptr, NX_PACKET_POOL *packet_pool, @@ -435,24 +442,16 @@ UINT host_name_size; _nx_mdns_created_ptr = mdns_ptr; #ifndef NX_MDNS_DISABLE_SERVER - /* Register IP address change callback. */ - status = nx_ip_address_change_notify(mdns_ptr -> nx_mdns_ip_ptr, _nx_mdns_ip_address_change_notify, NX_NULL); - /* Check for error */ - if (status) - { - return(status); - } +#ifndef NX_DISABLE_IPV4 + /* Setup the IP address change callback function. */ + ip_ptr -> nx_ip_address_change_notify_internal = _nx_mdns_ip_address_change_notify; +#endif /* NX_DISABLE_IPV4 */ #ifdef NX_MDNS_ENABLE_IPV6 - /* Register IPv6 address change callback. */ - status = nxd_ipv6_address_change_notify(mdns_ptr -> nx_mdns_ip_ptr, _nx_mdns_ipv6_address_change_notify); - /* Check for error */ - if (status) - { - return(status); - } + /* Setup the IPv6 address change callback function. */ + ip_ptr -> nx_ipv6_address_change_notify_internal = _nx_mdns_ipv6_address_change_notify; #endif /* NX_MDNS_ENABLE_IPV6 */ #endif /* NX_MDNS_DISABLE_SERVER */ @@ -608,7 +607,7 @@ UINT host_name_size; mdns_ptr -> nx_mdns_id = NX_MDNS_ID; /* The random delay of first probing for RR. */ - mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (NX_RAND() % NX_MDNS_PROBING_TIMER_COUNT)); + mdns_ptr -> nx_mdns_first_probing_delay = (ULONG)(1 + (((ULONG)NX_RAND()) % NX_MDNS_PROBING_TIMER_COUNT)); /* Return a successful status. */ return(NX_SUCCESS); @@ -3100,7 +3099,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_service_one_shot_query PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3144,6 +3143,9 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_mdns_service_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, NX_MDNS_SERVICE *service, UINT timeout) @@ -3231,7 +3233,7 @@ UINT name_length; /* Release the mDNS mutex. */ tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex)); - return (status); + return (NX_MDNS_DATA_SIZE_ERROR); } memcpy((char *)(service -> buffer), (char*)(answer_rr -> nx_mdns_rr_name), name_length); /* Use case of memcpy is verified. */ } @@ -3244,7 +3246,7 @@ UINT name_length; /* Release the mDNS mutex. */ tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex)); - return (status); + return (NX_MDNS_DATA_SIZE_ERROR); } memcpy((CHAR *)(service -> buffer), (CHAR *)(answer_rr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_ptr.nx_mdns_rr_ptr_name), name_length); /* Use case of memcpy is verified. */ } @@ -3280,7 +3282,7 @@ UINT name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_one_shot_query PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3327,6 +3329,10 @@ UINT name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_one_shot_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, NX_MDNS_RR **out_rr, ULONG wait_option, UINT interface_index) @@ -3394,7 +3400,7 @@ UINT name_length; temp_resource_record.nx_mdns_rr_word = (temp_resource_record.nx_mdns_rr_word | NX_MDNS_RR_FLAG_PEER); /* Set the interface index. */ - temp_resource_record.nx_mdns_rr_interface_index = interface_index; + temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index; /* Add the resource record. */ status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL); @@ -3410,7 +3416,7 @@ UINT name_length; /* A multicast DNS querier should also delay the first query of the series by a randomly chosen amount in the range 20-120ms. */ - insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (NX_RAND() % NX_MDNS_QUERY_DELAY_RANGE)); + insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE)); insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE; /* Set the mDNS timer. */ @@ -3716,7 +3722,7 @@ UINT i; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_continuous_query PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3759,6 +3765,10 @@ UINT i; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_continuous_query(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT interface_index) @@ -3815,7 +3825,7 @@ UINT name_length; } /* Set the interface index. */ - temp_resource_record.nx_mdns_rr_interface_index = interface_index; + temp_resource_record.nx_mdns_rr_interface_index = (UCHAR)interface_index; /* Add the resource record. */ status = _nx_mdns_cache_add_resource_record(mdns_ptr, NX_MDNS_CACHE_TYPE_PEER, &temp_resource_record, &insert_rr, NX_NULL); @@ -3831,7 +3841,7 @@ UINT name_length; /* A multicast DNS querier should also delay the first query of the series by a randomly chosen amount in the range 20-120ms. */ - insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (NX_RAND() % NX_MDNS_QUERY_DELAY_RANGE)); + insert_rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE)); insert_rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE; /* Set the mDNS timer. */ @@ -4190,7 +4200,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_service_lookup PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4235,6 +4245,9 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_mdns_service_lookup(NX_MDNS *mdns_ptr, UCHAR *name, UCHAR *type, UCHAR *sub_type, UINT service_index, NX_MDNS_SERVICE *service) @@ -4304,7 +4317,7 @@ UINT target_string_length; /* Release the mDNS mutex. */ tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex)); - return (status); + return (NX_MDNS_DATA_SIZE_ERROR); } } @@ -4314,7 +4327,7 @@ UINT target_string_length; /* Release the mDNS mutex. */ tx_mutex_put(&(mdns_ptr -> nx_mdns_mutex)); - return (status); + return (NX_MDNS_DATA_SIZE_ERROR); } /* Loop to search local and peer cache. */ @@ -5655,7 +5668,7 @@ UINT name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_rr_parameter_set PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5695,6 +5708,9 @@ UINT name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_rr_parameter_set(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, ULONG ttl, UINT rdata_length, @@ -5723,7 +5739,7 @@ UINT name_length; return(status); /* Set the parameters. */ - rr_record -> nx_mdns_rr_interface_index = interface_index; + rr_record -> nx_mdns_rr_interface_index = (UCHAR)interface_index; rr_record -> nx_mdns_rr_type = type; rr_record -> nx_mdns_rr_class = NX_MDNS_RR_CLASS_IN; rr_record -> nx_mdns_rr_ttl = ttl; @@ -6766,7 +6782,7 @@ UINT active; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_timer_event_process PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6808,6 +6824,10 @@ UINT active; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static VOID _nx_mdns_timer_event_process(NX_MDNS *mdns_ptr) @@ -6881,9 +6901,9 @@ UINT rr_name_length; } /* Calculate the time interval for two responses.*/ - if (p -> nx_mdns_rr_response_interval > (UCHAR)mdns_ptr -> nx_mdns_timer_min_count) + if (p -> nx_mdns_rr_response_interval > mdns_ptr -> nx_mdns_timer_min_count) { - p -> nx_mdns_rr_response_interval = (UCHAR)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count); + p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - mdns_ptr -> nx_mdns_timer_min_count); /* Compare the timer count.and set the minimum timer count. */ if ((p -> nx_mdns_rr_response_interval != 0) && @@ -7201,7 +7221,7 @@ UINT rr_name_length; p -> nx_mdns_rr_retransmit_count = NX_MDNS_RR_UPDATE_COUNT; /* 50% of the record lifetime has elapsed,the querier should plan to issure a query at 80%-82% of the record lifetime */ - p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (NX_RAND() % 3)) / 100; + p -> nx_mdns_rr_timer_count = p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(30 + (((ULONG)NX_RAND()) % 3)) / 100; } else { @@ -7236,7 +7256,7 @@ UINT rr_name_length; /* mDNS Responder MUST NOT multicast a record until at least one second has elapsed since the last time that record was multicast. RFC6762, Section6, Page16. */ /* Set the next response time interval. */ - p -> nx_mdns_rr_response_interval = (UCHAR)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE); + p -> nx_mdns_rr_response_interval = (ULONG)(NX_MDNS_RESPONSE_INTERVAL + NX_MDNS_TIMER_COUNT_RANGE); /* Compare the timer count.and set the minimum timer count. */ if (p -> nx_mdns_rr_response_interval < timer_min_count) @@ -7344,7 +7364,7 @@ UINT rr_name_length; while(remaining_ticks > p -> nx_mdns_rr_timer_count) remaining_ticks -= p -> nx_mdns_rr_timer_count; - p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(NX_RAND() % 3) / 100); + p -> nx_mdns_rr_timer_count = remaining_ticks + (p -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(((ULONG)NX_RAND()) % 3) / 100); } /* Compare the timer count.and set the minimum timer count. */ @@ -7463,6 +7483,7 @@ static VOID _nx_mdns_udp_receive_notify(NX_UDP_SOCKET *socket_ptr) } #ifndef NX_MDNS_DISABLE_SERVER +#ifndef NX_DISABLE_IPV4 /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -7519,6 +7540,7 @@ static VOID _nx_mdns_ip_address_change_notify(NX_IP *ip_ptr, VOID *additional_in return; } +#endif /* NX_DISABLE_IPV4 */ /**************************************************************************/ @@ -7791,7 +7813,7 @@ UINT interface_index; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7837,6 +7859,13 @@ UINT interface_index; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UINT interface_index) @@ -7912,7 +7941,7 @@ NX_MDNS_RR *nsec_rr; /* Multicast DNS responses MUST NOT contain any question in the Question Section, Any questions in the Question Section of a received Multicast DNS response MUST be silently ignored. RFC6762, Section6, Page14. */ - data_ptr += (_nx_mdns_name_size_calculate(data_ptr) + 4); + data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4); } else { @@ -8051,7 +8080,7 @@ NX_MDNS_RR *nsec_rr; Responders SHOULD delay their responses by a random amount of time selected with uniform random distribution in the range 400-500ms. RFC6762, Section6, Page 15. */ if (mdns_flags & NX_MDNS_TC_FLAG) { - p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (NX_RAND() % NX_MDNS_RESPONSE_TC_DELAY_RANGE)); + p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_TC_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_TC_DELAY_RANGE)); } else { @@ -8061,7 +8090,7 @@ NX_MDNS_RR *nsec_rr; if (authority_count) { if (p -> nx_mdns_rr_response_interval > (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT)) - p -> nx_mdns_rr_response_interval = (UCHAR)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT)); + p -> nx_mdns_rr_response_interval = (ULONG)(p -> nx_mdns_rr_response_interval - (NX_MDNS_RESPONSE_INTERVAL - NX_MDNS_RESPONSE_PROBING_TIMER_COUNT)); else p -> nx_mdns_rr_response_interval = 0; } @@ -8078,7 +8107,7 @@ NX_MDNS_RR *nsec_rr; else { /* Set the timer count, delay 20-120ms. */ - p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (NX_RAND() % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE)); + p -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE)); } } else @@ -8105,7 +8134,7 @@ NX_MDNS_RR *nsec_rr; #endif /* NX_MDNS_DISABLE_SERVER */ /* Update the data_ptr. */ - data_ptr += (_nx_mdns_name_size_calculate(data_ptr) + 4); + data_ptr += (_nx_mdns_name_size_calculate(data_ptr, packet_ptr) + 4); } } @@ -8137,7 +8166,7 @@ NX_MDNS_RR *nsec_rr; _nx_mdns_conflict_process(mdns_ptr, rr_search); /* Update the data_ptr. */ - data_ptr += _nx_mdns_rr_size_get(data_ptr); + data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr); continue; } @@ -8155,7 +8184,7 @@ NX_MDNS_RR *nsec_rr; rr_search -> nx_mdns_rr_send_flag = NX_MDNS_RR_SEND_MULTICAST; /* Set the timer count, delay 20-120ms. */ - rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (NX_RAND() % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE)); + rr_search -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_RESPONSE_SHARED_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_RESPONSE_SHARED_DELAY_RANGE)); /* Set the mDNS timer. */ _nx_mdns_timer_set(mdns_ptr, rr_search, rr_search -> nx_mdns_rr_timer_count); @@ -8179,7 +8208,7 @@ NX_MDNS_RR *nsec_rr; { /* Update the data_ptr. */ - data_ptr += _nx_mdns_rr_size_get(data_ptr); + data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr); continue; } @@ -8200,7 +8229,7 @@ NX_MDNS_RR *nsec_rr; _nx_mdns_conflict_process(mdns_ptr, rr_search); /* Update the data_ptr. */ - data_ptr += _nx_mdns_rr_size_get(data_ptr); + data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr); continue; } @@ -8279,7 +8308,7 @@ NX_MDNS_RR *nsec_rr; } /* Update the data_ptr. */ - data_ptr += _nx_mdns_rr_size_get(data_ptr); + data_ptr += _nx_mdns_rr_size_get(data_ptr, packet_ptr); } return(NX_MDNS_SUCCESS); @@ -9632,7 +9661,7 @@ UINT rr_name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_set PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -9671,6 +9700,15 @@ UINT rr_name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), improved */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op, UINT interface_index) @@ -9709,12 +9747,13 @@ UINT temp_string_length; } /* Set the interface. */ - rr_ptr -> nx_mdns_rr_interface_index = interface_index; + rr_ptr -> nx_mdns_rr_interface_index = (UCHAR)interface_index; /* Process the name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), - temp_string_buffer, NX_MDNS_NAME_MAX)) + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, + temp_string_buffer, NX_MDNS_NAME_MAX)) { /* Check string length. */ @@ -9735,11 +9774,18 @@ UINT temp_string_length; return(NX_MDNS_ERROR); } + /* Plus 4 for 2 bytes type and 2 bytes class. */ + temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr); + if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr)) + { + return(NX_MDNS_ERROR); + } + /* Set the resource record type. */ - rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr)); + rr_ptr -> nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length); /* Get the resource record class.*/ - record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr) + 2); + record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2); /* Remote RR, set the RR owner flag.*/ if (cache_type == NX_MDNS_CACHE_TYPE_PEER) @@ -9776,7 +9822,7 @@ UINT temp_string_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_process PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -9818,6 +9864,16 @@ UINT temp_string_length; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_process(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, UINT interface_index) @@ -9847,8 +9903,9 @@ UINT rr_name_length; /* Process the name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), - temp_string_buffer, NX_MDNS_NAME_MAX)) + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, + temp_string_buffer, NX_MDNS_NAME_MAX)) { /* Check string length. */ @@ -9869,11 +9926,18 @@ UINT rr_name_length; return(NX_MDNS_ERROR); } + /* Plus 4 for 2 bytes type and 2 bytes class. */ + temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr); + if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 4) > packet_ptr -> nx_packet_append_ptr)) + { + return(NX_MDNS_ERROR); + } + /* Set the resource record type. */ - rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr)); + rr_ptr.nx_mdns_rr_type = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length); /* Get the resource record class.*/ - record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr) + 2); + record_class = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 2); /* Set the resource record class. */ rr_ptr.nx_mdns_rr_class = record_class & NX_MDNS_TOP_BIT_MASK; @@ -9888,7 +9952,7 @@ UINT rr_name_length; } /* Set the interface index. */ - rr_ptr.nx_mdns_rr_interface_index = interface_index; + rr_ptr.nx_mdns_rr_interface_index = (UCHAR)interface_index; /* Set the rdata information for answer record. */ status = _nx_mdns_packet_rr_data_set(mdns_ptr, packet_ptr, data_ptr, &rr_ptr, NX_MDNS_RR_OP_PEER_ADD_ANSWER); @@ -10036,7 +10100,7 @@ UINT rr_name_length; { /* Set the timer count. */ - p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (NX_RAND() % 3)) / 100; + p -> nx_mdns_rr_timer_count = insert_ptr -> nx_mdns_rr_ttl * NX_IP_PERIODIC_RATE * (ULONG)(80 + (((ULONG)NX_RAND()) % 3)) / 100; /* Set the mDNS timer. */ _nx_mdns_timer_set(mdns_ptr, p, p -> nx_mdns_rr_timer_count); @@ -10079,7 +10143,7 @@ UINT rr_name_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_rr_data_set PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -10121,6 +10185,12 @@ UINT rr_name_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_rr_data_set(NX_MDNS *mdns_ptr, NX_PACKET *packet_ptr, UCHAR *data_ptr, NX_MDNS_RR *rr_ptr, UINT op) @@ -10146,14 +10216,21 @@ UINT temp_string_length; find_string = NX_FALSE; } + /* Plus 10 for 2 bytes type, 2 bytes class, 4 bytes ttl and 2 bytes rdata length. */ + temp_string_length = _nx_mdns_name_size_calculate(data_ptr, packet_ptr); + if ((temp_string_length == 0) || ((data_ptr + temp_string_length + 10) > packet_ptr -> nx_packet_append_ptr)) + { + return(NX_MDNS_ERROR); + } + /* Set the resource record time to live.*/ - rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr) + 4); + rr_ptr -> nx_mdns_rr_ttl = NX_MDNS_GET_ULONG_DATA(data_ptr + temp_string_length + 4); /* Set the resource record rdata length. */ - rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + _nx_mdns_name_size_calculate(data_ptr) + 8);; + rr_ptr -> nx_mdns_rr_rdata_length = NX_MDNS_GET_USHORT_DATA(data_ptr + temp_string_length + 8);; /* Update the pointer to point at the resource data. */ - data_ptr = data_ptr + _nx_mdns_name_size_calculate(data_ptr) + 10; + data_ptr = data_ptr + temp_string_length + 10; /* Check the type. */ switch (rr_ptr -> nx_mdns_rr_type) @@ -10161,6 +10238,12 @@ UINT temp_string_length; case NX_MDNS_RR_TYPE_A: { + /* 4 bytes IP address. */ + if (data_ptr + 4 > packet_ptr -> nx_packet_append_ptr) + { + return(NX_MDNS_ERROR); + } + /* Get the rdata. */ rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_a.nx_mdns_rr_a_address = NX_MDNS_GET_ULONG_DATA(data_ptr); rr_ptr -> nx_mdns_rr_rdata_length = 4; @@ -10172,6 +10255,12 @@ UINT temp_string_length; case NX_MDNS_RR_TYPE_AAAA: { + /* 16 bytes IPv6 address. */ + if (data_ptr + 16 > packet_ptr -> nx_packet_append_ptr) + { + return(NX_MDNS_ERROR); + } + /* Get the rdata. */ rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[0] = NX_MDNS_GET_ULONG_DATA(data_ptr); rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_aaaa.nx_mdns_rr_aaaa_address[1] = NX_MDNS_GET_ULONG_DATA(data_ptr + 4); @@ -10196,6 +10285,11 @@ UINT temp_string_length; else if (rr_ptr -> nx_mdns_rr_rdata_length > 1) { + if (data_ptr + rr_ptr -> nx_mdns_rr_rdata_length > packet_ptr -> nx_packet_append_ptr) + { + return(NX_MDNS_ERROR); + } + /* Add the txt string. */ if (_nx_mdns_txt_string_decode(data_ptr, rr_ptr -> nx_mdns_rr_rdata_length, temp_string_buffer, NX_MDNS_NAME_MAX) == NX_MDNS_SUCCESS) { @@ -10228,6 +10322,12 @@ UINT temp_string_length; case NX_MDNS_RR_TYPE_SRV: { + /* Plus 6 bytes for 2 bytes priority, 2 bytes weights and 2 bytes port. */ + if (data_ptr + 6 > packet_ptr -> nx_packet_append_ptr) + { + return(NX_MDNS_ERROR); + } + /* Get the priority. */ rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_srv.nx_mdns_rr_srv_priority = NX_MDNS_GET_USHORT_DATA(data_ptr); data_ptr += 2; @@ -10265,6 +10365,12 @@ UINT temp_string_length; case NX_MDNS_RR_TYPE_MX: { + /* Plus 2 bytes for preference. */ + if (data_ptr + 2 > packet_ptr -> nx_packet_append_ptr) + { + return(NX_MDNS_ERROR); + } + /* Set the preference. */ rr_ptr -> nx_mdns_rr_rdata.nx_mdns_rr_rdata_mx.nx_mdns_rr_mx_preference = NX_MDNS_GET_USHORT_DATA(data_ptr); data_ptr += 2; @@ -10285,7 +10391,8 @@ UINT temp_string_length; /* Process the target/domain name string. */ if (_nx_mdns_name_string_decode(packet_ptr -> nx_packet_prepend_ptr, - (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + (UINT)(data_ptr - packet_ptr -> nx_packet_prepend_ptr), + packet_ptr -> nx_packet_length, temp_string_buffer, NX_MDNS_NAME_MAX)) { @@ -10323,7 +10430,7 @@ UINT temp_string_length; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_packet_address_check PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -10355,6 +10462,9 @@ UINT temp_string_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_mdns_packet_address_check(NX_PACKET *packet_ptr) @@ -10378,6 +10488,12 @@ NX_IPV6_HEADER *ipv6_header; #endif /* NX_MDNS_ENABLE_IPV6 */ + /* 2 bytes ID and 2 bytes flags. */ + if (packet_ptr -> nx_packet_length < 4) + { + return(NX_MDNS_ERROR); + } + /* Extract the message type which should be the first byte. */ mdns_flags = NX_MDNS_GET_USHORT_DATA(packet_ptr -> nx_packet_prepend_ptr + NX_MDNS_FLAGS_OFFSET); @@ -12804,7 +12920,7 @@ UINT cache_count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_query_check PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -12841,6 +12957,9 @@ UINT cache_count = 1; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_mdns_query_check(NX_MDNS *mdns_ptr, UCHAR *name, USHORT type, UINT one_shot, NX_MDNS_RR **search_rr, UINT interface_index) @@ -12924,7 +13043,7 @@ UINT name_length; /* A multicast DNS querier should also delay the first query of the series by a randomly chosen amount in the range 20-120ms. */ - rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (NX_RAND() % NX_MDNS_QUERY_DELAY_RANGE)); + rr -> nx_mdns_rr_timer_count = (ULONG)(NX_MDNS_QUERY_DELAY_MIN + (((ULONG)NX_RAND()) % NX_MDNS_QUERY_DELAY_RANGE)); rr -> nx_mdns_rr_retransmit_lifetime = NX_MDNS_TIMER_COUNT_RANGE; /* Set the mDNS timer. */ @@ -13567,7 +13686,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_txt_string_decode PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13605,6 +13724,9 @@ UINT count = 1; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buffer, UINT size) @@ -13628,7 +13750,7 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf { /* Simple count, check for space and copy the label. */ - while (labelSize > 0) + while ((labelSize > 0) && (data_length > 1)) { *buffer++ = *data++; @@ -13666,7 +13788,7 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf /* FUNCTION RELEASE */ /* */ /* _nx_mdns_name_size_calculate PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13678,6 +13800,7 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf /* INPUT */ /* */ /* name Pointer to the name */ +/* packet_ptr Pointer to received packet */ /* */ /* OUTPUT */ /* */ @@ -13697,9 +13820,12 @@ static UINT _nx_mdns_txt_string_decode(UCHAR *data, UINT data_length, UCHAR *buf /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ -static UINT _nx_mdns_name_size_calculate(UCHAR *name) +static UINT _nx_mdns_name_size_calculate(UCHAR *name, NX_PACKET *packet_ptr) { UINT size = 0; @@ -13715,6 +13841,13 @@ UINT size = 0; if (labelSize <= NX_MDNS_LABEL_MAX) { + if (name + labelSize >= packet_ptr -> nx_packet_append_ptr) + { + + /* If name buffer is OOB, just fail. */ + return(0); + } + /* Simple count, adjust size and skip the label. */ size += labelSize + 1; name += labelSize; @@ -13842,7 +13975,7 @@ UINT count = 1; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_name_string_decode PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13857,6 +13990,7 @@ UINT count = 1; /* */ /* data Pointer to buffer to decode */ /* start Location of start of data */ +/* data_length Length of data buffer */ /* buffer Pointer to decoded data */ /* size Size of data buffer to decode */ /* */ @@ -13878,21 +14012,42 @@ UINT count = 1; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* prevented infinite loop in */ +/* name compression, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ -static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UCHAR *buffer, UINT size) +static UINT _nx_mdns_name_string_decode(UCHAR *data, UINT start, UINT data_length, UCHAR *buffer, UINT size) { UCHAR *character = data + start; UINT length = 0; +UINT offset; +UINT pointer_count = 0; +UINT labelSize; /* As long as there is space in the buffer and we haven't found a zero terminating label */ - while ((size > length) && (*character != '\0')) + while (1) { - UINT labelSize = *character++; + if (character >= data + data_length) + { + return(0); + } + + if ((size <= length) || (*character == '\0')) + { + break; + } + + labelSize = *character++; /* Is this a compression pointer or a count. */ if (labelSize <= NX_MDNS_LABEL_MAX) @@ -13901,6 +14056,10 @@ UINT length = 0; /* Simple count, check for space and copy the label. */ while ((size > length) && (labelSize > 0)) { + if (character >= data + data_length) + { + return(0); + } *buffer++ = *character++; length++; @@ -13914,8 +14073,34 @@ UINT length = 0; else if ((labelSize & NX_MDNS_COMPRESS_MASK) == NX_MDNS_COMPRESS_VALUE) { + if (character >= data + data_length) + { + return(0); + } + /* This is a pointer, just adjust the source. */ - character = data + ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character; + offset = ((labelSize & NX_MDNS_LABEL_MAX) << 8) + *character; + + /* Make sure offset is in the buffer. */ + if (offset >= data_length) + { + return(0); + } + + /* Pointer must not point back to itself. */ + if ((data + offset == character) || (data + offset == character - 1)) + { + return(0); + } + + /* Prevent infinite loop with compression pointers. */ + pointer_count++; + if (pointer_count > NX_MDNS_MAX_COMPRESSION_POINTERS) + { + return(0); + } + + character = data + offset; } else { @@ -13926,7 +14111,7 @@ UINT length = 0; } /* Done copying the data, set the last . to a trailing null */ - if (*(buffer - 1) == '.') + if ((length > 0) && (*(buffer - 1) == '.')) { buffer--; @@ -13946,7 +14131,7 @@ UINT length = 0; /* FUNCTION RELEASE */ /* */ /* _nx_mdns_rr_size_get PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13958,6 +14143,7 @@ UINT length = 0; /* INPUT */ /* */ /* resource Pointer to the resource */ +/* packet_ptr Pointer to received packet */ /* */ /* OUTPUT */ /* */ @@ -13976,9 +14162,12 @@ UINT length = 0; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* packet length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ -static UINT _nx_mdns_rr_size_get(UCHAR *resource) +static UINT _nx_mdns_rr_size_get(UCHAR *resource, NX_PACKET *packet_ptr) { UINT name_size; @@ -13988,7 +14177,12 @@ UINT data_size; name size + data size + 2 bytes for type, 2 for class, 4 for time to live and 2 for data length i.e. name size + data size + 10 bytes overhead. */ - name_size = _nx_mdns_name_size_calculate(resource); + name_size = _nx_mdns_name_size_calculate(resource, packet_ptr); + + if (resource + name_size + 8 + 2 > packet_ptr -> nx_packet_append_ptr) + { + return(0); + } data_size = NX_MDNS_GET_USHORT_DATA(resource + name_size + 8); /* Return resource size. */ diff --git a/addons/mdns/nxd_mdns.h b/addons/mdns/nxd_mdns.h index 9f0faa6b..0d57abce 100644 --- a/addons/mdns/nxd_mdns.h +++ b/addons/mdns/nxd_mdns.h @@ -25,7 +25,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_mdns.h PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,13 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* buffer length verification, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), */ +/* prevented infinite loop in */ +/* name compression, */ +/* resulting in version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of timer, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -245,23 +252,23 @@ extern "C" { /* Define the mDNS's probing timer interval, default 250ms in spec. In tick. - should be:250 * NX_IP_PERIODIC_RATE /1000 = 250 * 100 /1000 = 25. */ + should be: 250 * NX_IP_PERIODIC_RATE / 1000. */ #ifndef NX_MDNS_PROBING_TIMER_COUNT -#define NX_MDNS_PROBING_TIMER_COUNT 25 +#define NX_MDNS_PROBING_TIMER_COUNT (250 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_PROBING_TIMER_COUNT */ /* Define the mDNS's announcing timer interval, default 250ms in spec. In tick. - should be:250 * NX_IP_PERIODIC_RATE /1000 = 250 * 100 /1000 = 25. */ + should be: 250 * NX_IP_PERIODIC_RATE / 1000. */ #ifndef NX_MDNS_ANNOUNCING_TIMER_COUNT -#define NX_MDNS_ANNOUNCING_TIMER_COUNT 25 +#define NX_MDNS_ANNOUNCING_TIMER_COUNT (250 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_ANNOUNCING_TIMER_COUNT */ /* Define the mDNS's goodbye timer interval, default 250ms in spec. In tick. - should be:250 * NX_IP_PERIODIC_RATE /1000 = 250 * 100 /1000 = 25. */ + should be: 250 * NX_IP_PERIODIC_RATE / 1000. */ #ifndef NX_MDNS_GOODBYE_TIMER_COUNT -#define NX_MDNS_GOODBYE_TIMER_COUNT 25 +#define NX_MDNS_GOODBYE_TIMER_COUNT (250 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_GOODBYE_TIMER_COUNT */ @@ -279,17 +286,17 @@ extern "C" { /* Define the mDNS's query delay timer interval, 20-120ms. In tick. */ #ifndef NX_MDNS_QUERY_DELAY_MIN -#define NX_MDNS_QUERY_DELAY_MIN 2 +#define NX_MDNS_QUERY_DELAY_MIN (20 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_QUERY_DELAY_MIN */ #ifndef NX_MDNS_QUERY_DELAY_RANGE -#define NX_MDNS_QUERY_DELAY_RANGE 10 +#define NX_MDNS_QUERY_DELAY_RANGE (100 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_QUERY_DELAY_RANGE */ /* Define the mDNS's response delay time interval for multicast query. */ /* The time interval, in ticks, in responding to a query to ensure an interval of at least 1s - since the last time the record was multicast. The default value is 100 ticks. */ + since the last time the record was multicast. The default value is NX_IP_PERIODIC_RATE ticks. */ #ifndef NX_MDNS_RESPONSE_INTERVAL #define NX_MDNS_RESPONSE_INTERVAL NX_IP_PERIODIC_RATE #endif /* NX_MDNS_RESPONSE_INTERVAL */ @@ -297,35 +304,35 @@ extern "C" { /* Define the mDNS's response delay time interval for probe message. */ /* The time interval, in ticks, in responding to a probe queries to ensure an interval of - at least 250ms since the last time the record was multicast. The default value is 25 ticks. */ + at least 250ms since the last time the record was multicast. The default value is (250 * NX_IP_PERIODIC_RATE / 1000) ticks. */ #ifndef NX_MDNS_RESPONSE_PROBING_TIMER_COUNT -#define NX_MDNS_RESPONSE_PROBING_TIMER_COUNT 25 +#define NX_MDNS_RESPONSE_PROBING_TIMER_COUNT (250 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_PROBING_TIMER_COUNT */ /* Define the mDNS's response delay time interval for unicast query, 10 ms. In tick. */ #ifndef NX_MDNS_RESPONSE_UNIQUE_DELAY -#define NX_MDNS_RESPONSE_UNIQUE_DELAY 1 +#define NX_MDNS_RESPONSE_UNIQUE_DELAY (10 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_UNIQUE_DELAY */ /* Define the mDNS's response delay time interval for shared message, 20-120ms. In tick. */ #ifndef NX_MDNS_RESPONSE_SHARED_DELAY_MIN -#define NX_MDNS_RESPONSE_SHARED_DELAY_MIN 2 +#define NX_MDNS_RESPONSE_SHARED_DELAY_MIN (20 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_SHARED_DELAY_MIN */ #ifndef NX_MDNS_RESPONSE_SHARED_DELAY_RANGE -#define NX_MDNS_RESPONSE_SHARED_DELAY_RANGE 10 +#define NX_MDNS_RESPONSE_SHARED_DELAY_RANGE (100 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_SHARED_DELAY_RANGE */ /* Define the mDNS's response delay time interval for query with TC, 400-500 ms. In tick. */ #ifndef NX_MDNS_RESPONSE_TC_DELAY_MIN -#define NX_MDNS_RESPONSE_TC_DELAY_MIN 40 +#define NX_MDNS_RESPONSE_TC_DELAY_MIN (400 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_TC_DELAY_MIN */ #ifndef NX_MDNS_RESPONSE_TC_DELAY_RANGE -#define NX_MDNS_RESPONSE_TC_DELAY_RANGE 10 +#define NX_MDNS_RESPONSE_TC_DELAY_RANGE (100 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_RESPONSE_TC_DELAY_RANGE */ @@ -333,7 +340,7 @@ extern "C" { /* This value allows a response to include messages that would be sent within the next 120ms range. */ #ifndef NX_MDNS_TIMER_COUNT_RANGE -#define NX_MDNS_TIMER_COUNT_RANGE 12 +#define NX_MDNS_TIMER_COUNT_RANGE (120 * NX_IP_PERIODIC_RATE / 1000) #endif /* NX_MDNS_TIMER_COUNT_RANGE */ @@ -378,6 +385,11 @@ extern "C" { #define NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT NX_IP_PERIODIC_RATE #endif /* NX_MDNS_RR_DELETE_DELAY_TIMER_COUNT */ +/* Define the maximum number of pointers allowed in name compression. */ +#ifndef NX_MDNS_MAX_COMPRESSION_POINTERS +#define NX_MDNS_MAX_COMPRESSION_POINTERS 16 +#endif /* NX_MDNS_MAX_COMPRESSION_POINTERS */ + /* Define the default mDNS's announcing value. */ #define NX_MDNS_ANNOUNCING_PERIOD NX_IP_PERIODIC_RATE @@ -972,8 +984,6 @@ typedef struct NX_MDNS_RR_STRUCT ULONG nx_mdns_rr_ttl; /* The time interval that the RR may be cached before the source of the information should again be consulted. */ - UINT nx_mdns_rr_interface_index; /* RR interface index. */ - USHORT nx_mdns_rr_rdata_length; /* The length of rdata. nx_mdns_rr_rdata */ UCHAR nx_mdns_rr_state; /* The resource records state, Probing, Annoncing, Valid. */ @@ -987,11 +997,13 @@ typedef struct NX_MDNS_RR_STRUCT ULONG nx_mdns_rr_elapsed_time; /* Define the time elasped for the peer RR. */ ULONG nx_mdns_rr_remaining_ticks; /* Define the remaining ticks of the peer RR. */ - + + ULONG nx_mdns_rr_response_interval; /* Define the time interval for two responses. Local RR. */ + + UCHAR nx_mdns_rr_interface_index; /* RR interface index. */ + UCHAR nx_mdns_rr_announcing_max_time; /* RR announcing max time. Local RR. */ - UCHAR nx_mdns_rr_response_interval; /* Define the time interval for two responses. Local RR. */ - UCHAR nx_mdns_rr_conflict_count; /* The conflict count of service name or host name. Local RR. */ UCHAR nx_mdns_rr_poof_count; /* The Passive Observation Of Failures count of resource record. Peer RR.*/ diff --git a/addons/mqtt/nxd_mqtt_client.c b/addons/mqtt/nxd_mqtt_client.c index 5915e7a1..015e6750 100644 --- a/addons/mqtt/nxd_mqtt_client.c +++ b/addons/mqtt/nxd_mqtt_client.c @@ -52,7 +52,9 @@ static UINT _nxd_mqtt_client_create_internal(NXD_MQTT_CLIENT *client_ptr, CHAR * CHAR *client_id, UINT client_id_length, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *stack_ptr, ULONG stack_size, UINT mqtt_thread_priority); -static UINT _nxd_mqtt_packet_allocate(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr); +static UINT _nxd_mqtt_packet_allocate(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +static UINT _nxd_mqtt_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT wait_option); +static UINT _nxd_mqtt_packet_receive(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT wait_option); static UINT _nxd_mqtt_copy_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET **new_packet_ptr, USHORT packet_id, UCHAR set_duplicate_flag, UINT wait_option); static VOID _nxd_mqtt_release_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET *previous_packet_ptr); @@ -246,7 +248,7 @@ ULONG bytes_copied; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_sub_unsub PORTABLE C */ -/* 6.1.2 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -282,8 +284,7 @@ ULONG bytes_copied; /* _nxd_mqtt_client_set_fixed_header */ /* _nxd_mqtt_client_append_message */ /* tx_mutex_put */ -/* nx_tcp_socket_send */ -/* nx_secure_tls_session_send */ +/* _nxd_mqtt_packet_send */ /* nx_packet_release */ /* _nxd_mqtt_copy_transmit_packet */ /* */ @@ -302,6 +303,12 @@ ULONG bytes_copied; /* 11-09-2020 Yuxin Zhou Modified comment(s), and */ /* added packet id parameter, */ /* resulting in version 6.1.2 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_sub_unsub(NXD_MQTT_CLIENT *client_ptr, UINT op, @@ -332,7 +339,7 @@ UCHAR temp_data[2]; return(NXD_MQTT_NOT_CONNECTED); } - status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr); + status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr, NX_WAIT_FOREVER); if (status) { tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); @@ -461,19 +468,7 @@ UCHAR temp_data[2]; tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); /* Ready to send the connect message to the server. */ -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, NX_WAIT_FOREVER); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); -#endif /* NX_SECURE_ENABLE */ - + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, NX_WAIT_FOREVER); if (status) { @@ -492,7 +487,7 @@ UCHAR temp_data[2]; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_packet_allocate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -539,45 +534,202 @@ UCHAR temp_data[2]; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -static UINT _nxd_mqtt_packet_allocate(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr) +static UINT _nxd_mqtt_packet_allocate(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option) { UINT status = NXD_MQTT_SUCCESS; +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + + /* Use WebSocket packet allocate since it is able to count for WebSocket-related header space */ + status = nx_websocket_client_packet_allocate(&(client_ptr -> nxd_mqtt_client_websocket), packet_ptr, wait_option); + } + else +#endif /* NXD_MQTT_OVER_WEBSOCKET */ #ifdef NX_SECURE_ENABLE if (client_ptr -> nxd_mqtt_client_use_tls) { /* Use TLS packet allocate. The TLS packet allocate is able to count for TLS-related header space including crypto initial vector area. */ status = nx_secure_tls_packet_allocate(&client_ptr -> nxd_mqtt_tls_session, client_ptr -> nxd_mqtt_client_packet_pool_ptr, - packet_ptr, TX_WAIT_FOREVER); + packet_ptr, wait_option); } /* Allocate a packet */ else { -#endif +#endif /* NX_SECURE_ENABLE */ if (client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) { status = nx_packet_allocate(client_ptr -> nxd_mqtt_client_packet_pool_ptr, packet_ptr, NX_IPv4_TCP_PACKET, - TX_WAIT_FOREVER); + wait_option); } else { status = nx_packet_allocate(client_ptr -> nxd_mqtt_client_packet_pool_ptr, packet_ptr, NX_IPv6_TCP_PACKET, - TX_WAIT_FOREVER); + wait_option); } #ifdef NX_SECURE_ENABLE } -#endif +#endif /* NX_SECURE_ENABLE */ if (status != NX_SUCCESS) { return(NXD_MQTT_PACKET_POOL_FAILURE); } + return(NXD_MQTT_SUCCESS); } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_mqtt_packet_send PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends out a packet. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to MQTT Client */ +/* packet_ptr Pointer to packet */ +/* wait_option Timeout value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_websocket_client_send */ +/* nx_secure_tls_session_send */ +/* nx_tcp_socket_send */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +static UINT _nxd_mqtt_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT wait_option) +{ +UINT status = NXD_MQTT_SUCCESS; + +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + status = nx_websocket_client_send(&(client_ptr -> nxd_mqtt_client_websocket), packet_ptr, NX_WEBSOCKET_OPCODE_BINARY_FRAME, NX_TRUE, wait_option); + } + else +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nxd_mqtt_client_use_tls) + { + status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, wait_option); + } + else +#endif /* NX_SECURE_ENABLE */ + { + status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); + } + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_mqtt_packet_receive PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a packet. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to MQTT Client */ +/* packet_ptr Pointer to packet */ +/* wait_option Timeout value */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_websocket_client_receive */ +/* nx_secure_tls_session_receive */ +/* nx_tcp_socket_receive */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +static UINT _nxd_mqtt_packet_receive(NXD_MQTT_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT wait_option) +{ +UINT status = NXD_MQTT_SUCCESS; +#ifdef NXD_MQTT_OVER_WEBSOCKET +UINT op_code = 0; +#endif /* NXD_MQTT_OVER_WEBSOCKET*/ + +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + status = nx_websocket_client_receive(&(client_ptr -> nxd_mqtt_client_websocket), packet_ptr, &op_code, wait_option); + if ((status == NX_SUCCESS) && (op_code != NX_WEBSOCKET_OPCODE_BINARY_FRAME)) + { + return(NX_INVALID_PACKET); + } + } + else +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nxd_mqtt_client_use_tls) + { + status = nx_secure_tls_session_receive(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, wait_option); + } + else +#endif /* NX_SECURE_ENABLE */ + { + status = nx_tcp_socket_receive(&(client_ptr -> nxd_mqtt_client_socket), packet_ptr, wait_option); + } + + return(status); +} + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -705,7 +857,7 @@ NXD_MQTT_CLIENT *client_ptr; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_copy_transmit_packet PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -749,6 +901,10 @@ NXD_MQTT_CLIENT *client_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* supported maximum transmit */ +/* queue depth, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_copy_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET **new_packet_ptr, @@ -756,6 +912,15 @@ static UINT _nxd_mqtt_copy_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKE { UINT status; +#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH + if (client_ptr -> message_transmit_queue_depth >= NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH) + { + + /* Hit the transmit queue depeth. No more packets should be queued. */ + return(NX_TX_QUEUE_DEPTH); + } +#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */ + /* Copy current packet. */ status = nx_packet_copy(packet_ptr, new_packet_ptr, client_ptr -> nxd_mqtt_client_packet_pool_ptr, wait_option); if (status) @@ -775,6 +940,11 @@ UINT status; *((*new_packet_ptr) -> nx_packet_prepend_ptr) = (*((*new_packet_ptr) -> nx_packet_prepend_ptr)) | MQTT_PUBLISH_DUP_FLAG; } +#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH + /* Increase the transmit queue depth. */ + client_ptr -> message_transmit_queue_depth++; +#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */ + return(NXD_MQTT_SUCCESS); } @@ -783,7 +953,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_release_transmit_packet PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -824,6 +994,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* supported maximum transmit */ +/* queue depth, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ static VOID _nxd_mqtt_release_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PACKET *previous_packet_ptr) @@ -843,6 +1017,10 @@ static VOID _nxd_mqtt_release_transmit_packet(NXD_MQTT_CLIENT *client_ptr, NX_PA client_ptr -> message_transmit_queue_tail = previous_packet_ptr; } nx_packet_release(packet_ptr); + +#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH + client_ptr -> message_transmit_queue_depth--; +#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */ } /**************************************************************************/ @@ -1168,7 +1346,7 @@ ULONG bytes_copied; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_process_publish PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1193,7 +1371,7 @@ ULONG bytes_copied; /* [receive_notify] User supplied receive */ /* callback function */ /* _nxd_mqtt_packet_allocate */ -/* nx_tcp_socket_send */ +/* _nxd_mqtt_packet_send */ /* nx_packet_release */ /* nx_secure_tls_session_send */ /* _nxd_mqtt_process_publish_packet */ @@ -1211,6 +1389,9 @@ ULONG bytes_copied; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_process_publish(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr) @@ -1346,7 +1527,7 @@ ULONG bytes_copied; /* Send out proper ACKs for QoS 1 and 2 messages. */ /* Allocate a new packet so we can send out a response. */ - status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr); + status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr, NX_WAIT_FOREVER); if (status) { /* Packet allocation fails. */ @@ -1396,19 +1577,9 @@ ULONG bytes_copied; } tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, NX_WAIT_FOREVER); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); -#endif /* NX_SECURE_ENABLE */ + /* Send packet to server. */ + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, NX_WAIT_FOREVER); tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, TX_WAIT_FOREVER); if (status) @@ -1432,7 +1603,7 @@ ULONG bytes_copied; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_process_publish_response PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1456,8 +1627,7 @@ ULONG bytes_copied; /* [nxd_mqtt_client_receive_notify] User supplied publish */ /* callback function */ /* _nxd_mqtt_release_transmit_packet */ -/* nx_tcp_socket_send */ -/* nx_secure_tls_session_send */ +/* _nxd_mqtt_packet_send */ /* */ /* */ /* CALLED BY */ @@ -1472,6 +1642,9 @@ ULONG bytes_copied; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* added ack receive notify, */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_process_publish_response(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr) @@ -1547,7 +1720,7 @@ USHORT transmit_packet_id; /* Send PUBCOMP */ /* Allocate a packet to send the response. */ - ret = _nxd_mqtt_packet_allocate(client_ptr, &response_packet); + ret = _nxd_mqtt_packet_allocate(client_ptr, &response_packet, NX_WAIT_FOREVER); if (ret) { return(1); @@ -1574,19 +1747,8 @@ USHORT transmit_packet_id; tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - ret = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), response_packet, NX_WAIT_FOREVER); - } - else - { - ret = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, response_packet, NX_WAIT_FOREVER); - } -#else - ret = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, response_packet, NX_WAIT_FOREVER); - -#endif /* NX_SECURE_ENABLE */ + /* Send packet to server. */ + ret = _nxd_mqtt_packet_send(client_ptr, response_packet, NX_WAIT_FOREVER); tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, TX_WAIT_FOREVER); @@ -1982,7 +2144,7 @@ UCHAR fixed_header; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_packet_receive_process PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2023,6 +2185,9 @@ UCHAR fixed_header; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static VOID _nxd_mqtt_packet_receive_process(NXD_MQTT_CLIENT *client_ptr) @@ -2044,22 +2209,11 @@ ULONG packet_length; tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); /* Make a receive call. */ -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_receive(&(client_ptr -> nxd_mqtt_tls_session), &packet_ptr, NX_NO_WAIT); - } - else - { - status = nx_tcp_socket_receive(&client_ptr -> nxd_mqtt_client_socket, &packet_ptr, NX_NO_WAIT); - } -#else - status = nx_tcp_socket_receive(&client_ptr -> nxd_mqtt_client_socket, &packet_ptr, NX_NO_WAIT); -#endif /* NX_SECURE_ENABLE */ + status = _nxd_mqtt_packet_receive(client_ptr, &packet_ptr, NX_NO_WAIT); if (status != NX_SUCCESS) { - if (status != NX_NO_PACKET) + if ((status != NX_NO_PACKET) && (status != NX_CONTINUE)) { /* Network issue. Close the MQTT session. */ @@ -2260,7 +2414,7 @@ ULONG packet_length; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_tcp_establish_process PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2294,6 +2448,9 @@ ULONG packet_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static VOID _nxd_mqtt_tcp_establish_process(NXD_MQTT_CLIENT *client_ptr) @@ -2331,6 +2488,36 @@ UINT status; } #endif /* NX_SECURE_ENABLE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET + + /* If using websocket, start websocket connection. */ + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + status = nx_websocket_client_connect(&(client_ptr -> nxd_mqtt_client_websocket), &(client_ptr -> nxd_mqtt_client_socket), + client_ptr -> nxd_mqtt_client_websocket_host, client_ptr -> nxd_mqtt_client_websocket_host_length, + client_ptr -> nxd_mqtt_client_websocket_uri_path, client_ptr -> nxd_mqtt_client_websocket_uri_path_length, + (UCHAR *)NXD_MQTT_OVER_WEBSOCKET_PROTOCOL, sizeof(NXD_MQTT_OVER_WEBSOCKET_PROTOCOL) - 1, + NX_NO_WAIT); + + if (status != NX_IN_PROGRESS) + { + + /* End connection. */ + _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); + + /* Check callback function. */ + if (client_ptr -> nxd_mqtt_connect_notify) + { + client_ptr -> nxd_mqtt_connect_notify(client_ptr, status, client_ptr -> nxd_mqtt_connect_context); + } + + return; + } + + return; + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Start to send MQTT connect packet. */ status = _nxd_mqtt_client_connect_packet_send(client_ptr, NX_NO_WAIT); @@ -2356,7 +2543,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_tls_establish_process PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2390,6 +2577,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static VOID _nxd_mqtt_tls_establish_process(NXD_MQTT_CLIENT *client_ptr) @@ -2403,29 +2593,40 @@ UINT status; { /* TLS session established. */ - client_ptr -> nxd_mqtt_tls_in_progress= NX_FALSE; + client_ptr -> nxd_mqtt_tls_in_progress = NX_FALSE; - /* Start to send MQTT connect packet. */ - status = _nxd_mqtt_client_connect_packet_send(client_ptr, NX_NO_WAIT); +#ifdef NXD_MQTT_OVER_WEBSOCKET - /* Check status. */ - if (status) + /* If using websocket, start websocket connection. */ + if (client_ptr -> nxd_mqtt_client_use_websocket) { + status = nx_websocket_client_secure_connect(&(client_ptr -> nxd_mqtt_client_websocket), &(client_ptr -> nxd_mqtt_tls_session), + client_ptr -> nxd_mqtt_client_websocket_host, client_ptr -> nxd_mqtt_client_websocket_host_length, + client_ptr -> nxd_mqtt_client_websocket_uri_path, client_ptr -> nxd_mqtt_client_websocket_uri_path_length, + (UCHAR *)NXD_MQTT_OVER_WEBSOCKET_PROTOCOL, sizeof(NXD_MQTT_OVER_WEBSOCKET_PROTOCOL) - 1, + NX_NO_WAIT); - /* End connection. */ - _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); - - /* Check callback function. */ - if (client_ptr -> nxd_mqtt_connect_notify) + if (status == NX_IN_PROGRESS) { - client_ptr -> nxd_mqtt_connect_notify(client_ptr, status, client_ptr -> nxd_mqtt_connect_context); + return; } } + else +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + { + + /* Start to send MQTT connect packet. */ + status = _nxd_mqtt_client_connect_packet_send(client_ptr, NX_NO_WAIT); + } } - else if (status != NX_CONTINUE) + else if (status == NX_CONTINUE) { + return; + } - /* Error. */ + /* Check status. */ + if (status) + { /* End connection. */ _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); @@ -2519,7 +2720,7 @@ UCHAR len[2]; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_connection_end PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2557,6 +2758,9 @@ UCHAR len[2]; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nxd_mqtt_client_connection_end(NXD_MQTT_CLIENT *client_ptr, ULONG wait_option) @@ -2571,6 +2775,13 @@ VOID _nxd_mqtt_client_connection_end(NXD_MQTT_CLIENT *client_ptr, ULONG wait_opt /* Release the mutex. */ tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + nx_websocket_client_disconnect(&(client_ptr -> nxd_mqtt_client_websocket), wait_option); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + #ifdef NX_SECURE_ENABLE if (client_ptr -> nxd_mqtt_client_use_tls) { @@ -3087,7 +3298,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_create_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3134,6 +3345,9 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* corrected mqtt client state,*/ /* resulting in version 6.1 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_client_create_internal(NXD_MQTT_CLIENT *client_ptr, CHAR *client_name, @@ -3141,7 +3355,9 @@ static UINT _nxd_mqtt_client_create_internal(NXD_MQTT_CLIENT *client_ptr, CHAR * NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *stack_ptr, ULONG stack_size, UINT mqtt_thread_priority) { +#ifndef NXD_MQTT_CLOUD_ENABLE UINT status; +#endif /* NXD_MQTT_CLOUD_ENABLE */ #ifdef NXD_MQTT_CLOUD_ENABLE NX_PARAMETER_NOT_USED(stack_ptr); @@ -3203,26 +3419,10 @@ UINT status; client_ptr -> nxd_mqtt_client_name = client_name; /* Create the socket. */ - status = nx_tcp_socket_create(client_ptr -> nxd_mqtt_client_ip_ptr, &(client_ptr -> nxd_mqtt_client_socket), client_ptr -> nxd_mqtt_client_name, - NX_IP_NORMAL, NX_DONT_FRAGMENT, 0x80, NXD_MQTT_CLIENT_SOCKET_WINDOW_SIZE, - NX_NULL, _mqtt_client_disconnect_callback); - - /* Determine if an error occurred. */ - if (status != NX_SUCCESS) - { -#ifndef NXD_MQTT_CLOUD_ENABLE - /* Delete the mutex. */ - tx_mutex_delete(&client_ptr -> nxd_mqtt_protection); - - /* Delete the event flags. */ - tx_event_flags_delete(&(client_ptr -> nxd_mqtt_events)); - - /* Delete the thread. */ - tx_thread_delete(&(client_ptr -> nxd_mqtt_thread)); -#endif /* NXD_MQTT_CLOUD_ENABLE */ + nx_tcp_socket_create(client_ptr -> nxd_mqtt_client_ip_ptr, &(client_ptr -> nxd_mqtt_client_socket), client_ptr -> nxd_mqtt_client_name, + NX_IP_NORMAL, NX_DONT_FRAGMENT, 0x80, NXD_MQTT_CLIENT_SOCKET_WINDOW_SIZE, + NX_NULL, _mqtt_client_disconnect_callback); - return(NXD_MQTT_INTERNAL_ERROR); - } /* Record the client_ptr in the socket structure. */ client_ptr -> nxd_mqtt_client_socket.nx_tcp_socket_reserved_ptr = (VOID *)client_ptr; @@ -3555,7 +3755,7 @@ UINT _nxde_mqtt_client_login_set(NXD_MQTT_CLIENT *client_ptr, /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_retransmit_message PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3579,8 +3779,7 @@ UINT _nxde_mqtt_client_login_set(NXD_MQTT_CLIENT *client_ptr, /* */ /* tx_mutex_get */ /* tx_mutex_put */ -/* nx_secure_tls_session_send */ -/* nx_tcp_socket_send */ +/* _nxd_mqtt_packet_send */ /* nx_packet_release */ /* tx_time_get */ /* nx_packet_copy */ @@ -3596,6 +3795,9 @@ UINT _nxde_mqtt_client_login_set(NXD_MQTT_CLIENT *client_ptr, /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_client_retransmit_message(NXD_MQTT_CLIENT *client_ptr, ULONG wait_option) @@ -3627,20 +3829,8 @@ UCHAR fixed_header; /* Release the mutex. */ tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); - /* Send the packet. */ -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, wait_option); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - -#endif /* NX_SECURE_ENABLE */ + /* Send packet to server. */ + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, wait_option); if (status) { @@ -3675,7 +3865,7 @@ UCHAR fixed_header; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_connect PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3738,6 +3928,16 @@ UCHAR fixed_header; /* is set in CONNACK, corrected*/ /* mqtt client state, */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* corrected the logic for */ +/* non-blocking mode, */ +/* resulting in version 6.1.8 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port, @@ -3788,6 +3988,7 @@ UINT old_priority; nx_secure_tls_session_delete(&(client_ptr -> nxd_mqtt_tls_session)); } #endif /* NX_SECURE_ENABLE */ + tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); return(NXD_MQTT_INVALID_STATE); } @@ -3810,20 +4011,8 @@ UINT old_priority; client_ptr -> nxd_mqtt_ping_timeout = NXD_MQTT_PING_TIMEOUT_DELAY; /* Create timer */ - status = tx_timer_create(&(client_ptr -> nxd_mqtt_timer), "MQTT Timer", _nxd_mqtt_periodic_timer_entry, (ULONG)client_ptr, - client_ptr -> nxd_mqtt_timer_value, client_ptr -> nxd_mqtt_timer_value, TX_AUTO_ACTIVATE); - if (status) - { -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - nx_secure_tls_session_delete(&(client_ptr -> nxd_mqtt_tls_session)); - } -#endif /* NX_SECURE_ENABLE */ - - tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); - return(NXD_MQTT_INTERNAL_ERROR); - } + tx_timer_create(&(client_ptr -> nxd_mqtt_timer), "MQTT Timer", _nxd_mqtt_periodic_timer_entry, (ULONG)client_ptr, + client_ptr -> nxd_mqtt_timer_value, client_ptr -> nxd_mqtt_timer_value, TX_AUTO_ACTIVATE); } else { @@ -3837,49 +4026,41 @@ UINT old_priority; /* Set TCP connection establish notify for non-blocking mode. */ if (wait_option == 0) { - status = nx_tcp_socket_establish_notify(&client_ptr -> nxd_mqtt_client_socket, _nxd_mqtt_tcp_establish_notify); - - /* Check status. */ - if (status != NX_SUCCESS) - { -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - nx_secure_tls_session_delete(&(client_ptr -> nxd_mqtt_tls_session)); - } -#endif /* NX_SECURE_ENABLE */ - tx_timer_delete(&(client_ptr -> nxd_mqtt_timer)); - tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); - return(status); - } + nx_tcp_socket_establish_notify(&client_ptr -> nxd_mqtt_client_socket, _nxd_mqtt_tcp_establish_notify); /* Set the receive callback. */ nx_tcp_socket_receive_notify(&client_ptr -> nxd_mqtt_client_socket, _nxd_mqtt_receive_callback); + +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + + /* Set the websocket connection callback. */ + nx_websocket_client_connection_status_callback_set(&client_ptr -> nxd_mqtt_client_websocket, client_ptr, _nxd_mqtt_client_websocket_connection_status_callback); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ } else { /* Clean receive callback. */ client_ptr -> nxd_mqtt_client_socket.nx_tcp_receive_callback = NX_NULL; + +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + + /* Clean the websocket connection callback. */ + nx_websocket_client_connection_status_callback_set(&client_ptr -> nxd_mqtt_client_websocket, NX_NULL, NX_NULL); + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ } /* Release mutex */ tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); /* First attempt to bind the client socket. */ - status = nx_tcp_client_socket_bind(&(client_ptr -> nxd_mqtt_client_socket), NX_ANY_PORT, wait_option); - - if (status != NX_SUCCESS) - { -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - nx_secure_tls_session_delete(&(client_ptr -> nxd_mqtt_tls_session)); - } -#endif /* NX_SECURE_ENABLE */ - tx_timer_delete(&(client_ptr -> nxd_mqtt_timer)); - return(NXD_MQTT_INTERNAL_ERROR); - } + nx_tcp_client_socket_bind(&(client_ptr -> nxd_mqtt_client_socket), NX_ANY_PORT, wait_option); /* Obtain the mutex. */ tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, NX_WAIT_FOREVER); @@ -3916,7 +4097,7 @@ UINT old_priority; } /* Just return for non-blocking mode. */ - if (status == NX_IN_PROGRESS) + if (wait_option == 0) { return(NX_IN_PROGRESS); } @@ -3952,6 +4133,43 @@ UINT old_priority; } #endif /* NX_SECURE_ENABLE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nxd_mqtt_client_use_tls) + { + status = nx_websocket_client_secure_connect(&(client_ptr -> nxd_mqtt_client_websocket), &(client_ptr -> nxd_mqtt_tls_session), + client_ptr -> nxd_mqtt_client_websocket_host, client_ptr -> nxd_mqtt_client_websocket_host_length, + client_ptr -> nxd_mqtt_client_websocket_uri_path, client_ptr -> nxd_mqtt_client_websocket_uri_path_length, + (UCHAR *)NXD_MQTT_OVER_WEBSOCKET_PROTOCOL, sizeof(NXD_MQTT_OVER_WEBSOCKET_PROTOCOL) - 1, + wait_option); + } + else +#endif /* NX_SECURE_ENABLE */ + { + status = nx_websocket_client_connect(&(client_ptr -> nxd_mqtt_client_websocket), &(client_ptr -> nxd_mqtt_client_socket), + client_ptr -> nxd_mqtt_client_websocket_host, client_ptr -> nxd_mqtt_client_websocket_host_length, + client_ptr -> nxd_mqtt_client_websocket_uri_path, client_ptr -> nxd_mqtt_client_websocket_uri_path_length, + (UCHAR *)NXD_MQTT_OVER_WEBSOCKET_PROTOCOL, sizeof(NXD_MQTT_OVER_WEBSOCKET_PROTOCOL) - 1, + wait_option); + } + + if (status != NX_SUCCESS) + { + + /* Revert thread priority. */ + tx_thread_priority_change(tx_thread_identify(), old_priority, &old_priority); + + /* End connection. */ + _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); + + return(NXD_MQTT_CONNECT_FAILURE); + } + } + +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Start to send connect packet. */ status = _nxd_mqtt_client_connect_packet_send(client_ptr, wait_option); @@ -3963,22 +4181,11 @@ UINT old_priority; /* End connection. */ _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); - return(NXD_MQTT_CONNECT_FAILURE); } -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_receive(&(client_ptr -> nxd_mqtt_tls_session), &packet_ptr, wait_option); - } - else - { - status = nx_tcp_socket_receive(&client_ptr -> nxd_mqtt_client_socket, &packet_ptr, wait_option); - } -#else - status = nx_tcp_socket_receive(&client_ptr -> nxd_mqtt_client_socket, &packet_ptr, wait_option); -#endif /* NX_SECURE_ENABLE */ + /* Call a receive. */ + status = _nxd_mqtt_packet_receive(client_ptr, &packet_ptr, wait_option); /* Revert thread priority. */ tx_thread_priority_change(tx_thread_identify(), old_priority, &old_priority); @@ -4014,7 +4221,7 @@ UINT old_priority; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_connect_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4039,13 +4246,12 @@ UINT old_priority; /* CALLS */ /* */ /* nx_packet_release */ -/* nx_tcp_socket_send */ -/* nx_secure_tls_session_send */ /* _nxd_mqtt_packet_allocate */ /* _nxd_mqtt_release_transmit_packet */ /* _nxd_mqtt_client_connection_end */ /* _nxd_mqtt_client_set_fixed_header */ /* _nxd_mqtt_client_append_message */ +/* _nxd_mqtt_packet_send */ /* */ /* CALLED BY */ /* */ @@ -4060,6 +4266,12 @@ UINT old_priority; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_connect_packet_send(NXD_MQTT_CLIENT *client_ptr, ULONG wait_option) @@ -4137,10 +4349,10 @@ UINT keepalive = (client_ptr -> nxd_mqtt_keepalive/NX_IP_PERIODI return(NXD_MQTT_INTERNAL_ERROR); } - status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr); + status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr, wait_option); + if (status) { - return(status); } @@ -4152,21 +4364,18 @@ UINT keepalive = (client_ptr -> nxd_mqtt_keepalive/NX_IP_PERIODI if (ret) { - /* Release the packet. */ nx_packet_release(packet_ptr); - return(NXD_MQTT_PACKET_POOL_FAILURE); } - + + /* Fill in protocol name. */ ret = _nxd_mqtt_client_append_message(client_ptr, packet_ptr, "MQTT", 4, wait_option); if (ret) { - /* Release the packet. */ nx_packet_release(packet_ptr); - return(NXD_MQTT_PACKET_POOL_FAILURE); } @@ -4233,19 +4442,7 @@ UINT keepalive = (client_ptr -> nxd_mqtt_keepalive/NX_IP_PERIODI } /* Ready to send the connect message to the server. */ -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, wait_option); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - -#endif /* NX_SECURE_ENABLE */ + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, wait_option); if (status) { @@ -4353,7 +4550,7 @@ UINT ret; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_delete PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4390,6 +4587,9 @@ UINT ret; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr) @@ -4422,6 +4622,14 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr) nx_cloud_delete(&(client_ptr -> nxd_mqtt_client_cloud)); #endif /* NXD_MQTT_CLOUD_ENABLE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET + if (client_ptr -> nxd_mqtt_client_use_websocket) + { + nx_websocket_client_delete(&client_ptr -> nxd_mqtt_client_websocket); + client_ptr -> nxd_mqtt_client_use_websocket = NX_FALSE; + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + return(NXD_MQTT_SUCCESS); } @@ -4430,7 +4638,7 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr) /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_publish_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4456,10 +4664,9 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr) /* */ /* tx_mutex_get */ /* tx_mutex_put */ -/* nx_tcp_socket_send */ -/* nx_secure_tls_session_send */ /* nx_packet_release */ /* _nxd_mqtt_copy_transmit_packet */ +/* _nxd_mqtt_packet_send */ /* */ /* CALLED BY */ /* */ @@ -4472,6 +4679,13 @@ UINT _nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr) /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* supported maximum transmit */ +/* queue depth, */ +/* resulting in version 6.1.8 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_publish_packet_send(NXD_MQTT_CLIENT *client_ptr, NX_PACKET *packet_ptr, @@ -4499,6 +4713,11 @@ UINT ret = NXD_MQTT_SUCCESS; if (status != TX_SUCCESS) { nx_packet_release(transmit_packet_ptr); + +#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH + /* Decrease the transmit queue depth. */ + client_ptr -> message_transmit_queue_depth--; +#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */ return(NXD_MQTT_MUTEX_FAILURE); } @@ -4532,19 +4751,7 @@ UINT ret = NXD_MQTT_SUCCESS; tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); /* Ready to send the connect message to the server. */ -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, wait_option); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, wait_option); - -#endif /* NX_SECURE_ENABLE */ + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, wait_option); if (status) { @@ -4559,7 +4766,7 @@ UINT ret = NXD_MQTT_SUCCESS; /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_client_publish PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4608,6 +4815,9 @@ UINT ret = NXD_MQTT_SUCCESS; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nxd_mqtt_client_publish(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name, UINT topic_name_length, @@ -4633,7 +4843,7 @@ UINT ret = NXD_MQTT_SUCCESS; return(NXD_MQTT_NOT_CONNECTED); } - status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr); + status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr, wait_option); if (status != NXD_MQTT_SUCCESS) { @@ -4886,7 +5096,7 @@ UINT _nxd_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name, /* FUNCTION RELEASE */ /* */ /* _nxd_mqtt_send_simple_message PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4912,8 +5122,7 @@ UINT _nxd_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name, /* tx_mutex_get */ /* _nxd_mqtt_packet_allocate */ /* tx_mutex_put */ -/* nx_tcp_socket_send */ -/* nx_secure_tls_session_send */ +/* _nxd_mqtt_packet_send */ /* nx_packet_release */ /* */ /* CALLED BY */ @@ -4928,6 +5137,12 @@ UINT _nxd_mqtt_client_unsubscribe(NXD_MQTT_CLIENT *client_ptr, CHAR *topic_name, /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Spencer McDonough Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Bo Chen Modified comment(s), improved */ +/* the logic of sending packet,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ static UINT _nxd_mqtt_send_simple_message(NXD_MQTT_CLIENT *client_ptr, UCHAR header_value) @@ -4938,7 +5153,7 @@ UINT status; UINT status_mutex; UCHAR *byte; - status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr); + status = _nxd_mqtt_packet_allocate(client_ptr, &packet_ptr, NX_WAIT_FOREVER); if (status) { return(NXD_MQTT_INTERNAL_ERROR); @@ -4963,20 +5178,9 @@ UCHAR *byte; /* Release MQTT protection before making NetX/TLS calls. */ tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); -#ifdef NX_SECURE_ENABLE - if (client_ptr -> nxd_mqtt_client_use_tls) - { - status = nx_secure_tls_session_send(&(client_ptr -> nxd_mqtt_tls_session), packet_ptr, NX_WAIT_FOREVER); - } - else - { - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); - } -#else - status = nx_tcp_socket_send(&client_ptr -> nxd_mqtt_client_socket, packet_ptr, NX_WAIT_FOREVER); - -#endif /* NX_SECURE_ENABLE */ + /* Send packet to server. */ + status = _nxd_mqtt_packet_send(client_ptr, packet_ptr, NX_WAIT_FOREVER); status_mutex = tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, NX_WAIT_FOREVER); if (status) @@ -6163,3 +6367,207 @@ UINT status; return(NXD_MQTT_SUCCESS); } #endif /* NXD_MQTT_CLOUD_ENABLE */ + +#ifdef NXD_MQTT_OVER_WEBSOCKET +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_mqtt_client_websocket_connection_status_callback */ +/* PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the websocket connection status callback. */ +/* */ +/* INPUT */ +/* */ +/* websocket_client_ptr Pointer to websocket client */ +/* context Pointer to MQTT client */ +/* status Websocket connection status */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nxd_mqtt_client_connect_packet_send */ +/* _nxd_mqtt_client_connection_end */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_mqtt_client_event_process */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +VOID _nxd_mqtt_client_websocket_connection_status_callback(NX_WEBSOCKET_CLIENT *websocket_client_ptr, VOID *context, UINT status) +{ +NXD_MQTT_CLIENT *client_ptr = (NXD_MQTT_CLIENT *)context; + + + NX_PARAMETER_NOT_USED(websocket_client_ptr); + + if (status == NX_SUCCESS) + { + + /* Start to send MQTT connect packet. */ + status = _nxd_mqtt_client_connect_packet_send(client_ptr, NX_NO_WAIT); + } + + /* If an error occurs. */ + if (status) + { + + /* End connection. */ + _nxd_mqtt_client_connection_end(client_ptr, NX_NO_WAIT); + + /* Check callback function. */ + if (client_ptr -> nxd_mqtt_connect_notify) + { + client_ptr -> nxd_mqtt_connect_notify(client_ptr, status, client_ptr -> nxd_mqtt_connect_context); + } + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_mqtt_client_websocket_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the websocket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to MQTT Client */ +/* host Host used by the client */ +/* host_length Length of host, in bytes */ +/* uri_path URI path used by the client */ +/* uri_path_length Length of uri path, in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxd_mqtt_client_websocket_set(NXD_MQTT_CLIENT *client_ptr, UCHAR *host, UINT host_length, UCHAR *uri_path, UINT uri_path_length) +{ +UINT status; + + /* Obtain the mutex. */ + status = tx_mutex_get(client_ptr -> nxd_mqtt_client_mutex_ptr, NX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + return(NXD_MQTT_MUTEX_FAILURE); + } + + /* Set the host info. */ + client_ptr -> nxd_mqtt_client_websocket_host = host; + client_ptr -> nxd_mqtt_client_websocket_host_length = host_length; + client_ptr -> nxd_mqtt_client_websocket_uri_path = uri_path; + client_ptr -> nxd_mqtt_client_websocket_uri_path_length = uri_path_length; + + /* Create WebSocket. */ + status = nx_websocket_client_create(&client_ptr -> nxd_mqtt_client_websocket, (UCHAR *)"", + client_ptr -> nxd_mqtt_client_ip_ptr, + client_ptr -> nxd_mqtt_client_packet_pool_ptr); + + /* Check status. */ + if (status) + { + tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); + return(status); + } + + client_ptr -> nxd_mqtt_client_use_websocket = NX_TRUE; + + tx_mutex_put(client_ptr -> nxd_mqtt_client_mutex_ptr); + return(NXD_MQTT_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxde_mqtt_client_websocket_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in setting MQTT client websocket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to MQTT Client */ +/* host Host used by the client */ +/* host_length Length of host, in bytes */ +/* uri_path URI path used by the client */ +/* uri_path_length Length of uri path, in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nxd_mqtt_client_websocket_set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxde_mqtt_client_websocket_set(NXD_MQTT_CLIENT *client_ptr, UCHAR *host, UINT host_length, UCHAR *uri_path, UINT uri_path_length) +{ + + /* Validate the parameters. */ + if ((client_ptr == NX_NULL) || (host == NX_NULL) || (host_length == 0) || + (uri_path == NX_NULL) || (uri_path_length == 0)) + { + return(NX_PTR_ERROR); + } + + return(_nxd_mqtt_client_websocket_set(client_ptr, host, host_length, uri_path, uri_path_length)); +} +#endif /* NXD_MQTT_OVER_WEBSOCKET */ diff --git a/addons/mqtt/nxd_mqtt_client.h b/addons/mqtt/nxd_mqtt_client.h index 92433689..9327a779 100644 --- a/addons/mqtt/nxd_mqtt_client.h +++ b/addons/mqtt/nxd_mqtt_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_mqtt_client.h PORTABLE C */ -/* 6.1.2 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -48,6 +48,16 @@ /* 11-09-2020 Yuxin Zhou Modified comment(s), and */ /* added packet id parameter, */ /* resulting in version 6.1.2 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported maximum transmit */ +/* queue depth, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ +/* 10-31-2022 Bo Chen Modified comment(s), supported*/ +/* mqtt over websocket, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -64,6 +74,8 @@ extern "C" { #endif +#include "nx_api.h" + #ifdef NX_SECURE_ENABLE #include "nx_secure_tls_api.h" #endif /* NX_SECURE_ENABLE */ @@ -78,6 +90,18 @@ extern "C" { #endif /* NX_SECURE_ENABLE */ #endif /* NXD_MQTT_REQUIRE_TLS */ +#ifdef NXD_MQTT_OVER_WEBSOCKET +#include "nx_websocket_client.h" +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + +/* Defined, MQTT transmit queue depth is enabled. It must be positive integer. */ +/* +#define NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH 20 +*/ + +/* Define MQTT protocol for websocket. */ +#define NXD_MQTT_OVER_WEBSOCKET_PROTOCOL "mqtt" + /* Define memcpy, memset and memcmp functions used internal. */ #ifndef NXD_MQTT_SECURE_MEMCPY #define NXD_MQTT_SECURE_MEMCPY memcpy @@ -145,6 +169,9 @@ extern "C" { /* Define the default MQTT TLS (secure) port number */ #define NXD_MQTT_TLS_PORT 8883 +/* Define the default MQTT TLS (secure) over WebSocket port number */ +#define NXD_MQTT_OVER_WEBSOCKET_TLS_PORT 443 + #define MQTT_PROTOCOL_LEVEL 4 @@ -331,6 +358,9 @@ typedef struct NXD_MQTT_CLIENT_STRUCT NX_PACKET *nxd_mqtt_client_processing_packet; NX_PACKET *message_transmit_queue_head; NX_PACKET *message_transmit_queue_tail; +#ifdef NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH + UINT message_transmit_queue_depth; +#endif /* NXD_MQTT_MAXIMUM_TRANSMIT_QUEUE_DEPTH */ NX_PACKET *message_receive_queue_head; NX_PACKET *message_receive_queue_tail; UINT message_receive_queue_depth; @@ -351,6 +381,14 @@ typedef struct NXD_MQTT_CLIENT_STRUCT NX_SECURE_TLS_SESSION nxd_mqtt_tls_session; UINT nxd_mqtt_tls_in_progress; #endif +#ifdef NXD_MQTT_OVER_WEBSOCKET + UINT nxd_mqtt_client_use_websocket; + NX_WEBSOCKET_CLIENT nxd_mqtt_client_websocket; + UCHAR *nxd_mqtt_client_websocket_host; + UINT nxd_mqtt_client_websocket_host_length; + UCHAR *nxd_mqtt_client_websocket_uri_path; + UINT nxd_mqtt_client_websocket_uri_path_length; +#endif /* NXD_MQTT_OVER_WEBSOCKET */ } NXD_MQTT_CLIENT; @@ -379,6 +417,9 @@ typedef struct NXD_MQTT_CLIENT_STRUCT #define nxd_mqtt_client_receive_notify_set _nxd_mqtt_client_receive_notify_set #define nxd_mqtt_client_message_get _nxd_mqtt_client_message_get #define nxd_mqtt_client_disconnect_notify_set _nxd_mqtt_client_disconnect_notify_set +#ifdef NXD_MQTT_OVER_WEBSOCKET +#define nxd_mqtt_client_websocket_set _nxd_mqtt_client_websocket_set +#endif /* NXD_MQTT_OVER_WEBSOCKET */ #else /* if !NXD_MQTT_CLIENT_SOURCE_CODE */ #define nxd_mqtt_client_create _nxde_mqtt_client_create @@ -394,6 +435,9 @@ typedef struct NXD_MQTT_CLIENT_STRUCT #define nxd_mqtt_client_receive_notify_set _nxde_mqtt_client_receive_notify_set #define nxd_mqtt_client_message_get _nxde_mqtt_client_message_get #define nxd_mqtt_client_disconnect_notify_set _nxde_mqtt_client_disconnect_notify_set +#ifdef NXD_MQTT_OVER_WEBSOCKET +#define nxd_mqtt_client_websocket_set _nxde_mqtt_client_websocket_set +#endif /* NXD_MQTT_OVER_WEBSOCKET */ #endif /* NX_DISABLE_ERROR_CHECKING */ @@ -427,6 +471,9 @@ UINT nxd_mqtt_client_disconnect(NXD_MQTT_CLIENT *client_ptr); UINT nxd_mqtt_client_delete(NXD_MQTT_CLIENT *client_ptr); UINT nxd_mqtt_client_disconnect_notify_set(NXD_MQTT_CLIENT *client_ptr, VOID (*disconnect_notify)(NXD_MQTT_CLIENT *)); +#ifdef NXD_MQTT_OVER_WEBSOCKET +UINT nxd_mqtt_client_websocket_set(NXD_MQTT_CLIENT *client_ptr, UCHAR *host, UINT host_length, UCHAR *uri_path, UINT uri_path_length); +#endif /* NXD_MQTT_OVER_WEBSOCKET */ #else /* ifdef NXD_MQTT_CLIENT_SOURCE_CODE */ @@ -500,6 +547,12 @@ UINT _nxde_mqtt_client_secure_connect(NXD_MQTT_CLIENT *client_ptr, NXD_ADDRESS * UINT keepalive, UINT clean_session, ULONG timeout); #endif /* NX_SECURE_ENABLE */ +#ifdef NXD_MQTT_OVER_WEBSOCKET +UINT _nxd_mqtt_client_websocket_set(NXD_MQTT_CLIENT *client_ptr, UCHAR *host, UINT host_length, UCHAR *uri_path, UINT uri_path_length); +UINT _nxde_mqtt_client_websocket_set(NXD_MQTT_CLIENT *client_ptr, UCHAR *host, UINT host_length, UCHAR *uri_path, UINT uri_path_length); +VOID _nxd_mqtt_client_websocket_connection_status_callback(NX_WEBSOCKET_CLIENT *websocket_client_ptr, VOID *context, UINT status); +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + #endif /* ifndef NXD_MQTT_CLIENT_SOURCE_CODE */ #ifdef NXD_MQTT_CLOUD_ENABLE diff --git a/addons/pop3/nxd_pop3_client.c b/addons/pop3/nxd_pop3_client.c index 66f9363c..b5916b32 100644 --- a/addons/pop3/nxd_pop3_client.c +++ b/addons/pop3/nxd_pop3_client.c @@ -2229,7 +2229,7 @@ UINT pid_index; /* FUNCTION RELEASE */ /* */ /* _nx_pop3_parse_response PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2275,6 +2275,9 @@ UINT pid_index; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ void _nx_pop3_parse_response(CHAR *buffer, UINT argument_index, UINT buffer_length, CHAR *argument, UINT argument_length, @@ -2343,7 +2346,7 @@ UINT argument_char_count; } /* Are we at the end of the buffer? */ - if (i == buffer_length) + if ((i == buffer_length) && (buffer_length >= 2)) { /* Yes, is there a line terminator? */ @@ -2607,7 +2610,7 @@ UINT size; /* FUNCTION RELEASE */ /* */ /* _nxd_pop3_client_connect PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2655,6 +2658,9 @@ UINT size; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* corrected the client port, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxd_pop3_client_connect(NX_POP3_CLIENT *client_ptr, NXD_ADDRESS *server_ip_address, ULONG server_port) @@ -2674,7 +2680,7 @@ CHAR argument[10]; return NX_POP3_PARAM_ERROR; } - status = nx_tcp_client_socket_bind(&client_ptr -> nx_pop3_client_tcp_socket, 4228, NX_IP_PERIODIC_RATE); + status = nx_tcp_client_socket_bind(&client_ptr -> nx_pop3_client_tcp_socket, NX_ANY_PORT, NX_IP_PERIODIC_RATE); /* Check for error. */ if (status != NX_SUCCESS) diff --git a/addons/ppp/nx_ppp.c b/addons/ppp/nx_ppp.c index 47410a20..5a3a42a4 100644 --- a/addons/ppp/nx_ppp.c +++ b/addons/ppp/nx_ppp.c @@ -24,14 +24,17 @@ /* Force error checking to be disabled in this module */ +#include "tx_port.h" #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif +#endif /* Include necessary system files. */ @@ -2210,7 +2213,7 @@ NX_PACKET *packet_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_ppp_lcp_state_machine_update PORTABLE C */ -/* 6.1.2 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2257,6 +2260,9 @@ NX_PACKET *packet_ptr; /* improved packet length */ /* verification, */ /* resulting in version 6.1.2 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), fixed */ +/* the logic of retransmission,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ void _nx_ppp_lcp_state_machine_update(NX_PPP *ppp_ptr, NX_PACKET *packet_ptr) @@ -2801,9 +2807,6 @@ UINT status; /* Yes, the peer can accept larger messages than the default. */ (ppp_ptr -> nx_ppp_interface_ptr) -> nx_interface_ip_mtu_size = ppp_ptr -> nx_ppp_mru; } - - /* Disable the LCP timeout. */ - ppp_ptr -> nx_ppp_timeout = 0; } /* Send configuration reply. */ diff --git a/addons/ppp/nx_ppp.h b/addons/ppp/nx_ppp.h index 854bc13e..0f2f7bed 100644 --- a/addons/ppp/nx_ppp.h +++ b/addons/ppp/nx_ppp.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_ppp.h PORTABLE C */ -/* 6.1.2 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -49,6 +49,9 @@ /* improved packet length */ /* verification, */ /* resulting in version 6.1.2 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -65,6 +68,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the PPP ID. */ #define NX_PPP_ID 0x50505020UL diff --git a/addons/pppoe/nx_pppoe_client.c b/addons/pppoe/nx_pppoe_client.c index 7959cd0f..aa9e44b3 100644 --- a/addons/pppoe/nx_pppoe_client.c +++ b/addons/pppoe/nx_pppoe_client.c @@ -24,14 +24,17 @@ /* Force error checking to be disabled in this module */ +#include "tx_port.h" #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif +#endif /* Include necessary system files. */ @@ -609,7 +612,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_service_name_set_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -650,6 +653,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_pppoe_client_service_name_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *service_name, UINT service_name_length) @@ -671,6 +677,9 @@ UINT temp_service_name_length = 0; /* Setup service name pointer. */ pppoe_client_ptr -> nx_pppoe_service_name = service_name; + /* Setup service name length. */ + pppoe_client_ptr -> nx_pppoe_service_name_length = service_name_length; + /* Release the IP internal mutex. */ tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection)); @@ -869,7 +878,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_host_uniq_set_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -910,6 +919,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_pppoe_client_host_uniq_set_extended(NX_PPPOE_CLIENT *pppoe_client_ptr, UCHAR *host_uniq, UINT host_uniq_length) @@ -927,8 +939,11 @@ UINT temp_host_uniq_length = 0; /* Obtain the IP internal mutex before processing the IP event. */ tx_mutex_get(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); - /* Setup service name pointer. */ + /* Setup host unique pointer. */ pppoe_client_ptr -> nx_pppoe_host_uniq = host_uniq; + + /* Setup host unique length. */ + pppoe_client_ptr -> nx_pppoe_host_uniq_length = host_uniq_length; /* Release the IP internal mutex. */ tx_mutex_put(&(pppoe_client_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection)); @@ -2160,7 +2175,7 @@ UINT ethernet_type; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_discovery_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2203,6 +2218,9 @@ UINT ethernet_type; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ VOID _nx_pppoe_client_discovery_packet_process(NX_PPPOE_CLIENT *pppoe_client_ptr, NX_PACKET *packet_ptr, ULONG server_mac_msw, ULONG server_mac_lsw) @@ -2367,7 +2385,8 @@ UINT tag_host_uniq_valid = NX_FALSE; { /* Compare the service name with PPPoE Service name that Client is requesting. */ - if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length)) + if ((pppoe_client_ptr -> nx_pppoe_service_name_length == tag_length) && + (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_service_name, tag_length))) { /* Update the information. */ @@ -2407,7 +2426,8 @@ UINT tag_host_uniq_valid = NX_FALSE; tag_host_uniq_count ++; /* Check the Host-Uniq. */ - if (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length)) + if ((pppoe_client_ptr -> nx_pppoe_host_uniq_length == tag_length) && + (!memcmp(tag_ptr + tag_index, pppoe_client_ptr -> nx_pppoe_host_uniq, tag_length))) { /* Update the information. */ @@ -2754,7 +2774,7 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_client_discovery_send PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2796,6 +2816,9 @@ NX_PPPOE_SERVER_SESSION *server_session_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ static UINT _nx_pppoe_client_discovery_send(NX_PPPOE_CLIENT *pppoe_client_ptr, UINT code) @@ -2806,7 +2829,6 @@ NX_PACKET *packet_ptr; UCHAR *work_ptr; UINT status; UINT index = 0; -UINT tag_length; /* Allocate a PPPoE packet. */ @@ -2846,21 +2868,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_service_name) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_service_name_length)) { /* Added the Service-Name tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); } else { @@ -2881,21 +2894,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_host_uniq) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length)) { /* Added the Host-Uniq tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); } else { @@ -2914,22 +2918,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_service_name) { - - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_service_name), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_SERVICE_NAME_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_service_name_length)) { /* Added the Service-Name tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, tag_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_SERVICE_NAME, pppoe_client_ptr -> nx_pppoe_service_name_length, pppoe_client_ptr -> nx_pppoe_service_name, &index); } else { @@ -2950,21 +2944,12 @@ UINT tag_length; if (pppoe_client_ptr -> nx_pppoe_host_uniq) { - /* Calculate the name length. */ - if (_nx_utility_string_length_check((char *)(pppoe_client_ptr -> nx_pppoe_host_uniq), &tag_length, NX_MAX_STRING_LENGTH)) - { - - /* Packet too small. */ - nx_packet_release(packet_ptr); - return(NX_PPPOE_CLIENT_PACKET_PAYLOAD_ERROR); - } - if (((ULONG)(packet_ptr -> nx_packet_data_end) - (ULONG)(&work_ptr[index])) >= - (4 + tag_length)) + (4 + pppoe_client_ptr -> nx_pppoe_host_uniq_length)) { /* Added the Host-Uniq tag. */ - _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, tag_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); + _nx_pppoe_client_tag_string_add(work_ptr, NX_PPPOE_CLIENT_TAG_TYPE_HOST_UNIQ, pppoe_client_ptr -> nx_pppoe_host_uniq_length, pppoe_client_ptr -> nx_pppoe_host_uniq, &index); } else { diff --git a/addons/pppoe/nx_pppoe_client.h b/addons/pppoe/nx_pppoe_client.h index 8c03978e..bd345924 100644 --- a/addons/pppoe/nx_pppoe_client.h +++ b/addons/pppoe/nx_pppoe_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_pppoe_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,6 +44,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* resulting in version 6.1.3 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -60,6 +66,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Note: Prerequisite for using PPPoE. Redefine NX_PHYSICAL_HEADER to 24 to ensure enough space for filling in physical header. Physical header:14(Ethernet header) + 6(PPPoE header) + 2(PPP header) + 2(four-byte aligment). */ @@ -228,7 +236,9 @@ typedef struct NX_PPPOE_CLIENT_STRUCT UINT nx_pppoe_state; NX_PPPOE_SERVER_SESSION nx_pppoe_server_session; UCHAR *nx_pppoe_service_name; + UINT nx_pppoe_service_name_length; UCHAR *nx_pppoe_host_uniq; + UINT nx_pppoe_host_uniq_length; UCHAR nx_pppoe_ac_name[NX_PPPOE_CLIENT_MAX_AC_NAME_SIZE]; UINT nx_pppoe_ac_name_size; UCHAR nx_pppoe_ac_cookie[NX_PPPOE_CLIENT_MAX_AC_COOKIE_SIZE]; diff --git a/addons/pppoe/nx_pppoe_server.c b/addons/pppoe/nx_pppoe_server.c index 31c51b57..1a926cf9 100644 --- a/addons/pppoe/nx_pppoe_server.c +++ b/addons/pppoe/nx_pppoe_server.c @@ -24,14 +24,17 @@ /* Force error checking to be disabled in this module */ +#include "tx_port.h" #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif +#endif /* Include necessary system files. */ @@ -2790,7 +2793,7 @@ NX_PPPOE_CLIENT_SESSION *client_session_ptr = NX_NULL; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_server_discovery_send PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2834,6 +2837,9 @@ NX_PPPOE_CLIENT_SESSION *client_session_ptr = NX_NULL; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_pppoe_server_discovery_send(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code) @@ -2919,7 +2925,7 @@ UCHAR *service_name_ptr; { /* Get the service name. */ - if (_nx_utility_string_length_check((const char *)(service_name_ptr), &tag_length, NX_MAX_STRING_LENGTH)) + if (_nx_utility_string_length_check((char *)(service_name_ptr), &tag_length, NX_MAX_STRING_LENGTH)) { nx_packet_release(packet_ptr); return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR); @@ -3057,7 +3063,7 @@ UCHAR *service_name_ptr; { /* Calculate the Generic-Error string length. */ - if (_nx_utility_string_length_check((const char *)(client_session_ptr -> nx_pppoe_generic_error), &tag_length, NX_MAX_STRING_LENGTH)) + if (_nx_utility_string_length_check((char *)(client_session_ptr -> nx_pppoe_generic_error), &tag_length, NX_MAX_STRING_LENGTH)) { nx_packet_release(packet_ptr); return(NX_SIZE_ERROR); @@ -3181,7 +3187,7 @@ NX_IP_DRIVER driver_request; /* FUNCTION RELEASE */ /* */ /* _nx_pppoe_server_tag_process PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3220,6 +3226,10 @@ NX_IP_DRIVER driver_request; /* packet length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* string length verification, */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ static UINT _nx_pppoe_server_tag_process(NX_PPPOE_SERVER *pppoe_server_ptr, NX_PPPOE_CLIENT_SESSION *client_session_ptr, UINT code, UCHAR *tag_ptr, ULONG length) @@ -3231,9 +3241,9 @@ UINT tag_index = 0; UINT tag_service_name_count = 0; UINT tag_service_name_valid = NX_FALSE; UINT service_name_index = 0; +UINT service_name_length; #ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE UCHAR *service_name_ptr; -UINT service_name_length; #endif /* Initialize the value. */ @@ -3303,11 +3313,21 @@ UINT service_name_length; while (service_name_index < pppoe_server_ptr -> nx_pppoe_service_name_count) { + /* Get the length of service name. */ + if (_nx_utility_string_length_check((char *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), + &service_name_length, tag_length)) + { + service_name_index++; + continue; + } + /* Compare the same service name with PPPoE Service Name. */ - if (!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length)) + if ((service_name_length == tag_length) && + (!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length))) { tag_service_name_valid = NX_TRUE; client_session_ptr -> nx_pppoe_service_name = pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]; + client_session_ptr -> nx_pppoe_service_name_length = service_name_length; break; } service_name_index ++; @@ -3337,7 +3357,7 @@ UINT service_name_length; { /* Get the service name. */ - if (_nx_utility_string_length_check((const char *)(service_name_ptr), &service_name_length, NX_MAX_STRING_LENGTH)) + if (_nx_utility_string_length_check((char *)(service_name_ptr), &service_name_length, NX_MAX_STRING_LENGTH)) { return(NX_PPPOE_SERVER_SERVICE_NAME_ERROR); } @@ -3347,7 +3367,7 @@ UINT service_name_length; { tag_service_name_valid = NX_TRUE; } - else if ((tag_length != 0) && (service_name_length != 0)) + else if ((tag_length != 0) && (tag_length == service_name_length)) { /* Compare the service name. */ @@ -3383,8 +3403,17 @@ UINT service_name_length; while (service_name_index < pppoe_server_ptr -> nx_pppoe_service_name_count) { + /* Get the length of service name. */ + if (_nx_utility_string_length_check((char *)(pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), + &service_name_length, tag_length)) + { + service_name_index++; + continue; + } + /* Find the same service name. */ - if (!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length)) + if ((service_name_length == tag_length) && + (!memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_service_name[service_name_index]), tag_length))) { /* Update the information. */ @@ -3403,7 +3432,8 @@ UINT service_name_length; if (pppoe_server_ptr -> nx_pppoe_ac_name) { /* Check the access concentrator name. */ - if (memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_ac_name), tag_length)) + if ((pppoe_server_ptr -> nx_pppoe_ac_name_length != tag_length) || + (memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_ac_name), tag_length))) { return(NX_PPPOE_SERVER_AC_NAME_ERROR); @@ -3412,7 +3442,8 @@ UINT service_name_length; else { /* If user does not separately set Access Concentrator name, will use PPPoE server name as Access Concentrator name.*/ - if (memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_name), tag_length)) + if ((pppoe_server_ptr -> nx_pppoe_name_length != tag_length) || + (memcmp(tag_ptr + tag_index, (pppoe_server_ptr -> nx_pppoe_name), tag_length))) { return(NX_PPPOE_SERVER_AC_NAME_ERROR); @@ -3960,7 +3991,7 @@ NX_PACKET *current_packet; /* FUNCTION RELEASE */ /* */ /* PppInitInd PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3981,7 +4012,7 @@ NX_PACKET *current_packet; /* */ /* CALLS */ /* */ -/* nx_pppoe_server_service_name_set Set the service name */ +/* _nx_pppoe_server_service_name_set Set the service name */ /* */ /* CALLED BY */ /* */ @@ -3994,6 +4025,9 @@ NX_PACKET *current_packet; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ VOID PppInitInd(UINT length, UCHAR *aData) @@ -4009,7 +4043,7 @@ VOID PppInitInd(UINT length, UCHAR *aData) { /* Clean the default service name. */ - nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, NX_NULL, 0); + _nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, NX_NULL, 0); } else { @@ -4018,7 +4052,7 @@ VOID PppInitInd(UINT length, UCHAR *aData) nx_pppoe_service_name[0] = aData; /* Set the default service name. */ - nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, nx_pppoe_service_name, 1); + _nx_pppoe_server_service_name_set(_nx_pppoe_server_created_ptr, nx_pppoe_service_name, 1); } } @@ -4215,7 +4249,7 @@ NX_PPPOE_CLIENT_SESSION *client_session_ptr; /* FUNCTION RELEASE */ /* */ /* PppCloseInd PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4235,7 +4269,7 @@ NX_PPPOE_CLIENT_SESSION *client_session_ptr; /* */ /* CALLS */ /* */ -/* nx_pppoe_server_session_terminate Terminate the PPPoE Session */ +/* _nx_pppoe_server_session_terminate Terminate the PPPoE Session */ /* */ /* CALLED BY */ /* */ @@ -4248,6 +4282,9 @@ NX_PPPOE_CLIENT_SESSION *client_session_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ VOID PppCloseInd(UINT interfaceHandle, UCHAR *causeCode) @@ -4278,7 +4315,7 @@ VOID PppCloseInd(UINT interfaceHandle, UCHAR *causeCode) _nx_pppoe_server_created_ptr -> nx_pppoe_client_session[interfaceHandle].nx_pppoe_generic_error = causeCode; /* Send PADT to terminate the session. */ - nx_pppoe_server_session_terminate(_nx_pppoe_server_created_ptr, interfaceHandle); + _nx_pppoe_server_session_terminate(_nx_pppoe_server_created_ptr, interfaceHandle); /* Release the IP internal mutex. */ tx_mutex_put(&(_nx_pppoe_server_created_ptr -> nx_pppoe_ip_ptr -> nx_ip_protection)); @@ -4354,7 +4391,7 @@ VOID PppCloseCnf(UINT interfaceHandle) /* FUNCTION RELEASE */ /* */ /* PppTransmitDataCnf PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4388,6 +4425,9 @@ VOID PppCloseCnf(UINT interfaceHandle) /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ VOID PppTransmitDataCnf(UINT interfaceHandle, UCHAR *data_ptr, UINT packet_id) @@ -4395,6 +4435,8 @@ VOID PppTransmitDataCnf(UINT interfaceHandle, UCHAR *data_ptr, UINT packet_id) NX_PACKET *packet_ptr; + NX_PARAMETER_NOT_USED(data_ptr); + /* Check to see if PPPoE instance is created. */ if ((_nx_pppoe_server_created_ptr == NX_NULL) || (_nx_pppoe_server_created_ptr -> nx_pppoe_id != NX_PPPOE_SERVER_ID)) @@ -4435,7 +4477,7 @@ NX_PACKET *packet_ptr; /* FUNCTION RELEASE */ /* */ /* PppReceiveDataInd PORTABLE C */ -/* 6.1 */ +/* 6.1.4 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4454,7 +4496,7 @@ NX_PACKET *packet_ptr; /* */ /* CALLS */ /* */ -/* nx_pppoe_server_session_send Send PPPoE session data */ +/* _nx_pppoe_server_session_send Send PPPoE session data */ /* */ /* CALLED BY */ /* */ @@ -4467,6 +4509,9 @@ NX_PACKET *packet_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ /* */ /**************************************************************************/ VOID PppReceiveDataInd(UINT interfaceHandle, UINT data_length, UCHAR *data_ptr) @@ -4491,7 +4536,7 @@ VOID PppReceiveDataInd(UINT interfaceHandle, UINT data_length, UCHAR *data_ptr) return; /* Send data. */ - nx_pppoe_server_session_send(_nx_pppoe_server_created_ptr, interfaceHandle, data_ptr, data_length); + _nx_pppoe_server_session_send(_nx_pppoe_server_created_ptr, interfaceHandle, data_ptr, data_length); } #endif #endif /* NX_DISABLE_IPV4 */ diff --git a/addons/pppoe/nx_pppoe_server.h b/addons/pppoe/nx_pppoe_server.h index 859aa666..402f0d22 100644 --- a/addons/pppoe/nx_pppoe_server.h +++ b/addons/pppoe/nx_pppoe_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_pppoe_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,6 +44,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the compiler errors, */ +/* resulting in version 6.1.4 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -60,6 +66,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Note: Prerequisite for using PPPoE. Redefine NX_PHYSICAL_HEADER to 24 to ensure enough space for filling in physical header. Physical header:14(Ethernet header) + 6(PPPoE header) + 2(PPP header) + 2(four-byte aligment). */ @@ -315,16 +323,6 @@ UINT nx_pppoe_server_session_terminate(NX_PPPOE_SERVER *pppoe_server_ptr, UIN UINT nx_pppoe_server_session_get(NX_PPPOE_SERVER *pppoe_server_ptr, UINT session_index, ULONG *client_mac_msw, ULONG *client_mac_lsw, ULONG *session_id); VOID _nx_pppoe_server_packet_deferred_receive(NX_PACKET *packet_ptr); -#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE -VOID PppInitInd(UINT length, UCHAR *aData); -VOID PppDiscoverCnf(UINT length, UCHAR *aData, UINT interfaceHandle); -VOID PppOpenCnf(UCHAR accept, UINT interfaceHandle); -VOID PppCloseInd(UINT interfaceHandle, UCHAR *causeCode); -VOID PppCloseCnf(UINT interfaceHandle); -VOID PppTransmitDataCnf(UINT interfaceHandle, UCHAR *aData, UINT packet_id); -VOID PppReceiveDataInd(UINT interfaceHandle, UINT length, UCHAR *aData); -#endif - #else UINT _nxe_pppoe_server_create(NX_PPPOE_SERVER *pppoe_server_ptr, UCHAR *name, NX_IP *ip_ptr, UINT interface_index, @@ -369,6 +367,16 @@ VOID _nx_pppoe_server_packet_deferred_receive(NX_PACKET *packet_ptr); #endif /* NX_PPPOE_SERVER_SOURCE_CODE */ +#ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE +VOID PppInitInd(UINT length, UCHAR *aData); +VOID PppDiscoverCnf(UINT length, UCHAR *aData, UINT interfaceHandle); +VOID PppOpenCnf(UCHAR accept, UINT interfaceHandle); +VOID PppCloseInd(UINT interfaceHandle, UCHAR *causeCode); +VOID PppCloseCnf(UINT interfaceHandle); +VOID PppTransmitDataCnf(UINT interfaceHandle, UCHAR *aData, UINT packet_id); +VOID PppReceiveDataInd(UINT interfaceHandle, UINT length, UCHAR *aData); +#endif + /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ #ifdef __cplusplus diff --git a/addons/ptp/nxd_ptp_client.c b/addons/ptp/nxd_ptp_client.c new file mode 100644 index 00000000..347e158b --- /dev/null +++ b/addons/ptp/nxd_ptp_client.c @@ -0,0 +1,3739 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX PTP Client Component */ +/** */ +/** Precision Time Protocol (PTP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nxd_ptp_client.c PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX Precision Time Protocol (PTP) */ +/* Client component, including all data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + + +/* Force error checking to be disabled in this module */ + +#ifndef NX_DISABLE_ERROR_CHECKING +#define NX_DISABLE_ERROR_CHECKING +#endif + +#define NX_PTP_SOURCE_CODE + +#include "nxd_ptp_client.h" +#include "nx_udp.h" +#include "nx_ipv4.h" +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +#include "nx_ipv6.h" +#endif +#include "tx_timer.h" + +/* #define NX_PTP_DEBUG */ +/* #define NX_PTP_DEBUG_OFFSET */ +#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET) +#include +#endif +#ifdef NX_PTP_DEBUG +#ifndef NX_PTP_DEBUG_PRINTF +#define NX_PTP_DEBUG_PRINTF(x) printf x +#endif +#else +#define NX_PTP_DEBUG_PRINTF(x) +#endif + +/* Bring in externs for caller checking code. */ + +NX_CALLER_CHECKING_EXTERNS + +/* number of nanoseconds per second */ +#define NX_PTP_NANOSECONDS_PER_SEC 1000000000L + +/* Define the PTP version */ +#define NX_PTP_VERSION 2 + +/* Define the UDP ports */ +#define NX_PTP_EVENT_UDP_PORT 319 +#define NX_PTP_GENERAL_UDP_PORT 320 + +/* Define the TTL of PTP packets */ +#define NX_PTP_TIME_TO_LIVE 1 + +/* Define the IPv4 multicast address "224.0.1.129" */ +#define NX_PTP_IPV4_MULTICAST_ADDR IP_ADDRESS(224, 0, 1, 129) + +/* Define the IPv6 multicast address "ff0e::181" */ +#define NX_PTP_IPV6_MULTICAST_ADDR_SET(x) { \ + (x) -> nxd_ip_version = NX_IP_VERSION_V6; \ + (x) -> nxd_ip_address.v6[0] = 0xff0e0000UL; \ + (x) -> nxd_ip_address.v6[1] = 0; \ + (x) -> nxd_ip_address.v6[2] = 0; \ + (x) -> nxd_ip_address.v6[3] = 0x181; } + +/* Length of PTP message header */ +#define NX_PTP_MSG_HDR_LEN 34 + +/* Length of PTP messages (without header) */ +#define NX_PTP_MSG_ANNOUNCE_LEN 30 +#define NX_PTP_MSG_SYNC_LEN 10 +#define NX_PTP_MSG_FOLLOW_UP_LEN 10 +#define NX_PTP_MSG_DELAY_RESP_LEN 20 + +/* Length of PTP timestamp */ +#define NX_PTP_MSG_TIMESTAMP_LEN 10 + +/* Get version number */ +#define NX_PTP_MSG_VERSION(p_) ((p_)[1] & 0xf) + +/* Get domain number */ +#define NX_PTP_MSG_DOMAIN(p_) ((p_)[4]) + +/* Type of messages */ +#define NX_PTP_MSG_TYPE_SYNC 0 +#define NX_PTP_MSG_TYPE_DELAY_REQ 1 +#define NX_PTP_MSG_TYPE_FOLLOW_UP 8 +#define NX_PTP_MSG_TYPE_DELAY_RESP 9 +#define NX_PTP_MSG_TYPE_ANNOUNCE 11 + +/* Message flags */ +#define NX_PTP_MSG_HDR_FLAG_LEAP61 (1 << 0) +#define NX_PTP_MSG_HDR_FLAG_LEAP59 (1 << 1) +#define NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE (1 << 2) +#define NX_PTP_MSG_HDR_FLAG_TWO_STEP (1 << 9) + +/* Common Message Header */ +typedef struct NX_PTP_MSG_HEADER_STRUCT +{ + UCHAR transportSpecific; + UCHAR messageType; + UCHAR versionPTP; + UCHAR domainNumber; + USHORT messageLength; + USHORT flagField; + ULONG cFieldHigh; + ULONG cFieldLow; + UCHAR *sourcePortIdentity; + USHORT sequenceId; + UCHAR logMessageInterval; +} NX_PTP_MSG_HEADER; + +/* Get UTC offset from announce message */ +#define NX_PTP_MSG_UTC_OFFSET(p_) ((SHORT)((p_[10] << 8) | p_[11])) + +/* Macros for reading PTP packet fields */ +#define NX_PTP_RD16(p_, v_) { \ + USHORT t_; \ + t_ = *p_++; \ + t_ = (USHORT)(t_ << 8); \ + v_ = (USHORT)(t_ | *p_++); } + +#define NX_PTP_RD32(p_, v_) { \ + ULONG t_; \ + t_ = *p_++; \ + t_ <<= 8; \ + t_ |= *p_++; \ + t_ <<= 8; \ + t_ |= *p_++; \ + t_ <<= 8; \ + v_ = t_ |= *p_++; } + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_timestamp PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses timestamp field of a PTP message. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to PTP message */ +/* time_ptr Pointer to PTP time for output*/ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_msg_parse_timestamp(UCHAR *ptr, NX_PTP_TIME *time_ptr) +{ +ULONG nanoseconds = (ULONG)time_ptr -> nanosecond; + + NX_PTP_RD16(ptr, time_ptr -> second_high); + NX_PTP_RD32(ptr, time_ptr -> second_low); + NX_PTP_RD32(ptr, nanoseconds); + time_ptr -> nanosecond = (LONG)nanoseconds; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_hdr PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses the header of a PTP packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* hdr Parsed PTP header for output */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nxd_udp_packet_info_extract Extract UDP packet information*/ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static UINT _nx_ptp_msg_parse_hdr(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_MSG_HEADER *hdr) +{ +UCHAR b; +UCHAR *ptr; +UINT len; +UINT status; +NXD_ADDRESS src_addr; +UINT interface_index; + +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) + { + + /* Chained packet is not supported */ + return(NX_NOT_SUPPORTED); + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* get pointer to PTP message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + + /* get length of PTP message */ + len = packet_ptr -> nx_packet_length; + + /* check packet validity: */ + /* - length >= PTP header length */ + /* - PTP version */ + /* - domain number */ + if ((len < NX_PTP_MSG_HDR_LEN) || + (NX_PTP_MSG_VERSION(ptr) != NX_PTP_VERSION) || + (NX_PTP_MSG_DOMAIN(ptr) != client_ptr -> nx_ptp_client_domain)) + { + + /* discard invalid packet */ + return(NX_INVALID_PACKET); + } + + /* get info about sender and check packet validity: */ + /* - network interface */ + /* - IP version */ + status = nxd_udp_packet_info_extract(packet_ptr, &src_addr, NX_NULL, NX_NULL, &interface_index); + if ((status != NX_SUCCESS) || + (interface_index != client_ptr -> nx_ptp_client_interface_index) +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + || ((src_addr.nxd_ip_version == NX_IP_VERSION_V4) && + !client_ptr -> nx_ptp_client_ipv4_group_joined) || + ((src_addr.nxd_ip_version == NX_IP_VERSION_V6) && + !client_ptr -> nx_ptp_client_ipv6_group_joined) +#endif + ) + { + + /* discard invalid packet */ + return(NX_INVALID_PACKET); + } + + /* Save source address in listening state */ + if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING) + { + client_ptr -> nx_ptp_client_master_addr = src_addr; + } + + b = *ptr++; + hdr -> transportSpecific = b >> 4; + hdr -> messageType = b & 0xf; + b = *ptr++; + hdr -> versionPTP = b & 0xf; + NX_PTP_RD16(ptr, hdr -> messageLength); + hdr -> domainNumber = *ptr++; + ptr++; /* reserved */ + NX_PTP_RD16(ptr, hdr -> flagField); + NX_PTP_RD32(ptr, hdr -> cFieldHigh); + NX_PTP_RD32(ptr, hdr -> cFieldLow); + ptr += 4; /* reserved */ + hdr -> sourcePortIdentity = ptr; + ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + NX_PTP_RD16(ptr, hdr -> sequenceId); + ptr++; /* controlField - ignore */ + hdr -> logMessageInterval = *ptr; + + /* adjust message length */ + if (len > hdr -> messageLength) + { + if (hdr -> messageLength < NX_PTP_MSG_HDR_LEN) + { + + /* invalid length */ + return(NX_INVALID_PACKET); + } + len = hdr -> messageLength; + } + + /* Adjust packet. */ + packet_ptr -> nx_packet_prepend_ptr += NX_PTP_MSG_HDR_LEN; + packet_ptr -> nx_packet_length = len - NX_PTP_MSG_HDR_LEN; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_msg_parse_announce PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function parses PTP Announce message. */ +/* */ +/* INPUT */ +/* */ +/* ptr Pointer to PTP message */ +/* master_ptr Parsed PTP master for output */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_announce_received Process Announce message */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_msg_parse_announce(UCHAR *ptr, NX_PTP_CLIENT_MASTER *master) +{ + ptr += NX_PTP_MSG_TIMESTAMP_LEN + 2 + 1; /* originTimestamp, utcOffset, reserved */ + master -> nx_ptp_client_master_priority1 = *ptr++; + master -> nx_ptp_client_master_clock_class = *ptr++; + master -> nx_ptp_client_master_clock_accuracy = *ptr++; + NX_PTP_RD16(ptr, master -> nx_ptp_client_master_offset_scaled_log_variance); + master -> nx_ptp_client_master_priority2 = *ptr++; + master -> nx_ptp_client_master_grandmaster_identity = ptr; + ptr += NX_PTP_CLOCK_IDENTITY_SIZE; + NX_PTP_RD16(ptr, master -> nx_ptp_client_master_steps_removed); + master -> nx_ptp_client_master_time_source = *ptr; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_soft_clock_adjust PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adjusts the value of the soft PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* offset_ns Signed number of nanoseconds */ +/* to add to the PTP clock */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_callback Soft PTP clock */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_soft_clock_adjust(VOID *ptp_instance, LONG offset_ns) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; +TX_INTERRUPT_SAVE_AREA + + /* enforce min/max values of offset */ + if (offset_ns > NX_PTP_NANOSECONDS_PER_SEC) + { + offset_ns = NX_PTP_NANOSECONDS_PER_SEC; + } + else if (offset_ns < -NX_PTP_NANOSECONDS_PER_SEC) + { + offset_ns = -NX_PTP_NANOSECONDS_PER_SEC; + } + + /* add the number of nanosecond to the current time */ + TX_DISABLE + client_ptr -> nx_ptp_client_soft_clock.nanosecond += offset_ns; + if (client_ptr -> nx_ptp_client_soft_clock.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + client_ptr -> nx_ptp_client_soft_clock.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&client_ptr -> nx_ptp_client_soft_clock.second_high, + &client_ptr -> nx_ptp_client_soft_clock.second_low); + } + else if (client_ptr -> nx_ptp_client_soft_clock.nanosecond < 0) + { + client_ptr -> nx_ptp_client_soft_clock.nanosecond += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&client_ptr -> nx_ptp_client_soft_clock.second_high, + &client_ptr -> nx_ptp_client_soft_clock.second_low); + } + TX_RESTORE +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_timer_handler PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements the PTP client timer handler. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set Set PTP timer event */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX Timer */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_timer_handler(ULONG ptp_instance) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; + + /* Update soft timer. */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE, + &client_ptr -> nx_ptp_client_soft_clock, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* set timer event */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_TIMER_EVENT, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_socket_receive_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is invoked when UDP packet is received. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to general socket */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_event_flags_set Set UDP receive event */ +/* */ +/* CALLED BY */ +/* */ +/* NetX UDP */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_socket_receive_notify(NX_UDP_SOCKET *socket_ptr) +{ +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)(socket_ptr -> nx_udp_socket_reserved_ptr); + + /* set timer event */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_RX_EVENT, TX_OR); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_clock_adjust PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Adjust the PTP clock with the given offset */ +/* If the offset is greater than one second, the clock is updated, */ +/* otherwise it is adjusted with the number of nanoseconds. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* offset_ptr Pointer to time offset */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* _nx_ptp_client_utility_add64 Add two 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_clock_adjust(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *offset_ptr) +{ +NX_PTP_TIME current; + + if ((offset_ptr -> second_high == 0) && (offset_ptr -> second_low == 0)) + { + + /* offset less than 1s, adjust clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_ADJUST, offset_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + NX_PTP_DEBUG_PRINTF(("PTP: adjust clock %d ns\r\n", (INT)offset_ptr -> nanosecond)); + } + else + { + + /* offset greater than 1s, set new clock value */ + /* get current clock value */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, ¤t, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* add nanoseconds offset */ + current.nanosecond += offset_ptr -> nanosecond; + + /* ensure nanosecond field is in range 0-999999999 */ + if (current.nanosecond < 0) + { + current.nanosecond += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(¤t.second_high, ¤t.second_low); + } + else if (current.nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + current.nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(¤t.second_high, ¤t.second_low); + } + + /* add seconds offset */ + _nx_ptp_client_utility_add64(¤t.second_high, ¤t.second_low, + offset_ptr -> second_high, offset_ptr -> second_low); + + /* set new clock value */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, ¤t, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + NX_PTP_DEBUG_PRINTF(("PTP: set clock %u.%d\r\n", + (UINT)current.second_low, + (INT)current.nanosecond)); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_send_delay_req PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a PTP Delay Request message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_allocate Allocate a packet */ +/* nxd_udp_socket_source_send Send a UDP packet */ +/* nx_packet_release Release a packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_send_delay_req(NX_PTP_CLIENT *client_ptr) +{ +NX_PACKET *packet_ptr; +UINT status = NX_NOT_SUCCESSFUL; +UCHAR *ptr; +NXD_ADDRESS addr; +UINT addr_index = 0; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_IPV6_ADDRESS *ipv6_addr; +NX_IP *ip_ptr; +NX_INTERFACE *if_ptr; +#endif + + NX_PTP_DEBUG_PRINTF(("PTP: send DELAY_REQ\r\n")); + + /* allocate a packet from the pool */ + status = nx_packet_allocate(client_ptr -> nx_ptp_client_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_NO_WAIT); + if (status != NX_SUCCESS) + { + /* Failed to allocate the packet */ + return; + } + + /* start of message */ + ptr = packet_ptr -> nx_packet_prepend_ptr; + +#define PTP_MSG_DELAY_REQ_TOTAL_LEN (NX_PTP_MSG_HDR_LEN + NX_PTP_MSG_TIMESTAMP_LEN) +#define PTP_MSG_DELAY_REQ_ZERO1_LEN (1 + 2 + 8 + 4) + + /* write header */ + *ptr++ = NX_PTP_MSG_TYPE_DELAY_REQ; + *ptr++ = NX_PTP_VERSION; + *ptr++ = PTP_MSG_DELAY_REQ_TOTAL_LEN >> 8; + *ptr++ = (UCHAR)PTP_MSG_DELAY_REQ_TOTAL_LEN; + *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_transport_specific << 4) | client_ptr -> nx_ptp_client_domain; + memset(ptr, 0, PTP_MSG_DELAY_REQ_ZERO1_LEN); /* reserved/flags/correction/reserved */ + ptr += PTP_MSG_DELAY_REQ_ZERO1_LEN; + memcpy(ptr, client_ptr -> nx_ptp_client_port_identity, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + ptr += NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + client_ptr -> nx_ptp_client_delay_req_id++; + *ptr++ = (UCHAR)(client_ptr -> nx_ptp_client_delay_req_id >> 8); + *ptr++ = (UCHAR)client_ptr -> nx_ptp_client_delay_req_id; + *ptr++ = 0; /* control */ + *ptr++ = 0; /* XXX */ + + /* write timestamp (0) */ + memset(ptr, 0, NX_PTP_MSG_TIMESTAMP_LEN); + ptr += NX_PTP_MSG_TIMESTAMP_LEN; + + /* set final length of message */ + packet_ptr -> nx_packet_length = (ULONG)(ptr - packet_ptr -> nx_packet_prepend_ptr); + packet_ptr -> nx_packet_append_ptr = ptr; + + /* set source and destination addresses */ +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (client_ptr -> nx_ptp_client_master_addr.nxd_ip_version == NX_IP_VERSION_V6) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&addr); + + /* Use first IPv6 address as source address. */ + ip_ptr = client_ptr -> nx_ptp_client_ip_ptr; + if_ptr = &ip_ptr -> nx_ip_interface[client_ptr -> nx_ptp_client_interface_index]; + ipv6_addr = if_ptr -> nxd_interface_ipv6_address_list_head; + if (ipv6_addr == NX_NULL) + { + + /* No available IPv6 address. */ + /* Release packet. */ + nx_packet_release(packet_ptr); + + /* Reset state. */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL; + + return; + } + addr_index = ipv6_addr -> nxd_ipv6_address_index; + } + else +#endif + { +#ifndef NX_DISABLE_IPV4 + addr.nxd_ip_version = NX_IP_VERSION_V4; + addr.nxd_ip_address.v4 = NX_PTP_IPV4_MULTICAST_ADDR; + addr_index = client_ptr -> nx_ptp_client_interface_index; +#endif + } + + /* Prepare timestamp for current packet */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_REQ_TS; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = packet_ptr; + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE, + &client_ptr -> nx_ptp_client_delay_ts, packet_ptr, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* Send delay request */ + status = nxd_udp_socket_source_send((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket, + packet_ptr, &addr, NX_PTP_EVENT_UDP_PORT, addr_index); + if (status) + { + + /* release packet in case of error */ + nx_packet_release(packet_ptr); + + /* reset state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_packet_ptr = NX_NULL; + + return; + } + + /* rearm delay req timer */ + client_ptr -> nx_ptp_client_delay_req_timer = NX_PTP_CLIENT_DELAY_REQ_INTERVAL; + client_ptr -> nx_ptp_client_delay_req_flag = 0; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_sync_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Sync message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ts_ptr Pointer to the timestamp */ +/* delivered by the Sync message*/ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_msg_parse_timestamp Parse timestamp field */ +/* _nx_ptp_client_send_delay_req Send delay request */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_sync_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr) +{ + NX_PTP_DEBUG_PRINTF(("PTP: rcv SYNC\r\n")); + + /* store Sync master timestamp */ + _nx_ptp_msg_parse_timestamp(ts_ptr, &client_ptr -> nx_ptp_client_sync); + + /* delay and offset determination */ + if (client_ptr -> nx_ptp_client_delay_req_flag) + { + + /* send delay request message */ + /* (delay_req_flag is cleared by this function) */ + _nx_ptp_client_send_delay_req(client_ptr); + } + + /* update Sync state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_delay_resp_received PORTABLE C */ +/* 6.1.5 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Delay Response message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ts_ptr Pointer to the timestamp */ +/* delivered by the Delay Resp */ +/* message */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_msg_parse_timestamp Parse timestamp field */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_delay_resp_received(NX_PTP_CLIENT *client_ptr, VOID *ts_ptr) +{ +NX_PTP_TIME t4, a, b; +NX_PTP_CLIENT_SYNC sync; + + NX_PTP_DEBUG_PRINTF(("PTP: rcv DELAY_RESP\r\n")); + + /* + * The following timestamps are used for delay/offset determination: + * + * t1 = nx_ptp_client_sync + * t2 = nx_ptp_client_sync_ts + * t3 = nx_ptp_client_delay_ts + * t4 = timestamp in Delay_Resp message (ts_ptr) + * + * A = t2 - t1 + * B = t4 - t3 + * + * delay = (A + B) / 2 + * offset = (B - A) / 2 + */ + + /* check for valid timestamp t1 */ + if ((client_ptr -> nx_ptp_client_sync.second_low == 0) && + (client_ptr -> nx_ptp_client_sync.second_high == 0)) + { + return; + } + + /* get master clock timestamp */ + _nx_ptp_msg_parse_timestamp(ts_ptr, &t4); + + /* compute A = t2 - t1 */ + _nx_ptp_client_utility_time_diff(&client_ptr -> nx_ptp_client_sync_ts, &client_ptr -> nx_ptp_client_sync, &a); + + /* compute B = t4 - t3 */ + _nx_ptp_client_utility_time_diff(&t4, &client_ptr -> nx_ptp_client_delay_ts, &b); + + /* compute offset = (B - A) / 2 */ + _nx_ptp_client_utility_time_diff(&b, &a, &a); + _nx_ptp_client_utility_time_div_by_2(&a); + +#if defined(NX_PTP_DEBUG) || defined(NX_PTP_DEBUG_OFFSET) + if ((a.second_low == 0) && (a.second_high == 0)) + { + if ((a.nanosecond > -1000) && (a.nanosecond < 1000)) + { + printf("PTP: offset = %ld ns\n", a.nanosecond); + } + else if ((a.nanosecond > -1000000) && (a.nanosecond < 1000000)) + { + printf("PTP: offset = %ld us\n", a.nanosecond / 1000); + } + else + { + printf("PTP: offset = %ld ms\n", a.nanosecond / 1000000); + } + } + else + { + printf("PTP: offset > 1s\n"); + } +#endif + + /* add the time offset the client clock */ + _nx_ptp_client_clock_adjust(client_ptr, &a); + + /* set calibrated flag */ + if (!(client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED)) + { + + client_ptr -> nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_CALIBRATED; + + /* application callback */ + if (client_ptr -> nx_ptp_client_event_callback) + { + sync.nx_ptp_client_sync_flags = client_ptr -> nx_ptp_client_sync_flags; + sync.nx_ptp_client_sync_utc_offset = client_ptr -> nx_ptp_client_utc_offset; + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + + /* update delay req state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_announce_received PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes a received PTP Announce message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* hdr Pointer to PTP header */ +/* ptr Pointer to PTP message */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_msg_parse_announce Parse Announce message */ +/* memcpy Copy memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_announce_received(NX_PTP_CLIENT *client_ptr, + NX_PTP_MSG_HEADER *hdr, + UCHAR *ptr) +{ +NX_PTP_CLIENT_SYNC sync; +NX_PTP_CLIENT_MASTER master; + + /* parse Sync information */ + sync.nx_ptp_client_sync_flags = 0; + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_UTC_REASONABLE) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_UTC_REASONABLE; + } + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP59) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP59; + } + if (hdr -> flagField & NX_PTP_MSG_HDR_FLAG_LEAP61) + { + sync.nx_ptp_client_sync_flags |= NX_PTP_CLIENT_SYNC_LEAP61; + } + sync.nx_ptp_client_sync_utc_offset = NX_PTP_MSG_UTC_OFFSET(ptr); + + /* check for new master */ + if (client_ptr -> nx_ptp_client_state == NX_PTP_CLIENT_STATE_LISTENING) + { + + /* first announce message, save master clock parameters */ + client_ptr -> nx_ptp_client_sync_flags = sync.nx_ptp_client_sync_flags; + client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset; + memcpy(client_ptr -> nx_ptp_client_master_port_identity, hdr -> sourcePortIdentity, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + + /* wait for Sync message */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_SYNC; + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_IDLE; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_delay_req_flag = 1; + + + /* call application callback */ + if (client_ptr -> nx_ptp_client_event_callback) + { + + /* parse annouce message */ + _nx_ptp_msg_parse_announce(ptr, &master); + master.nx_ptp_client_master_address = &(client_ptr -> nx_ptp_client_master_addr); + master.nx_ptp_client_master_port_identity = hdr -> sourcePortIdentity; + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_MASTER, &master, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + else + { + + /* check for UTC offset update or flags changes */ + if (((client_ptr -> nx_ptp_client_sync_flags & ~NX_PTP_CLIENT_SYNC_CALIBRATED) != + sync.nx_ptp_client_sync_flags) || + (client_ptr -> nx_ptp_client_utc_offset != sync.nx_ptp_client_sync_utc_offset)) + { + client_ptr -> nx_ptp_client_sync_flags = + (USHORT)((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) | + sync.nx_ptp_client_sync_flags); + client_ptr -> nx_ptp_client_utc_offset = sync.nx_ptp_client_sync_utc_offset; + + /* call application callback */ + if ((client_ptr -> nx_ptp_client_sync_flags & NX_PTP_CLIENT_SYNC_CALIBRATED) && + (client_ptr -> nx_ptp_client_event_callback)) + { + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_SYNC, &sync, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + } + + /* reset annouce timer */ + client_ptr -> nx_ptp_client_announce_timeout = NX_PTP_CLIENT_ANNOUNCE_EXPIRATION; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_process_event_packet PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes PTP packet received through event socket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_msg_parse_hdr Parse PTP header */ +/* memcmp Compare memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_thread_entry PTP thread entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_process_event_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ +NX_PTP_MSG_HEADER hdr; + + /* parse PTP message header */ + if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr)) + { + return; + } + + /* check origin of message */ + if (memcmp(&client_ptr -> nx_ptp_client_master_port_identity, + hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0) + { + + /* not from our master clock */ + return; + } + + if (hdr.messageType != NX_PTP_MSG_TYPE_SYNC) + { + return; + } + + if (((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_SYNC) && + (client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP)) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_SYNC_LEN)) + { + + /* not waiting for Sync or invalid message */ + return; + } + + /* retrieve timestamp of event message */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT, + &client_ptr -> nx_ptp_client_sync_ts, packet_ptr, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* two-step message? */ + if (hdr.flagField & NX_PTP_MSG_HDR_FLAG_TWO_STEP) + { + + /* wait for follow up message */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP; + client_ptr -> nx_ptp_client_sync_id = hdr.sequenceId; + } + else + { + + /* process Sync event */ + _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_process_general_packet PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes PTP packet received through general socket. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_received Process Sync message */ +/* _nx_ptp_msg_parse_hdr Parse PTP header */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* _nx_ptp_client_announce_received Process Announce message */ +/* memcmp Compare memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_thread_entry PTP thread entry */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_process_general_packet(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ +NX_PTP_MSG_HEADER hdr; + + /* parse PTP message header */ + if (_nx_ptp_msg_parse_hdr(client_ptr, packet_ptr, &hdr)) + { + return; + } + + /* check origin of message */ + if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_LISTENING) && + (memcmp(&client_ptr -> nx_ptp_client_master_port_identity, + hdr.sourcePortIdentity, NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)) + { + + /* not from our master clock */ + return; + } + + /* process ANNOUNCE message */ + if (hdr.messageType == NX_PTP_MSG_TYPE_ANNOUNCE) + { + if (packet_ptr -> nx_packet_length < NX_PTP_MSG_ANNOUNCE_LEN) + { + + /* invalid message */ + return; + } + + /* process announce message */ + _nx_ptp_client_announce_received(client_ptr, &hdr, packet_ptr -> nx_packet_prepend_ptr); + } + else if (hdr.messageType == NX_PTP_MSG_TYPE_FOLLOW_UP) + { + if ((client_ptr -> nx_ptp_client_state != NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP) || + (client_ptr -> nx_ptp_client_sync_id != hdr.sequenceId) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_FOLLOW_UP_LEN)) + { + + /* not a follow up for a previous Sync or invalid message */ + return; + } + + /* process Sync message */ + _nx_ptp_client_sync_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } + else if (hdr.messageType == NX_PTP_MSG_TYPE_DELAY_RESP) + { + if ((client_ptr -> nx_ptp_client_delay_state != NX_PTP_CLIENT_DELAY_WAIT_RESP) || + (client_ptr -> nx_ptp_client_delay_req_id != hdr.sequenceId) || + (packet_ptr -> nx_packet_length < NX_PTP_MSG_DELAY_RESP_LEN) || + (memcmp(client_ptr -> nx_ptp_client_port_identity, + packet_ptr -> nx_packet_prepend_ptr + NX_PTP_MSG_TIMESTAMP_LEN, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE) != 0)) + { + + /* not a delay_resp for a previous delay_req or invalid message */ + return; + } + + /* process delay response message */ + _nx_ptp_client_delay_resp_received(client_ptr, packet_ptr -> nx_packet_prepend_ptr); + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_thread_entry PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements the PTP client processing thread. */ +/* */ +/* INPUT */ +/* */ +/* ptp_instance Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_process_general_packet Process PTP general packet */ +/* _nx_ptp_client_process_event_packet Process PTP event packet */ +/* tx_event_flags_get Get PTP events */ +/* nx_udp_socket_receive Receive a UDP packet */ +/* nx_packet_release Release a packet */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +static VOID _nx_ptp_client_thread_entry(ULONG ptp_instance) +{ +TX_INTERRUPT_SAVE_AREA +NX_PTP_CLIENT *client_ptr = (NX_PTP_CLIENT *)ptp_instance; +ULONG ptp_events; +UINT status; +NX_PACKET *packet_ptr = NX_NULL; +UCHAR packet_received; + + /* start in listening state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_announce_timeout = -1; + + /* main loop */ + for (;;) + { + + /* wait for message */ + status = tx_event_flags_get(&(client_ptr -> nx_ptp_client_events), + NX_PTP_CLIENT_ALL_EVENTS, TX_OR_CLEAR, + &ptp_events, TX_WAIT_FOREVER); + if (status != TX_SUCCESS) + { + + /* error while reading queue, abort thread */ + break; + } + + if (ptp_events & NX_PTP_CLIENT_STOP_EVENT) + { + + /* terminate thread */ + break; + } + + /* + * PTP Message Received + */ + if (ptp_events & NX_PTP_CLIENT_RX_EVENT) + { + + /* Loop to receive all packets. */ + for (;;) + { + packet_received = NX_FALSE; + if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_general_socket), + &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + _nx_ptp_client_process_general_packet(client_ptr, packet_ptr); + + /* Release packet. */ + nx_packet_release(packet_ptr); + packet_received = NX_TRUE; + } + + if (nx_udp_socket_receive(&(client_ptr -> nx_ptp_client_event_socket), + &packet_ptr, NX_NO_WAIT) == NX_SUCCESS) + { + _nx_ptp_client_process_event_packet(client_ptr, packet_ptr); + + /* Release packet. */ + nx_packet_release(packet_ptr); + packet_received = NX_TRUE; + } + + if (packet_received == NX_FALSE) + { + + /* No more packets available. */ + break; + } + } + } + + /* + * Timer Event + */ + if (ptp_events & NX_PTP_CLIENT_TIMER_EVENT) + { + + /* announce messages timeout */ + if ((client_ptr -> nx_ptp_client_announce_timeout > 0) && + (--client_ptr -> nx_ptp_client_announce_timeout == 0)) + { + + /* no Annouce message received from master clock, back to listening state */ + client_ptr -> nx_ptp_client_state = NX_PTP_CLIENT_STATE_LISTENING; + client_ptr -> nx_ptp_client_delay_req_timer = -1; + client_ptr -> nx_ptp_client_announce_timeout = -1; + + /* call handler */ + if (client_ptr -> nx_ptp_client_event_callback) + { + client_ptr -> nx_ptp_client_event_callback(client_ptr, NX_PTP_CLIENT_EVENT_TIMEOUT, NX_NULL, + client_ptr -> nx_ptp_client_event_callback_data); + } + } + + /* delay req interval timer */ + if ((client_ptr -> nx_ptp_client_delay_req_timer > 0) && + (--client_ptr -> nx_ptp_client_delay_req_timer == 0)) + { + + /* set flag */ + client_ptr -> nx_ptp_client_delay_req_flag = 1; + } + } + } + + /* set stopped state */ + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPED; + TX_RESTORE +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client create service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ip_ptr Pointer to client IP instance */ +/* interface_index Index of PTP network interface*/ +/* packet_pool_ptr Pointer to client packet pool */ +/* thread_priority Priority of PTP thread */ +/* thread_stack Pointer to thread stack */ +/* stack_size Size of thread stack */ +/* clock_callback PTP clock callback */ +/* clock_callback_data Data for the clock callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_create Actual create service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (ip_ptr == NX_NULL) || (packet_pool_ptr == NX_NULL) || + (thread_stack == NX_NULL) || (stack_size == 0) || (clock_callback == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for invalid network interface input. */ + if (interface_index >= NX_MAX_PHYSICAL_INTERFACES) + { + return(NX_INVALID_INTERFACE); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return _nx_ptp_client_create(client_ptr, ip_ptr, interface_index, packet_pool_ptr, thread_priority, + thread_stack, stack_size, clock_callback, clock_callback_data); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_create PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* ip_ptr Pointer to client IP instance */ +/* interface_index Index of PTP network interface*/ +/* packet_pool_ptr Pointer to client packet pool */ +/* thread_priority Priority of PTP thread */ +/* thread_stack Pointer to thread stack */ +/* stack_size Size of thread stack */ +/* clock_callback PTP clock callback */ +/* clock_callback_data Data for the clock callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* memset Reset memory */ +/* [clock_callback] Initialize clock */ +/* tx_event_flags_create Create PTP event flags */ +/* tx_event_flags_delete Delete PTP event flags */ +/* nx_udp_socket_create Create a UDP socket */ +/* nx_udp_socket_delete Delete a UDP socket */ +/* nx_udp_socket_receive_notify Set UDP receive notify */ +/* tx_timer_create Create a timer */ +/* tx_timer_delete Delete a timer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data) +{ +UINT status; + + /* Null the members of NX_PTP_CLIENT. */ + memset(client_ptr, 0, sizeof(NX_PTP_CLIENT)); + + /* Set the Client ID to indicate the PTP client thread is ready. */ + client_ptr -> nx_ptp_client_id = NX_PTP_CLIENT_ID; + + /* Set the IP instance. */ + client_ptr -> nx_ptp_client_ip_ptr = ip_ptr; + + /* Set the PTP network interface. */ + client_ptr -> nx_ptp_client_interface_index = interface_index; + + /* Set the packet pool, check for minimal packet size requirement. */ + if (packet_pool_ptr -> nx_packet_pool_payload_size < + (NX_UDP_PACKET + NX_PTP_CLIENT_PACKET_DATA_SIZE)) + { + return(NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD); + } + client_ptr -> nx_ptp_client_packet_pool_ptr = packet_pool_ptr; + + /* Initialize callback function. */ + status = clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_INIT, NX_NULL, NX_NULL, clock_callback_data); + if (status) + { + + /* Fail to initialize clock in callback function. */ + return(NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE); + } + + /* Set the PTP clock callback */ + client_ptr -> nx_ptp_client_clock_callback = clock_callback; + client_ptr -> nx_ptp_client_clock_callback_data = clock_callback_data; + + /* create the internal PTP event flag object. */ + status = tx_event_flags_create(&(client_ptr -> nx_ptp_client_events), "NetX PTP event flag"); + if (status != TX_SUCCESS) + { + return(status); + } + + /* create the general socket */ + status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_general_socket, + "NetX PTP Client general socket", NX_IP_NORMAL, + NX_DONT_FRAGMENT, NX_PTP_TIME_TO_LIVE, + NX_PTP_CLIENT_MAX_QUEUE_DEPTH); + if (status != NX_SUCCESS) + { + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + client_ptr -> nx_ptp_client_general_socket.nx_udp_socket_reserved_ptr = client_ptr; + nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_general_socket, _nx_ptp_client_socket_receive_notify); + + /* create the event socket */ + status = nx_udp_socket_create(ip_ptr, &client_ptr -> nx_ptp_client_event_socket, + "NetX PTP Client event socket", NX_IP_NORMAL, NX_DONT_FRAGMENT, + NX_PTP_TIME_TO_LIVE, + NX_PTP_CLIENT_MAX_QUEUE_DEPTH); + if (status != NX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + client_ptr -> nx_ptp_client_event_socket.nx_udp_socket_reserved_ptr = client_ptr; + nx_udp_socket_receive_notify(&client_ptr -> nx_ptp_client_event_socket, _nx_ptp_client_socket_receive_notify); + + /* create the timer */ + status = tx_timer_create(&client_ptr -> nx_ptp_client_timer, + "NetX PTP Client timer", + _nx_ptp_client_timer_handler, + (ULONG)client_ptr, + TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND, + TX_TIMER_TICKS_PER_SECOND / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND, + TX_NO_ACTIVATE); + if (status != TX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + + /* create the Client thread */ + status = tx_thread_create(&client_ptr -> nx_ptp_client_thread, + "NetX PTP Client", _nx_ptp_client_thread_entry, + (ULONG)client_ptr, thread_stack, stack_size, + thread_priority, thread_priority, + NX_PTP_CLIENT_THREAD_TIME_SLICE, TX_DONT_START); + if (status != TX_SUCCESS) + { + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_delete(&client_ptr -> nx_ptp_client_event_socket); + tx_timer_delete(&client_ptr -> nx_ptp_client_timer); + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + return(status); + } + + /* return Success */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client delete service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_delete Actual delete service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr) +{ + + /* Check input parameters. */ + if (client_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_delete(client_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_delete PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_stop Stop PTP service */ +/* tx_thread_suspend Suspend PTP thread */ +/* tx_thread_terminate Terminate PTP thread */ +/* tx_thread_delete Delete PTP thread */ +/* tx_event_flags_delete Delete PTP event flags */ +/* nx_udp_socket_delete Delete a UDP socket */ +/* tx_timer_delete Delete a timer */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr) +{ + + /* Ensure the Client is stopped */ + _nx_ptp_client_stop(client_ptr); + + /* Suspend the Client thread. */ + tx_thread_suspend(&client_ptr -> nx_ptp_client_thread); + + /* Terminate Client thread. */ + tx_thread_terminate(&client_ptr -> nx_ptp_client_thread); + + /* Delete Client thread. */ + tx_thread_delete(&client_ptr -> nx_ptp_client_thread); + + /* Delete the timer */ + tx_timer_delete(&client_ptr -> nx_ptp_client_timer); + + /* Delete the general socket */ + nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket); + + /* Delete the event socket */ + nx_udp_socket_delete((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket); + + /* Delete the event flag */ + tx_event_flags_delete(&client_ptr -> nx_ptp_client_events); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_start PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client start service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* client_port_identity_ptr Pointer to client port and */ +/* identity */ +/* client_port_identity_length Length of client port and */ +/* identity */ +/* domain PTP clock domain */ +/* transport_specific Transport specific */ +/* event_callback Event callback */ +/* event_callback_data Data for the event callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_start Actual start service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || + ((client_port_identity_ptr == NX_NULL) && (client_port_identity_length != 0)) || + ((client_port_identity_ptr != NX_NULL) && (client_port_identity_length != NX_PTP_CLOCK_PORT_IDENTITY_SIZE))) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_start(client_ptr, client_port_identity_ptr, client_port_identity_length, + domain, transport_specific, event_callback, event_callback_data)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_start PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function starts the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* client_port_identity_ptr Pointer to client port and */ +/* identity */ +/* client_port_identity_length Length of client port and */ +/* identity */ +/* domain PTP clock domain */ +/* transport_specific Transport specific */ +/* event_callback Event callback */ +/* event_callback_data Data for the event callback */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_thread_suspend Suspend PTP thread */ +/* tx_thread_terminate Terminate PTP thread */ +/* tx_thread_reset Reset PTP thread */ +/* tx_thread_resume Resume PTP thread */ +/* memcpy Copy memory */ +/* nx_ip_interface_physical_address_get Get physical address */ +/* nx_udp_socket_bind Bind UDP port */ +/* nx_ipv4_multicast_interface_join Join IPv4 multicast group */ +/* nxd_ipv6_multicast_interface_join Join IPv6 multicast group */ +/* tx_timer_activate Activate timer */ +/* _nx_ptp_client_stop Stop PTP service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; +UINT status; +ULONG msw, lsw; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_ADDRESS maddr; +#endif + + NX_PARAMETER_NOT_USED(client_port_identity_length); + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + if (state == NX_PTP_CLIENT_THREAD_IDLE) + { + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_RUNNING; + } + TX_RESTORE + if (state != NX_PTP_CLIENT_THREAD_IDLE) + { + + /* Client is already running */ + return(NX_PTP_CLIENT_ALREADY_STARTED); + } + + /* ensure the thread is terminated */ + tx_thread_suspend(&client_ptr -> nx_ptp_client_thread); + tx_thread_terminate(&client_ptr -> nx_ptp_client_thread); + + /* save the client parameters */ + client_ptr -> nx_ptp_client_domain = (UCHAR)domain; + client_ptr -> nx_ptp_client_transport_specific = (UCHAR)transport_specific; + client_ptr -> nx_ptp_client_event_callback = event_callback; + client_ptr -> nx_ptp_client_event_callback_data = event_callback_data; + + /* reset and resume the thread */ + status = tx_thread_reset(&client_ptr -> nx_ptp_client_thread); + if (status != TX_SUCCESS) + { + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE; + TX_RESTORE + + return(status); + } + tx_thread_resume(&client_ptr -> nx_ptp_client_thread); + + /* set the client port and identity */ + if (client_port_identity_ptr != NX_NULL) + { + + /* copy provided identifier */ + memcpy(client_ptr -> nx_ptp_client_port_identity, client_port_identity_ptr, + NX_PTP_CLOCK_PORT_IDENTITY_SIZE); /* use case of memcpy is verified. */ + } + else + { + + /* get MAC address of interface */ + status = nx_ip_interface_physical_address_get(client_ptr -> nx_ptp_client_ip_ptr, + client_ptr -> nx_ptp_client_interface_index, + &msw, &lsw); + if (status == TX_SUCCESS) + { + /* convert 48-bit MAC address to 64-bit EUI */ + client_ptr -> nx_ptp_client_port_identity[0] = (UCHAR)(msw >> 8); + client_ptr -> nx_ptp_client_port_identity[1] = (UCHAR)msw; + client_ptr -> nx_ptp_client_port_identity[2] = (UCHAR)(lsw >> 24); + client_ptr -> nx_ptp_client_port_identity[3] = 0xff; + client_ptr -> nx_ptp_client_port_identity[4] = 0xfe; + client_ptr -> nx_ptp_client_port_identity[5] = (UCHAR)(lsw >> 16); + client_ptr -> nx_ptp_client_port_identity[6] = (UCHAR)(lsw >> 8); + client_ptr -> nx_ptp_client_port_identity[7] = (UCHAR)lsw; + + /* set default port number (1) */ + client_ptr -> nx_ptp_client_port_identity[8] = 0; + client_ptr -> nx_ptp_client_port_identity[9] = 1; + } + } + + /* bind the general socket */ + if (status == TX_SUCCESS) + { + status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket, + NX_PTP_GENERAL_UDP_PORT, NX_NO_WAIT); + } + + /* bind the event socket */ + if (status == TX_SUCCESS) + { + status = nx_udp_socket_bind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket, + NX_PTP_EVENT_UDP_PORT, NX_NO_WAIT); + } + + /* join the multicast groups */ + if (status == TX_SUCCESS) + { + status = nx_ipv4_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr, + NX_PTP_IPV4_MULTICAST_ADDR, + client_ptr -> nx_ptp_client_interface_index); + if (status == TX_SUCCESS) + { + client_ptr -> nx_ptp_client_ipv4_group_joined = NX_TRUE; + } + } +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (status == TX_SUCCESS) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr); + status = nxd_ipv6_multicast_interface_join(client_ptr -> nx_ptp_client_ip_ptr, + &maddr, client_ptr -> nx_ptp_client_interface_index); + if (status == TX_SUCCESS) + { + client_ptr -> nx_ptp_client_ipv6_group_joined = NX_TRUE; + } + else if ((status == NX_NOT_SUPPORTED) && (client_ptr -> nx_ptp_client_ipv4_group_joined)) + { + + /* IPv6 not enabled, use IPv4 only */ + status = TX_SUCCESS; + } + } +#endif + + /* activate the Client timer */ + if (status == TX_SUCCESS) + { + + /* activate the timer */ + status = tx_timer_activate(&client_ptr -> nx_ptp_client_timer); + } + + /* stop the client thread in case of error */ + if (status != TX_SUCCESS) + { + _nx_ptp_client_stop(client_ptr); + + /* return failure */ + return(status); + } + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_stop PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP client stop service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_stop Actual stop service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr) +{ + + /* Check input parameters. */ + if (client_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_stop(client_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_stop PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function stops the PTP client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_timer_deactivate Deactivate timer */ +/* nx_udp_socket_unbind Unbind UDP port */ +/* nx_ipv4_multicast_interface_leave Leave IPv4 multicast group */ +/* nxd_ipv6_multicast_interface_leave Leave IPv6 multicast group */ +/* tx_event_flags_set Set PTP timer event */ +/* tx_thread_sleep Thread sleep */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) +NXD_ADDRESS maddr; +#endif + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + if (state == NX_PTP_CLIENT_THREAD_RUNNING) + { + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_STOPPING; + } + TX_RESTORE + if ((state != NX_PTP_CLIENT_THREAD_RUNNING) && + (state != NX_PTP_CLIENT_THREAD_STOPPED)) + { + + /* Client is not running */ + return(NX_PTP_CLIENT_NOT_STARTED); + } + + /* deactivate the timer */ + tx_timer_deactivate(&client_ptr -> nx_ptp_client_timer); + + /* unbind the sockets */ + nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_general_socket); + nx_udp_socket_unbind((NX_UDP_SOCKET *)&client_ptr -> nx_ptp_client_event_socket); + + /* leave multicast groups */ + if (client_ptr -> nx_ptp_client_ipv4_group_joined) + { + nx_ipv4_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr, + NX_PTP_IPV4_MULTICAST_ADDR, + client_ptr -> nx_ptp_client_interface_index); + client_ptr -> nx_ptp_client_ipv4_group_joined = NX_FALSE; + } +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + if (client_ptr -> nx_ptp_client_ipv6_group_joined) + { + NX_PTP_IPV6_MULTICAST_ADDR_SET(&maddr); + nxd_ipv6_multicast_interface_leave(client_ptr -> nx_ptp_client_ip_ptr, + &maddr, client_ptr -> nx_ptp_client_interface_index); + client_ptr -> nx_ptp_client_ipv6_group_joined = NX_FALSE; + } +#endif + + /* send STOP message */ + tx_event_flags_set(&(client_ptr -> nx_ptp_client_events), NX_PTP_CLIENT_STOP_EVENT, TX_OR); + + /* wait for thread termination */ + while (state != NX_PTP_CLIENT_THREAD_STOPPED) + { + tx_thread_sleep(1); + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + TX_RESTORE + } + + /* set Idle state */ + TX_DISABLE + client_ptr -> nx_ptp_client_thread_state = NX_PTP_CLIENT_THREAD_IDLE; + TX_RESTORE + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_time_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time get service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_time_get Actual time get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_time_get(client_ptr, time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_time_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets the current value of the PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Get the current PTP clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_GET, + time_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_time_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time set service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_time_set Actual time set service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ + + /* Check input parameters. */ + if ((client_ptr == NX_NULL) || (time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_time_set(client_ptr, time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_time_set PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the initial time of the PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT state; + + /* Check if Client is running */ + TX_DISABLE + state = client_ptr -> nx_ptp_client_thread_state; + TX_RESTORE + + if (state != NX_PTP_CLIENT_THREAD_IDLE) + { + + /* Cannot set the clock when the client is running */ + return(NX_PTP_CLIENT_ALREADY_STARTED); + } + + /* Set the current PTP clock */ + client_ptr -> nx_ptp_client_clock_callback(client_ptr, NX_PTP_CLIENT_CLOCK_SET, + time_ptr, NX_NULL, + client_ptr -> nx_ptp_client_clock_callback_data); + + /* return Success */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_master_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP master info get service. */ +/* */ +/* INPUT */ +/* */ +/* master_ptr Pointer to PTP master clock */ +/* address Address of master clock */ +/* port_identity PTP master port and identity */ +/* port_identity_length Length of PTP master port and */ +/* identity */ +/* priority1 Priority1 of PTP master clock */ +/* priority2 Priority2 of PTP master clock */ +/* clock_class Class of PTP master clock */ +/* clock_accuracy Accuracy of PTP master clock */ +/* clock_variance Variance of PTP master clock */ +/* grandmaster_identity Identity of grandmaster clock */ +/* grandmaster_identity_length Length of grandmaster Identity*/ +/* steps_removed Steps removed from PTP header */ +/* time_source The source of timer used by */ +/* grandmaster clock */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_master_info_get Actual master info get service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source) +{ + if (master_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + return(_nx_ptp_client_master_info_get(master_ptr, address, port_identity, port_identity_length, priority1, + priority2, clock_class, clock_accuracy, clock_variance, grandmaster_identity, + grandmaster_identity_length, steps_removed, time_source)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_master_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets information of master clock. */ +/* */ +/* INPUT */ +/* */ +/* master_ptr Pointer to PTP master clock */ +/* address Address of master clock */ +/* port_identity PTP master port and identity */ +/* port_identity_length Length of PTP master port and */ +/* identity */ +/* priority1 Priority1 of PTP master clock */ +/* priority2 Priority2 of PTP master clock */ +/* clock_class Class of PTP master clock */ +/* clock_accuracy Accuracy of PTP master clock */ +/* clock_variance Variance of PTP master clock */ +/* grandmaster_identity Identity of grandmaster clock */ +/* grandmaster_identity_length Length of grandmaster Identity*/ +/* steps_removed Steps removed from PTP header */ +/* time_source The source of timer used by */ +/* grandmaster clock */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source) +{ + + /* Set master information when the output pointer is provided. */ + if (address) + { + *address = *(master_ptr -> nx_ptp_client_master_address); + } + + if (port_identity && port_identity_length) + { + *port_identity = master_ptr -> nx_ptp_client_master_port_identity; + *port_identity_length = NX_PTP_CLOCK_PORT_IDENTITY_SIZE; + } + + if (priority1) + { + *priority1 = master_ptr -> nx_ptp_client_master_priority1; + } + + if (priority2) + { + *priority2 = master_ptr -> nx_ptp_client_master_priority2; + } + + if (clock_class) + { + *clock_class = master_ptr -> nx_ptp_client_master_clock_class; + } + + if (clock_accuracy) + { + *clock_accuracy = master_ptr -> nx_ptp_client_master_clock_accuracy; + } + + if (clock_variance) + { + *clock_variance = master_ptr -> nx_ptp_client_master_offset_scaled_log_variance; + } + + if (grandmaster_identity && grandmaster_identity_length) + { + *grandmaster_identity = master_ptr -> nx_ptp_client_master_grandmaster_identity; + *grandmaster_identity_length = NX_PTP_CLOCK_IDENTITY_SIZE; + } + + if (steps_removed) + { + *steps_removed = master_ptr -> nx_ptp_client_master_steps_removed; + } + + if (time_source) + { + *time_source = master_ptr -> nx_ptp_client_master_time_source; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_sync_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP Sync get service. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* flags Flags in Sync message */ +/* utc_offset Offset between TAI and UTC */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_sync_info_get Actual Sync info get service */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset) +{ + if (sync_ptr == NX_NULL) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + return(_nx_ptp_client_sync_info_get(sync_ptr, flags, utc_offset)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_sync_info_get PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function gets information of Sync message. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* flags Flags in Sync message */ +/* utc_offset Offset between TAI and UTC */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset) +{ + + /* Set SYNC information when the output pointer is provided. */ + if (flags) + { + *flags = sync_ptr -> nx_ptp_client_sync_flags; + } + + if (utc_offset) + { + *utc_offset = sync_ptr -> nx_ptp_client_sync_utc_offset; + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_packet_timestamp_notify PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function notifies the PTP packet is transmitted with timestamp.*/ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* packet_ptr Pointer to PTP packet */ +/* timestamp_ptr Pointer to timestamp */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr) +{ + + /* get timestamp of previous delay_req message */ + if (client_ptr && + (client_ptr -> nx_ptp_client_delay_state == NX_PTP_CLIENT_DELAY_WAIT_REQ_TS) && + (client_ptr -> nx_ptp_client_delay_req_packet_ptr == packet_ptr)) + { + + /* store timestamp */ + client_ptr -> nx_ptp_client_delay_ts = *timestamp_ptr; + + /* update state */ + client_ptr -> nx_ptp_client_delay_state = NX_PTP_CLIENT_DELAY_WAIT_RESP; + } +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_soft_clock_callback PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function implements soft PTP clock. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to PTP client */ +/* operation PTP clock operation */ +/* time_ptr Pointer to timestamp */ +/* packet_ptr Pointer to PTP packet */ +/* callback_data Pointer to callback data */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* PTP internal */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data) +{ +TX_INTERRUPT_SAVE_AREA + + NX_PARAMETER_NOT_USED(callback_data); + + switch (operation) + { + + /* Nothing to do for soft initialization. */ + case NX_PTP_CLIENT_CLOCK_INIT: + break; + + /* Set clock. */ + case NX_PTP_CLIENT_CLOCK_SET: + TX_DISABLE + client_ptr -> nx_ptp_client_soft_clock = *time_ptr; + TX_RESTORE + break; + + /* Extract timestamp from packet. + For soft implementation, simply fallthrough and return current timestamp. */ + case NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT: + + /* Get clock. */ + case NX_PTP_CLIENT_CLOCK_GET: + TX_DISABLE + *time_ptr = client_ptr -> nx_ptp_client_soft_clock; + TX_RESTORE + break; + + /* Adjust clock. */ + case NX_PTP_CLIENT_CLOCK_ADJUST: + _nx_ptp_client_soft_clock_adjust(client_ptr, time_ptr -> nanosecond); + break; + + /* Prepare timestamp for current packet. + For soft implementation, simply notify current timestamp. */ + case NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE: + _nx_ptp_client_packet_timestamp_notify(client_ptr, packet_ptr, &(client_ptr -> nx_ptp_client_soft_clock)); + break; + + /* Update soft timer. */ + case NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE: + TX_DISABLE + + /* increment the nanosecond field of the software clock */ + time_ptr -> nanosecond += + (LONG)(NX_PTP_NANOSECONDS_PER_SEC / NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND); + + /* update the second field */ + if (time_ptr -> nanosecond >= NX_PTP_NANOSECONDS_PER_SEC) + { + time_ptr -> nanosecond -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&(time_ptr -> second_high), + &(time_ptr -> second_low)); + } + TX_RESTORE + break; + + default: + return(NX_PTP_PARAM_ERROR); + } + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_utility_time_diff PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time difference service. */ +/* */ +/* INPUT */ +/* */ +/* time1_ptr Pointer to first PTP time */ +/* time2_ptr Pointer to second PTP time */ +/* result_ptr Pointer to result time1-time2 */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_time_diff Actual time difference service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr) +{ + + /* Check input parameters. */ + if ((time1_ptr == NX_NULL) || (time2_ptr == NX_NULL) || (result_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_utility_time_diff(time1_ptr, time2_ptr, result_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_time_diff PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function computes the difference between two PTP times. */ +/* */ +/* INPUT */ +/* */ +/* time1_ptr Pointer to first PTP time */ +/* time2_ptr Pointer to second PTP time */ +/* result_ptr Pointer to result time1-time2 */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_sub64 Subtracts two 64-bit numbers */ +/* _nx_ptp_client_utility_dec64 Decrement a 64-bit number */ +/* _nx_ptp_client_utility_inc64 Increment a 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr) +{ +LONG sec_hi; +ULONG sec_lo; +LONG ns; + + /* compute difference of seconds */ + sec_hi = time1_ptr -> second_high; + sec_lo = time1_ptr -> second_low; + _nx_ptp_client_utility_sub64(&sec_hi, &sec_lo, time2_ptr -> second_high, + time2_ptr -> second_low); + + /* compute difference of nanoseconds */ + /* note: this cannot overflow as nanosecond field is in range +/-0-999999999 */ + ns = time1_ptr -> nanosecond - time2_ptr -> nanosecond; + + /* keep nanoseconds in range +/-0-999999999 */ + if (ns <= -NX_PTP_NANOSECONDS_PER_SEC) + { + ns += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo); + } + else if (ns >= NX_PTP_NANOSECONDS_PER_SEC) + { + ns -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo); + } + + /* ensure the nanoseconds field has same sign as seconds field */ + if ((sec_hi >= 0) && ((sec_hi != 0) || (sec_lo != 0))) + { + /* positive number of seconds */ + if (ns < 0) + { + ns += NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_dec64(&sec_hi, &sec_lo); + } + } + else if (sec_hi < 0) + { + /* negative number of seconds */ + if (ns > 0) + { + ns -= NX_PTP_NANOSECONDS_PER_SEC; + _nx_ptp_client_utility_inc64(&sec_hi, &sec_lo); + } + } + + /* return result time */ + result_ptr -> second_high = sec_hi; + result_ptr -> second_low = sec_lo; + result_ptr -> nanosecond = ns; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_ptp_client_utility_convert_time_to_date PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors on the PTP time conversion service. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* offset signed second offset to add */ +/* the PTP time */ +/* date_time_ptr Pointer to resulting date */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_convert_time_to_date */ +/* Actual time conversion service*/ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr) +{ + + /* Check input parameters. */ + if ((time_ptr == NX_NULL) || (date_time_ptr == NX_NULL)) + { + + /* Return error status. */ + return(NX_PTR_ERROR); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* Call the actual function. */ + return(_nx_ptp_client_utility_convert_time_to_date(time_ptr, offset, date_time_ptr)); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_convert_time_to_date PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts a PTP time to a UTC date and time. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* offset Signed second offset to add */ +/* the PTP time */ +/* date_time_ptr Pointer to resulting date */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_add64 Add two 64-bit number */ +/* */ +/* CALLED BY */ +/* */ +/* Application */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr) +{ +#define IS_LEAP(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0)) +#define SECS_PER_MINUTE 60 +#define SECS_PER_HOUR (60 * SECS_PER_MINUTE) +#define SECS_PER_DAY (24 * SECS_PER_HOUR) +LONG secs_high; +ULONG secs_low; +UINT year, month, day, hour, minute; +ULONG secs_per_year, secs_per_month; +ULONG weekday; +UINT is_leap; + + /* get number of seconds */ + secs_high = time_ptr -> second_high; + secs_low = time_ptr -> second_low; + + /* add local time offset */ + if (offset != 0) + { + _nx_ptp_client_utility_add64(&secs_high, &secs_low, offset < 0 ? -1 : 0, (ULONG)offset); + } + if (secs_high < 0) + { + + /* invalid negative time */ + return(NX_PTP_PARAM_ERROR); + } + + /* determine the current year from Epoch (January 1, 1970) */ + year = 1970; + secs_per_year = 365 * SECS_PER_DAY; + is_leap = 0; + weekday = 4; /* thursday */ + while ((secs_high > 0) || (secs_low >= secs_per_year)) + { + if (secs_low < secs_per_year) + { + secs_high--; + } + secs_low -= secs_per_year; + weekday += is_leap ? 366 : 365; + year++; + is_leap = IS_LEAP(year) ? 1 : 0; + secs_per_year = is_leap ? 366 * SECS_PER_DAY : 365 * SECS_PER_DAY; + } + /* compute day of the week from remaining seconds */ + weekday = (weekday + secs_low / SECS_PER_DAY) % 7; + + /* determine current month */ + month = 1; + secs_per_month = 31 * SECS_PER_DAY; + while (secs_low >= secs_per_month) + { + secs_low -= secs_per_month; + month++; + if (month == 2) + { + + /* february */ + secs_per_month = is_leap ? 29 * SECS_PER_DAY : 28 * SECS_PER_DAY; + } + else if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) + { + + /* april, june, september, november */ + secs_per_month = 30 * SECS_PER_DAY; + } + else + { + + /* the other months */ + secs_per_month = 31 * SECS_PER_DAY; + } + } + + /* determine current day of the month */ + day = secs_low / SECS_PER_DAY; + secs_low -= day * SECS_PER_DAY; + + /* determine current hour */ + hour = secs_low / SECS_PER_HOUR; + secs_low -= hour * SECS_PER_HOUR; + + /* determine current minute */ + minute = secs_low / SECS_PER_MINUTE; + secs_low -= minute * SECS_PER_MINUTE; + + /* return date */ + date_time_ptr -> year = year; + date_time_ptr -> month = (UCHAR)month; + date_time_ptr -> day = (UCHAR)(day + 1); + date_time_ptr -> hour = (UCHAR)hour; + date_time_ptr -> minute = (UCHAR)minute; + date_time_ptr -> second = (UCHAR)secs_low; + date_time_ptr -> weekday = (UCHAR)weekday; + date_time_ptr -> nanosecond = (ULONG)time_ptr -> nanosecond; + + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_add64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds two 64-bit numbers: A = A + B. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* b_hi higher 32-bit of B */ +/* b_lo lower 32-bit of B */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_convert_time_to_date */ +/* Convert time to date */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo) +{ +LONG r_hi; +ULONG r_lo; + + r_hi = *a_hi + b_hi; + r_lo = *a_lo + b_lo; + if (r_lo < *a_lo) + { + r_hi++; /* add carry */ + } + *a_hi = r_hi; + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_sub64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function substracts two 64-bit numbers: A = A - B. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* b_hi higher 32-bit of B */ +/* b_lo lower 32-bit of B */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo) +{ +LONG r_hi; +ULONG r_lo; + + r_hi = *a_hi - b_hi; + r_lo = *a_lo - b_lo; + if (*a_lo < b_lo) + { + r_hi--; /* substract carry */ + } + *a_hi = r_hi; + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_inc64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function increments a 64-bit number: A = A + 1. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* _nx_ptp_client_soft_clock_callback Soft PTP clock */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo) +{ +ULONG r_lo; + + r_lo = *a_lo + 1; + if (r_lo == 0) + { + *a_hi = *a_hi + 1; /* add carry */ + } + *a_lo = r_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_dec64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function decrements a 64-bit number: A = A - 1. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_soft_clock_adjust Adjust soft PTP clock */ +/* _nx_ptp_client_clock_adjust Adjust PTP clock */ +/* _nx_ptp_client_utility_time_diff Diff two PTP times */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo) +{ +ULONG r_lo; + + r_lo = *a_lo; + if (r_lo == 0) + { + *a_hi = *a_hi - 1; /* substract carry */ + } + *a_lo = r_lo - 1; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_neg64 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function changes the sign of a 64-bit number: A = -A. */ +/* */ +/* INPUT */ +/* */ +/* a_hi Pointer to higher 32-bit of A */ +/* a_lo Pointer to lower 32-bit of A */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_utility_time_div_by_2 Divide a PTP time by 2 */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo) +{ +LONG r_hi; + + r_hi = -*a_hi; + if (*a_lo != 0) + { + r_hi--; /* substract carry */ + } + *a_hi = r_hi; + *a_lo = -*a_lo; +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_ptp_client_utility_time_div_by_2 PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function divides a PTP time by 2. */ +/* */ +/* INPUT */ +/* */ +/* time_ptr Pointer to PTP time */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _nx_ptp_client_utility_neg64 Change the sign of number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_ptp_client_delay_resp_received Process delay response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr) +{ +UINT neg; +LONG sec_hi; +ULONG sec_lo; +LONG ns; + + /* get current time value */ + sec_hi = time_ptr -> second_high; + sec_lo = time_ptr -> second_low; + ns = time_ptr -> nanosecond; + + /* implement division on unsigned values */ + if ((sec_hi < 0) || (ns < 0)) + { + _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo); + ns = -ns; + neg = 1; + } + else + { + neg = 0; + } + + /* divide nanoseconds by two */ + ns >>= 1; + if (sec_lo & 1) + { + + /* add rest of seconds division */ + ns += 500000000L; + } + + /* divide seconds by two */ + sec_lo >>= 1; + if (sec_hi & 1) + { + sec_lo |= 0x80000000UL; + } + sec_hi >>= 1; + + /* restore sign */ + if (neg) + { + _nx_ptp_client_utility_neg64(&sec_hi, &sec_lo); + ns = -ns; + } + + /* return result */ + time_ptr -> second_high = sec_hi; + time_ptr -> second_low = sec_lo; + time_ptr -> nanosecond = ns; +} diff --git a/addons/ptp/nxd_ptp_client.h b/addons/ptp/nxd_ptp_client.h new file mode 100644 index 00000000..3524b860 --- /dev/null +++ b/addons/ptp/nxd_ptp_client.h @@ -0,0 +1,482 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX PTP Client Component */ +/** */ +/** Precision Time Protocol (PTP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nxd_ptp_client.h PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX Precision Time Protocol (PTP) */ +/* Client component, including all data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NXD_PTP_CLIENT_H +#define NXD_PTP_CLIENT_H + + +/* Include NetX and ThreadX definitions */ + +#include "nx_api.h" + + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + + +/* PTP Client configurable options. */ + + +/* Set the client thread time slice. */ + +#ifndef NX_PTP_CLIENT_THREAD_TIME_SLICE +#define NX_PTP_CLIENT_THREAD_TIME_SLICE TX_NO_TIME_SLICE +#endif + + +/* Define the PTP Client ID */ + +#define NX_PTP_CLIENT_ID 0x50545001UL + + +/* Define the PTP client internal timer frequency */ + +#ifndef NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND +#define NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND 10 +#endif + + +/* Define the maximum number of missing Announce packets before timeout */ + +#ifndef NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT +#define NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT 3 +#endif + + +/* Define the time interval between successive Announce packet, expressed as log 2. + This value should be uniform throughout a domain. The default value is 1=2s. */ + +#ifndef NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL +#define NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL 1 +#endif + + +/* Define the interval for sending Delay request packets */ + +#ifndef NX_PTP_CLIENT_DELAY_REQ_INTERVAL +#define NX_PTP_CLIENT_DELAY_REQ_INTERVAL (2 * NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND) +#endif + + +/* Set maximum queue depth for client socket.*/ + +#ifndef NX_PTP_CLIENT_MAX_QUEUE_DEPTH +#define NX_PTP_CLIENT_MAX_QUEUE_DEPTH 5 +#endif + +/* Define the maximum size of a PTP message */ + +#define NX_PTP_CLIENT_PACKET_DATA_SIZE 64 + +/* Define Announce receipt timeout expire value */ +#define NX_PTP_CLIENT_ANNOUNCE_EXPIRATION (NX_PTP_CLIENT_ANNOUNCE_RECEIPT_TIMEOUT * \ + (1 << NX_PTP_CLIENT_LOG_ANNOUNCE_INTERVAL) * \ + NX_PTP_CLIENT_TIMER_TICKS_PER_SECOND) + + +/* Define a PTP Time */ + +typedef struct NX_PTP_TIME_STRUCT +{ + /* The MSB of the number of seconds */ + LONG second_high; + + /* The LSB of the number of seconds */ + ULONG second_low; + + /* The number of nanoseconds */ + LONG nanosecond; +} NX_PTP_TIME; + + +/* Define the PTP Date Time structure. */ + +typedef struct NX_PTP_DATE_TIME_STRUCT +{ + UINT year; + UCHAR month; + UCHAR day; + UCHAR hour; + UCHAR minute; + UCHAR second; + UCHAR weekday; + ULONG nanosecond; +} NX_PTP_DATE_TIME; + + +/* Internal PTP error processing codes. */ + +#define NX_PTP_ERROR_CONSTANT 0xD00 +/* Client side errors. */ +#define NX_PTP_CLIENT_NOT_STARTED (NX_PTP_ERROR_CONSTANT | 0x01) /* PTP Client task is not running */ +#define NX_PTP_CLIENT_ALREADY_STARTED (NX_PTP_ERROR_CONSTANT | 0x02) /* PTP Client task is already running */ +#define NX_PTP_PARAM_ERROR (NX_PTP_ERROR_CONSTANT | 0x03) /* Invalid non pointer parameter. */ +#define NX_PTP_CLIENT_INSUFFICIENT_PACKET_PAYLOAD (NX_PTP_ERROR_CONSTANT | 0x04) /* Client not properly initialized to receive time data. */ +#define NX_PTP_CLIENT_CLOCK_CALLBACK_FAILURE (NX_PTP_ERROR_CONSTANT | 0x05) /* PTP clock callback returns error. */ + + +/* PTP Protocol Definitions */ + +/* Define the size of the PTP Clock Identity field */ +#define NX_PTP_CLOCK_IDENTITY_SIZE 8 + +/* Define the size of the PTP Clock Port and Identity field */ +#define NX_PTP_CLOCK_PORT_IDENTITY_SIZE (NX_PTP_CLOCK_IDENTITY_SIZE + 2) + + +/* PTP event callback */ + +struct NX_PTP_CLIENT_STRUCT; + +typedef UINT (*NX_PTP_CLIENT_EVENT_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT event, + VOID *event_data, VOID *callback_data); + +#define NX_PTP_CLIENT_EVENT_MASTER 0 +#define NX_PTP_CLIENT_EVENT_SYNC 1 +#define NX_PTP_CLIENT_EVENT_TIMEOUT 2 + + +/* PTP clock callback operations */ + +typedef UINT (*NX_PTP_CLIENT_CLOCK_CALLBACK)(struct NX_PTP_CLIENT_STRUCT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, VOID *callback_data); + +#define NX_PTP_CLIENT_CLOCK_INIT 0 /* Initialization */ +#define NX_PTP_CLIENT_CLOCK_SET 1 /* Set the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_GET 2 /* Get the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_ADJUST 3 /* Adjust the PTP clock */ +#define NX_PTP_CLIENT_CLOCK_PACKET_TS_EXTRACT 4 /* Extract timestamp from packet */ +#define NX_PTP_CLIENT_CLOCK_PACKET_TS_PREPARE 5 /* Prepare timestamp for packet */ +#define NX_PTP_CLIENT_CLOCK_SOFT_TIMER_UPDATE 6 /* Update timer for soft implementation */ + + +/* Master messages data */ +typedef struct NX_PTP_CLIENT_MASTER_STRUCT +{ + NXD_ADDRESS *nx_ptp_client_master_address; + UCHAR *nx_ptp_client_master_port_identity; + UCHAR nx_ptp_client_master_priority1; + UCHAR nx_ptp_client_master_priority2; + UCHAR nx_ptp_client_master_clock_class; + UCHAR nx_ptp_client_master_clock_accuracy; + USHORT nx_ptp_client_master_offset_scaled_log_variance; + UCHAR *nx_ptp_client_master_grandmaster_identity; + USHORT nx_ptp_client_master_steps_removed; + UCHAR nx_ptp_client_master_time_source; +} NX_PTP_CLIENT_MASTER; + +/* Sync flags */ +#define NX_PTP_CLIENT_SYNC_CALIBRATED (1 << 0) +#define NX_PTP_CLIENT_SYNC_UTC_REASONABLE (1 << 1) +#define NX_PTP_CLIENT_SYNC_LEAP59 (1 << 2) +#define NX_PTP_CLIENT_SYNC_LEAP61 (1 << 3) + +/* Sync message data */ +typedef struct NX_PTP_CLIENT_SYNC_STRUCT +{ + USHORT nx_ptp_client_sync_flags; + SHORT nx_ptp_client_sync_utc_offset; +} NX_PTP_CLIENT_SYNC; + + +/* Define the Type of messages */ + +#define NX_PTP_CLIENT_ALL_EVENTS 0xFFFFFFFF /* all events of PTP client */ +#define NX_PTP_CLIENT_STOP_EVENT 0x00000001 /* stop the PTP client */ +#define NX_PTP_CLIENT_RX_EVENT 0x00000002 /* received UDP packet */ +#define NX_PTP_CLIENT_TIMER_EVENT 0x00000004 /* timer tick */ + + +/* Define the size of the PTP client message queue */ + +#define NX_PTP_CLIENT_MESSAGE_QUEUE_SIZE 16 + + +/* Define the state of the PTP Client thread */ + +#define NX_PTP_CLIENT_THREAD_IDLE 0 +#define NX_PTP_CLIENT_THREAD_RUNNING 1 +#define NX_PTP_CLIENT_THREAD_STOPPING 2 +#define NX_PTP_CLIENT_THREAD_STOPPED 3 + + +/* Define the state of the PTP Client clock */ + +#define NX_PTP_CLIENT_STATE_LISTENING 0 +#define NX_PTP_CLIENT_STATE_WAIT_SYNC 1 +#define NX_PTP_CLIENT_STATE_WAIT_FOLLOW_UP 2 + + +/* Define the state of the delay measurement process */ + +#define NX_PTP_CLIENT_DELAY_IDLE 0 +#define NX_PTP_CLIENT_DELAY_WAIT_REQ_TS 1 +#define NX_PTP_CLIENT_DELAY_WAIT_RESP 2 + + +/* Define the structure of a PTP Client */ + +typedef struct NX_PTP_CLIENT_STRUCT +{ + /* PTP Client ID */ + ULONG nx_ptp_client_id; + + /* Pointer to the Client IP instance. */ + NX_IP *nx_ptp_client_ip_ptr; + + /* Index to PTP network interface */ + UINT nx_ptp_client_interface_index; + + /* Pointer to the Client packet pool. */ + NX_PACKET_POOL *nx_ptp_client_packet_pool_ptr; + + /* PTP Domain Number */ + UCHAR nx_ptp_client_domain; + + /* PTP Transport Specific */ + UCHAR nx_ptp_client_transport_specific; + + /* PTP Client Port and Identity */ + UCHAR nx_ptp_client_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE]; + + /* PTP event handler callback */ + NX_PTP_CLIENT_EVENT_CALLBACK nx_ptp_client_event_callback; + VOID *nx_ptp_client_event_callback_data; + + /* PTP clock callback */ + NX_PTP_CLIENT_CLOCK_CALLBACK nx_ptp_client_clock_callback; + VOID *nx_ptp_client_clock_callback_data; + + /* PTP General Messages UDP Socket */ + NX_UDP_SOCKET nx_ptp_client_general_socket; + + /* PTP Event Messages UDP Socket */ + NX_UDP_SOCKET nx_ptp_client_event_socket; + + /* The message queue */ + TX_EVENT_FLAGS_GROUP nx_ptp_client_events; + + /* Set if IPv4 multicast group has been joined */ + UCHAR nx_ptp_client_ipv4_group_joined; + +#if defined(NX_ENABLE_IPV6_MULTICAST) && defined(FEATURE_NX_IPV6) + /* Set if IPv6 multicast group has been joined */ + UCHAR nx_ptp_client_ipv6_group_joined; +#endif + + /* The software clock value */ + NX_PTP_TIME nx_ptp_client_soft_clock; + + /* The state of the PTP client */ + UCHAR nx_ptp_client_state; + + /* The state of the delay measurement */ + UCHAR nx_ptp_client_delay_state; + + /* The current UTC offset flags */ + USHORT nx_ptp_client_sync_flags; + + /* The current UTC offset */ + SHORT nx_ptp_client_utc_offset; + + /* The address of the master clock */ + NXD_ADDRESS nx_ptp_client_master_addr; + + /* The identity of the master clock */ + UCHAR nx_ptp_client_master_port_identity[NX_PTP_CLOCK_PORT_IDENTITY_SIZE]; + + /* The current sync master timestamp */ + NX_PTP_TIME nx_ptp_client_sync; + + /* The current sync client timestamp */ + NX_PTP_TIME nx_ptp_client_sync_ts; + + /* The id of the sync message */ + USHORT nx_ptp_client_sync_id; + + /* The id of the last delay_req message */ + USHORT nx_ptp_client_delay_req_id; + + /* The delay request interval timer */ + INT nx_ptp_client_delay_req_timer; + + /* The Announce timeout */ + INT nx_ptp_client_announce_timeout; + + /* The delay request flag */ + UINT nx_ptp_client_delay_req_flag; + + /* The delay request client timestamp */ + NX_PTP_TIME nx_ptp_client_delay_ts; + + /* The delay request packet pointer */ + NX_PACKET *nx_ptp_client_delay_req_packet_ptr; + + /* The PTP client timer */ + TX_TIMER nx_ptp_client_timer; + + /* The current state of the PTP Client thread */ + UINT nx_ptp_client_thread_state; + + /* The PTP client processing thread */ + TX_THREAD nx_ptp_client_thread; +} NX_PTP_CLIENT; + + +#ifndef NX_PTP_SOURCE_CODE + +/* Define the system API mappings based on the error checking selected by the user. */ + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + + +#ifdef NX_PTP_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define nx_ptp_client_create _nx_ptp_client_create +#define nx_ptp_client_delete _nx_ptp_client_delete +#define nx_ptp_client_start _nx_ptp_client_start +#define nx_ptp_client_stop _nx_ptp_client_stop +#define nx_ptp_client_time_get _nx_ptp_client_time_get +#define nx_ptp_client_time_set _nx_ptp_client_time_set +#define nx_ptp_client_master_info_get _nx_ptp_client_master_info_get +#define nx_ptp_client_sync_info_get _nx_ptp_client_sync_info_get +#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify +#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback +#define nx_ptp_client_utility_time_diff _nx_ptp_client_utility_time_diff +#define nx_ptp_client_utility_convert_time_to_date _nx_ptp_client_utility_convert_time_to_date + +#else + +/* Services with error checking. */ + +#define nx_ptp_client_create _nxe_ptp_client_create +#define nx_ptp_client_delete _nxe_ptp_client_delete +#define nx_ptp_client_start _nxe_ptp_client_start +#define nx_ptp_client_stop _nxe_ptp_client_stop +#define nx_ptp_client_time_get _nxe_ptp_client_time_get +#define nx_ptp_client_time_set _nxe_ptp_client_time_set +#define nx_ptp_client_master_info_get _nxe_ptp_client_master_info_get +#define nx_ptp_client_sync_info_get _nxe_ptp_client_sync_info_get +#define nx_ptp_client_packet_timestamp_notify _nx_ptp_client_packet_timestamp_notify +#define nx_ptp_client_soft_clock_callback _nx_ptp_client_soft_clock_callback +#define nx_ptp_client_utility_time_diff _nxe_ptp_client_utility_time_diff +#define nx_ptp_client_utility_convert_time_to_date _nxe_ptp_client_utility_convert_time_to_date + +#endif + +#endif + + +/* Define the function prototypes of the PTP Client API */ + +UINT _nx_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data); +UINT _nx_ptp_client_delete(NX_PTP_CLIENT *client_ptr); +UINT _nx_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data); +UINT _nx_ptp_client_stop(NX_PTP_CLIENT *client_ptr); +UINT _nx_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nx_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nx_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source); +UINT _nx_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset); +UINT _nx_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr); +UINT _nx_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr); +VOID _nx_ptp_client_packet_timestamp_notify(NX_PTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, NX_PTP_TIME *timestamp_ptr); +UINT _nx_ptp_client_soft_clock_callback(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data); + +UINT _nxe_ptp_client_create(NX_PTP_CLIENT *client_ptr, NX_IP *ip_ptr, UINT interface_index, + NX_PACKET_POOL *packet_pool_ptr, UINT thread_priority, UCHAR *thread_stack, UINT stack_size, + NX_PTP_CLIENT_CLOCK_CALLBACK clock_callback, VOID *clock_callback_data); +UINT _nxe_ptp_client_delete(NX_PTP_CLIENT *client_ptr); +UINT _nxe_ptp_client_start(NX_PTP_CLIENT *client_ptr, UCHAR *client_port_identity_ptr, UINT client_port_identity_length, + UINT domain, UINT transport_specific, NX_PTP_CLIENT_EVENT_CALLBACK event_callback, + VOID *event_callback_data); +UINT _nxe_ptp_client_stop(NX_PTP_CLIENT *client_ptr); +UINT _nxe_ptp_client_time_get(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nxe_ptp_client_time_set(NX_PTP_CLIENT *client_ptr, NX_PTP_TIME *time_ptr); +UINT _nxe_ptp_client_master_info_get(NX_PTP_CLIENT_MASTER *master_ptr, NXD_ADDRESS *address, UCHAR **port_identity, + UINT *port_identity_length, UCHAR *priority1, UCHAR *priority2, UCHAR *clock_class, + UCHAR *clock_accuracy, USHORT *clock_variance, UCHAR **grandmaster_identity, + UINT *grandmaster_identity_length, USHORT *steps_removed, UCHAR *time_source); +UINT _nxe_ptp_client_sync_info_get(NX_PTP_CLIENT_SYNC *sync_ptr, USHORT *flags, SHORT *utc_offset); +UINT _nxe_ptp_client_utility_time_diff(NX_PTP_TIME *time1_ptr, NX_PTP_TIME *time2_ptr, NX_PTP_TIME *result_ptr); +UINT _nxe_ptp_client_utility_convert_time_to_date(NX_PTP_TIME *time_ptr, LONG offset, NX_PTP_DATE_TIME *date_time_ptr); + + +/* Define the function prototypes of the private utility functions */ + +VOID _nx_ptp_client_utility_time_div_by_2(NX_PTP_TIME *time_ptr); +VOID _nx_ptp_client_utility_add64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo); +VOID _nx_ptp_client_utility_sub64(LONG *a_hi, ULONG *a_lo, LONG b_hi, ULONG b_lo); +VOID _nx_ptp_client_utility_inc64(LONG *a_hi, ULONG *a_lo); +VOID _nx_ptp_client_utility_dec64(LONG *a_hi, ULONG *a_lo); +VOID _nx_ptp_client_utility_neg64(LONG *a_hi, ULONG *a_lo); + + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus +} +#endif + +#endif /* NX_PTP_CLIENT_H */ diff --git a/addons/smtp/nxd_smtp_client.c b/addons/smtp/nxd_smtp_client.c index 16e23d8d..2c010c07 100644 --- a/addons/smtp/nxd_smtp_client.c +++ b/addons/smtp/nxd_smtp_client.c @@ -20,33 +20,6 @@ /**************************************************************************/ /**************************************************************************/ -/**************************************************************************/ -/* */ -/* APPLICATION INTERFACE DEFINITION RELEASE */ -/* */ -/* nxd_smtp_client.c PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This file defines the NetX Simple Mail Transfer Protocol (SMTP) */ -/* Client component, including all data types and external references. */ -/* It is assumed that tx_api.h, tx_port.h, nx_api.h, and nx_port.h, */ -/* have already been included. */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ - #define NX_SMTP_SOURCE_CODE @@ -81,8 +54,6 @@ static CHAR _nx_smtp_buffer[NX_SMTP_BUFFER_SIZE]; /* Define internal SMTP Client functions. */ static VOID _nx_smtp_find_crlf(UCHAR *buffer, UINT length, UCHAR **CRLF, UINT reverse); -static VOID _nx_smtp_base64_encode(UCHAR *name, UCHAR *base64name, UINT length); -static VOID _nx_smtp_base64_decode(UCHAR *base64name, UCHAR *name); static UINT _nx_smtp_cmd_idle(NX_SMTP_CLIENT *client_ptr); static UINT _nx_smtp_rsp_idle(NX_SMTP_CLIENT *client_ptr); static UINT _nx_smtp_cmd_greeting(NX_SMTP_CLIENT *client_ptr); @@ -115,7 +86,7 @@ static UINT _nx_smtp_utility_send_to_server(NX_SMTP_CLIENT *client_ptr, CHAR *bu static UINT _nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer_ptr, UINT length); static UINT _nx_smtp_client_process(NX_SMTP_CLIENT *client_ptr); static UINT _nx_smtp_utility_send_header_to_server(NX_SMTP_CLIENT *client_ptr, ULONG timeout) ; -static UINT _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr); +static VOID _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr); static UINT _nx_smtp_parse_250_response(UCHAR *buffer_ptr, UINT buffer_length, UINT *is_last_code); static UINT _nx_smtp_parse_response(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer, UINT arguement_index, UINT buffer_length, UCHAR *arguement, UINT arguement_length, @@ -1767,7 +1738,7 @@ UINT index; /* FUNCTION RELEASE */ /* */ /* _nx_smtp_rsp_auth PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1816,6 +1787,9 @@ UINT index; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_smtp_rsp_auth(NX_SMTP_CLIENT *client_ptr) @@ -1823,13 +1797,10 @@ UINT _nx_smtp_rsp_auth(NX_SMTP_CLIENT *client_ptr) UINT status; UINT server_reply_first_digit; -UCHAR *carriage_return_linefeed_ptr; +UCHAR *carriage_return_linefeed_ptr = NX_NULL; UINT auth_length; - /* Initialize authentication flags. */ - carriage_return_linefeed_ptr = (CHAR)0x0; - /* Get the server response to the AUTH command. */ status = _nx_smtp_utility_read_server_code(client_ptr, NX_SMTP_ENVELOPE_TIMEOUT, NX_TRUE); @@ -1987,7 +1958,7 @@ UINT auth_length; /* FUNCTION RELEASE */ /* */ /* _nx_smtp_cmd_auth_challenge PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2009,7 +1980,7 @@ UINT auth_length; /* CALLS */ /* */ /* _nx_smtp_utility_send_to_server Send data to server */ -/* _nx_smtp_base64_encode Base64 encode specified text */ +/* _nx_utility_base64_encode Base64 encode specified text */ /* memcpy Copy data to area of memory */ /* */ /* CALLED BY */ @@ -2025,6 +1996,10 @@ UINT auth_length; /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_smtp_cmd_auth_challenge(NX_SMTP_CLIENT *client_ptr) @@ -2032,7 +2007,8 @@ UINT _nx_smtp_cmd_auth_challenge(NX_SMTP_CLIENT *client_ptr) UINT status; UINT index; -UCHAR auth_reply_encoded[NX_SMTP_CLIENT_AUTH_CHALLENGE_ENCODED_SIZE + 1]; +UCHAR auth_reply_encoded[NX_SMTP_CLIENT_AUTH_CHALLENGE_ENCODED_SIZE + 1]; +UINT auth_reply_encoded_size; UINT length; UINT password_length; @@ -2077,14 +2053,14 @@ UINT password_length; length += password_length; /* Now encode the combined client username/password. */ - _nx_smtp_base64_encode(&plain_auth_buffer[0], auth_reply_encoded, length); + _nx_utility_base64_encode(&plain_auth_buffer[0], length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size); } else { + /* Just encode the client username. */ - _nx_smtp_base64_encode((UCHAR *)client_ptr -> nx_smtp_username, auth_reply_encoded, - length); + _nx_utility_base64_encode((UCHAR *)client_ptr -> nx_smtp_username, length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size); } } @@ -2093,8 +2069,7 @@ UINT password_length; { /* Encode the client password. */ - _nx_smtp_base64_encode((UCHAR *)client_ptr -> nx_smtp_password, auth_reply_encoded, - password_length); + _nx_utility_base64_encode((UCHAR *)client_ptr -> nx_smtp_password, password_length, auth_reply_encoded, sizeof(auth_reply_encoded), &auth_reply_encoded_size); } else @@ -2102,14 +2077,10 @@ UINT password_length; /* Unknown prompt: Send the '*' to terminate the authentication process. */ memcpy(auth_reply_encoded, NX_SMTP_CANCEL_AUTHENTICATION, sizeof(NX_SMTP_CANCEL_AUTHENTICATION)); /* Use case of memcpy is verified. */ + auth_reply_encoded_size = sizeof(NX_SMTP_CANCEL_AUTHENTICATION) - 1; } - if (_nx_utility_string_length_check((CHAR *)auth_reply_encoded, &length, sizeof(auth_reply_encoded) - 1)) - { - return(NX_SIZE_ERROR); - } - - if (sizeof(_nx_smtp_buffer) < (length + sizeof(NX_SMTP_LINE_TERMINATOR) - 1)) + if (sizeof(_nx_smtp_buffer) < (auth_reply_encoded_size + sizeof(NX_SMTP_LINE_TERMINATOR) - 1)) { /* Buffer size too small. */ @@ -2117,8 +2088,8 @@ UINT password_length; } /* Format the encoded response. */ - memcpy(&_nx_smtp_buffer[0],auth_reply_encoded, length); /* Use case of memcpy is verified. */ - index = length; + memcpy(&_nx_smtp_buffer[0],auth_reply_encoded, auth_reply_encoded_size); /* Use case of memcpy is verified. */ + index = auth_reply_encoded_size; memcpy(&_nx_smtp_buffer[index], NX_SMTP_LINE_TERMINATOR, sizeof(NX_SMTP_LINE_TERMINATOR) - 1); /* Use case of memcpy is verified. */ index += sizeof(NX_SMTP_LINE_TERMINATOR) - 1; @@ -3858,7 +3829,7 @@ UINT subject_length; /* FUNCTION RELEASE */ /* */ /* _nx_smtp_utility_authentication_challenge PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -3883,7 +3854,7 @@ UINT subject_length; /* CALLS */ /* */ /* _nx_smtp_parse_response Parses argument from buffer text */ -/* _nx_smtp_base64_decode Decodes base64 text */ +/* _nx_utility_base64_decode Decodes base64 text */ /* memset Clears specified area of memory */ /* memcmp Compares data between areas of memory */ /* */ @@ -3898,6 +3869,10 @@ UINT subject_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT *client_ptr, UCHAR *server_challenge, UINT length) @@ -3905,6 +3880,8 @@ UINT _nx_smtp_utility_authentication_challenge(NX_SMTP_CLIENT *client_ptr, UCHA UCHAR encrypted_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; +UINT encrypted_server_prompt_size; +UINT decoded_server_prompt_size; if (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_PLAIN) { @@ -3933,11 +3910,18 @@ UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; return NX_SMTP_INVALID_SERVER_REPLY; } + /* Calculate the name length. */ + if (_nx_utility_string_length_check((CHAR *)encrypted_server_prompt, &encrypted_server_prompt_size, NX_SMTP_SERVER_CHALLENGE_MAX_STRING)) + { + return NX_SMTP_INVALID_SERVER_REPLY; + } + /* Decode the parsed server challenge. */ - _nx_smtp_base64_decode(encrypted_server_prompt, decoded_server_prompt); + _nx_utility_base64_decode(encrypted_server_prompt, encrypted_server_prompt_size, decoded_server_prompt, sizeof(decoded_server_prompt), &decoded_server_prompt_size); /* Is this a username prompt? */ - if (((decoded_server_prompt[0] == 'U') || (decoded_server_prompt[0] == 'u')) && + if ((decoded_server_prompt_size == 9) && + ((decoded_server_prompt[0] == 'U') || (decoded_server_prompt[0] == 'u')) && ((decoded_server_prompt[1] == 'S') || (decoded_server_prompt[1] == 's')) && ((decoded_server_prompt[2] == 'E') || (decoded_server_prompt[2] == 'e')) && ((decoded_server_prompt[3] == 'R') || (decoded_server_prompt[3] == 'r')) && @@ -3952,7 +3936,8 @@ UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; client_ptr -> nx_smtp_client_authentication_reply = NX_SMTP_CLIENT_REPLY_TO_USERNAME_PROMPT; } /* Is this a password prompt? */ - else if (((decoded_server_prompt[0] == 'P') || (decoded_server_prompt[0] == 'p')) && + else if ((decoded_server_prompt_size == 9) && + ((decoded_server_prompt[0] == 'P') || (decoded_server_prompt[0] == 'p')) && ((decoded_server_prompt[1] == 'A') || (decoded_server_prompt[1] == 'a')) && ((decoded_server_prompt[2] == 'S') || (decoded_server_prompt[2] == 's')) && ((decoded_server_prompt[3] == 'S') || (decoded_server_prompt[3] == 's')) && @@ -3983,7 +3968,7 @@ UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; /* FUNCTION RELEASE */ /* */ /* _nx_smtp_utility_parse_server_services PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4003,7 +3988,7 @@ UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; /* */ /* OUTPUT */ /* */ -/* NX_SUCCESS Successful completion status */ +/* None */ /* */ /* CALLS */ /* */ @@ -4020,9 +4005,12 @@ UCHAR decoded_server_prompt[NX_SMTP_SERVER_CHALLENGE_MAX_STRING + 1]; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved boundary check, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ -UINT _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr) +VOID _nx_smtp_utility_parse_server_services(NX_SMTP_CLIENT *client_ptr) { UINT plain_option = NX_FALSE; @@ -4042,6 +4030,12 @@ UINT found = NX_FALSE; /* Find the location of the AUTH command. */ work_ptr = client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr; + /* Check length. */ + if (length <= 4) + { + return; + } + for (i = 0; i < length - 4; i++) { if ( @@ -4065,7 +4059,7 @@ UINT found = NX_FALSE; { /* It does not. So leave the Client authentication type as is. */ - return NX_SUCCESS; + return; } /* Check if the client prefers no authentication. */ @@ -4073,14 +4067,24 @@ UINT found = NX_FALSE; { /* There is an AUTH keyword but the client prefers not to authenticate. */ - return NX_SUCCESS; + return; } /* Save the location where the search stopped. */ temp_ptr = work_ptr; found = NX_FALSE; - new_length = (length - 5) - (ULONG)(temp_ptr - client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr); + new_length = length - (ULONG)(temp_ptr - client_ptr -> nx_smtp_server_packet -> nx_packet_prepend_ptr); + + /* Check length. */ + if (new_length < 5) + { + return; + } + else + { + new_length -= 5; + } /* Search for supported authentication types. */ for (i = 0; i < new_length; i++) @@ -4146,14 +4150,14 @@ UINT found = NX_FALSE; if (login_option) { - return NX_SUCCESS; + return; } else { /* Switch client to plain authentication. */ client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_PLAIN; - return NX_SUCCESS; + return; } } @@ -4161,7 +4165,7 @@ UINT found = NX_FALSE; if (plain_option && (client_ptr -> nx_smtp_client_authentication_type == NX_SMTP_CLIENT_AUTH_PLAIN)) { /* Yes, and there's a match, we're done here. */ - return NX_SUCCESS; + return; } /* If we are here, the server offers LOGIN authentication but the Client preference is something else. */ @@ -4171,15 +4175,15 @@ UINT found = NX_FALSE; /* Switch client to LOGIN authentication. */ client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_LOGIN; - return NX_SUCCESS; + return; } /* Handle the case of no matches between server/client. Assume the server requires authentication and set Client type to plain. */ client_ptr -> nx_smtp_client_authentication_type = NX_SMTP_CLIENT_AUTH_PLAIN; - /* Return successful completion of checking options. */ - return NX_SUCCESS; + /* Return. */ + return; } @@ -4188,7 +4192,7 @@ UINT found = NX_FALSE; /* FUNCTION RELEASE */ /* */ /* _nx_smtp_parse_response PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4238,6 +4242,9 @@ UINT found = NX_FALSE; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved boundary check, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_smtp_parse_response(NX_SMTP_CLIENT *client_ptr, UCHAR *buffer, UINT argument_index, @@ -4253,17 +4260,15 @@ UCHAR *work_ptr; UINT is_last_code; - memset(&argument[0], 0, argument_length); - work_ptr = argument; - /* Check for invalid input parameters. */ - if ((buffer == NX_NULL) || (argument == NX_NULL) || (buffer_length == 0) || - (argument_length == 0) || (argument_index == 0)) + if ((buffer == NX_NULL) || (buffer_length == 0) || (argument_index == 0)) { return NX_SMTP_INVALID_PARAM; } + work_ptr = argument; + /* Is this the first word? The first word is the reply code, not an SMTP command parameter */ if (argument_index == 1) @@ -4288,6 +4293,11 @@ UINT is_last_code; else if ((*buffer >= 0x30) && (*buffer <= 0x39)) { + if (work_ptr >= argument + argument_length) + { + return(NX_SMTP_INTERNAL_ERROR); + } + /* Yes, copy to buffer. */ *work_ptr = *buffer; work_ptr++; @@ -4303,19 +4313,6 @@ UINT is_last_code; buffer++; i++; } - - /* Are we at the end of the buffer? */ - if (i == buffer_length) - { - - /* Yes, is there a line terminator? */ - if (*(argument - 2) == 0x0D && *(argument - 1) == 0x0A) - { - - /* Yes, remove it with a null character */ - *(argument - 2) = (CHAR) 0x0; - } - } } else { @@ -4593,270 +4590,3 @@ UINT i = 0; return ; } - - -CHAR _nx_smtp_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_smtp_base64_encode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function encodes the input string into a base64 */ -/* representation. It is the caller's responsibility to match the */ -/* name and base64name buffers in size to avoid overwriting memory. */ -/* */ -/* INPUT */ -/* */ -/* name Pointer to name to encode */ -/* base64name Pointer to name base64 encoded */ -/* length Size of input buffer to encode */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* Application Code */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_smtp_base64_encode(UCHAR *name, UCHAR *base64name, UINT length) -{ - -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - - /* Default padding to none. */ - pad = 0; - - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) - { - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; - } - - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) - { - /* Determine which step we are in. */ - if (step == 0) - { - /* Use first 6 bits of name character for index. */ - base64name[j++] = (UCHAR)_nx_smtp_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) - { - - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = (UCHAR)_nx_smtp_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; - } - else if (step == 2) - { - - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = (UCHAR)_nx_smtp_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ - { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = (UCHAR)_nx_smtp_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; - } - } - - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < NX_SMTP_CLIENT_AUTH_CHALLENGE_ENCODED_SIZE)) - { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; - } - - /* Put a NULL character in. */ - base64name[j] = NX_NULL; -} - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_smtp_base64_decode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function decodes the input base64 ASCII string and converts */ -/* it into a standard ASCII representation. It is the caller's */ -/* responsibility to match the name and base64name buffers in size to */ -/* avoid overwriting memory. */ -/* */ -/* INPUT */ -/* */ -/* base64name Encoded base64 name string */ -/* name Name string */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _nx_utility_string_length_check Get length of string */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_smtp_server_basic_authenticate Basic authentication */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_smtp_base64_decode(UCHAR *base64name, UCHAR *name) -{ - -UINT length; -UINT i, j; -UINT value1, value2; -UINT step; - - - /* Calculate the name length. */ - if (_nx_utility_string_length_check((CHAR *)base64name, &length, NX_SMTP_SERVER_CHALLENGE_MAX_STRING)) - { - name[0] = NX_NULL; - return; - } - - /* Adjust the length to represent the ASCII name. */ - length = ((length * 6) / 8); - - /* Setup index into the ASCII name. */ - j = 0; - - /* Compute the ASCII name. */ - step = 0; - i = 0; - - while ((j < length) && (base64name[i]) && (base64name[i] != '=') && (j < NX_SMTP_CLIENT_AUTH_CHALLENGE_SIZE)) - { - - /* Derive values of the Base64 name. */ - if ((base64name[i] >= 'A') && (base64name[i] <= 'Z')) - value1 = (UINT) (base64name[i] - 'A'); - else if ((base64name[i] >= 'a') && (base64name[i] <= 'z')) - value1 = (UINT) (base64name[i] - 'a') + 26; - else if ((base64name[i] >= '0') && (base64name[i] <= '9')) - value1 = (UINT) (base64name[i] - '0') + 52; - else if (base64name[i] == '+') - value1 = 62; - else if (base64name[i] == '/') - value1 = 63; - else - value1 = 0; - - /* Derive value for the next character. */ - if ((base64name[i+1] >= 'A') && (base64name[i+1] <= 'Z')) - value2 = (UINT) (base64name[i+1] - 'A'); - else if ((base64name[i+1] >= 'a') && (base64name[i+1] <= 'z')) - value2 = (UINT) (base64name[i+1] - 'a') + 26; - else if ((base64name[i+1] >= '0') && (base64name[i+1] <= '9')) - value2 = (UINT) (base64name[i+1] - '0') + 52; - else if (base64name[i+1] == '+') - value2 = 62; - else if (base64name[i+1] == '/') - value2 = 63; - else - value2 = 0; - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first value and first 2 bits of second value. */ - name[j++] = (UCHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3)); - i++; - step++; - } - else if (step == 1) - { - - /* Use last 4 bits of first value and first 4 bits of next value. */ - name[j++] = (UCHAR) (((value1 & 0xF) << 4) | (value2 >> 2)); - i++; - step++; - } - else if (step == 2) - { - - /* Use first 2 bits and following 6 bits of next value. */ - name[j++] = (UCHAR) (((value1 & 3) << 6) | (value2 & 0x3f)); - i++; - i++; - step = 0; - } - } - - /* Put a NULL character in. */ - name[j] = NX_NULL; - - return; -} - diff --git a/addons/smtp/nxd_smtp_client.h b/addons/smtp/nxd_smtp_client.h index c82bc390..21689dad 100644 --- a/addons/smtp/nxd_smtp_client.h +++ b/addons/smtp/nxd_smtp_client.h @@ -24,7 +24,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_smtp_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -43,6 +43,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NXD_SMTP_CLIENT_H @@ -59,6 +62,8 @@ extern "C" { #endif +#include "nx_api.h" + /* NX SMTP Client configurable options. */ diff --git a/addons/snmp/nxd_snmp.c b/addons/snmp/nxd_snmp.c index 3c433172..c9453b36 100644 --- a/addons/snmp/nxd_snmp.c +++ b/addons/snmp/nxd_snmp.c @@ -1613,7 +1613,7 @@ UINT _nx_snmp_agent_version_set(NX_SNMP_AGENT *agent_ptr, UINT enabled_v1, UINT /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_set_interface PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1646,6 +1646,9 @@ UINT _nx_snmp_agent_version_set(NX_SNMP_AGENT *agent_ptr, UINT enabled_v1, UINT /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), */ +/* checked the interface index,*/ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_snmp_agent_set_interface(NX_SNMP_AGENT *agent_ptr, UINT if_index) @@ -1657,6 +1660,12 @@ UINT status; return NX_PTR_ERROR; } + /* Check for valid interface index. */ + if (if_index >= NX_MAX_PHYSICAL_INTERFACES) + { + return(NX_INVALID_INTERFACE); + } + status = _nx_snmp_agent_set_interface(agent_ptr, if_index); return status; @@ -3977,7 +3986,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nxd_snmp_agent_trap_send PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4035,6 +4044,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), */ +/* checked the interface index,*/ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxd_snmp_agent_trap_send(NX_SNMP_AGENT *agent_ptr, NXD_ADDRESS *ip_address, UCHAR *community, UCHAR *enterprise, @@ -4233,6 +4245,21 @@ UINT packet_type; #ifndef NX_DISABLE_IPV4 + + /* Check if the interface index is valid. */ + if (agent_ptr -> nx_snmp_agent_interface_index >= NX_MAX_PHYSICAL_INTERFACES) + { + + /* Increment the internal error counter. */ + agent_ptr -> nx_snmp_agent_internal_errors++; + + /* Release the trap packet. */ + nx_packet_release(trap_packet_ptr); + + /* Return to caller. */ + return(NX_SNMP_ERROR); + } + trap_object_data.nx_snmp_object_data_msw = (LONG)(agent_ptr -> nx_snmp_agent_ip_ptr) -> nx_ip_interface[agent_ptr -> nx_snmp_agent_interface_index].nx_interface_ip_address; #else @@ -12084,7 +12111,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ipv6_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -12121,6 +12148,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* optimized boundary check, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ipv6_address_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) @@ -12137,6 +12167,12 @@ UCHAR *string_ptr; return(NX_SNMP_ERROR_WRONGTYPE); } + /* Determine if the string is too big. */ + if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) + { + return NX_SNMP_ERROR_TOOBIG; + } + /* Setup pointer to the value. */ string_ptr = destination_ptr; @@ -12145,15 +12181,6 @@ UCHAR *string_ptr; for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { - /* Determine if the string is too big. */ - if (i >= NX_SNMP_MAX_OCTET_STRING) - { - - /* Error, source string is too large. */ - string_ptr[0] = NX_NULL; - return(NX_SNMP_ERROR); - } - /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } @@ -12226,7 +12253,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_ipv6_address_get PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -12262,6 +12289,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* optimized boundary check, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_ipv6_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *object_data) @@ -12270,7 +12300,13 @@ UINT _nx_snmp_object_ipv6_address_get(VOID *source_ptr, NX_SNMP_OBJECT_DATA *ob UINT i; UCHAR *source_string; - + + /* Determine if the string is too big. */ + if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) + { + return NX_SNMP_ERROR_TOOBIG; + } + /* Setup pointer to source string. */ source_string = (UCHAR *) source_ptr; @@ -12980,7 +13016,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_octet_string_set PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13016,6 +13052,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* optimized boundary check, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_octet_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) @@ -13045,15 +13084,6 @@ UCHAR *string_ptr; for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { - /* Determine if the string is too big. */ - if (i >= NX_SNMP_MAX_OCTET_STRING) - { - - /* Error, source string is too large. */ - string_ptr[0] = NX_NULL; - return(NX_SNMP_ERROR); - } - /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } @@ -13273,7 +13303,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_object_string_set PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -13308,6 +13338,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* optimized boundary check, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_snmp_object_string_set(VOID *destination_ptr, NX_SNMP_OBJECT_DATA *object_data) @@ -13325,6 +13358,12 @@ UCHAR *string_ptr; return(NX_SNMP_ERROR_WRONGTYPE); } + /* Determine if the string is too big. */ + if (object_data -> nx_snmp_object_octet_string_size > NX_SNMP_MAX_OCTET_STRING) + { + return NX_SNMP_ERROR_TOOBIG; + } + /* Setup pointer to the destination string. */ string_ptr = (UCHAR *) destination_ptr; @@ -13332,14 +13371,6 @@ UCHAR *string_ptr; for (i = 0; i < object_data -> nx_snmp_object_octet_string_size; i++) { - /* Determine if the string is too big. */ - if (i >= NX_SNMP_MAX_OCTET_STRING) - { - - /* Error, source string is too large. */ - return(NX_SNMP_ERROR); - } - /* Copy character. */ string_ptr[i] = object_data -> nx_snmp_object_octet_string[i]; } @@ -14063,7 +14094,7 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_id_get PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -14086,7 +14117,7 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e /* */ /* CALLS */ /* */ -/* None */ +/* _nx_utility_uint_to_string Convert number to ASCII */ /* */ /* CALLED BY */ /* */ @@ -14102,6 +14133,14 @@ UINT _nx_snmp_utility_error_info_set(UCHAR *buffer_ptr, UINT error_code, UINT e /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), */ +/* initialized the sequence */ +/* byte value, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_id_get(UCHAR *buffer_ptr, UCHAR *object_string, INT buffer_length) @@ -14132,9 +14171,6 @@ UINT string_length; /* Initialize the string length to 0. */ string_length = 0; - /* Initialize the sequence byte value to NULL. */ - value = 0; - /* First see if the ANS1 object type is present. */ if (buffer_ptr[0] != NX_SNMP_ANS1_OBJECT_ID) { @@ -14285,6 +14321,9 @@ UINT string_length; while (total) { + /* Initialize the sequence byte value to NULL. */ + value = 0; + /* Move the buffer pointer forward. */ byte = *buffer_ptr++; @@ -14373,48 +14412,23 @@ UINT string_length; value = value + temp; } - /* Loop to convert value into ASCII. */ - size = 0; - do - { - - /* Shift the current digits over one. */ - for (i = size; i != 0; i--) - { - - /* Move each digit over one place. */ - object_string[i] = object_string[i-1]; - } - - /* Compute the next decimal digit. */ - byte = (UCHAR) (value % 10); - - /* Update the input number. */ - value = value / 10; - - /* Store the new digit in ASCII form. */ - object_string[0] = (UCHAR)(byte + 0x30); - - /* Increment the size. */ - size++; - - /* Increment the string length. */ - string_length++; + /* Convert value into ASCII. */ + size = _nx_utility_uint_to_string(value, 10, (CHAR *)object_string, NX_SNMP_MAX_OCTET_STRING + 1 - string_length); - /* Determine if the length is too long. */ - if (string_length >= NX_SNMP_MAX_OCTET_STRING) - { + if (size == 0) + { - /* String is too long. */ + /* String is too long. */ - /* Null-terminate the string. */ - *object_string = NX_NULL; + /* Null-terminate the string. */ + *object_string = NX_NULL; - /* Return the length. */ - return(length); - } - - } while ((size < 10) && (value)); + /* Return the length. */ + return(length); + } + + /* Adjust the object string length. */ + string_length += size; /* Adjust the object string. */ object_string = object_string + size; @@ -15131,7 +15145,7 @@ UCHAR encoding_started; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_utility_object_data_get PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -15168,6 +15182,9 @@ UCHAR encoding_started; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_snmp_utility_object_data_get(UCHAR *buffer_ptr, NX_SNMP_OBJECT_DATA *object_data, INT buffer_length) @@ -15175,9 +15192,9 @@ UINT _nx_snmp_utility_object_data_get(UCHAR *buffer_ptr, NX_SNMP_OBJECT_DATA *o UINT i; -UINT length; +UINT length = 0; LONG data; -UINT total; +UINT total = 0; CHAR byte; LONG temp = 0; USHORT tlv_type, tlv_tag_class; @@ -16984,7 +17001,7 @@ UINT _nx_snmp_utility_version_set(UCHAR *buffer_ptr, UINT snmp_version, UCHAR * /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_error_response PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -17029,13 +17046,16 @@ UINT _nx_snmp_utility_version_set(UCHAR *buffer_ptr, UINT snmp_version, UCHAR * /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* verification of encryption, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_error_response(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr, UCHAR *request_type_ptr, UCHAR *error_string_ptr, UINT error_code, UINT error_index) { -UINT status; +UINT status = NX_SUCCESS; #ifndef NX_SNMP_DISABLE_V3 ULONG temp; #endif @@ -17080,24 +17100,47 @@ ULONG temp; _nx_snmp_utility_error_info_set(error_string_ptr, error_code, error_index, packet_ptr -> nx_packet_data_end); #ifndef NX_SNMP_DISABLE_V3 - /* Is the security set to encryption? */ - temp = (ULONG)agent_ptr -> nx_snmp_agent_v3_message_security_options; - if (temp & NX_SNMP_SECURITY_PRIVACY) + + if (agent_ptr -> nx_snmp_agent_current_version == NX_SNMP_VERSION_3) { - /* Encrypt the PDU and setup the response to have an encryption header. This - will also compute our privacy parameter. */ - _nx_snmp_agent_encrypt_pdu(agent_ptr, NX_NULL, NX_NULL, - NX_NULL, NX_NULL, - NX_NULL, NX_NULL, pdu_privacy_ptr); - } + /* Is the security set to encryption? */ + temp = (ULONG)agent_ptr -> nx_snmp_agent_v3_message_security_options; + if (temp & NX_SNMP_SECURITY_PRIVACY) + { - /* Is the security set to authentication? */ - if (temp & NX_SNMP_SECURITY_AUTHORIZE) - { + /* Encrypt the PDU and setup the response to have an encryption header. This + will also compute our privacy parameter. */ + status = _nx_snmp_agent_encrypt_pdu(agent_ptr, NX_NULL, NX_NULL, + NX_NULL, NX_NULL, + NX_NULL, NX_NULL, pdu_privacy_ptr); + + /* Check status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(packet_ptr); + return; + } + } + + /* Is the security set to authentication? */ + if (temp & NX_SNMP_SECURITY_AUTHORIZE) + { - /* Compute our authentication parameter. */ - status = _nx_snmp_agent_add_auth_parameter(agent_ptr, packet_ptr, pdu_auth_parm_ptr); + /* Compute our authentication parameter. */ + status = _nx_snmp_agent_add_auth_parameter(agent_ptr, packet_ptr, pdu_auth_parm_ptr); + + /* Check status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(packet_ptr); + return; + } + } } #endif @@ -19179,7 +19222,7 @@ INT buffer_length; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_version_3_process PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -19244,6 +19287,10 @@ INT buffer_length; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved boundary check, */ +/* checked NULL pointer, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _nx_snmp_version_3_process(NX_SNMP_AGENT *agent_ptr, NX_PACKET *packet_ptr) @@ -19714,6 +19761,23 @@ INT buffer_length; else { + /* Check if security option is set, but the security parameter is empty.*/ + if (agent_ptr -> nx_snmp_agent_v3_message_security_options) + { + + /* Increment the invalid packet error counter. */ + agent_ptr -> nx_snmp_agent_invalid_packets++; + + /* Increment the internal error counter. */ + agent_ptr -> nx_snmp_agent_internal_errors++; + + /* Release the packet. */ + nx_packet_release(packet_ptr); + + /* Return to caller. */ + return; + } + /* Position past the empty security parameter field. */ length = 2; } @@ -19917,7 +19981,7 @@ INT buffer_length; return; } - else + else if (request_authentication_ptr) { /* Otherwise Ok to process authentication parameter. */ authenticate_message = NX_TRUE; @@ -21405,6 +21469,23 @@ INT buffer_length; /* Calculate the total variable size. */ total_variable_length = variable_length + length; + if ((length == 0) || (total_variable_length > variable_list_length) || + (total_variable_length > (UINT)buffer_length)) + { + + /* Increment the invalid packet error counter. */ + agent_ptr -> nx_snmp_agent_invalid_packets++; + + /* Release the packet. */ + nx_packet_release(packet_ptr); + + /* Release the response packet. */ + nx_packet_release(response_packet_ptr); + + /* Return to caller. */ + return; + } + /* Move the buffer pointer up. */ buffer_ptr = buffer_ptr + length; @@ -23183,7 +23264,7 @@ UCHAR report_security_level; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_add_auth_parameter PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -23226,6 +23307,9 @@ UCHAR report_security_level; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), */ +/* checked NULL pointer, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_snmp_agent_add_auth_parameter(NX_SNMP_AGENT *agent_ptr, NX_PACKET *response_packet_ptr, UCHAR *response_authentication_ptr) @@ -23235,6 +23319,11 @@ UINT i; UCHAR key1[NX_SNMP_DIGEST_WORKING_SIZE]; UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; + /* Check if the pointer is NULL. */ + if (!response_authentication_ptr) + { + return(NX_SNMP_UNSUPPORTED_AUTHENTICATION); + } /* Determine which authentication is required. */ if ((agent_ptr -> nx_snmp_agent_v3_authentication_key) && @@ -23362,7 +23451,7 @@ UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; /* FUNCTION RELEASE */ /* */ /* _nx_snmp_agent_encrypt_pdu PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -23406,6 +23495,9 @@ UCHAR key2[NX_SNMP_DIGEST_WORKING_SIZE]; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), improved */ +/* verification of encryption, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -23447,6 +23539,13 @@ UINT adjusted_pdu_length; } else { + + /* Check if the pointer is NULL. */ + if (!pdu_buffer_ptr) + { + return(NX_SNMP_INVALID_PDU_ENCRYPTION); + } + /* Set the temp ptr to where the PDU starts in the request packet. */ temp_ptr = pdu_buffer_ptr; adjusted_pdu_length = pdu_length; diff --git a/addons/sntp/nxd_sntp_client.c b/addons/sntp/nxd_sntp_client.c index b6f5fe55..c275ea54 100644 --- a/addons/sntp/nxd_sntp_client.c +++ b/addons/sntp/nxd_sntp_client.c @@ -72,8 +72,6 @@ extern volatile ULONG _tx_thread_system_state; TX_EVENT_FLAGS_GROUP nx_sntp_client_events; -static UINT _nx_sntp_client_number_to_ascii(CHAR *buffer_ptr, UINT buffer_size, UINT number); - /* Define internal time variables for offsets between receipt of SNTP packet and application to SNTP Client local time. */ @@ -2434,7 +2432,7 @@ NX_SNTP_TIME local_time; /* FUNCTION RELEASE */ /* */ /* _nx_sntp_client_receive_time_update PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2482,6 +2480,9 @@ NX_SNTP_TIME local_time; /* added support for disabling */ /* message check, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the port check, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_sntp_client_receive_time_update(NX_SNTP_CLIENT *client_ptr, ULONG timeout) @@ -2523,7 +2524,7 @@ NXD_ADDRESS source_ip_address, destination_ip_address; sender_port = (UINT)udp_header_ptr -> nx_udp_header_word_0 >> NX_SHIFT_BY_16; /* Check if this is the server port the Client expects. */ - if (sender_port != NX_SNTP_CLIENT_UDP_PORT) + if (sender_port != NX_SNTP_SERVER_UDP_PORT) { /* No, reject the packet. */ @@ -2728,7 +2729,7 @@ NXD_ADDRESS source_ip_address, destination_ip_address; /* FUNCTION RELEASE */ /* */ /* _nx_sntp_client_extract_time_message_from_packet PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2763,6 +2764,9 @@ NXD_ADDRESS source_ip_address, destination_ip_address; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), corrected*/ +/* the Reference Identifier, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_sntp_client_extract_time_message_from_packet(NX_SNTP_CLIENT *client_ptr, NX_PACKET *packet_ptr) @@ -2805,7 +2809,6 @@ NX_SNTP_TIME_MESSAGE *time_message_ptr; /* Advance to the next 32 bit field and extract the reference clock ID field. */ ntp_word_0++; - NX_CHANGE_ULONG_ENDIAN(*ntp_word_0); memcpy(time_message_ptr -> reference_clock_id, ntp_word_0, 4); /* Use case of memcpy is verified. */ /* Advance to the next field (64 bit field) and extract the reference time stamp field. */ @@ -4154,7 +4157,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_sntp_client_get_local_time_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4180,8 +4183,8 @@ UINT status; /* CALLS */ /* */ /* _nx_sntp_client_utility_fraction_to_usecs */ -/* Convert NTP fraction to usecs */ -/* _nx_sntp_client_number_to_ascii Converts number to ascii text */ +/* Convert NTP fraction to usecs */ +/* _nx_utility_uint_to_string Converts number to ascii text */ /* */ /* CALLED BY */ /* */ @@ -4195,6 +4198,10 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memmove use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_sntp_client_get_local_time_extended(NX_SNTP_CLIENT *client_ptr, ULONG *seconds, ULONG *fraction, CHAR *buffer, UINT buffer_size) @@ -4228,8 +4235,8 @@ UINT length = 0; buffer[offset++] = 'e'; buffer[offset++] = ':'; buffer[offset++] = ' '; - length = _nx_sntp_client_number_to_ascii(&buffer[offset], buffer_size - offset, - client_ptr->nx_sntp_client_local_ntp_time.seconds); + length = _nx_utility_uint_to_string(client_ptr -> nx_sntp_client_local_ntp_time.seconds, + 10, &buffer[offset], buffer_size - offset); if (length == 0) { return(NX_SIZE_ERROR); @@ -4240,7 +4247,7 @@ UINT length = 0; return(NX_SIZE_ERROR); } buffer[offset++] = '.'; - length = _nx_sntp_client_number_to_ascii(&buffer[offset], 6, usecs); + length = _nx_utility_uint_to_string(usecs, 10, &buffer[offset], buffer_size - offset); if (length == 0) { return(NX_SIZE_ERROR); @@ -4253,6 +4260,8 @@ UINT length = 0; memmove(&buffer[offset + (6 - length)], &buffer[offset], length); /* Use case of memmove is verified. */ memset(&buffer[offset], '0', (6 - length)); } + + offset += 6; buffer[offset++] = ' '; buffer[offset++] = 's'; buffer[offset++] = 'e'; @@ -4840,7 +4849,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_sntp_client_utility_display_date_time PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -4869,8 +4878,8 @@ UINT status; /* */ /* CALLS */ /* _nx_sntp_client_utility_convert_seconds_to_date */ -/* Converts seconds to year, month */ -/* _nx_sntp_client_number_to_ascii Converts number to ascii text */ +/* Converts seconds to year, month */ +/* _nx_utility_uint_to_string Converts number to ascii text */ /* */ /* CALLED BY */ /* */ @@ -4883,6 +4892,13 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the typo of August string, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_sntp_client_utility_display_date_time(NX_SNTP_CLIENT *client_ptr, CHAR *buffer, UINT length) @@ -4893,7 +4909,7 @@ UINT offset; UINT return_length; NX_SNTP_DATE_TIME DisplayTime; const CHAR *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aud", "Sep", "Oct", "Nov", "Dec"}; + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; #ifndef NX_SNTP_CURRENT_YEAR @@ -4935,48 +4951,48 @@ const CHAR *months[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", offset = 4; /* Write in the rest of the data as numeric from the Date Time objext. */ - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.day); + return_length = _nx_utility_uint_to_string(DisplayTime.day, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 2)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = ','; buffer[offset++] = ' '; - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.year); + return_length = _nx_utility_uint_to_string(DisplayTime.year, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 1)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = ' '; - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.hour); + return_length = _nx_utility_uint_to_string(DisplayTime.hour, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 1)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = ':'; - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.minute); + return_length = _nx_utility_uint_to_string(DisplayTime.minute, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 1)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = ':'; - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.second); + return_length = _nx_utility_uint_to_string(DisplayTime.second, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 1)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = '.'; - return_length = _nx_sntp_client_number_to_ascii(&buffer[offset], length - offset, DisplayTime.millisecond); + return_length = _nx_utility_uint_to_string(DisplayTime.millisecond, 10, &buffer[offset], length - offset); + offset += return_length; if ((return_length == 0) || ((length - offset) < 5)) { return NX_SNTP_ERROR_CONVERTING_DATETIME; } - offset += return_length; buffer[offset++] = ' '; buffer[offset++] = 'U'; buffer[offset++] = 'T'; @@ -6404,105 +6420,4 @@ UINT carry; /* Ok to add operands!*/ return NX_SUCCESS; -} - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_sntp_client_number_to_ascii PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function converts a number to ascii text. */ -/* */ -/* INPUT */ -/* */ -/* buffer_ptr Pointer to output string buffer */ -/* buffer_size Size of output buffer */ -/* number Number to convert to ASCII */ -/* */ -/* OUTPUT */ -/* */ -/* size Size of converted string */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_sntp_client_utility_display_date_time */ -/* Convert an NTP time */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -static UINT _nx_sntp_client_number_to_ascii(CHAR *buffer_ptr, UINT buffer_size, UINT number) -{ - -UINT i; -UINT digit; -UINT size; - - /* Initialize counters. */ - size = 0; - - /* Loop to convert the number to ASCII. */ - while (size < buffer_size) - { - - /* Shift the current digits over one. */ - for (i = size; i != 0; i--) - { - - /* Move each digit over one place. */ - buffer_ptr[i] = buffer_ptr[i - 1]; - } - - /* Compute the next decimal digit. */ - digit = (number % 10); - - /* Update the input number. */ - number = (number / 10); - - /* Store the new digit in ASCII form. */ - if (digit < 10) - { - buffer_ptr[0] = (CHAR)(digit + '0'); - } - else - { - buffer_ptr[0] = (CHAR)((digit - 10) + 'a'); - } - - /* Increment the size. */ - size++; - - /* Determine if the number is now zero. */ - if (number == 0) - break; - } - - /* Determine if there is an overflow error. */ - if (number) - { - - /* Error, return bad values to user. */ - return(0); - } - - /* Return size to caller. */ - return(size); } \ No newline at end of file diff --git a/addons/telnet/nxd_telnet_client.h b/addons/telnet/nxd_telnet_client.h index 3dbe5065..dd045c08 100644 --- a/addons/telnet/nxd_telnet_client.h +++ b/addons/telnet/nxd_telnet_client.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_telnet_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -61,6 +64,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the TELNET ID. */ #define NX_TELNET_CLIENT_ID 0x54454C4DUL diff --git a/addons/telnet/nxd_telnet_server.c b/addons/telnet/nxd_telnet_server.c index 8d24600c..b72a1ea7 100644 --- a/addons/telnet/nxd_telnet_server.c +++ b/addons/telnet/nxd_telnet_server.c @@ -595,7 +595,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_telnet_server_disconnect PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -631,6 +631,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Wenhui Xie Modified comment(s), and */ +/* corrected the processing of */ +/* disconnection, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ UINT _nx_telnet_server_disconnect(NX_TELNET_SERVER *server_ptr, UINT logical_connection) @@ -650,14 +654,6 @@ NX_TELNET_CLIENT_REQUEST *client_ptr; /* Disconnect the socket. */ nx_tcp_socket_disconnect(&(client_ptr -> nx_telnet_client_request_socket), NX_TELNET_SERVER_TIMEOUT); - /* Call the application's end connection callback routine. */ - if (server_ptr -> nx_telnet_connection_end) - { - - /* Yes, there is a connection end callback routine - call it! */ - (server_ptr -> nx_telnet_connection_end)(server_ptr, client_ptr -> nx_telnet_client_request_connection); - } - /* Unaccept this socket. */ nx_tcp_server_socket_unaccept(&(client_ptr -> nx_telnet_client_request_socket)); @@ -667,6 +663,14 @@ NX_TELNET_CLIENT_REQUEST *client_ptr; /* Clear the client request activity timeout. */ client_ptr -> nx_telnet_client_request_activity_timeout = 0; + + /* Call the application's end connection callback routine. */ + if (server_ptr -> nx_telnet_connection_end) + { + + /* Yes, there is a connection end callback routine - call it! */ + (server_ptr -> nx_telnet_connection_end)(server_ptr, client_ptr -> nx_telnet_client_request_connection); + } } else { diff --git a/addons/telnet/nxd_telnet_server.h b/addons/telnet/nxd_telnet_server.h index e6dcb16e..7af487bc 100644 --- a/addons/telnet/nxd_telnet_server.h +++ b/addons/telnet/nxd_telnet_server.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_telnet_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -45,6 +45,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -61,6 +64,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the Server TELNET ID. */ #define NX_TELNET_SERVER_ID 0x54454C4EUL diff --git a/addons/tftp/nxd_tftp_client.h b/addons/tftp/nxd_tftp_client.h index dd0fc8da..6d6e65de 100644 --- a/addons/tftp/nxd_tftp_client.h +++ b/addons/tftp/nxd_tftp_client.h @@ -27,7 +27,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_tftp_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -62,6 +65,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the NetX TFTP CLIENT ID. */ #define NXD_TFTP_CLIENT_ID 0x54465460UL diff --git a/addons/tftp/nxd_tftp_server.c b/addons/tftp/nxd_tftp_server.c index e0f58612..207dad8e 100644 --- a/addons/tftp/nxd_tftp_server.c +++ b/addons/tftp/nxd_tftp_server.c @@ -1074,7 +1074,7 @@ ULONG events; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_process_received_data PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1115,6 +1115,10 @@ ULONG events; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), improved */ +/* the logic of processing */ +/* chained packet, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_tftp_server_process_received_data(NX_TFTP_SERVER *server_ptr) @@ -1122,8 +1126,8 @@ VOID _nx_tftp_server_process_received_data(NX_TFTP_SERVER *server_ptr) UINT status; NX_PACKET *packet_ptr; -UCHAR *buffer_ptr; -UCHAR request_code; +UCHAR request_code[2]; +ULONG bytes_copyed; /* Wait for a request on the TFTP UDP well known port 69. */ @@ -1150,26 +1154,19 @@ UCHAR request_code; /* Otherwise, we have received a packet successfully. */ - /* Setup a pointer to packet buffer area. */ - buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; - - /* Pickup up the request code. First one must be zero. */ - request_code = *buffer_ptr++; + /* Pickup up the request code. First one must be zero. */ + status = nx_packet_data_extract_offset(packet_ptr, 0, request_code, sizeof(request_code), &bytes_copyed); - /* If not zero, abort. */ - if (request_code) + /* Check the return status. */ + if (status || (request_code[0] != 0)) { - nx_packet_release(packet_ptr); - + nx_packet_release(packet_ptr); return; } - /* Now get the actual request code. */ - request_code = *buffer_ptr++; - /* Process relative to the TFTP request code. */ - switch (request_code) + switch (request_code[1]) { case NX_TFTP_CODE_READ: @@ -1233,7 +1230,7 @@ UCHAR request_code; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_open_for_read_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1277,6 +1274,14 @@ UCHAR request_code; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), */ +/* checked the format of the */ +/* received packet, improved */ +/* the logic of processing */ +/* chained packet, fixed the */ +/* issue of cleaning up the */ +/* client request entry, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ void _nx_tftp_server_open_for_read_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr) @@ -1289,6 +1294,7 @@ UCHAR *buffer_ptr; NX_TFTP_CLIENT_REQUEST *client_request_ptr; NX_PACKET *new_packet = NX_NULL; UINT status; +UINT count = 0; /* Extract the source IP and port numbers. */ @@ -1327,64 +1333,46 @@ UINT status; return; } - /* Initialize the client request structure. */ -#ifndef NX_DISABLE_IPV4 - if (ip_address.nxd_ip_version == NX_IP_VERSION_V4) - { - - client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_version = NX_IP_VERSION_V4; - client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4; - } - else -#endif /* NX_DISABLE_IPV4 */ -#ifdef FEATURE_NX_IPV6 - if (ip_address.nxd_ip_version == NX_IP_VERSION_V6) - { - COPY_NXD_ADDRESS(&ip_address, &(client_request_ptr ->nx_tftp_client_request_ip_address)); - } - else -#endif + /* Packet chain isn't supported. */ +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) { - /* Release the original packet. */ nx_packet_release(packet_ptr); - return; } - - - client_request_ptr -> nx_tftp_client_request_port = port; - client_request_ptr -> nx_tftp_client_request_block_number = 1; - client_request_ptr -> nx_tftp_client_request_open_type = NX_TFTP_STATE_OPEN; - client_request_ptr -> nx_tftp_client_request_exact_fit = NX_FALSE; - -#ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE - - /* Reset the retransmission timeout and retries for the client request. */ - client_request_ptr -> nx_tftp_client_retransmit_timeout = NX_TFTP_SERVER_RETRANSMIT_TIMEOUT; - client_request_ptr -> nx_tftp_client_retransmit_retries = 0; -#else - - /* Clear the count of ACK retransmits from the other side. */ - client_request_ptr -> nx_tftp_client_request_retransmits = 0; - -#endif +#endif /* NX_DISABLE_PACKET_CHAIN */ /* Setup a pointer to the file name. */ buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); - if (packet_ptr -> nx_packet_length < 4) + /* The format of RRQ/WRQ packet should be: + 2 bytes string 1 byte string 1 byte + ------------------------------------------------ + | Opcode | Filename | 0 | Mode | 0 | + ------------------------------------------------ + */ + while (buffer_ptr < (packet_ptr -> nx_packet_append_ptr - 1)) { - nx_packet_release(packet_ptr); - return; + if (*buffer_ptr == 0) + { + count++; + if (count == 2) + break; + } + + buffer_ptr++; } - /* Check if the packet buffer ends with NULL. */ - if (*(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1)) + /* Check if the format of the termination is correct. */ + if ((count != 1) || *(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1)) { nx_packet_release(packet_ptr); return; } + /* Reset the pointer to the file name. */ + buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); + /* Pickup the file size. */ status = fx_directory_information_get(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr, NX_NULL, &file_size, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL); @@ -1449,6 +1437,47 @@ UINT status; return; } + /* Initialize the client request structure. */ +#ifndef NX_DISABLE_IPV4 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V4) + { + + client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_version = NX_IP_VERSION_V4; + client_request_ptr ->nx_tftp_client_request_ip_address.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4; + } + else +#endif /* NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V6) + { + COPY_NXD_ADDRESS(&ip_address, &(client_request_ptr ->nx_tftp_client_request_ip_address)); + } + else +#endif + { + /* Release the original packet. */ + nx_packet_release(packet_ptr); + + return; + } + + client_request_ptr -> nx_tftp_client_request_port = port; + client_request_ptr -> nx_tftp_client_request_block_number = 1; + client_request_ptr -> nx_tftp_client_request_open_type = NX_TFTP_STATE_OPEN; + client_request_ptr -> nx_tftp_client_request_exact_fit = NX_FALSE; + +#ifdef NX_TFTP_SERVER_RETRANSMIT_ENABLE + + /* Reset the retransmission timeout and retries for the client request. */ + client_request_ptr -> nx_tftp_client_retransmit_timeout = NX_TFTP_SERVER_RETRANSMIT_TIMEOUT; + client_request_ptr -> nx_tftp_client_retransmit_retries = 0; +#else + + /* Clear the count of ACK retransmits from the other side. */ + client_request_ptr -> nx_tftp_client_request_retransmits = 0; + +#endif + client_request_ptr -> nx_tftp_client_file_size = file_size; /* Read data when length of file is larger then 0. */ @@ -1470,6 +1499,8 @@ UINT status; /* Unable to read the file, close it and release the packet. */ fx_file_close(&(client_request_ptr ->nx_tftp_client_request_file)); + memset(client_request_ptr, 0, sizeof(NX_TFTP_CLIENT_REQUEST)); + nx_packet_release(packet_ptr); return; } @@ -1532,7 +1563,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_open_for_write_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1576,6 +1607,12 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), */ +/* checked the format of the */ +/* received packet, improved */ +/* the logic of processing */ +/* chained packet, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_tftp_server_open_for_write_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr) @@ -1586,6 +1623,7 @@ UCHAR *buffer_ptr; NX_TFTP_CLIENT_REQUEST *client_request_ptr; NX_PACKET *new_packet; UINT status; +UINT count = 0; /* Extract the source IP and port numbers. */ @@ -1624,22 +1662,46 @@ UINT status; return; } + /* Packet chain isn't supported. */ +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) + { + nx_packet_release(packet_ptr); + return; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + /* Setup a pointer to the file name. */ buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); - if (packet_ptr -> nx_packet_length < 4) + /* The format of RRQ/WRQ packet should be: + 2 bytes string 1 byte string 1 byte + ------------------------------------------------ + | Opcode | Filename | 0 | Mode | 0 | + ------------------------------------------------ + */ + while (buffer_ptr < (packet_ptr -> nx_packet_append_ptr - 1)) { - nx_packet_release(packet_ptr); - return; + if (*buffer_ptr == 0) + { + count++; + if (count == 2) + break; + } + + buffer_ptr++; } - /* Check if the packet buffer ends with NULL. */ - if (*(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1)) + /* Check if the format of the termination is correct. */ + if ((count != 1) || *(UCHAR *)(packet_ptr -> nx_packet_append_ptr - 1)) { nx_packet_release(packet_ptr); return; } + /* Reset the pointer to the file name. */ + buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); + /* Perform a file create. This will fail if the file is already present, which we don't care about at this point. */ fx_file_delete(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr); fx_file_create(server_ptr -> nx_tftp_server_media_ptr, (CHAR *) buffer_ptr); @@ -1776,7 +1838,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_data_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1819,6 +1881,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), improved */ +/* the logic of processing */ +/* chained packet, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_tftp_server_data_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr) @@ -1827,7 +1893,7 @@ VOID _nx_tftp_server_data_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet NXD_ADDRESS ip_address; UINT port; USHORT block_number; -UCHAR *buffer_ptr; +ULONG bytes_copyed; NX_TFTP_CLIENT_REQUEST *client_request_ptr; UINT status; @@ -1854,18 +1920,18 @@ UINT status; return; } - /* Setup a pointer to the block number. */ - buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); + /* Pickup the block number. */ + status = nx_packet_data_extract_offset(packet_ptr, 2, (UCHAR *)&block_number, sizeof(block_number), &bytes_copyed); - if (packet_ptr -> nx_packet_length < 4) + /* Check return status. */ + if (status || (bytes_copyed != 2)) { nx_packet_release(packet_ptr); return; } - /* Pickup the block number. */ - block_number = (USHORT)(*buffer_ptr++); - block_number = (USHORT)((block_number << 8) | (*buffer_ptr)); + /* Adjust the endianness. */ + NX_CHANGE_USHORT_ENDIAN(block_number); /* Determine if this block number matches the current client block number. */ if (client_request_ptr -> nx_tftp_client_request_block_number != block_number) @@ -2026,7 +2092,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_ack_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2069,6 +2135,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), improved */ +/* the logic of processing */ +/* chained packet, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_tftp_server_ack_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr) @@ -2077,8 +2147,9 @@ VOID _nx_tftp_server_ack_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ NXD_ADDRESS ip_address; UINT port; USHORT block_number; -UCHAR *buffer_ptr; +ULONG bytes_copyed; NX_TFTP_CLIENT_REQUEST *client_request_ptr; +UINT status; /* Extract the source IP and port numbers. */ @@ -2103,18 +2174,18 @@ NX_TFTP_CLIENT_REQUEST *client_request_ptr; return; } - /* Setup a pointer to the block number. */ - buffer_ptr = (UCHAR *) (packet_ptr -> nx_packet_prepend_ptr + 2); + /* Pickup the block number. */ + status = nx_packet_data_extract_offset(packet_ptr, 2, (UCHAR *)&block_number, sizeof(block_number), &bytes_copyed); - if (packet_ptr -> nx_packet_length < 4) + /* Check return status. */ + if (status || (bytes_copyed != 2)) { nx_packet_release(packet_ptr); return; } - /* Pickup the block number. */ - block_number = (USHORT)(*buffer_ptr++); - block_number = (USHORT)((block_number << 8) | (*buffer_ptr)); + /* Adjust the endianness. */ + NX_CHANGE_USHORT_ENDIAN(block_number); /* Determine if this block number matches the request. */ if (client_request_ptr -> nx_tftp_client_request_block_number != block_number) @@ -2536,7 +2607,7 @@ NX_PACKET *new_packet; /* FUNCTION RELEASE */ /* */ /* _nx_tftp_server_error_process PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2570,6 +2641,10 @@ NX_PACKET *new_packet; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), improved */ +/* the logic of processing */ +/* chained packet, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_tftp_server_error_process(NX_TFTP_SERVER *server_ptr, NX_PACKET *packet_ptr) @@ -2581,15 +2656,17 @@ UINT port; NXD_ADDRESS ip_address; NX_TFTP_CLIENT_REQUEST *client_request_ptr; - - /* Pickup a pointer to the error code in the buffer. */ - buffer_ptr = packet_ptr -> nx_packet_prepend_ptr + 2; - - if (packet_ptr -> nx_packet_length < 4) + /* Packet chain isn't supported. */ +#ifndef NX_DISABLE_PACKET_CHAIN + if (packet_ptr -> nx_packet_next) { nx_packet_release(packet_ptr); return; } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* Pickup a pointer to the error code in the buffer. */ + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr + 2; /* Set the error code in the server control block. */ server_ptr -> nx_tftp_server_error_code = (((UINT) (*buffer_ptr)) << 8); diff --git a/addons/tftp/nxd_tftp_server.h b/addons/tftp/nxd_tftp_server.h index 526eed43..ececc41c 100644 --- a/addons/tftp/nxd_tftp_server.h +++ b/addons/tftp/nxd_tftp_server.h @@ -27,7 +27,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nxd_tftp_server.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ @@ -62,6 +65,8 @@ extern "C" { #endif +#include "nx_api.h" + /* Define the TFTP ID. */ #define NXD_TFTP_SERVER_ID 0x54465461UL diff --git a/addons/web/nx_tcpserver.c b/addons/web/nx_tcpserver.c index 3619c940..409d2d72 100644 --- a/addons/web/nx_tcpserver.c +++ b/addons/web/nx_tcpserver.c @@ -128,7 +128,7 @@ NX_TCP_SOCKET *socket_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_tcpserver_relisten PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -164,6 +164,9 @@ NX_TCP_SOCKET *socket_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* removed debug output, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ static UINT _nx_tcpserver_relisten(NX_TCPSERVER *server_ptr) @@ -187,7 +190,6 @@ NX_TCP_SESSION *session_ptr; &session_ptr -> nx_tcp_session_socket); if((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING)) { - printf("%d, %d\n", status, __LINE__); return NX_TCPSERVER_FAIL; } @@ -202,7 +204,6 @@ NX_TCP_SESSION *session_ptr; &server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_socket); if((status != NX_SUCCESS) && (status != NX_CONNECTION_PENDING)) { - printf("%d, %d\n", status, __LINE__); return NX_TCPSERVER_FAIL; } } @@ -351,7 +352,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_tcpserver_tls_setup PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -435,6 +436,10 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the index of the */ +/* remote certificate list, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -529,7 +534,7 @@ UINT status; for(cert_count = 0; cert_count < remote_certs_num; ++cert_count) { /* Allocate a remote certificate from the provided array. */ - status = nx_secure_tls_remote_certificate_allocate(tls_session, remote_certificates[i], + status = nx_secure_tls_remote_certificate_allocate(tls_session, remote_certificates[cert_count], session_cert_buffer, session_cert_buffer_size); if(status != NX_SUCCESS) @@ -547,6 +552,72 @@ UINT status; } return(NX_SUCCESS); } + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcpserver_tls_ecc_setup PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function configures supported curve lists for NetX socket */ +/* server instance using TLS. */ +/* */ +/* INPUT */ +/* */ +/* server_ptr Pointer to control block */ +/* supported_groups List of supported groups */ +/* supported_group_count Number of supported groups */ +/* curves List of curve methods */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_secure_tls_ecc_initialize Initializes curve lists for TLS*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +UINT _nx_tcpserver_tls_ecc_setup(NX_TCPSERVER *server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves) +{ +UINT i; +UINT status; +NX_SECURE_TLS_SESSION* tls_session; + + /* Loop through all sessions, initialize each one. */ + for (i = 0; i < server_ptr -> nx_tcpserver_sessions_count; ++i) + { + + tls_session = &(server_ptr -> nx_tcpserver_sessions[i].nx_tcp_session_tls_session); + status = nx_secure_tls_ecc_initialize(tls_session, supported_groups, supported_group_count, curves); + if (status != NX_SUCCESS) + { + return(status); + } + } + + return(NX_SUCCESS); +} +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #endif /**************************************************************************/ @@ -832,7 +903,7 @@ NX_TCPSERVER *server_ptr = (NX_TCPSERVER *)tcpserver_address; /* FUNCTION RELEASE */ /* */ /* _nx_tcpserver_connect_process PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -872,6 +943,14 @@ NX_TCPSERVER *server_ptr = (NX_TCPSERVER *)tcpserver_address; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* fixed packet leak issue, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed TLS connection */ +/* deadlock issue, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the wait option */ +/* of TLS connection, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static VOID _nx_tcpserver_connect_process(NX_TCPSERVER *server_ptr) @@ -936,11 +1015,12 @@ NX_TCP_SESSION *session_ptr = NX_NULL; if(server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_using_tls == NX_TRUE) { status = nx_secure_tls_session_start(&server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_tls_session, - &server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_socket, NX_WAIT_FOREVER); + &server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_socket, server_ptr -> nx_tcpserver_timeout * NX_IP_PERIODIC_RATE); if(status != NX_SUCCESS) { nx_secure_tls_session_end(&server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_tls_session, NX_WAIT_FOREVER); + nx_tcp_socket_disconnect(&server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_socket, NX_NO_WAIT); nx_tcp_server_socket_unaccept(&server_ptr -> nx_tcpserver_listen_session -> nx_tcp_session_socket); } } diff --git a/addons/web/nx_tcpserver.h b/addons/web/nx_tcpserver.h index 88947295..41f4c1a8 100644 --- a/addons/web/nx_tcpserver.h +++ b/addons/web/nx_tcpserver.h @@ -24,7 +24,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_tcpserver.h PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -42,6 +42,12 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* fixed packet leak issue, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* deprecated unused macros, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* supported ECC configuration,*/ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -60,14 +66,17 @@ #include "nx_secure_tls_api.h" #endif /* NX_WEB_HTTPS_ENABLE */ +/* Deprecated. This symbol is defined for compatibility. */ #ifndef NX_TCPSERVER_ACCEPT_WAIT #define NX_TCPSERVER_ACCEPT_WAIT 1 #endif /* NX_TCPSERVER_ACCEPT_WAIT */ +/* Deprecated. This symbol is defined for compatibility. */ #ifndef NX_TCPSERVER_DISCONNECT_WAIT #define NX_TCPSERVER_DISCONNECT_WAIT 1 #endif /* NX_TCPSERVER_DISCONNECT_WAIT */ +/* Deprecated. This symbol is defined for compatibility. */ #ifndef NX_TCPSERVER_PRIORITY #define NX_TCPSERVER_PRIORITY 4 #endif /* NX_TCPSERVER_PRIORITY */ @@ -142,6 +151,9 @@ typedef struct NX_TCPSERVER_STRUCT #define nx_tcpserver_delete _nx_tcpserver_delete #ifdef NX_TCPSERVER_ENABLE_TLS #define nx_tcpserver_tls_setup _nx_tcpserver_tls_setup +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +#define nx_tcpserver_tls_ecc_setup _nx_tcpserver_tls_ecc_setup +#endif #endif #ifdef NX_TCPSERVER_ENABLE_TLS @@ -149,6 +161,11 @@ UINT nx_tcpserver_tls_setup(NX_TCPSERVER *server_ptr, const NX_SECURE_TLS_CRYPTO VOID *metadata_buffer, ULONG metadata_size, UCHAR* packet_buffer, UINT packet_buffer_size, NX_SECURE_X509_CERT *identity_certificate, NX_SECURE_X509_CERT *trusted_certificates[], UINT trusted_certs_num, NX_SECURE_X509_CERT *remote_certificates[], UINT remote_certs_num, UCHAR *remote_certificate_buffer, UINT remote_cert_buffer_size); +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +UINT nx_tcpserver_tls_ecc_setup(NX_TCPSERVER *server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves); +#endif #endif UINT nx_tcpserver_create(NX_IP *ip_ptr, NX_TCPSERVER *server_ptr, CHAR *name, @@ -174,6 +191,11 @@ UINT _nx_tcpserver_tls_setup(NX_TCPSERVER *server_ptr, const NX_SECURE_TLS_CRYPT VOID *metadata_buffer, ULONG metadata_size, UCHAR* packet_buffer, UINT packet_buffer_size, NX_SECURE_X509_CERT *identity_certificate, NX_SECURE_X509_CERT *trusted_certificates[], UINT trusted_certs_num, NX_SECURE_X509_CERT *remote_certificates[], UINT remote_certs_num, UCHAR *remote_certificate_buffer, UINT remote_cert_buffer_size); +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +UINT _nx_tcpserver_tls_ecc_setup(NX_TCPSERVER *server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves); +#endif #endif UINT _nx_tcpserver_create(NX_IP *ip_ptr, NX_TCPSERVER *server_ptr, CHAR *name, diff --git a/addons/web/nx_web_http_client.c b/addons/web/nx_web_http_client.c index c6207447..d5becc3c 100644 --- a/addons/web/nx_web_http_client.c +++ b/addons/web/nx_web_http_client.c @@ -43,12 +43,6 @@ /* Define global HTTPS variables and strings. */ - -/* Define the Base64 array that is used to build username and passwords for Basic authentication. Indexing - into this array yields the base64 representation of the 6bit number. */ - -CHAR _nx_web_http_client_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - /* Define status maps. */ static NX_WEB_HTTP_CLIENT_STATUS_MAP _nx_web_http_client_status_maps[] = { @@ -1511,7 +1505,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_client_response_body_get PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -1557,6 +1551,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* released invalid packet, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_web_http_client_response_body_get(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET **packet_pptr, ULONG wait_option) @@ -1592,6 +1589,9 @@ UINT status_code = NX_SUCCESS; { if (response_packet_ptr -> nx_packet_append_ptr - response_packet_ptr -> nx_packet_prepend_ptr < 12) { + + /* Release invalid packet. */ + nx_packet_release(response_packet_ptr); status = NX_WEB_HTTP_ERROR; } } @@ -2614,7 +2614,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_client_request_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2651,6 +2651,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the invalid release issue, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_web_http_client_request_packet_send(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT more_data, ULONG wait_option) @@ -2693,9 +2696,6 @@ UINT length = packet_ptr -> nx_packet_length; /* No, send was not successful. */ - /* Release the packet. */ - nx_packet_release(packet_ptr); - /* Disconnect and unbind the socket. */ _nx_web_http_client_error_exit(client_ptr, wait_option); @@ -5824,7 +5824,7 @@ UINT header_size; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_client_put_packet PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5863,6 +5863,9 @@ UINT header_size; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the invalid release issue, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_web_http_client_put_packet(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option) @@ -5943,9 +5946,6 @@ UINT status; { /* No, send was not successful. */ - - /* Release the packet. */ - nx_packet_release(packet_ptr); /* Disconnect and unbind the socket. */ _nx_web_http_client_error_exit(client_ptr, wait_option); @@ -6647,138 +6647,6 @@ UINT size; return(size); } - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_web_http_client_base64_encode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function encodes the input string into a base64 */ -/* representation. */ -/* */ -/* INPUT */ -/* */ -/* name Name string */ -/* length Length of name */ -/* base64name Encoded base64 name string */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* _nx_utility_string_length_check Check string length */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_web_http_client_get_start Start GET processing */ -/* _nx_web_http_client_put_start Start PUT processing */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_web_http_client_base64_encode(CHAR *name, UINT length, CHAR *base64name) -{ - -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - - /* Default padding to none. */ - pad = 0; - - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) - { - - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; - } - - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) - { - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first 6 bits of name character for index. */ - base64name[j++] = _nx_web_http_client_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) - { - - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = _nx_web_http_client_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; - } - else if (step == 2) - { - - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = _nx_web_http_client_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ - { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = _nx_web_http_client_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; - } - } - - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < NX_WEB_HTTP_MAX_STRING)) - { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; - } - - /* Put a NULL character in. */ - base64name[j] = NX_NULL; -} - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -6845,7 +6713,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_web_https_client_connect PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6892,6 +6760,9 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), */ +/* supported non-blocking mode,*/ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ UINT _nx_web_http_client_connect(NX_WEB_HTTP_CLIENT *client_ptr, NXD_ADDRESS *server_ip, UINT server_port, ULONG wait_option) @@ -6936,13 +6807,21 @@ UINT status; status = nx_tcp_client_socket_bind(&(client_ptr -> nx_web_http_client_socket), NX_ANY_PORT, wait_option); /* Check status of the bind. */ - if (status != NX_SUCCESS) + if ((status != NX_SUCCESS) && (status != NX_ALREADY_BOUND)) { /* Error binding to a port, return to caller. */ return(status); } + /* Set the server IP and port. */ +#ifdef FEATURE_NX_IPV6 + COPY_NXD_ADDRESS(server_ip, &(client_ptr -> nx_web_http_client_server_address)); +#else + client_ptr -> nx_web_http_client_server_address.nxd_ip_version = NX_IP_VERSION_V4; + client_ptr -> nx_web_http_client_server_address.nxd_ip_address.v4 = server_ip -> nxd_ip_address.v4; +#endif + client_ptr -> nx_web_http_client_connect_port = server_port; /* Connect to the HTTPS server with TCP. */ @@ -6950,23 +6829,14 @@ UINT status; client_ptr -> nx_web_http_client_connect_port, wait_option); /* Check for connection status. */ - if (status != NX_SUCCESS) + if ((status != NX_SUCCESS) && (status != NX_IN_PROGRESS)) { /* Error, unbind the port and return an error. */ nx_tcp_client_socket_unbind(&(client_ptr -> nx_web_http_client_socket)); - return(status); } - /* At this point, the TCP socket to the remote HTTP server is connected. */ -#ifdef FEATURE_NX_IPV6 - COPY_NXD_ADDRESS(server_ip, &(client_ptr -> nx_web_http_client_server_address)); -#else - client_ptr -> nx_web_http_client_server_address.nxd_ip_version = NX_IP_VERSION_V4; - client_ptr -> nx_web_http_client_server_address.nxd_ip_address.v4 = server_ip -> nxd_ip_address.v4; -#endif - - return(NX_SUCCESS); + return(status); } #ifdef NX_WEB_HTTPS_ENABLE @@ -7471,7 +7341,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_client_request_initialize_extended PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7528,6 +7398,10 @@ UINT status; /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_web_http_client_request_initialize_extended(NX_WEB_HTTP_CLIENT *client_ptr, @@ -7741,10 +7615,7 @@ UINT string2_length; string1[username_length + password_length + 1] = NX_NULL; /* Now encode the username:password string. */ - _nx_web_http_client_base64_encode(string1, username_length + password_length + 1, string2); - - /* Check string length. */ - _nx_utility_string_length_check(string2, &string2_length, NX_WEB_HTTP_MAX_STRING); + _nx_utility_base64_encode((UCHAR *)string1, username_length + password_length + 1, (UCHAR *)string2, sizeof(string2), &string2_length); nx_packet_data_append(packet_ptr, string2, string2_length, client_ptr -> nx_web_http_client_packet_pool_ptr, wait_option); nx_packet_data_append(packet_ptr, crlf, 2, client_ptr -> nx_web_http_client_packet_pool_ptr, wait_option); } diff --git a/addons/web/nx_web_http_client.h b/addons/web/nx_web_http_client.h index 23bcfa9d..1c2adec0 100644 --- a/addons/web/nx_web_http_client.h +++ b/addons/web/nx_web_http_client.h @@ -27,7 +27,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_web_http_client.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -632,7 +636,6 @@ UINT _nx_web_http_client_type_get(CHAR *name, CHAR *http_type_string); UINT _nx_web_http_client_content_length_get(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr); UINT _nx_web_http_client_process_header_fields(NX_WEB_HTTP_CLIENT *client_ptr, NX_PACKET *packet_ptr); UINT _nx_web_http_client_number_convert(UINT number, CHAR *string); -VOID _nx_web_http_client_base64_encode(CHAR *name, UINT length, CHAR *base64name); UINT _nx_web_http_client_content_type_header_add(NX_WEB_HTTP_CLIENT *client_ptr, CHAR *resource, ULONG wait_option); UINT _nx_web_http_client_content_length_header_add(NX_WEB_HTTP_CLIENT *client_ptr, ULONG total_bytes, ULONG wait_option); VOID _nx_web_http_client_error_exit(NX_WEB_HTTP_CLIENT *client_ptr, UINT wait_option); diff --git a/addons/web/nx_web_http_common.h b/addons/web/nx_web_http_common.h index a2340a7e..abe3e02b 100644 --- a/addons/web/nx_web_http_common.h +++ b/addons/web/nx_web_http_common.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_web_http_common.h PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ @@ -103,8 +107,8 @@ extern "C" { #define NX_PHYSICAL_TRAILER 4 #endif -/* NX_WEB_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed. */ -#define NX_WEB_HTTP_MAX_STRING ((NX_WEB_HTTP_MAX_NAME + NX_WEB_HTTP_MAX_PASSWORD + 1 ) * 4 / 3 + 1) +/* NX_WEB_HTTP_MAX_STRING is base64 of "name:password" and plus 1 if an extra conversion is needed and plus 2 pad if needed.. */ +#define NX_WEB_HTTP_MAX_STRING ((NX_WEB_HTTP_MAX_NAME + NX_WEB_HTTP_MAX_PASSWORD + 1 ) * 4 / 3 + 1 + 2) #define NX_WEB_HTTP_MAX_BINARY_MD5 16 #define NX_WEB_HTTP_MAX_ASCII_MD5 32 diff --git a/addons/web/nx_web_http_server.c b/addons/web/nx_web_http_server.c index 1110019e..7e2c5837 100644 --- a/addons/web/nx_web_http_server.c +++ b/addons/web/nx_web_http_server.c @@ -46,17 +46,10 @@ #error "Content length needed when keepalive is enabled" #endif /* NX_WEB_HTTP_SERVER_OMIT_CONTENT_LENGTH */ -/* Define the Base64 array that is used to build username and passwords for Basic authentication. Indexing - into this array yields the base64 representation of the 6bit number. */ - -CHAR _nx_web_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - #ifdef NX_WEB_HTTP_DIGEST_ENABLE -/* Define the default nonce, used only for MD5 authentication. For security reasons, this ASCII value should - change over time. */ -CHAR _nx_web_http_server_nonce[] = "a4b8c8d7e0f6a7b2c3d2e4f5a4b7c5d2e7f"; +/* Use for mapping random nonces to printable characters. */ +static CHAR _nx_web_http_server_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; #endif /* Define date strings. */ @@ -277,7 +270,7 @@ UINT _nxe_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER *server_ptr, N /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_packet_content_find PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -324,6 +317,9 @@ UINT _nxe_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER *server_ptr, N /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_packet_content_find(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG *content_length) @@ -398,6 +394,12 @@ ULONG temp_offset; (*packet_ptr) = (*packet_ptr) -> nx_packet_next; } + /* Chack if packet is valid. */ + if ((*packet_ptr) == NX_NULL) + { + return(NX_WEB_HTTP_BAD_PACKET_LENGTH); + } + /* If this packet contain no content, set next packet as the first packet of the content. */ if (temp_offset == (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr)) { @@ -2189,8 +2191,8 @@ UINT status; /* */ /* FUNCTION RELEASE */ /* */ -/* _nxe_web_http_server_secure_configure PORTABLE C */ -/* 6.1 */ +/* _nx_web_http_server_secure_configure PORTABLE C */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -2258,6 +2260,8 @@ UINT status; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_server_ptr, const NX_SECURE_TLS_CRYPTO *crypto_table, @@ -2289,6 +2293,120 @@ UINT status; return(status); } +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_web_http_server_secure_ecc_configure PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the HTTPS ECC configuration call.*/ +/* */ +/* INPUT */ +/* */ +/* http_server_ptr Pointer to HTTP server */ +/* supported_groups List of supported groups */ +/* supported_group_count Number of supported groups */ +/* curves List of curve methods */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_web_http_server_secure_ecc_configure */ +/* Actual ECC configuration call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +UINT _nxe_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves) +{ +UINT status; + + /* Check for invalid input pointers. */ + if ((http_server_ptr == NX_NULL) || (http_server_ptr -> nx_web_http_server_id != NX_WEB_HTTP_SERVER_ID) || + (supported_groups == NX_NULL) || (supported_group_count == 0) || (curves == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual ECC configuration function. */ + status = _nx_web_http_server_secure_ecc_configure(http_server_ptr, supported_groups, supported_group_count, curves); + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_web_http_server_secure_ecc_configure PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function configures supported curve lists for NetX Web HTTP */ +/* server instance using TLS. */ +/* */ +/* INPUT */ +/* */ +/* http_server_ptr Pointer to HTTP server */ +/* supported_groups List of supported groups */ +/* supported_group_count Number of supported groups */ +/* curves List of curve methods */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_tcpserver_tls_ecc_setup Socket server ECC configure */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +UINT _nx_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves) +{ +UINT status; + + /* Configure TLS ECC for the socket server. */ + status = nx_tcpserver_tls_ecc_setup(&http_server_ptr -> nx_web_http_server_tcpserver, + supported_groups, supported_group_count, curves); + return(status); +} +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + #endif /* NX_WEB_HTTPS_ENABLE */ /**************************************************************************/ @@ -2997,7 +3115,7 @@ NX_WEB_HTTP_SERVER *server_ptr; /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_web_http_server_connection_present PORTABLE C */ +/* _nx_web_http_server_receive_data PORTABLE C */ /* 6.1 */ /* AUTHOR */ /* */ @@ -5034,7 +5152,7 @@ NX_PACKET *packet_ptr; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_basic_authenticate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5085,6 +5203,14 @@ NX_PACKET *packet_ptr; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the issue of processing */ +/* empty password, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_basic_authenticate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT *auth_request_present) @@ -5097,6 +5223,7 @@ CHAR crlf[2] = {13,10}; UINT match; UINT realm_length; UINT length; +UINT authorization_decoded_size; /* Default to no authentication request detected. */ *auth_request_present = NX_FALSE; @@ -5117,14 +5244,14 @@ UINT length; *auth_request_present = NX_TRUE; /* Convert the request from Base64 representation to ASCII. */ - _nx_web_http_base64_decode(authorization_request, length, authorization_decoded); + _nx_utility_base64_decode((UCHAR *)authorization_request, length, (UCHAR *)authorization_decoded, sizeof(authorization_decoded), &authorization_decoded_size); /* See if it is valid. */ /* Compare the name. */ i = 0; match = NX_TRUE; - while (name_ptr[i] && (i < sizeof(authorization_decoded))) + while (name_ptr[i] && (i < authorization_decoded_size)) { /* Is there a mismatch? */ @@ -5140,7 +5267,7 @@ UINT length; } /* Determine if everything matches. */ - if (match && (i < sizeof(authorization_decoded)) && (authorization_decoded[i] == ':')) + if (match && (i < authorization_decoded_size) && (authorization_decoded[i] == ':')) { /* Move the authorization index past the semicolon. */ @@ -5149,7 +5276,7 @@ UINT length; /* Now compare the passwords. */ j = 0; match = NX_TRUE; - while (password_ptr[j] && (i < sizeof(authorization_decoded))) + while (password_ptr[j] && (i < authorization_decoded_size)) { /* Is there a mismatch? */ @@ -5166,7 +5293,9 @@ UINT length; } /* Determine if we have a match. */ - if (match && (i < sizeof(authorization_decoded)) && (authorization_decoded[i] == (CHAR) NX_NULL)) + if (match && (i == authorization_decoded_size) && + (authorization_decoded[i] == (CHAR) NX_NULL) && + (password_ptr[j] == (CHAR) NX_NULL)) { /* Yes, we have successful authorization!! */ @@ -5260,7 +5389,7 @@ UINT length; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_retrieve_basic_authorization PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -5297,6 +5426,10 @@ UINT length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the HTTP Server state issue */ +/* with basic authorization, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr) @@ -5362,6 +5495,9 @@ CHAR *buffer_ptr; return(length); } + /* Set the found flag back to false. */ + found = NX_FALSE; + /* Now remove any extra blanks. */ while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' ')) { @@ -5757,105 +5893,6 @@ UINT crlf_found = 0; } -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_web_http_server_number_convert PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function converts a number into an ASCII string. */ -/* */ -/* INPUT */ -/* */ -/* number Unsigned integer number */ -/* string Destination string */ -/* */ -/* OUTPUT */ -/* */ -/* Size Number of bytes in string */ -/* (0 implies an error) */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_web_http_server_get_process Process GET request */ -/* _nx_web_http_server_response_send Send response to client */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -UINT _nx_web_http_server_number_convert(UINT number, CHAR *string) -{ - -UINT j; -UINT digit; -UINT size; - - - /* Initialize counters. */ - size = 0; - - /* Loop to convert the number to ASCII. */ - while (size < 10) - { - - /* Shift the current digits over one. */ - for (j = size; j != 0; j--) - { - - /* Move each digit over one place. */ - string[j] = string[j-1]; - } - - /* Compute the next decimal digit. */ - digit = number % 10; - - /* Update the input number. */ - number = number / 10; - - /* Store the new digit in ASCII form. */ - string[0] = (CHAR) (digit + 0x30); - - /* Increment the size. */ - size++; - - /* Determine if the number is now zero. */ - if (number == 0) - break; - } - - /* Make the string NULL terminated. */ - string[size] = (CHAR) NX_NULL; - - /* Determine if there is an overflow error. */ - if (number) - { - - /* Error, return bad values to user. */ - size = 0; - string[0] = '0'; - } - - /* Return size to caller. */ - return(size); -} - - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -6223,26 +6260,26 @@ UINT temp_name_length; } +#ifdef NX_WEB_HTTP_DIGEST_ENABLE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_web_http_base64_encode PORTABLE C */ -/* 6.1 */ +/* _nx_web_http_server_nonce_allocate PORTABLE C */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function encodes the input string into a base64 */ -/* representation. */ +/* This function allocate a new nonce for digest authentication. */ /* */ /* INPUT */ /* */ -/* name Name string */ -/* name Length of name */ -/* base64name Encoded base64 name string */ +/* server_ptr HTTP Server pointer */ +/* nonce_ptr Allocated nonce pointer */ /* */ /* OUTPUT */ /* */ @@ -6250,241 +6287,82 @@ UINT temp_name_length; /* */ /* CALLS */ /* */ -/* _nx_utility_string_length_check Check string length */ +/* tx_time_get Get system time */ /* */ /* CALLED BY */ /* */ -/* None */ +/* _nx_web_http_server_digest_authenticate */ +/* Digest authentication */ /* */ /* RELEASE HISTORY */ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Initial Version 6.2.0 */ /* */ /**************************************************************************/ -VOID _nx_web_http_base64_encode(CHAR *name, UINT length, CHAR *base64name) +UINT _nx_web_http_server_nonce_allocate(NX_WEB_HTTP_SERVER *server_ptr, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr) { +UINT i; +UCHAR random_value; +NX_WEB_HTTP_SERVER_NONCE *nonces_list = server_ptr -> nx_web_http_server_nonces; -UINT pad; -UINT i, j; -UINT step; - - - /* Adjust the length to represent the base64 name. */ - length = ((length * 8) / 6); - - /* Default padding to none. */ - pad = 0; - /* Determine if an extra conversion is needed. */ - if ((length * 6) % 24) + /* Search if there is free entry for new nonce. */ + for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++) { - - /* Some padding is needed. */ - - /* Calculate the number of pad characters. */ - pad = (length * 6) % 24; - pad = (24 - pad) / 6; - pad = pad - 1; - - /* Adjust the length to pickup the character fraction. */ - length++; + if (nonces_list[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_INVALID) + { + *nonce_ptr = &(nonces_list[i]); + break; + } } - /* Setup index into the base64name. */ - j = 0; - - /* Compute the base64name. */ - step = 0; - i = 0; - while (j < length) + if (i == NX_WEB_HTTP_SERVER_NONCE_MAX) { - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first 6 bits of name character for index. */ - base64name[j++] = _nx_web_http_server_base64_array[((UINT) name[i]) >> 2]; - step++; - } - else if (step == 1) + /* If no free entry, check the timeout of allocated nonces. */ + for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++) { + if (nonces_list[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_VALID) + { + if (tx_time_get() > nonces_list[i].nonce_timestamp + NX_WEB_HTTP_SERVER_NONCE_TIMEOUT) + { - /* Use last 2 bits of name character and first 4 bits of next name character for index. */ - base64name[j++] = _nx_web_http_server_base64_array[((((UINT) name[i]) & 0x3) << 4) | (((UINT) name[i+1]) >> 4)]; - i++; - step++; + /* If this nonce is timed out, free up this entry for new nonce. */ + *nonce_ptr = &(nonces_list[i]); + break; + } + } } - else if (step == 2) - { - /* Use last 4 bits of name character and first 2 bits of next name character for index. */ - base64name[j++] = _nx_web_http_server_base64_array[((((UINT) name[i]) & 0xF) << 2) | (((UINT) name[i+1]) >> 6)]; - i++; - step++; - } - else /* Step 3 */ + /* If no entry can be allocated, return error. */ + if (i == NX_WEB_HTTP_SERVER_NONCE_MAX) { - - /* Use last 6 bits of name character for index. */ - base64name[j++] = _nx_web_http_server_base64_array[(((UINT) name[i]) & 0x3F)]; - i++; - step = 0; + return(NX_NOT_FOUND); } } - /* Determine if the index needs to be advanced. */ - if (step != 3) - i++; - - /* Now add the PAD characters. */ - while ((pad--) && (j < NX_WEB_HTTP_MAX_STRING)) + /* Generate new nonce for digest authentication. */ + for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_SIZE; i++) { - - /* Pad base64name with '=' characters. */ - base64name[j++] = '='; + random_value = (UCHAR)NX_RAND() % (sizeof(_nx_web_http_server_base64_array) - 1); + (*nonce_ptr) -> nonce_buffer[i] = (UCHAR)_nx_web_http_server_base64_array[random_value]; } - /* Put a NULL character in. */ - base64name[j] = NX_NULL; -} - + /* Reset the timestamp and state for the new nonce. */ + (*nonce_ptr) -> nonce_timestamp = tx_time_get(); + (*nonce_ptr) -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_VALID; -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_web_http_base64_decode PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Yuxin Zhou, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function decodes the input base64 ASCII string and converts */ -/* it into a standard ASCII representation. */ -/* */ -/* INPUT */ -/* */ -/* base64name Encoded base64 name string */ -/* length Length of encoded base64 name */ -/* name Name string */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_web_http_server_basic_authenticate */ -/* Basic authentication */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ -/* 09-30-2020 Yuxin Zhou Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -VOID _nx_web_http_base64_decode(CHAR *base64name, UINT length, CHAR *name) -{ - -UINT i, j; -UINT value1, value2; -UINT step; - - - /* Adjust the length to represent the ASCII name. */ - length = ((length * 6) / 8); - - /* Setup index into the ASCII name. */ - j = 0; - - /* Compute the ASCII name. */ - step = 0; - i = 0; - while ((j < length) && (base64name[i]) && (base64name[i] != '=')) - { - - /* Derive values of the Base64 name. */ - if ((base64name[i] >= 'A') && (base64name[i] <= 'Z')) - value1 = (UINT) (base64name[i] - 'A'); - else if ((base64name[i] >= 'a') && (base64name[i] <= 'z')) - value1 = (UINT) (base64name[i] - 'a') + 26; - else if ((base64name[i] >= '0') && (base64name[i] <= '9')) - value1 = (UINT) (base64name[i] - '0') + 52; - else if (base64name[i] == '+') - value1 = 62; - else if (base64name[i] == '/') - value1 = 63; - else - value1 = 0; - - /* Derive value for the next character. */ - if ((base64name[i+1] >= 'A') && (base64name[i+1] <= 'Z')) - value2 = (UINT) (base64name[i+1] - 'A'); - else if ((base64name[i+1] >= 'a') && (base64name[i+1] <= 'z')) - value2 = (UINT) (base64name[i+1] - 'a') + 26; - else if ((base64name[i+1] >= '0') && (base64name[i+1] <= '9')) - value2 = (UINT) (base64name[i+1] - '0') + 52; - else if (base64name[i+1] == '+') - value2 = 62; - else if (base64name[i+1] == '/') - value2 = 63; - else - value2 = 0; - - /* Determine which step we are in. */ - if (step == 0) - { - - /* Use first value and first 2 bits of second value. */ - name[j++] = (CHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3)); - i++; - step++; - } - else if (step == 1) - { - - /* Use last 4 bits of first value and first 4 bits of next value. */ - name[j++] = (CHAR) (((value1 & 0xF) << 4) | (value2 >> 2)); - i++; - step++; - } - else if (step == 2) - { - - /* Use first 2 bits and following 6 bits of next value. */ - name[j++] = (CHAR) (((value1 & 3) << 6) | (value2 & 0x3f)); - i++; - i++; - step = 0; - } - } - - /* Put a NULL character in. */ - name[j] = NX_NULL; + return(NX_SUCCESS); } - -#ifdef NX_WEB_HTTP_DIGEST_ENABLE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_digest_authenticate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6536,6 +6414,9 @@ UINT step; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_digest_authenticate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT *auth_request_present) @@ -6553,6 +6434,7 @@ CHAR crlf[2] = {13,10}; CHAR authorization_nc[NX_WEB_HTTP_MAX_RESOURCE + 1]; CHAR authorization_cnonce[NX_WEB_HTTP_MAX_RESOURCE + 1]; UINT realm_length; +NX_WEB_HTTP_SERVER_NONCE *nonce_ptr = NX_NULL; /* Default to no authentication request detected. */ *auth_request_present = NX_FALSE; @@ -6561,7 +6443,7 @@ UINT realm_length; status = NX_WEB_HTTP_DIGEST_AUTHENTICATE; /* Is the authorization request present? */ - if (_nx_web_http_server_retrieve_digest_authorization(packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce)) + if (_nx_web_http_server_retrieve_digest_authorization(server_ptr, packet_ptr, authorization_response, authorization_uri, authorization_nc, authorization_cnonce, &nonce_ptr)) { /* Yes, an authorization request is present. */ @@ -6595,7 +6477,7 @@ UINT realm_length; } /* Calculate what the MD5 should be. */ - _nx_web_http_server_digest_response_calculate(server_ptr, name_ptr, realm_ptr, password_ptr, _nx_web_http_server_nonce, method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response); + _nx_web_http_server_digest_response_calculate(server_ptr, name_ptr, realm_ptr, password_ptr, (CHAR *)(nonce_ptr -> nonce_buffer), method, authorization_uri, authorization_nc, authorization_cnonce, calculated_response); /* Determine if the calculated response is the same as the received response. */ i = 0; @@ -6613,6 +6495,32 @@ UINT realm_length; /* Otherwise, look at next character. */ i++; } + + /* If the response is authenticated, mark the nonce as accepted. */ + if (status == NX_SUCCESS) + { + + /* If another session uses the same nonce, don't accept it. */ + if (nonce_ptr -> nonce_state == NX_WEB_HTTP_SERVER_NONCE_ACCEPTED) + { + if (nonce_ptr -> nonce_session_ptr != server_ptr -> nx_web_http_server_current_session_ptr) + { + status = NX_WEB_HTTP_DIGEST_AUTHENTICATE; + } + } + else + { + + /* Update nonce state and set the session pointer for mapping in disconnection. */ + nonce_ptr -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_ACCEPTED; + nonce_ptr -> nonce_session_ptr = server_ptr -> nx_web_http_server_current_session_ptr; + } + } + else + { + nonce_ptr -> nonce_state = NX_WEB_HTTP_SERVER_NONCE_INVALID; + } + /* If digest authenticate callback function returns non-success value, the request is considered unauthenticated. */ if(callback_status != NX_SUCCESS) @@ -6623,6 +6531,24 @@ UINT realm_length; if (status == NX_WEB_HTTP_DIGEST_AUTHENTICATE) { + /* Allocate a new nonce for digest authentication. */ + status1 = _nx_web_http_server_nonce_allocate(server_ptr, &nonce_ptr); + + /* Determine if an error occurred in the packet allocation. */ + if (status1) + { + + /* Send response back to HTTP Client. */ + _nx_web_http_server_response_send(server_ptr, NX_WEB_HTTP_STATUS_INTERNAL_ERROR, sizeof(NX_WEB_HTTP_STATUS_INTERNAL_ERROR) - 1, + "NetX HTTP Server Internal Error", sizeof("NetX HTTP Server Internal Error") - 1, NX_NULL, 0); + + /* Indicate an allocation error occurred. */ + server_ptr -> nx_web_http_server_allocation_errors++; + + /* Return the internal NetX error. */ + return(status1); + } + /* We need authorization so build the HTTP 401 Unauthorized message to send to the server. */ /* Check string length. */ @@ -6705,7 +6631,7 @@ UINT realm_length; server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Place the nonce string into the buffer. */ - nx_packet_data_append(packet_ptr, _nx_web_http_server_nonce, sizeof(_nx_web_http_server_nonce) - 1, + nx_packet_data_append(packet_ptr, nonce_ptr -> nonce_buffer, NX_WEB_HTTP_SERVER_NONCE_SIZE, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Insert the double quote. */ @@ -6720,6 +6646,14 @@ UINT realm_length; nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + /* Set Content-Length as 0. */ + nx_packet_data_append(packet_ptr, "Content-Length: 0", 17, + server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + + /* Place the into the buffer. */ + nx_packet_data_append(packet_ptr, crlf, 2, + server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); + /* Place another into the buffer to signal end of FULL HTTP response. */ nx_packet_data_append(packet_ptr, crlf, 2, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); @@ -6749,7 +6683,7 @@ UINT realm_length; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_digest_response_calculate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6796,6 +6730,9 @@ UINT realm_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_web_http_server_digest_response_calculate(NX_WEB_HTTP_SERVER *server_ptr, CHAR *username, CHAR *realm, CHAR *password, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result) @@ -6809,7 +6746,6 @@ UINT password_length; UINT realm_length; UINT method_length; UINT uri_length; -UINT nonce_length; UINT nc_length; UINT cnonce_length; @@ -6819,7 +6755,6 @@ UINT cnonce_length; _nx_utility_string_length_check(realm, &realm_length, NX_MAX_STRING_LENGTH) || _nx_utility_string_length_check(method, &method_length, 7) || _nx_utility_string_length_check(uri, &uri_length, NX_WEB_HTTP_MAX_RESOURCE) || - _nx_utility_string_length_check(nonce, &nonce_length, sizeof(_nx_web_http_server_nonce) - 1) || _nx_utility_string_length_check(nc, &nc_length, NX_WEB_HTTP_MAX_RESOURCE) || _nx_utility_string_length_check(cnonce, &cnonce_length, NX_WEB_HTTP_MAX_RESOURCE)) { @@ -6853,7 +6788,7 @@ UINT cnonce_length; _nx_md5_initialize(&(server_ptr -> nx_web_http_server_md5data)); _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ha1_string, sizeof(ha1_string) - 1); _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1); - _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) nonce, nonce_length); + _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) nonce, NX_WEB_HTTP_SERVER_NONCE_SIZE); /* Start of Internet Explorer bug work-around. */ _nx_md5_update(&(server_ptr -> nx_web_http_server_md5data), (unsigned char *) ":", 1); @@ -6878,7 +6813,7 @@ UINT cnonce_length; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_retrieve_digest_authorization PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -6890,11 +6825,13 @@ UINT cnonce_length; /* */ /* INPUT */ /* */ +/* server_ptr HTTP Server pointer */ /* packet_ptr Request packet pointer */ /* response Digest response pointer */ /* uri URI from response pointer */ /* nc Nonce count string */ /* cnonce Client nonce string */ +/* nonce_ptr Server nonce pointer */ /* */ /* OUTPUT */ /* */ @@ -6918,15 +6855,20 @@ UINT cnonce_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -UINT _nx_web_http_server_retrieve_digest_authorization(NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce) +UINT _nx_web_http_server_retrieve_digest_authorization(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr) { UINT length; UINT found; CHAR *buffer_ptr; CHAR *saved_buffer_ptr; +UCHAR *nonce_buffer; +UINT i; /* Set the found flag to false. */ @@ -7046,6 +6988,86 @@ CHAR *saved_buffer_ptr; /* Save current buffer pointer, so each parameter search always starts from here. */ saved_buffer_ptr = buffer_ptr; + while (((buffer_ptr + 6) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0)) + { + + /* Check for the uri token. */ + if (((*(buffer_ptr) == 'n') || (*(buffer_ptr) == 'N')) && + ((*(buffer_ptr+1) == 'o') || (*(buffer_ptr+1) == 'O')) && + ((*(buffer_ptr+2) == 'n') || (*(buffer_ptr+2) == 'N')) && + ((*(buffer_ptr+3) == 'c') || (*(buffer_ptr+3) == 'C')) && + ((*(buffer_ptr+4) == 'e') || (*(buffer_ptr+4) == 'E')) && + (*(buffer_ptr+5) == '=')) + { + + /* Move the pointer up to the actual nonce string. */ + buffer_ptr = buffer_ptr + 6; + found = NX_TRUE; + + break; + } + + /* Move the pointer up to the next character. */ + buffer_ptr++; + } + + /* Check if nonce is found. */ + if (!found) + { + return(0); + } + + /* Now remove any extra blanks and quotes. */ + while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && ((*buffer_ptr == ' ') || (*buffer_ptr == (CHAR) 0x22))) + { + + /* Move the pointer up one character. */ + buffer_ptr++; + } + + /* Now pickup the nonce string. */ + length = 0; + nonce_buffer = (UCHAR *)buffer_ptr; + while ((buffer_ptr < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0) && (*buffer_ptr != ' ') && (*buffer_ptr != (CHAR) 13)) + { + + /* Determine if the ending quote is present. */ + if (*buffer_ptr == (CHAR) 0x22) + { + break; + } + + /* Increase the length. */ + length++; + buffer_ptr++; + } + + /* Check the nonce size. */ + if (length != NX_WEB_HTTP_SERVER_NONCE_SIZE) + { + return(0); + } + + /* Check if the nonce is valid. */ + for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++) + { + if ((server_ptr -> nx_web_http_server_nonces[i].nonce_state != NX_WEB_HTTP_SERVER_NONCE_INVALID) && + (memcmp(server_ptr -> nx_web_http_server_nonces[i].nonce_buffer, nonce_buffer, NX_WEB_HTTP_SERVER_NONCE_SIZE) == 0)) /* Use case of memcmp is verified. */ + { + *nonce_ptr = &(server_ptr -> nx_web_http_server_nonces[i]); + break; + } + } + + /* If the nonca is invalid, just return. */ + if (i == NX_WEB_HTTP_SERVER_NONCE_MAX) + { + return(0); + } + + /* Get saved buffer pointer. */ + buffer_ptr = saved_buffer_ptr; + /* Now look for the nc in the digest response. */ while (((buffer_ptr+3) < (CHAR *) packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != (CHAR) 0)) { @@ -7105,9 +7127,9 @@ CHAR *saved_buffer_ptr; if (((*buffer_ptr == 'c') || (*buffer_ptr == 'C')) && ((*(buffer_ptr+1) == 'n') || (*(buffer_ptr+1) == 'N')) && ((*(buffer_ptr+2) == 'o') || (*(buffer_ptr+2) == 'O')) && - ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+2) == 'N')) && - ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+2) == 'C')) && - ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+2) == 'E')) && + ((*(buffer_ptr+3) == 'n') || (*(buffer_ptr+3) == 'N')) && + ((*(buffer_ptr+4) == 'c') || (*(buffer_ptr+4) == 'C')) && + ((*(buffer_ptr+5) == 'e') || (*(buffer_ptr+5) == 'E')) && (*(buffer_ptr+6) == '=')) { @@ -7212,11 +7234,11 @@ CHAR *saved_buffer_ptr; if (((*buffer_ptr == 'r') || (*buffer_ptr == 'R')) && ((*(buffer_ptr+1) == 'e') || (*(buffer_ptr+1) == 'E')) && ((*(buffer_ptr+2) == 's') || (*(buffer_ptr+2) == 'S')) && - ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+2) == 'P')) && - ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+2) == 'O')) && - ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+2) == 'N')) && - ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+2) == 'S')) && - ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+2) == 'E')) && + ((*(buffer_ptr+3) == 'p') || (*(buffer_ptr+3) == 'P')) && + ((*(buffer_ptr+4) == 'o') || (*(buffer_ptr+4) == 'O')) && + ((*(buffer_ptr+5) == 'n') || (*(buffer_ptr+5) == 'N')) && + ((*(buffer_ptr+6) == 's') || (*(buffer_ptr+6) == 'S')) && + ((*(buffer_ptr+7) == 'e') || (*(buffer_ptr+7) == 'E')) && (*(buffer_ptr+8) == '=')) { @@ -7423,7 +7445,7 @@ UINT _nxe_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER *server_ptr, NX_ /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_get_entity_header PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -7465,6 +7487,9 @@ UINT _nxe_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER *server_ptr, NX_ /* 09-30-2020 Yuxin Zhou Modified comment(s), and */ /* fixed write underflow, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* verified memmove use cases, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_get_entity_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, UCHAR *entity_header_buffer, ULONG buffer_size) @@ -7568,7 +7593,7 @@ UINT index; /* Leave boundary string only. */ memmove(&multipart_ptr -> nx_web_http_server_multipart_boundary[4], &multipart_ptr -> nx_web_http_server_multipart_boundary[index], - quotation_index - index + 1); + quotation_index - index + 1); /* Use case of memmove is verified. */ } else { @@ -8516,7 +8541,7 @@ UCHAR ch; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_generate_response_header PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -8547,7 +8572,7 @@ UCHAR ch; /* Allocate response packet */ /* nx_packet_data_append Append packet data */ /* memcmp Compare string */ -/* _nx_web_http_server_number_convert Convert number to ASCII */ +/* _nx_utility_uint_to_string Convert number to ASCII */ /* _nx_web_http_server_date_to_string Convert data to string */ /* nx_packet_release Release packet */ /* */ @@ -8566,6 +8591,10 @@ UCHAR ch; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_web_http_server_generate_response_header(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_pptr, @@ -8665,7 +8694,7 @@ CHAR status_code_not_modified; { /* Convert the content_length to ASCII representation. */ - temp = _nx_web_http_server_number_convert(content_length, temp_string); + temp = _nx_utility_uint_to_string(content_length, 10, temp_string, sizeof(temp_string)); /* Place the "Content-Length" field in the header. */ status += nx_packet_data_append(packet_ptr, "Content-Length: ", 16, @@ -8733,7 +8762,7 @@ CHAR status_code_not_modified; server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); /* Convert the max-age to ASCII representation. */ - temp = _nx_web_http_server_number_convert(max_age, temp_string); + temp = _nx_utility_uint_to_string(max_age, 10, temp_string, sizeof(temp_string)); status += nx_packet_data_append(packet_ptr, temp_string, temp, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER); @@ -10978,7 +11007,7 @@ NX_TCP_SOCKET *tcp_socket; /* FUNCTION RELEASE */ /* */ /* _nx_web_http_server_connection_disconnect PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -11015,6 +11044,9 @@ NX_TCP_SOCKET *tcp_socket; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_web_http_server_connection_disconnect(NX_WEB_HTTP_SERVER *server_ptr, NX_TCP_SESSION *session_ptr, UINT wait_option) @@ -11022,13 +11054,30 @@ VOID _nx_web_http_server_connection_disconnect(NX_WEB_HTTP_SERVER *server_ptr, N NX_TCP_SOCKET *tcp_socket; #ifdef NX_WEB_HTTPS_ENABLE NX_SECURE_TLS_SESSION *tls_session; -#endif +#endif /* NX_WEB_HTTPS_ENABLE */ +#ifdef NX_WEB_HTTP_DIGEST_ENABLE +UINT i; +#endif /* NX_WEB_HTTP_DIGEST_ENABLE */ #ifndef NX_WEB_HTTPS_ENABLE NX_PARAMETER_NOT_USED(server_ptr); NX_PARAMETER_NOT_USED(wait_option); #endif /* NX_WEB_HTTPS_ENABLE */ +#ifdef NX_WEB_HTTP_DIGEST_ENABLE + + /* Once the nonce has been accepted, set the state as invalid. */ + for (i = 0; i < NX_WEB_HTTP_SERVER_NONCE_MAX; i++) + { + if ((server_ptr -> nx_web_http_server_nonces[i].nonce_state == NX_WEB_HTTP_SERVER_NONCE_ACCEPTED) && + (server_ptr -> nx_web_http_server_nonces[i].nonce_session_ptr == session_ptr)) + { + server_ptr -> nx_web_http_server_nonces[i].nonce_state = NX_WEB_HTTP_SERVER_NONCE_INVALID; + break; + } + } +#endif /* NX_WEB_HTTP_DIGEST_ENABLE */ + tcp_socket = &(session_ptr -> nx_tcp_session_socket); #ifdef NX_WEB_HTTPS_ENABLE @@ -11302,4 +11351,4 @@ UINT _nx_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER *http_serve /* Return success. */ return(NX_SUCCESS); -} +} \ No newline at end of file diff --git a/addons/web/nx_web_http_server.h b/addons/web/nx_web_http_server.h index afe834d8..ae2c0bc4 100644 --- a/addons/web/nx_web_http_server.h +++ b/addons/web/nx_web_http_server.h @@ -27,7 +27,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_web_http_server.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -46,6 +46,23 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* parsing base64, */ +/* resulting in version 6.1.6 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* improved the logic of */ +/* converting number to string,*/ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* deprecated unused macros, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* supported ECC configuration,*/ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), and */ +/* supported random nonce, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -134,11 +151,11 @@ extern "C" { #define NX_WEB_HTTP_SERVER_MAX_PENDING (NX_WEB_HTTP_SERVER_SESSION_MAX << 1) #endif +/* Deprecated. This symbol is defined for compatibility. */ #ifndef NX_WEB_HTTP_SERVER_THREAD_TIME_SLICE #define NX_WEB_HTTP_SERVER_THREAD_TIME_SLICE 2 #endif - #ifndef NX_WEB_HTTP_SERVER_MIN_PACKET_SIZE #define NX_WEB_HTTP_SERVER_MIN_PACKET_SIZE 600 #endif @@ -161,6 +178,24 @@ extern "C" { #define NX_WEB_HTTP_SERVER_RETRY_SHIFT 1 /* Every retry is twice as long */ #endif +#ifndef NX_WEB_HTTP_SERVER_NONCE_MAX +#define NX_WEB_HTTP_SERVER_NONCE_MAX (NX_WEB_HTTP_SERVER_SESSION_MAX << 1) +#endif + +#ifndef NX_WEB_HTTP_SERVER_NONCE_SIZE +#define NX_WEB_HTTP_SERVER_NONCE_SIZE 32 +#endif + +#ifndef NX_WEB_HTTP_SERVER_NONCE_TIMEOUT +#define NX_WEB_HTTP_SERVER_NONCE_TIMEOUT (10 * NX_IP_PERIODIC_RATE) +#endif + +/* Define the state of the nonce. */ + +#define NX_WEB_HTTP_SERVER_NONCE_INVALID 0 +#define NX_WEB_HTTP_SERVER_NONCE_VALID 1 +#define NX_WEB_HTTP_SERVER_NONCE_ACCEPTED 2 + /* Define HTTP Server request types. */ #define NX_WEB_HTTP_SERVER_UNKNOWN_REQUEST 0 @@ -211,6 +246,16 @@ typedef struct NX_WEB_HTTP_SERVER_DATE_STRUCT UCHAR nx_web_http_server_weekday; /* Weekday */ } NX_WEB_HTTP_SERVER_DATE; +/* Define the nonce structure. */ + +typedef struct NX_WEB_HTTP_SERVER_NONCE_STRUCT +{ + UINT nonce_state; /* The state of the nonce */ + ULONG nonce_timestamp; /* The time when the nonce is created */ + NX_TCP_SESSION *nonce_session_ptr; /* The session accepted with this nonce */ + UCHAR nonce_buffer[NX_WEB_HTTP_SERVER_NONCE_SIZE]; /* Nonce for digest authetication */ +} NX_WEB_HTTP_SERVER_NONCE; + /* Define the multipart context data structure. */ typedef struct NX_WEB_HTTP_SERVER_MULTIPART_STRUCT @@ -276,6 +321,9 @@ typedef struct NX_WEB_HTTP_SERVER_STRUCT #ifdef NX_WEB_HTTP_DIGEST_ENABLE NX_MD5 nx_web_http_server_md5data; /* HTTP server MD5 work area */ + NX_WEB_HTTP_SERVER_NONCE + nx_web_http_server_nonces[NX_WEB_HTTP_SERVER_NONCE_MAX]; + /* Nonce for digest authetication */ #endif /* NX_WEB_HTTP_DIGEST_ENABLE */ #ifdef NX_WEB_HTTP_MULTIPART_ENABLE @@ -348,6 +396,7 @@ typedef struct NX_WEB_HTTP_SERVER_STRUCT #define nx_web_http_server_query_get _nx_web_http_server_query_get #define nx_web_http_server_start _nx_web_http_server_start #define nx_web_http_server_secure_configure _nx_web_http_server_secure_configure +#define nx_web_http_server_secure_ecc_configure _nx_web_http_server_secure_ecc_configure #define nx_web_http_server_stop _nx_web_http_server_stop #define nx_web_http_server_content_get_extended _nx_web_http_server_content_get_extended #define nx_web_http_server_content_length_get _nx_web_http_server_content_length_get @@ -384,6 +433,7 @@ typedef struct NX_WEB_HTTP_SERVER_STRUCT #define nx_web_http_server_query_get _nxe_web_http_server_query_get #define nx_web_http_server_start _nxe_web_http_server_start #define nx_web_http_server_secure_configure _nxe_web_http_server_secure_configure +#define nx_web_http_server_secure_ecc_configure _nxe_web_http_server_secure_ecc_configure #define nx_web_http_server_stop _nxe_web_http_server_stop #define nx_web_http_server_content_get_extended _nxe_web_http_server_content_get_extended #define nx_web_http_server_get_entity_header _nxe_web_http_server_get_entity_header @@ -444,6 +494,11 @@ UINT nx_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_server_ UINT remote_certs_num, UCHAR *remote_certificate_buffer, UINT remote_cert_buffer_size); +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +UINT nx_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves); +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #endif /* NX_WEB_HTTPS_ENABLE */ UINT nx_web_http_server_stop(NX_WEB_HTTP_SERVER *http_server_ptr); UINT nx_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size); @@ -508,6 +563,11 @@ UINT _nx_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_server UINT remote_certs_num, UCHAR *remote_certificate_buffer, UINT remote_cert_buffer_size); +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +UINT _nx_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves); +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #endif /* NX_WEB_HTTPS_ENABLE */ UINT _nx_web_http_server_stop(NX_WEB_HTTP_SERVER *http_server_ptr); UINT _nx_web_http_server_content_get_extended(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG byte_offset, CHAR *destination_ptr, UINT destination_size, UINT *actual_size); @@ -540,7 +600,6 @@ UINT _nx_web_http_server_authentication_check_set(NX_WEB_HTTP_SERVER *htt /* Define internal HTTP Server functions. */ -VOID _nx_web_http_server_connection_present(NX_TCP_SOCKET *socket_ptr, UINT port); UINT _nx_web_http_server_get_client_request(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr); VOID _nx_web_http_server_get_process(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, NX_PACKET *packet_ptr); VOID _nx_web_http_server_put_process(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr); @@ -553,12 +612,9 @@ UINT _nx_web_http_server_basic_authenticate(NX_WEB_HTTP_SERVER *server_pt UINT _nx_web_http_server_retrieve_basic_authorization(NX_PACKET *packet_ptr, CHAR *authorization_request_ptr); UINT _nx_web_http_server_retrieve_resource(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *destination, UINT max_size); UINT _nx_web_http_server_calculate_content_offset(NX_PACKET *packet_ptr); -UINT _nx_web_http_server_number_convert(UINT number, CHAR *string); UINT _nx_web_http_server_type_get(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, CHAR *http_type_string, UINT *string_size); UINT _nx_web_http_server_type_get_extended(NX_WEB_HTTP_SERVER *server_ptr, CHAR *name, UINT name_length, CHAR *http_type_string, UINT http_type_string_max_size, UINT *string_size); -VOID _nx_web_http_base64_encode(CHAR *name, UINT length, CHAR *base64name); -VOID _nx_web_http_base64_decode(CHAR *base64name, UINT length, CHAR *name); UINT _nx_web_http_server_receive(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET **packet_ptr, ULONG wait_option); UINT _nx_web_http_server_send(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, ULONG wait_option); @@ -568,8 +624,9 @@ VOID _nx_web_http_server_connection_disconnect(NX_WEB_HTTP_SERVER *server #ifdef NX_WEB_HTTP_DIGEST_ENABLE UINT _nx_web_http_server_digest_authenticate(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *name_ptr, CHAR *password_ptr, CHAR *realm_ptr, UINT *auth_request_present); VOID _nx_web_http_server_digest_response_calculate(NX_WEB_HTTP_SERVER *server_ptr, CHAR *username, CHAR *realm, CHAR *password, CHAR *nonce, CHAR *method, CHAR *uri, CHAR *nc, CHAR *cnonce, CHAR *result); -UINT _nx_web_http_server_retrieve_digest_authorization(NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce); +UINT _nx_web_http_server_retrieve_digest_authorization(NX_WEB_HTTP_SERVER *server_ptr, NX_PACKET *packet_ptr, CHAR *response, CHAR *uri, CHAR *nc, CHAR *cnonce, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr); VOID _nx_web_http_server_hex_ascii_convert(CHAR *source, UINT source_length, CHAR *destination); +UINT _nx_web_http_server_nonce_allocate(NX_WEB_HTTP_SERVER *server_ptr, NX_WEB_HTTP_SERVER_NONCE **nonce_ptr); #endif #ifdef NX_WEB_HTTP_MULTIPART_ENABLE @@ -636,6 +693,11 @@ UINT _nxe_web_http_server_secure_configure(NX_WEB_HTTP_SERVER *http_serve UINT remote_certs_num, UCHAR *remote_certificate_buffer, UINT remote_cert_buffer_size); +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +UINT _nxe_web_http_server_secure_ecc_configure(NX_WEB_HTTP_SERVER *http_server_ptr, + const USHORT *supported_groups, USHORT supported_group_count, + const NX_CRYPTO_METHOD **curves); +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #endif /* NX_WEB_HTTPS_ENABLE */ UINT _nxe_web_http_server_stop(NX_WEB_HTTP_SERVER *http_server_ptr); UINT _nxe_web_http_server_invalid_userpassword_notify_set(NX_WEB_HTTP_SERVER *http_server_ptr, diff --git a/addons/websocket/nx_sha1.c b/addons/websocket/nx_sha1.c new file mode 100644 index 00000000..53def7f5 --- /dev/null +++ b/addons/websocket/nx_sha1.c @@ -0,0 +1,503 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/* + Copyright (C) The Internet Society (2001). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + ""AS IS"" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +*/ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** SHA1 Digest Algorithm (SHA1) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#include "nx_api.h" +#include "nx_sha1.h" + +/* Define macros for the SHA1 transform function. */ + +/* Define the SHA1 basic F1, F2, F3, and F4 functions. */ + +#define F1(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define F2(x, y, z) ((x) ^ (y) ^ (z)) +#define F3(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z))) +#define F4(x, y, z) ((x) ^ (y) ^ (z)) + + +/* Define the SHA1 left shift circular function. */ + +#define LEFT_SHIFT_CIRCULAR(x, n) (((x) << (n)) | ((x) >> (32-(n)))) + + +/* Define the padding array. This is used to pad the message such that its length is + 64 bits shy of being a multiple of 512 bits long. */ + +static UCHAR _nx_sha1_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_sha1_initialize PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the SHA1 context. It must be called prior */ +/* to creating the SHA1 digest. */ +/* */ +/* INPUT */ +/* */ +/* context SHA1 context pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* NetX Applications */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _nx_sha1_initialize(NX_SHA1 *context) +{ + + /* Determine if the context is non-null. */ + if (context == NX_NULL) + return(NX_PTR_ERROR); + + /* First, clear the bit count for this context. */ + context -> nx_sha1_bit_count[0] = 0; /* Clear the lower 32-bits of the count */ + context -> nx_sha1_bit_count[1] = 0; /* Clear the upper 32-bits of the count */ + + /* Finally, setup the context states. */ + context -> nx_sha1_states[0] = 0x67452301UL; /* Setup state A */ + context -> nx_sha1_states[1] = 0xEFCDAB89UL; /* Setup state B */ + context -> nx_sha1_states[2] = 0x98BADCFEUL; /* Setup state C */ + context -> nx_sha1_states[3] = 0x10325476UL; /* Setup state D */ + context -> nx_sha1_states[4] = 0xC3D2E1F0UL; /* Setup state E */ + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_sha1_update PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the digest calculation with new input from */ +/* the caller. */ +/* */ +/* INPUT */ +/* */ +/* context SHA1 context pointer */ +/* input_ptr Pointer to byte(s) of input */ +/* input_length Length of bytes of input */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_sha1_process_buffer Process complete buffer, */ +/* which is 64-bytes in size */ +/* */ +/* CALLED BY */ +/* */ +/* NetX Applications */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), and */ +/* verified memcpy use cases, */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _nx_sha1_update(NX_SHA1 *context, UCHAR *input_ptr, UINT input_length) +{ + +ULONG current_bytes; +ULONG needed_fill_bytes; + + + /* Determine if the context is non-null. */ + if (context == NX_NULL) + return(NX_PTR_ERROR); + + /* Determine if there is a length. */ + if (input_length == 0) + return(NX_SUCCESS); + + /* Calculate the current byte count mod 64. Note the reason for the + shift by 3 is to account for the 8 bits per byte. */ + current_bytes = (context -> nx_sha1_bit_count[0] >> 3) & 0x3F; + + /* Calculate the current number of bytes needed to be filled. */ + needed_fill_bytes = 64 - current_bytes; + + /* Update the total bit count based on the input length. */ + context -> nx_sha1_bit_count[0] += (input_length << 3); + + /* Determine if there is roll-over of the bit count into the MSW. */ + if (context -> nx_sha1_bit_count[0] < (input_length << 3)) + { + + /* Yes, increment the MSW of the bit count. */ + context -> nx_sha1_bit_count[1]++; + } + + /* Update upper total bit count word. */ + context -> nx_sha1_bit_count[1] += (input_length >> 29); + + /* Check for a partial buffer that needs to be transformed. */ + if ((current_bytes) && (input_length >= needed_fill_bytes)) + { + + /* Yes, we can complete the buffer and transform it. */ + + /* Copy the appropriate portion of the input buffer into the internal + buffer of the context. */ + memcpy((void *) &(context -> nx_sha1_buffer[current_bytes]), (void *) input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. */ + + /* Process the 64-byte (512 bit) buffer. */ + _nx_sha1_process_buffer(context, context -> nx_sha1_buffer); + + /* Adjust the pointers and length accordingly. */ + input_length = input_length - needed_fill_bytes; + input_ptr = input_ptr + needed_fill_bytes; + + /* Clear the remaining bits, since the buffer was processed. */ + current_bytes = 0; + } + + /* Process any and all whole blocks of input. */ + while (input_length >= 64) + { + + /* Process this 64-byte (512 bit) buffer. */ + _nx_sha1_process_buffer(context, input_ptr); + + /* Adjust the pointers and length accordingly. */ + input_length = input_length - 64; + input_ptr = input_ptr + 64; + } + + /* Determine if there is anything left. */ + if (input_length) + { + + /* Save the remaining bytes in the internal buffer after any remaining bytes + that it is processed later. */ + memcpy((void *) &(context -> nx_sha1_buffer[current_bytes]), (void *) input_ptr, input_length); /* Use case of memcpy is verified. */ + } + + /* Return success. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_sha1_digest_calculate PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finishes calculation of the SHA1 digest. It is called */ +/* where there is no further input needed for the digest. The resulting*/ +/* 20-byte (160-bit) SHA1 digest is returned to the caller. */ +/* */ +/* INPUT */ +/* */ +/* context SHA1 context pointer */ +/* digest Pointer to return digest in */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_sha1_update Update the digest with padding*/ +/* and length of digest */ +/* */ +/* CALLED BY */ +/* */ +/* NetX Applications */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +UINT _nx_sha1_digest_calculate(NX_SHA1 *context, UCHAR digest[20]) +{ + +UCHAR bit_count_string[8]; +ULONG current_byte_count; +ULONG padding_bytes; + + + /* Move the lower portion of the bit count into the array. */ + bit_count_string[0] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 24); + bit_count_string[1] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 16); + bit_count_string[2] = (UCHAR) (context -> nx_sha1_bit_count[1] >> 8); + bit_count_string[3] = (UCHAR) (context -> nx_sha1_bit_count[1]); + bit_count_string[4] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 24); + bit_count_string[5] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 16); + bit_count_string[6] = (UCHAR) (context -> nx_sha1_bit_count[0] >> 8); + bit_count_string[7] = (UCHAR) (context -> nx_sha1_bit_count[0]); + + /* Calculate the current byte count. */ + current_byte_count = (context -> nx_sha1_bit_count[0] >> 3) & 0x3F; + + /* Calculate the padding bytes needed. */ + padding_bytes = (current_byte_count < 56) ? (56 - current_byte_count) : (120 - current_byte_count); + + /* Add any padding required. */ + _nx_sha1_update(context, _nx_sha1_padding, padding_bytes); + + /* Add the in the length. */ + _nx_sha1_update(context, bit_count_string, 8); + + /* Now store the digest in the caller specified destination. */ + digest[ 0] = (UCHAR) (context -> nx_sha1_states[0] >> 24); + digest[ 1] = (UCHAR) (context -> nx_sha1_states[0] >> 16); + digest[ 2] = (UCHAR) (context -> nx_sha1_states[0] >> 8); + digest[ 3] = (UCHAR) (context -> nx_sha1_states[0]); + digest[ 4] = (UCHAR) (context -> nx_sha1_states[1] >> 24); + digest[ 5] = (UCHAR) (context -> nx_sha1_states[1] >> 16); + digest[ 6] = (UCHAR) (context -> nx_sha1_states[1] >> 8); + digest[ 7] = (UCHAR) (context -> nx_sha1_states[1]); + digest[ 8] = (UCHAR) (context -> nx_sha1_states[2] >> 24); + digest[ 9] = (UCHAR) (context -> nx_sha1_states[2] >> 16); + digest[10] = (UCHAR) (context -> nx_sha1_states[2] >> 8); + digest[11] = (UCHAR) (context -> nx_sha1_states[2]); + digest[12] = (UCHAR) (context -> nx_sha1_states[3] >> 24); + digest[13] = (UCHAR) (context -> nx_sha1_states[3] >> 16); + digest[14] = (UCHAR) (context -> nx_sha1_states[3] >> 8); + digest[15] = (UCHAR) (context -> nx_sha1_states[3]); + digest[16] = (UCHAR) (context -> nx_sha1_states[4] >> 24); + digest[17] = (UCHAR) (context -> nx_sha1_states[4] >> 16); + digest[18] = (UCHAR) (context -> nx_sha1_states[4] >> 8); + digest[19] = (UCHAR) (context -> nx_sha1_states[4]); + + /* Return successful completion. */ + return(NX_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_sha1_process_buffer PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function actually uses the SHA1 algorithm to process a 64-byte */ +/* (512 bit) buffer. */ +/* */ +/* INPUT */ +/* */ +/* context SHA1 context pointer */ +/* buffer Pointer to 64-byte buffer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* NetX Applications */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ +VOID _nx_sha1_process_buffer(NX_SHA1 *context, UCHAR buffer[64]) +{ + +ULONG *w; +UINT t; +ULONG temp; +ULONG a, b, c, d, e; + + + /* Setup pointers to the word array. */ + w = context -> nx_sha1_word_array; + + /* Initialize the first 16 words of the word array, taking care of the + endian issues at the same time. */ + for (t = 0; t < 16; t++) + { + + /* Setup each entry. */ + w[t] = (((ULONG) buffer[t * 4]) << 24) | (((ULONG) buffer[(t * 4) + 1]) << 16) | (((ULONG) buffer[(t * 4) + 2]) << 8) | ((ULONG) buffer[(t * 4) + 3]); + } + + /* Setup the remaining entries of the word array. */ + for (t = 16; t < 80; t++) + { + + /* Setup each entry. */ + w[t] = LEFT_SHIFT_CIRCULAR((w[t-3] ^ w[t-8] ^ w[t-14] ^ w[t-16]), 1); + } + + /* Initialize the state variables. */ + a = context -> nx_sha1_states[0]; + b = context -> nx_sha1_states[1]; + c = context -> nx_sha1_states[2]; + d = context -> nx_sha1_states[3]; + e = context -> nx_sha1_states[4]; + + /* Now, perform Round 1 operations. */ + for (t = 0; t < 20; t++) + { + + /* Compute round 1 (t = 0 through t = 19). */ + temp = LEFT_SHIFT_CIRCULAR(a, 5) + F1(b, c, d) + e + w[t] + 0x5A827999UL; + e = d; + d = c; + c = LEFT_SHIFT_CIRCULAR(b, 30); + b = a; + a = temp; + } + + /* Now, perform Round 2 operations. */ + for (t = 20; t < 40; t++) + { + + /* Compute round 2 (t = 20 through t = 39). */ + temp = LEFT_SHIFT_CIRCULAR(a, 5) + F2(b, c, d) + e + w[t] + 0x6ED9EBA1UL; + e = d; + d = c; + c = LEFT_SHIFT_CIRCULAR(b, 30); + b = a; + a = temp; + } + + /* Now, perform Round 3 operations. */ + for (t = 40; t < 60; t++) + { + + /* Compute round 3 (t = 40 through t = 59). */ + temp = LEFT_SHIFT_CIRCULAR(a, 5) + F3(b, c, d) + e + w[t] + 0x8F1BBCDCUL; + e = d; + d = c; + c = LEFT_SHIFT_CIRCULAR(b, 30); + b = a; + a = temp; + } + + /* Finally, perform Round 4 operations. */ + for (t = 60; t < 80; t++) + { + + /* Compute round 4 (t = 60 through t = 79). */ + temp = LEFT_SHIFT_CIRCULAR(a, 5) + F4(b, c, d) + e + w[t] + 0xCA62C1D6UL; + e = d; + d = c; + c = LEFT_SHIFT_CIRCULAR(b, 30); + b = a; + a = temp; + } + + /* Save the resulting in this SHA1 context. */ + context -> nx_sha1_states[0] += a; + context -> nx_sha1_states[1] += b; + context -> nx_sha1_states[2] += c; + context -> nx_sha1_states[3] += d; + context -> nx_sha1_states[4] += e; +} + diff --git a/addons/websocket/nx_sha1.h b/addons/websocket/nx_sha1.h new file mode 100644 index 00000000..8385d8c0 --- /dev/null +++ b/addons/websocket/nx_sha1.h @@ -0,0 +1,116 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/* + Copyright (C) The Internet Society (2001). All Rights Reserved. + + This document and translations of it may be copied and furnished to + others, and derivative works that comment on or otherwise explain it + or assist in its implementation may be prepared, copied, published + and distributed, in whole or in part, without restriction of any + kind, provided that the above copyright notice and this paragraph are + included on all such copies and derivative works. However, this + document itself may not be modified in any way, such as by removing + the copyright notice or references to the Internet Society or other + Internet organizations, except as needed for the purpose of + developing Internet standards in which case the procedures for + copyrights defined in the Internet Standards process must be + followed, or as required to translate it into languages other than + English. + + The limited permissions granted above are perpetual and will not be + revoked by the Internet Society or its successors or assigns. + + This document and the information contained herein is provided on an + ""AS IS"" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING + TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION + HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF + MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +*/ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** SHA1 Digest Algorithm (SHA1) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* nx_sha1.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX SHA1 algorithm, derived principally from */ +/* RFC3174. From a user-specified number of input bytes, this routine */ +/* produces a 20-byte (160-bit) digest or sometimes called a hash */ +/* value. The resulting digest is returned in a 20-byte array supplied */ +/* by the caller. */ +/* */ +/* It is assumed that nx_api.h and nx_port.h have already been */ +/* included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ +/* 09-30-2020 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1 */ +/* */ +/**************************************************************************/ + +#ifndef NX_SHA1_H +#define NX_SHA1_H + + +/* Define the SHA1 context structure. */ + +typedef struct NX_SHA1_STRUCT +{ + + ULONG nx_sha1_states[5]; /* Contains each state (A,B,C,D) */ + ULONG nx_sha1_bit_count[2]; /* Contains the 64-bit total bit */ + /* count, where index 0 holds the */ + /* least significant bit count and*/ + /* index 1 contains the most */ + /* significant portion of the bit */ + /* count */ + UCHAR nx_sha1_buffer[64]; /* Working buffer for SHA1 algorithm*/ + /* where partial buffers are */ + /* accumulated until a full block */ + /* can be processed */ + ULONG nx_sha1_word_array[80]; /* Working 80 word array */ +} NX_SHA1; + + +/* Define the function prototypes for SHA1. */ + +UINT _nx_sha1_initialize(NX_SHA1 *context); +UINT _nx_sha1_update(NX_SHA1 *context, UCHAR *input_ptr, UINT input_length); +UINT _nx_sha1_digest_calculate(NX_SHA1 *context, UCHAR digest[20]); +VOID _nx_sha1_process_buffer(NX_SHA1 *context, UCHAR buffer[64]); + +#endif diff --git a/addons/websocket/nx_websocket_client.c b/addons/websocket/nx_websocket_client.c new file mode 100644 index 00000000..f335e2d5 --- /dev/null +++ b/addons/websocket/nx_websocket_client.c @@ -0,0 +1,2987 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX WebSocket Component */ +/** */ +/** WebSocket Protocol */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_WEBSOCKET_CLIENT_SOURCE_CODE + +/* Force error checking to be disabled in this module */ + +#ifndef NX_DISABLE_ERROR_CHECKING +#define NX_DISABLE_ERROR_CHECKING +#endif + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "nx_ip.h" +#include "nx_packet.h" +#include "nx_tcp.h" +#include "nx_websocket_client.h" + + +/* Bring in externs for caller checking code. */ + +NX_CALLER_CHECKING_EXTERNS + +#define NX_WEBSOCKET_CRLF "\r\n" +#define NX_WEBSOCKET_CRLF_SIZE 2 + +#define NX_WEBSOCKET_HEADER_MINIMUM_LENGTH 2 + +#define NX_WEBSOCKET_ACCEPT_PREDEFINED_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" +#define NX_WEBSOCKET_ACCEPT_PREDEFINED_GUID_SIZE (sizeof(NX_WEBSOCKET_ACCEPT_PREDEFINED_GUID) - 1) +#define NX_WEBSOCKET_ACCEPT_DIGEST_SIZE 20 /* The length of SHA-1 hash is 20 bytes */ +#define NX_WEBSOCKET_ACCEPT_KEY_SIZE 28 /* The base64 encode key for 20 bytes digest requires (27 bytes name size + 1 byte pad) = 28 bytes */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_create PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket instance create */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* client_name Name of this WebSocket */ +/* ip_ptr Pointer to IP instance */ +/* pool_ptr Pointer to packet pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_create Actual websocket create call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr) +{ + +UINT status; + + /* Check for invalid input pointers. */ + if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) || + (client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id == NX_WEBSOCKET_CLIENT_ID) || + (pool_ptr == NX_NULL) || (pool_ptr -> nx_packet_pool_id != NX_PACKET_POOL_ID)) + { + return(NX_PTR_ERROR); + } + + /* Call actual client create function. */ + status = _nx_websocket_client_create(client_ptr, client_name, ip_ptr, pool_ptr); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_create PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates an instance for WebSocket Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* client_name Name of this WebSocket */ +/* ip_ptr Pointer to IP instance */ +/* pool_ptr Pointer to packet pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr) +{ + +UINT status; + + /* Clear the WebSocket structure. */ + memset((void *)client_ptr, 0, sizeof(NX_WEBSOCKET_CLIENT)); + + /* Create WebSocket mutex. */ + status = tx_mutex_create(&client_ptr -> nx_websocket_client_mutex, (CHAR *)client_name, TX_NO_INHERIT); + if (status) + { + return(status); + } + + /* Save the Client name. */ + client_ptr -> nx_websocket_client_name = client_name; + + /* Save the IP pointer address. */ + client_ptr -> nx_websocket_client_ip_ptr = ip_ptr; + + /* Save the packet pool pointer. */ + client_ptr -> nx_websocket_client_packet_pool_ptr = pool_ptr; + + /* Set the Client ID to indicate the WebSocket client thread is ready. */ + client_ptr -> nx_websocket_client_id = NX_WEBSOCKET_CLIENT_ID; + + /* Update the state. */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + + /* Return successful completion. */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_delete PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket instance delete */ +/* function call. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_delete Actual websocket delete call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr) +{ + +UINT status; + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID)) + { + return(NX_PTR_ERROR); + } + + /* Call actual client delete function. */ + status = _nx_websocket_client_delete(client_ptr); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_delete PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function deletes an instance for WebSocket Client. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* */ +/* OUTPUT */ +/* */ +/* _nx_websocket_client_cleanup Cleanup unused resources */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr) +{ + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Clean up unused resources. */ + _nx_websocket_client_cleanup(client_ptr); + + /* Set the Client ID to a default value. */ + client_ptr -> nx_websocket_client_id = 0; + + /* Update the state. */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_INITIALIZE; + + /* Release the mutex, delete the mutex and assign the pointer to NULL. */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + tx_mutex_delete(&(client_ptr -> nx_websocket_client_mutex)); + + /* Return successful completion. */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_connect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket connect. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* socket_ptr Pointer to TCP socket */ +/* host Pointer to host */ +/* host_length Length of host */ +/* uri_path Pointer to uri path */ +/* uri_path_length Length of uri path */ +/* protocol Pointer to protocol */ +/* protocol_length Length of protocol */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_connect Actual websocket connect call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID) || + (socket_ptr == NX_NULL) || (socket_ptr -> nx_tcp_socket_id != NX_TCP_ID) || + (host == NX_NULL) || (host_length == 0) || + (uri_path == NX_NULL) || (uri_path_length == 0) || + (protocol == NX_NULL) || (protocol_length == 0)) + { + return(NX_PTR_ERROR); + } + + /* Call actual connect function. */ + status = _nx_websocket_client_connect(client_ptr, socket_ptr, host, host_length, uri_path, uri_path_length, protocol, protocol_length, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_connect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function makes a WebSocket connection over TCP socket to the */ +/* server. */ +/* Note: Application must establish a TCP connection before. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* socket_ptr Pointer to TCP socket */ +/* host Pointer to host */ +/* host_length Length of host */ +/* uri_path Pointer to uri path */ +/* uri_path_length Length of uri path */ +/* protocol Pointer to protocol */ +/* protocol_length Length of protocol */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr, + UCHAR *host, UINT host_length, + UCHAR *resource, UINT resource_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option) +{ + +UINT status; + + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Check the state. */ + if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTED) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_ALREADY_CONNECTED); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTING) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_CONNECTING); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_INITIALIZE) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_INVALID_STATE); + } + + /* Save the socket pointer. */ + client_ptr -> nx_websocket_client_socket_ptr = socket_ptr; + +#ifdef NX_SECURE_ENABLE + client_ptr -> nx_websocket_client_use_tls = NX_FALSE; +#endif /* NX_SECURE_ENABLE */ + + status = _nx_websocket_client_connect_internal(client_ptr, host, host_length, resource, resource_length, protocol, protocol_length, wait_option); + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_connect_internal PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function makes a WebSocket connection over TCP socket or TLS */ +/* session to the server. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* host Pointer to host */ +/* host_length Length of host */ +/* uri_path Pointer to uri path */ +/* uri_path_length Length of uri path */ +/* protocol Pointer to protocol */ +/* protocol_length Length of protocol */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_allocate Allocate a packet */ +/* nx_packet_release Release the packet */ +/* nx_secure_tls_packet_allocate Allocate a TLS packet */ +/* nx_packet_data_append Append data */ +/* _nx_utility_base64_encode Base64 encode */ +/* _nx_websocket_client_packet_send Send out websocket packet */ +/* _nx_websocket_client_packet_receive Receive a websocket packet */ +/* _nx_websocket_client_connect_response_check */ +/* Process connect response */ +/* _nx_websocket_client_cleanup Cleanup resources */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect Make websocket connection */ +/* _nx_websocket_client_secure_connect Make secure websocket */ +/* connection */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_connect_internal(NX_WEBSOCKET_CLIENT *client_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option) +{ + +UINT i; +UINT status; +NX_PACKET *packet_ptr; + + + /* To guarantee resources are cleaned-up if a re-connect happens. */ + _nx_websocket_client_cleanup(client_ptr); + + /* Generate GUID for WebSocket Key. */ + for (i = 0; i < NX_WEBSOCKET_CLIENT_GUID_SIZE; i ++) + { + client_ptr -> nx_websocket_client_guid[i] = (UCHAR)(NX_RAND()); + } + + /* Encode the GUID as key. */ + _nx_utility_base64_encode(client_ptr -> nx_websocket_client_guid, NX_WEBSOCKET_CLIENT_GUID_SIZE, + client_ptr -> nx_websocket_client_key, NX_WEBSOCKET_CLIENT_KEY_SIZE, + &client_ptr -> nx_websocket_client_key_size); + + /* Release the mutex */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + + /* Allocate a packet. */ +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nx_websocket_client_use_tls) + { + + /* Use TLS packet allocate. The TLS packet allocate is able to count for + TLS-related header space including crypto initial vector area. */ + status = nx_secure_tls_packet_allocate(client_ptr -> nx_websocket_client_tls_session_ptr, + client_ptr -> nx_websocket_client_packet_pool_ptr, + &packet_ptr, TX_WAIT_FOREVER); + } + else + { +#endif /* NX_SECURE_ENABLE */ + + /* Allocate packet. */ + if (client_ptr -> nx_websocket_client_socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + status = nx_packet_allocate(client_ptr -> nx_websocket_client_packet_pool_ptr, + &packet_ptr, + NX_IPv4_TCP_PACKET, wait_option); + } + else + { + status = nx_packet_allocate(client_ptr -> nx_websocket_client_packet_pool_ptr, + &packet_ptr, + NX_IPv6_TCP_PACKET, wait_option); + } +#ifdef NX_SECURE_ENABLE + } +#endif /* NX_SECURE_ENABLE */ + + /* Check status. */ + if (status) + { + + /* Obtain the mutex again and return error status. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + return(status); + } + + /* WebSocket opening handshake message format: + GET /mqtt HTTP/1.1\r\n + Host: example.com\r\n + Upgrade: websocket\r\n + connection: Upgrade\r\n + Sec-WebSocket-Key: xxxxxxx=\r\n + Sec-WebSocket-Protocol: mqtt\r\n + Sec-WebSocket-Version: 13\r\n + \r\n + */ + + /* Build the GET request: Get + Request URI + HTTP version. */ + status = nx_packet_data_append(packet_ptr, "GET ", sizeof("GET ") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, uri_path, uri_path_length, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, " HTTP/1.1", sizeof(" HTTP/1.1") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the Host in the header. */ + status += nx_packet_data_append(packet_ptr, "Host: ", sizeof("Host: ") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, host, host_length, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the Upgrade in the header. */ + status += nx_packet_data_append(packet_ptr, "Upgrade: websocket", sizeof("Upgrade: websocket") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the Connection in the header. */ + status += nx_packet_data_append(packet_ptr, "Connection: Upgrade", sizeof("Connection: Upgrade") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the Sec-WebSocket-Key in the header. */ + status += nx_packet_data_append(packet_ptr, "Sec-WebSocket-Key: ", sizeof("Sec-WebSocket-Key: ") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, client_ptr -> nx_websocket_client_key, client_ptr -> nx_websocket_client_key_size, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the connection in the header. */ + status += nx_packet_data_append(packet_ptr, "Sec-WebSocket-Protocol: ", sizeof("Sec-WebSocket-Protocol: ") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, protocol, protocol_length, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Place the connection in the header. */ + status += nx_packet_data_append(packet_ptr, "Sec-WebSocket-Version: 13", sizeof("Sec-WebSocket-Version: 13") - 1, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Fill the last \r\n. */ + status += nx_packet_data_append(packet_ptr, NX_WEBSOCKET_CRLF, NX_WEBSOCKET_CRLF_SIZE, client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Check status. */ + if (status) + { + + /* Obtain the mutex, release the packet and return error status. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + nx_packet_release(packet_ptr); + return(NX_WEBSOCKET_DATA_APPEND_FAILURE); + } + + /* Send out the packet. */ + status = _nx_websocket_client_packet_send(client_ptr, packet_ptr, wait_option); + if (status) + { + + /* Release the packet and return error status. */ + nx_packet_release(packet_ptr); + return(status); + } + + /* Obtain the mutex again. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Update the subprotocol name and length */ + client_ptr -> nx_websocket_client_subprotocol = protocol; + client_ptr -> nx_websocket_client_subprotocol_length = protocol_length; + + /* Update the state. */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_CONNECTING; + + /* Set the frame flag to be unfragmented and corresponding opcode to be zero */ + client_ptr -> nx_websocket_client_frame_fragmented = NX_FALSE; + client_ptr -> nx_websocket_client_frame_opcode = 0; + + /* Check if using non-blocking mode. */ + if (wait_option == 0) + { + return(NX_IN_PROGRESS); + } + + while (1) + { + + /* Receive response. */ + status = _nx_websocket_client_packet_receive(client_ptr, &packet_ptr, wait_option); + if (status) + { + return(status); + } + + /* Process the response. */ + status = _nx_websocket_client_connect_response_check(client_ptr, packet_ptr, wait_option); + + /* If status is NX_IN_PROGRESS, continue to receive connect response. + Otherwise, break the while loop. */ + if (status != NX_IN_PROGRESS) + { + break; + } + } + + /* Return status. */ + return(status); +} + +#ifdef NX_SECURE_ENABLE +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_secure_connect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket secure connect. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* tls_session Pointer to TLS session */ +/* host Pointer to host */ +/* host_length Length of host */ +/* uri_path Pointer to uri path */ +/* uri_path_length Length of uri path */ +/* protocol Pointer to protocol */ +/* protocol_length Length of protocol */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_secure_connect Actual websocket connect call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID) || + (tls_session == NX_NULL) || + (host == NX_NULL) || (host_length == 0) || + (uri_path == NX_NULL) || (uri_path_length == 0) || + (protocol == NX_NULL) || (protocol_length == 0)) + { + return(NX_PTR_ERROR); + } + + /* Call actual secure connect function. */ + status = _nx_websocket_client_secure_connect(client_ptr, tls_session, host, host_length, uri_path, uri_path_length, protocol, protocol_length, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_secure_connect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function makes a WebSocket connection over TLS session to the */ +/* server. */ +/* Note: Application must establish a TLS connection before. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* tls_session Pointer to TLS session */ +/* host Pointer to host */ +/* host_length Length of host */ +/* uri_path Pointer to uri path */ +/* uri_path_length Length of uri path */ +/* protocol Pointer to protocol */ +/* protocol_length Length of protocol */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option) +{ + +UINT status; + + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Check the state. */ + if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTED) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_ALREADY_CONNECTED); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTING) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_CONNECTING); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_INITIALIZE) + { + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_INVALID_STATE); + } + + /* Save the tls session pointer. */ + client_ptr -> nx_websocket_client_tls_session_ptr = tls_session; + client_ptr -> nx_websocket_client_use_tls = NX_TRUE; + + status = _nx_websocket_client_connect_internal(client_ptr, host, host_length, uri_path, uri_path_length, protocol, protocol_length, wait_option); + + /* Release the mutex and return */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); +} +#endif /* NX_SECURE_ENABLE */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_name_compare PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function compares two pieces of memory case insensitive. */ +/* */ +/* INPUT */ +/* */ +/* src Pointer to source */ +/* src_length Length of source */ +/* dest Pointer to destination */ +/* dest_length Length of destination */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect_response_process */ +/* Process connect response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_name_compare(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length) +{ +UCHAR ch; + + /* Compare the length. */ + if(src_length != dest_length) + { + return(NX_WEBSOCKET_ERROR); + } + + while(src_length) + { + + /* Is src lowercase? */ + if((*src >= 'a') && (*src <= 'z')) + ch = (UCHAR)(*src - 'a' + 'A'); + + /* Is src uppercase? */ + else if((*src >= 'A') && (*src <= 'Z')) + ch = (UCHAR)(*src - 'A' + 'a'); + else + ch = *src; + + /* Compare case insensitive. */ + if((*src != *dest) && (ch != *dest)) + { + return(NX_WEBSOCKET_ERROR); + } + + /* Pickup next character. */ + src_length--; + src++; + dest++; + } + + return(NX_WEBSOCKET_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_connect_response_process PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes connect response. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_name_compare Compare memory data */ +/* _nx_sha1_initialize Initialize sha1 */ +/* _nx_sha1_update Update sha1 */ +/* _nx_sha1_digest_calculate Calculate sha1 digest */ +/* _nx_utility_base64_encode Base64 encode */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect_response_check */ +/* Check connect response */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_connect_response_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr) +{ +UCHAR *buffer_ptr; +UINT offset; +UCHAR *field_name; +UINT field_name_length; +UCHAR *field_value; +UINT field_value_length; +UCHAR digest[NX_WEBSOCKET_ACCEPT_DIGEST_SIZE]; +UCHAR key[NX_WEBSOCKET_ACCEPT_KEY_SIZE + 1]; +UINT key_size = 0; +UCHAR upgrade_flag = NX_FALSE; +UCHAR connection_flag = NX_FALSE; +UCHAR protocol_cnt = 0; +UCHAR accept_cnt = 0; + + NX_PARAMETER_NOT_USED(client_ptr); + + /* WebSocket opening handshake message format: + HTTP/1.1 101 Switching Protocols + Upgrade: websocket\r\n + Server: Microsoft-HTTPAPI/2.0\r\n + Sec-WebSocket-Protocol: mqtt\r\n + Connection: Upgrade\r\n + Sec-WebSocket-Accept: xxxxxxxxxx=\r\n + Date: Mon, 06 Jun 2022 07:46:53 GMT\r\n + \r\n + */ + + /* Setup pointer and offset. */ + buffer_ptr = packet_ptr -> nx_packet_prepend_ptr; + offset = 0; + + /* Check the length. */ + if ((packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < 12) + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + /* Check the status code. Must be "101" Switching Protocols. */ + if ((buffer_ptr[9] != '1') || (buffer_ptr[10] != '0') || (buffer_ptr[11] != '1')) + { + return(NX_WEBSOCKET_INVALID_STATUS_CODE); + } + + /* Skip over the first HTTP line (HTTP/1.1 101 Switching Protocols\r\n). */ + offset = 12; + buffer_ptr += 12; + while(((buffer_ptr + 1) < packet_ptr -> nx_packet_append_ptr) && + (*buffer_ptr != '\r') && (*(buffer_ptr + 1) != '\n')) + { + buffer_ptr++; + offset++; + } + + /* Skip over the CR,LF. */ + buffer_ptr += 2; + offset += 2; + + /* Loop until we find the "cr,lf,cr,lf" token. */ + while (((buffer_ptr + 1) < packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != 0)) + { + + /* Check for the token. This signals a blank line, which also + specifies the start of the content. */ + if ((*buffer_ptr == '\r') && + (*(buffer_ptr + 1) == '\n')) + { + + /* Adjust the offset. */ + offset = offset + 2; + break; + } + + /* We haven't seen the so we are still processing header data. + Extract the field name and it's value. */ + field_name = buffer_ptr; + field_name_length = 0; + + /* Look for the ':' that separates the field name from its value. */ + while ((buffer_ptr < packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != ':')) + { + buffer_ptr++; + field_name_length++; + } + offset += field_name_length; + + /* Skip ':'. */ + buffer_ptr++; + offset++; + + /* Now skip over white space. */ + while ((buffer_ptr < packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr == ' ')) + { + buffer_ptr++; + offset++; + } + + /* Now get the field value. */ + field_value = buffer_ptr; + field_value_length = 0; + + /* Loop until we see a . */ + while (((buffer_ptr + 1) < packet_ptr -> nx_packet_append_ptr) && (*buffer_ptr != '\r') && (*(buffer_ptr+1) != '\n')) + { + buffer_ptr++; + field_value_length++; + } + offset += field_value_length; + + /* Skip over the CR,LF. */ + buffer_ptr += 2; + offset += 2; + + /* Check the upgrade. */ + if (_nx_websocket_client_name_compare((UCHAR *)field_name, field_name_length, (UCHAR *)"Upgrade", sizeof("Upgrade") - 1) == NX_SUCCESS) + { + if (_nx_websocket_client_name_compare((UCHAR *)field_value, field_value_length, (UCHAR *)"websocket", sizeof("websocket") - 1)) + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + upgrade_flag = NX_TRUE; + } + else if (_nx_websocket_client_name_compare((UCHAR *)field_name, field_name_length, (UCHAR *)"Connection", sizeof("Connection") - 1) == NX_SUCCESS) + { + if (_nx_websocket_client_name_compare((UCHAR *)field_value, field_value_length, (UCHAR *)"Upgrade", sizeof("Upgrade") - 1)) + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + connection_flag = NX_TRUE; + } + else if (_nx_websocket_client_name_compare((UCHAR *)field_name, field_name_length, (UCHAR *)"Sec-WebSocket-Protocol", sizeof("Sec-WebSocket-Protocol") - 1) == NX_SUCCESS) + { + if (_nx_websocket_client_name_compare((UCHAR *)field_value, field_value_length, client_ptr -> nx_websocket_client_subprotocol, client_ptr -> nx_websocket_client_subprotocol_length)) + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + protocol_cnt++; + } + else if (_nx_websocket_client_name_compare((UCHAR *)field_name, field_name_length, (UCHAR *)"Sec-WebSocket-Accept", sizeof("Sec-WebSocket-Accept") - 1) == NX_SUCCESS) + { + + /* Calculate the SHA-1 hash of the concatenation of the client key and the Globally Unique Identifier (GUID) + Referenced in RFC 6455, Section 1.3, Page 6 */ + _nx_sha1_initialize(&(client_ptr -> nx_websocket_client_sha1)); + _nx_sha1_update(&(client_ptr -> nx_websocket_client_sha1), client_ptr->nx_websocket_client_key, client_ptr->nx_websocket_client_key_size); + _nx_sha1_update(&(client_ptr -> nx_websocket_client_sha1), (UCHAR*)NX_WEBSOCKET_ACCEPT_PREDEFINED_GUID, NX_WEBSOCKET_ACCEPT_PREDEFINED_GUID_SIZE); + _nx_sha1_digest_calculate(&(client_ptr -> nx_websocket_client_sha1), digest); + + /* Encode the hash and compare it with the field value from the server. */ + _nx_utility_base64_encode(digest, NX_WEBSOCKET_ACCEPT_DIGEST_SIZE, key, (NX_WEBSOCKET_ACCEPT_KEY_SIZE + 1), &key_size); + if ((field_value_length != NX_WEBSOCKET_ACCEPT_KEY_SIZE) || (memcmp((void *)field_value, (void *)key, NX_WEBSOCKET_ACCEPT_KEY_SIZE))) /* Use case of memcpy is verified. */ + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + accept_cnt++; + } + } + + /* Check if the all fields are processed and found as required. */ + if ((offset != packet_ptr -> nx_packet_length) || + (upgrade_flag != NX_TRUE) || (connection_flag != NX_TRUE) || + (protocol_cnt != 1) || (accept_cnt != 1)) /* Both sec-websocket-protocol field and sec-websocket-accept field are allowed occur once only. + Reference in RFC 6455, Section 11.3.3 and 11.3.4, Page 59-60 */ + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_disconnect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket disconnect. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_disconnect Actual disconnect call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID)) + { + return(NX_PTR_ERROR); + } + + /* Call actual disconnect function. */ + status = _nx_websocket_client_disconnect(client_ptr, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_disconnect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function disconnects the WebSocket connection created */ +/* previously. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_packet_allocate Allocate websocket packet */ +/* _nx_websocket_client_send Send websocket packet */ +/* nx_packet_release Release websocket packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option) +{ + +UINT status; +NX_PACKET *packet_ptr; + + + /* Check the state. */ + if ((client_ptr -> nx_websocket_client_state <= NX_WEBSOCKET_CLIENT_STATE_IDLE) || (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT)) + { + + /* Return error status */ + return(NX_WEBSOCKET_INVALID_STATE); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTING) + { + + /* Update the state and return */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + return(NX_WEBSOCKET_NOT_CONNECTED); + } + + /* Allocate a packet. */ + status = _nx_websocket_client_packet_allocate(client_ptr, &packet_ptr, wait_option); + + /* Check the status. */ + if (status == NX_SUCCESS) + { + + /* Send out the packet. */ + status = _nx_websocket_client_send(client_ptr, packet_ptr, NX_WEBSOCKET_OPCODE_CONNECTION_CLOSE, NX_TRUE, wait_option); + + /* Check the status. */ + if (status) + { + nx_packet_release(packet_ptr); + } + } + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Check if the CLOSE frame has already been received before */ + if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_RECEIVED) + { + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + } + else /* i.e. The state is CONNECTED */ + { + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT; + } + + /* Release the mutex and return completion status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_send PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket send. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet */ +/* code Opcode: text or binary frame */ +/* is_final Flag: final fragment or not */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_send Actual websocket send call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID) || + (packet_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual send function. */ + status = _nx_websocket_client_send(client_ptr, packet_ptr, code, is_final, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_send PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends Websocket data frame to server. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet */ +/* code Opcode: text or binary frame */ +/* is_final Flag: final fragment or not */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_packet_send Send websocket packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option) +{ + +UINT status; +UCHAR *data_ptr; +NX_PACKET *data_packet; +USHORT message; +ULONG tmp; +UCHAR masking_key[4]; +UINT mask_id = 0; +UINT header_size = NX_WEBSOCKET_HEADER_NORMAL_SIZE; + + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Check the state */ + if (client_ptr -> nx_websocket_client_state < NX_WEBSOCKET_CLIENT_STATE_CONNECTED) + { + + /* Release the mutex and return error status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_NOT_CONNECTED); + } + else if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT) + { + + /* Release the mutex and return error status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_INVALID_STATE); + } + + /* Check the payload length. */ + if (packet_ptr -> nx_packet_length > 65535) + { + + /* Release the mutex and return error status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_NOT_SUPPORTED); + } + else if (packet_ptr -> nx_packet_length > 125) + { + header_size += 2; + } + + /* Check the packet. */ + if ((UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < header_size) + { + + /* Release the mutex and return error status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_INVALID_PACKET); + } + + /* Adjust the pointer for filling the WebSocket header. */ + data_ptr = packet_ptr -> nx_packet_prepend_ptr - header_size; + + /* Fill the first byte (FIN + OPCODE) in header. */ + if (is_final == NX_TRUE) + { + *data_ptr = (UCHAR)(NX_WEBSOCKET_FIN | code); + } + else + { + *data_ptr = (UCHAR)code; + } + data_ptr++; + + /* Fill the next byte for MASK and Payload length. */ + *data_ptr = NX_WEBSOCKET_MASK; + if (packet_ptr -> nx_packet_length < 125) + { + *data_ptr |= (UCHAR)packet_ptr -> nx_packet_length; + data_ptr++; + } + else + { + *data_ptr |= NX_WEBSOCKET_PAYLOAD_LEN_16BITS; + data_ptr++; + + /* Fill the next two bytes for extended payload length. */ + message = (USHORT)packet_ptr -> nx_packet_length; + NX_CHANGE_USHORT_ENDIAN(message); + memcpy(data_ptr, &message, NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE); /* Use case of memcpy is verified. */ + data_ptr += NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE; + } + + /* Fill the masking key, the masking key is a 32-bit value chosen at random, must mask websocket data from client*/ + tmp = (ULONG)NX_RAND(); + masking_key[0] = (UCHAR)(tmp >> 24); + masking_key[1] = (UCHAR)(tmp >> 16); + masking_key[2] = (UCHAR)(tmp >> 8); + masking_key[3] = (UCHAR)(tmp); + memcpy(data_ptr, &masking_key, NX_WEBSOCKET_MASKING_KEY_SIZE); /* Use case of memcpy is verified. */ + data_ptr += NX_WEBSOCKET_MASKING_KEY_SIZE; + + /* Mask all payload data. */ + data_packet = packet_ptr; +#ifndef NX_DISABLE_PACKET_CHAIN + while(data_packet) + { +#endif /* NX_DISABLE_PACKET_CHAIN */ + + data_ptr = data_packet -> nx_packet_prepend_ptr; + while(data_ptr < data_packet -> nx_packet_append_ptr) + { + *data_ptr ^= masking_key[mask_id % 4]; + mask_id++; + data_ptr++; + } + +#ifndef NX_DISABLE_PACKET_CHAIN + data_packet = data_packet -> nx_packet_next; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + /* Update prepend pointer and packet length to include WebSocket header. */ + packet_ptr -> nx_packet_prepend_ptr -= header_size; + packet_ptr -> nx_packet_length += header_size; + + /* Release the mutex */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + + /* Send out the packet. */ + status = _nx_websocket_client_packet_send(client_ptr, packet_ptr, wait_option); + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_receive PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket receive. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* code Opcode: text or binary frame */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_receive Actual websocket receive call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID) || + (packet_ptr == NX_NULL) || (code == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual process function. */ + status = _nx_websocket_client_receive(client_ptr, packet_ptr, code, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_receive PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives Websocket data frame from server. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* code Opcode: text or binary frame */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_packet_receive Receive websocket packet */ +/* _nx_websocket_client_data_process Process data frame */ +/* _nx_websocket_client_connect_response_check */ +/* Check connect response */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option) +{ + +UINT status = NX_SUCCESS; + + + /* Initialize here since packet_ptr will be compared with NX_NULL in following function */ + *packet_ptr = NX_NULL; + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + while (1) /* The while loop ensures parsing all received packets. */ + { + + /* Check the state */ + if ((client_ptr -> nx_websocket_client_state < NX_WEBSOCKET_CLIENT_STATE_CONNECTING) || + (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_RECEIVED)) + { + + /* Release the mutex and return error status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(NX_WEBSOCKET_INVALID_STATE); + } + + /* If the state is NX_WEBSOCKET_CLIENT_STATE_CONNECTING, the received packet should be connect response. */ + if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_CONNECTING) + { + + /* Receive the data packet */ + status = _nx_websocket_client_packet_receive(client_ptr, packet_ptr, wait_option); + if (status != NX_SUCCESS) + { + + /* Release the mutex and return status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); + } + + /* Process the connect response. */ + status = _nx_websocket_client_connect_response_check(client_ptr, *packet_ptr, wait_option); + + if ((status == NX_SUCCESS) || (status == NX_IN_PROGRESS)) + { + + /* Continue to receive remaining connect response or application data. */ + continue; + } + else + { + + /* Release the mutex and return status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); + } + } + else + { + + /* Check if there is an existing complete frame in the waiting list */ + if ((status == NX_SUCCESS) && (client_ptr -> nx_websocket_client_processing_packet != NX_NULL)) + { + + /* Parse the data packet. */ + status = _nx_websocket_client_data_process(client_ptr, packet_ptr, code); + if (status != NX_CONTINUE) + { + + /* Release the mutex and return directly if a complete frame is parsed or any error status is found. */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); + } + } + + /* No existing frame, go to receive the data packet */ + status = _nx_websocket_client_packet_receive(client_ptr, packet_ptr, wait_option); + if (status != NX_SUCCESS) + { + + /* Release the mutex and return status */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); + } + + /* Parse with the new data packet. */ + status = _nx_websocket_client_data_process(client_ptr, packet_ptr, code); + if (status != NX_CONTINUE) + { + + /* Release the mutex and return directly if a complete frame is parsed or any error status is found. */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + return(status); + } + + /* Due to no application data found, continue to check if there is any pending data packet. */ + } + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_data_process PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes Websocket data frame from server. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* code Opcode: text or binary frame */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_data_extract_offset Extract data from packet */ +/* nx_packet_allocate Allocate a packet */ +/* _nx_websocket_client_packet_trim Trim data from packet */ +/* _nx_websocket_client_cleanup Cleanup resource */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_receive Receive websocket data */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_data_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code) +{ +UINT status; +UCHAR fin_bit = NX_FALSE; +UCHAR opcode = 0; +UCHAR bytes[4]; +ULONG payload_length; +ULONG offset = 0; +ULONG bytes_copied; +ULONG packet_length; +NX_PACKET *data_packet; +UCHAR *data_ptr; + + + /* Is there a packet waiting for processing? */ + if (client_ptr -> nx_websocket_client_processing_packet) + { + if (*packet_ptr != NX_NULL) + { + + /* Yes. Link received packet to existing one. */ + if (client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last) + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last -> nx_packet_next = *packet_ptr; + } + else + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_next = *packet_ptr; + } + if ((*packet_ptr) -> nx_packet_last) + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last = (*packet_ptr) -> nx_packet_last; + } + else + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last = *packet_ptr; + } + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_length += (*packet_ptr) -> nx_packet_length; + } + + /* Make packet_ptr point to the waiting list */ + *packet_ptr = client_ptr -> nx_websocket_client_processing_packet; + } + else + { + if (*packet_ptr == NX_NULL) + { + return(NX_WEBSOCKET_INVALID_PACKET); + } + + client_ptr -> nx_websocket_client_processing_packet = *packet_ptr; + } + + /* Check if the websocket frame header shall be parsed and found first */ + if (client_ptr -> nx_websocket_client_frame_header_found == NX_FALSE) + { + + /* Parse the first 2 bytes. */ + if (nx_packet_data_extract_offset(*packet_ptr, offset, bytes, NX_WEBSOCKET_HEADER_MINIMUM_LENGTH, &bytes_copied) + || (bytes_copied < NX_WEBSOCKET_HEADER_MINIMUM_LENGTH)) + { + return(NX_CONTINUE); + } + + /* Update the offset */ + offset += NX_WEBSOCKET_HEADER_MINIMUM_LENGTH; + + /* Obtain the fin bit and opcode */ + fin_bit = bytes[0] & NX_WEBSOCKET_FIN_MASK; + opcode = bytes[0] & NX_WEBSOCKET_OPCODE_MASK; + + /* Parse the mask bit and payload length */ + if (bytes[1] & NX_WEBSOCKET_MASK) + { + client_ptr -> nx_websocket_client_frame_masked = NX_TRUE; + } + else + { + client_ptr -> nx_websocket_client_frame_masked = NX_FALSE; + } + + payload_length = (UCHAR)(bytes[1] & NX_WEBSOCKET_PAYLOAD_LEN_MASK); + if (payload_length < 126) + { + + /* No extend payload length; record data payload length directly. */ + } + else if (payload_length == 126) + { + + /* Extract the 16-bit extended data payload length */ + if (nx_packet_data_extract_offset(*packet_ptr, offset, bytes, NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE, &bytes_copied) + || (bytes_copied < NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE)) + { + return(NX_CONTINUE); + } + + /* Record 16-bit data payload length. */ + payload_length = ((((ULONG)bytes[0]) << 8) + (ULONG)bytes[1]); + + /* Add the byte count by the payload size */ + offset += NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE; + } + else + { + + /* Since 64 bits extend payload length is not supported, clean up and return directly. */ + _nx_websocket_client_cleanup(client_ptr); + return(NX_NOT_SUPPORTED); + } + + /* Parse the masking key */ + if (client_ptr -> nx_websocket_client_frame_masked == NX_TRUE) + { + if (nx_packet_data_extract_offset(*packet_ptr, offset, bytes, NX_WEBSOCKET_MASKING_KEY_SIZE, &bytes_copied) + || (bytes_copied < NX_WEBSOCKET_MASKING_KEY_SIZE)) + { + return(NX_CONTINUE); + } + + /* Get the masking key. */ + memcpy(client_ptr -> nx_websocket_client_frame_masking_key, bytes, NX_WEBSOCKET_MASKING_KEY_SIZE); /* Use case of memcpy is verified. */ + + /* Add the byte count by the masking key size */ + offset += NX_WEBSOCKET_MASKING_KEY_SIZE; + } + + /* Set the flag to indicate the frame header found, and re-initialize corresponding variables */ + client_ptr -> nx_websocket_client_frame_header_found = NX_TRUE; + client_ptr -> nx_websocket_client_frame_data_received = 0; + + /* Record the payload length for judging if all payload data received */ + client_ptr -> nx_websocket_client_frame_data_length = payload_length; + + /* Check the rules apply to fragmentation corresponding to the FIN bit and opcode + RFC 6455, Section 5.4, Page 33-35 */ + if (fin_bit == NX_WEBSOCKET_FIN) /* This is the final frame (tip: the first frame may also be the final frame) */ + { + if (client_ptr -> nx_websocket_client_frame_fragmented == NX_FALSE) /* A single unfragmented frame shall be received */ + { + if (opcode == 0) /* The opcode should not denotes a continuation frame for a single unfragmented frame */ + { + _nx_websocket_client_cleanup(client_ptr); + return(NX_INVALID_PACKET); + } + + /* Update the header opcode */ + client_ptr -> nx_websocket_client_frame_opcode = opcode; + } + else /* This is the termination frame in overall fragmented frames */ + { + if (opcode != 0) /* The opcode of the termination frame shall be zero */ + { + _nx_websocket_client_cleanup(client_ptr); + return(NX_INVALID_PACKET); + } + + /* Set the header flag to be unfragmented for next time to use */ + client_ptr -> nx_websocket_client_frame_fragmented = NX_FALSE; + } + } + else /* This is not the final header */ + { + if (client_ptr -> nx_websocket_client_frame_fragmented == NX_FALSE) /* This is the beginning frame in fragmented frames */ + { + + /* The opcode of the beginning frame shall indicate the opcode of overall fragmented frames. Besides, + since control frames cannot be fragmented, the supported frame type shall be text or binary */ + if ((opcode != NX_WEBSOCKET_OPCODE_BINARY_FRAME) && (opcode != NX_WEBSOCKET_OPCODE_TEXT_FRAME)) + { + _nx_websocket_client_cleanup(client_ptr); + return(NX_INVALID_PACKET); + } + + /* Update the frame fragmented flag and the opcode since a beginning frame is received */ + client_ptr -> nx_websocket_client_frame_fragmented = NX_TRUE; + client_ptr -> nx_websocket_client_frame_opcode = opcode; + } + else /* This is a continuation frame in overall fragmented frames */ + { + if (opcode != 0) /* The opcode of a continuation frame shall be zero */ + { + _nx_websocket_client_cleanup(client_ptr); + return(NX_INVALID_PACKET); + } + } + } + + /* Trim the WebSocket header */ + status = _nx_websocket_client_packet_trim(client_ptr, packet_ptr, offset); + client_ptr -> nx_websocket_client_processing_packet = *packet_ptr; + if (status) + { + if (status == NX_NO_PACKET) + { + + /* Try to receive more payload data from TCP/TLS if the packet holds the WebSocket header only */ + return(NX_CONTINUE); + } + + /* Return error status */ + return(status); + } + } + + /* Reset payload length and use the variable to count the data length processed by the function call this time */ + payload_length = 0; + + /* Unmask payload data if there is masking key. */ + if (client_ptr -> nx_websocket_client_frame_masked == NX_TRUE) + { + data_packet = (*packet_ptr); +#ifndef NX_DISABLE_PACKET_CHAIN + while (data_packet && client_ptr -> nx_websocket_client_frame_header_found) + { +#endif /* NX_DISABLE_PACKET_CHAIN */ + + data_ptr = (*packet_ptr) -> nx_packet_prepend_ptr; + while (data_ptr < data_packet -> nx_packet_append_ptr) + { + + /* Unmask payload data byte by byte */ + *data_ptr ^= client_ptr -> nx_websocket_client_frame_masking_key[client_ptr -> nx_websocket_client_frame_data_received % 4]; + data_ptr++; + + /* Increase the payload length for the usage in frame process */ + payload_length++; + + /* Check and jump out if all data payload in the frame have been processed. */ + client_ptr -> nx_websocket_client_frame_data_received++; + if (client_ptr -> nx_websocket_client_frame_data_received >= client_ptr -> nx_websocket_client_frame_data_length) + { + + /* Reset the frame header flag as not found and break. */ + client_ptr -> nx_websocket_client_frame_header_found = NX_FALSE; + break; + } + } + +#ifndef NX_DISABLE_PACKET_CHAIN + data_packet = data_packet -> nx_packet_next; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + + /* Add the payload length if no masking key */ + else + { + + /* Check and adjust received data length for processing */ + payload_length = (*packet_ptr) -> nx_packet_length; + if (payload_length >= (client_ptr -> nx_websocket_client_frame_data_length - client_ptr -> nx_websocket_client_frame_data_received)) + { + + /* The maximum the payload length for each frame process shall not exceed the remaining frame data to be received */ + payload_length = (client_ptr -> nx_websocket_client_frame_data_length - client_ptr -> nx_websocket_client_frame_data_received); + + /* Reset the frame header flag as not found. */ + client_ptr -> nx_websocket_client_frame_header_found = NX_FALSE; + } + + /* Add the length to the total count */ + client_ptr -> nx_websocket_client_frame_data_received += payload_length; + } + + /* Check the opcode for the received frame, and return corresponding status. */ + switch (opcode) + { + case NX_WEBSOCKET_OPCODE_CONTINUATION_FRAME: + case NX_WEBSOCKET_OPCODE_TEXT_FRAME: + case NX_WEBSOCKET_OPCODE_BINARY_FRAME: + { + + /* Assign the return opcode by the pre-stored opcode */ + *code = client_ptr -> nx_websocket_client_frame_opcode; + + /* Update the offset by payload length */ + offset = payload_length; + + /* For a data frame (i.e. text/binary frame), search and find the end of the complete frame */ + data_packet = *packet_ptr; + packet_length = (ULONG)(data_packet -> nx_packet_append_ptr - data_packet -> nx_packet_prepend_ptr); + while (packet_length < offset) + { + offset -= packet_length; + + /* Move the current data packet pointer to next and compute the length of next packet */ + data_packet = data_packet -> nx_packet_next; + packet_length = (ULONG)(data_packet -> nx_packet_append_ptr - data_packet -> nx_packet_prepend_ptr); + } + + /* After subtracting by the offset, packet_length represents the size of remaining data in the single packet to be linked into the waiting list */ + packet_length -= offset; + + /* Check if the frame end is just in the end of one of the packet(s) */ + if (packet_length == 0) + { + + /* Put remaining packet(s) into the waiting list */ + client_ptr -> nx_websocket_client_processing_packet = data_packet -> nx_packet_next; + + /* Check if there is data remaining and determine whether to go on to following logic. */ + if (data_packet -> nx_packet_next == NX_NULL) + { + + /* The packet is fully parsed, return success directly. */ + return(NX_WEBSOCKET_SUCCESS); + } + } + else /* One more frame in the packet */ + { + + /* Release the mutex. */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + + /* Allocate a packet for the remaining data in the packet. */ + status = nx_packet_allocate((*packet_ptr) -> nx_packet_pool_owner, &client_ptr -> nx_websocket_client_processing_packet, NX_RECEIVE_PACKET, NX_WAIT_FOREVER); + + /* The return status may be not NX_SUCCESS only there is an unexpected issue from the packet pool (e.g. a delete operation ). + Assert here for the unexpected issue shall not happen in normal status */ + NX_ASSERT(status == NX_SUCCESS); + + /* Obtain the mutex again. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Copy the contents of the remaining part of current packet into the new allocated packet */ + memcpy((void *)client_ptr -> nx_websocket_client_processing_packet -> nx_packet_prepend_ptr, + (void *)(data_packet -> nx_packet_prepend_ptr + offset), packet_length); /* Use case of memcpy is verified. */ + + /* Move the append pointer with by the extended length */ + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_append_ptr += packet_length; + + /* Link the possibly had remaining packet(s) to the waiting list. The overall packet length will be updated outside this else branch */ + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_next = data_packet -> nx_packet_next; + } + + /* Update the last packet pointer in the waiting liast */ + if (client_ptr -> nx_websocket_client_processing_packet -> nx_packet_next) + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last = (*packet_ptr) -> nx_packet_last; + } + else + { + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_last = NX_NULL; + } + + /* Update the overall packet length for the waiting list */ + client_ptr -> nx_websocket_client_processing_packet -> nx_packet_length = (*packet_ptr) -> nx_packet_length - payload_length; + + /* Disconnect the link between the return packet and the waiting list */ + data_packet -> nx_packet_next = NX_NULL; + data_packet -> nx_packet_append_ptr -= packet_length; + (*packet_ptr) -> nx_packet_length = payload_length; + + /* Update the last packet pointer of the returned packet */ + if ((*packet_ptr) -> nx_packet_next) + { + (*packet_ptr) -> nx_packet_last = data_packet; + } + else + { + (*packet_ptr) -> nx_packet_last = NX_NULL; + } + + /* Return success status */ + return(NX_WEBSOCKET_SUCCESS); + } + + case NX_WEBSOCKET_OPCODE_CONNECTION_CLOSE: + { + /* Make sure the complete control frame is received */ + if (client_ptr -> nx_websocket_client_frame_data_received < client_ptr -> nx_websocket_client_frame_data_length) + { + return(NX_CONTINUE); + } + + /* A disconnection is informed, notify the application. */ + if (client_ptr -> nx_websocket_client_connection_status_callback) + { + client_ptr -> nx_websocket_client_connection_status_callback(client_ptr, client_ptr -> nx_websocket_client_connection_context, NX_WEBSOCKET_DISCONNECTED); + } + + /* Check the current state and update the state when the CLOSE frame is found */ + if (client_ptr -> nx_websocket_client_state == NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT) + { + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + } + else + { + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_RECEIVED; + } + + /* Return disconnect received status only, without returning any packet data, since it is required no more data after the Close frame. + There is no need to release the packet_ptr since it points to the same memory region as the waiting list + Referenced in RFC 6455, Section 5.5.1, Page 36 */ + _nx_websocket_client_cleanup(client_ptr); + return(NX_WEBSOCKET_DISCONNECTED); + } + + case NX_WEBSOCKET_OPCODE_PING: + case NX_WEBSOCKET_OPCODE_PONG: + { + + /* Make sure the complete control frame is received */ + if (client_ptr -> nx_websocket_client_frame_data_received < client_ptr -> nx_websocket_client_frame_data_length) + { + return(NX_CONTINUE); + } + + /* Trim payload data in the frame. */ + status = _nx_websocket_client_packet_trim(client_ptr, packet_ptr, client_ptr -> nx_websocket_client_frame_data_received); + + /* Update the waiting list */ + client_ptr -> nx_websocket_client_processing_packet = *packet_ptr; + + /* Check if error status happens */ + if ((status != NX_WEBSOCKET_SUCCESS) && (status != NX_NO_PACKET)) + { + return(status); + } + + /* A PING/PONG frame is parsed and found, continue to check any more data or frame received */ + return(NX_CONTINUE); + } + + default: + { + + /* Clean up and return invalid status */ + _nx_websocket_client_cleanup(client_ptr); + return(NX_INVALID_PACKET); + } + } +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_packet_trim PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function trims extra bytes from the data packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* trim_size Number of bytes to remove */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_release Release the packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_data_process Process data frame */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_packet_trim(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG trim_size) +{ + +ULONG packet_length; +NX_PACKET *head_packet_ptr = *packet_ptr; +NX_PACKET *previous_packet_ptr = NX_NULL; + + NX_PARAMETER_NOT_USED(client_ptr); + + /* The trim size shall be less than or equal to the packet length */ + if ((*packet_ptr) -> nx_packet_length < trim_size) + { + return(NX_PACKET_OFFSET_ERROR); + } + packet_length = (*packet_ptr) -> nx_packet_length - trim_size; + + /* Search and find the trim point */ + while ((ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr) <= trim_size) + { + trim_size -= (ULONG)((*packet_ptr) -> nx_packet_append_ptr - (*packet_ptr) -> nx_packet_prepend_ptr); + + previous_packet_ptr = *packet_ptr; + *packet_ptr = (*packet_ptr) -> nx_packet_next; + + if (*packet_ptr == NX_NULL) + { + break; + } + } + + /* Disconnect the link if the trim point is not in the head packet */ + if (previous_packet_ptr != NX_NULL) + { + previous_packet_ptr -> nx_packet_next = NX_NULL; + + /* Set the nx_packet_last pointer due to the packet header changed */ + if (*packet_ptr) + { + (*packet_ptr) -> nx_packet_last = head_packet_ptr -> nx_packet_last; + } + + nx_packet_release(head_packet_ptr); + } + + if (*packet_ptr) + { + + /* Adjust current packet */ + (*packet_ptr) -> nx_packet_prepend_ptr += trim_size; + (*packet_ptr) -> nx_packet_length = packet_length; + + return(NX_WEBSOCKET_SUCCESS); + } + + /* Return this value to tell the caller that the whole packet is trimmed */ + return(NX_NO_PACKET); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_packet_allocate PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket packet allocate. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_packet_allocate Actual websocket allocate call*/ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option) +{ + +UINT status; + + + /* Check for invalid input pointers */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID) || (packet_ptr == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Call actual process function. */ + status = _nx_websocket_client_packet_allocate(client_ptr, packet_ptr, wait_option); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_packet_allocate PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a Websocket packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_allocate Allocate a packet */ +/* nx_packet_release Release packet */ +/* nx_secure_tls_packet_allocate Allocate a TLS packet */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option) +{ + +UINT status; + + +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nx_websocket_client_use_tls) + { + + /* Use TLS packet allocate. The TLS packet allocate is able to count for + TLS-related header space including crypto initial vector area. */ + status = nx_secure_tls_packet_allocate(client_ptr -> nx_websocket_client_tls_session_ptr, + client_ptr -> nx_websocket_client_packet_pool_ptr, + packet_ptr, TX_WAIT_FOREVER); + } + else + { +#endif /* NX_SECURE_ENABLE */ + + /* Allocate packet. */ + if (client_ptr -> nx_websocket_client_socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + status = nx_packet_allocate(client_ptr -> nx_websocket_client_packet_pool_ptr, + packet_ptr, + NX_IPv4_TCP_PACKET, wait_option); + } + else + { + status = nx_packet_allocate(client_ptr -> nx_websocket_client_packet_pool_ptr, + packet_ptr, + NX_IPv6_TCP_PACKET, wait_option); + } +#ifdef NX_SECURE_ENABLE + } +#endif /* NX_SECURE_ENABLE */ + + if (status == NX_SUCCESS) + { + + /* Check the buffer size for the basic data header of websocket. */ + if (((ULONG)(((*packet_ptr) -> nx_packet_data_end) - ((*packet_ptr) -> nx_packet_prepend_ptr))) < NX_WEBSOCKET_HEADER_SIZE) + { + + /* Packet buffer is too small. */ + nx_packet_release(*packet_ptr); + return(NX_WEBSOCKET_INVALID_PACKET); + } + + /* Adjust the pointers. */ + ((*packet_ptr) -> nx_packet_prepend_ptr) += NX_WEBSOCKET_HEADER_SIZE; + ((*packet_ptr) -> nx_packet_append_ptr) += NX_WEBSOCKET_HEADER_SIZE; + } + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_packet_send PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends Websocket packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_tcp_socket_send Send tcp packet */ +/* nx_secure_tls_session_send Send tls packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* _nx_websocket_client_send Send websocket data frame */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_packet_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option) +{ + +UINT status; + +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nx_websocket_client_use_tls) + { + status = nx_secure_tls_session_send(client_ptr -> nx_websocket_client_tls_session_ptr, packet_ptr, wait_option); + } + else + { + status = nx_tcp_socket_send(client_ptr -> nx_websocket_client_socket_ptr, packet_ptr, wait_option); + } +#else + status = nx_tcp_socket_send(client_ptr -> nx_websocket_client_socket_ptr, packet_ptr, wait_option); +#endif /* NX_SECURE_ENABLE */ + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_packet_receive PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives Websocket packet. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet pointer */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_tcp_socket_receive Receive tcp packet */ +/* nx_secure_tls_session_receive Receive tls packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* _nx_websocket_client_receive Receive websocket data frame */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_packet_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option) +{ + +UINT status; + + + /* Release the mutex first */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + +#ifdef NX_SECURE_ENABLE + if (client_ptr -> nx_websocket_client_use_tls) + { + status = nx_secure_tls_session_receive(client_ptr -> nx_websocket_client_tls_session_ptr, packet_ptr, wait_option); + } + else + { + status = nx_tcp_socket_receive(client_ptr -> nx_websocket_client_socket_ptr, packet_ptr, wait_option); + } +#else + status = nx_tcp_socket_receive(client_ptr -> nx_websocket_client_socket_ptr, packet_ptr, wait_option); +#endif /* NX_SECURE_ENABLE */ + + /* Obtain the mutex again. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_connect_response_check PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if a whole connect response is received, then */ +/* process the response. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* packet_ptr Pointer to packet */ +/* wait_option Wait option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* nx_packet_data_append Append data into packet */ +/* nx_packet_release Release packet */ +/* _nx_websocket_client_connect_response_process */ +/* Process connect response */ +/* _nx_websocket_client_cleanup Cleanup resource */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* _nx_websocket_client_receive Receive websocket data frame */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_connect_response_check(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT wait_option) +{ +CHAR *buffer_ptr; +UINT status = NX_SUCCESS; +UINT crlf_found = 0; +NX_PACKET *tmp_ptr; + + + if (client_ptr -> nx_websocket_client_processing_packet == NX_NULL) + { + client_ptr -> nx_websocket_client_processing_packet = packet_ptr; + } + else + { + + /* Its contents now need to be placed in the head packet. */ + tmp_ptr = packet_ptr; + +#ifndef NX_DISABLE_PACKET_CHAIN + while (tmp_ptr) +#endif /* NX_DISABLE_PACKET_CHAIN */ + { + + /* Release the mutex */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + + /* Copy the contents of the current packet into the head packet. */ + status = nx_packet_data_append(client_ptr -> nx_websocket_client_processing_packet, + (VOID *) tmp_ptr -> nx_packet_prepend_ptr, + (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr), + client_ptr -> nx_websocket_client_packet_pool_ptr, wait_option); + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Determine if an error occurred or an unexpected packet chain happens since the connect response shall not exceed the maximum length of one packet */ + if ((status != NX_SUCCESS) || (client_ptr -> nx_websocket_client_processing_packet -> nx_packet_next)) + { + + /* Reset the state to idle */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + + /* Clean up unused resources. */ + _nx_websocket_client_cleanup(client_ptr); + + /* Release the new packet and return. */ + nx_packet_release(packet_ptr); + return(status); + } +#ifndef NX_DISABLE_PACKET_CHAIN + else + { + tmp_ptr = tmp_ptr -> nx_packet_next; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + + /* Release the new packet. */ + nx_packet_release(packet_ptr); + } + + crlf_found = 0; + tmp_ptr = client_ptr -> nx_websocket_client_processing_packet; + + while (1) + { + + /* Build a pointer to the buffer area. */ + buffer_ptr = (CHAR *) tmp_ptr -> nx_packet_prepend_ptr; + + /* See if there is a blank line present in the buffer. */ + /* Search the buffer for a cr/lf pair. */ + while ((buffer_ptr < (CHAR *) tmp_ptr -> nx_packet_append_ptr) && + (crlf_found < 4)) + { + if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13)) + { + + /* Found CR. */ + crlf_found++; + } + else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10)) + { + + /* Found LF. */ + crlf_found++; + } + else + { + + /* Reset the CRLF marker. */ + crlf_found = 0; + } + + /* Move the buffer pointer up. */ + buffer_ptr++; + } + + if (crlf_found == 4) + { + + /* Yes, we have found the end of the HTTP response header. */ + break; + } + +#ifndef NX_DISABLE_PACKET_CHAIN + + if (tmp_ptr -> nx_packet_next != NX_NULL) + { + + /* Get the next packet in the chain. */ + tmp_ptr = tmp_ptr -> nx_packet_next; + } + else +#endif + { + return(NX_IN_PROGRESS); + } + } + + /* Process the response. */ + status = _nx_websocket_client_connect_response_process(client_ptr, client_ptr -> nx_websocket_client_processing_packet); + if (status == NX_SUCCESS) + { + + /* Update the state. */ + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_CONNECTED; + + /* If connection is established, notify application. */ + if (client_ptr -> nx_websocket_client_connection_status_callback) + { + client_ptr -> nx_websocket_client_connection_status_callback(client_ptr, client_ptr -> nx_websocket_client_connection_context, NX_SUCCESS); + } + } + else + { + client_ptr -> nx_websocket_client_state = NX_WEBSOCKET_CLIENT_STATE_IDLE; + } + + /* Clean up unused resources. */ + _nx_websocket_client_cleanup(client_ptr); + + return (status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_websocket_client_connection_status_callback_set */ +/* PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the WebSocket callback set. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* context Context for callback */ +/* connection_status_callback Routine to call when connect */ +/* or disconnect occurs */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_websocket_client_connection_status_callback_set */ +/* Actual websocket callback set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID *context, + VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT)) +{ +UINT status; + + + /* Check for invalid input pointers. */ + if ((client_ptr == NX_NULL) || (client_ptr -> nx_websocket_client_id != NX_WEBSOCKET_CLIENT_ID)) + { + return(NX_PTR_ERROR); + } + + /* Call actual process function. */ + status = _nx_websocket_client_connection_status_callback_set(client_ptr, context, connection_status_callback); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_connection_status_callback_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets Websocket connection callback. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* context Context for callback */ +/* connection_status_callback Routine to call when connect */ +/* or disconnect occurs */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID *context, + VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT)) +{ + + /* Obtain the mutex. */ + tx_mutex_get(&(client_ptr -> nx_websocket_client_mutex), NX_WAIT_FOREVER); + + /* Set the context which will be passed to connection status callback. */ + client_ptr -> nx_websocket_client_connection_context = context; + + /* Set the connection status callback. */ + client_ptr -> nx_websocket_client_connection_status_callback = connection_status_callback; + + /* Release the mutex */ + tx_mutex_put(&(client_ptr -> nx_websocket_client_mutex)); + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_websocket_client_cleanup PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Bo Chen, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleanups resources. */ +/* */ +/* INPUT */ +/* */ +/* client_ptr Pointer to WebSocket Client */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_websocket_client_delete Delete websocket instance */ +/* _nx_websocket_client_data_process Process data frame */ +/* _nx_websocket_client_connect_response_check */ +/* Check connect response */ +/* _nx_websocket_client_connect_internal Make websocket connection */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +void _nx_websocket_client_cleanup(NX_WEBSOCKET_CLIENT *client_ptr) +{ + + /* Reset the flag for frame header found */ + client_ptr -> nx_websocket_client_frame_header_found = NX_FALSE; + + /* Release the waiting list. */ + if (client_ptr -> nx_websocket_client_processing_packet) + { + nx_packet_release(client_ptr -> nx_websocket_client_processing_packet); + client_ptr -> nx_websocket_client_processing_packet = NX_NULL; + } +} diff --git a/addons/websocket/nx_websocket_client.h b/addons/websocket/nx_websocket_client.h new file mode 100644 index 00000000..e4cf8622 --- /dev/null +++ b/addons/websocket/nx_websocket_client.h @@ -0,0 +1,342 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX WebSocket Component */ +/** */ +/** WebSocket Protocol */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nx_websocket_client.h PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the NetX WebSocket Protocol component, including */ +/* all data types and external references. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Bo Chen Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ + +#ifndef NX_WEBSOCKET_CLIENT_H +#define NX_WEBSOCKET_CLIENT_H + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + +#include "nx_api.h" +#include "nx_sha1.h" + +#ifdef NX_SECURE_ENABLE +#include "nx_secure_tls_api.h" +#endif /* NX_SECURE_ENABLE */ + +#ifdef NX_DISABLE_PACKET_CHAIN +#error "NX_DISABLE_PACKET_CHAIN must not be defined" +#endif /* NX_DISABLE_PACKET_CHAIN */ + +/* Define the WebSocket ID. */ +#define NX_WEBSOCKET_CLIENT_ID 0x57454253UL + +/* Define the GUID size. */ +#define NX_WEBSOCKET_CLIENT_GUID_SIZE 16 + +/* Define the WebSocket Key size. */ +#define NX_WEBSOCKET_CLIENT_KEY_SIZE 26 + +/* WebSocket Header Format: + 0 1 2 3 + 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 + +-+-+-+-+-------+-+-------------+-------------------------------+ + |F|R|R|R| opcode|M| Payload len | Extended payload length | + |I|S|S|S| (4) |A| (7) | (16) | + |N|V|V|V| |S| | | + | |1|2|3| |K| | | + +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - + + | Masking-key , if MASK set to 1 | + +-------------------------------- - - - - - - - - - - - - - - - + + | Payload Data... | + +-------------------------------- - - - - - - - - - - - - - - - + +*/ + +/* First two bytes are required. */ + +/* Define FIN. */ +#define NX_WEBSOCKET_FIN 0x80 +#define NX_WEBSOCKET_FIN_MASK 0x80 + +/* Define the opcode. */ +#define NX_WEBSOCKET_OPCODE_CONTINUATION_FRAME 0x00 +#define NX_WEBSOCKET_OPCODE_TEXT_FRAME 0x01 +#define NX_WEBSOCKET_OPCODE_BINARY_FRAME 0x02 +#define NX_WEBSOCKET_OPCODE_CONNECTION_CLOSE 0x08 +#define NX_WEBSOCKET_OPCODE_PING 0x09 +#define NX_WEBSOCKET_OPCODE_PONG 0x0A +#define NX_WEBSOCKET_OPCODE_MASK 0x0F + +/* Define the mask bit. */ +#define NX_WEBSOCKET_MASK 0x80 +#define NX_WEBSOCKET_MASK_MASK 0x80 + +/* Define the payload length, always using 7bits + 16bits for payload length. */ +#define NX_WEBSOCKET_PAYLOAD_LEN_MASK 0x7F +#define NX_WEBSOCKET_PAYLOAD_LEN_16BITS 0x7E /* Payload length: 126, the following 2 bytes interpreted as a 16-bits unsigned integer are the payload length. */ +#define NX_WEBSOCKET_PAYLOAD_LEN_64BITS 0x7F /* Payload length: 127, the following 4 bytes interpreted as a 64-bits unsigned integer are the payload length. */ +#define NX_WEBSOCKET_EXTENDED_PAYLOAD_16BITS_SIZE 2 +#define NX_WEBSOCKET_EXTENDED_PAYLOAD_64BITS_SIZE 8 + +/* Define the masking key size. */ +#define NX_WEBSOCKET_MASKING_KEY_SIZE 4 + +/* Define the basic header size (2 bytes normal header + 4 bytes masking key)*/ +#define NX_WEBSOCKET_HEADER_NORMAL_SIZE 6 + +/* Define the header size (2 bytes normal header + 2 bytes extended payload length + 4 bytes masking key). 8 bytes extended payload length is not supported yet. */ +#define NX_WEBSOCKET_HEADER_SIZE 8 + +/* Define the state. */ +#define NX_WEBSOCKET_CLIENT_STATE_INITIALIZE 0 +#define NX_WEBSOCKET_CLIENT_STATE_IDLE 1 +#define NX_WEBSOCKET_CLIENT_STATE_CONNECTING 2 +#define NX_WEBSOCKET_CLIENT_STATE_CONNECTED 3 +#define NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_SENT 4 +#define NX_WEBSOCKET_CLIENT_STATE_DISCONNECT_RECEIVED 5 + +/* Define the return value. */ +#define NX_WEBSOCKET_SUCCESS 0x0 +#define NX_WEBSOCKET_ERROR 0x30001 +#define NX_WEBSOCKET_CONNECTING 0x30002 +#define NX_WEBSOCKET_ALREADY_CONNECTED 0x30003 +#define NX_WEBSOCKET_NOT_CONNECTED 0x30004 +#define NX_WEBSOCKET_DATA_APPEND_FAILURE 0x30005 +#define NX_WEBSOCKET_INVALID_STATE 0x30006 +#define NX_WEBSOCKET_INVALID_PACKET 0x30007 +#define NX_WEBSOCKET_INVALID_STATUS_CODE 0x30008 +#define NX_WEBSOCKET_DISCONNECTED 0x30009 + +/* Define the websocket Client data structure. */ +typedef struct NX_WEBSOCKET_CLIENT_STRUCT +{ + + /* WebSocket Client ID. */ + ULONG nx_websocket_client_id; + + /* Name of this WebSocket Client. */ + UCHAR *nx_websocket_client_name; + + /* Pointer to associated IP structure. */ + NX_IP *nx_websocket_client_ip_ptr; + + /* Pointer to WebSocket Client packet pool. */ + NX_PACKET_POOL *nx_websocket_client_packet_pool_ptr; + + /* State. */ + UINT nx_websocket_client_state; + + /* Pointer to WebSocket Client TCP socket. */ + NX_TCP_SOCKET *nx_websocket_client_socket_ptr; + +#ifdef NX_SECURE_ENABLE + UINT nx_websocket_client_use_tls; + NX_SECURE_TLS_SESSION *nx_websocket_client_tls_session_ptr; +#endif + + /* Pointer to the received packet to be processed. This packet may be composited by more than one tcp/tls packet. */ + NX_PACKET *nx_websocket_client_processing_packet; + + /* Globally Unique Identifier. */ + UCHAR nx_websocket_client_guid[NX_WEBSOCKET_CLIENT_GUID_SIZE]; + + /* Protocol Name and length */ + UCHAR *nx_websocket_client_subprotocol; + UINT nx_websocket_client_subprotocol_length; + + /* WebSocket-Key. */ + UINT nx_websocket_client_key_size; + UCHAR nx_websocket_client_key[NX_WEBSOCKET_CLIENT_KEY_SIZE]; + + /* Websocket frame header parse context */ + UCHAR nx_websocket_client_frame_header_found; + UCHAR nx_websocket_client_frame_fragmented; + UCHAR nx_websocket_client_frame_opcode; + UCHAR nx_websocket_client_frame_masked; + UCHAR nx_websocket_client_frame_masking_key[4]; + ULONG nx_websocket_client_frame_data_length; + ULONG nx_websocket_client_frame_data_received; + + /* SHA1 in connect response calculation for Sec-Protocol-Accept field */ + NX_SHA1 nx_websocket_client_sha1; + + /* Connection status callback function. */ + VOID (*nx_websocket_client_connection_status_callback)(struct NX_WEBSOCKET_CLIENT_STRUCT *, VOID *, UINT); + + /* Pointer to an argument passed to connection status callback. */ + VOID *nx_websocket_client_connection_context; + + /* Define the websocket protect purpose mutex */ + TX_MUTEX nx_websocket_client_mutex; + +} NX_WEBSOCKET_CLIENT; + + + +#ifndef NX_WEBSOCKET_CLIENT_SOURCE_CODE + +/* Application caller is present, perform API mapping. */ + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + +#ifdef NX_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define nx_websocket_client_create _nx_websocket_client_create +#define nx_websocket_client_delete _nx_websocket_client_delete +#define nx_websocket_client_connect _nx_websocket_client_connect +#ifdef NX_SECURE_ENABLE +#define nx_websocket_client_secure_connect _nx_websocket_client_secure_connect +#endif /* NX_SECURE_ENABLE */ +#define nx_websocket_client_disconnect _nx_websocket_client_disconnect +#define nx_websocket_client_packet_allocate _nx_websocket_client_packet_allocate +#define nx_websocket_client_send _nx_websocket_client_send +#define nx_websocket_client_receive _nx_websocket_client_receive +#define nx_websocket_client_connection_status_callback_set _nx_websocket_client_connection_status_callback_set + +#else + +/* Services with error checking. */ + +#define nx_websocket_client_create _nxe_websocket_client_create +#define nx_websocket_client_delete _nxe_websocket_client_delete +#define nx_websocket_client_connect _nxe_websocket_client_connect +#ifdef NX_SECURE_ENABLE +#define nx_websocket_client_secure_connect _nxe_websocket_client_secure_connect +#endif /* NX_SECURE_ENABLE */ +#define nx_websocket_client_disconnect _nxe_websocket_client_disconnect +#define nx_websocket_client_packet_allocate _nxe_websocket_client_packet_allocate +#define nx_websocket_client_send _nxe_websocket_client_send +#define nx_websocket_client_receive _nxe_websocket_client_receive +#define nx_websocket_client_connection_status_callback_set _nxe_websocket_client_connection_status_callback_set + +#endif /* NX_DISABLE_ERROR_CHECKING */ + +/* Define the prototypes accessible to the application software. */ + +UINT nx_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr); +UINT nx_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr); +UINT nx_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +UINT nx_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +#ifdef NX_SECURE_ENABLE +UINT nx_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +#endif /* NX_SECURE_ENABLE */ +UINT nx_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option); +UINT nx_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option); +UINT nx_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option); +UINT nx_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID *context, + VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT)); + +#else + +/* Websocket source code is being compiled, do not perform any API mapping. */ + +UINT _nxe_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr); +UINT _nx_websocket_client_create(NX_WEBSOCKET_CLIENT *client_ptr, UCHAR *client_name, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr); +UINT _nxe_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr); +UINT _nx_websocket_client_delete(NX_WEBSOCKET_CLIENT *client_ptr); +UINT _nxe_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +UINT _nx_websocket_client_packet_allocate(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +UINT _nxe_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +UINT _nx_websocket_client_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_TCP_SOCKET *socket_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +#ifdef NX_SECURE_ENABLE +UINT _nxe_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +UINT _nx_websocket_client_secure_connect(NX_WEBSOCKET_CLIENT *client_ptr, NX_SECURE_TLS_SESSION *tls_session, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +#endif /* NX_SECURE_ENABLE */ +UINT _nxe_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option); +UINT _nx_websocket_client_disconnect(NX_WEBSOCKET_CLIENT *client_ptr, UINT wait_option); +UINT _nxe_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option); +UINT _nx_websocket_client_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT code, UINT is_final, UINT wait_option); +UINT _nxe_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option); +UINT _nx_websocket_client_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code, UINT wait_option); +UINT _nxe_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID * context, + VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT)); +UINT _nx_websocket_client_connection_status_callback_set(NX_WEBSOCKET_CLIENT *client_ptr, VOID * context, + VOID (*connection_status_callback)(NX_WEBSOCKET_CLIENT *, VOID *, UINT)); + +#endif /* NX_WEBSOCKET_CLIENT_SOURCE_CODE */ + +/* Define internal websocket functions. */ +UINT _nx_websocket_client_connect_internal(NX_WEBSOCKET_CLIENT *client_ptr, + UCHAR *host, UINT host_length, + UCHAR *uri_path, UINT uri_path_length, + UCHAR *protocol, UINT protocol_length,UINT wait_option); +UINT _nx_websocket_client_name_compare(UCHAR *src, ULONG src_length, UCHAR *dest, ULONG dest_length); +UINT _nx_websocket_client_connect_response_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr); +UINT _nx_websocket_client_packet_trim(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG trim_size); +UINT _nx_websocket_client_packet_send(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, ULONG wait_option); +UINT _nx_websocket_client_packet_receive(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, ULONG wait_option); +UINT _nx_websocket_client_data_process(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET **packet_ptr, UINT *code); +UINT _nx_websocket_client_connect_response_check(NX_WEBSOCKET_CLIENT *client_ptr, NX_PACKET *packet_ptr, UINT wait_option); +void _nx_websocket_client_cleanup(NX_WEBSOCKET_CLIENT *client_ptr); + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus + } +#endif + +#endif /* NX_WEBSOCKET_CLIENT_H */ diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 8351a24f..3f6b9b25 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_arp_static_entry_create.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_arp_static_entry_delete.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_arp_static_entry_delete_internal.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_http_proxy_client.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_icmp_cleanup.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_icmp_enable.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_icmp_info_get.c @@ -226,6 +227,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_receive_cleanup.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_accept.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_listen.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_driver_listen.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_relisten.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_unaccept.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_server_socket_unlisten.c @@ -236,6 +238,8 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_delete.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_disconnect.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_disconnect_complete_notify.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_driver_establish.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_driver_packet_receive.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_establish_notify.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_info_get.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_tcp_socket_mss_get.c @@ -287,6 +291,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_checksum_enable.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_create.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_delete.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_driver_packet_receive.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_info_get.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_port_get.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_udp_socket_receive.c diff --git a/common/inc/nx_api.h b/common/inc/nx_api.h index cd56b4eb..9b20cf8c 100644 --- a/common/inc/nx_api.h +++ b/common/inc/nx_api.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_api.h PORTABLE C */ -/* 6.1.2 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -52,6 +52,51 @@ /* 11-09-2020 Yuxin Zhou Modified comment(s), and */ /* updated product constants, */ /* resulting in version 6.1.2 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), added */ +/* PTP timestamp capability, */ +/* added function to convert */ +/* string to unsigned integer, */ +/* updated product constants, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.4 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.5 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* added functions for base64, */ +/* resulting in version 6.1.6 */ +/* 06-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.7 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* added new ip filter, */ +/* added function to convert */ +/* unsigned integer to string, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* added support for getting */ +/* interface type, */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* fixed compiler errors when */ +/* TX_SAFETY_CRITICAL is */ +/* enabled, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -76,12 +121,15 @@ extern "C" { /* Bypass ThreadX API error checking for internal NetX calls. */ +#include "tx_port.h" #ifdef NX_SOURCE_CODE +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif #endif +#endif @@ -97,6 +145,12 @@ extern "C" { #include "tx_trace.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +#ifndef NX_ENABLE_INTERFACE_CAPABILITY +#error "NX_ENABLE_INTERFACE_CAPABILITY must be defined to enable TCP/IP offload" +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Define symbols for compatibility before and after ThreadX 5.8. */ #if (((THREADX_MAJOR_VERSION << 8) | THREADX_MINOR_VERSION) >= 0x0508) #define NX_CLEANUP_PARAMETER , ULONG suspension_sequence @@ -458,8 +512,8 @@ VOID _nx_trace_event_update(TX_TRACE_BUFFER_ENTRY *event, ULONG timestamp, ULONG /* Define basic constants for the NetX TCP/IP Stack. */ #define AZURE_RTOS_NETXDUO #define NETXDUO_MAJOR_VERSION 6 -#define NETXDUO_MINOR_VERSION 1 -#define NETXDUO_PATCH_VERSION 2 +#define NETXDUO_MINOR_VERSION 2 +#define NETXDUO_PATCH_VERSION 0 /* Define the following symbols for backward compatibility */ #define EL_PRODUCT_NETXDUO @@ -1159,6 +1213,22 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_MAX_LISTEN_REQUESTS 10 #endif +/* Define the max length of username and password for HTTP Proxy authentication. */ + +/* Define the max length of username. */ +#ifndef NX_HTTP_PROXY_MAX_USERNAME +#define NX_HTTP_PROXY_MAX_USERNAME 20 +#endif + +/* Define the max length of password. */ +#ifndef NX_HTTP_PROXY_MAX_PASSWORD +#define NX_HTTP_PROXY_MAX_PASSWORD 20 +#endif + +/* NX_HTTP_PROXY_MAX_AUTHENTICATION is the max length of base64 of "name:password", + 1 bytes for an extra conversion if needed, 2 bytes for pad if needed, 1 byte for null terminator and four byte alignment. */ +#define NX_HTTP_PROXY_MAX_AUTHENTICATION (((((NX_HTTP_PROXY_MAX_USERNAME + NX_HTTP_PROXY_MAX_PASSWORD + 1 ) * 4 / 3) + 1 + 2 + 1) / 4 + 1) * 4) + /* Define the IP status checking/return bits. */ @@ -1253,6 +1323,7 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_PACKET_OFFSET_ERROR 0x53 #define NX_OPTION_HEADER_ERROR 0x54 #define NX_CONTINUE 0x55 +#define NX_TCPIP_OFFLOAD_ERROR 0x56 /* Define Link Driver constants. */ @@ -1284,9 +1355,23 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_LINK_RX_ENABLE 25 #define NX_LINK_RX_DISABLE 26 #define NX_LINK_6LOWPAN_COMMAND 27 /* 6LowPAN driver command, the sub command see nx_6lowpan.h. */ +#define NX_LINK_GET_INTERFACE_TYPE 28 #define NX_LINK_USER_COMMAND 50 /* Values after this value are reserved for application. */ + +/* Define operations for TCP/IP offload callback functions. */ +#define NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT 0 +#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN 1 +#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT 2 +#define NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN 3 +#define NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT 4 +#define NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND 5 +#define NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND 6 +#define NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND 7 +#define NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND 8 + + /* Define Link Driver Capability Flags. */ #ifdef NX_ENABLE_INTERFACE_CAPABILITY #define NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM 0x00000001 @@ -1301,6 +1386,20 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM 0x00000200 #define NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM 0x00000400 #define NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM 0x00000800 +#define NX_INTERFACE_CAPABILITY_PTP_TIMESTAMP 0x00001000 +#define NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD 0x00002000 +#define NX_INTERFACE_CAPABILITY_CHECKSUM_ALL (NX_INTERFACE_CAPABILITY_IPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_IPV4_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_TCP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_TCP_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_UDP_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV4_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV4_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV6_RX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_ICMPV6_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_IGMP_TX_CHECKSUM | \ + NX_INTERFACE_CAPABILITY_IGMP_RX_CHECKSUM) #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ #define NX_IP_VERSION_V4 0x4 @@ -1320,13 +1419,21 @@ typedef struct NX_IPV6_DEFAULT_ROUTER_ENTRY_STRUCT #define NX_IP_PACKET_OUT 1 #endif /* NX_ENABLE_IP_PACKET_FILTER */ +/* Define the interface type. */ +#define NX_INTERFACE_TYPE_UNKNOWN 0 +#define NX_INTERFACE_TYPE_OTHER 1 +#define NX_INTERFACE_TYPE_ETHERNET 2 +#define NX_INTERFACE_TYPE_WIFI 3 +#define NX_INTERFACE_TYPE_CELLULAR 4 +#define NX_INTERFACE_TYPE_BLUETOOTH 5 +#define NX_INTERFACE_TYPE_LORAWAN 6 +#define NX_INTERFACE_TYPE_MAX 7 #ifdef NX_ENABLE_THREAD /* Define the packet type for Thread MLE. */ #define NX_PACKET_TYPE_THREAD_MLE 0x01 #endif /* NX_ENABLE_THREAD */ - /* Define IPv4/v6 Address structure */ typedef struct NXD_ADDRESS_STRUCT { @@ -1745,7 +1852,12 @@ typedef struct NX_UDP_SOCKET_STRUCT /* This pointer is reserved for application specific use. */ /*lint -esym(768,NX_UDP_SOCKET_STRUCT::nx_udp_socket_reserved_ptr) suppress member not referenced. It is reserved for future use. */ void *nx_udp_socket_reserved_ptr; - + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Store a pointer to TCP/IP offload context. */ + VOID *nx_udp_socket_tcpip_offload_context; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Define the port extension in the UDP socket control block. This is typically defined to whitespace in nx_port.h. */ NX_UDP_SOCKET_MODULE_EXTENSION @@ -1850,9 +1962,22 @@ typedef struct NX_TCP_SOCKET_STRUCT /* Define whether or not TCP socket is in fast recovery procedure. */ UCHAR nx_tcp_socket_fast_recovery; +#ifdef NX_ENABLE_HTTP_PROXY + + /* Define the state of HTTP Proxy connection. */ + UCHAR nx_tcp_socket_http_proxy_state; + + /* Define the packet to store HTTP response header. */ + NX_PACKET *nx_tcp_socket_http_proxy_header_packet; + + /* Define the IP and port for original server. */ + NXD_ADDRESS nx_tcp_socket_original_server_ip; + UINT nx_tcp_socket_original_server_port; +#else /* Reserved to four bytes alignment. */ /*lint -esym(768,NX_TCP_SOCKET_STRUCT::nx_tcp_socket_reserved) suppress member not referenced. It is reserved for future use. */ UCHAR nx_tcp_socket_reserved; +#endif /* NX_ENABLE_HTTP_PROXY */ /* Define the entry that this TCP socket belongs to. */ struct NX_IP_STRUCT @@ -2021,6 +2146,11 @@ typedef struct NX_TCP_SOCKET_STRUCT #endif /* NX_IPSEC_ENABLE */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Store a pointer to TCP/IP offload context. */ + VOID *nx_tcp_socket_tcpip_offload_context; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Define the port extension in the TCP socket control block. This is typically defined to whitespace in nx_port.h. */ NX_TCP_SOCKET_MODULE_EXTENSION @@ -2225,6 +2355,15 @@ typedef struct NX_INTERFACE_STRUCT ARP packet that matches that of nx_interface_ip_probe_address. */ VOID (*nx_interface_ip_conflict_notify_handler)(struct NX_IP_STRUCT *, UINT, ULONG, ULONG, ULONG); #endif /* !NX_DISABLE_IPV4 */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Define the TCP/IP offload handler. */ + UINT (*nx_interface_tcpip_offload_handler)(struct NX_IP_STRUCT *ip_ptr, + struct NX_INTERFACE_STRUCT *interface_ptr, + VOID *socket_ptr, UINT operation, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, + UINT local_port, UINT *remote_port, UINT wait_option); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ } NX_INTERFACE; /* Define the static IPv4 routing table entry structure. */ @@ -2550,11 +2689,17 @@ typedef struct NX_IP_STRUCT /* Define the IP address change notification callback routine pointer. */ VOID (*nx_ip_address_change_notify)(struct NX_IP_STRUCT *, VOID *); VOID *nx_ip_address_change_notify_additional_info; + + /* Define the internal IP address change notification callback routine pointer, used in mDNS. */ + VOID (*nx_ip_address_change_notify_internal)(struct NX_IP_STRUCT *, VOID *); #endif /* !NX_DISABLE_IPV4 */ #ifdef FEATURE_NX_IPV6 #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY VOID (*nx_ipv6_address_change_notify)(struct NX_IP_STRUCT *ip_ptr, UINT status, UINT interface_index, UINT addres_index, ULONG *ip_address); + + /* Define the internal IPv6 address change notification callback routine pointer, used in mDNS. */ + VOID (*nx_ipv6_address_change_notify_internal)(struct NX_IP_STRUCT *ip_ptr, UINT status, UINT interface_index, UINT addres_index, ULONG *ip_address); #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ #endif /* FEATURE_NX_IPV6 */ @@ -2702,6 +2847,21 @@ typedef struct NX_IP_STRUCT NX_TCP_LISTEN *nx_ip_tcp_active_listen_requests; +#ifdef NX_ENABLE_HTTP_PROXY + /* Define the IP address of HTTP proxy server. */ + NXD_ADDRESS nx_ip_http_proxy_ip_address; + + /* Define the port of HTTP proxy server. */ + USHORT nx_ip_http_proxy_port; + + /* Define the flag indicating the HTTP proxy is enabled. */ + USHORT nx_ip_http_proxy_enable; + + /* Define the buffer for HTTP proxy authentication. */ + UCHAR nx_ip_http_proxy_authentication[NX_HTTP_PROXY_MAX_AUTHENTICATION]; + UINT nx_ip_http_proxy_authentication_length; +#endif /* NX_ENABLE_HTTP_PROXY */ + /* Define a flag indicating the IP fast timer has been created */ UINT nx_ip_fast_periodic_timer_created; @@ -2894,6 +3054,10 @@ typedef struct NX_IP_STRUCT #ifdef NX_ENABLE_IP_PACKET_FILTER /* Define the IP packet filter routine. */ UINT (*nx_ip_packet_filter)(VOID *, UINT); + + /* Define the IP packet filter extended routine. */ + /* Note: Developers are encouraged to use nx_ip_packet_filter_extended since nx_ip_packet_filter will be deprecated.*/ + UINT (*nx_ip_packet_filter_extended)(struct NX_IP_STRUCT *ip_ptr, NX_PACKET *packet_ptr, UINT direction); #endif /* NX_ENABLE_IP_PACKET_FILTER */ /* Define the port extension in the IP control block. This @@ -3149,6 +3313,7 @@ typedef struct NX_IP_DRIVER_STRUCT /* APIs for others. */ #define nx_system_initialize _nx_system_initialize +#define nx_http_proxy_client_enable _nx_http_proxy_client_enable #else @@ -3336,6 +3501,7 @@ typedef struct NX_IP_DRIVER_STRUCT /* APIs for others. */ #define nx_system_initialize _nx_system_initialize +#define nx_http_proxy_client_enable _nxe_http_proxy_client_enable #endif @@ -3673,6 +3839,8 @@ UINT nxd_udp_packet_info_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *ip_address, /* APIs for others. */ VOID nx_system_initialize(VOID); +UINT nx_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port, + UCHAR *username, UINT username_length, UCHAR *password, UINT password_length); /* Define several function prototypes for exclusive use by NetX I/O drivers. These routines are used by NetX drivers to report received packets to NetX. */ @@ -3727,6 +3895,18 @@ VOID _nx_ip_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr); processing in the driver's receive ISR. */ VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index); +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/* Define the direct TCP packet receive processing. This is used with TCP/IP offload feature. */ +VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr); + +/* Define the direct TCP established processing. This is used with TCP/IP offload feature. */ +UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port); + +/* Define the direct UDP packet receive processing. This is used with TCP/IP offload feature. */ +VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #endif #ifdef FEATURE_NX_IPV6 @@ -3803,6 +3983,10 @@ VOID _nx_ip_driver_link_status_event(NX_IP *ip_ptr, UINT interface_index); /* Utility functions. */ UINT _nx_utility_string_length_check(CHAR *input_string, UINT *string_length, UINT max_string_length); +UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number); +UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size); +UINT _nx_utility_base64_encode(UCHAR *name, UINT name_size, UCHAR *base64name, UINT base64name_size, UINT *bytes_copied); +UINT _nx_utility_base64_decode(UCHAR *base64name, UINT base64name_size, UCHAR *name, UINT name_size, UINT *bytes_copied); /* Determine if a C++ compiler is being used. If so, complete the standard C conditional started above. */ diff --git a/common/inc/nx_arp.h b/common/inc/nx_arp.h index 8844bb7a..faac7122 100644 --- a/common/inc/nx_arp.h +++ b/common/inc/nx_arp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_arp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_ARP_H #define NX_ARP_H +#include "nx_api.h" + #ifndef NX_DISABLE_IPV4 /* Define ARP Message format. This will get encapsulated by an Ethernet frame diff --git a/common/inc/nx_http_proxy_client.h b/common/inc/nx_http_proxy_client.h new file mode 100644 index 00000000..78566d46 --- /dev/null +++ b/common/inc/nx_http_proxy_client.h @@ -0,0 +1,89 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** HTTP Proxy Protocol */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* nx_http_proxy_client.h PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the Hypertext Transfer Protocol(HTTP) Proxy */ +/* component, including all data types and external references. */ +/* It is assumed that nx_api.h and nx_port.h have already been */ +/* included. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ + +#ifndef NX_HTTP_PROXY_CLIENT_H +#define NX_HTTP_PROXY_CLIENT_H + +/* Determine if a C++ compiler is being used. If so, ensure that standard + C is used to process the API information. */ + + +#ifdef __cplusplus + +/* Yes, C++ compiler is present. Use standard C. */ +extern "C" { + +#endif + +#include "nx_api.h" + +/* Define the states for HTTP Proxy connection. */ +#define NX_HTTP_PROXY_STATE_INIT 0 +#define NX_HTTP_PROXY_STATE_WAITING 1 +#define NX_HTTP_PROXY_STATE_CONNECTING 2 +#define NX_HTTP_PROXY_STATE_CONNECTED 3 + +/* Define HTTP Proxy function prototypes. */ +UINT _nx_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port, + UCHAR *username, UINT username_length, UCHAR *password, UINT password_length); +VOID _nx_http_proxy_client_initialize(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS **server_ip, UINT *server_port); +UINT _nx_http_proxy_client_connect(NX_TCP_SOCKET *socket_ptr); +UINT _nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET *socket_ptr); +VOID _nx_http_proxy_client_cleanup(NX_TCP_SOCKET *socket_ptr); + +/* Define error checking shells for API services. These are only referenced by the + application. */ +UINT _nxe_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port, + UCHAR *username, UINT username_length, UCHAR *password, UINT password_length); + +/* Determine if a C++ compiler is being used. If so, complete the standard + C conditional started above. */ +#ifdef __cplusplus + } +#endif + +#endif /* NX_HTTP_PROXY_CLIENT_H */ \ No newline at end of file diff --git a/common/inc/nx_icmp.h b/common/inc/nx_icmp.h index eb7ad73e..f60096fc 100644 --- a/common/inc/nx_icmp.h +++ b/common/inc/nx_icmp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_icmp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_ICMP_H #define NX_ICMP_H +#include "nx_api.h" + VOID _nx_icmp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr); VOID _nx_icmp_cleanup(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER); diff --git a/common/inc/nx_icmpv4.h b/common/inc/nx_icmpv4.h index 7b824fd1..86672e31 100644 --- a/common/inc/nx_icmpv4.h +++ b/common/inc/nx_icmpv4.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_icmpv4.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_ICMPV4_H #define NX_ICMPV4_H +#include "nx_api.h" + #ifndef NX_DISABLE_IPV4 /* Define ICMP types and codes. According to RFC792. */ diff --git a/common/inc/nx_icmpv6.h b/common/inc/nx_icmpv6.h index 6e0441fc..15b2e196 100644 --- a/common/inc/nx_icmpv6.h +++ b/common/inc/nx_icmpv6.h @@ -212,7 +212,7 @@ typedef struct NX_ICMPV6_OPTION_STRUCT /* Size of the option. */ UCHAR nx_icmpv6_option_length; - /* Option data. */ + /* Option data. This field is used to retrieve starting address of option. The size is decided by option length. */ USHORT nx_icmpv6_option_data; } NX_ICMPV6_OPTION; diff --git a/common/inc/nx_igmp.h b/common/inc/nx_igmp.h index 9b2bd069..d1561238 100644 --- a/common/inc/nx_igmp.h +++ b/common/inc/nx_igmp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_igmp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,13 +44,16 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_IGMP_H #define NX_IGMP_H - +#include "nx_api.h" #ifndef NX_DISABLE_IPV4 diff --git a/common/inc/nx_ip.h b/common/inc/nx_ip.h index 9fa45a05..5dc3fde1 100644 --- a/common/inc/nx_ip.h +++ b/common/inc/nx_ip.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_ip.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_IP_H #define NX_IP_H +#include "nx_api.h" + /* Define IP constants. */ diff --git a/common/inc/nx_ipv4.h b/common/inc/nx_ipv4.h index 7f19e18a..638946a7 100644 --- a/common/inc/nx_ipv4.h +++ b/common/inc/nx_ipv4.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_ipv4.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,20 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_IPV4_H #define NX_IPV4_H +#include "nx_api.h" + #ifndef NX_DISABLE_IPV4 #define NX_IP_VERSION 0x45000000UL /* Version 4, Length of 5 */ @@ -151,7 +159,8 @@ typedef struct NX_IPV4_HEADER_STRUCT VOID _nx_ip_forward_packet_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr); VOID _nx_ip_fragment_forward_packet(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG fragment, ULONG next_hop_address); void _nx_ip_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment, ULONG next_hop_address); -UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment); +UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip, + ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment); VOID _nx_ip_driver_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, ULONG fragment, ULONG next_hop_address); ULONG _nx_ip_route_find(NX_IP *ip_ptr, ULONG destination_address, NX_INTERFACE **nx_ip_interface, ULONG *next_hop_address); VOID _nx_ipv4_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr); diff --git a/common/inc/nx_ipv6.h b/common/inc/nx_ipv6.h index 5ba12418..38569d29 100644 --- a/common/inc/nx_ipv6.h +++ b/common/inc/nx_ipv6.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_ipv6.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -47,13 +47,16 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_IPV6_H #define NX_IPV6_H -#include "tx_api.h" +#include "nx_api.h" #ifdef FEATURE_NX_IPV6 /* Define basic IP Header constant. */ diff --git a/common/inc/nx_md5.h b/common/inc/nx_md5.h index 735d0bd8..e76c0b9d 100644 --- a/common/inc/nx_md5.h +++ b/common/inc/nx_md5.h @@ -50,7 +50,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_md5.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -73,12 +73,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_MD5_H #define NX_MD5_H +#include "nx_api.h" + /* Define the MD5 context structure. */ diff --git a/common/inc/nx_packet.h b/common/inc/nx_packet.h index e3d1c59d..88e93dad 100644 --- a/common/inc/nx_packet.h +++ b/common/inc/nx_packet.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_packet.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_PAC_H #define NX_PAC_H +#include "nx_api.h" + #define NX_PACKET_POOL_ID ((ULONG)0x5041434B) diff --git a/common/inc/nx_rarp.h b/common/inc/nx_rarp.h index 4d13c6ad..e1fcd2a8 100644 --- a/common/inc/nx_rarp.h +++ b/common/inc/nx_rarp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_rarp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_RARP_H #define NX_RARP_H +#include "nx_api.h" + #ifndef NX_DISABLE_IPV4 /* Define RARP Message format. This will get encapsulated by an Ethernet frame diff --git a/common/inc/nx_tcp.h b/common/inc/nx_tcp.h index ad83972f..57877a4f 100644 --- a/common/inc/nx_tcp.h +++ b/common/inc/nx_tcp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_tcp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,20 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_TCP_H #define NX_TCP_H +#include "nx_api.h" + /* Define TCP constants. */ @@ -278,6 +286,14 @@ UINT _nx_tcp_socket_establish_notify(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_estab UINT _nx_tcp_socket_disconnect_complete_notify(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_disconnect_complete_notify)(NX_TCP_SOCKET *socket_ptr)); UINT _nx_tcp_socket_timed_wait_callback(NX_TCP_SOCKET *socket_ptr, VOID (*tcp_timed_wait_callback)(NX_TCP_SOCKET *socket_ptr)); UINT _nx_tcp_socket_receive_queue_max_set(NX_TCP_SOCKET *socket_ptr, UINT receive_queue_maximum); +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/* Define the direct TCP packet receive processing. This is used with TCP/IP offload feature. */ +VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr); + +/* Define the direct TCP established processing. This is used with TCP/IP offload feature. */ +UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port); +UINT _nx_tcp_server_socket_driver_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Define TCP component internal function prototypes. */ VOID _nx_tcp_cleanup_deferred(TX_THREAD *thread_ptr NX_CLEANUP_PARAMETER); diff --git a/common/inc/nx_udp.h b/common/inc/nx_udp.h index 599af6b2..37fc5c93 100644 --- a/common/inc/nx_udp.h +++ b/common/inc/nx_udp.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_udp.h PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -44,12 +44,20 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), included */ +/* necessary header file, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ #ifndef NX_UDP_H #define NX_UDP_H +#include "nx_api.h" + /* Define UDP constants. */ @@ -116,6 +124,11 @@ UINT _nx_udp_socket_unbind(NX_UDP_SOCKET *socket_ptr); UINT _nx_udp_source_extract(NX_PACKET *packet_ptr, ULONG *ip_address, UINT *port); UINT _nx_udp_packet_info_extract(NX_PACKET *packet_ptr, ULONG *ip_address, UINT *protocol, UINT *port, UINT *interface_index); UINT _nxd_udp_source_extract(NX_PACKET *packet_ptr, NXD_ADDRESS *ip_address, UINT *port); +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/* Define the direct UDP packet receive processing. This is used with TCP/IP offload feature. */ +VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Define error checking shells for API services. These are only referenced by the application. */ diff --git a/common/inc/nx_user_sample.h b/common/inc/nx_user_sample.h index 978c2956..f7bab5f1 100644 --- a/common/inc/nx_user_sample.h +++ b/common/inc/nx_user_sample.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_user.h PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,11 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -326,7 +331,7 @@ #define NX_ARP_DEFEND_BY_REPLY */ -/* To use the ARP collision hander to check for invalid ARP messages +/* To use the ARP collision handler to check for invalid ARP messages matching existing entries in the table (man in the middle attack), enable this feature. */ /* @@ -531,14 +536,14 @@ /* Configuration options for checksum */ -/* Defiend, this option disables checksum logic on received ICMPv4 packets. +/* Defined, this option disables checksum logic on received ICMPv4 packets. Note that if NX_DISABLE_ICMP_RX_CHECKSUM is defined, this option is automatically defined. By default this option is not defined.*/ /* #define NX_DISABLE_ICMPV4_RX_CHECKSUM */ -/* Defiend, this option disables checksum logic on received ICMPv6 packets. +/* Defined, this option disables checksum logic on received ICMPv6 packets. Note that if NX_DISABLE_ICMP_RX_CHECKSUM is defined, this option is automatically defined. By default this option is not defined.*/ /* @@ -552,14 +557,14 @@ #define NX_DISABLE_ICMP_RX_CHECKSUM */ -/* Defiend, this option disables checksum logic on transmitted ICMPv4 packets. +/* Defined, this option disables checksum logic on transmitted ICMPv4 packets. Note that if NX_DISABLE_ICMP_TX_CHECKSUM is defined, this option is automatically defined. By default this option is not defined.*/ /* #define NX_DISABLE_ICMPV4_TX_CHECKSUM */ -/* Defiend, this option disables checksum logic on transmitted ICMPv6 packets. +/* Defined, this option disables checksum logic on transmitted ICMPv6 packets. Note that if NX_DISABLE_ICMP_TX_CHECKSUM is defined, this option is automatically defined. By default this option is not defined.*/ /* @@ -752,5 +757,11 @@ #define NX_MAX_STRING_LENGTH 1024 */ +/* Defined, the TCP/IP offload feature is enabled. + NX_ENABLE_INTERFACE_CAPABILITY must be defined to enable this feature. */ +/* +#define NX_ENABLE_TCPIP_OFFLOAD +*/ + #endif diff --git a/common/src/nx_arp_dynamic_entry_set.c b/common/src/nx_arp_dynamic_entry_set.c index df04d1e0..912eeac9 100644 --- a/common/src/nx_arp_dynamic_entry_set.c +++ b/common/src/nx_arp_dynamic_entry_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_arp_dynamic_entry_set PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), corrected*/ +/* the returned status, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_arp_dynamic_entry_set(NX_IP *ip_ptr, ULONG ip_address, @@ -164,7 +167,7 @@ ULONG next_hop_address; tx_mutex_put(&(ip_ptr -> nx_ip_protection)); /* Return the error status. */ - return(NX_SUCCESS); + return(NX_DUPLICATED_ENTRY); } } else diff --git a/common/src/nx_arp_packet_receive.c b/common/src/nx_arp_packet_receive.c index 58a6f8be..6b6e343b 100644 --- a/common/src/nx_arp_packet_receive.c +++ b/common/src/nx_arp_packet_receive.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_arp_packet_receive PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -75,6 +75,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler errors, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ VOID _nx_arp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -242,10 +245,10 @@ NX_INTERFACE *interface_ptr; #endif /* If trace is enabled, insert this event into the trace buffer. */ - NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_ARP_RESPONSE_SEND, ip_ptr, sender_ip, packet_ptr, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0) + NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_ARP_RESPONSE_SEND, ip_ptr, sender_ip_address, packet_ptr, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* Set the ARP message type to ARP response. */ - * (message_ptr + 1) = (*(message_ptr + 1) & 0xFFFF0000) | NX_ARP_OPTION_RESPONSE; + *(message_ptr + 1) = (*(message_ptr + 1) & 0xFFFF0000) | NX_ARP_OPTION_RESPONSE; /* Now fill in the new source and destination information for the ARP response. */ *(message_ptr + 2) = (ULONG)(packet_ptr -> nx_packet_ip_interface -> nx_interface_physical_address_msw << 16) | @@ -281,7 +284,7 @@ NX_INTERFACE *interface_ptr; driver_request.nx_ip_driver_interface = packet_ptr -> nx_packet_ip_interface; /* If trace is enabled, insert this event into the trace buffer. */ - NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_ARP_RESPONSE_SEND, ip_ptr, packet_ptr, packet_ptr -> nx_packet_length, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0) + NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_ARP_RESPONSE_SEND, ip_ptr, packet_ptr, packet_ptr -> nx_packet_length, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* No need to update packet_ptr -> nx_packet_ip_interface. When responding to an ARP request, use the same interface where the request was received. */ diff --git a/common/src/nx_http_proxy_client.c b/common/src/nx_http_proxy_client.c new file mode 100644 index 00000000..bd995dde --- /dev/null +++ b/common/src/nx_http_proxy_client.c @@ -0,0 +1,803 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** HTTP Proxy Protocol */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +#define NX_SOURCE_CODE + + +#include "nx_ip.h" +#include "nx_ipv6.h" +#include "nx_packet.h" +#include "nx_tcp.h" +#include "nx_http_proxy_client.h" + +#ifdef NX_ENABLE_HTTP_PROXY +#define NX_HTTP_CRLF "\r\n" +#define NX_HTTP_CRLF_SIZE 2 + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_http_proxy_client_enable PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the HTTP Proxy enable call. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* proxy_server_ip IP address of proxy server */ +/* proxy_server_port Port of proxy server */ +/* username Pointer to username */ +/* username_length Length of username */ +/* password Pointer to password */ +/* password_length Length of password */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_http_proxy_client_enable Actual HTTP Proxy enable call */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port, + UCHAR *username, UINT username_length, UCHAR *password, UINT password_length) +{ +UINT status; + + /* Check for invalid input pointers. */ + if ((ip_ptr == NX_NULL) || (ip_ptr -> nx_ip_id != NX_IP_ID) || + (proxy_server_ip == NX_NULL) || (proxy_server_port == 0) || + ((username == NX_NULL) && (username_length != 0)) || + ((password == NX_NULL) && (password_length != 0))) + { + return(NX_PTR_ERROR); + } + + /* Check the length of username and password. */ + if ((username_length > NX_HTTP_PROXY_MAX_USERNAME) || + (password_length > NX_HTTP_PROXY_MAX_PASSWORD)) + { + return(NX_SIZE_ERROR); + } + + /* Check that the server IP address version is either IPv4 or IPv6. */ + if ((proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V4) && + (proxy_server_ip -> nxd_ip_version != NX_IP_VERSION_V6)) + { + + return(NX_IP_ADDRESS_ERROR); + } + +#ifndef NX_DISABLE_IPV4 + /* Check for a valid server IP address if the server_ip is version IPv4. */ + if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + if (((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_A_MASK) != NX_IP_CLASS_A_TYPE) && + ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_B_MASK) != NX_IP_CLASS_B_TYPE) && + ((proxy_server_ip -> nxd_ip_address.v4 & NX_IP_CLASS_C_MASK) != NX_IP_CLASS_C_TYPE)) + { + return(NX_IP_ADDRESS_ERROR); + } + } +#endif /* !NX_DISABLE_IPV4 */ + + /* Check for an invalid port. */ + if (((ULONG)proxy_server_port) > (ULONG)NX_MAX_PORT) + { + return(NX_INVALID_PORT); + } + + /* Call actual HTTP proxy enable function. */ + status = _nx_http_proxy_client_enable(ip_ptr, proxy_server_ip, proxy_server_port, username, + username_length, password, password_length); + + /* Return completion status. */ + return(status); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_proxy_client_enable PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enables the HTTP Proxy and sets the information of */ +/* the HTTP Proxy server. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* proxy_server_ip IP address of proxy server */ +/* proxy_server_port Port of proxy server */ +/* username Pointer to username */ +/* username_length Length of username */ +/* password Pointer to password */ +/* password_length Length of password */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* COPY_IPV6_ADDRESS Copy IPv6 address */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_http_proxy_client_enable(NX_IP *ip_ptr, NXD_ADDRESS *proxy_server_ip, UINT proxy_server_port, + UCHAR *username, UINT username_length, UCHAR *password, UINT password_length) +{ + +UINT status; +UCHAR string[NX_HTTP_PROXY_MAX_USERNAME + NX_HTTP_PROXY_MAX_PASSWORD + 2]; + + /* Set the IP address of HTTP proxy. */ + ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_version = proxy_server_ip -> nxd_ip_version; + +#ifndef NX_DISABLE_IPV4 + if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + + /* Copy the IPv4 address */ + ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v4 = proxy_server_ip -> nxd_ip_address.v4; + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (proxy_server_ip -> nxd_ip_version == NX_IP_VERSION_V6) + { + + /* Copy the IPv6 address */ + COPY_IPV6_ADDRESS(proxy_server_ip -> nxd_ip_address.v6, + ip_ptr -> nx_ip_http_proxy_ip_address.nxd_ip_address.v6); + } +#endif /* FEATURE_NX_IPV6 */ + + /* Set the port of HTTP proxy. */ + ip_ptr -> nx_ip_http_proxy_port = (USHORT)proxy_server_port; + + /* Determine if basic authentication is required. */ + if ((username_length) && (password_length)) + { + + /* Encode the "name:password" into authentication buffer. */ + + /* Place the name and password in a single string. */ + + /* Copy the name into the merged string. */ + memcpy(string, username, username_length); /* Use case of memcpy is verified. */ + + /* Insert the colon. */ + string[username_length] = ':'; + + /* Copy the password into the merged string. */ + memcpy(&string[username_length + 1], password, password_length); /* Use case of memcpy is verified. */ + + /* Make combined string NULL terminated. */ + string[username_length + password_length + 1] = NX_NULL; + + /* Now encode the username:password string. */ + status = _nx_utility_base64_encode((UCHAR *)string, username_length + password_length + 1, + (UCHAR *)ip_ptr -> nx_ip_http_proxy_authentication, + sizeof(ip_ptr -> nx_ip_http_proxy_authentication), + &(ip_ptr -> nx_ip_http_proxy_authentication_length)); + + /* Check status. */ + if (status) + { + return(status); + } + } + else + { + ip_ptr -> nx_ip_http_proxy_authentication_length = 0; + } + + /* Set HTTP proxy as enabled. */ + ip_ptr -> nx_ip_http_proxy_enable = NX_TRUE; + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_proxy_client_initialize PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes the state of HTTP Proxy and stores the */ +/* the information of remote server. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* server_ip IP address of remote server */ +/* server_port Port of remote server */ +/* */ +/* OUTPUT */ +/* */ +/* NONE */ +/* */ +/* CALLS */ +/* */ +/* COPY_IPV6_ADDRESS Copy IPv6 address */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_tcp_client_socket_connect Connect TCP client socket */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +VOID _nx_http_proxy_client_initialize(NX_TCP_SOCKET *socket_ptr, NXD_ADDRESS **server_ip, UINT *server_port) +{ + +NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Store the server's IP and port for sending CONNECT request later. */ + socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_version = (*server_ip) -> nxd_ip_version; + +#ifndef NX_DISABLE_IPV4 + if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V4) + { + + /* Copy the IPv4 address */ + socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v4 = (*server_ip) -> nxd_ip_address.v4; + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if ((*server_ip) -> nxd_ip_version == NX_IP_VERSION_V6) + { + + /* Copy the IPv6 address */ + COPY_IPV6_ADDRESS((*server_ip) -> nxd_ip_address.v6, + socket_ptr -> nx_tcp_socket_original_server_ip.nxd_ip_address.v6); + } +#endif /* FEATURE_NX_IPV6 */ + + socket_ptr -> nx_tcp_socket_original_server_port = *server_port; + + /* Replace the peer info with HTTP proxy's IP and port. */ + *server_ip = &(ip_ptr -> nx_ip_http_proxy_ip_address); + *server_port = ip_ptr -> nx_ip_http_proxy_port; + + /* Initialize the state. */ + socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT; + socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL; +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_proxy_client_connect PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends HTTP request to connect with HTTP Proxy server. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_tcp_socket_disconnect Disconnect TCP socket */ +/* _nx_utility_uint_to_string Convert integer to string */ +/* _nx_utility_base64_encode Base64 encode */ +/* _nx_packet_allocate Allocate packet */ +/* _nx_packet_data_append Append packet data */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_socket_state_syn_received Process SYN RECEIVED state */ +/* _nx_tcp_socket_state_syn_sent Process SYN SENT state */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_http_proxy_client_connect(NX_TCP_SOCKET *socket_ptr) +{ + +UINT status; +NX_PACKET *packet_ptr; +NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; +NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool; +CHAR *ip_string_ptr; +UINT ip_string_len = 0; +CHAR *port_string_ptr; +UINT port_string_len = 0; +UINT temp_length = 0; +NXD_ADDRESS *server_ip = &(socket_ptr -> nx_tcp_socket_original_server_ip); +UINT port = socket_ptr -> nx_tcp_socket_original_server_port; + + + /* Check the IP version of the server. */ + if (server_ip -> nxd_ip_version != NX_IP_VERSION_V4) + { + + /* Only IPv4 is supported. */ + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(NX_NOT_SUPPORTED); + } + + /* Allocate packet. */ + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + status = _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv4_TCP_PACKET, NX_NO_WAIT); + } + else + { + status = _nx_packet_allocate(pool_ptr, &packet_ptr, NX_IPv6_TCP_PACKET, NX_NO_WAIT); + } + + /* Check status. */ + if (status) + { + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + /* Convert IP address and port to string. */ + /* Use the buffer before prepend pointer to store the IP and port string. */ + ip_string_ptr = (CHAR *)packet_ptr -> nx_packet_data_start; + temp_length = (UINT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start); + + /* Convert IP address to string. */ + ip_string_len = _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 24), 10, ip_string_ptr, temp_length); + ip_string_ptr[ip_string_len++] = '.'; + ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 16), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len); + ip_string_ptr[ip_string_len++] = '.'; + ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4 >> 8), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len); + ip_string_ptr[ip_string_len++] = '.'; + ip_string_len += _nx_utility_uint_to_string((UCHAR)(server_ip -> nxd_ip_address.v4), 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len); + + /* Convert port to string. */ + port_string_ptr = ip_string_ptr + ip_string_len; + port_string_len = _nx_utility_uint_to_string(port, 10, ip_string_ptr + ip_string_len, temp_length - ip_string_len); + + /* HTTP proxy opening handshake message format: + CONNECT IP address:port HTTP/1.1 + Host: IP address + */ + + /* Build the CONNECT request: CONNECT + Request URI(IP address:port) + HTTP version. */ + status = _nx_packet_data_append(packet_ptr, "CONNECT ", sizeof("CONNECT ") - 1, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, ":", sizeof(":") - 1, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, port_string_ptr, port_string_len, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, " HTTP/1.1", sizeof(" HTTP/1.1") - 1, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT); + + /* Place the Host in the header. */ + status += _nx_packet_data_append(packet_ptr, "Host: ", sizeof("Host: ") - 1, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, ip_string_ptr, ip_string_len, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + _nx_packet_release(packet_ptr); + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(NX_NOT_SUCCESSFUL); + } + + /* Determine if basic authentication is required. */ + if (ip_ptr -> nx_ip_http_proxy_authentication_length) + { + + /* Yes, attempt to build basic authentication. */ + status = _nx_packet_data_append(packet_ptr, "Proxy-authorization: Basic ", 27, pool_ptr, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + _nx_packet_release(packet_ptr); + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + /* Append authentication string. */ + status = _nx_packet_data_append(packet_ptr, ip_ptr -> nx_ip_http_proxy_authentication, + ip_ptr -> nx_ip_http_proxy_authentication_length, pool_ptr, NX_NO_WAIT); + status += _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + _nx_packet_release(packet_ptr); + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(NX_NOT_SUCCESSFUL); + } + } + + /* Append CRLF. */ + status = _nx_packet_data_append(packet_ptr, NX_HTTP_CRLF, NX_HTTP_CRLF_SIZE, pool_ptr, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + _nx_packet_release(packet_ptr); + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + /* Send out the packet. */ + status = _nx_tcp_socket_send(socket_ptr, packet_ptr, NX_NO_WAIT); + + /* Check status. */ + if (status) + { + _nx_packet_release(packet_ptr); + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + /* Update HTTP Proxy state. */ + socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTING; + + /* Return successful completion. */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_proxy_client_connect_response_process PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the CONNECT response from HTTP Proxy server.*/ +/* */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_tcp_socket_receive Receive TCP socket */ +/* _nx_tcp_socket_disconnect Disconnect TCP socket */ +/* _nx_tcp_socket_thread_resume Resume the suspended thread */ +/* _nx_packet_data_append Append packet data */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_socket_packet_process Process socket packet */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_http_proxy_client_connect_response_process(NX_TCP_SOCKET *socket_ptr) +{ +NX_PACKET *head_packet_ptr = socket_ptr -> nx_tcp_socket_http_proxy_header_packet; +NX_PACKET *new_packet_ptr; +CHAR *buffer_ptr; +UINT status = NX_SUCCESS; +NX_PACKET *work_ptr; +UINT crlf_found = 0; +NX_PACKET *tmp_ptr; +NX_IP *ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; +NX_PACKET_POOL *pool_ptr = ip_ptr -> nx_ip_default_packet_pool; + + + if (head_packet_ptr == NX_NULL) + { + + /* Wait for a response from HTTP proxy. */ + status = _nx_tcp_socket_receive(socket_ptr, &head_packet_ptr, NX_NO_WAIT); + + /* Check the return status. */ + if (status == NX_NO_PACKET) + { + return(NX_IN_PROGRESS); + } + else if (status != NX_SUCCESS) + { + + /* Return an error condition. */ + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + socket_ptr -> nx_tcp_socket_http_proxy_header_packet = head_packet_ptr; + } + + crlf_found = 0; + work_ptr = head_packet_ptr; + + /* Build a pointer to the buffer area. */ + buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr; + + do + { + + /* See if there is a blank line present in the buffer. */ + /* Search the buffer for a cr/lf pair. */ + while ((buffer_ptr < (CHAR *) work_ptr -> nx_packet_append_ptr) && + (crlf_found < 4)) + { + if (!(crlf_found & 1) && (*buffer_ptr == (CHAR)13)) + { + + /* Found CR. */ + crlf_found++; + } + else if((crlf_found & 1) && (*buffer_ptr == (CHAR)10)) + { + + /* Found LF. */ + crlf_found++; + } + else + { + + /* Reset the CRLF marker. */ + crlf_found = 0; + } + + /* Move the buffer pointer up. */ + buffer_ptr++; + } + + if (crlf_found == 4) + { + + /* Yes, we have found the end of the HTTP response header. */ + break; + } + + /* Determine if the packet has already overflowed into another packet. */ + +#ifndef NX_DISABLE_PACKET_CHAIN + + if (work_ptr -> nx_packet_next != NX_NULL) + { + + /* Get the next packet in the chain. */ + work_ptr = work_ptr -> nx_packet_next; + buffer_ptr = (CHAR *) work_ptr -> nx_packet_prepend_ptr; + } + else +#endif + { + /* Receive another packet from the HTTP proxy. */ + status = _nx_tcp_socket_receive(socket_ptr, &new_packet_ptr, NX_NO_WAIT); + + /* Check the return status. */ + if (status == NX_NO_PACKET) + { + return(NX_IN_PROGRESS); + } + else if (status != NX_SUCCESS) + { + break; + } + + /* Successfully received another packet. Its contents now need to be placed in the head packet. */ + tmp_ptr = new_packet_ptr; + +#ifndef NX_DISABLE_PACKET_CHAIN + while (tmp_ptr) +#endif /* NX_DISABLE_PACKET_CHAIN */ + { + + /* Copy the contents of the current packet into the head packet. */ + status = _nx_packet_data_append(head_packet_ptr, (VOID *) tmp_ptr -> nx_packet_prepend_ptr, + (ULONG)(tmp_ptr -> nx_packet_append_ptr - tmp_ptr -> nx_packet_prepend_ptr), + pool_ptr, NX_NO_WAIT); + +#ifndef NX_DISABLE_PACKET_CHAIN + + /* Determine if an error occurred. */ + if (status != NX_SUCCESS) + { + break; + } + else + { + tmp_ptr = tmp_ptr -> nx_packet_next; + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + + /* Release the new packet. */ + _nx_packet_release(new_packet_ptr); + } + + } while (status == NX_SUCCESS); + + if (status) + { + + /* Return an error condition. */ + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(status); + } + + /* Check the packet length and response code. */ + if ((head_packet_ptr -> nx_packet_append_ptr - head_packet_ptr -> nx_packet_prepend_ptr < 12) || + (*(head_packet_ptr -> nx_packet_prepend_ptr + 9) != '2')) + { + + /* If error occurs, disconnect the TCP connection. */ + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + return(NX_NOT_SUCCESSFUL); + } + + /* Update the HTTP Proxy state. */ + socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_CONNECTED; + + /* Release the packet. */ + _nx_packet_release(head_packet_ptr); + socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL; + +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif /* NX_DISABLE_EXTENDED_NOTIFY_SUPPORT */ + + /* Determine if we need to wake a thread suspended on the connection. */ + if (socket_ptr -> nx_tcp_socket_connect_suspended_thread) + { + + /* Resume the suspended thread. */ + _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS); + } + + /* Return status. */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_http_proxy_client_cleanup PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Wenhui Xie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function cleans up the HTTP Proxy by resetting the state and */ +/* release the processing packet. */ +/* */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_packet_release Release packet */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_socket_block_cleanup Clean up the socket block */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Wenhui Xie Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +VOID _nx_http_proxy_client_cleanup(NX_TCP_SOCKET *socket_ptr) +{ + + /* Clear the HTTP Proxy connection state. */ + socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_INIT; + + /* Release HTTP Proxy header packet. */ + if (socket_ptr -> nx_tcp_socket_http_proxy_header_packet) + { + _nx_packet_release(socket_ptr -> nx_tcp_socket_http_proxy_header_packet); + socket_ptr -> nx_tcp_socket_http_proxy_header_packet = NX_NULL; + } +} +#endif /* NX_ENABLE_HTTP_PROXY */ \ No newline at end of file diff --git a/common/src/nx_icmpv6_perform_DAD.c b/common/src/nx_icmpv6_perform_DAD.c index 7555068e..331367a8 100644 --- a/common/src/nx_icmpv6_perform_DAD.c +++ b/common/src/nx_icmpv6_perform_DAD.c @@ -42,7 +42,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_icmpv6_perform_DAD PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -80,6 +80,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -144,6 +148,14 @@ UINT ipv6_addr_index; ip_ptr -> nx_ipv6_address_change_notify(ip_ptr, NX_IPV6_ADDRESS_DAD_SUCCESSFUL, i, ipv6_addr_index, &nx_ipv6_address_next -> nxd_ipv6_address[0]); } + + /* If the internal callback function is set, invoke the callback function . */ + if (ip_ptr -> nx_ipv6_address_change_notify_internal) + { + ipv6_addr_index = (ULONG)nx_ipv6_address_next -> nxd_ipv6_address_index; + ip_ptr -> nx_ipv6_address_change_notify_internal(ip_ptr, NX_IPV6_ADDRESS_DAD_SUCCESSFUL, + i, ipv6_addr_index, &nx_ipv6_address_next -> nxd_ipv6_address[0]); + } #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ } } diff --git a/common/src/nx_icmpv6_process_na.c b/common/src/nx_icmpv6_process_na.c index 523eedc2..acfd9452 100644 --- a/common/src/nx_icmpv6_process_na.c +++ b/common/src/nx_icmpv6_process_na.c @@ -238,7 +238,7 @@ UINT i; /*lint -e{927} suppress cast of pointer to pointer, since it is necessary */ /*lint -e{644} suppress variable might not be initialized, since "nd_entry" was initialized in _nx_nd_cache_find_entry. */ lla = (USHORT *)nd_entry -> nx_nd_cache_mac_addr; - if ((new_lla[0] == lla[0]) && (new_lla[1] == lla[1]) && (new_lla[2] == lla[2])) + if ((new_lla[0] == lla[0]) && (new_lla[1] == lla[1]) && (new_lla[2] == lla[2])) /* lgtm[cpp/overflow-buffer] */ { /* No change in LLA. */ @@ -391,8 +391,8 @@ UINT i; /*lint -e{927} suppress cast of pointer to pointer, since it is necessary */ lla = (USHORT *)nd_entry -> nx_nd_cache_mac_addr; lla[0] = new_lla[0]; - lla[1] = new_lla[1]; - lla[2] = new_lla[2]; + lla[1] = new_lla[1]; /* lgtm[cpp/overflow-buffer] */ + lla[2] = new_lla[2]; /* lgtm[cpp/overflow-buffer] */ } if (nd_ptr -> nx_icmpv6_nd_flag & 0x40000000) /* S bit is set, force cache entry to REACHABLE */ { diff --git a/common/src/nx_icmpv6_process_ns.c b/common/src/nx_icmpv6_process_ns.c index c35cd22d..9cdc06f1 100644 --- a/common/src/nx_icmpv6_process_ns.c +++ b/common/src/nx_icmpv6_process_ns.c @@ -285,7 +285,7 @@ ULONG dest_address[4]; mac_lsw = ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[2]) << 24) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[3]) << 16) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[4]) << 8) | nd_entry -> nx_nd_cache_mac_addr[5]; new_msw = ((ULONG)(new_mac[0]) << 8) | (new_mac[1]); - new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; + new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; /* lgtm[cpp/overflow-buffer] */ if ((mac_msw != new_msw) || (mac_lsw != new_lsw)) /* If the new MAC is different from what we have in the table. */ { @@ -410,12 +410,12 @@ ULONG dest_address[4]; mac_addr = &option_ptr -> nx_icmpv6_option_data; mac_addr[0] = (USHORT)(interface_addr -> nxd_ipv6_address_attached -> nx_interface_physical_address_msw); - mac_addr[1] = (USHORT)((interface_addr -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); - mac_addr[2] = (USHORT)(interface_addr -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0x0000FFFF); + mac_addr[1] = (USHORT)((interface_addr -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); /* lgtm[cpp/overflow-buffer] */ + mac_addr[2] = (USHORT)(interface_addr -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0x0000FFFF); /* lgtm[cpp/overflow-buffer] */ NX_CHANGE_USHORT_ENDIAN(mac_addr[0]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); + NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); /* lgtm[cpp/overflow-buffer] */ + NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); /* lgtm[cpp/overflow-buffer] */ #ifdef NX_DISABLE_ICMPV6_TX_CHECKSUM compute_checksum = 0; diff --git a/common/src/nx_icmpv6_process_ra.c b/common/src/nx_icmpv6_process_ra.c index 6d5a3981..423576a1 100644 --- a/common/src/nx_icmpv6_process_ra.c +++ b/common/src/nx_icmpv6_process_ra.c @@ -37,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_icmpv6_process_ra PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -79,6 +79,10 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), improved */ /* option length verification, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ VOID _nx_icmpv6_process_ra(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -409,6 +413,12 @@ UINT interface_index; (ip_ptr -> nx_ipv6_address_change_notify)(ip_ptr, NX_IPV6_ADDRESS_STATELESS_AUTO_CONFIG, interface_index, first_unused, &ipv6_address -> nxd_ipv6_address[0]); } + if ((ip_ptr -> nx_ipv6_address_change_notify_internal) && (ipv6_address -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)) + { + interface_index = if_ptr -> nx_interface_index; + (ip_ptr -> nx_ipv6_address_change_notify_internal)(ip_ptr, NX_IPV6_ADDRESS_STATELESS_AUTO_CONFIG, interface_index, + first_unused, &ipv6_address -> nxd_ipv6_address[0]); + } #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ } } @@ -445,7 +455,7 @@ UINT interface_index; mac_lsw = ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[2]) << 24) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[3]) << 16) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[4]) << 8) | nd_entry -> nx_nd_cache_mac_addr[5]; new_msw = ((ULONG)(new_mac[0]) << 8) | (new_mac[1]); - new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; + new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; /* lgtm[cpp/overflow-buffer] */ if ((mac_msw != new_msw) || (mac_lsw != new_lsw)) { diff --git a/common/src/nx_icmpv6_process_redirect.c b/common/src/nx_icmpv6_process_redirect.c index 920d22a5..8c42db68 100644 --- a/common/src/nx_icmpv6_process_redirect.c +++ b/common/src/nx_icmpv6_process_redirect.c @@ -303,7 +303,7 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr; new_msw = ((ULONG)(new_mac[0]) << 8) | (new_mac[1]); mac_lsw = ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[2]) << 24) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[3]) << 16) | ((ULONG)(nd_entry -> nx_nd_cache_mac_addr[4]) << 8) | nd_entry -> nx_nd_cache_mac_addr[5]; - new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; + new_lsw = ((ULONG)(new_mac[2]) << 24) | ((ULONG)(new_mac[3]) << 16) | ((ULONG)(new_mac[4]) << 8) | new_mac[5]; /* lgtm[cpp/overflow-buffer] */ if ((mac_msw != new_msw) || (mac_lsw != new_lsw)) /* If the new MAC is different. */ { diff --git a/common/src/nx_icmpv6_send_error_message.c b/common/src/nx_icmpv6_send_error_message.c index 664d7e6d..02c84d2a 100644 --- a/common/src/nx_icmpv6_send_error_message.c +++ b/common/src/nx_icmpv6_send_error_message.c @@ -42,7 +42,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_icmpv6_send_error_message PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -90,6 +90,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), */ +/* fixed unsigned integers */ +/* comparison, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_icmpv6_send_error_message(NX_IP *ip_ptr, NX_PACKET *offending_packet, @@ -197,7 +201,7 @@ NXD_ADDRESS dest_addr; room for the Physical frame header, IPv6 header and ICMPv6 header of the error message. */ payload = pkt_ptr -> nx_packet_pool_owner -> nx_packet_pool_payload_size; - if (((INT)(bytes_to_copy + sizeof(NX_IPV6_HEADER) + sizeof(NX_ICMPV6_ERROR) + NX_PHYSICAL_HEADER) - (INT)payload) > 0) + if (((INT)((bytes_to_copy + sizeof(NX_IPV6_HEADER) + sizeof(NX_ICMPV6_ERROR) + NX_PHYSICAL_HEADER) - payload)) > 0) { bytes_to_copy = (UINT)(payload - (sizeof(NX_IPV6_HEADER) + sizeof(NX_ICMPV6_ERROR) + NX_PHYSICAL_HEADER)); diff --git a/common/src/nx_icmpv6_send_ns.c b/common/src/nx_icmpv6_send_ns.c index 903d3329..0c2a32e1 100644 --- a/common/src/nx_icmpv6_send_ns.c +++ b/common/src/nx_icmpv6_send_ns.c @@ -226,13 +226,13 @@ NX_IP_DRIVER driver_request; /* Fill in the source MAC address */ mac_addr = &nd_options -> nx_icmpv6_option_data; mac_addr[0] = (USHORT)(outgoing_address -> nxd_ipv6_address_attached -> nx_interface_physical_address_msw); - mac_addr[1] = (USHORT)((outgoing_address -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); - mac_addr[2] = (USHORT)(outgoing_address -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0x0000FFFF); + mac_addr[1] = (USHORT)((outgoing_address -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); /* lgtm[cpp/overflow-buffer] */ + mac_addr[2] = (USHORT)(outgoing_address -> nxd_ipv6_address_attached -> nx_interface_physical_address_lsw & 0x0000FFFF); /* lgtm[cpp/overflow-buffer] */ /* Byte swapping. */ NX_CHANGE_USHORT_ENDIAN(mac_addr[0]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); + NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); /* lgtm[cpp/overflow-buffer] */ + NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); /* lgtm[cpp/overflow-buffer] */ } #ifdef NX_DISABLE_ICMPV6_TX_CHECKSUM diff --git a/common/src/nx_icmpv6_send_rs.c b/common/src/nx_icmpv6_send_rs.c index 7ff18deb..eb3f0ae9 100644 --- a/common/src/nx_icmpv6_send_rs.c +++ b/common/src/nx_icmpv6_send_rs.c @@ -164,13 +164,13 @@ NX_ICMPV6_OPTION *rs_options; /* Fill in the source mac address. */ mac_addr = &rs_options -> nx_icmpv6_option_data; mac_addr[0] = (USHORT)(ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_msw); - mac_addr[1] = (USHORT)((ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); - mac_addr[2] = (USHORT)(ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_lsw & 0x0000FFFF); + mac_addr[1] = (USHORT)((ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_lsw & 0xFFFF0000) >> 16); /* lgtm[cpp/overflow-buffer] */ + mac_addr[2] = (USHORT)(ip_ptr -> nx_ip_interface[if_index].nx_interface_physical_address_lsw & 0x0000FFFF); /* lgtm[cpp/overflow-buffer] */ /* Byte swapping. */ NX_CHANGE_USHORT_ENDIAN(mac_addr[0]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); - NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); + NX_CHANGE_USHORT_ENDIAN(mac_addr[1]); /* lgtm[cpp/overflow-buffer] */ + NX_CHANGE_USHORT_ENDIAN(mac_addr[2]); /* lgtm[cpp/overflow-buffer] */ #ifdef NX_DISABLE_ICMPV6_TX_CHECKSUM compute_checksum = 0; diff --git a/common/src/nx_ip_address_set.c b/common/src/nx_ip_address_set.c index 71a2081a..24a0e281 100644 --- a/common/src/nx_ip_address_set.c +++ b/common/src/nx_ip_address_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -70,75 +70,13 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), */ +/* merged duplicated functions,*/ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ip_address_set(NX_IP *ip_ptr, ULONG ip_address, ULONG network_mask) { - -#ifndef NX_DISABLE_IPV4 -TX_INTERRUPT_SAVE_AREA - -VOID (*address_change_notify)(NX_IP *, VOID *); -VOID *additional_info; -ULONG previous_ip_address; -ULONG previous_network_mask; - - - /* If trace is enabled, insert this event into the trace buffer. */ - NX_TRACE_IN_LINE_INSERT(NX_TRACE_IP_ADDRESS_SET, ip_ptr, ip_address, network_mask, 0, NX_TRACE_IP_EVENTS, 0, 0); - - /* Get mutex protection. */ - tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); - - - /* Disable interrupts. */ - TX_DISABLE - - /* Save previous IP address and network mask. This service assumes the - operations on the primary interface. */ - previous_ip_address = ip_ptr -> nx_ip_interface[0].nx_interface_ip_address; - previous_network_mask = ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask; - - /* Pickup the current notification callback and additional information pointers. */ - address_change_notify = ip_ptr -> nx_ip_address_change_notify; - additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info; - - /* Setup the IP address and the network mask. */ - ip_ptr -> nx_ip_interface[0].nx_interface_ip_address = ip_address; - ip_ptr -> nx_ip_interface[0].nx_interface_ip_network_mask = network_mask; - ip_ptr -> nx_ip_interface[0].nx_interface_ip_network = ip_address & network_mask; - - /* Ensure the RARP function is disabled. */ - ip_ptr -> nx_ip_rarp_periodic_update = NX_NULL; - ip_ptr -> nx_ip_rarp_queue_process = NX_NULL; - - /* Restore interrupts. */ - TX_RESTORE - - /* Release mutex protection. */ - tx_mutex_put(&(ip_ptr -> nx_ip_protection)); - - /* Determine if the application should be notified of the IP address and/or - network mask change. */ - if ((address_change_notify) && - ((ip_address != previous_ip_address) || (network_mask != previous_network_mask))) - { - - /* Yes, call the application's IP address change notify function. */ - (address_change_notify)(ip_ptr, additional_info); - } - - /* Initialize the ARP defend timeout. */ - ip_ptr -> nx_ip_interface[0].nx_interface_arp_defend_timeout = 0; - - /* Return completion status. */ - return(NX_SUCCESS); -#else /* NX_DISABLE_IPV4 */ - NX_PARAMETER_NOT_USED(ip_ptr); - NX_PARAMETER_NOT_USED(ip_address); - NX_PARAMETER_NOT_USED(network_mask); - - return(NX_NOT_SUPPORTED); -#endif /* !NX_DISABLE_IPV4 */ + return(_nx_ip_interface_address_set(ip_ptr, 0, ip_address, network_mask)); } diff --git a/common/src/nx_ip_dispatch_process.c b/common/src/nx_ip_dispatch_process.c index 768306b9..385cdffe 100644 --- a/common/src/nx_ip_dispatch_process.c +++ b/common/src/nx_ip_dispatch_process.c @@ -43,7 +43,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_dispatch_process PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -98,6 +98,10 @@ /* 09-30-2020 Yuxin Zhou Modified comment(s), fixed */ /* destination header check, */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), expanded */ +/* protocols support for raw */ +/* packet, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_ip_dispatch_process(NX_IP *ip_ptr, NX_PACKET *packet_ptr, UINT protocol) @@ -452,6 +456,19 @@ NX_ICMPV6_HEADER *icmp_header_ptr; } #endif /* NX_IPSEC_ENABLE */ +#if defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) + if ((ip_ptr -> nx_ip_raw_ip_processing) && (ip_ptr -> nx_ip_raw_packet_filter)) + { + + /* Let RAW packet filter handler filter all incoming packets. */ + if ((ip_ptr -> nx_ip_raw_ip_processing)(ip_ptr, protocol << 16, packet_ptr) == NX_SUCCESS) + { + /* No need to free the packet as it is consumed by the raw process */ + return(0); + } + } +#endif /* defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */ + if (protocol == NX_PROTOCOL_TCP) { #ifdef FEATURE_NX_IPV6 @@ -565,10 +582,15 @@ NX_ICMPV6_HEADER *icmp_header_ptr; { if (ip_ptr -> nx_ip_raw_ip_processing) { - if ((ip_ptr -> nx_ip_raw_ip_processing)(ip_ptr, protocol << 16, packet_ptr) == NX_SUCCESS) +#if defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) + if (ip_ptr -> nx_ip_raw_packet_filter == NX_NULL) +#endif /* defined(NX_ENABLE_IP_RAW_PACKET_ALL_STACK) && defined(NX_ENABLE_IP_RAW_PACKET_FILTER) */ { - /* No need to free the packet as it is consumed by the raw process */ - return(0); + if ((ip_ptr -> nx_ip_raw_ip_processing)(ip_ptr, protocol << 16, packet_ptr) == NX_SUCCESS) + { + /* No need to free the packet as it is consumed by the raw process */ + return(0); + } } } diff --git a/common/src/nx_ip_header_add.c b/common/src/nx_ip_header_add.c index 46758a0e..a638aac8 100644 --- a/common/src/nx_ip_header_add.c +++ b/common/src/nx_ip_header_add.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_header_add PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -52,6 +52,7 @@ /* */ /* ip_ptr Pointer to IP control block */ /* packet_ptr Pointer to packet to send */ +/* source_ip Source IP address */ /* destination_ip Destination IP address */ /* type_of_service Type of service for packet */ /* time_to_live Time to live value for packet */ @@ -79,9 +80,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ -UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG destination_ip, +UINT _nx_ip_header_add(NX_IP *ip_ptr, NX_PACKET *packet_ptr, ULONG source_ip, ULONG destination_ip, ULONG type_of_service, ULONG time_to_live, ULONG protocol, ULONG fragment) { ULONG router_alert = 0; @@ -154,7 +158,7 @@ ULONG val; ip_header_ptr -> nx_ip_header_word_2 = ((time_to_live << NX_IP_TIME_TO_LIVE_SHIFT) | protocol); /* Place the source IP address in the IP header. */ - ip_header_ptr -> nx_ip_header_source_ip = packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address; + ip_header_ptr -> nx_ip_header_source_ip = source_ip; /* Place the destination IP address in the IP header. */ ip_header_ptr -> nx_ip_header_destination_ip = destination_ip; diff --git a/common/src/nx_ip_interface_address_set.c b/common/src/nx_ip_interface_address_set.c index c5cb7595..b2cebc2a 100644 --- a/common/src/nx_ip_interface_address_set.c +++ b/common/src/nx_ip_interface_address_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_interface_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -71,6 +71,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_ip_interface_address_set(NX_IP *ip_ptr, UINT interface_index, ULONG ip_address, ULONG network_mask) @@ -81,6 +85,7 @@ TX_INTERRUPT_SAVE_AREA VOID (*address_change_notify)(NX_IP *, VOID *); VOID *additional_info; +VOID (*address_change_notify_internal)(NX_IP *, VOID *); ULONG previous_ip_address; ULONG previous_network_mask; @@ -103,6 +108,9 @@ ULONG previous_network_mask; address_change_notify = ip_ptr -> nx_ip_address_change_notify; additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info; + /* Pickup the internal notification callback. */ + address_change_notify_internal = ip_ptr -> nx_ip_address_change_notify_internal; + /* Setup the IP address and the network mask. */ ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_address = ip_address; ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_network_mask = network_mask; @@ -128,6 +136,16 @@ ULONG previous_network_mask; (address_change_notify)(ip_ptr, additional_info); } + /* Determine if the internal application should be notified of the IP address and/or + network mask change. */ + if ((address_change_notify_internal) && + ((ip_address != previous_ip_address) || (network_mask != previous_network_mask))) + { + + /* Yes, call the application's IP address change notify function. */ + (address_change_notify_internal)(ip_ptr, NX_NULL); + } + /* Initialize the ARP defend timeout. */ ip_ptr -> nx_ip_interface[interface_index].nx_interface_arp_defend_timeout = 0; diff --git a/common/src/nx_ip_interface_attach.c b/common/src/nx_ip_interface_attach.c index 23d20e76..5c62d951 100644 --- a/common/src/nx_ip_interface_attach.c +++ b/common/src/nx_ip_interface_attach.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_interface_attach PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -88,6 +88,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ip_interface_attach(NX_IP *ip_ptr, CHAR *interface_name, ULONG ip_address, ULONG network_mask, VOID (*ip_link_driver)(struct NX_IP_DRIVER_STRUCT *)) @@ -159,12 +162,25 @@ ULONG address[4]; if (ip_ptr -> nx_ip_initialize_done == NX_TRUE) { +#ifdef NX_ENABLE_INTERFACE_CAPABILITY + /* Clear capability flag. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag = 0; +#endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + /* First attach the interface to the device. */ driver_request.nx_ip_driver_ptr = ip_ptr; driver_request.nx_ip_driver_command = NX_LINK_INTERFACE_ATTACH; driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]); (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { + + /* Set checksum capability for TCP/IP offload interface. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Call the link driver to initialize the hardware. Among other responsibilities, the driver is required to provide the diff --git a/common/src/nx_ip_interface_status_check.c b/common/src/nx_ip_interface_status_check.c index 1edfc816..e45731c7 100644 --- a/common/src/nx_ip_interface_status_check.c +++ b/common/src/nx_ip_interface_status_check.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_interface_status_check PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -79,6 +79,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* added driver entry check, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ UINT _nx_ip_interface_status_check(NX_IP *ip_ptr, UINT interface_index, ULONG needed_status, @@ -185,6 +188,14 @@ ULONG trace_timestamp; NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_GET_STATUS, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* Call link level driver. */ + if(ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry == NX_NULL) + { + + /* Release mutex protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(NX_NOT_SUCCESSFUL); + } (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry)(&driver_request); /* If the driver does not recognize this keyword, we fall back to reading the IP link status.*/ @@ -254,6 +265,14 @@ ULONG trace_timestamp; NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_IO_DRIVER_GET_STATUS, ip_ptr, 0, 0, 0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* Call link level driver. */ + if(ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry == NX_NULL) + { + + /* Release mutex protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(NX_NOT_SUCCESSFUL); + } (ip_ptr -> nx_ip_interface[interface_index].nx_interface_link_driver_entry)(&driver_request); /* If the driver does not recognize this keyword, we fall back to reading the IP link status.*/ diff --git a/common/src/nx_ip_packet_receive.c b/common/src/nx_ip_packet_receive.c index b9044e56..270ca7a5 100644 --- a/common/src/nx_ip_packet_receive.c +++ b/common/src/nx_ip_packet_receive.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_packet_receive PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* added new ip filter, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -124,6 +127,20 @@ UCHAR version_byte; return; } } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_IN) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_release(packet_ptr); + return; + } + } #endif /* NX_ENABLE_IP_PACKET_FILTER */ #ifndef NX_DISABLE_IPV4 diff --git a/common/src/nx_ip_packet_send.c b/common/src/nx_ip_packet_send.c index 7847dbcd..7b258baf 100644 --- a/common/src/nx_ip_packet_send.c +++ b/common/src/nx_ip_packet_send.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -83,6 +83,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* added new ip filter, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, @@ -133,6 +137,24 @@ ULONG val; return; } +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { +#ifndef NX_DISABLE_IP_INFO + + /* Increment the IP invalid packet error. */ + ip_ptr -> nx_ip_invalid_transmit_packets++; +#endif + + /* Ignore sending all packets for TCP/IP offload. Release the packet. */ + _nx_packet_transmit_release(packet_ptr); + + /* Return... nothing more can be done! */ + return; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE /* Check if this packet is continued after HW crypto engine. */ if (packet_ptr -> nx_packet_ipsec_sa_ptr && @@ -191,7 +213,8 @@ ULONG val; { /* Add the IP Header to the packet. */ - _nx_ip_header_add(ip_ptr, packet_ptr, destination_ip, type_of_service, time_to_live, protocol, fragment); + _nx_ip_header_add(ip_ptr, packet_ptr, packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address, + destination_ip, type_of_service, time_to_live, protocol, fragment); #ifdef NX_ENABLE_IP_PACKET_FILTER /* Check if the IP packet filter is set. */ @@ -208,6 +231,20 @@ ULONG val; return; } } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } #endif /* NX_ENABLE_IP_PACKET_FILTER */ } diff --git a/common/src/nx_ip_thread_entry.c b/common/src/nx_ip_thread_entry.c index 69409683..9fab67d3 100644 --- a/common/src/nx_ip_thread_entry.c +++ b/common/src/nx_ip_thread_entry.c @@ -43,7 +43,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ip_thread_entry PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -114,6 +114,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ip_thread_entry(ULONG ip_ptr_value) @@ -164,6 +167,15 @@ NXD_IPV6_ADDRESS *interface_ipv6_address; driver_request.nx_ip_driver_interface = &(ip_ptr -> nx_ip_interface[i]); (ip_ptr -> nx_ip_interface[i].nx_interface_link_driver_entry)(&driver_request); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { + + /* Set checksum capability for TCP/IP offload interface. */ + ip_ptr -> nx_ip_interface[i].nx_interface_capability_flag |= NX_INTERFACE_CAPABILITY_CHECKSUM_ALL; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Call the link driver to initialize the hardware. Among other responsibilities, the driver is required to provide the Maximum Transfer Unit (MTU) for the physical layer. The MTU diff --git a/common/src/nx_ipv6_header_add.c b/common/src/nx_ipv6_header_add.c index 3dcc2693..602ec001 100644 --- a/common/src/nx_ipv6_header_add.c +++ b/common/src/nx_ipv6_header_add.c @@ -43,7 +43,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_header_add PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -84,6 +84,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_ipv6_header_add(NX_IP *ip_ptr, NX_PACKET **packet_pptr, @@ -251,22 +254,6 @@ USHORT short_val; NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_destination_ip); NX_IPV6_ADDRESS_CHANGE_ENDIAN(ip_header_ptr -> nx_ip_header_source_ip); -#ifdef NX_ENABLE_IP_PACKET_FILTER - /* Check if the IP packet filter is set. */ - if (ip_ptr -> nx_ip_packet_filter) - { - - /* Yes, call the IP packet filter routine. */ - if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), - NX_IP_PACKET_OUT) != NX_SUCCESS) - { - - /* Drop the packet. */ - _nx_packet_transmit_release(packet_ptr); - return(NX_INVALID_PACKET); - } - } -#endif /* NX_ENABLE_IP_PACKET_FILTER */ #ifdef NX_IPSEC_ENABLE } else diff --git a/common/src/nx_ipv6_packet_send.c b/common/src/nx_ipv6_packet_send.c index 8d03c1a6..2c17a67b 100644 --- a/common/src/nx_ipv6_packet_send.c +++ b/common/src/nx_ipv6_packet_send.c @@ -39,7 +39,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_packet_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -93,6 +93,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ VOID _nx_ipv6_packet_send(NX_IP *ip_ptr, NX_PACKET *packet_ptr, @@ -120,6 +123,23 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr; /* Interface can not be NULL. */ NX_ASSERT(if_ptr != NX_NULL); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (if_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) + { +#ifndef NX_DISABLE_IP_INFO + + /* Increment the IP invalid packet error. */ + ip_ptr -> nx_ip_invalid_transmit_packets++; +#endif + + /* Ignore sending all packets for TCP/IP offload. Release the packet. */ + _nx_packet_transmit_release(packet_ptr); + + /* Return... nothing more can be done! */ + return; + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Add IPv6 header. */ if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, protocol, payload_size, hop_limit, src_address, dest_address, &fragment) != NX_SUCCESS) @@ -129,6 +149,37 @@ NX_IPV6_DESTINATION_ENTRY *dest_entry_ptr; return; } +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter) + { + + /* Yes, call the IP packet filter routine. */ + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Drop the packet. */ + _nx_packet_transmit_release(packet_ptr); + return; + } + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + next_hop_mtu = if_ptr -> nx_interface_ip_mtu_size; packet_ptr -> nx_packet_ip_header = packet_ptr -> nx_packet_prepend_ptr; diff --git a/common/src/nx_ipv6_process_hop_by_hop_option.c b/common/src/nx_ipv6_process_hop_by_hop_option.c index cef14f7b..c5881662 100644 --- a/common/src/nx_ipv6_process_hop_by_hop_option.c +++ b/common/src/nx_ipv6_process_hop_by_hop_option.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_ipv6_process_hop_by_hop_option PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Yuxin Zhou Modified comment(s), improved */ +/* buffer read overflow check, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_ipv6_process_hop_by_hop_option(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -87,6 +90,14 @@ NX_IPV6_HOP_BY_HOP_OPTION *option; /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); + /* Make sure there's no OOB when reading Hdr Ext Len from the packet buffer. */ + if ((UINT)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr) < 2) + { + + /* return an error code. */ + return(NX_OPTION_HEADER_ERROR); + } + /* Read the Hdr Ext Len field. */ header_length = *(packet_ptr -> nx_packet_prepend_ptr + 1); diff --git a/common/src/nx_md5.c b/common/src/nx_md5.c index 68567c88..deeea5d4 100644 --- a/common/src/nx_md5.c +++ b/common/src/nx_md5.c @@ -242,7 +242,7 @@ ULONG needed_fill_bytes; /* Copy the appropriate portion of the input buffer into the internal buffer of the context. */ - memcpy((void *) &(context -> nx_md5_buffer[current_bytes]), (void *) input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. */ + memcpy((void *) &(context -> nx_md5_buffer[current_bytes]), (void *) input_ptr, needed_fill_bytes); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Process the 64-byte (512 bit) buffer. */ _nx_md5_process_buffer(context, context -> nx_md5_buffer); @@ -273,7 +273,7 @@ ULONG needed_fill_bytes; /* Save the remaining bytes in the internal buffer after any remaining bytes that it is processed later. */ - memcpy((void *) &(context -> nx_md5_buffer[current_bytes]), (void *) input_ptr, input_length); /* Use case of memcpy is verified. */ + memcpy((void *) &(context -> nx_md5_buffer[current_bytes]), (void *) input_ptr, input_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } /* Return success. */ diff --git a/common/src/nx_packet_data_adjust.c b/common/src/nx_packet_data_adjust.c index fd34c8aa..103d5cab 100644 --- a/common/src/nx_packet_data_adjust.c +++ b/common/src/nx_packet_data_adjust.c @@ -154,7 +154,7 @@ NX_PACKET *work_ptr; } /* Firstly, append the overflowing data to the new packet.. */ - memcpy(work_ptr -> nx_packet_prepend_ptr, data_start, append_size); /* Use case of memcpy is verified. */ + memcpy(work_ptr -> nx_packet_prepend_ptr, data_start, append_size); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ work_ptr -> nx_packet_append_ptr = (UCHAR *)((ALIGN_TYPE)work_ptr -> nx_packet_prepend_ptr + append_size); /* Secondly, calculate the shift data size. */ diff --git a/common/src/nx_packet_data_append.c b/common/src/nx_packet_data_append.c index 20b66dd1..b7318941 100644 --- a/common/src/nx_packet_data_append.c +++ b/common/src/nx_packet_data_append.c @@ -265,7 +265,7 @@ NX_PACKET *work_ptr; /* Working packet pointer */ #endif /* NX_DISABLE_PACKET_CHAIN */ /* Copy the data into the current packet buffer. */ - memcpy(work_ptr -> nx_packet_append_ptr, source_ptr, copy_size); /* Use case of memcpy is verified. */ + memcpy(work_ptr -> nx_packet_append_ptr, source_ptr, copy_size); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Adjust the remaining data size. */ data_size = data_size - copy_size; diff --git a/common/src/nx_packet_data_extract_offset.c b/common/src/nx_packet_data_extract_offset.c index 813448af..9a892d57 100644 --- a/common/src/nx_packet_data_extract_offset.c +++ b/common/src/nx_packet_data_extract_offset.c @@ -187,7 +187,7 @@ NX_PACKET *working_packet_ptr; } /* Copy data from this packet. */ - memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. */ + memcpy(destination_ptr, source_ptr, bytes_to_copy); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Update the pointers. */ destination_ptr += bytes_to_copy; diff --git a/common/src/nx_packet_data_retrieve.c b/common/src/nx_packet_data_retrieve.c index 97a8afde..75a419a0 100644 --- a/common/src/nx_packet_data_retrieve.c +++ b/common/src/nx_packet_data_retrieve.c @@ -103,7 +103,7 @@ ULONG bytes_to_copy; /* Copy data to destination. */ /* Note: The buffer size must be not less than packet_ptr -> nx_packet_length. */ - memcpy(destination_ptr, packet_ptr -> nx_packet_prepend_ptr, bytes_to_copy); /* Use case of memcpy is verified. The buffer is provided by user. */ + memcpy(destination_ptr, packet_ptr -> nx_packet_prepend_ptr, bytes_to_copy); /* Use case of memcpy is verified. The buffer is provided by user. lgtm[cpp/banned-api-usage-required-any] */ remaining_bytes -= bytes_to_copy; destination_ptr += bytes_to_copy; diff --git a/common/src/nx_ram_network_driver.c b/common/src/nx_ram_network_driver.c index 53785fa9..9bac2ef7 100644 --- a/common/src/nx_ram_network_driver.c +++ b/common/src/nx_ram_network_driver.c @@ -110,7 +110,7 @@ static _nx_ram_network_driver_instance_type nx_ram_driver[NX_MAX_RAM_INTERFACES] /* FUNCTION RELEASE */ /* */ /* _nx_ram_network_driver PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -146,6 +146,10 @@ static _nx_ram_network_driver_instance_type nx_ram_driver[NX_MAX_RAM_INTERFACES] /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* added sample of returning */ +/* link's interface type, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ VOID _nx_ram_network_driver(NX_IP_DRIVER *driver_req_ptr) @@ -525,6 +529,14 @@ UINT interface_index; break; } + case NX_LINK_GET_INTERFACE_TYPE: + { + + /* Return the link's interface type in the supplied return pointer. Unsupported feature. */ + *(driver_req_ptr -> nx_ip_driver_return_ptr) = NX_INTERFACE_TYPE_UNKNOWN; + break; + } + case NX_LINK_DEFERRED_PROCESSING: { diff --git a/common/src/nx_rarp_packet_receive.c b/common/src/nx_rarp_packet_receive.c index 82fd9f7a..998a7b3c 100644 --- a/common/src/nx_rarp_packet_receive.c +++ b/common/src/nx_rarp_packet_receive.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_rarp_packet_receive PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -72,6 +72,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ VOID _nx_rarp_packet_receive(NX_IP *ip_ptr, NX_PACKET *packet_ptr) @@ -83,6 +87,7 @@ ULONG *message_ptr; UINT i; VOID (*address_change_notify)(NX_IP *, VOID *) = NX_NULL; VOID *additional_info = NX_NULL; +VOID (*address_change_notify_internal)(NX_IP *, VOID *) = NX_NULL; #ifndef NX_DISABLE_RX_SIZE_CHECKING @@ -155,6 +160,9 @@ VOID *additional_info = NX_NULL; address_change_notify = ip_ptr -> nx_ip_address_change_notify; additional_info = ip_ptr -> nx_ip_address_change_notify_additional_info; + /* Pickup the internal notification callback. */ + address_change_notify_internal = ip_ptr -> nx_ip_address_change_notify_internal; + /* Set the IP address of this IP instance to the target IP address in the RARP response. */ packet_ptr -> nx_packet_address.nx_packet_interface_ptr -> nx_interface_ip_address = *(message_ptr + 6); @@ -213,6 +221,13 @@ VOID *additional_info = NX_NULL; (address_change_notify)(ip_ptr, additional_info); } + /* Determine if the internal application should be notified of the IP address change. */ + if (address_change_notify_internal != NX_NULL) + { + /* Yes, call the internal application's IP address change notify function. */ + (address_change_notify_internal)(ip_ptr, NX_NULL); + } + return; } #endif /* !NX_DISABLE_IPV4 */ diff --git a/common/src/nx_tcp_client_socket_bind.c b/common/src/nx_tcp_client_socket_bind.c index 2467200c..535ed414 100644 --- a/common/src/nx_tcp_client_socket_bind.c +++ b/common/src/nx_tcp_client_socket_bind.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_client_socket_bind PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_tcp_client_socket_bind(NX_TCP_SOCKET *socket_ptr, UINT port, ULONG wait_option) @@ -116,7 +119,7 @@ NX_TCP_SOCKET *end_ptr; { /* Call the find routine to allocate a TCP port. */ - port = NX_SEARCH_PORT_START + (UINT)(NX_RAND() % ((NX_MAX_PORT + 1) - NX_SEARCH_PORT_START)); + port = NX_SEARCH_PORT_START + (UINT)(((ULONG)NX_RAND()) % ((NX_MAX_PORT + 1) - NX_SEARCH_PORT_START)); if (_nx_tcp_free_port_find(ip_ptr, port, &port) != NX_SUCCESS) { diff --git a/common/src/nx_tcp_server_socket_driver_listen.c b/common/src/nx_tcp_server_socket_driver_listen.c new file mode 100644 index 00000000..f0c68cd7 --- /dev/null +++ b/common/src/nx_tcp_server_socket_driver_listen.c @@ -0,0 +1,119 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_server_socket_driver_listen PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers a listen request to all TCP/IP offload */ +/* interfaces. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* port TCP port number */ +/* socket_ptr Server socket pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_server_socket_listen Register a listen request */ +/* _nx_tcp_server_socket_relisten Register a listen request */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_tcp_server_socket_driver_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr) +{ +UINT status; +UINT i; +NX_INTERFACE *interface_ptr; + + /* Loop all interfaces to listen to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if ((interface_ptr -> nx_interface_valid == NX_FALSE) || + (interface_ptr -> nx_interface_link_up == NX_FALSE)) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface listen to port. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_LISTEN, + NX_NULL, NX_NULL, NX_NULL, + port, NX_NULL, NX_NO_WAIT); + if (status) + { + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ \ No newline at end of file diff --git a/common/src/nx_tcp_server_socket_listen.c b/common/src/nx_tcp_server_socket_listen.c index 3a5162c2..52b6d6f3 100644 --- a/common/src/nx_tcp_server_socket_listen.c +++ b/common/src/nx_tcp_server_socket_listen.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_listen PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_listen(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr, UINT listen_queue_size, @@ -232,6 +235,22 @@ UINT bound; listen_ptr -> nx_tcp_listen_next = listen_ptr; } +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Listen to TCP/IP offload interfaces. */ + if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr)) + { + + /* At least one of the interface fails to listen to port. */ + _nx_tcp_server_socket_unlisten(ip_ptr, port); + + /* Listen request failure, release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Successful listen request, release the protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); diff --git a/common/src/nx_tcp_server_socket_relisten.c b/common/src/nx_tcp_server_socket_relisten.c index 5bb5896c..b868eb6d 100644 --- a/common/src/nx_tcp_server_socket_relisten.c +++ b/common/src/nx_tcp_server_socket_relisten.c @@ -38,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_relisten PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_relisten(NX_IP *ip_ptr, UINT port, NX_TCP_SOCKET *socket_ptr) @@ -150,6 +153,19 @@ VOID (*listen_callback)(NX_TCP_SOCKET *socket_ptr, UINT /* Yes, a listen request was found for this port, with an empty socket designation. */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD + /* Listen to TCP/IP offload interfaces. */ + if (_nx_tcp_server_socket_driver_listen(ip_ptr, port, socket_ptr)) + { + + /* Listen request failure, release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Return an already bound error code. */ + return(NX_TCPIP_OFFLOAD_ERROR); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Determine if there are any connection requests queued up. */ if (!listen_ptr -> nx_tcp_listen_queue_current) { diff --git a/common/src/nx_tcp_server_socket_unlisten.c b/common/src/nx_tcp_server_socket_unlisten.c index c56191e6..7b5053d2 100644 --- a/common/src/nx_tcp_server_socket_unlisten.c +++ b/common/src/nx_tcp_server_socket_unlisten.c @@ -30,12 +30,96 @@ #include "nx_packet.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_server_socket_driver_unlisten PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles the TCP server unlisten for TCP/IP offload */ +/* interface. */ +/* */ +/* INPUT */ +/* */ +/* ip_ptr Pointer to IP instance */ +/* socket_ptr Pointer to TCP socket */ +/* port TCP port number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection */ +/* tx_mutex_put Release protection */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_server_socket_unlisten */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_tcp_server_socket_driver_unlisten(NX_IP *ip_ptr, NX_TCP_SOCKET *socket_ptr, UINT port) +{ +UINT i; +NX_INTERFACE *interface_ptr; + + /* Loop all interfaces to unlisten to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if (interface_ptr -> nx_interface_valid == NX_FALSE) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface unlisten to port. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_UNLISTEN, + NX_NULL, NX_NULL, NX_NULL, + port, NX_NULL, NX_NO_WAIT); + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_server_socket_unlisten PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -71,6 +155,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_server_socket_unlisten(NX_IP *ip_ptr, UINT port) @@ -192,6 +279,10 @@ struct NX_TCP_LISTEN_STRUCT *listen_ptr; listen_ptr -> nx_tcp_listen_next = ip_ptr -> nx_ip_tcp_available_listen_requests; ip_ptr -> nx_ip_tcp_available_listen_requests = listen_ptr; +#ifdef NX_ENABLE_TCPIP_OFFLOAD + _nx_tcp_server_socket_driver_unlisten(ip_ptr, socket_ptr, port); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Release the protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); diff --git a/common/src/nx_tcp_socket_block_cleanup.c b/common/src/nx_tcp_socket_block_cleanup.c index 3270d683..544f8e79 100644 --- a/common/src/nx_tcp_socket_block_cleanup.c +++ b/common/src/nx_tcp_socket_block_cleanup.c @@ -28,13 +28,16 @@ #include "nx_api.h" #include "nx_tcp.h" #include "nx_ipv6.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_block_cleanup PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -53,7 +56,7 @@ /* */ /* CALLS */ /* */ -/* None */ +/* _nx_http_proxy_client_cleanup Clean up HTTP Proxy */ /* */ /* CALLED BY */ /* */ @@ -70,6 +73,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_block_cleanup(NX_TCP_SOCKET *socket_ptr) @@ -109,6 +115,15 @@ VOID _nx_tcp_socket_block_cleanup(NX_TCP_SOCKET *socket_ptr) /* Client socket, return to a CLOSED state. */ socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED; + +#ifdef NX_ENABLE_HTTP_PROXY + if (socket_ptr -> nx_tcp_socket_ip_ptr -> nx_ip_http_proxy_enable) + { + + /* Clean up the HTTP Proxy. */ + _nx_http_proxy_client_cleanup(socket_ptr); + } +#endif /* NX_ENABLE_HTTP_PROXY */ } else { diff --git a/common/src/nx_tcp_socket_connection_reset.c b/common/src/nx_tcp_socket_connection_reset.c index 526493df..cf7500c3 100644 --- a/common/src/nx_tcp_socket_connection_reset.c +++ b/common/src/nx_tcp_socket_connection_reset.c @@ -35,7 +35,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_connection_reset PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -81,6 +81,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the logic of */ +/* flushing receive queue. */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_connection_reset(NX_TCP_SOCKET *socket_ptr) @@ -103,15 +107,6 @@ UINT saved_state; _nx_tcp_socket_transmit_queue_flush(socket_ptr); } - /* Check for queued receive packets and if found they need - to be released. */ - if (socket_ptr -> nx_tcp_socket_receive_queue_count) - { - - /* Release all received packets. */ - _nx_tcp_socket_receive_queue_flush(socket_ptr); - } - /* Clear all receive thread suspensions on this socket. */ while (socket_ptr -> nx_tcp_socket_receive_suspension_list) { diff --git a/common/src/nx_tcp_socket_disconnect.c b/common/src/nx_tcp_socket_disconnect.c index e04f4f09..bd49d3a3 100644 --- a/common/src/nx_tcp_socket_disconnect.c +++ b/common/src/nx_tcp_socket_disconnect.c @@ -36,7 +36,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_disconnect PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option) @@ -88,6 +91,9 @@ UINT _nx_tcp_socket_disconnect(NX_TCP_SOCKET *socket_ptr, ULONG wait_option) #ifndef NX_DISABLE_RESET_DISCONNECT NX_TCP_HEADER tcp_header; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD +NX_INTERFACE *interface_ptr; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ UINT status; NX_IP *ip_ptr; @@ -129,6 +135,25 @@ NX_IP *ip_ptr; socket_ptr -> nx_tcp_socket_keepalive_retries = 0; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + if (interface_ptr && + (interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + + /* Let TCP/IP offload interface close the connection. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SOCKET_DISCONNECT, + NX_NULL, NX_NULL, NX_NULL, 0, NX_NULL, + wait_option); + + /* Reset socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED; + } + else +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Determine if the connection wasn't fully completed. */ if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_SENT) || (socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_RECEIVED)) diff --git a/common/src/nx_tcp_socket_driver_establish.c b/common/src/nx_tcp_socket_driver_establish.c new file mode 100644 index 00000000..2be2a994 --- /dev/null +++ b/common/src/nx_tcp_socket_driver_establish.c @@ -0,0 +1,243 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" +#include "nx_packet.h" +#include "tx_thread.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_establish PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is invoked when a TCP connection is established. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* interface_ptr Pointer to IP interface */ +/* remote_port Pointer to remote UDP port */ +/* */ +/* OUTPUT */ +/* */ +/* Status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +UINT _nx_tcp_socket_driver_establish(NX_TCP_SOCKET *socket_ptr, NX_INTERFACE *interface_ptr, UINT remote_port) +{ +NX_IP *ip_ptr; +NXD_ADDRESS ip_address; +UINT status; +UINT index; +UINT port; +struct NX_TCP_LISTEN_STRUCT *listen_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Obtain the IP internal mutex before processing the IP event. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + /* Check socket state first. */ + if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_SENT) && + (socket_ptr -> nx_tcp_socket_state != NX_TCP_LISTEN_STATE)&& + (socket_ptr -> nx_tcp_socket_state != NX_TCP_SYN_RECEIVED)) + { + + /* Just ignore socket not in connecting state. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_NOT_SUCCESSFUL); + } + + if (socket_ptr -> nx_tcp_socket_client_type == NX_FALSE) + { + if (socket_ptr -> nx_tcp_socket_bound_next) + { + + /* TCP socket is connecting on other interface. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_NOT_SUCCESSFUL); + } + + /* For TCP server socket, the connection is not established yet. */ + port = socket_ptr -> nx_tcp_socket_port; + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SERVER_SOCKET_ACCEPT, + NX_NULL, NX_NULL, &ip_address, port, + &remote_port, NX_NO_WAIT); + + if (status) + { + + /* This should not happen as a connection is pendding. */ + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_TCPIP_OFFLOAD_ERROR); + } + + /* Setup connection parameters. */ + socket_ptr -> nx_tcp_socket_connect_interface = interface_ptr; + + /* Save the server port and server IP address. */ + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version = ip_address.nxd_ip_version; +#ifndef NX_DISABLE_IPV4 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V4) + { + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4 = ip_address.nxd_ip_address.v4; + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (ip_address.nxd_ip_version == NX_IP_VERSION_V6) + { + COPY_IPV6_ADDRESS(ip_address.nxd_ip_address.v6, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6); + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* FEATURE_NX_IPV6 */ + + socket_ptr -> nx_tcp_socket_connect_port = remote_port; + + /* Find listen callback function. */ + listen_ptr = ip_ptr -> nx_ip_tcp_active_listen_requests; + if (listen_ptr) + { + do + { + if (listen_ptr -> nx_tcp_listen_port == port) + { + if (listen_ptr -> nx_tcp_listen_callback) + { + + /* Clear the server socket pointer in the listen request. If the + application wishes to honor more server connections on this port, + the application must call relisten with a new server socket + pointer. */ + listen_ptr->nx_tcp_listen_socket_ptr = NX_NULL; + + /* Call the user's listen callback function. */ + (listen_ptr ->nx_tcp_listen_callback)(socket_ptr, listen_ptr -> nx_tcp_listen_port); + break; + } + } + + /* Move to the next listen request. */ + listen_ptr = listen_ptr -> nx_tcp_listen_next; + } while (listen_ptr != ip_ptr -> nx_ip_tcp_active_listen_requests); + } + + /* Calculate the hash index in the TCP port array of the associated IP instance. */ + index = (UINT)((port + (port >> 8)) & NX_TCP_PORT_TABLE_MASK); + + /* Determine if the list is NULL. */ + if (ip_ptr -> nx_ip_tcp_port_table[index]) + { + + /* There are already sockets on this list... just add this one + to the end. */ + socket_ptr -> nx_tcp_socket_bound_next = + ip_ptr -> nx_ip_tcp_port_table[index]; + socket_ptr -> nx_tcp_socket_bound_previous = + (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous; + ((ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous) -> nx_tcp_socket_bound_next = + socket_ptr; + (ip_ptr -> nx_ip_tcp_port_table[index]) -> nx_tcp_socket_bound_previous = socket_ptr; + } + else + { + + /* Nothing is on the TCP port list. Add this TCP socket to an + empty list. */ + socket_ptr -> nx_tcp_socket_bound_next = socket_ptr; + socket_ptr -> nx_tcp_socket_bound_previous = socket_ptr; + ip_ptr -> nx_ip_tcp_port_table[index] = socket_ptr; + } + } + + /* Update socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED; + +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif + + /* Determine if we need to wake a thread suspended on the connection. */ + if (socket_ptr -> nx_tcp_socket_connect_suspended_thread) + { + + /* Resume the suspended thread. */ + _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS); + } + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_tcp_socket_driver_packet_receive.c b/common/src/nx_tcp_socket_driver_packet_receive.c new file mode 100644 index 00000000..5c800215 --- /dev/null +++ b/common/src/nx_tcp_socket_driver_packet_receive.c @@ -0,0 +1,181 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Transmission Control Protocol (TCP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "nx_tcp.h" +#include "nx_packet.h" +#include "tx_thread.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_packet_receive PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a TCP packet from the TCP/IP driver and add */ +/* fake TCP/IP header. Then pass the packet to IP deferred receive */ +/* routine. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* packet_ptr Pointer to packet to process */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +VOID _nx_tcp_socket_driver_packet_receive(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) +{ +NX_IP *ip_ptr; +NX_TCP_HEADER *header_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Obtain the IP internal mutex before processing the IP event. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + if (packet_ptr == NX_NULL) + { + + /* Connection closed. */ + if (socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED) + { + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSE_WAIT; + + /* Loop to release all threads suspended while trying to receive on the socket. */ + while (socket_ptr -> nx_tcp_socket_receive_suspension_list) + { + + /* Release the head of the receive suspension list. */ + _nx_tcp_receive_cleanup(socket_ptr -> nx_tcp_socket_receive_suspension_list NX_CLEANUP_ARGUMENT); + } + + /* If given, call the application's disconnect callback function + for disconnect. */ + if (socket_ptr -> nx_tcp_disconnect_callback) + { + + /* Call the application's disconnect handling function. It is + responsible for calling the socket disconnect function. */ + (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr); + } + } + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + + /* Fake TCP and IP header. */ + /* Prepend the TCP header to the packet. First, make room for the TCP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER); + + /* Add the length of the TCP header. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER); + + /* Pickup the pointer to the head of the TCP packet. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the output request in the TCP header. */ + header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_connect_port)) << NX_SHIFT_BY_16) | + (ULONG)socket_ptr -> nx_tcp_socket_port; + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0); + header_ptr -> nx_tcp_acknowledgment_number = 0; + header_ptr -> nx_tcp_sequence_number = 0; + header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT; + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3); + header_ptr -> nx_tcp_header_word_4 = 0; + +#ifndef NX_DISABLE_IPV4 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4, + packet_ptr -> nx_packet_ip_interface -> nx_interface_ip_address, + socket_ptr -> nx_tcp_socket_type_of_service, + socket_ptr -> nx_tcp_socket_time_to_live, + NX_IP_TCP, + socket_ptr -> nx_tcp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_TCP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6, + socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address, + NX_NULL)) + { + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + } +#endif /* FEATURE_NX_IPV6 */ + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_tcp_socket_packet_process.c b/common/src/nx_tcp_socket_packet_process.c index 085d8b47..00b7945b 100644 --- a/common/src/nx_tcp_socket_packet_process.c +++ b/common/src/nx_tcp_socket_packet_process.c @@ -28,6 +28,9 @@ #include "nx_api.h" #include "nx_tcp.h" #include "nx_packet.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ @@ -35,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_packet_process PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -71,6 +74,9 @@ /* _nx_tcp_socket_state_transmit_check Check for transmit ability */ /* (nx_tcp_urgent_data_callback) Application urgent callback */ /* function */ +/* _nx_http_proxy_client_connect_response_process */ +/* Process HTTP Proxy CONNECT */ +/* response */ /* */ /* CALLED BY */ /* */ @@ -83,6 +89,16 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed unsigned integers */ +/* comparison, */ +/* resulting in version 6.1.10 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_packet_process(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) @@ -98,6 +114,12 @@ ULONG rx_sequence; ULONG rx_window; UINT outside_of_window; ULONG mss = 0; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +ULONG tcpip_offload; + + tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); @@ -112,7 +134,11 @@ ULONG mss = 0; header_length = (tcp_header_copy.nx_tcp_header_word_3 >> NX_TCP_HEADER_SHIFT) * (ULONG)sizeof(ULONG); /* Process the segment if socket state is equal or greater than NX_TCP_SYN_RECEIVED. According to RFC 793, Section 3.9, Page 69. */ - if (socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED) + if ((socket_ptr -> nx_tcp_socket_state >= NX_TCP_SYN_RECEIVED) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Step1: Check sequence number. According to RFC 793, Section 3.9, Page 69. */ @@ -165,8 +191,8 @@ ULONG mss = 0; outside_of_window = NX_FALSE; } } - else if (((INT)packet_sequence - (INT)rx_sequence >= 0) && - ((INT)rx_sequence + (INT)rx_window - (INT)packet_sequence > 0)) + else if (((INT)(packet_sequence - rx_sequence) >= 0) && + ((INT)(rx_sequence + rx_window - packet_sequence) > 0)) { outside_of_window = NX_FALSE; } @@ -174,10 +200,10 @@ ULONG mss = 0; else { if ((rx_window > 0) && - ((((INT)packet_sequence - (INT)rx_sequence >= 0) && - ((INT)rx_sequence + (INT)rx_window - (INT)packet_sequence > 0)) || - (((INT)packet_sequence + ((INT)packet_data_length - 1) - (INT)rx_sequence >= 0) && - ((INT)rx_sequence + 1 + ((INT)rx_window - (INT)packet_sequence) - (INT)packet_data_length > 0)))) + ((((INT)(packet_sequence - rx_sequence) >= 0) && + ((INT)(rx_sequence + rx_window - packet_sequence) > 0)) || + (((INT)(packet_sequence + (packet_data_length - 1) - rx_sequence) >= 0) && + ((INT)(rx_sequence + 1 + (rx_window - packet_sequence) - packet_data_length) > 0)))) { outside_of_window = NX_FALSE; } @@ -366,12 +392,18 @@ ULONG mss = 0; /* Check for data in the current packet. */ packet_queued = _nx_tcp_socket_state_data_check(socket_ptr, packet_ptr); - /* Call the ESTABLISHED state handling function to process any state - changes caused by this new packet. */ - _nx_tcp_socket_state_established(socket_ptr); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { - /* Determine if any transmit suspension can be lifted. */ - _nx_tcp_socket_state_transmit_check(socket_ptr); + /* Call the ESTABLISHED state handling function to process any state + changes caused by this new packet. */ + _nx_tcp_socket_state_established(socket_ptr); + + /* Determine if any transmit suspension can be lifted. */ + _nx_tcp_socket_state_transmit_check(socket_ptr); + } /* State processing is complete. */ break; @@ -435,6 +467,19 @@ ULONG mss = 0; break; } +#ifdef NX_ENABLE_HTTP_PROXY + + /* Check if HTTP Proxy is started and waiting for the response form the HTTP Proxy server. */ + if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_ESTABLISHED) && + (socket_ptr -> nx_tcp_socket_ip_ptr -> nx_ip_http_proxy_enable) && + (socket_ptr -> nx_tcp_socket_http_proxy_state == NX_HTTP_PROXY_STATE_CONNECTING)) + { + + /* Receive and process the response. */ + _nx_http_proxy_client_connect_response_process(socket_ptr); + } +#endif /* NX_ENABLE_HTTP_PROXY */ + /* Check for an URG (urgent) bit set. */ /*lint -e{644} suppress variable might not be initialized, since "tcp_header_copy" was initialized. */ if (tcp_header_copy.nx_tcp_header_word_3 & NX_TCP_URG_BIT) diff --git a/common/src/nx_tcp_socket_send_internal.c b/common/src/nx_tcp_socket_send_internal.c index 4d176c6f..cbfaa6f7 100644 --- a/common/src/nx_tcp_socket_send_internal.c +++ b/common/src/nx_tcp_socket_send_internal.c @@ -38,12 +38,176 @@ #endif /* NX_IPSEC_ENABLE */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_tcp_socket_driver_send PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a TCP packet through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to socket */ +/* packet_ptr Pointer to packet to send */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_send Packet send function */ +/* _nx_ipv6_packet_send Packet send function */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_tcp_socket_send_internal */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_tcp_socket_driver_send(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option) +{ +UINT status; +NX_IP *ip_ptr; +NX_INTERFACE *interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; +#ifdef NX_ENABLE_IP_PACKET_FILTER +UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr; +ULONG original_length = packet_ptr -> nx_packet_length; +NX_TCP_HEADER *header_ptr; +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, add the TCP and IP Header to trigger filtering. */ + /* Prepend the TCP header to the packet. First, make room for the TCP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_TCP_HEADER); + + /* Add the length of the TCP header. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_TCP_HEADER); + + /* Pickup the pointer to the head of the TCP packet. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + header_ptr = (NX_TCP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the output request in the TCP header. */ + header_ptr -> nx_tcp_header_word_0 = (((ULONG)(socket_ptr -> nx_tcp_socket_port)) << NX_SHIFT_BY_16) | + (ULONG)socket_ptr -> nx_tcp_socket_connect_port; + header_ptr -> nx_tcp_acknowledgment_number = 0; + header_ptr -> nx_tcp_sequence_number = 0; + header_ptr -> nx_tcp_header_word_3 = NX_TCP_HEADER_SIZE | NX_TCP_ACK_BIT | NX_TCP_PSH_BIT; + header_ptr -> nx_tcp_header_word_4 = 0; + + /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will + swap the endian of the TCP header. */ + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_0); + NX_CHANGE_ULONG_ENDIAN(header_ptr -> nx_tcp_header_word_3); + +#ifndef NX_DISABLE_IPV4 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, + socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4, + socket_ptr -> nx_tcp_socket_type_of_service, + socket_ptr -> nx_tcp_socket_time_to_live, + NX_IP_TCP, + socket_ptr -> nx_tcp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_TCP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address, + socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6, + NX_NULL)) + { + + /* Invalid interface address. Just return success. */ + return(NX_SUCCESS); + } + } +#endif /* FEATURE_NX_IPV6 */ + + if (ip_ptr -> nx_ip_packet_filter) + { + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Reset UDP and IP header. */ + packet_ptr -> nx_packet_prepend_ptr = original_ptr; + packet_ptr -> nx_packet_length = original_length; + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Let TCP/IP offload interface send the packet. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_SOCKET_SEND, + packet_ptr, NX_NULL, NX_NULL, 0, NX_NULL, + wait_option); + + if (status) + { + return(NX_TCPIP_OFFLOAD_ERROR); + } + else + { + return(NX_SUCCESS); + } +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_send_internal PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -70,6 +234,7 @@ /* _nx_tcp_socket_thread_suspend Suspend calling thread */ /* tx_mutex_get Get protection mutex */ /* tx_mutex_put Put protection mutex */ +/* _nx_tcp_socket_driver_send TCP/IP offload send function */ /* */ /* CALLED BY */ /* */ @@ -88,6 +253,17 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed the bug of race */ +/* condition, */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* improved the throughput of */ +/* TCP transmission, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_send_internal(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, ULONG wait_option) @@ -116,6 +292,10 @@ UCHAR preempted = NX_FALSE; UCHAR adjust_packet; UINT old_threshold = 0; ULONG window_size; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +UINT status; +NX_INTERFACE *interface_ptr; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ #if defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) UINT compute_checksum = 1; #endif /* defined(NX_DISABLE_TCP_TX_CHECKSUM) || defined(NX_ENABLE_INTERFACE_CAPABILITY) || defined(NX_IPSEC_ENABLE) */ @@ -146,6 +326,14 @@ UINT compute_checksum = 1; return(NX_NOT_BOUND); } + /* Pickup the important information from the socket. */ + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Restore interrupts. */ + TX_RESTORE + /* Check if the connection is in progress. */ if ((socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_SENT) || (socket_ptr -> nx_tcp_socket_state == NX_TCP_SYN_RECEIVED)) { @@ -154,25 +342,20 @@ UINT compute_checksum = 1; _nx_tcp_socket_state_wait(socket_ptr, NX_TCP_ESTABLISHED, wait_option); } + /* Obtain the IP mutex. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + /* Check for the socket being in an established state. */ if ((socket_ptr -> nx_tcp_socket_state != NX_TCP_ESTABLISHED) && (socket_ptr -> nx_tcp_socket_state != NX_TCP_CLOSE_WAIT)) { - /* Restore interrupts. */ - TX_RESTORE + /* Release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); /* Socket is not connected, return an error message. */ return(NX_NOT_CONNECTED); } - /* Pickup the important information from the socket. */ - - /* Setup the pointer to the associated IP instance. */ - ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; - - /* Restore interrupts. */ - TX_RESTORE - /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); @@ -183,7 +366,7 @@ UINT compute_checksum = 1; /* Set the source address. */ source_ip = &socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_ip_address; - /* Set the destinatino address. */ + /* Set the destination address. */ dest_ip = &socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v4; /* The outgoing interface should have been stored in the socket structure. */ @@ -202,6 +385,9 @@ UINT compute_checksum = 1; if (socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address_state != NX_IPV6_ADDR_STATE_VALID) { + /* Release the protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + /* Add debug information. */ NX_PACKET_DEBUG(__FILE__, __LINE__, packet_ptr); @@ -210,7 +396,7 @@ UINT compute_checksum = 1; /* Set the source address. */ source_ip = socket_ptr -> nx_tcp_socket_ipv6_addr -> nxd_ipv6_address; - /* Set the destinatino address. */ + /* Set the destination address. */ dest_ip = socket_ptr -> nx_tcp_socket_connect_ip.nxd_ip_address.v6; /* The outgoing address should have been stored in the socket structure. */ @@ -221,6 +407,22 @@ UINT compute_checksum = 1; } #endif /* FEATURE_NX_IPV6 */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + + /* This interface supports TCP/IP offload. */ + status = _nx_tcp_socket_driver_send(socket_ptr, packet_ptr, wait_option); + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(status); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE /* Increase the data offset when IPsec is enabled. */ data_offset += socket_ptr -> nx_tcp_socket_egress_sa_data_offset; @@ -239,9 +441,6 @@ UINT compute_checksum = 1; for (;;) { - /* Place protection while we check the sequence number for the new TCP packet. */ - tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); - /* Pick up the min(cwnd, swnd) */ if (socket_ptr -> nx_tcp_socket_tx_window_advertised > socket_ptr -> nx_tcp_socket_tx_window_congestion) { @@ -626,6 +825,9 @@ UINT compute_checksum = 1; { _nx_packet_release(send_packet); } + + /* Regain exclusive access to IP instance. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); continue; } @@ -809,6 +1011,9 @@ UINT compute_checksum = 1; /* Release the protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + /* Regain exclusive access to IP instance. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); } } else if ((wait_option) && (_tx_thread_current_ptr != &(ip_ptr -> nx_ip_thread))) @@ -907,5 +1112,4 @@ UINT compute_checksum = 1; } } } -} - +} \ No newline at end of file diff --git a/common/src/nx_tcp_socket_state_ack_check.c b/common/src/nx_tcp_socket_state_ack_check.c index eafc92d1..2b27969a 100644 --- a/common/src/nx_tcp_socket_state_ack_check.c +++ b/common/src/nx_tcp_socket_state_ack_check.c @@ -40,7 +40,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_ack_check PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -81,11 +81,25 @@ /* corrected the calculation of*/ /* ending packet sequence, */ /* resulting in version 6.1 */ +/* 06-02-2021 Yuxin Zhou Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.7 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* fixed the bug of race */ +/* condition, removed useless */ +/* code, */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed unsigned integers */ +/* comparison, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_state_ack_check(NX_TCP_SOCKET *socket_ptr, NX_TCP_HEADER *tcp_header_ptr) { +TX_INTERRUPT_SAVE_AREA + NX_TCP_HEADER *search_header_ptr = NX_NULL; NX_PACKET *search_ptr; NX_PACKET *previous_ptr; @@ -132,6 +146,7 @@ UINT wrapped_flag = NX_FALSE; search_header_ptr = (NX_TCP_HEADER *)(search_ptr -> nx_packet_ip_header + sizeof(NX_IPV4_HEADER)); } + else #endif /* NX_DISABLE_IPV4 */ #ifdef FEATURE_NX_IPV6 if (search_ptr -> nx_packet_ip_version == NX_IP_VERSION_V6) @@ -141,7 +156,11 @@ UINT wrapped_flag = NX_FALSE; search_header_ptr = (NX_TCP_HEADER *)(search_ptr -> nx_packet_ip_header + sizeof(NX_IPV6_HEADER)); } + else #endif /* FEATURE_NX_IPV6 */ + { + return(NX_FALSE); + } /* Determine the size of the TCP header. */ temp = search_header_ptr -> nx_tcp_header_word_3; @@ -223,10 +242,6 @@ UINT wrapped_flag = NX_FALSE; if ((search_ptr) && (search_ptr -> nx_packet_queue_next == ((NX_PACKET *)NX_DRIVER_TX_DONE))) { - /* Setup a pointer to header of this packet in the sent list. */ - /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ - search_header_ptr = (NX_TCP_HEADER *)search_ptr -> nx_packet_prepend_ptr; - /* Determine if the incoming ACK matches the front of our transmit queue. */ if (tcp_header_ptr -> nx_tcp_acknowledgment_number == starting_tx_sequence) { @@ -425,7 +440,7 @@ UINT wrapped_flag = NX_FALSE; { /* If the ACK is a duplicate, it can be ignored. */ - if ((INT)tcp_header_ptr -> nx_tcp_acknowledgment_number - (INT)ending_tx_sequence > 0) + if ((INT)(tcp_header_ptr -> nx_tcp_acknowledgment_number - ending_tx_sequence) > 0) { /* The ACK sequence is invalid. Respond with an ACK to let the other @@ -475,23 +490,6 @@ UINT wrapped_flag = NX_FALSE; /* Reset the duplicated ACK counter. */ socket_ptr -> nx_tcp_socket_duplicated_ack_received = 0; - /* Determine if the packet has been transmitted. */ - /*lint -e{923} suppress cast of ULONG to pointer. */ - if (socket_ptr -> nx_tcp_socket_transmit_sent_head -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE)) - { - - /* Setup a pointer to header of this packet in the sent list. */ - search_header_ptr = (NX_TCP_HEADER *)(socket_ptr -> nx_tcp_socket_transmit_sent_head -> nx_packet_ip_header + - socket_ptr -> nx_tcp_socket_transmit_sent_head -> nx_packet_ip_header_length); - } - else - { - - /* Setup a pointer to header of this packet in the sent list. */ - /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ - search_header_ptr = (NX_TCP_HEADER *)socket_ptr -> nx_tcp_socket_transmit_sent_head -> nx_packet_prepend_ptr; - } - /* Set previous cumulative acknowlesgement. */ socket_ptr -> nx_tcp_socket_previous_highest_ack = starting_tx_sequence; @@ -555,11 +553,11 @@ UINT wrapped_flag = NX_FALSE; * 2. SND.WL1 < SEG.SEQ or * 3. SND.WL1 = SEG.SEQ and SND.WL2 =< SEG.ACK * RFC793, Section 3.9, Page72. */ - if ((((INT)tcp_header_ptr -> nx_tcp_acknowledgment_number - (INT)starting_tx_sequence > 0) && - ((INT)tcp_header_ptr -> nx_tcp_acknowledgment_number - (INT)ending_tx_sequence <= 0)) || - ((INT)tcp_header_ptr -> nx_tcp_sequence_number - (INT)ending_rx_sequence > 0) || - (((INT)tcp_header_ptr -> nx_tcp_sequence_number == (INT)ending_rx_sequence) && - ((INT)tcp_header_ptr -> nx_tcp_acknowledgment_number - (INT)starting_tx_sequence >= 0))) + if ((((INT)(tcp_header_ptr -> nx_tcp_acknowledgment_number - starting_tx_sequence) > 0) && + ((INT)(tcp_header_ptr -> nx_tcp_acknowledgment_number - ending_tx_sequence) <= 0)) || + ((INT)(tcp_header_ptr -> nx_tcp_sequence_number - ending_rx_sequence) > 0) || + (((INT)(tcp_header_ptr -> nx_tcp_sequence_number == ending_rx_sequence)) && + ((INT)(tcp_header_ptr -> nx_tcp_acknowledgment_number - starting_tx_sequence) >= 0))) { /* Update this socket's transmit window with the advertised window size in the ACK message. */ @@ -665,6 +663,9 @@ UINT wrapped_flag = NX_FALSE; next pointer. */ search_ptr = search_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next; + /* Disable interrupts temporarily. */ + TX_DISABLE + /* Set the packet to allocated to indicate it is no longer part of the TCP queue. */ /*lint -e{923} suppress cast of ULONG to pointer. */ previous_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next = ((NX_PACKET *)NX_PACKET_ALLOCATED); @@ -678,6 +679,9 @@ UINT wrapped_flag = NX_FALSE; if (previous_ptr -> nx_packet_queue_next == ((NX_PACKET *)NX_DRIVER_TX_DONE)) { + /* Restore interrupts. */ + TX_RESTORE + /* Yes, the driver has already released the packet. */ /* Open up the transmit window. */ @@ -722,8 +726,8 @@ UINT wrapped_flag = NX_FALSE; socket_ptr -> nx_tcp_socket_tx_outstanding_bytes = 0; } - /* Let driver release the packet. */ - previous_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next = ((NX_PACKET *)NX_PACKET_ALLOCATED); + /* Restore interrupts. */ + TX_RESTORE } } diff --git a/common/src/nx_tcp_socket_state_data_check.c b/common/src/nx_tcp_socket_state_data_check.c index 1f6475d1..e23023d0 100644 --- a/common/src/nx_tcp_socket_state_data_check.c +++ b/common/src/nx_tcp_socket_state_data_check.c @@ -27,6 +27,9 @@ #include "nx_packet.h" #include "nx_ip.h" #include "nx_tcp.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ @@ -34,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_data_trim PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -69,6 +72,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_state_data_trim(NX_PACKET *packet_ptr, ULONG amount) @@ -276,7 +282,7 @@ ULONG work_length; /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_data_check PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -317,6 +323,16 @@ ULONG work_length; /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* fixed unsigned integers */ +/* comparison, */ +/* resulting in version 6.1.10 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_state_data_check(NX_TCP_SOCKET *socket_ptr, NX_PACKET *packet_ptr) @@ -339,6 +355,9 @@ ULONG trim_data_length; TX_THREAD *thread_ptr; ULONG acked_packets = 0; UINT need_ack = NX_FALSE; +#ifdef NX_ENABLE_TCPIP_OFFLOAD +ULONG tcpip_offload; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ #ifdef NX_ENABLE_LOW_WATERMARK UCHAR drop_packet = NX_FALSE; #endif /* NX_ENABLE_LOW_WATERMARK */ @@ -349,6 +368,10 @@ NX_IP *ip_ptr; ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; #endif +#ifdef NX_ENABLE_TCPIP_OFFLOAD + tcpip_offload = socket_ptr -> nx_tcp_socket_connect_interface -> nx_interface_capability_flag & + NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ /* Pickup the pointer to the head of the TCP packet. */ /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ @@ -370,11 +393,15 @@ NX_IP *ip_ptr; packet_end_sequence = tcp_header_ptr -> nx_tcp_sequence_number + packet_data_length; /* Trim the data that out of the receive window, make sure all data are in receive window. */ - if (packet_data_length) + if (packet_data_length +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Step1. trim the data on the left side of the receive window. */ - if (((INT)socket_ptr -> nx_tcp_socket_rx_sequence - (INT)packet_begin_sequence) > 0) + if (((INT)(socket_ptr -> nx_tcp_socket_rx_sequence - packet_begin_sequence)) > 0) { /* Calculate the data length that out of window. */ @@ -392,8 +419,8 @@ NX_IP *ip_ptr; } /* Step2. trim the data on the right side of the receive window. */ - if ((((INT)packet_end_sequence - (INT)socket_ptr -> nx_tcp_socket_rx_sequence) - - (INT)socket_ptr -> nx_tcp_socket_rx_window_current) > 0) + if (((INT)((packet_end_sequence - socket_ptr -> nx_tcp_socket_rx_sequence) - + socket_ptr -> nx_tcp_socket_rx_window_current)) > 0) { /* Calculate the data length that out of window. */ @@ -480,13 +507,17 @@ NX_IP *ip_ptr; search_end_sequence = socket_ptr -> nx_tcp_socket_rx_sequence; } -#ifdef NX_ENABLE_LOW_WATERMARK /* Does the number of queued packets exceed the maximum rx queue length, or the number of * available packets in the default packet pool reaches low watermark? */ - if ((socket_ptr -> nx_tcp_socket_receive_queue_count >= - socket_ptr -> nx_tcp_socket_receive_queue_maximum) || - (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available < - packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark)) +#ifdef NX_ENABLE_LOW_WATERMARK + if (((socket_ptr -> nx_tcp_socket_receive_queue_count >= + socket_ptr -> nx_tcp_socket_receive_queue_maximum) || + (packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_available < + packet_ptr -> nx_packet_pool_owner -> nx_packet_pool_low_watermark)) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + && (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Yes it is. The last packet in queue should be dropped. */ @@ -497,8 +528,12 @@ NX_IP *ip_ptr; /* Determine if we have a simple case of TCP data coming in the correct order. This means the socket's sequence number matches the incoming packet sequence number and the last packet's data on the socket's receive queue (if any) matches the current sequence number. */ - if ((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) && - (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence)) + if (((tcp_header_ptr -> nx_tcp_sequence_number == socket_ptr -> nx_tcp_socket_rx_sequence) && + (search_end_sequence == socket_ptr -> nx_tcp_socket_rx_sequence)) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + || tcpip_offload +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { /* Yes, this is the simple case of adding receive packets in sequence. */ @@ -534,7 +569,12 @@ NX_IP *ip_ptr; socket_ptr -> nx_tcp_socket_receive_queue_tail = packet_ptr; /* Setup a new delayed ACK timeout. */ - socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate; +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (!tcpip_offload) +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { + socket_ptr -> nx_tcp_socket_delayed_ack_timeout = _nx_tcp_ack_timer_rate; + } } /* Increment the receive TCP packet count. */ @@ -631,7 +671,7 @@ NX_IP *ip_ptr; packet_begin_sequence is to the right of the end of it. */ /* Packet data begins to the right of the expected sequence (out of sequence data). Force an ACK. */ - if (((INT)packet_begin_sequence - (INT)socket_ptr -> nx_tcp_socket_rx_sequence) > 0) + if (((INT)(packet_begin_sequence - socket_ptr -> nx_tcp_socket_rx_sequence)) > 0) { _nx_tcp_packet_send_ack(socket_ptr, socket_ptr -> nx_tcp_socket_tx_sequence); } @@ -1059,8 +1099,12 @@ NX_IP *ip_ptr; /* At this point, we can use the packet TCP header pointers since the received packet is already queued. */ - /* Any packets for receving? */ - while (acked_packets && socket_ptr -> nx_tcp_socket_receive_suspension_list) + /* Any packets for receiving? */ + while (acked_packets && socket_ptr -> nx_tcp_socket_receive_suspension_list +#ifdef NX_ENABLE_HTTP_PROXY + && (socket_ptr -> nx_tcp_socket_http_proxy_state != NX_HTTP_PROXY_STATE_CONNECTING) +#endif /* NX_ENABLE_HTTP_PROXY */ + ) { /* Setup a pointer to the first queued packet. */ @@ -1134,15 +1178,28 @@ NX_IP *ip_ptr; /* If the incoming packet caused the sequence number to move forward, indicating the new piece of data is in order, in sequence, and valid for receiving. */ - if (original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence) + if ((original_rx_sequence != socket_ptr -> nx_tcp_socket_rx_sequence) +#ifdef NX_ENABLE_TCPIP_OFFLOAD + || tcpip_offload +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + ) { - /* Determine if there is a socket receive notification function specified. */ - if (socket_ptr -> nx_tcp_receive_callback) + +#ifdef NX_ENABLE_HTTP_PROXY + + /* If HTTP Proxy is connecting, the data is the response from HTTP Proxy server, don't need to notify application. */ + if (socket_ptr -> nx_tcp_socket_http_proxy_state != NX_HTTP_PROXY_STATE_CONNECTING) +#endif /* NX_ENABLE_HTTP_PROXY */ { - /* Yes, notification is requested. Call the application's receive notification - function for this socket. */ - (socket_ptr -> nx_tcp_receive_callback)(socket_ptr); + /* Determine if there is a socket receive notification function specified. */ + if (socket_ptr -> nx_tcp_receive_callback) + { + + /* Yes, notification is requested. Call the application's receive notification + function for this socket. */ + (socket_ptr -> nx_tcp_receive_callback)(socket_ptr); + } } #ifdef NX_TCP_ACK_EVERY_N_PACKETS diff --git a/common/src/nx_tcp_socket_state_established.c b/common/src/nx_tcp_socket_state_established.c index 4cae6a85..082dee63 100644 --- a/common/src/nx_tcp_socket_state_established.c +++ b/common/src/nx_tcp_socket_state_established.c @@ -28,6 +28,9 @@ #include "nx_api.h" #include "nx_ip.h" #include "nx_tcp.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ @@ -35,7 +38,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_established PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +77,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_state_established(NX_TCP_SOCKET *socket_ptr) @@ -127,14 +133,28 @@ NX_IP *ip_ptr; /* Send ACK message. */ _nx_tcp_packet_send_ack(socket_ptr, socket_ptr -> nx_tcp_socket_tx_sequence); - /* If given, call the application's disconnect callback function - for disconnect. */ - if (socket_ptr -> nx_tcp_disconnect_callback) +#ifdef NX_ENABLE_HTTP_PROXY + if ((ip_ptr -> nx_ip_http_proxy_enable) && + (socket_ptr -> nx_tcp_socket_http_proxy_state == NX_HTTP_PROXY_STATE_CONNECTING)) { - /* Call the application's disconnect handling function. It is - responsible for calling the socket disconnect function. */ - (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr); + /* If received FIN before HTTP Proxy connection established, disconnect the TCP connection + and don't notify the application. */ + _nx_tcp_socket_disconnect(socket_ptr, NX_NO_WAIT); + } + else +#endif /* NX_ENABLE_HTTP_PROXY */ + { + + /* If given, call the application's disconnect callback function + for disconnect. */ + if (socket_ptr -> nx_tcp_disconnect_callback) + { + + /* Call the application's disconnect handling function. It is + responsible for calling the socket disconnect function. */ + (socket_ptr -> nx_tcp_disconnect_callback)(socket_ptr); + } } } } diff --git a/common/src/nx_tcp_socket_state_syn_sent.c b/common/src/nx_tcp_socket_state_syn_sent.c index 2ff220f0..97426200 100644 --- a/common/src/nx_tcp_socket_state_syn_sent.c +++ b/common/src/nx_tcp_socket_state_syn_sent.c @@ -27,6 +27,9 @@ #include "nx_api.h" #include "nx_tcp.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ @@ -34,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_syn_sent PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -62,6 +65,7 @@ /* _nx_tcp_packet_send_syn Send SYN packet */ /* _nx_tcp_packet_send_rst Send RST packet */ /* _nx_tcp_socket_thread_resume Resume suspended thread */ +/* _nx_http_proxy_client_connect Connect with HTTP Proxy */ /* */ /* CALLED BY */ /* */ @@ -74,6 +78,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ VOID _nx_tcp_socket_state_syn_sent(NX_TCP_SOCKET *socket_ptr, NX_TCP_HEADER *tcp_header_ptr, NX_PACKET *packet_ptr) @@ -185,17 +192,6 @@ VOID _nx_tcp_socket_state_syn_sent(NX_TCP_SOCKET *socket_ptr, NX_TCP_HEADER *tc /* Clear the socket timeout. */ socket_ptr -> nx_tcp_socket_timeout = 0; -#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT - - /* Is a connection completion callback registered with the TCP socket? */ - if (socket_ptr -> nx_tcp_establish_notify) - { - - /* Call the application's establish callback function. */ - (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); - } -#endif - #ifdef NX_ENABLE_TCP_KEEPALIVE /* Is the keepalive feature enabled on this socket? */ if (socket_ptr -> nx_tcp_socket_keepalive_enabled) @@ -206,12 +202,37 @@ VOID _nx_tcp_socket_state_syn_sent(NX_TCP_SOCKET *socket_ptr, NX_TCP_HEADER *tc } #endif - /* Determine if we need to wake a thread suspended on the connection. */ - if (socket_ptr -> nx_tcp_socket_connect_suspended_thread) +#ifdef NX_ENABLE_HTTP_PROXY + + /* Check if the HTTP Proxy is started and waiting for TCP socket connection. */ + if ((socket_ptr -> nx_tcp_socket_ip_ptr -> nx_ip_http_proxy_enable) && + (socket_ptr -> nx_tcp_socket_http_proxy_state == NX_HTTP_PROXY_STATE_WAITING)) { - /* Resume the suspended thread. */ - _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS); + /* TCP connection established, start the HTTP Proxy connection. */ + _nx_http_proxy_client_connect(socket_ptr); + } + else +#endif /* NX_ENABLE_HTTP_PROXY */ + { +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif + + /* Determine if we need to wake a thread suspended on the connection. */ + if (socket_ptr -> nx_tcp_socket_connect_suspended_thread) + { + + /* Resume the suspended thread. */ + _nx_tcp_socket_thread_resume(&(socket_ptr -> nx_tcp_socket_connect_suspended_thread), NX_SUCCESS); + } } } else if ((tcp_header_ptr -> nx_tcp_header_word_3 & NX_TCP_SYN_BIT) && diff --git a/common/src/nx_tcp_socket_state_wait.c b/common/src/nx_tcp_socket_state_wait.c index e52bc6e3..63f534ed 100644 --- a/common/src/nx_tcp_socket_state_wait.c +++ b/common/src/nx_tcp_socket_state_wait.c @@ -27,6 +27,9 @@ #include "nx_api.h" #include "nx_tcp.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ /**************************************************************************/ @@ -34,7 +37,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_tcp_socket_state_wait PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -69,6 +72,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_tcp_socket_state_wait(NX_TCP_SOCKET *socket_ptr, UINT desired_state, ULONG wait_option) @@ -93,8 +99,16 @@ UINT _nx_tcp_socket_state_wait(NX_TCP_SOCKET *socket_ptr, UINT desired_state, U if (socket_ptr -> nx_tcp_socket_state == desired_state) { - /* The desired state is present, return success! */ - return(NX_SUCCESS); +#ifdef NX_ENABLE_HTTP_PROXY + if ((desired_state != NX_TCP_ESTABLISHED) || + (!socket_ptr -> nx_tcp_socket_ip_ptr -> nx_ip_http_proxy_enable) || + (!socket_ptr -> nx_tcp_socket_client_type) || + (socket_ptr -> nx_tcp_socket_http_proxy_state == NX_HTTP_PROXY_STATE_CONNECTED)) +#endif /* NX_ENABLE_HTTP_PROXY */ + { + /* The desired state is present, return success! */ + return(NX_SUCCESS); + } } /* Check to see if there is more time to wait. */ diff --git a/common/src/nx_udp_socket_bind.c b/common/src/nx_udp_socket_bind.c index 6917a2a6..f8699660 100644 --- a/common/src/nx_udp_socket_bind.c +++ b/common/src/nx_udp_socket_bind.c @@ -30,12 +30,117 @@ #include "tx_thread.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_bind PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function binds to a UDP port through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* port 16-bit UDP port number */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_udp_socket_unbind Unbind UDP port */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_udp_socket_bind */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option) +{ +UINT status = NX_SUCCESS; +UINT i; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Obtain the IP mutex. */ + tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); + + /* Loop all interfaces to bind to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if ((interface_ptr -> nx_interface_valid == NX_FALSE) || + (interface_ptr -> nx_interface_link_up == NX_FALSE)) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface bind to port. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, + socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_BIND, + NX_NULL, NX_NULL, NX_NULL, port, + NX_NULL, wait_option); + if (status) + { + + /* At least one of the interface fails to bind to port. */ + _nx_udp_socket_unbind(socket_ptr); + status = NX_TCPIP_OFFLOAD_ERROR; + break; + } + } + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + return(status); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_udp_socket_bind PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -75,6 +180,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* corrected the random value, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_udp_socket_bind(NX_UDP_SOCKET *socket_ptr, UINT port, ULONG wait_option) @@ -89,6 +200,7 @@ NX_IP *ip_ptr; TX_THREAD *thread_ptr; NX_UDP_SOCKET *search_ptr; NX_UDP_SOCKET *end_ptr; +UINT status = NX_SUCCESS; /* Setup the pointer to the associated IP instance. */ @@ -119,7 +231,7 @@ NX_UDP_SOCKET *end_ptr; { /* Call the find routine to allocate a UDP port. */ - port = NX_SEARCH_PORT_START + (UINT)(NX_RAND() % ((NX_MAX_PORT + 1) - NX_SEARCH_PORT_START)); + port = NX_SEARCH_PORT_START + (UINT)(((ULONG)NX_RAND()) % ((NX_MAX_PORT + 1) - NX_SEARCH_PORT_START)); if (_nx_udp_free_port_find(ip_ptr, port, &port) != NX_SUCCESS) { @@ -222,9 +334,6 @@ NX_UDP_SOCKET *end_ptr; /* Release the mutex protection. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); - - /* Return success to the caller. */ - return(NX_SUCCESS); } else if (wait_option) { @@ -296,7 +405,7 @@ NX_UDP_SOCKET *end_ptr; _tx_thread_system_suspend(thread_ptr); /* Return the completion status. */ - return(thread_ptr -> tx_thread_suspend_status); + status = thread_ptr -> tx_thread_suspend_status; } else { @@ -305,7 +414,19 @@ NX_UDP_SOCKET *end_ptr; tx_mutex_put(&(ip_ptr -> nx_ip_protection)); /* Return the port unavailable error. */ - return(NX_PORT_UNAVAILABLE); + status = NX_PORT_UNAVAILABLE; + } + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if (status == NX_SUCCESS) + { + + /* Bind to TCP/IP offload interface. */ + status = _nx_udp_socket_driver_bind(socket_ptr, port, wait_option); } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /* Return success to the caller. */ + return(status); } diff --git a/common/src/nx_udp_socket_driver_packet_receive.c b/common/src/nx_udp_socket_driver_packet_receive.c new file mode 100644 index 00000000..cfc9897f --- /dev/null +++ b/common/src/nx_udp_socket_driver_packet_receive.c @@ -0,0 +1,158 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** User Datagram Protocol (UDP) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "nx_api.h" +#include "tx_thread.h" +#include "nx_udp.h" +#include "nx_packet.h" +#include "nx_ip.h" +#ifdef FEATURE_NX_IPV6 +#include "nx_ipv6.h" +#endif /* FEATURE_NX_IPV6 */ + + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_packet_receive PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function receives a UDP packet from the TCP/IP driver and add */ +/* fake TCP/IP header. Then pass the packet to IP deferred receive */ +/* routine. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to owning socket */ +/* packet_ptr Pointer to packet to process */ +/* local_ip Pointer to local IP address */ +/* remote_ip Pointer to remote IP address */ +/* remote_port Pointer to remote UDP port */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection mutex */ +/* tx_mutex_put Release protection mutex */ +/* _nx_ip_packet_deferred_receive Defer IP packet receive */ +/* */ +/* CALLED BY */ +/* */ +/* Driver */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +VOID _nx_udp_socket_driver_packet_receive(NX_UDP_SOCKET *socket_ptr, NX_PACKET *packet_ptr, + NXD_ADDRESS *local_ip, NXD_ADDRESS *remote_ip, UINT remote_port) +{ + +NX_IP *ip_ptr; +NX_UDP_HEADER *udp_header_ptr; + + /* Setup the IP pointer. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + if (packet_ptr == NX_NULL) + { + + /* Socket error. Just ignore. */ + return; + } + + /* Fake UDP and IP header. */ + /* Prepend the UDP header to the packet. First, make room for the UDP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER); + + /* Increase the packet length. */ + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length + (ULONG)sizeof(NX_UDP_HEADER); + + /* Setup the UDP header pointer. */ + /*lint -e{927} -e{826} suppress cast of pointer to pointer, since it is necessary */ + udp_header_ptr = (NX_UDP_HEADER *)packet_ptr -> nx_packet_prepend_ptr; + + /* Build the first 32-bit word of the UDP header. */ + udp_header_ptr -> nx_udp_header_word_0 = + ((ULONG)remote_port << NX_SHIFT_BY_16) | (ULONG)socket_ptr -> nx_udp_socket_port; + + /* Build the second 32-bit word of the UDP header. */ + udp_header_ptr -> nx_udp_header_word_1 = (packet_ptr -> nx_packet_length << NX_SHIFT_BY_16); + + /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will + swap the endian of the UDP header. */ + NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0); + NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1); + +#ifndef NX_DISABLE_IPV4 + if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, remote_ip -> nxd_ip_address.v4, + local_ip -> nxd_ip_address.v4, + socket_ptr -> nx_udp_socket_type_of_service, + socket_ptr -> nx_udp_socket_time_to_live, + NX_IP_UDP, + socket_ptr -> nx_udp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (remote_ip -> nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, + NX_PROTOCOL_UDP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + remote_ip -> nxd_ip_address.v6, + local_ip -> nxd_ip_address.v6, + NX_NULL)) + { + + /* Release the IP internal mutex. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return; + } + } +#endif /* FEATURE_NX_IPV6 */ + + _nx_ip_packet_deferred_receive(ip_ptr, packet_ptr); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + diff --git a/common/src/nx_udp_socket_unbind.c b/common/src/nx_udp_socket_unbind.c index 145e2743..05953d1e 100644 --- a/common/src/nx_udp_socket_unbind.c +++ b/common/src/nx_udp_socket_unbind.c @@ -31,12 +31,98 @@ #include "tx_thread.h" +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_unbind PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function unbinds a UDP port through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_udp_socket_bind */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_unbind(NX_UDP_SOCKET *socket_ptr) +{ +UINT i; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Loop all interfaces to unbind to ones support TCP/IP offload. */ + for (i = 0; i < NX_MAX_IP_INTERFACES; i++) + { + + /* Use a local variable for convenience. */ + interface_ptr = &(ip_ptr -> nx_ip_interface[i]); + + /* Check for valid interfaces. */ + if (interface_ptr -> nx_interface_valid == NX_FALSE) + { + + /* Skip interface not valid. */ + continue; + } + + /* Check for TCP/IP offload feature. */ + if (((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) == 0) || + (interface_ptr -> nx_interface_tcpip_offload_handler == NX_NULL)) + { + + /* Skip interface not support TCP/IP offload. */ + continue; + } + + /* Let TCP/IP offload interface unbind port. Return value is ignored. */ + interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, + socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_UNBIND, + NX_NULL, NX_NULL, NX_NULL, + socket_ptr -> nx_udp_socket_port, + NX_NULL, NX_NO_WAIT); + } + + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_udp_socket_unbind PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -74,6 +160,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_udp_socket_unbind(NX_UDP_SOCKET *socket_ptr) @@ -138,6 +227,10 @@ NX_PACKET *next_packet_ptr; /* Calculate the hash index in the UDP port array of the associated IP instance. */ index = (UINT)((port + (port >> 8)) & NX_UDP_PORT_TABLE_MASK); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + _nx_udp_socket_driver_unbind(socket_ptr); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /* Disable interrupts while we unlink the current socket. */ TX_DISABLE diff --git a/common/src/nx_utility.c b/common/src/nx_utility.c index eb2aac31..00e76dab 100644 --- a/common/src/nx_utility.c +++ b/common/src/nx_utility.c @@ -28,6 +28,8 @@ #include "tx_api.h" #include "nx_api.h" +/* Define the base64 letters. */ +static CHAR _nx_utility_base64_array[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; /**************************************************************************/ /* */ @@ -107,3 +109,537 @@ UINT i; return(NX_SUCCESS); } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_utility_string_to_uint PORTABLE C */ +/* 6.1.3 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts the string to unsigned integer. */ +/* */ +/* INPUT */ +/* */ +/* input_string Pointer to input string */ +/* string_length Length of input string */ +/* number Pointer to the number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_string_to_uint(CHAR *input_string, UINT string_length, UINT *number) +{ + +UINT i; + + + /* Check for invalid input pointers. */ + if ((input_string == NX_NULL) || (number == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Check string length. */ + if (string_length == 0) + { + return(NX_SIZE_ERROR); + } + + /* Initialize. */ + i = 0; + *number = 0; + + /* Traverse the string. */ + while (i < string_length) + { + + /* Is a numeric character present? */ + if ((input_string[i] >= '0') && (input_string[i] <= '9')) + { + + /* Check overflow. Max Value: Hex:0xFFFFFFFF, Decimal: 4294967295. */ + if (((*number == 429496729) && (input_string[i] > '5')) || + (*number >= 429496730)) + { + return(NX_OVERFLOW); + } + + /* Yes, numeric character is present. Update the number. */ + *number = (*number * 10) + (UINT) (input_string[i] - '0'); + } + else + { + return(NX_INVALID_PARAMETERS); + } + + i++; + } + + /* Return success. */ + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_utility_uint_to_string PORTABLE C */ +/* 6.1.9 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function converts the unsigned integer to string. */ +/* */ +/* INPUT */ +/* */ +/* number Input number */ +/* base Base of the conversion */ +/* 8 for OCT */ +/* 10 for DEC */ +/* 16 for HEX */ +/* string_buffer Pointer to string buffer */ +/* string_buffer_size Size of string buffer */ +/* */ +/* OUTPUT */ +/* */ +/* size The size of output string */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* checked invalid input value,*/ +/* resulting in version 6.1.9 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_uint_to_string(UINT number, UINT base, CHAR *string_buffer, UINT string_buffer_size) +{ +UINT i; +UINT digit; +UINT size; + + /* Check for invalid input pointers. */ + if ((string_buffer == NX_NULL) || (string_buffer_size == 0) || (base == 0)) + { + return(0); + } + + /* Initialize. */ + i = 0; + size = 0; + + /* Loop to convert the number to ASCII. Minus 1 to put NULL terminal. */ + while (size < string_buffer_size - 1) + { + + /* Shift the current digits over one. */ + for (i = size; i != 0; i--) + { + + /* Move each digit over one place. */ + string_buffer[i] = string_buffer[i-1]; + } + + /* Compute the next decimal digit. */ + digit = number % base; + + /* Update the input number. */ + number = number / base; + + /* Store the new digit in ASCII form. */ + if (digit < 10) + { + string_buffer[0] = (CHAR) (digit + '0'); + } + else + { + string_buffer[0] = (CHAR) (digit + 'a' - 0xa); + } + + /* Increment the size. */ + size++; + + /* Determine if the number is now zero. */ + if (number == 0) + break; + } + + /* Determine if there is an overflow error. */ + if (number) + { + + /* Error, return bad values to user. */ + size = 0; + } + + /* Make the string NULL terminated. */ + string_buffer[size] = (CHAR) NX_NULL; + + /* Return size to caller. */ + return(size); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_utility_base64_encode PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function encodes the input string into a base64 */ +/* representation. */ +/* */ +/* INPUT */ +/* */ +/* name Name string */ +/* name_size Size of name */ +/* base64name Encoded base64 name string */ +/* base64name_size Size of encoded base64 name */ +/* bytes_copied Number of bytes copied */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-02-2021 Yuxin Zhou Initial Version 6.1.6 */ +/* 10-31-2022 Yuxin Zhou Modified comment(s), */ +/* improved the internal logic,*/ +/* resulting in version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_base64_encode(UCHAR *name, UINT name_size, UCHAR *base64name, UINT base64name_size, UINT *bytes_copied) +{ +UINT pad; +UINT i, j; +UINT step; +UINT input_name_size = name_size; + + + /* Check for invalid input pointers. */ + if ((name == NX_NULL) || (base64name == NX_NULL) || (bytes_copied == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Check the size. */ + if ((name_size == 0) || (base64name_size == 0)) + { + return(NX_SIZE_ERROR); + } + + /* Adjust the length to represent the base64 name. */ + name_size = ((name_size * 8) / 6); + + /* Default padding to none. */ + pad = 0; + + /* Determine if an extra conversion is needed. */ + if ((name_size * 6) % 24) + { + + /* Some padding is needed. */ + + /* Calculate the number of pad characters. */ + pad = (name_size * 6) % 24; + pad = (24 - pad) / 6; + pad = pad - 1; + + /* Adjust the length to pickup the character fraction. */ + name_size++; + } + + /* Check the buffer size. */ + if (base64name_size <= (name_size + pad)) + { + return(NX_SIZE_ERROR); + } + + /* Setup index into the base64name. */ + j = 0; + + /* Compute the base64name. */ + step = 0; + i = 0; + while (j < name_size) + { + + /* Determine which step we are in. */ + if (step == 0) + { + + /* Use first 6 bits of name character for index. */ + base64name[j++] = (UCHAR)_nx_utility_base64_array[((UCHAR)name[i]) >> 2]; + step++; + } + else if (step == 1) + { + + /* Use last 2 bits of name character and first 4 bits of next name character for index. */ + if ((i + 1) < input_name_size) + { + base64name[j++] = (UCHAR)_nx_utility_base64_array[((((UCHAR)name[i]) & 0x3) << 4) | (((UCHAR)name[i + 1]) >> 4)]; + } + else + { + + /* If no more name character, pad with zero. */ + base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0x3) << 4]; + } + i++; + step++; + } + else if (step == 2) + { + + /* Use last 4 bits of name character and first 2 bits of next name character for index. */ + if ((i + 1) < input_name_size) + { + base64name[j++] = (UCHAR)_nx_utility_base64_array[((((UCHAR)name[i]) & 0xF) << 2) | (((UCHAR)name[i + 1]) >> 6)]; + } + else + { + + /* If no more name character, pad with zero. */ + base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0xF) << 2]; + } + i++; + step++; + } + else /* Step 3 */ + { + + /* Use last 6 bits of name character for index. */ + base64name[j++] = (UCHAR)_nx_utility_base64_array[(((UCHAR)name[i]) & 0x3F)]; + i++; + step = 0; + } + } + + /* Now add the PAD characters. */ + while (pad--) + { + + /* Pad base64name with '=' characters. */ + base64name[j++] = '='; + } + + /* Put a NULL character in. */ + base64name[j] = NX_NULL; + *bytes_copied = j; + + return(NX_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_utility_base64_decode PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function decodes the input base64 ASCII string and converts */ +/* it into a standard ASCII representation. */ +/* */ +/* INPUT */ +/* */ +/* base64name Encoded base64 name string */ +/* base64name_size Size of encoded base64 name */ +/* name Name string */ +/* name_size Size of name */ +/* bytes_copied Number of bytes copied */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-02-2021 Yuxin Zhou Initial Version 6.1.6 */ +/* 10-15-2021 Yuxin Zhou Modified comment(s), */ +/* removed useless condition, */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), */ +/* fixed the issue of reading */ +/* overflow, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +UINT _nx_utility_base64_decode(UCHAR *base64name, UINT base64name_size, UCHAR *name, UINT name_size, UINT *bytes_copied) +{ +UINT i, j; +UINT value1, value2; +UINT step; +UINT source_size = base64name_size; + + /* Check for invalid input pointers. */ + if ((base64name == NX_NULL) || (name == NX_NULL) || (bytes_copied == NX_NULL)) + { + return(NX_PTR_ERROR); + } + + /* Check the size. */ + if ((base64name_size == 0) || (name_size == 0)) + { + return(NX_SIZE_ERROR); + } + + /* Adjust the length to represent the ASCII name. */ + base64name_size = ((base64name_size * 6) / 8); + + if ((base64name_size) && (base64name[source_size - 1] == '=')) + { + base64name_size--; + + if ((base64name_size) && (base64name[source_size - 2] == '=')) + { + base64name_size--; + } + } + + /* Check the buffer size. */ + if (name_size <= base64name_size) + { + return(NX_SIZE_ERROR); + } + + /* Setup index into the ASCII name. */ + j = 0; + + /* Compute the ASCII name. */ + step = 0; + i = 0; + while ((j < base64name_size) && (base64name[i]) && (base64name[i] != '=')) + { + + /* Derive values of the Base64 name. */ + if ((base64name[i] >= 'A') && (base64name[i] <= 'Z')) + value1 = (UINT) (base64name[i] - 'A'); + else if ((base64name[i] >= 'a') && (base64name[i] <= 'z')) + value1 = (UINT) (base64name[i] - 'a') + 26; + else if ((base64name[i] >= '0') && (base64name[i] <= '9')) + value1 = (UINT) (base64name[i] - '0') + 52; + else if ((base64name[i] == '+') || + (base64name[i] == '-')) /* Base64 URL. */ + value1 = 62; + else if ((base64name[i] == '/') || + (base64name[i] == '_')) /* Base64 URL. */ + value1 = 63; + else + value1 = 0; + + /* Derive value for the next character. */ + if ((base64name[i + 1] >= 'A') && (base64name[i + 1] <= 'Z')) + value2 = (UINT) (base64name[i+1] - 'A'); + else if ((base64name[i + 1] >= 'a') && (base64name[i + 1] <= 'z')) + value2 = (UINT) (base64name[i+1] - 'a') + 26; + else if ((base64name[i + 1] >= '0') && (base64name[i + 1] <= '9')) + value2 = (UINT) (base64name[i+1] - '0') + 52; + else if ((base64name[i + 1] == '+') || + (base64name[i + 1] == '-')) /* Base64 URL. */ + value2 = 62; + else if ((base64name[i + 1] == '/') || + (base64name[i + 1] == '_')) /* Base64 URL. */ + value2 = 63; + else + value2 = 0; + + /* Determine which step we are in. */ + if (step == 0) + { + + /* Use first value and first 2 bits of second value. */ + name[j++] = (UCHAR) (((value1 & 0x3f) << 2) | ((value2 >> 4) & 3)); + i++; + step++; + } + else if (step == 1) + { + + /* Use last 4 bits of first value and first 4 bits of next value. */ + name[j++] = (UCHAR) (((value1 & 0xF) << 4) | (value2 >> 2)); + i++; + step++; + } + else + { + + /* Use first 2 bits and following 6 bits of next value. */ + name[j++] = (UCHAR) (((value1 & 3) << 6) | (value2 & 0x3f)); + i++; + i++; + step = 0; + } + } + + /* Put a NULL character in. */ + name[j] = NX_NULL; + *bytes_copied = j; + + return(NX_SUCCESS); +} \ No newline at end of file diff --git a/common/src/nxd_ipv6_address_set.c b/common/src/nxd_ipv6_address_set.c index 72629225..f8d796b7 100644 --- a/common/src/nxd_ipv6_address_set.c +++ b/common/src/nxd_ipv6_address_set.c @@ -34,7 +34,7 @@ /* FUNCTION RELEASE */ /* */ /* _nxd_ipv6_address_set PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -83,6 +83,10 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added internal ip address */ +/* change notification, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nxd_ipv6_address_set(NX_IP *ip_ptr, UINT interface_index, NXD_ADDRESS *ip_address, ULONG prefix_length, UINT *address_index) @@ -92,6 +96,7 @@ UINT _nxd_ipv6_address_set(NX_IP *ip_ptr, UINT interface_index, NXD_ADDRESS *ip TX_INTERRUPT_SAVE_AREA #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY VOID (*address_change_notify)(NX_IP *, UINT, UINT, UINT, ULONG *); +VOID (*address_change_notify_internal)(NX_IP *, UINT, UINT, UINT, ULONG *); #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ NXD_IPV6_ADDRESS *ipv6_addr; NXD_IPV6_ADDRESS *interface_ipv6_address; @@ -292,6 +297,7 @@ ULONG multicast_address[4]; #ifdef NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY /* Pickup the current notification callback and additional information pointers. */ address_change_notify = ip_ptr -> nx_ipv6_address_change_notify; + address_change_notify_internal = ip_ptr -> nx_ipv6_address_change_notify_internal; #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ /* Release the protection while the IPv6 address is modified. */ tx_mutex_put(&(ip_ptr -> nx_ip_protection)); @@ -305,6 +311,15 @@ ULONG multicast_address[4]; /* Yes, call the application's address change notify function. */ (address_change_notify)(ip_ptr, NX_IPV6_ADDRESS_MANUAL_CONFIG, interface_index, index, &ipv6_addr -> nxd_ipv6_address[0]); } + + /* Is the internal application configured for notification of address changes and/or + prefix_length change? */ + if ((address_change_notify_internal) && (ipv6_addr -> nxd_ipv6_address_state == NX_IPV6_ADDR_STATE_VALID)) + { + + /* Yes, call the internal application's address change notify function. */ + (address_change_notify_internal)(ip_ptr, NX_IPV6_ADDRESS_MANUAL_CONFIG, interface_index, index, &ipv6_addr -> nxd_ipv6_address[0]); + } #endif /* NX_ENABLE_IPV6_ADDRESS_CHANGE_NOTIFY */ /* Return completion status. */ diff --git a/common/src/nxd_tcp_client_socket_connect.c b/common/src/nxd_tcp_client_socket_connect.c index 9cbd88ab..2cf3bc3a 100644 --- a/common/src/nxd_tcp_client_socket_connect.c +++ b/common/src/nxd_tcp_client_socket_connect.c @@ -31,13 +31,167 @@ #include "nx_ipv6.h" #include "nx_ipv4.h" #include "nx_ip.h" +#ifdef NX_ENABLE_HTTP_PROXY +#include "nx_http_proxy_client.h" +#endif /* NX_ENABLE_HTTP_PROXY */ + + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxd_tcp_client_socket_driver_connect PORTABLE C */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles the connect request for TCP/IP offload */ +/* interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to TCP client socket */ +/* server_ip IP address of server */ +/* server_port Port number of server */ +/* wait_option Suspension option */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* tx_mutex_get Obtain protection */ +/* tx_mutex_put Release protection */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_tcp_client_socket_connect */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ +static UINT _nxd_tcp_client_socket_driver_connect(NX_TCP_SOCKET *socket_ptr, + NXD_ADDRESS *server_ip, + UINT server_port, + ULONG wait_option) +{ +UINT status; +NX_INTERFACE *interface_ptr; +NX_IP *ip_ptr; + + + /* Setup the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; + + /* Clear the socket timeout. */ + socket_ptr -> nx_tcp_socket_timeout = 0; + + /* Let TCP/IP offload interface make the connection. */ + interface_ptr = socket_ptr -> nx_tcp_socket_connect_interface; + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_TCP_CLIENT_SOCKET_CONNECT, + NX_NULL, NX_NULL, server_ip, + socket_ptr -> nx_tcp_socket_port, + &server_port, wait_option); + if ((status == NX_SUCCESS) || (status == NX_IN_PROGRESS)) + { + + /* Set MSS. */ +#ifndef NX_DISABLE_IPV4 + if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4) + { + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV4_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* !NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 + if (server_ip -> nxd_ip_version == NX_IP_VERSION_V6) + { + socket_ptr -> nx_tcp_socket_mss = + (ULONG)((interface_ptr -> nx_interface_ip_mtu_size - sizeof(NX_IPV6_HEADER)) - sizeof(NX_TCP_HEADER)); + } +#endif /* FEATURE_NX_IPV6 */ + socket_ptr -> nx_tcp_socket_connect_mss = socket_ptr -> nx_tcp_socket_mss; + socket_ptr -> nx_tcp_socket_peer_mss = socket_ptr -> nx_tcp_socket_mss; + + if (status == NX_SUCCESS) + { + + /* Connected to server. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_ESTABLISHED; +#ifndef NX_DISABLE_EXTENDED_NOTIFY_SUPPORT + + /* Is a connection completion callback registered with the TCP socket? */ + if (socket_ptr -> nx_tcp_establish_notify) + { + + /* Call the application's establish callback function. */ + (socket_ptr -> nx_tcp_establish_notify)(socket_ptr); + } +#endif + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); + } + else + { + + /* Connected to server. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_SYN_SENT; + } + } + else + { + + /* Unable to connect to server. */ + +#ifndef NX_DISABLE_TCP_INFO + + /* Reduce the active connections count. */ + ip_ptr -> nx_ip_tcp_active_connections--; + + /* Reduce the TCP connections count. */ + ip_ptr -> nx_ip_tcp_connections--; +#endif + + /* Restore the socket state. */ + socket_ptr -> nx_tcp_socket_state = NX_TCP_CLOSED; + + /* Reset server port and server IP address. */ + memset(&socket_ptr -> nx_tcp_socket_connect_ip, 0, sizeof(NXD_ADDRESS)); + socket_ptr -> nx_tcp_socket_connect_port = 0; + + /* Reset the next_hop_address information. */ + socket_ptr -> nx_tcp_socket_next_hop_address = 0; + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_TCPIP_OFFLOAD_ERROR); + } + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_tcp_client_socket_connect PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -67,6 +221,7 @@ /* interface. */ /* tx_mutex_get Obtain protection */ /* tx_mutex_put Release protection */ +/* _nx_http_proxy_client_initialize Initialize the HTTP Proxy */ /* */ /* CALLED BY */ /* */ @@ -79,6 +234,12 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ +/* 10-31-2022 Wenhui Xie Modified comment(s), and */ +/* supported HTTP Proxy, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nxd_tcp_client_socket_connect(NX_TCP_SOCKET *socket_ptr, @@ -102,6 +263,15 @@ ULONG ip_address_log = 0; /* Setup IP pointer. */ ip_ptr = socket_ptr -> nx_tcp_socket_ip_ptr; +#ifdef NX_ENABLE_HTTP_PROXY + if (ip_ptr -> nx_ip_http_proxy_enable) + { + + /* Initialize the HTTP Proxy info and replace the peer IP and port with HTTP proxy server's IP and port. */ + _nx_http_proxy_client_initialize(socket_ptr, &server_ip, &server_port); + } +#endif /* NX_ENABLE_HTTP_PROXY */ + /* Make sure the server IP address is accesible. */ #ifndef NX_DISABLE_IPV4 if (server_ip -> nxd_ip_version == NX_IP_VERSION_V4) @@ -307,8 +477,30 @@ ULONG ip_address_log = 0; socket_ptr -> nx_tcp_socket_receive_queue_head = NX_NULL; socket_ptr -> nx_tcp_socket_receive_queue_tail = NX_NULL; - /* Send the SYN message. */ - _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1)); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if ((outgoing_interface -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (outgoing_interface -> nx_interface_tcpip_offload_handler)) + { + + /* This interface supports TCP/IP offload. */ + return(_nxd_tcp_client_socket_driver_connect(socket_ptr, server_ip, server_port, wait_option)); + } + else +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + { + + /* Send the SYN message. */ + _nx_tcp_packet_send_syn(socket_ptr, (socket_ptr -> nx_tcp_socket_tx_sequence - 1)); + } + +#ifdef NX_ENABLE_HTTP_PROXY + if (ip_ptr -> nx_ip_http_proxy_enable) + { + + /* Set HTTP Proxy state as waiting for TCP connection. */ + socket_ptr -> nx_tcp_socket_http_proxy_state = NX_HTTP_PROXY_STATE_WAITING; + } +#endif /* NX_ENABLE_HTTP_PROXY */ /* Optionally suspend the thread. If timeout occurs, return a connection timeout status. If immediate response is selected, return a connection in progress status. Only on a real diff --git a/common/src/nxd_udp_socket_send.c b/common/src/nxd_udp_socket_send.c index a32c21e9..63291fcb 100644 --- a/common/src/nxd_udp_socket_send.c +++ b/common/src/nxd_udp_socket_send.c @@ -28,6 +28,7 @@ #include "nx_api.h" #include "nx_udp.h" #include "nx_ip.h" +#include "nx_packet.h" #ifdef FEATURE_NX_IPV6 #include "nx_ipv6.h" #endif /* FEATURE_NX_IPV6 */ @@ -36,12 +37,199 @@ #include "nx_ipsec.h" #endif /* NX_IPSEC_ENABLE */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_udp_socket_driver_send PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sends a UDP packet through TCP/IP offload interface. */ +/* */ +/* INPUT */ +/* */ +/* socket_ptr Pointer to UDP socket */ +/* packet_ptr Pointer to UDP packet */ +/* ip_src_address Source IP address */ +/* ip_dst_address Destination IP address */ +/* port 16-bit UDP port number */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_ip_packet_send Packet send function */ +/* _nx_ipv6_packet_send Packet send function */ +/* */ +/* CALLED BY */ +/* */ +/* _nxd_udp_socket_send */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Yuxin Zhou Initial Version 6.1.8 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), corrected*/ +/* the logic for queued packet,*/ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +static UINT _nx_udp_socket_driver_send(NX_UDP_SOCKET *socket_ptr, + NX_PACKET *packet_ptr, + NXD_ADDRESS *ip_src_address, + NXD_ADDRESS *ip_dst_address, + UINT port) +{ +UINT status; +NX_IP *ip_ptr; +NX_INTERFACE *interface_ptr = NX_NULL; +UCHAR *original_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_UDP_HEADER); +ULONG original_length = packet_ptr -> nx_packet_length - sizeof(NX_UDP_HEADER); +UINT packet_reset = NX_FALSE; + + /* Set up the pointer to the associated IP instance. */ + ip_ptr = socket_ptr -> nx_udp_socket_ip_ptr; + + /* Get the outgoing interface. */ +#ifndef NX_DISABLE_IPV4 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4) + { + interface_ptr = packet_ptr -> nx_packet_address.nx_packet_interface_ptr; + } +#endif /* NX_DISABLE_IPV4 */ +#ifdef FEATURE_NX_IPV6 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached; + } +#endif /* FEATURE_NX_IPV6 */ + +#ifdef NX_ENABLE_IP_PACKET_FILTER + /* Check if the IP packet filter is set. */ + if (ip_ptr -> nx_ip_packet_filter || ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Add the IP Header to trigger filtering. */ +#ifndef NX_DISABLE_IPV4 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V4) + { + _nx_ip_header_add(ip_ptr, packet_ptr, + ip_src_address -> nxd_ip_address.v4, + ip_dst_address -> nxd_ip_address.v4, + socket_ptr -> nx_udp_socket_type_of_service, + socket_ptr -> nx_udp_socket_time_to_live, + NX_IP_UDP, socket_ptr -> nx_udp_socket_fragment_enable); + } +#endif /* !NX_DISABLE_IPV4 */ + +#ifdef FEATURE_NX_IPV6 + if (ip_dst_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + if (_nx_ipv6_header_add(ip_ptr, &packet_ptr, NX_PROTOCOL_UDP, + packet_ptr -> nx_packet_length, + ip_ptr -> nx_ipv6_hop_limit, + ip_src_address -> nxd_ip_address.v6, + ip_dst_address -> nxd_ip_address.v6, NX_NULL)) + { + + /* Packet consumed by IPv6 layer. Just return success. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + return(NX_SUCCESS); + } + + /* Reset IP header. */ + packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr + sizeof(NX_IPV6_HEADER); + packet_ptr -> nx_packet_length = packet_ptr -> nx_packet_length - sizeof(NX_IPV6_HEADER); + } +#endif /* FEATURE_NX_IPV6 */ + + if (ip_ptr -> nx_ip_packet_filter) + { + if (ip_ptr -> nx_ip_packet_filter((VOID *)(packet_ptr -> nx_packet_prepend_ptr), + NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + + /* Check if the IP packet filter extended is set. */ + if (ip_ptr -> nx_ip_packet_filter_extended) + { + + /* Yes, call the IP packet filter extended routine. */ + if (ip_ptr -> nx_ip_packet_filter_extended(ip_ptr, packet_ptr, NX_IP_PACKET_OUT) != NX_SUCCESS) + { + + /* Packet consumed by IP filter. Just return success. */ + _nx_packet_transmit_release(packet_ptr); + return(NX_SUCCESS); + } + } + } +#endif /* NX_ENABLE_IP_PACKET_FILTER */ + + /* Reset UDP and IP header. */ + packet_ptr -> nx_packet_prepend_ptr = original_ptr; + packet_ptr -> nx_packet_length = original_length; + + /* Determine if the packet is a queued data packet. _nx_packet_transmit_release in Offload handler + does not release the packet immediately and only adjusts the prepend pointer to User data, + since the packet may need to be resent. To keep the same logic for retransmission in upper layer, + the prepend pointer must be reset to UDP header. */ + if ((packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next != ((NX_PACKET*)NX_PACKET_ALLOCATED)) && + (packet_ptr -> nx_packet_union_next.nx_packet_tcp_queue_next != ((NX_PACKET*)NX_PACKET_FREE))) + { + packet_reset = NX_TRUE; + } + + /* Let TCP/IP offload interface send the packet. */ + status = interface_ptr -> nx_interface_tcpip_offload_handler(ip_ptr, interface_ptr, socket_ptr, + NX_TCPIP_OFFLOAD_UDP_SOCKET_SEND, + packet_ptr, ip_src_address, ip_dst_address, + socket_ptr -> nx_udp_socket_port, + &port, NX_NO_WAIT); + + /* Release the IP protection. */ + tx_mutex_put(&(ip_ptr -> nx_ip_protection)); + + if (status) + { + return(NX_TCPIP_OFFLOAD_ERROR); + } + else + { + + /* Reset prepend pointer to UDP header for queued packet. */ + if (packet_reset == NX_TRUE) + { + packet_ptr -> nx_packet_prepend_ptr = original_ptr - sizeof(NX_UDP_HEADER); + packet_ptr -> nx_packet_length = original_length + sizeof(NX_UDP_HEADER); + } + + return(NX_SUCCESS); + } +} +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nxd_udp_socket_send PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -87,6 +275,9 @@ /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Yuxin Zhou Modified comment(s), and */ +/* supported TCP/IP offload, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nxd_udp_socket_send(NX_UDP_SOCKET *socket_ptr, @@ -109,6 +300,10 @@ NX_INTERFACE *interface_ptr = NX_NULL; UINT status; #endif /* FEATURE_NX_IPV6 */ +#ifdef NX_ENABLE_TCPIP_OFFLOAD +NXD_ADDRESS ip_src_address; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifdef NX_IPSEC_ENABLE VOID *sa = NX_NULL; ULONG data_offset; @@ -199,6 +394,11 @@ UINT compute_checksum = 1; /* Fill in the IP src/dest address */ ip_dest_addr = &ip_address -> nxd_ip_address.v4; ip_src_addr = &interface_ptr -> nx_interface_ip_address; + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + ip_src_address.nxd_ip_version = NX_IP_VERSION_V4; + ip_src_address.nxd_ip_address.v4 = interface_ptr -> nx_interface_ip_address; +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ } #endif /* NX_DISABLE_IPV4 */ @@ -229,6 +429,11 @@ UINT compute_checksum = 1; /* Get the packet interface information. */ interface_ptr = packet_ptr -> nx_packet_address.nx_packet_ipv6_address_ptr -> nxd_ipv6_address_attached; #endif /* NX_ENABLE_INTERFACE_CAPABILITY */ + +#ifdef NX_ENABLE_TCPIP_OFFLOAD + ip_src_address.nxd_ip_version = NX_IP_VERSION_V6; + COPY_IPV6_ADDRESS(ip_src_addr, ip_src_address.nxd_ip_address.v6); +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ } #endif /* FEATURE_NX_IPV6 */ @@ -281,7 +486,7 @@ UINT compute_checksum = 1; } } #endif /* NX_IPSEC_ENABLE */ - + /* Prepend the UDP header to the packet. First, make room for the UDP header. */ packet_ptr -> nx_packet_prepend_ptr = packet_ptr -> nx_packet_prepend_ptr - sizeof(NX_UDP_HEADER); @@ -320,16 +525,16 @@ UINT compute_checksum = 1; NX_TRACE_IN_LINE_INSERT(NX_TRACE_INTERNAL_UDP_SEND, ip_ptr, socket_ptr, packet_ptr, udp_header_ptr -> nx_udp_header_word_0, NX_TRACE_INTERNAL_EVENTS, 0, 0); /* Endian swapping logic. If NX_LITTLE_ENDIAN is specified, these macros will - swap the endian of the UDP header. */ + swap the endian of the UDP header. */ NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_0); NX_CHANGE_ULONG_ENDIAN(udp_header_ptr -> nx_udp_header_word_1); /* Determine if we need to compute the UDP checksum. - Note that with IPv6, UDP packet checksum is mandatory. However if the underly device - driver is able to compute UDP checksum in hardware, let the driver handle the checksum - computation. - */ + Note that with IPv6, UDP packet checksum is mandatory. However if the underly device + driver is able to compute UDP checksum in hardware, let the driver handle the checksum + computation. + */ if ((!socket_ptr -> nx_udp_socket_disable_checksum) || (ip_address -> nxd_ip_version == NX_IP_VERSION_V6)) @@ -343,8 +548,8 @@ UINT compute_checksum = 1; #ifdef NX_IPSEC_ENABLE /* In case this packet is going through the IPsec protected channel, the checksum would have to be computed - in software even if the hardware checksum is available at driver layer. The checksum value must be present - in order when applying IPsec process. */ + in software even if the hardware checksum is available at driver layer. The checksum value must be present + in order when applying IPsec process. */ if ((packet_ptr -> nx_packet_ipsec_sa_ptr != NX_NULL) && (((NX_IPSEC_SA *)(packet_ptr -> nx_packet_ipsec_sa_ptr)) -> nx_ipsec_sa_encryption_method != NX_CRYPTO_NONE)) { @@ -392,6 +597,14 @@ UINT compute_checksum = 1; /* Get mutex protection. */ tx_mutex_get(&(ip_ptr -> nx_ip_protection), TX_WAIT_FOREVER); +#ifdef NX_ENABLE_TCPIP_OFFLOAD + if ((interface_ptr -> nx_interface_capability_flag & NX_INTERFACE_CAPABILITY_TCPIP_OFFLOAD) && + (interface_ptr -> nx_interface_tcpip_offload_handler)) + { + return(_nx_udp_socket_driver_send(socket_ptr, packet_ptr, &ip_src_address, ip_address, port)); + } +#endif /* NX_ENABLE_TCPIP_OFFLOAD */ + #ifndef NX_DISABLE_IPV4 /* Send the UDP packet to the IPv4 component. */ if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) diff --git a/common/src/nxe_tcp_socket_receive_notify.c b/common/src/nxe_tcp_socket_receive_notify.c index e145110c..936efece 100644 --- a/common/src/nxe_tcp_socket_receive_notify.c +++ b/common/src/nxe_tcp_socket_receive_notify.c @@ -38,7 +38,7 @@ NX_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_tcp_socket_receive_notify PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Yuxin Zhou, Microsoft Corporation */ @@ -75,6 +75,9 @@ NX_CALLER_CHECKING_EXTERNS /* 05-19-2020 Yuxin Zhou Initial Version 6.0 */ /* 09-30-2020 Yuxin Zhou Modified comment(s), */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed invalid check, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ UINT _nxe_tcp_socket_receive_notify(NX_TCP_SOCKET *socket_ptr, @@ -89,12 +92,6 @@ UINT status; return(NX_PTR_ERROR); } - /* Check for invalid input pointers. */ - if (tcp_receive_notify == NX_NULL) - { - return(NX_PTR_ERROR); - } - /* Check to see if TCP is enabled. */ if (!(socket_ptr -> nx_tcp_socket_ip_ptr) -> nx_ip_tcp_packet_receive) { diff --git a/crypto_libraries/CMakeLists.txt b/crypto_libraries/CMakeLists.txt index 6b65c1aa..3898fab0 100644 --- a/crypto_libraries/CMakeLists.txt +++ b/crypto_libraries/CMakeLists.txt @@ -45,7 +45,6 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_method_self_test_rsa.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_method_self_test_sha.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_methods.c - ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_module_start.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_null_cipher.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_phash.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_crypto_pkcs1_v1.5.c diff --git a/crypto_libraries/inc/nx_crypto.h b/crypto_libraries/inc/nx_crypto.h index 5a71357d..20144bb7 100644 --- a/crypto_libraries/inc/nx_crypto.h +++ b/crypto_libraries/inc/nx_crypto.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto.h PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -45,6 +45,16 @@ /* by default, and added */ /* crypto standalone support, */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* Renamed FIPS symbol and */ +/* fips memory functions, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* added missing symbol, */ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* cleaned up memory functions,*/ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -76,49 +86,43 @@ extern "C" { #define NX_CRYPTO_LITTLE_ENDIAN 1 #endif +/* Deprecated definition, provided only for backward compatibility */ +#ifdef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST +#define NX_CRYPTO_SELF_TEST +#endif /* NX_CRYPTO_SELF_TEST */ +#endif /* NX_CRYPTO_FIPS */ + #include "nx_crypto_const.h" #include #include -#ifdef NX_CRYPTO_FIPS -VOID *_nx_crypto_fips_memcpy(void *dest, const void *src, size_t size); -VOID *_nx_crypto_fips_memmove(void *dest, const void *src, size_t size); -VOID *_nx_crypto_fips_memset(void *dest, int value, size_t size); -int _nx_crypto_fips_memcmp(const void *dest, const void *src, size_t size); -UINT _nx_crypto_drbg(UINT bits, UCHAR *result); +/* Configuration macro: enable curve25519 and curve448. */ +/* #define NX_CRYPTO_ENABLE_CURVE25519_448 */ -#ifdef _NX_CRYPTO_INITIALIZE_ -VOID *(*volatile _nx_crypto_memset_ptr)(void *dest, int value, size_t size) = _nx_crypto_fips_memset; -VOID *(*volatile _nx_crypto_memcpy_ptr)(void *dest, const void *src, size_t size) = _nx_crypto_fips_memcpy; -#else -extern VOID *(*volatile _nx_crypto_memset_ptr)(void *dest, int value, size_t size); -extern VOID *(*volatile _nx_crypto_memcpy_ptr)(void *dest, const void *src, size_t size); -#endif +#ifdef NX_CRYPTO_SELF_TEST -#ifndef NX_CRYPTO_MEMCPY -#define NX_CRYPTO_MEMCPY _nx_crypto_memcpy_ptr -#endif +VOID *_nx_crypto_self_test_memcpy(void *dest, const void *src, size_t size); +VOID *_nx_crypto_self_test_memmove(void *dest, const void *src, size_t size); +VOID *_nx_crypto_self_test_memset(void *dest, int value, size_t size); +int _nx_crypto_self_test_memcmp(const void *dest, const void *src, size_t size); +UINT _nx_crypto_drbg(UINT bits, UCHAR *result); -#ifndef NX_CRYPTO_MEMMOVE -#define NX_CRYPTO_MEMMOVE _nx_crypto_fips_memmove +#ifndef NX_CRYPTO_RBG +#define NX_CRYPTO_RBG _nx_crypto_drbg #endif -#ifndef NX_CRYPTO_MEMSET -#define NX_CRYPTO_MEMSET _nx_crypto_memset_ptr -#endif +#define NX_CRYPTO_CONST -#ifndef NX_CRYPTO_MEMCMP -#define NX_CRYPTO_MEMCMP _nx_crypto_fips_memcmp -#endif +#else /* NON NX_CRYPTO_SELF_TEST build. */ #ifndef NX_CRYPTO_RBG -#define NX_CRYPTO_RBG _nx_crypto_drbg +#define NX_CRYPTO_RBG _nx_crypto_huge_number_rbg #endif -#define NX_CRYPTO_CONST - -#else /* NON FIPS build. */ +#define NX_CRYPTO_CONST const +#endif #ifdef _NX_CRYPTO_INITIALIZE_ VOID *(*volatile _nx_crypto_memset_ptr)(void *dest, int value, size_t size) = memset; @@ -144,17 +148,14 @@ extern VOID *(*volatile _nx_crypto_memcpy_ptr)(void *dest, const void *src, size #define NX_CRYPTO_MEMCMP memcmp #endif -#ifndef NX_CRYPTO_RBG -#define NX_CRYPTO_RBG _nx_crypto_huge_number_rbg -#endif - -#define NX_CRYPTO_CONST const -#endif - #if !defined(NX_CRYPTO_CHANGE_ULONG_ENDIAN) && defined(NX_CHANGE_ULONG_ENDIAN) #define NX_CRYPTO_CHANGE_ULONG_ENDIAN NX_CHANGE_ULONG_ENDIAN #endif +#if !defined(NX_CRYPTO_CHANGE_USHORT_ENDIAN) && defined(NX_CHANGE_USHORT_ENDIAN) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN NX_CHANGE_USHORT_ENDIAN +#endif + #ifndef NX_CRYPTO_INTEGRITY_TEST #define NX_CRYPTO_INTEGRITY_TEST #endif @@ -177,9 +178,9 @@ extern VOID *(*volatile _nx_crypto_memcpy_ptr)(void *dest, const void *src, size #endif #endif -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST -/* FIPS build forces NX_SECURE_KEY_CLEAR to be set */ +/* NX_CRYPTO_SELF_TEST build forces NX_SECURE_KEY_CLEAR to be set */ #ifndef NX_SECURE_KEY_CLEAR #define NX_SECURE_KEY_CLEAR #endif /* NX_SECURE_KEY_CLEAR */ @@ -197,7 +198,7 @@ extern unsigned int _nx_crypto_library_state; #else #define NX_CRYPTO_STATE_CHECK -#endif /* NX_CRYPTO_FIPS */ +#endif /* NX_CRYPTO_SELF_TEST */ /* Keep functions not used which is compiler specific. */ #ifndef NX_CRYPTO_KEEP @@ -374,7 +375,7 @@ typedef struct NX_CRYPTO_CIPHERSUITE_STRUCT UINT _nx_crypto_initialize(VOID); -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST #define nx_crypto_method_self_test _nx_crypto_method_self_test #define nx_crypto_module_state_get _nx_crypto_module_state_get /* int nx_crypto_rand(void); */ diff --git a/crypto_libraries/inc/nx_crypto_aes.h b/crypto_libraries/inc/nx_crypto_aes.h index 03f5e0f0..08f977dc 100644 --- a/crypto_libraries/inc/nx_crypto_aes.h +++ b/crypto_libraries/inc/nx_crypto_aes.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_crypto_aes.h PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -43,6 +43,10 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* moved inverse key expansion,*/ +/* added using RAM tables, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -106,6 +110,13 @@ extern "C" { #define NX_CRYPTO_AES_KEY_SCHEDULE_ENCRYPT 1 #define NX_CRYPTO_AES_KEY_SCHEDULE_DECRYPT 2 +/* Define NX_CRYPTO_AES_USE_RAM_TABLES to move tables to RAM. */ +#ifdef NX_CRYPTO_AES_USE_RAM_TABLES +#define NX_CRYPTO_AES_TABLE static +#else +#define NX_CRYPTO_AES_TABLE static const +#endif + /* Define the control block structure for backward compatibility. */ #define NX_AES NX_CRYPTO_AES @@ -122,7 +133,8 @@ typedef struct NX_CRYPTO_AES_STRUCT /* Number of AES rounds for the current key. */ UCHAR nx_crypto_aes_rounds; - UCHAR nx_crypto_aes_reserved; + /* Use the flag field to indicate the inverse key expansion is done. */ + UCHAR nx_crypto_aes_inverse_key_expanded; /* The key schedule is as large as the key size (max = 256 bits) with expansion, total 64 UINT words. */ UINT nx_crypto_aes_key_schedule[NX_CRYPTO_AES_MAX_KEY_SIZE * 8]; diff --git a/crypto_libraries/inc/nx_crypto_const.h b/crypto_libraries/inc/nx_crypto_const.h index b7fb2adf..213bdcd1 100644 --- a/crypto_libraries/inc/nx_crypto_const.h +++ b/crypto_libraries/inc/nx_crypto_const.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_const.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -43,6 +43,16 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), added */ /* new constants, */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), added */ +/* x25519 and x448 curves, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* EC curve type macro, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -191,6 +201,8 @@ extern "C" { #define NX_CRYPTO_EC_BRAINPOOLP256r1 0x0006001A #define NX_CRYPTO_EC_BRAINPOOLP384r1 0x0006001B #define NX_CRYPTO_EC_BRAINPOOLP512r1 0x0006001C +#define NX_CRYPTO_EC_X25519 0x0006001D +#define NX_CRYPTO_EC_X448 0x0006001E #define NX_CRYPTO_EC_FFDHE2048 0x00060100 #define NX_CRYPTO_EC_FFDHE3072 0x00060101 #define NX_CRYPTO_EC_FFDHE4096 0x00060102 @@ -204,6 +216,11 @@ extern "C" { #define NX_CRYPTO_EC_POINT_ANSIX962_COMPRESSED_PRIME 1 #define NX_CRYPTO_EC_POINT_ANSIX962_COMPRESSED_CHAR2 2 +/* Elliptic curve type definitions. */ +#define NX_CRYPTO_EC_CURVE_TYPE_EXPLICIT_PRIME 1 +#define NX_CRYPTO_EC_CURVE_TYPE_EXPLICIT_CHAR2 2 +#define NX_CRYPTO_EC_CURVE_TYPE_NAMED_CURVE 3 + /* Define crypto ICV bits size. */ #define NX_CRYPTO_AUTHENTICATION_ICV_TRUNC_BITS 96 @@ -319,13 +336,13 @@ typedef UINT NX_CRYPTO_KEY_SIZE; /* The following symbols are mapped to the error code for backward compatibility. */ #define NX_CRYPTO_AES_UNSUPPORTED_KEY_SIZE NX_CRYPTO_UNSUPPORTED_KEY_SIZE -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST #define NX_CRYPTO_LIBRARY_STATE_UNINITIALIZED 0x00000001U #define NX_CRYPTO_LIBRARY_STATE_POST_IN_PROGRESS 0x00000002U #define NX_CRYPTO_LIBRARY_STATE_POST_FAILED 0x00000004U #define NX_CRYPTO_LIBRARY_STATE_OPERATIONAL 0x80000000U -#endif /* NX_CRYPTO_FIPS */ +#endif /* NX_CRYPTO_SELF_TEST */ #ifdef __cplusplus diff --git a/crypto_libraries/inc/nx_crypto_ec.h b/crypto_libraries/inc/nx_crypto_ec.h index a582c06a..0a372cb9 100644 --- a/crypto_libraries/inc/nx_crypto_ec.h +++ b/crypto_libraries/inc/nx_crypto_ec.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_crypto_ec.h PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -44,6 +44,15 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), and */ /* added public key validation,*/ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* added x25519 curve, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curve, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -181,26 +190,288 @@ typedef struct NX_CRYPTO_EC_STRUCT _nx_crypto_huge_number_shift_left(value, shift); \ curve -> nx_crypto_ec_reduce(curve, value, scratch); -#define NX_CRYPTO_EC_SECP192R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5) \ - b[0] = c0; b[1] = c1; b[2] = c2; \ - b[3] = c3; b[4] = c4; b[5] = c5; \ - _nx_crypto_huge_number_setup(s, (UCHAR *)b, 24); - -#define NX_CRYPTO_EC_SECP224R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6) \ - b[0] = c0; b[1] = c1; b[2] = c2; b[3] = c3; \ - b[4] = c4; b[5] = c5; b[6] = c6; \ - _nx_crypto_huge_number_setup(s, (UCHAR *)b, 28); +#if (NX_CRYPTO_HUGE_NUMBER_BITS == 32) + +#define NX_CRYPTO_EC_ASSIGN_REV(a, b) (a) = (b); NX_CRYPTO_CHANGE_ULONG_ENDIAN(a) +#define NX_CRYPTO_EC_CHANGE_ENDIAN(a, b, c) NX_CRYPTO_EC_ASSIGN_REV(b, c); (a) = (b) + +#define NX_CRYPTO_EC_SECP192R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, c0); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, c1); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, c2); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, c3); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, c4); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, c5); \ + (s) -> nx_crypto_huge_number_size = 6; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP224R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, c0); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, c1); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, c2); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, c3); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, c4); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, c5); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, c6); \ + (s) -> nx_crypto_huge_number_size = 7; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; #define NX_CRYPTO_EC_SECP256R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6, c7) \ - b[0] = c0; b[1] = c1; b[2] = c2; b[3] = c3; \ - b[4] = c4; b[5] = c5; b[6] = c6; b[7] = c7; \ - _nx_crypto_huge_number_setup(s, (UCHAR *)b, 32); + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, c0); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, c1); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, c2); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, c3); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, c4); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, c5); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, c6); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, c7); \ + (s) -> nx_crypto_huge_number_size = 8; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP256R1_DATA_SETUP_LS1(s, b1, b2, c0, c1, c2, c3, c4, c5, c6, c7) \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c0); \ + (s) -> nx_crypto_huge_number_data[8] = (b1) >> 31; \ + (s) -> nx_crypto_huge_number_size = 8 + ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c1); \ + (s) -> nx_crypto_huge_number_data[7] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c2); \ + (s) -> nx_crypto_huge_number_data[6] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c3); \ + (s) -> nx_crypto_huge_number_data[5] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c4); \ + (s) -> nx_crypto_huge_number_data[4] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c5); \ + (s) -> nx_crypto_huge_number_data[3] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c6); \ + (s) -> nx_crypto_huge_number_data[2] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c7); \ + (s) -> nx_crypto_huge_number_data[1] = ((b1) << 1) | ((b2) >> 31); \ + (s) -> nx_crypto_huge_number_data[0] = (b2) << 1; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP384R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[11], b, c0); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[10], b, c1); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[9], b, c2); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[8], b, c3); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, c4); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, c5); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, c6); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, c7); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, c8); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, c9); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, c10); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, c11); \ + (s) -> nx_crypto_huge_number_size = 12; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP384R1_DATA_SETUP_LS1(s, b1, b2, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c0); \ + (s) -> nx_crypto_huge_number_data[12] = (b1) >> 31; \ + (s) -> nx_crypto_huge_number_size = 12 + ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c1); \ + (s) -> nx_crypto_huge_number_data[11] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c2); \ + (s) -> nx_crypto_huge_number_data[10] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c3); \ + (s) -> nx_crypto_huge_number_data[9] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c4); \ + (s) -> nx_crypto_huge_number_data[8] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c5); \ + (s) -> nx_crypto_huge_number_data[7] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c6); \ + (s) -> nx_crypto_huge_number_data[6] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c7); \ + (s) -> nx_crypto_huge_number_data[5] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c8); \ + (s) -> nx_crypto_huge_number_data[4] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c9); \ + (s) -> nx_crypto_huge_number_data[3] = ((b1) << 1) | ((b2) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, c10); \ + (s) -> nx_crypto_huge_number_data[2] = ((b2) << 1) | ((b1) >> 31); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, c11); \ + (s) -> nx_crypto_huge_number_data[1] = ((b1) << 1) | ((b2) >> 31); \ + (s) -> nx_crypto_huge_number_data[0] = (b2) << 1; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#else + +#define NX_CRYPTO_EC_ASSIGN_REV(a,b) (a) = (b); NX_CRYPTO_CHANGE_USHORT_ENDIAN(a) +#define NX_CRYPTO_EC_CHANGE_ENDIAN(a, b, c) NX_CRYPTO_EC_ASSIGN_REV(b, c); (a) = (b) + +#define NX_CRYPTO_EC_SECP192R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[11], b, (HN_UBASE)(c0)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[10], b, (HN_UBASE)(c0 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[9], b, (HN_UBASE)(c1)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[8], b, (HN_UBASE)(c1 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, (HN_UBASE)(c2)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, (HN_UBASE)(c2 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, (HN_UBASE)(c3)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, (HN_UBASE)(c3 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, (HN_UBASE)(c4)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, (HN_UBASE)(c4 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, (HN_UBASE)(c5)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, (HN_UBASE)(c5 >> 16)); \ + (s) -> nx_crypto_huge_number_size = 12; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP224R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[13], b, (HN_UBASE)(c0)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[12], b, (HN_UBASE)(c0 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[11], b, (HN_UBASE)(c1)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[10], b, (HN_UBASE)(c1 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[9], b, (HN_UBASE)(c2)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[8], b, (HN_UBASE)(c2 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, (HN_UBASE)(c3)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, (HN_UBASE)(c3 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, (HN_UBASE)(c4)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, (HN_UBASE)(c4 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, (HN_UBASE)(c5)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, (HN_UBASE)(c5 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, (HN_UBASE)(c6)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, (HN_UBASE)(c6 >> 16)); \ + (s) -> nx_crypto_huge_number_size = 14; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP256R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6, c7) \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[15], b, (HN_UBASE)(c0)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[14], b, (HN_UBASE)(c0 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[13], b, (HN_UBASE)(c1)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[12], b, (HN_UBASE)(c1 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[11], b, (HN_UBASE)(c2)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[10], b, (HN_UBASE)(c2 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[9], b, (HN_UBASE)(c3)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[8], b, (HN_UBASE)(c3 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, (HN_UBASE)(c4)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, (HN_UBASE)(c4 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, (HN_UBASE)(c5)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, (HN_UBASE)(c5 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, (HN_UBASE)(c6)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, (HN_UBASE)(c6 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, (HN_UBASE)(c7)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, (HN_UBASE)(c7 >> 16)); \ + (s) -> nx_crypto_huge_number_size = 16; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP256R1_DATA_SETUP_LS1(s, b1, b2, c0, c1, c2, c3, c4, c5, c6, c7) \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c0)); \ + (s) -> nx_crypto_huge_number_data[16] = (HN_UBASE)((b1) >> 15); \ + (s) -> nx_crypto_huge_number_size = (UINT)(16 + (HN_UBASE)((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c0 >> 16)); \ + (s) -> nx_crypto_huge_number_data[15] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c1)); \ + (s) -> nx_crypto_huge_number_data[14] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c1 >> 16)); \ + (s) -> nx_crypto_huge_number_data[13] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c2)); \ + (s) -> nx_crypto_huge_number_data[12] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c2 >> 16)); \ + (s) -> nx_crypto_huge_number_data[11] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c3)); \ + (s) -> nx_crypto_huge_number_data[10] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c3 >> 16)); \ + (s) -> nx_crypto_huge_number_data[9] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c4)); \ + (s) -> nx_crypto_huge_number_data[8] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c4 >> 16)); \ + (s) -> nx_crypto_huge_number_data[7] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c5)); \ + (s) -> nx_crypto_huge_number_data[6] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c5 >> 16)); \ + (s) -> nx_crypto_huge_number_data[5] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c6)); \ + (s) -> nx_crypto_huge_number_data[4] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c6 >> 16)); \ + (s) -> nx_crypto_huge_number_data[3] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c7)); \ + (s) -> nx_crypto_huge_number_data[2] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c7 >> 16)); \ + (s) -> nx_crypto_huge_number_data[1] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + (s) -> nx_crypto_huge_number_data[0] = (HN_UBASE)((b2) << 1); \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; #define NX_CRYPTO_EC_SECP384R1_DATA_SETUP(s, b, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \ - b[0] = c0; b[1] = c1; b[2] = c2; b[3] = c3; \ - b[4] = c4; b[5] = c5; b[6] = c6; b[7] = c7; \ - b[8] = c8; b[9] = c9; b[10] = c10; b[11] = c11; \ - _nx_crypto_huge_number_setup(s, (UCHAR *)b, 48); + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[23], b, (HN_UBASE)(c0)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[22], b, (HN_UBASE)(c0 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[21], b, (HN_UBASE)(c1)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[20], b, (HN_UBASE)(c1 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[19], b, (HN_UBASE)(c2)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[18], b, (HN_UBASE)(c2 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[17], b, (HN_UBASE)(c3)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[16], b, (HN_UBASE)(c3 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[15], b, (HN_UBASE)(c4)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[14], b, (HN_UBASE)(c4 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[13], b, (HN_UBASE)(c5)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[12], b, (HN_UBASE)(c5 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[11], b, (HN_UBASE)(c6)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[10], b, (HN_UBASE)(c6 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[9], b, (HN_UBASE)(c7)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[8], b, (HN_UBASE)(c7 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[7], b, (HN_UBASE)(c8)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[6], b, (HN_UBASE)(c8 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[5], b, (HN_UBASE)(c9)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[4], b, (HN_UBASE)(c9 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[3], b, (HN_UBASE)(c10)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[2], b, (HN_UBASE)(c10 >> 16)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[1], b, (HN_UBASE)(c11)); \ + NX_CRYPTO_EC_CHANGE_ENDIAN((s) -> nx_crypto_huge_number_data[0], b, (HN_UBASE)(c11 >> 16)); \ + (s) -> nx_crypto_huge_number_size = 24; \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#define NX_CRYPTO_EC_SECP384R1_DATA_SETUP_LS1(s, b1, b2, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11) \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c0)); \ + (s) -> nx_crypto_huge_number_data[24] = (HN_UBASE)((b1) >> 15); \ + (s) -> nx_crypto_huge_number_size = (UINT)(24 + (HN_UBASE)((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c0 >> 16)); \ + (s) -> nx_crypto_huge_number_data[23] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c1)); \ + (s) -> nx_crypto_huge_number_data[22] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c1 >> 16)); \ + (s) -> nx_crypto_huge_number_data[21] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c2)); \ + (s) -> nx_crypto_huge_number_data[20] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c2 >> 16)); \ + (s) -> nx_crypto_huge_number_data[19] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c3)); \ + (s) -> nx_crypto_huge_number_data[18] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c3 >> 16)); \ + (s) -> nx_crypto_huge_number_data[17] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c4)); \ + (s) -> nx_crypto_huge_number_data[16] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c4 >> 16)); \ + (s) -> nx_crypto_huge_number_data[15] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c5)); \ + (s) -> nx_crypto_huge_number_data[14] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c5 >> 16)); \ + (s) -> nx_crypto_huge_number_data[13] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c6)); \ + (s) -> nx_crypto_huge_number_data[12] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c6 >> 16)); \ + (s) -> nx_crypto_huge_number_data[11] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c7)); \ + (s) -> nx_crypto_huge_number_data[10] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c7 >> 16)); \ + (s) -> nx_crypto_huge_number_data[9] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c8)); \ + (s) -> nx_crypto_huge_number_data[8] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c8 >> 16)); \ + (s) -> nx_crypto_huge_number_data[7] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c9)); \ + (s) -> nx_crypto_huge_number_data[6] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c9 >> 16)); \ + (s) -> nx_crypto_huge_number_data[5] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c10)); \ + (s) -> nx_crypto_huge_number_data[4] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c10 >> 16)); \ + (s) -> nx_crypto_huge_number_data[3] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b1, (HN_UBASE)(c11)); \ + (s) -> nx_crypto_huge_number_data[2] = (HN_UBASE)(((b2) << 1) | ((b1) >> 15)); \ + NX_CRYPTO_EC_ASSIGN_REV(b2, (HN_UBASE)(c11 >> 16)); \ + (s) -> nx_crypto_huge_number_data[1] = (HN_UBASE)(((b1) << 1) | ((b2) >> 15)); \ + (s) -> nx_crypto_huge_number_data[0] = (HN_UBASE)((b2) << 1); \ + (s) -> nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + +#endif extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp192r1; extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp224r1; @@ -361,6 +632,46 @@ UINT _nx_crypto_method_ec_secp521r1_operation(UINT op, VOID *crypto_metadata, ULONG crypto_metadata_size, VOID *packet_ptr, VOID (*nx_crypto_hw_process_callback)(VOID *, UINT)); + +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 +extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_x25519; +extern NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_x448; + +VOID _nx_crypto_ec_cswap(UINT swap, NX_CRYPTO_HUGE_NUMBER *h1, NX_CRYPTO_HUGE_NUMBER *h2); +VOID _nx_crypto_ec_x25519_448_multiple(NX_CRYPTO_EC *curve, + NX_CRYPTO_EC_POINT *u, + NX_CRYPTO_HUGE_NUMBER *k, + NX_CRYPTO_EC_POINT *r, + HN_UBASE *scratch); +UINT _nx_crypto_method_ec_x25519_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *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 *, UINT)); +UINT _nx_crypto_method_ec_x448_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *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 *, UINT)); +UINT _nx_crypto_ec_key_pair_generation_x25519_448(NX_CRYPTO_EC *curve, + NX_CRYPTO_EC_POINT *g, + NX_CRYPTO_HUGE_NUMBER *private_key, + NX_CRYPTO_EC_POINT *public_key, + HN_UBASE *scratch); +UINT _nx_crypto_ec_extract_fixed_size_le(NX_CRYPTO_HUGE_NUMBER *number, + UCHAR *byte_stream, UINT byte_stream_size); +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + #ifdef __cplusplus } #endif diff --git a/crypto_libraries/inc/nx_crypto_ecdh.h b/crypto_libraries/inc/nx_crypto_ecdh.h index cbc131ce..c5d20074 100644 --- a/crypto_libraries/inc/nx_crypto_ecdh.h +++ b/crypto_libraries/inc/nx_crypto_ecdh.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_crypto_ecdh.h PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -43,6 +43,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), supported*/ +/* x25519 and x448 curves, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -133,6 +136,32 @@ UINT _nx_crypto_method_ecdh_operation(UINT op, VOID *packet_ptr, VOID (*nx_crypto_hw_process_callback)(VOID *, UINT)); +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 +UINT _nx_crypto_ecdh_key_pair_import_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + NX_CRYPTO_EC *curve, + UCHAR *local_private_key_ptr, + ULONG local_private_key_len, + UCHAR *local_public_key_ptr, + ULONG local_public_key_len); +UINT _nx_crypto_ecdh_private_key_export_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *local_private_key_ptr, + ULONG local_private_key_len, + ULONG *actual_local_private_key_len); +UINT _nx_crypto_ecdh_setup_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *local_public_key_ptr, + ULONG local_public_key_len, + ULONG *actual_local_public_key_len, + NX_CRYPTO_EC *curve, + HN_UBASE *scratch_buf_ptr); +UINT _nx_crypto_ecdh_compute_secret_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *share_secret_key_ptr, + ULONG share_secret_key_len_ptr, + ULONG *actual_share_secret_key_len, + UCHAR *remote_public_key, + ULONG remote_public_key_len, + HN_UBASE *scratch_buf_ptr); +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + #ifdef __cplusplus } #endif diff --git a/crypto_libraries/inc/nx_crypto_huge_number.h b/crypto_libraries/inc/nx_crypto_huge_number.h index a988fb9a..be905c5c 100644 --- a/crypto_libraries/inc/nx_crypto_huge_number.h +++ b/crypto_libraries/inc/nx_crypto_huge_number.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_crypto_huge_number.h PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), and */ /* fixed number initialization,*/ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), and */ +/* used ULONG64_DEFINED macro, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -77,10 +80,9 @@ extern "C" { #endif /* NX_CRYPTO_HUGE_NUMBER_BITS */ #if (NX_CRYPTO_HUGE_NUMBER_BITS == 32) -#ifndef ULONG64 +#ifndef ULONG64_DEFINED +#define ULONG64_DEFINED #define ULONG64 unsigned long long -#endif -#ifndef LONG64 #define LONG64 long long #endif #define HN_BASE LONG diff --git a/crypto_libraries/inc/nx_crypto_method_self_test.h b/crypto_libraries/inc/nx_crypto_method_self_test.h index 37d6446d..0bec9858 100644 --- a/crypto_libraries/inc/nx_crypto_method_self_test.h +++ b/crypto_libraries/inc/nx_crypto_method_self_test.h @@ -34,7 +34,7 @@ extern "C" { #include "nx_crypto.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST UINT _nx_crypto_method_self_test_aes(NX_CRYPTO_METHOD *crypto_method_aes, VOID *metadata, UINT metadata_size); diff --git a/crypto_libraries/inc/nx_crypto_sha5.h b/crypto_libraries/inc/nx_crypto_sha5.h index 8b1b7ee0..aecf1ebe 100644 --- a/crypto_libraries/inc/nx_crypto_sha5.h +++ b/crypto_libraries/inc/nx_crypto_sha5.h @@ -25,7 +25,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_sha5.h PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -45,6 +45,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), and */ +/* used ULONG64_DEFINED macro, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -65,13 +68,11 @@ extern "C" { #include "nx_crypto.h" -#ifndef ULONG64 +#ifndef ULONG64_DEFINED +#define ULONG64_DEFINED #define ULONG64 unsigned long long #endif /* ULONG64 */ -#ifndef LONG64 -#define LONG64 long long -#endif /* LONG64 */ #define NX_CRYPTO_SHA512_BLOCK_SIZE_IN_BYTES 128 #define NX_CRYPTO_SHA384_ICV_LEN_IN_BITS 384 diff --git a/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h index 024d9356..6d804b37 100644 --- a/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h +++ b/crypto_libraries/ports/cortex_m3/ac5/inc/nx_crypto_port.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_port.h Cortex-M3/AC5 */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -41,6 +41,8 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -48,6 +50,7 @@ #define _NX_CRYPTO_PORT_H_ #include #include +#include "cmsis_compiler.h" #ifdef NX_CRYPTO_STANDALONE_ENABLE diff --git a/crypto_libraries/ports/cortex-m7/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h similarity index 97% rename from crypto_libraries/ports/cortex-m7/ac5/inc/nx_crypto_port.h rename to crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h index 28e969cd..00548f97 100644 --- a/crypto_libraries/ports/cortex-m7/ac5/inc/nx_crypto_port.h +++ b/crypto_libraries/ports/cortex_m3/ac6/inc/nx_crypto_port.h @@ -25,8 +25,8 @@ /* */ /* COMPONENT DEFINITION RELEASE */ /* */ -/* nx_crypto_port.h Cortex-M7/AC5 */ -/* 6.1 */ +/* nx_crypto_port.h Cortex-M3/AC6 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -40,7 +40,7 @@ /* */ /* DATE NAME DESCRIPTION */ /* */ -/* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */ /* */ /**************************************************************************/ @@ -48,6 +48,7 @@ #define _NX_CRYPTO_PORT_H_ #include #include +#include "cmsis_compiler.h" #ifdef NX_CRYPTO_STANDALONE_ENABLE diff --git a/crypto_libraries/ports/cortex_m3/kiel/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h similarity index 96% rename from crypto_libraries/ports/cortex_m3/kiel/inc/nx_crypto_port.h rename to crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h index f32d3c0d..4686e62f 100644 --- a/crypto_libraries/ports/cortex_m3/kiel/inc/nx_crypto_port.h +++ b/crypto_libraries/ports/cortex_m3/keil/inc/nx_crypto_port.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_port.h Cortex-M3/Keil */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -41,6 +41,8 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -48,6 +50,7 @@ #define _NX_CRYPTO_PORT_H_ #include #include +#include "cmsis_compiler.h" #ifdef NX_CRYPTO_STANDALONE_ENABLE diff --git a/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h index ab2dfd4a..5c87204b 100644 --- a/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h +++ b/crypto_libraries/ports/cortex_m4/ac5/inc/nx_crypto_port.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_port.h Cortex-M4/AC5 */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -41,6 +41,8 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -48,6 +50,7 @@ #define _NX_CRYPTO_PORT_H_ #include #include +#include "cmsis_compiler.h" #ifdef NX_CRYPTO_STANDALONE_ENABLE diff --git a/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h new file mode 100644 index 00000000..07f0e1bf --- /dev/null +++ b/crypto_libraries/ports/cortex_m4/ac6/inc/nx_crypto_port.h @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Crypto Component */ +/** */ +/** Crypto */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* nx_crypto_port.h Cortex-M4/AC6 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions for the NetX Security */ +/* Encryption component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ + +#ifndef _NX_CRYPTO_PORT_H_ +#define _NX_CRYPTO_PORT_H_ +#include +#include +#include "cmsis_compiler.h" + +#ifdef NX_CRYPTO_STANDALONE_ENABLE + +/* Default to little endian, since this is what most ARM targets are. */ +#define NX_CRYPTO_LITTLE_ENDIAN 1 + +/* Define macros that swap the endian for little endian ports. */ +#if NX_CRYPTO_LITTLE_ENDIAN +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg)) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16) +#else +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a) +#endif + +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +#endif + +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ + +#endif /* _NX_CRYPTO_PORT_H_ */ diff --git a/crypto_libraries/ports/cortex_m4/kiel/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h similarity index 96% rename from crypto_libraries/ports/cortex_m4/kiel/inc/nx_crypto_port.h rename to crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h index f95f0451..8d516e18 100644 --- a/crypto_libraries/ports/cortex_m4/kiel/inc/nx_crypto_port.h +++ b/crypto_libraries/ports/cortex_m4/keil/inc/nx_crypto_port.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_crypto_port.h Cortex-M4/Keil */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -41,6 +41,8 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -48,6 +50,7 @@ #define _NX_CRYPTO_PORT_H_ #include #include +#include "cmsis_compiler.h" #ifdef NX_CRYPTO_STANDALONE_ENABLE diff --git a/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h new file mode 100644 index 00000000..dd7140bd --- /dev/null +++ b/crypto_libraries/ports/cortex_m7/ac5/inc/nx_crypto_port.h @@ -0,0 +1,83 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Crypto Component */ +/** */ +/** Crypto */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* nx_crypto_port.h Cortex-M7/AC5 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions for the NetX Security */ +/* Encryption component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 08-02-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.8 */ +/* */ +/**************************************************************************/ + +#ifndef _NX_CRYPTO_PORT_H_ +#define _NX_CRYPTO_PORT_H_ +#include +#include +#include "cmsis_compiler.h" + +#ifdef NX_CRYPTO_STANDALONE_ENABLE + +/* Default to little endian, since this is what most ARM targets are. */ +#define NX_CRYPTO_LITTLE_ENDIAN 1 + +/* Define macros that swap the endian for little endian ports. */ +#if NX_CRYPTO_LITTLE_ENDIAN +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg)) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16) +#else +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a) +#endif + +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +#endif + +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ + +#endif /* _NX_CRYPTO_PORT_H_ */ diff --git a/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h new file mode 100644 index 00000000..4e2e12ea --- /dev/null +++ b/crypto_libraries/ports/cortex_m7/ac6/inc/nx_crypto_port.h @@ -0,0 +1,81 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Crypto Component */ +/** */ +/** Crypto */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* nx_crypto_port.h Cortex-M7/AC6 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions for the NetX Security */ +/* Encryption component. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-02-2021 Bhupendra Naphade Initial Version 6.1.8 */ +/* */ +/**************************************************************************/ + +#ifndef _NX_CRYPTO_PORT_H_ +#define _NX_CRYPTO_PORT_H_ +#include +#include +#include "cmsis_compiler.h" + +#ifdef NX_CRYPTO_STANDALONE_ENABLE + +/* Default to little endian, since this is what most ARM targets are. */ +#define NX_CRYPTO_LITTLE_ENDIAN 1 + +/* Define macros that swap the endian for little endian ports. */ +#if NX_CRYPTO_LITTLE_ENDIAN +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(arg) (arg) = (unsigned int)(__rev(arg)) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(arg) (arg) = (unsigned short)(__rev(arg) >> 16) +#else +#define NX_CRYPTO_CHANGE_ULONG_ENDIAN(a) +#define NX_CRYPTO_CHANGE_USHORT_ENDIAN(a) +#endif + +#ifndef VOID +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; +#endif + +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ + +#endif /* _NX_CRYPTO_PORT_H_ */ diff --git a/crypto_libraries/ports/cortex-m7/gnu/CMakeLists.txt b/crypto_libraries/ports/cortex_m7/gnu/CMakeLists.txt similarity index 100% rename from crypto_libraries/ports/cortex-m7/gnu/CMakeLists.txt rename to crypto_libraries/ports/cortex_m7/gnu/CMakeLists.txt diff --git a/crypto_libraries/ports/cortex-m7/gnu/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/gnu/inc/nx_crypto_port.h similarity index 100% rename from crypto_libraries/ports/cortex-m7/gnu/inc/nx_crypto_port.h rename to crypto_libraries/ports/cortex_m7/gnu/inc/nx_crypto_port.h diff --git a/crypto_libraries/ports/cortex-m7/iar/inc/nx_crypto_port.h b/crypto_libraries/ports/cortex_m7/iar/inc/nx_crypto_port.h similarity index 100% rename from crypto_libraries/ports/cortex-m7/iar/inc/nx_crypto_port.h rename to crypto_libraries/ports/cortex_m7/iar/inc/nx_crypto_port.h diff --git a/crypto_libraries/src/nx_crypto_3des.c b/crypto_libraries/src/nx_crypto_3des.c index aaa65fc0..8411a555 100644 --- a/crypto_libraries/src/nx_crypto_3des.c +++ b/crypto_libraries/src/nx_crypto_3des.c @@ -28,7 +28,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_3des_key_set PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -63,16 +63,20 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_3des_key_set(NX_CRYPTO_3DES *context, UCHAR key[24]) { - _nx_crypto_des_key_set(&context -> des_1, key); + _nx_crypto_des_key_set(&context -> des_1, key); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_key_set(&context -> des_2, key + 8); + _nx_crypto_des_key_set(&context -> des_2, key + 8); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_key_set(&context -> des_3, key + 16); + _nx_crypto_des_key_set(&context -> des_3, key + 16); /* lgtm[cpp/weak-cryptographic-algorithm] */ return(NX_CRYPTO_SUCCESS); } @@ -83,7 +87,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_key_set(NX_CRYPTO_3DES *context, UCHAR key[ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_3des_encrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -121,6 +125,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_key_set(NX_CRYPTO_3DES *context, UCHAR key[ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_3des_encrypt(NX_CRYPTO_3DES *context, UCHAR source[8], @@ -129,11 +137,11 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_encrypt(NX_CRYPTO_3DES *context, UCHAR sour /* ciphertext = EK3(DK2(EK1(plaintext))) I.e., DES encrypt with K1, DES decrypt with K2, then DES encrypt with K3. */ - _nx_crypto_des_encrypt(&context -> des_1, source, destination, length); + _nx_crypto_des_encrypt(&context -> des_1, source, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_decrypt(&context -> des_2, destination, destination, length); + _nx_crypto_des_decrypt(&context -> des_2, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_encrypt(&context -> des_3, destination, destination, length); + _nx_crypto_des_encrypt(&context -> des_3, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ /* Return successful completion. */ return(NX_CRYPTO_SUCCESS); @@ -145,7 +153,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_encrypt(NX_CRYPTO_3DES *context, UCHAR sour /* FUNCTION RELEASE */ /* */ /* _nx_crypto_3des_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -183,6 +191,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_encrypt(NX_CRYPTO_3DES *context, UCHAR sour /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR source[8], @@ -194,11 +206,11 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR sour plaintext = DK1(EK2(DK3(ciphertext))) I.e., decrypt with K3, encrypt with K2, then decrypt with K1. */ - _nx_crypto_des_decrypt(&context -> des_3, source, destination, length); + _nx_crypto_des_decrypt(&context -> des_3, source, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_encrypt(&context -> des_2, destination, destination, length); + _nx_crypto_des_encrypt(&context -> des_2, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ - _nx_crypto_des_decrypt(&context -> des_1, destination, destination, length); + _nx_crypto_des_decrypt(&context -> des_1, destination, destination, length); /* lgtm[cpp/weak-cryptographic-algorithm] */ /* Return successful completion. */ @@ -211,7 +223,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR sour /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_3des_init PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -249,6 +261,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_3des_decrypt(NX_CRYPTO_3DES *context, UCHAR sour /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_init(struct NX_CRYPTO_METHOD_STRUCT *method, @@ -281,7 +297,7 @@ NX_CRYPTO_3DES *triple_des_context_ptr; } - if (key_size_in_bits != NX_CRYPTO_3DES_KEY_LEN_IN_BITS) + if (key_size_in_bits != NX_CRYPTO_3DES_KEY_LEN_IN_BITS) /* lgtm[cpp/weak-cryptographic-algorithm] */ { return(NX_CRYPTO_UNSUPPORTED_KEY_SIZE); } @@ -289,7 +305,7 @@ NX_CRYPTO_3DES *triple_des_context_ptr; triple_des_context_ptr = (NX_CRYPTO_3DES *)(crypto_metadata); - _nx_crypto_3des_key_set(triple_des_context_ptr, key); + _nx_crypto_3des_key_set(triple_des_context_ptr, key); /* lgtm[cpp/weak-cryptographic-algorithm] */ return(NX_CRYPTO_SUCCESS); } @@ -358,7 +374,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_cleanup(VOID *crypto_metadata) /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_3des_operation PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -405,6 +421,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_cleanup(VOID *crypto_metadata) /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_3des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */ @@ -456,7 +476,7 @@ NX_CRYPTO_3DES *context; return(NX_CRYPTO_PTR_ERROR); } - if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_3DES_CBC) + if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_3DES_CBC) /* lgtm[cpp/weak-cryptographic-algorithm] */ { /* Incorrect method. */ return(NX_CRYPTO_INVALID_ALGORITHM); @@ -478,7 +498,7 @@ NX_CRYPTO_3DES *context; status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_decrypt, input, output, input_length_in_byte, - (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT: @@ -493,7 +513,7 @@ NX_CRYPTO_3DES *context; status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_encrypt, input, output, input_length_in_byte, - (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_DECRYPT_INITIALIZE: @@ -513,7 +533,7 @@ NX_CRYPTO_3DES *context; status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_decrypt, input, output, input_length_in_byte, - (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT_UPDATE: @@ -521,7 +541,7 @@ NX_CRYPTO_3DES *context; status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_3des_encrypt, input, output, input_length_in_byte, - (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT_CALCULATE: diff --git a/crypto_libraries/src/nx_crypto_aes.c b/crypto_libraries/src/nx_crypto_aes.c index fed6e737..16b4ae9f 100644 --- a/crypto_libraries/src/nx_crypto_aes.c +++ b/crypto_libraries/src/nx_crypto_aes.c @@ -37,7 +37,7 @@ The most significant byte is the result of {02} dot S, and the least significant byte is the result of {03} dot S[x,c]. */ -static const ULONG aes_encryption_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_encryption_table[256] = { 0xc66363a5, 0xf87c7c84, 0xee777799, 0xf67b7b8d, 0xfff2f20d, 0xd66b6bbd, 0xde6f6fb1, 0x91c5c554, 0x60303050, 0x02010103, 0xce6767a9, 0x562b2b7d, 0xe7fefe19, 0xb5d7d762, 0x4dababe6, 0xec76769a, @@ -85,7 +85,7 @@ static const ULONG aes_encryption_table[256] = The most significant byte is the result of {0e} dot S, and the least significant byte is the result of {0b} dot S[x,c]. */ -static const ULONG aes_decryption_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_decryption_table[256] = { 0x51f4a750, 0x7e416553, 0x1a17a4c3, 0x3a275e96, 0x3bab6bcb, 0x1f9d45f1, 0xacfa58ab, 0x4be30393, 0x2030fa55, 0xad766df6, 0x88cc7691, 0xf5024c25, 0x4fe5d7fc, 0xc52acbd7, 0x26354480, 0xb562a38f, @@ -130,7 +130,7 @@ static const ULONG aes_decryption_table[256] = The most significant byte is the result of {0e} dot S, and the least significant byte is the result of {0b} dot S[x,c]. */ -static const ULONG aes_inv_mix_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_inv_mix_table[256] = { 0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, @@ -179,7 +179,7 @@ static const ULONG aes_inv_mix_table[256] = of {03} dot S[x,c]. */ -static const ULONG aes_encryption_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_encryption_table[256] = { 0xa56363c6, 0x847c7cf8, 0x997777ee, 0x8d7b7bf6, 0x0df2f2ff, 0xbd6b6bd6, 0xb16f6fde, 0x54c5c591, 0x50303060, 0x03010102, 0xa96767ce, 0x7d2b2b56, 0x19fefee7, 0x62d7d7b5, 0xe6abab4d, 0x9a7676ec, @@ -226,7 +226,7 @@ static const ULONG aes_encryption_table[256] = The most significant byte is the result of {0e} dot S, and the least significant byte is the result of {0b} dot S[x,c]. */ -static const ULONG aes_decryption_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_decryption_table[256] = { 0x50a7f451, 0x5365417e, 0xc3a4171a, 0x965e273a, 0xcb6bab3b, 0xf1459d1f, 0xab58faac, 0x9303e34b, 0x55fa3020, 0xf66d76ad, 0x9176cc88, 0x254c02f5, 0xfcd7e54f, 0xd7cb2ac5, 0x80443526, 0x8fa362b5, @@ -272,7 +272,7 @@ static const ULONG aes_decryption_table[256] = of {0b} dot S[x,c]. */ -static const ULONG aes_inv_mix_table[256] = +NX_CRYPTO_AES_TABLE ULONG aes_inv_mix_table[256] = { 0x00000000, 0x0b0d090e, 0x161a121c, 0x1d171b12, 0x2c342438, 0x27392d36, 0x3a2e3624, 0x31233f2a, 0x58684870, 0x5365417e, 0x4e725a6c, 0x457f5362, 0x745c6c48, 0x7f516546, 0x62467e54, 0x694b775a, @@ -312,7 +312,7 @@ static const ULONG aes_inv_mix_table[256] = #endif /* S-Box. Refer to figure 7 on page 16, AES specification(Pub 197) */ -static const UCHAR sub_bytes_sbox[] = +NX_CRYPTO_AES_TABLE UCHAR sub_bytes_sbox[] = { 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, @@ -333,7 +333,7 @@ static const UCHAR sub_bytes_sbox[] = }; /* Inverse S-Box. Refer to figure 14 on page 22, AES specification(Pub 197) */ -static const UCHAR inverse_sub_bytes_sbox[] = +NX_CRYPTO_AES_TABLE UCHAR inverse_sub_bytes_sbox[] = { 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, @@ -355,7 +355,7 @@ static const UCHAR inverse_sub_bytes_sbox[] = /* Rcon array, used for key expansion. Refer to Appendix A on page 27, AES specification(Pub 197) */ -static const UCHAR aes_rcon_array[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; +NX_CRYPTO_AES_TABLE UCHAR aes_rcon_array[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36}; /* This array is generated using the nx_crypto_aes_multiply function, as powers of x in the AES polynomial field. The array is shifted such that the indexes line up so that x**1 is @@ -396,9 +396,9 @@ static const UCHAR aes_rcon_array[] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, #endif -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST extern UINT _nx_crypto_library_state; -#endif /* NX_CRYPTO_FIPS */ +#endif /* NX_CRYPTO_SELF_TEST */ /**************************************************************************/ /* Utility routines */ @@ -411,7 +411,7 @@ extern UINT _nx_crypto_library_state; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_aes_add_round_key PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -447,6 +447,10 @@ extern UINT _nx_crypto_library_state; /* 09-30-2020 Timothy Stapko Modified comment(s), updated */ /* constants and conditionals, */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP static VOID _nx_crypto_aes_add_round_key(NX_CRYPTO_AES *aes_ptr, UINT *round_key) @@ -1308,7 +1312,7 @@ UINT key_size; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_aes_key_expansion_inverse PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1346,6 +1350,9 @@ UINT key_size; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* moved inverse key expansion,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP static VOID _nx_crypto_aes_key_expansion_inverse(NX_CRYPTO_AES *aes_ptr) @@ -1404,6 +1411,9 @@ ULONG key; expanded_key[i + 2] = aes_ptr -> nx_crypto_aes_key_schedule[i + 2]; expanded_key[i + 3] = aes_ptr -> nx_crypto_aes_key_schedule[i + 3]; + /* Set the inverse key expansion flag. */ + aes_ptr -> nx_crypto_aes_inverse_key_expanded = 1; + #ifdef NX_SECURE_KEY_CLEAR key = 0; #endif /* NX_SECURE_KEY_CLEAR */ @@ -1443,7 +1453,7 @@ ULONG key; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_aes_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1491,6 +1501,9 @@ ULONG key; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* moved inverse key expansion,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_aes_decrypt(NX_CRYPTO_AES *aes_ptr, UCHAR *input, UCHAR *output, UINT length) @@ -1508,6 +1521,14 @@ UINT *buf; NX_CRYPTO_PARAMETER_NOT_USED(length); + /* If the flag is not set, we assume the inverse key expansion + table is not created yet. Call the routine to create one. */ + if(aes_ptr -> nx_crypto_aes_inverse_key_expanded == 0) + { + _nx_crypto_aes_key_expansion_inverse(aes_ptr); + } + + w = aes_ptr -> nx_crypto_aes_decrypt_key_schedule; v = aes_ptr -> nx_crypto_aes_key_schedule; @@ -1590,7 +1611,7 @@ UINT *buf; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_aes_key_set PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1629,6 +1650,9 @@ UINT *buf; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* moved inverse key expansion,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_aes_key_set(NX_CRYPTO_AES *aes_ptr, UCHAR *key, UINT key_size) @@ -1665,7 +1689,10 @@ UINT i; _nx_crypto_aes_key_expansion(aes_ptr); - _nx_crypto_aes_key_expansion_inverse(aes_ptr); + /* Move key_expansion_inverse into the decrypt logic. + No reason to build the inverse table if the application doesn't do decryption. */ + /* Clear the inverse key expansion flag; */ + aes_ptr -> nx_crypto_aes_inverse_key_expanded = 0; return(NX_CRYPTO_SUCCESS); } @@ -2140,7 +2167,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_aes_ccm_operation PORTABLE C */ -/* 6.1 */ +/* 6.x */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -2188,6 +2215,9 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Tiejun Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_aes_ccm_operation(UINT op, /* Encrypt, Decrypt, Authenticate */ @@ -2251,7 +2281,7 @@ UINT status; break; } - if (input_length_in_byte < (method -> nx_crypto_ICV_size_in_bits >> 3) || + if (input_length_in_byte < (ULONG)(method -> nx_crypto_ICV_size_in_bits >> 3) || output_length_in_byte < input_length_in_byte - (method -> nx_crypto_ICV_size_in_bits >> 3)) { status = NX_CRYPTO_INVALID_BUFFER_SIZE; diff --git a/crypto_libraries/src/nx_crypto_des.c b/crypto_libraries/src/nx_crypto_des.c index 00755055..2b0f9f7c 100644 --- a/crypto_libraries/src/nx_crypto_des.c +++ b/crypto_libraries/src/nx_crypto_des.c @@ -316,7 +316,7 @@ UINT round; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_des_encrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -355,6 +355,10 @@ UINT round; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* updated constants, */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_des_encrypt(NX_CRYPTO_DES *context, UCHAR source[8], UCHAR destination[8], UINT length) @@ -362,7 +366,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_des_encrypt(NX_CRYPTO_DES *context, UCHAR source NX_CRYPTO_PARAMETER_NOT_USED(length); /* Encrypt the block by supplying the encryption key set. */ - _nx_crypto_des_process_block(source, destination, context -> nx_des_encryption_keys); + _nx_crypto_des_process_block(source, destination, context -> nx_des_encryption_keys); /* lgtm[cpp/weak-cryptographic-algorithm] */ /* Return successful completion. */ return(NX_CRYPTO_SUCCESS); @@ -374,7 +378,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_des_encrypt(NX_CRYPTO_DES *context, UCHAR source /* FUNCTION RELEASE */ /* */ /* _nx_crypto_des_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -413,6 +417,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_des_encrypt(NX_CRYPTO_DES *context, UCHAR source /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* updated constants, */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_des_decrypt(NX_CRYPTO_DES *context, UCHAR source[8], UCHAR destination[8], UINT length) @@ -420,7 +428,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_des_decrypt(NX_CRYPTO_DES *context, UCHAR source NX_CRYPTO_PARAMETER_NOT_USED(length); /* Decrypt the block by supplying the decryption key set. */ - _nx_crypto_des_process_block(source, destination, context -> nx_des_decryption_keys); + _nx_crypto_des_process_block(source, destination, context -> nx_des_decryption_keys); /* lgtm[cpp/weak-cryptographic-algorithm] */ /* Return successful completion. */ return(NX_CRYPTO_SUCCESS); @@ -566,7 +574,7 @@ UINT round; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_des_init PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -604,6 +612,10 @@ UINT round; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_init(struct NX_CRYPTO_METHOD_STRUCT *method, @@ -623,7 +635,7 @@ NX_CRYPTO_DES *des_context_ptr; return(NX_CRYPTO_PTR_ERROR); } - if ((key_size_in_bits != NX_CRYPTO_DES_KEY_LEN_IN_BITS) || (crypto_metadata_size < sizeof(NX_CRYPTO_DES))) + if ((key_size_in_bits != NX_CRYPTO_DES_KEY_LEN_IN_BITS) || (crypto_metadata_size < sizeof(NX_CRYPTO_DES))) /* lgtm[cpp/weak-cryptographic-algorithm] */ { return(NX_CRYPTO_SIZE_ERROR); } @@ -636,7 +648,7 @@ NX_CRYPTO_DES *des_context_ptr; des_context_ptr = (NX_CRYPTO_DES *)(crypto_metadata); - _nx_crypto_des_key_set(des_context_ptr, key); + _nx_crypto_des_key_set(des_context_ptr, key); /* lgtm[cpp/weak-cryptographic-algorithm] */ return(NX_CRYPTO_SUCCESS); } @@ -705,7 +717,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_cleanup(VOID *crypto_metadata) /* FUNCTION RELEASE */ /* */ /* _nx_crypto_method_des_operation PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -752,6 +764,10 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_cleanup(VOID *crypto_metadata) /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_des_operation(UINT op, /* Encrypt, Decrypt, Authenticate */ @@ -803,7 +819,7 @@ NX_CRYPTO_DES *context; return(NX_CRYPTO_PTR_ERROR); } - if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_DES_CBC) + if (method -> nx_crypto_algorithm != NX_CRYPTO_ENCRYPTION_DES_CBC) /* lgtm[cpp/weak-cryptographic-algorithm] */ { /* Incorrect method. */ return(NX_CRYPTO_NOT_SUCCESSFUL); @@ -825,7 +841,7 @@ NX_CRYPTO_DES *context; status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_decrypt, input, output, input_length_in_byte, - (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT: @@ -840,7 +856,7 @@ NX_CRYPTO_DES *context; status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_encrypt, input, output, input_length_in_byte, - (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_DECRYPT_INITIALIZE: @@ -860,7 +876,7 @@ NX_CRYPTO_DES *context; status = _nx_crypto_cbc_decrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_decrypt, input, output, input_length_in_byte, - (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT_UPDATE: @@ -868,7 +884,7 @@ NX_CRYPTO_DES *context; status = _nx_crypto_cbc_encrypt(context, &(context -> nx_crypto_cbc_context), (UINT (*)(VOID *, UCHAR *, UCHAR *, UINT))_nx_crypto_des_encrypt, input, output, input_length_in_byte, - (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); + (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3)); /* lgtm[cpp/weak-cryptographic-algorithm] */ } break; case NX_CRYPTO_ENCRYPT_CALCULATE: diff --git a/crypto_libraries/src/nx_crypto_dh.c b/crypto_libraries/src/nx_crypto_dh.c index 27cef7ea..84d5bf48 100644 --- a/crypto_libraries/src/nx_crypto_dh.c +++ b/crypto_libraries/src/nx_crypto_dh.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_dh.h" -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST /* The Diffie-Hellman group 2 modulus. */ /* Modulus, in byte stream, be */ @@ -57,7 +57,7 @@ static const HN_UBASE _nx_dh_group_2_modulus[] = /* FUNCTION RELEASE */ /* */ /* _nx_crypto_dh_setup PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -108,6 +108,10 @@ static const HN_UBASE _nx_dh_group_2_modulus[] = /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_dh_setup(NX_CRYPTO_DH *dh_ptr, diff --git a/crypto_libraries/src/nx_crypto_ec.c b/crypto_libraries/src/nx_crypto_ec.c index e033e125..530b777e 100644 --- a/crypto_libraries/src/nx_crypto_ec.c +++ b/crypto_libraries/src/nx_crypto_ec.c @@ -685,7 +685,7 @@ NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_secp521r1 = _nx_crypto_ec_fp_projective_multiple, _nx_crypto_ec_secp521r1_reduce }; -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST static NX_CRYPTO_CONST NX_CRYPTO_EC *_nx_crypto_ec_named_curves[] = { &_nx_crypto_ec_secp192r1, @@ -715,8 +715,8 @@ static NX_CRYPTO_CONST NX_CRYPTO_EC *_nx_crypto_ec_named_curves[] = /* */ /* OUTPUT */ /* */ -/* NX_CRYPTO_TRUE Point is infinite */ -/* NX_CRYPTO_FALSE Point is not infinite */ +/* NX_CRYPTO_TRUE Point is infinite */ +/* NX_CRYPTO_FALSE Point is not infinite */ /* */ /* CALLS */ /* */ @@ -1126,7 +1126,7 @@ UINT buffer_size; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_secp192r1_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1176,6 +1176,9 @@ UINT buffer_size; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memmove use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp192r1_reduce(NX_CRYPTO_EC *curve, @@ -1184,7 +1187,7 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp192r1_reduce(NX_CRYPTO_EC *curve, { NX_CRYPTO_HUGE_NUMBER temp; UINT *data; -UINT *buffer; +HN_UBASE rev1; UINT size = 0; UINT compare_value; @@ -1202,8 +1205,6 @@ UINT compare_value; NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, 36); data = (UINT *)(((ULONG)scratch + 3) & (ULONG) ~3); - scratch += (64 >> HN_SIZE_SHIFT); - buffer = (UINT *)scratch; /* c= (c5,...,c2,c1,c0), ci is a 64-bit word */ _nx_crypto_huge_number_extract(value, (UCHAR *)data, 48, &size); @@ -1219,19 +1220,19 @@ UINT compare_value; _nx_crypto_huge_number_setup(value, (UCHAR *)data + 24, 24); /* s2 = (0,c3,c3) */ - NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, rev1, 0, 0, data[4], data[5], data[4], data[5]); _nx_crypto_huge_number_add(value, &temp); /* s3 = (c4,c4,0) */ - NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, rev1, data[2], data[3], data[2], data[3], 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s4 = (c5,c5,c5) */ - NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP192R1_DATA_SETUP(&temp, rev1, data[0], data[1], data[0], data[1], data[0], data[1]); _nx_crypto_huge_number_add(value, &temp); @@ -1259,7 +1260,7 @@ UINT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_secp224r1_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1312,6 +1313,9 @@ UINT compare_value; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memmove use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp224r1_reduce(NX_CRYPTO_EC *curve, @@ -1320,7 +1324,7 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp224r1_reduce(NX_CRYPTO_EC *curve, { NX_CRYPTO_HUGE_NUMBER temp; UINT *data; -UINT *buffer; +HN_UBASE rev1; UINT size = 0; UINT compare_value; @@ -1338,8 +1342,6 @@ UINT compare_value; NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, 36); data = (UINT *)(((ULONG)scratch + 3) & (ULONG) ~3); - scratch += (64 >> HN_SIZE_SHIFT); - buffer = (UINT *)scratch; /* c= (c13,...,c2,c1,c0), ci is a 32-bit word */ _nx_crypto_huge_number_extract(value, (UCHAR *)data, 56, &size); @@ -1355,25 +1357,25 @@ UINT compare_value; _nx_crypto_huge_number_setup(value, (UCHAR *)data + 28, 28); /* s2 = (c10,c9,c8,c7,0,0,0) */ - NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, rev1, data[3], data[4], data[5], data[6], 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s3 = (0,c13,c12,c11,0,0,0) */ - NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, rev1, 0, data[0], data[1], data[2], 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s4 = (c13,c12,c11,c10,c9,c8,c7) */ - NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, rev1, data[0], data[1], data[2], data[3], data[4], data[5], data[6]); _nx_crypto_huge_number_subtract(value, &temp); /* s5 = (0,0,0,0,c13,c12,c11) */ - NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP224R1_DATA_SETUP(&temp, rev1, 0, 0, 0, 0, data[0], data[1], data[2]); _nx_crypto_huge_number_subtract(value, &temp); @@ -1401,7 +1403,7 @@ UINT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_secp256r1_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1454,6 +1456,9 @@ UINT compare_value; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memmove use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp256r1_reduce(NX_CRYPTO_EC *curve, @@ -1462,7 +1467,8 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp256r1_reduce(NX_CRYPTO_EC *curve, { NX_CRYPTO_HUGE_NUMBER temp; UINT *data; -UINT *buffer; +HN_UBASE rev1; +HN_UBASE rev2; UINT size = 0; UINT compare_value; @@ -1480,8 +1486,6 @@ UINT compare_value; NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, 36); data = (UINT *)(((ULONG)scratch + 3) & (ULONG) ~3); - scratch += (64 >> HN_SIZE_SHIFT); - buffer = (UINT *)scratch; /* c= (c15,...,c2,c1,c0), ci is a 32-bit word */ _nx_crypto_huge_number_extract(value, (UCHAR *)data, 64, &size); @@ -1497,51 +1501,49 @@ UINT compare_value; _nx_crypto_huge_number_setup(value, (UCHAR *)data + 32, 32); /* s2 = (c15,c14,c13,c12,c11,0,0,0) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, - data[0], data[1], data[2], data[3], - data[4], 0, 0, 0); - _nx_crypto_huge_number_shift_left(&temp, 1); + NX_CRYPTO_EC_SECP256R1_DATA_SETUP_LS1(&temp, rev1, rev2, + data[0], data[1], data[2], data[3], + data[4], 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s3 = (0,c15,c14,c13,c12,0,0,0) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, - 0, data[0], data[1], data[2], - data[3], 0, 0, 0); - _nx_crypto_huge_number_shift_left(&temp, 1); + NX_CRYPTO_EC_SECP256R1_DATA_SETUP_LS1(&temp, rev1, rev2, + 0, data[0], data[1], data[2], + data[3], 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s4 = (c15,c14,0,0,0,c10,c9,c8) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[0], data[1], 0, 0, 0, data[5], data[6], data[7]); _nx_crypto_huge_number_add(value, &temp); /* s5 = (c8,c13,c15,c14,c13,c11,c10,c9) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[7], data[2], data[0], data[1], data[2], data[4], data[5], data[6]); _nx_crypto_huge_number_add(value, &temp); /* s6 = (c10,c8,0,0,0,c13,c12,c11) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[5], data[7], 0, 0, 0, data[2], data[3], data[4]); _nx_crypto_huge_number_subtract(value, &temp); /* s7 = (c11,c9,0,0,c15,c14,c13,c12) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[4], data[6], 0, 0, data[0], data[1], data[2], data[3]); _nx_crypto_huge_number_subtract(value, &temp); /* s8 = (c12,0,c10,c9,c8,c15,c14,c13) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[3], 0, data[5], data[6], data[7], data[0], data[1], data[2]); _nx_crypto_huge_number_subtract(value, &temp); /* s9 = (c13,0,c11,c10,c9,0,c15,c14) */ - NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP256R1_DATA_SETUP(&temp, rev1, data[2], 0, data[4], data[5], data[6], 0, data[0], data[1]); _nx_crypto_huge_number_subtract(value, &temp); @@ -1569,7 +1571,7 @@ UINT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_secp384r1_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1619,6 +1621,9 @@ UINT compare_value; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memmove use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp384r1_reduce(NX_CRYPTO_EC *curve, @@ -1627,7 +1632,8 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_secp384r1_reduce(NX_CRYPTO_EC *curve, { NX_CRYPTO_HUGE_NUMBER temp; UINT *data; -UINT *buffer; +HN_UBASE rev1; +HN_UBASE rev2; UINT size = 0; UINT compare_value; @@ -1642,11 +1648,9 @@ UINT compare_value; return; } - NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, 48); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&temp, scratch, 52); data = (UINT *)(((ULONG)scratch + 3) & (ULONG) ~3); - scratch += (96 >> HN_SIZE_SHIFT); - buffer = (UINT *)scratch; /* c= (c23,...,c2,c1,c0), ci is a 32-bit word */ _nx_crypto_huge_number_extract(value, (UCHAR *)data, 96, &size); @@ -1662,10 +1666,9 @@ UINT compare_value; _nx_crypto_huge_number_setup(value, (UCHAR *)data + 48, 48); /* s2 = (0,0,0,0,0,c23,c22,c21,0,0,0,0) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, - 0, 0, 0, 0, 0, data[0], - data[1], data[2], 0, 0, 0, 0); - _nx_crypto_huge_number_shift_left(&temp, 1); + NX_CRYPTO_EC_SECP384R1_DATA_SETUP_LS1(&temp, rev1, rev2, + 0, 0, 0, 0, 0, data[0], + data[1], data[2], 0, 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s3 = (c23,c22,c21,c20,c19,c18,c17,c16,c15,c14,c13,c12) */ @@ -1673,48 +1676,48 @@ UINT compare_value; _nx_crypto_huge_number_add(value, &temp); /* s4 = (c20,c19,c18,c17,c16,c15,c14,c13,c12,c23,c22,c21) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[0], data[1], data[2]); _nx_crypto_huge_number_add(value, &temp); /* s5 = (c19,c18,c17,c16,c15,c14,c13,c12,c20,0,c23,0) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[3], 0, data[0], 0); _nx_crypto_huge_number_add(value, &temp); /* s6 = (0,0,0,0,c23,c22,c21,c20,0,0,0,0) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, 0, 0, 0, 0, data[0], data[1], data[2], data[3], 0, 0, 0, 0); _nx_crypto_huge_number_add(value, &temp); /* s7 = (0,0,0,0,0,0,c23,c22,c21,0,0,c20) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, 0, 0, 0, 0, 0, 0, data[0], data[1], data[2], 0, 0, data[3]); _nx_crypto_huge_number_add(value, &temp); /* s8 = (c22,c21,c20,c19,c18,c17,c16,c15,c14,c13,c12,c23) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, data[1], data[2], data[3], data[4], data[5], data[6], data[7], data[8], data[9], data[10], data[11], data[0]); _nx_crypto_huge_number_subtract(value, &temp); /* s9 = (0,0,0,0,0,0,0,c23,c22,c21,c20,0) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, 0, 0, 0, 0, 0, 0, 0, data[0], data[1], data[2], data[3], 0); _nx_crypto_huge_number_subtract(value, &temp); /* s10 = (0,0,0,0,0,0,0,c23,c23,0,0,0) */ - NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, buffer, + NX_CRYPTO_EC_SECP384R1_DATA_SETUP(&temp, rev1, 0, 0, 0, 0, 0, 0, 0, data[0], data[0], 0, 0, 0); _nx_crypto_huge_number_subtract(value, &temp); @@ -1863,7 +1866,7 @@ UINT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_add_digit_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1907,9 +1910,13 @@ UINT compare_value; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP VOID _nx_crypto_ec_add_digit_reduce(NX_CRYPTO_EC *curve, NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit, @@ -1994,7 +2001,7 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_subtract_digit_reduce(NX_CRYPTO_EC *curve, /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_fp_reduce PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -2028,9 +2035,13 @@ NX_CRYPTO_KEEP VOID _nx_crypto_ec_subtract_digit_reduce(NX_CRYPTO_EC *curve, /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP VOID _nx_crypto_ec_fp_reduce(NX_CRYPTO_EC *curve, NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE *scratch) @@ -3288,7 +3299,7 @@ NX_CRYPTO_EC_POINT public_key; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_precomputation PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -3330,9 +3341,13 @@ NX_CRYPTO_EC_POINT public_key; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP VOID _nx_crypto_ec_precomputation(NX_CRYPTO_EC *curve, UINT window_width, UINT bits, @@ -3474,7 +3489,7 @@ UINT i, j; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_fixed_output PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -3510,9 +3525,13 @@ UINT i, j; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP VOID _nx_crypto_ec_fixed_output(NX_CRYPTO_EC *curve, INT (*output)(const CHAR *format, ...), const CHAR *tab, @@ -3721,7 +3740,7 @@ const CHAR *array_name[] = {"", "_2e"}; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_get_named_curve PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -3755,9 +3774,13 @@ const CHAR *array_name[] = {"", "_2e"}; /* 09-30-2020 Timothy Stapko Modified comment(s), updated */ /* constants, resulting */ /* in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST NX_CRYPTO_KEEP UINT _nx_crypto_ec_get_named_curve(NX_CRYPTO_EC **curve, UINT curve_id) { UINT i; @@ -4217,7 +4240,7 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_secp521r1_operation(UINT op, /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ec_validate_public_key PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -4255,6 +4278,9 @@ NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_secp521r1_operation(UINT op, /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ #ifndef NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION @@ -4267,9 +4293,10 @@ NX_CRYPTO_HUGE_NUMBER temp; NX_CRYPTO_HUGE_NUMBER right; UINT compare_value; UINT buffer_size = chosen_curve -> nx_crypto_ec_n.nx_crypto_huge_buffer_size; -NX_CRYPTO_EC_POINT pt; HN_UBASE *scratch2 = scratch; + NX_CRYPTO_PARAMETER_NOT_USED(partial); + /* 1. Verify Q is not the point at infinity. */ if(_nx_crypto_ec_point_is_infinite(public_key)) { @@ -4330,6 +4357,8 @@ HN_UBASE *scratch2 = scratch; verification in step 1, ensures that the public key is in the correct range in the correct EC subgroup; that is, it is in the correct EC subgroup and is not the identity element O.) */ + /* Removed this validation as h is 1 for all the software supported curves and nQ = O + is implied by the checks in step 2 and 3. if (!partial) { NX_CRYPTO_EC_POINT_INITIALIZE(&pt, NX_CRYPTO_EC_POINT_AFFINE, scratch, buffer_size); @@ -4339,7 +4368,731 @@ HN_UBASE *scratch2 = scratch; return(NX_CRYPTO_INVALID_KEY); } } + */ return(NX_CRYPTO_SUCCESS); } #endif /* NX_CRYPTO_ECC_DISABLE_KEY_VALIDATION */ + +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + +/* x25519 */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x25519_p[] = +{ + + /* p = 7fffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffed */ + HN_ULONG_TO_UBASE(0xFFFFFFED), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0x7FFFFFFF), +}; + +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x25519_gx[] = +{ + + /* U(P) = 9 */ + HN_ULONG_TO_UBASE(0x00000009) +}; + + +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x25519_h[] = +{ + + /* h = 08 */ + HN_ULONG_TO_UBASE(0x00000008) +}; + +/* x448 */ +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x448_p[] = +{ + + /* p = ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff fffffffe ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff ffffffff */ + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFE), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), + HN_ULONG_TO_UBASE(0xFFFFFFFF), HN_ULONG_TO_UBASE(0xFFFFFFFF), +}; + +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x448_gx[] = +{ + + /* U(P) = 5 */ + HN_ULONG_TO_UBASE(0x00000005) +}; + + +static NX_CRYPTO_CONST HN_UBASE _nx_crypto_ec_x448_h[] = +{ + + /* h = 04 */ + HN_ULONG_TO_UBASE(0x00000004) +}; + + +NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_x25519 = +{ + "x25519", + NX_CRYPTO_EC_X25519, + 5, + 255, + { + .fp = + { + (HN_UBASE *)_nx_crypto_ec_x25519_p, + sizeof(_nx_crypto_ec_x25519_p) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x25519_p), + (UINT)NX_CRYPTO_FALSE + } + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + { + NX_CRYPTO_EC_POINT_AFFINE, + { + (HN_UBASE *)_nx_crypto_ec_x25519_gx, + sizeof(_nx_crypto_ec_x25519_gx) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x25519_gx), + (UINT)NX_CRYPTO_FALSE + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u} + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + { + (HN_UBASE *)_nx_crypto_ec_x25519_h, + sizeof(_nx_crypto_ec_x25519_h) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x25519_h), + (UINT)NX_CRYPTO_FALSE + }, + (NX_CRYPTO_EC_FIXED_POINTS *)NX_CRYPTO_NULL, + NX_CRYPTO_NULL, + NX_CRYPTO_NULL, + _nx_crypto_ec_x25519_448_multiple, + NX_CRYPTO_NULL +}; + +NX_CRYPTO_CONST NX_CRYPTO_EC _nx_crypto_ec_x448 = +{ + "x448", + NX_CRYPTO_EC_X448, + 5, + 448, + { + .fp = + { + (HN_UBASE *)_nx_crypto_ec_x448_p, + sizeof(_nx_crypto_ec_x448_p) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x448_p), + (UINT)NX_CRYPTO_FALSE + } + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + { + NX_CRYPTO_EC_POINT_AFFINE, + { + (HN_UBASE *)_nx_crypto_ec_x448_gx, + sizeof(_nx_crypto_ec_x448_gx) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x448_gx), + (UINT)NX_CRYPTO_FALSE + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u} + }, + {(HN_UBASE *)NX_CRYPTO_NULL, 0u, 0u, 0u}, + { + (HN_UBASE *)_nx_crypto_ec_x448_h, + sizeof(_nx_crypto_ec_x448_h) >> HN_SIZE_SHIFT, + sizeof(_nx_crypto_ec_x448_h), + (UINT)NX_CRYPTO_FALSE + }, + (NX_CRYPTO_EC_FIXED_POINTS *)NX_CRYPTO_NULL, + NX_CRYPTO_NULL, + NX_CRYPTO_NULL, + _nx_crypto_ec_x25519_448_multiple, + NX_CRYPTO_NULL +}; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ec_x25519_448_multiple PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs the scalar multiplication on X25519 and X448 */ +/* curves. */ +/* */ +/* INPUT */ +/* */ +/* curve Pointer to curve */ +/* u U coordinate */ +/* k Scalar */ +/* r Result */ +/* scratch Pointer to scratch buffer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* NX_CRYPTO_EC_POINT_INITIALIZE Initialize EC point */ +/* NX_CRYPTO_HUGE_NUMBER_COPY Copy huge number */ +/* _nx_crypto_ec_cswap Swap two huge numbers */ +/* _nx_crypto_huge_number_add Addition for huge numbers */ +/* _nx_crypto_huge_number_subtract Calculate subtraction for */ +/* huge numbers */ +/* _nx_crypto_huge_number_modulus Perform a modulus operation */ +/* _nx_crypto_huge_number_multiply Multiply two huge numbers */ +/* _nx_crypto_huge_number_square Compute the square of a value */ +/* _nx_crypto_huge_number_inverse_modulus_prime */ +/* Perform an inverse modulus */ +/* operation for prime number */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curve, */ +/* resulting in version 6.1.12 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP VOID _nx_crypto_ec_x25519_448_multiple(NX_CRYPTO_EC* curve, + NX_CRYPTO_EC_POINT* u, + NX_CRYPTO_HUGE_NUMBER* k, + NX_CRYPTO_EC_POINT* r, + HN_UBASE* scratch) +{ +NX_CRYPTO_HUGE_NUMBER k_2; +NX_CRYPTO_HUGE_NUMBER x_1; +NX_CRYPTO_HUGE_NUMBER x_2; +NX_CRYPTO_HUGE_NUMBER z_2; +NX_CRYPTO_HUGE_NUMBER x_3; +NX_CRYPTO_HUGE_NUMBER z_3; +NX_CRYPTO_HUGE_NUMBER t_1; +NX_CRYPTO_HUGE_NUMBER t_2; +INT t; +UINT k_t; +UINT swap; +UINT clen; +ULONG a24; +HN_UBASE* k_buf; + + clen = (curve -> nx_crypto_ec_bits + 7) >> 3; + + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&k_2, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&x_1, scratch, clen); + clen = clen << 1; + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&x_2, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&z_2, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&x_3, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&z_3, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&t_1, scratch, clen); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&t_2, scratch, clen); + + NX_CRYPTO_HUGE_NUMBER_COPY(&k_2, k); + NX_CRYPTO_HUGE_NUMBER_COPY(&x_1, &u -> nx_crypto_ec_point_x); + + if (curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519) + { + /* x25519 */ + x_1.nx_crypto_huge_number_data[7] &= 0x7FFFFFFF; + + k_buf = k_2.nx_crypto_huge_number_data; + + k_buf[0] &= 0xFFFFFFF8; + k_buf[7] &= 0x7FFFFFFF; + k_buf[7] |= 0x40000000; + a24 = 121665; + } + else + { + /* x448 */ + + k_buf = k_2.nx_crypto_huge_number_data; + + k_buf[0] &= 0xFFFFFFFC; + k_buf[13] |= 0x80000000; + a24 = 39081; + } + + NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(&x_2, 1); + NX_CRYPTO_HUGE_NUMBER_COPY(&x_3, &x_1); + NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(&z_3, 1); + + swap = 0; + + for (t = (INT)(curve -> nx_crypto_ec_bits - 1); t >= 0; t--) + { + k_t = 1 & (k_buf[t >> 5] >> (t & 31)); + swap ^= k_t; + _nx_crypto_ec_cswap(swap, &x_2, &x_3); + _nx_crypto_ec_cswap(swap, &z_2, &z_3); + swap = k_t; + + /* A = x_2 + z_2 */ + NX_CRYPTO_HUGE_NUMBER_COPY(&t_1, &x_2); + _nx_crypto_huge_number_add(&t_1, &z_2); + _nx_crypto_huge_number_modulus(&t_1, &curve->nx_crypto_ec_field.fp); + + /* B = x_2 - z_2 */ + _nx_crypto_huge_number_subtract(&x_2, &z_2); + + /* C = x_3 + z_3 */ + NX_CRYPTO_HUGE_NUMBER_COPY(&t_2, &x_3); + _nx_crypto_huge_number_add(&t_2, &z_3); + + /* D = x_3 - z_3 */ + _nx_crypto_huge_number_subtract(&x_3, &z_3); + + /* DA = D * A */ + _nx_crypto_huge_number_multiply(&x_3, &t_1, &z_3); + _nx_crypto_huge_number_modulus(&z_3, &curve -> nx_crypto_ec_field.fp); + + /* CB = C * B */ + _nx_crypto_huge_number_multiply(&x_2, &t_2, &z_2); + _nx_crypto_huge_number_modulus(&z_2, &curve -> nx_crypto_ec_field.fp); + + /* t_2 = DA + CB */ + NX_CRYPTO_HUGE_NUMBER_COPY(&t_2, &z_2); + _nx_crypto_huge_number_add(&t_2, &z_3); + _nx_crypto_huge_number_modulus(&t_2, &curve->nx_crypto_ec_field.fp); + + /* z_3 = DA - CB */ + _nx_crypto_huge_number_subtract(&z_3, &z_2); + + /* x_3 = (DA + CB)^2 */ + _nx_crypto_huge_number_square(&t_2, &x_3); + _nx_crypto_huge_number_modulus(&x_3, &curve -> nx_crypto_ec_field.fp); + + /* t_2 = (DA - CB)^2 */ + _nx_crypto_huge_number_square(&z_3, &t_2); + _nx_crypto_huge_number_modulus(&t_2, &curve -> nx_crypto_ec_field.fp); + + /* z_3 = x_1 * (DA - CB)^2 */ + _nx_crypto_huge_number_multiply(&t_2, &x_1, &z_3); + _nx_crypto_huge_number_modulus(&z_3, &curve -> nx_crypto_ec_field.fp); + + /* AA = A^2 */ + _nx_crypto_huge_number_square(&t_1, &z_2); + _nx_crypto_huge_number_modulus(&z_2, &curve -> nx_crypto_ec_field.fp); + + /* BB = B^2 */ + _nx_crypto_huge_number_square(&x_2, &t_1); + _nx_crypto_huge_number_modulus(&t_1, &curve -> nx_crypto_ec_field.fp); + + /* E = AA - BB */ + NX_CRYPTO_HUGE_NUMBER_COPY(&t_2, &z_2); + _nx_crypto_huge_number_subtract(&t_2, &t_1); + + /* x_2 = AA * BB */ + _nx_crypto_huge_number_multiply(&z_2, &t_1, &x_2); + _nx_crypto_huge_number_modulus(&x_2, &curve -> nx_crypto_ec_field.fp); + + /* z_2 = E * (AA + a24 * E) */ + _nx_crypto_huge_number_multiply_digit(&t_2, a24, &t_1); + + _nx_crypto_huge_number_add(&t_1, &z_2); + _nx_crypto_huge_number_modulus(&t_1, &curve -> nx_crypto_ec_field.fp); + + _nx_crypto_huge_number_multiply(&t_1, &t_2, &z_2); + _nx_crypto_huge_number_modulus(&z_2, &curve -> nx_crypto_ec_field.fp); + + } + + _nx_crypto_ec_cswap(swap, &x_2, &x_3); + _nx_crypto_ec_cswap(swap, &z_2, &z_3); + + /* Return x_2 * (z_2^(p - 2)) = x_2 * (z_2^-1) */ + _nx_crypto_huge_number_inverse_modulus_prime(&z_2, &curve -> nx_crypto_ec_field.fp, &t_1, scratch); + _nx_crypto_huge_number_multiply(&x_2, &t_1, &r -> nx_crypto_ec_point_x); + _nx_crypto_huge_number_modulus(&r -> nx_crypto_ec_point_x, &curve -> nx_crypto_ec_field.fp); + +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ec_cswap PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function performs conditional swap of two huge number in */ +/* constant time. */ +/* */ +/* INPUT */ +/* */ +/* swap Swap condition */ +/* h1 First huge number */ +/* h2 Second huge number */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_ec_x25519_448_multiple Scalar multiplication */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP VOID _nx_crypto_ec_cswap(UINT swap, NX_CRYPTO_HUGE_NUMBER *h1, NX_CRYPTO_HUGE_NUMBER *h2) +{ +UINT i; +HN_UBASE hswap = (HN_UBASE)(0 - swap); +HN_UBASE dummy; + + + for (i = 0; i < (h1 -> nx_crypto_huge_buffer_size >> HN_SIZE_SHIFT); i++) + { + dummy = hswap & (h1 -> nx_crypto_huge_number_data[i] ^ h2 -> nx_crypto_huge_number_data[i]); + h1 -> nx_crypto_huge_number_data[i] = h1 -> nx_crypto_huge_number_data[i] ^ dummy; + h2 -> nx_crypto_huge_number_data[i] = h2 -> nx_crypto_huge_number_data[i] ^ dummy; + } + + i = hswap & (h1 -> nx_crypto_huge_number_size ^ h2 -> nx_crypto_huge_number_size); + h1 -> nx_crypto_huge_number_size ^= i; + h2 -> nx_crypto_huge_number_size ^= i; + + i = hswap & (h1 -> nx_crypto_huge_number_is_negative ^ h2 -> nx_crypto_huge_number_is_negative); + h1 -> nx_crypto_huge_number_is_negative ^= i; + h2 -> nx_crypto_huge_number_is_negative ^= i; + +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_method_ec_x25519_operation PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the x25519 curve. */ +/* */ +/* INPUT */ +/* */ +/* op Operation */ +/* handle Crypto handle */ +/* method Cryption Method Object */ +/* key Encryption Key */ +/* key_size_in_bits Key size in bits */ +/* input Input data */ +/* input_length_in_byte Input data size */ +/* iv_ptr Initial vector */ +/* output Output buffer */ +/* output_length_in_byte Output buffer size */ +/* crypto_metadata Metadata area */ +/* crypto_metadata_size Metadata area size */ +/* packet_ptr Pointer to packet */ +/* nx_crypto_hw_process_callback Callback function pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_x25519_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *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 *, UINT)) +{ + NX_CRYPTO_PARAMETER_NOT_USED(handle); + NX_CRYPTO_PARAMETER_NOT_USED(method); + NX_CRYPTO_PARAMETER_NOT_USED(key); + NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits); + NX_CRYPTO_PARAMETER_NOT_USED(input); + NX_CRYPTO_PARAMETER_NOT_USED(input_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(output); + NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata_size); + NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback); + + if (op != NX_CRYPTO_EC_CURVE_GET) + { + return(NX_CRYPTO_NOT_SUCCESSFUL); + } + + *((NX_CRYPTO_EC **)output) = (NX_CRYPTO_EC *)&_nx_crypto_ec_x25519; + + return(NX_CRYPTO_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_method_ec_x448_operation PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the x448 curve. */ +/* */ +/* INPUT */ +/* */ +/* op Operation */ +/* handle Crypto handle */ +/* method Cryption Method Object */ +/* key Encryption Key */ +/* key_size_in_bits Key size in bits */ +/* input Input data */ +/* input_length_in_byte Input data size */ +/* iv_ptr Initial vector */ +/* output Output buffer */ +/* output_length_in_byte Output buffer size */ +/* crypto_metadata Metadata area */ +/* crypto_metadata_size Metadata area size */ +/* packet_ptr Pointer to packet */ +/* nx_crypto_hw_process_callback Callback function pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 07-29-2022 Yuxin Zhou Initial Version 6.1.12 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_method_ec_x448_operation(UINT op, + VOID *handle, + struct NX_CRYPTO_METHOD_STRUCT *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 *, UINT)) +{ + NX_CRYPTO_PARAMETER_NOT_USED(handle); + NX_CRYPTO_PARAMETER_NOT_USED(method); + NX_CRYPTO_PARAMETER_NOT_USED(key); + NX_CRYPTO_PARAMETER_NOT_USED(key_size_in_bits); + NX_CRYPTO_PARAMETER_NOT_USED(input); + NX_CRYPTO_PARAMETER_NOT_USED(input_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(iv_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(output); + NX_CRYPTO_PARAMETER_NOT_USED(output_length_in_byte); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata); + NX_CRYPTO_PARAMETER_NOT_USED(crypto_metadata_size); + NX_CRYPTO_PARAMETER_NOT_USED(packet_ptr); + NX_CRYPTO_PARAMETER_NOT_USED(nx_crypto_hw_process_callback); + + if (op != NX_CRYPTO_EC_CURVE_GET) + { + return(NX_CRYPTO_NOT_SUCCESSFUL); + } + + *((NX_CRYPTO_EC **)output) = (NX_CRYPTO_EC *)&_nx_crypto_ec_x448; + + return(NX_CRYPTO_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ec_key_pair_generation_x25519_448 PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function generates an elliptic curve key pair. */ +/* */ +/* INPUT */ +/* */ +/* curve Pointer to curve */ +/* g Base point g */ +/* private_key Private key generated */ +/* public_key Public key generated */ +/* scratch Pointer to scratch buffer */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* NX_CRYPTO_RBG Generate random huge number */ +/* [nx_crypto_ec_multiple] Perform multiplication for EC */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_ecdh_setup_x25519_448 Setup ECDH local key pair */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curve, */ +/* resulting in version 6.1.12 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ec_key_pair_generation_x25519_448(NX_CRYPTO_EC *curve, + NX_CRYPTO_EC_POINT *g, + NX_CRYPTO_HUGE_NUMBER *private_key, + NX_CRYPTO_EC_POINT *public_key, + HN_UBASE *scratch) +{ +UINT status; +UINT buffer_size = (curve -> nx_crypto_ec_bits + 7) >> 3; + + /* Get random number with specified length. */ + status = NX_CRYPTO_RBG(buffer_size << 3, (UCHAR*)private_key -> nx_crypto_huge_number_data); + + if (status) + { + return(status); + } + + private_key -> nx_crypto_huge_number_size = buffer_size >> HN_SIZE_SHIFT; + + /* Q = dG */ + curve -> nx_crypto_ec_multiple(curve, g, private_key, public_key, scratch); + + return(NX_CRYPTO_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ec_extract_fixed_size_le PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function extracts huge number in little-endian order to a */ +/* buffer with fixed size. */ +/* */ +/* INPUT */ +/* */ +/* number Huge number */ +/* byte_stream Output buffer */ +/* byte_stream_size Size of output buffer */ +/* */ +/* OUTPUT */ +/* */ +/* Status Operation result status */ +/* */ +/* CALLS */ +/* */ +/* NX_CRYPTO_MEMSET Copy the number data memory */ +/* NX_CRYPTO_MEMSET Set the memory */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_ecdh_setup_x25519_448 Setup ECDH local key pair */ +/* _nx_crypto_ecdh_compute_secret_x25519_448 */ +/* Compute ECDH shared secret */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ec_extract_fixed_size_le(NX_CRYPTO_HUGE_NUMBER *number, + UCHAR *byte_stream, UINT byte_stream_size) +{ +UINT number_size = number -> nx_crypto_huge_number_size << HN_SIZE_SHIFT; + + if (number_size > byte_stream_size) + { + + /* User byte stream buffer too small. */ + return(NX_CRYPTO_SIZE_ERROR); + } + + NX_CRYPTO_MEMCPY(byte_stream, number -> nx_crypto_huge_number_data, number_size); /* Use case of memcpy is verified. */ + + if (byte_stream_size > number_size) + { + NX_CRYPTO_MEMSET(&byte_stream[number_size], 0, byte_stream_size - number_size); + } + + return(NX_CRYPTO_SUCCESS); +} +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ diff --git a/crypto_libraries/src/nx_crypto_ecdh.c b/crypto_libraries/src/nx_crypto_ecdh.c index 0375847a..36826cde 100644 --- a/crypto_libraries/src/nx_crypto_ecdh.c +++ b/crypto_libraries/src/nx_crypto_ecdh.c @@ -701,12 +701,27 @@ NX_CRYPTO_EXTENDED_OUTPUT { /* Setup local key pair. */ extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output; - status = _nx_crypto_ecdh_setup(ecdh, - extended_output -> nx_crypto_extended_output_data, - extended_output -> nx_crypto_extended_output_length_in_byte, - &extended_output -> nx_crypto_extended_output_actual_size, - ecdh -> nx_crypto_ecdh_curve, - ecdh -> nx_crypto_ecdh_scratch_buffer); +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 || + ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448) + { + status = _nx_crypto_ecdh_setup_x25519_448(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size, + ecdh -> nx_crypto_ecdh_curve, + ecdh -> nx_crypto_ecdh_scratch_buffer); + } + else +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + { + status = _nx_crypto_ecdh_setup(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size, + ecdh -> nx_crypto_ecdh_curve, + ecdh -> nx_crypto_ecdh_scratch_buffer); + } } else if (op == NX_CRYPTO_DH_KEY_PAIR_IMPORT) { @@ -715,31 +730,80 @@ NX_CRYPTO_EXTENDED_OUTPUT return(NX_CRYPTO_PTR_ERROR); } - /* Import local key pair. */ - status = _nx_crypto_ecdh_key_pair_import(ecdh, ecdh -> nx_crypto_ecdh_curve, - key, (key_size_in_bits >> 3), - input, input_length_in_byte); +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 || + ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448) + { + + /* Import local key pair. */ + status = _nx_crypto_ecdh_key_pair_import_x25519_448(ecdh, ecdh -> nx_crypto_ecdh_curve, + key, (key_size_in_bits >> 3), + input, input_length_in_byte); + } + else +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + { + + /* Import local key pair. */ + status = _nx_crypto_ecdh_key_pair_import(ecdh, ecdh -> nx_crypto_ecdh_curve, + key, (key_size_in_bits >> 3), + input, input_length_in_byte); + } } else if (op == NX_CRYPTO_DH_PRIVATE_KEY_EXPORT) { /* Export local private key. */ extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output; - status = _nx_crypto_ecdh_private_key_export(ecdh, - extended_output -> nx_crypto_extended_output_data, - extended_output -> nx_crypto_extended_output_length_in_byte, - &extended_output -> nx_crypto_extended_output_actual_size); + +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 || + ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448) + { + status = _nx_crypto_ecdh_private_key_export_x25519_448(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size); + } + else +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + { + + status = _nx_crypto_ecdh_private_key_export(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size); + } } else if (op == NX_CRYPTO_DH_CALCULATE) { /* Compute shared secret. */ extended_output = (NX_CRYPTO_EXTENDED_OUTPUT *)output; - status = _nx_crypto_ecdh_compute_secret(ecdh, - extended_output -> nx_crypto_extended_output_data, - extended_output -> nx_crypto_extended_output_length_in_byte, - &extended_output -> nx_crypto_extended_output_actual_size, - input, - input_length_in_byte, - ecdh -> nx_crypto_ecdh_scratch_buffer); + +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + if (ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X25519 || + ecdh -> nx_crypto_ecdh_curve -> nx_crypto_ec_id == NX_CRYPTO_EC_X448) + { + + status = _nx_crypto_ecdh_compute_secret_x25519_448(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size, + input, + input_length_in_byte, + ecdh -> nx_crypto_ecdh_scratch_buffer); + } + else +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + { + + status = _nx_crypto_ecdh_compute_secret(ecdh, + extended_output -> nx_crypto_extended_output_data, + extended_output -> nx_crypto_extended_output_length_in_byte, + &extended_output -> nx_crypto_extended_output_actual_size, + input, + input_length_in_byte, + ecdh -> nx_crypto_ecdh_scratch_buffer); + } } else { @@ -748,3 +812,386 @@ NX_CRYPTO_EXTENDED_OUTPUT return(status); } + +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ecdh_key_pair_import_x25519_448 PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets up a Elliptic-curve Diffie-Hellman context by */ +/* importing a local key pair. */ +/* */ +/* INPUT */ +/* */ +/* ecdh_ptr ECDH context */ +/* curve Elliptic Curve */ +/* local_private_key_ptr Pointer to local private key */ +/* local_private_key_len Local private key length */ +/* local_public_key_ptr Pointer to local public key */ +/* local_public_key_len Remote public key length */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_method_ecdh_operation Perform ECDH operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_key_pair_import_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + NX_CRYPTO_EC *curve, + UCHAR *local_private_key_ptr, + ULONG local_private_key_len, + UCHAR *local_public_key_ptr, + ULONG local_public_key_len) +{ +UINT key_len; + + + NX_CRYPTO_PARAMETER_NOT_USED(local_public_key_ptr); + + key_len = (curve -> nx_crypto_ec_bits + 7) >> 3; + + if (local_private_key_len != key_len) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + if (local_public_key_len > key_len) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + /* Assign the desired key size based on the chosen elliptic curve. */ + ecdh_ptr -> nx_crypto_ecdh_key_size = key_len; + + /* Copy the private key buffer. */ + NX_CRYPTO_MEMCPY(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, local_private_key_ptr, local_private_key_len); /* Use case of memcpy is verified. */ + + return(NX_CRYPTO_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ecdh_private_key_export_x25519_448 PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function exports the local private key in Elliptic-curve */ +/* Diffie-Hellman context. */ +/* */ +/* INPUT */ +/* */ +/* ecdh_ptr ECDH context */ +/* local_private_key_ptr Pointer to local private key */ +/* local_private_key_len Local private key length */ +/* actual_local_private_key_len Pointer to private key length */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* NX_CRYPTO_MEMCPY Copy the key */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_method_ecdh_operation Perform ECDH operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_private_key_export_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *local_private_key_ptr, + ULONG local_private_key_len, + ULONG *actual_local_private_key_len) +{ +UINT clen; +NX_CRYPTO_EC *curve; + + /* Make sure the key size was assigned before we do anything else. */ + if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + curve = ecdh_ptr -> nx_crypto_ecdh_curve; + + /* Check to make sure the buffer is large enough to hold the private key. */ + clen = (curve -> nx_crypto_ec_bits + 7) >> 3; + if (local_private_key_len < clen) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + /* Copy the private key buffer. */ + NX_CRYPTO_MEMCPY(local_private_key_ptr, ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, clen); /* Use case of memcpy is verified. */ + + *actual_local_private_key_len = clen; + + return(NX_CRYPTO_SUCCESS); +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ecdh_setup_x25519_448 PORTABLE C */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets up a Elliptic-curve Diffie-Hellman context by */ +/* generating a local key pair. */ +/* */ +/* INPUT */ +/* */ +/* ecdh_ptr ECDH context */ +/* share_secret_key_ptr Shared secret buffer pointer */ +/* share_secret_key_len_ptr Length of shared secret */ +/* local_public_key_ptr Pointer to local public key */ +/* local_public_key_len Remote public key length */ +/* scratch_buf_ptr Pointer to scratch buffer, */ +/* which cannot be smaller */ +/* than 6 times of the key */ +/* size (in bytes). This */ +/* scratch buffer can be */ +/* reused after this function */ +/* returns. */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_crypto_ec_key_pair_generation_x25519 */ +/* Generate EC Key Pair */ +/* _nx_crypto_ec_extract_fixed_size_le Extract huge number */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_method_ecdh_operation Perform ECDH operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curve, */ +/* resulting in version 6.1.12 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_setup_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *local_public_key_ptr, + ULONG local_public_key_len, + ULONG *actual_local_public_key_len, + NX_CRYPTO_EC *curve, + HN_UBASE *scratch_buf_ptr) +{ +UINT key_len; +UINT status; +NX_CRYPTO_HUGE_NUMBER private_key; +NX_CRYPTO_EC_POINT public_key; + + key_len = (curve -> nx_crypto_ec_bits + 7) >> 3; + if (local_public_key_len < key_len) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + ecdh_ptr -> nx_crypto_ecdh_curve = curve; + + /* Assign the desired key size based on the chosen elliptic curve. */ + ecdh_ptr -> nx_crypto_ecdh_key_size = key_len; + + /* Public key buffer (and scratch). */ + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&public_key.nx_crypto_ec_point_x, scratch_buf_ptr, key_len); + + /* Private key buffer - note that no scratch is required for the private key. */ + private_key.nx_crypto_huge_number_data = ecdh_ptr -> nx_crypto_ecdh_private_key_buffer; + private_key.nx_crypto_huge_number_size = ecdh_ptr -> nx_crypto_ecdh_key_size >> HN_SIZE_SHIFT; + private_key.nx_crypto_huge_buffer_size = sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer); + private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + + /* Clear the private key buffer. */ + NX_CRYPTO_MEMSET(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer, 0, + sizeof(ecdh_ptr -> nx_crypto_ecdh_private_key_buffer)); + + /* Generate Key Pair. */ + status = _nx_crypto_ec_key_pair_generation_x25519_448(curve, &curve -> nx_crypto_ec_g, &private_key, + &public_key, scratch_buf_ptr); + if (status) + { + return(status); + } + + /* Copy the public key into the return buffer. */ + status = _nx_crypto_ec_extract_fixed_size_le(&public_key.nx_crypto_ec_point_x, + local_public_key_ptr, key_len); + if (status) + { + return(status); + } + + *actual_local_public_key_len = key_len; + + return(NX_CRYPTO_SUCCESS); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_crypto_ecdh_compute_secret_x25519_448 PORTABLE C */ +/* 6.1.11 */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function computes the Elliptic-curve Diffie-Hellman shared */ +/* secret using an existing Elliptic-curve Diffie-Hellman context */ +/* and a public key received from a remote entity. */ +/* */ +/* INPUT */ +/* */ +/* ecdh_ptr ECDH context */ +/* share_secret_key_ptr Shared secret buffer pointer */ +/* share_secret_key_len_ptr Length of shared secret */ +/* remote_public_key Pointer to remote public key */ +/* remote_public_key_len Remote public key length */ +/* scratch_buf_ptr Pointer to scratch buffer, */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_crypto_ec_extract_fixed_size_le Extract huge number */ +/* [nx_crypto_ec_multiple] Perform multiplication for EC */ +/* _nx_crypto_huge_number_is_zero Check for all-zero value */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_crypto_method_ecdh_operation Perform ECDH operation */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-25-2022 Yuxin Zhou Initial Version 6.1.11 */ +/* */ +/**************************************************************************/ +NX_CRYPTO_KEEP UINT _nx_crypto_ecdh_compute_secret_x25519_448(NX_CRYPTO_ECDH *ecdh_ptr, + UCHAR *share_secret_key_ptr, + ULONG share_secret_key_len_ptr, + ULONG *actual_share_secret_key_len, + UCHAR *remote_public_key, + ULONG remote_public_key_len, + HN_UBASE *scratch_buf_ptr) +{ +UINT status; +UINT key_size; +UINT clen; +NX_CRYPTO_EC *curve; +/* Actual huge numbers used in calculations */ +NX_CRYPTO_HUGE_NUMBER private_key; +NX_CRYPTO_EC_POINT public_key, shared_secret; + + /* Make sure the key size was assigned before we do anything else. */ + if (0 == ecdh_ptr -> nx_crypto_ecdh_key_size) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + curve = ecdh_ptr -> nx_crypto_ecdh_curve; + + /* Figure out the sizes of our keys and buffers. */ + key_size = ecdh_ptr -> nx_crypto_ecdh_key_size; + + /* Make sure the remote public key size is correct. */ + if (remote_public_key_len != key_size) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + /* Check to make sure the buffer is large enough to hold the shared secret key. */ + clen = (curve -> nx_crypto_ec_bits + 7) >> 3; + if (share_secret_key_len_ptr < clen) + { + return(NX_CRYPTO_SIZE_ERROR); + } + + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&public_key.nx_crypto_ec_point_x, scratch_buf_ptr, key_size); + NX_CRYPTO_HUGE_NUMBER_INITIALIZE(&shared_secret.nx_crypto_ec_point_x, scratch_buf_ptr, key_size); + + /* Copy the remote public key from the caller's buffer. */ + NX_CRYPTO_MEMCPY(public_key.nx_crypto_ec_point_x.nx_crypto_huge_number_data, remote_public_key, remote_public_key_len); /* Use case of memcpy is verified. */ + public_key.nx_crypto_ec_point_x.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT; + + /* Private key buffer */ + private_key.nx_crypto_huge_number_data = (HN_UBASE*)ecdh_ptr -> nx_crypto_ecdh_private_key_buffer; + private_key.nx_crypto_huge_number_size = key_size >> HN_SIZE_SHIFT; + private_key.nx_crypto_huge_buffer_size = key_size; + private_key.nx_crypto_huge_number_is_negative = NX_CRYPTO_FALSE; + + /* Finally, generate shared secret from the remote public key, our generated private key, and the curve. + The actual calculation is "shared_secret = private_key * public_key". */ + curve -> nx_crypto_ec_multiple(curve, &public_key, &private_key, &shared_secret, scratch_buf_ptr); + + /* Check for the all-zero value results. */ + if (_nx_crypto_huge_number_is_zero(&shared_secret.nx_crypto_ec_point_x)) + { + return(NX_CRYPTO_NOT_SUCCESSFUL); + } + + /* Copy the shared secret into the return buffer. */ + status = _nx_crypto_ec_extract_fixed_size_le(&shared_secret.nx_crypto_ec_point_x, + share_secret_key_ptr, clen); + + /* The public key size is simply the key size for this group. */ + *actual_share_secret_key_len = clen; + + return(status); +} + +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ diff --git a/crypto_libraries/src/nx_crypto_ecjpake.c b/crypto_libraries/src/nx_crypto_ecjpake.c index 3263613d..26bcf767 100644 --- a/crypto_libraries/src/nx_crypto_ecjpake.c +++ b/crypto_libraries/src/nx_crypto_ecjpake.c @@ -28,7 +28,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_ecjpake_init PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1525,9 +1525,13 @@ UINT status; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST UINT _nx_crypto_ecjpake_key_encryption_key_generate(NX_CRYPTO_METHOD *hash_method, VOID *hash_metadata, UCHAR *key_expansion, diff --git a/crypto_libraries/src/nx_crypto_generic_ciphersuites.c b/crypto_libraries/src/nx_crypto_generic_ciphersuites.c index 655bfe32..730c0dfb 100644 --- a/crypto_libraries/src/nx_crypto_generic_ciphersuites.c +++ b/crypto_libraries/src/nx_crypto_generic_ciphersuites.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* nx_crypto_generic_ciphersuites PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,6 +66,14 @@ /* curves in the crypto array, */ /* added TLS ciphersuite entry,*/ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), added */ +/* x25519 and x448 curves, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curves, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -90,6 +98,8 @@ extern NX_CRYPTO_METHOD crypto_method_auth_psk; extern NX_CRYPTO_METHOD crypto_method_ec_secp256; extern NX_CRYPTO_METHOD crypto_method_ec_secp384; extern NX_CRYPTO_METHOD crypto_method_ec_secp521; +extern NX_CRYPTO_METHOD crypto_method_ec_x25519; +extern NX_CRYPTO_METHOD crypto_method_ec_x448; extern NX_CRYPTO_METHOD crypto_method_md5; extern NX_CRYPTO_METHOD crypto_method_sha1; extern NX_CRYPTO_METHOD crypto_method_sha224; @@ -107,6 +117,7 @@ extern NX_CRYPTO_METHOD crypto_method_hmac; /* Ciphersuite table without ECC. */ /* Lookup table used to map ciphersuites to cryptographic routines. */ +/* For TLS Web servers, define NX_SECURE_ENABLE_AEAD_CIPHER to allow web browsers to connect using AES_128_GCM cipher suites. */ NX_SECURE_TLS_CIPHERSUITE_INFO _nx_crypto_ciphersuite_lookup_table[] = { /* Ciphersuite, public cipher, public_auth, session cipher & cipher mode, iv size, key size, hash method, hash size, TLS PRF */ @@ -210,6 +221,7 @@ const UINT _nx_crypto_ciphersuite_lookup_table_tls_1_3_size = sizeof(_nx_crypto_ /* Ciphersuite table with ECC. */ /* Lookup table used to map ciphersuites to cryptographic routines. */ /* Ciphersuites are negotiated IN ORDER - top priority first. Ciphersuites lower in the list are considered less secure. */ +/* For TLS Web servers, define NX_SECURE_ENABLE_AEAD_CIPHER to allow web browsers to connect using AES_128_GCM cipher suites. */ NX_SECURE_TLS_CIPHERSUITE_INFO _nx_crypto_ciphersuite_lookup_table_ecc[] = { /* Ciphersuite, public cipher, public_auth, session cipher & cipher mode, iv size, key size, hash method, hash size, TLS PRF */ @@ -284,6 +296,10 @@ const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers_ecc = const USHORT nx_crypto_ecc_supported_groups[] = { (USHORT)NX_CRYPTO_EC_SECP256R1, +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + (USHORT)NX_CRYPTO_EC_X25519, + (USHORT)NX_CRYPTO_EC_X448, +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ (USHORT)NX_CRYPTO_EC_SECP384R1, (USHORT)NX_CRYPTO_EC_SECP521R1, }; @@ -291,6 +307,10 @@ const USHORT nx_crypto_ecc_supported_groups[] = const NX_CRYPTO_METHOD *nx_crypto_ecc_curves[] = { &crypto_method_ec_secp256, +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + &crypto_method_ec_x25519, + &crypto_method_ec_x448, +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ &crypto_method_ec_secp384, &crypto_method_ec_secp521, }; @@ -598,6 +618,10 @@ const NX_CRYPTO_METHOD *supported_crypto[] = &crypto_method_tls_prf_sha256, &crypto_method_hkdf, &crypto_method_ec_secp256, +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + &crypto_method_ec_x25519, + &crypto_method_ec_x448, +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ &crypto_method_ec_secp384, &crypto_method_ec_secp521, }; diff --git a/crypto_libraries/src/nx_crypto_huge_number.c b/crypto_libraries/src/nx_crypto_huge_number.c index 3e0286c1..c176eb3a 100644 --- a/crypto_libraries/src/nx_crypto_huge_number.c +++ b/crypto_libraries/src/nx_crypto_huge_number.c @@ -203,7 +203,7 @@ UINT cmp; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_huge_number_subtract PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -262,6 +262,9 @@ UINT cmp; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_subtract(NX_CRYPTO_HUGE_NUMBER *left, NX_CRYPTO_HUGE_NUMBER *right) @@ -276,7 +279,6 @@ UINT cmp; } else { - cmp = _nx_crypto_huge_number_compare_unsigned(left, right); if (cmp == NX_CRYPTO_HUGE_NUMBER_EQUAL) { @@ -1340,7 +1342,7 @@ UINT i, j; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_huge_number_modulus PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1410,6 +1412,9 @@ UINT i, j; /* 09-30-2020 Timothy Stapko Modified comment(s), and */ /* fixed variable type issue, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* fixed division by zero bug, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_modulus(NX_CRYPTO_HUGE_NUMBER *dividend, NX_CRYPTO_HUGE_NUMBER *divisor) @@ -1518,7 +1523,7 @@ NX_CRYPTO_HUGE_NUMBER *result; } else { - scale = result_buffer[result_length] / (divisor_buffer[divisor_length] + 1); + scale = result_buffer[result_length] / ((HN_UBASE2)divisor_buffer[divisor_length] + 1); if (scale == 0) { scale = 1; @@ -2540,7 +2545,7 @@ HN_UBASE *result_buffer = result -> nx_crypto_huge_number_data; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_huge_number_mont_power_modulus PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -2600,6 +2605,8 @@ HN_UBASE *result_buffer = result -> nx_crypto_huge_number_data; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_mont_power_modulus(NX_CRYPTO_HUGE_NUMBER *x, @@ -2673,7 +2680,6 @@ NX_CRYPTO_HUGE_NUMBER *operand, *temp_result, *temp_swap; temp_result = &temp; exp_size = e -> nx_crypto_huge_number_size; - m -> nx_crypto_huge_number_size = m -> nx_crypto_huge_number_size; val = e -> nx_crypto_huge_number_data + (exp_size - 1); /* Loop through the bits of the exponent. For each bit set, multiply the result by the running square. */ diff --git a/crypto_libraries/src/nx_crypto_huge_number_extended.c b/crypto_libraries/src/nx_crypto_huge_number_extended.c index 498a186b..a2b3aa02 100644 --- a/crypto_libraries/src/nx_crypto_huge_number_extended.c +++ b/crypto_libraries/src/nx_crypto_huge_number_extended.c @@ -27,13 +27,13 @@ #include "stdio.h" #include "nx_crypto_huge_number.h" -#ifndef NX_CRYPTO_FIPS +#ifndef NX_CRYPTO_SELF_TEST /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_crypto_huge_number_add_digit PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,6 +73,10 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_add_digit(NX_CRYPTO_HUGE_NUMBER *value, HN_UBASE digit) @@ -185,7 +189,7 @@ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_subtract_digit(NX_CRYPTO_HUGE_NUMBER /* FUNCTION RELEASE */ /* */ /* _nx_crypto_huge_number_power_modulus PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -238,6 +242,8 @@ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_subtract_digit(NX_CRYPTO_HUGE_NUMBER /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Bhupendra Naphade Modified comment(s), */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_huge_number_power_modulus(NX_CRYPTO_HUGE_NUMBER *number, @@ -259,7 +265,6 @@ NX_CRYPTO_HUGE_NUMBER temp; NX_CRYPTO_HUGE_NUMBER_SET_DIGIT(result, 1); exp_size = exponent -> nx_crypto_huge_number_size; - modulus -> nx_crypto_huge_number_size = modulus -> nx_crypto_huge_number_size; val = exponent -> nx_crypto_huge_number_data; /* Loop through the bits of the exponent. For each bit set, multiply the result by the running square. */ for (index = 0; index < exp_size; index++) diff --git a/crypto_libraries/src/nx_crypto_initialize.c b/crypto_libraries/src/nx_crypto_initialize.c index 73f36e9c..6ae0aeff 100644 --- a/crypto_libraries/src/nx_crypto_initialize.c +++ b/crypto_libraries/src/nx_crypto_initialize.c @@ -24,7 +24,7 @@ #include "nx_crypto.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* Include necessary system files. */ @@ -33,8 +33,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_crypto_fips_memcpy PORTABLE C */ -/* 6.1 */ +/* _nx_crypto_self_test_memcpy PORTABLE C */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,9 +71,12 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed function, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memcpy(void *dest, const void *src, size_t size) +NX_CRYPTO_KEEP VOID *_nx_crypto_self_test_memcpy(void *dest, const void *src, size_t size) { char *from, *to; unsigned int i; @@ -93,8 +96,8 @@ NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memcpy(void *dest, const void *src, size_t /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_crypto_fips_memset PORTABLE C */ -/* 6.1 */ +/* _nx_crypto_self_test_memset PORTABLE C */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -131,9 +134,12 @@ NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memcpy(void *dest, const void *src, size_t /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed function, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memset(void *dest, int value, size_t size) +NX_CRYPTO_KEEP VOID *_nx_crypto_self_test_memset(void *dest, int value, size_t size) { char *to; unsigned int i; @@ -153,8 +159,8 @@ NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memset(void *dest, int value, size_t size) /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_crypto_fips_memcmp PORTABLE C */ -/* 6.1 */ +/* _nx_crypto_self_test_memcmp PORTABLE C */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -193,9 +199,12 @@ NX_CRYPTO_KEEP VOID *_nx_crypto_fips_memset(void *dest, int value, size_t size) /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed function, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -NX_CRYPTO_KEEP int _nx_crypto_fips_memcmp(const void *str1, const void *str2, size_t size) +NX_CRYPTO_KEEP int _nx_crypto_self_test_memcmp(const void *str1, const void *str2, size_t size) { char *string1; char *string2; @@ -216,8 +225,8 @@ NX_CRYPTO_KEEP int _nx_crypto_fips_memcmp(const void *str1, const void *str2, si /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_crypto_fips_memmove PORTABLE C */ -/* 6.1 */ +/* _nx_crypto_self_test_memmove PORTABLE C */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -253,9 +262,12 @@ NX_CRYPTO_KEEP int _nx_crypto_fips_memcmp(const void *str1, const void *str2, si /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed function, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ -NX_CRYPTO_KEEP void* _nx_crypto_fips_memmove(void *dest, const void *src, size_t size) +NX_CRYPTO_KEEP void* _nx_crypto_self_test_memmove(void *dest, const void *src, size_t size) { char *from, *to; unsigned int i; diff --git a/crypto_libraries/src/nx_crypto_method_self_test.c b/crypto_libraries/src/nx_crypto_method_self_test.c index cc320eb7..51d218fa 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test.c +++ b/crypto_libraries/src/nx_crypto_method_self_test.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST static UCHAR metadata[10240]; extern NX_CRYPTO_METHOD crypto_method_aes_cbc_128; @@ -76,7 +76,7 @@ const UINT nx_crypto_hash_key_size = sizeof(nx_crypto_hash_key) << 3; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -109,6 +109,10 @@ const UINT nx_crypto_hash_key_size = sizeof(nx_crypto_hash_key) << 3; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ diff --git a/crypto_libraries/src/nx_crypto_method_self_test_3des.c b/crypto_libraries/src/nx_crypto_method_self_test_3des.c index 8ec618e6..46d9e90b 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_3des.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_3des.c @@ -31,7 +31,7 @@ #endif -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* 8f4f7aab25043720f4fbae01aedf071c68a283689b08ad20 */ static UCHAR key_1[] = { @@ -95,7 +95,7 @@ static UCHAR output[72]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_3des PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -128,6 +128,10 @@ static UCHAR output[72]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_3des(NX_CRYPTO_METHOD *crypto_method_3des, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_aes.c b/crypto_libraries/src/nx_crypto_method_self_test_aes.c index f0919c8d..6fbd1a84 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_aes.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_aes.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST #define INPUT_OUTPUT_LENGTH (16) /* 02CF1E1D9796AD3395D8126757B6FC7C705F082FB85270427760AC173759CE07 */ @@ -122,7 +122,7 @@ static UCHAR output[INPUT_OUTPUT_LENGTH]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_aes PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -155,6 +155,10 @@ static UCHAR output[INPUT_OUTPUT_LENGTH]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_aes(NX_CRYPTO_METHOD *crypto_method_aes, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_des.c b/crypto_libraries/src/nx_crypto_method_self_test_des.c index 46998a2b..9df96187 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_des.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_des.c @@ -31,7 +31,7 @@ #endif -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST #define INPUT_OUTPUT_LENGTH 64 @@ -68,7 +68,7 @@ static UCHAR output[INPUT_OUTPUT_LENGTH]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_des PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -101,6 +101,10 @@ static UCHAR output[INPUT_OUTPUT_LENGTH]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_des(NX_CRYPTO_METHOD *crypto_method_des, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_drbg.c b/crypto_libraries/src/nx_crypto_method_self_test_drbg.c index c590cb2b..bf2d320a 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_drbg.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_drbg.c @@ -28,7 +28,7 @@ #include "nx_crypto_drbg.h" #include "nx_crypto_aes.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* [AES-128 use df] @@ -138,7 +138,7 @@ static UCHAR drbg_test_entropy_count_npr; /* FUNCTION RELEASE */ /* */ /* drbg_test_get_entropy_pr PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -175,6 +175,10 @@ static UCHAR drbg_test_entropy_count_npr; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP static UINT drbg_test_get_entropy_pr(UCHAR *entropy, UINT *entropy_len, UINT entropy_max_len) diff --git a/crypto_libraries/src/nx_crypto_method_self_test_ecdh.c b/crypto_libraries/src/nx_crypto_method_self_test_ecdh.c index 654e6382..8b99721f 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_ecdh.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_ecdh.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* 7fc1c44f7f432927f404922107eae9d10b26ed35527d66d9858c58be388c98a1 981a1b7c098a26747a723b171cae16670de0c320a82b1cfcbe77d2f807a217b5 */ @@ -61,7 +61,7 @@ extern NX_CRYPTO_METHOD crypto_method_ec_secp256; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_ecdh PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -94,6 +94,10 @@ extern NX_CRYPTO_METHOD crypto_method_ec_secp256; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_ecdh(NX_CRYPTO_METHOD *crypto_method_ecdh, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_ecdsa.c b/crypto_libraries/src/nx_crypto_method_self_test_ecdsa.c index 717fa17c..ae357656 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_ecdsa.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_ecdsa.c @@ -27,7 +27,7 @@ #include "nx_crypto_method_self_test.h" #include "nx_crypto_ecdsa.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST extern NX_CRYPTO_METHOD crypto_method_ec_secp256; extern NX_CRYPTO_METHOD crypto_method_sha256; @@ -52,7 +52,7 @@ static UCHAR scratch_buffer[4000]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_ecdsa PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -86,6 +86,10 @@ static UCHAR scratch_buffer[4000]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_ecdsa(NX_CRYPTO_METHOD *crypto_method_ecdsa, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_hmac_md5.c b/crypto_libraries/src/nx_crypto_method_self_test_hmac_md5.c index 9a7ff721..f558fef2 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_hmac_md5.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_hmac_md5.c @@ -27,7 +27,7 @@ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* BF8D54470B5F365F14F84C0E046DE4053DE7A05DB847CD2C9844632082F588602EA3885DEF9CA21B8B46AA7CB9588938 */ static UCHAR key_1[] = { @@ -57,7 +57,7 @@ static ULONG output[4]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_hmac_md5 PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -91,6 +91,10 @@ static ULONG output[4]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_hmac_md5(NX_CRYPTO_METHOD *crypto_method_hmac_md5, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_hmac_sha.c b/crypto_libraries/src/nx_crypto_method_self_test_hmac_sha.c index 86dc1248..a59fcf61 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_hmac_sha.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_hmac_sha.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* 39567E74085C7B4C94BCED431A18F109BBACEF73471C0E00B7FA0B1C4F979576B5F1025AD5ADAA1246A6974CEB6BEC30CF5CA14F65231F31F24338707AD35B7C */ static UCHAR key_1_96[] = { @@ -207,7 +207,7 @@ static ULONG output[16]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_hmac_sha PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -241,6 +241,10 @@ static ULONG output[16]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_hmac_sha(NX_CRYPTO_METHOD *crypto_method_hmac_sha, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_md5.c b/crypto_libraries/src/nx_crypto_method_self_test_md5.c index 750bfa71..65e02d0e 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_md5.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_md5.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* f149e41d848f59276cfddd743bafa9a90e1ee4a263a118142b33e3702176ef0a59f8237a1cb51b42f3ded6b202d9af0997898fdd03cf60bda951c514547a0850cec25444ae2f24cb711bfbafcc3956c941d3de69f155e3f8b10f06db5f37359b772ddd43e1035a0a0d3db33242d5843033833b0dd43b870c6bf60e8deab55f317cc3273f5e3ba747f0cb65050cb7228796210d9254873643008d45f29cfd6c5b060c9a */ static UCHAR plain_1[] = { @@ -56,7 +56,7 @@ static ULONG output[4]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_md5 PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -89,6 +89,10 @@ static ULONG output[4]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_md5(NX_CRYPTO_METHOD *crypto_method_md5, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_pkcs1.c b/crypto_libraries/src/nx_crypto_method_self_test_pkcs1.c index c3c1b6a7..bdca1ae6 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_pkcs1.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_pkcs1.c @@ -27,7 +27,7 @@ #include "nx_crypto_method_self_test.h" #include "nx_crypto_pkcs1_v1.5.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST static UCHAR pub_e_2048[] = {0x01, 0x00, 0x01}; @@ -109,7 +109,7 @@ extern NX_CRYPTO_METHOD crypto_method_sha256; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_pkcs1 PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -143,6 +143,10 @@ extern NX_CRYPTO_METHOD crypto_method_sha256; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_pkcs1(NX_CRYPTO_METHOD *crypto_method_pkcs1, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_prf.c b/crypto_libraries/src/nx_crypto_method_self_test_prf.c index a1cce84c..a80c2591 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_prf.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_prf.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST static UCHAR secret_sha1[] = { 0x86, 0xec, 0x88, 0xbb }; static UCHAR label_sha1[] = { 0xc8, 0x37, 0xaf, 0x7d }; @@ -112,7 +112,7 @@ static UCHAR output[256]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_prf PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -145,6 +145,10 @@ static UCHAR output[256]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_prf(NX_CRYPTO_METHOD *crypto_method_prf, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_rsa.c b/crypto_libraries/src/nx_crypto_method_self_test_rsa.c index 45f5c2d4..1ca4109c 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_rsa.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_rsa.c @@ -27,7 +27,7 @@ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* 00010001 */ static const UCHAR pub_e_1024[] = { @@ -559,7 +559,7 @@ static UCHAR output[512]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_rsa PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -592,6 +592,10 @@ static UCHAR output[512]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_rsa(NX_CRYPTO_METHOD *crypto_method, diff --git a/crypto_libraries/src/nx_crypto_method_self_test_sha.c b/crypto_libraries/src/nx_crypto_method_self_test_sha.c index 33ab6d54..626f674f 100644 --- a/crypto_libraries/src/nx_crypto_method_self_test_sha.c +++ b/crypto_libraries/src/nx_crypto_method_self_test_sha.c @@ -26,7 +26,7 @@ /* Include necessary system files. */ #include "nx_crypto_method_self_test.h" -#ifdef NX_CRYPTO_FIPS +#ifdef NX_CRYPTO_SELF_TEST /* 7c9c67323a1df1adbfe5ceb415eaef0155ece2820f4d50c1ec22cba4928ac656c83fe585db6a78ce40bc42757aba7e5a3f582428d6ca68d0c3978336a6efb729613e8d9979016204bfd921322fdd5222183554447de5e6e9bbe6edf76d7b71e18dc2e8d6dc89b7398364f652fafc734329aafa3dcd45d4f31e388e4fafd7fc6495f37ca5cbab7f54d586463da4bfeaa3bae09f7b8e9239d832b4f0a733aa609cc1f8d4 */ static UCHAR plain_1[] = { @@ -194,7 +194,7 @@ static ULONG output[16]; /* FUNCTION RELEASE */ /* */ /* nx_crypto_method_self_test_sha PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -227,6 +227,10 @@ static ULONG output[16]; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 06-02-2021 Bhupendra Naphade Modified comment(s), */ +/* renamed FIPS symbol to */ +/* self-test, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_method_self_test_sha(NX_CRYPTO_METHOD *crypto_method_sha, diff --git a/crypto_libraries/src/nx_crypto_methods.c b/crypto_libraries/src/nx_crypto_methods.c index 0236381c..bd3731ad 100644 --- a/crypto_libraries/src/nx_crypto_methods.c +++ b/crypto_libraries/src/nx_crypto_methods.c @@ -51,7 +51,7 @@ /* FUNCTION RELEASE */ /* */ /* nx_crypto_methods PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -86,6 +86,14 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comments(s), added */ +/* warning supression for */ +/* obsolete DES/3DES, */ +/* added x25519 curve, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* added x448 curve, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -513,6 +521,38 @@ NX_CRYPTO_METHOD crypto_method_ec_secp521 = _nx_crypto_method_ec_secp521r1_operation, /* Operation */ }; +#ifdef NX_CRYPTO_ENABLE_CURVE25519_448 + +/* Declare a placeholder for EC x25519. */ +NX_CRYPTO_METHOD crypto_method_ec_x25519 = +{ + NX_CRYPTO_EC_X25519, /* EC placeholder */ + 255, /* Key size in bits */ + 0, /* IV size in bits */ + 0, /* ICV size in bits, not used. */ + 0, /* Block size in bytes. */ + 0, /* Metadata size in bytes */ + NX_CRYPTO_NULL, /* Initialization routine. */ + NX_CRYPTO_NULL, /* Cleanup routine, not used. */ + _nx_crypto_method_ec_x25519_operation, /* Operation */ +}; + +/* Declare a placeholder for EC x448. */ +NX_CRYPTO_METHOD crypto_method_ec_x448 = +{ + NX_CRYPTO_EC_X448, /* EC placeholder */ + 448, /* Key size in bits */ + 0, /* IV size in bits */ + 0, /* ICV size in bits, not used. */ + 0, /* Block size in bytes. */ + 0, /* Metadata size in bytes */ + NX_CRYPTO_NULL, /* Initialization routine. */ + NX_CRYPTO_NULL, /* Cleanup routine, not used. */ + _nx_crypto_method_ec_x448_operation, /* Operation */ +}; + +#endif /* NX_CRYPTO_ENABLE_CURVE25519_448 */ + /* Declare the public NULL cipher (not to be confused with the NULL methods above). This * is used as a placeholder in ciphersuites that do not use a cipher method for a * particular operation (e.g. some PSK ciphersuites don't use a public-key algorithm @@ -735,11 +775,11 @@ NX_CRYPTO_METHOD crypto_method_hkdf = /* Declare the 3DES-CBC 128 encrytion method. */ NX_CRYPTO_METHOD crypto_method_des = { - NX_CRYPTO_ENCRYPTION_DES_CBC, /* DES crypto algorithm */ - NX_CRYPTO_DES_KEY_LEN_IN_BITS, /* Key size in bits */ - NX_CRYPTO_DES_IV_LEN_IN_BITS, /* IV size in bits */ + NX_CRYPTO_ENCRYPTION_DES_CBC, /* DES crypto algorithm */ /* lgtm[cpp/weak-cryptographic-algorithm] */ + NX_CRYPTO_DES_KEY_LEN_IN_BITS, /* Key size in bits */ /* lgtm[cpp/weak-cryptographic-algorithm] */ + NX_CRYPTO_DES_IV_LEN_IN_BITS, /* IV size in bits */ /* lgtm[cpp/weak-cryptographic-algorithm] */ 0, /* ICV size in bits, not used */ - (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3), /* Block size in bytes */ + (NX_CRYPTO_DES_BLOCK_SIZE_IN_BITS >> 3), /* Block size in bytes */ /* lgtm[cpp/weak-cryptographic-algorithm] */ sizeof(NX_CRYPTO_DES), /* Metadata size in bytes */ _nx_crypto_method_des_init, /* 3DES initialization routine */ _nx_crypto_method_des_cleanup, /* 3DES cleanup routine */ @@ -750,11 +790,11 @@ NX_CRYPTO_METHOD crypto_method_des = /* Declare the 3DES-CBC 128 encrytion method. */ NX_CRYPTO_METHOD crypto_method_3des = { - NX_CRYPTO_ENCRYPTION_3DES_CBC, /* 3DES crypto algorithm */ - NX_CRYPTO_3DES_KEY_LEN_IN_BITS, /* Key size in bits */ - NX_CRYPTO_3DES_IV_LEN_IN_BITS, /* IV size in bits */ - 0, /* ICV size in bits, not used */ - (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3), /* Block size in bytes */ + NX_CRYPTO_ENCRYPTION_3DES_CBC, /* 3DES crypto algorithm */ /* lgtm[cpp/weak-cryptographic-algorithm] */ + NX_CRYPTO_3DES_KEY_LEN_IN_BITS, /* Key size in bits */ /* lgtm[cpp/weak-cryptographic-algorithm] */ + NX_CRYPTO_3DES_IV_LEN_IN_BITS, /* IV size in bits */ /* lgtm[cpp/weak-cryptographic-algorithm] */ + 0, /* ICV size in bits, not used */ + (NX_CRYPTO_3DES_BLOCK_SIZE_IN_BITS >> 3), /* Block size in bytes */ /* lgtm[cpp/weak-cryptographic-algorithm] */ sizeof(NX_CRYPTO_3DES), /* Metadata size in bytes */ _nx_crypto_method_3des_init, /* 3DES initialization routine */ _nx_crypto_method_3des_cleanup, /* 3DES cleanup routine */ diff --git a/crypto_libraries/src/nx_crypto_module_start.c b/crypto_libraries/src/nx_crypto_module_start.c deleted file mode 100644 index 322d7520..00000000 --- a/crypto_libraries/src/nx_crypto_module_start.c +++ /dev/null @@ -1,379 +0,0 @@ -/**************************************************************************/ -/* */ -/* Copyright (c) Microsoft Corporation. All rights reserved. */ -/* */ -/* This software is licensed under the Microsoft Software License */ -/* Terms for Microsoft Azure RTOS. Full text of the license can be */ -/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ -/* and in the root directory of this software. */ -/* */ -/**************************************************************************/ - - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** NetX Crypto Component */ -/** */ -/** Crypto Module Initialization, startup, and helper routines */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - -/* NOTE: This file is used for FIPS certification on STM32F469 only. */ - -#define NX_CRYPTO_SOURCE_CODE - -#include "nx_crypto.h" -#include "nx_crypto_hmac_sha2.h" - -#ifdef NX_CRYPTO_FIPS - -#define NX_CRYPTO_INTEGRITY_TEST_CHECK(status) \ - if(status) \ - { \ - _nx_crypto_library_state |= NX_CRYPTO_LIBRARY_STATE_POST_FAILED; \ - } - -#define REG32(x) (*(volatile unsigned int *)(x)) - - -/* Define RCC register. */ -#define STM32F4_RCC 0x40023800 -#define STM32F4_RCC_AHB2ENR REG32(STM32F4_RCC + 0x34) -#define STM32F4_RCC_AHB2ENR_RNGEN 0x00000040 - -#define STM32L4_RCC 0x40021000 -#define STM32L4_RCC_AHB2ENR REG32(STM32L4_RCC + 0x4C) -#define STM32L4_RCC_AHB2ENR_RNGEN 0x00040000 - -/* Define RNG registers. */ -#define STM32_RNG 0x50060800 -#define STM32_RNG_CR REG32(STM32_RNG + 0x00) -#define STM32_RNG_SR REG32(STM32_RNG + 0x04) -#define STM32_RNG_DR REG32(STM32_RNG + 0x08) - -#define STM32_RNG_CR_RNGEN 0x00000004 -#define STM32_RNG_CR_IE 0x00000008 -#define STM32_RNG_CR_CED 0x00000020 - -#define STM32_RNG_SR_DRDY 0x00000001 -#define STM32_RNG_SR_CECS 0x00000002 -#define STM32_RNG_SR_SECS 0x00000004 -#define STM32_RNG_SR_CEIS 0x00000020 -#define STM32_RNG_SR_SEIS 0x00000040 - -#define DBGMCU_IDCODE REG32(0xE0042000) -#define DBGMCU_IDCODE_DEV_ID_MASK 0x00000FFF -#define DEV_ID_L47x 0x415 - -const unsigned long long _nx_crypto_module_program_begin @ "NX_CRYPTO_PROGRAM_BEGIN" = 0ull; - - -const unsigned char _nx_crypto_module_hash_value[32] @ "NX_CRYPTO_PROGRAM_END" = -{ - -#if (__VER__ == 8030002) -/* IAR 8.30.2 */ - 0xe0, 0xa6, 0xf3, 0x19, 0x9f, 0x43, 0x02, 0x4f, - 0xe6, 0x69, 0xfb, 0xd3, 0x4c, 0x1b, 0xdd, 0xee, - 0x90, 0x3c, 0xff, 0xba, 0x16, 0x56, 0x51, 0x78, - 0x57, 0xe6, 0x47, 0xc2, 0xca, 0x83, 0xff, 0xc9 -#else -/* IAR 8.22.2 */ - 0xe8, 0xd9, 0xe8, 0xac, 0xd3, 0x7c, 0x54, 0x7e, - 0xd0, 0x72, 0x96, 0x38, 0xde, 0x45, 0x78, 0xff, - 0xe1, 0xe4, 0xb2, 0xfc, 0xfd, 0xa6, 0x11, 0xd7, - 0x0c, 0xda, 0xc9, 0xc9, 0xf2, 0x95, 0xd2, 0xa4 -#endif -}; - -extern NX_CRYPTO_METHOD crypto_method_hmac_sha256; -extern const CHAR nx_crypto_hash_key[]; -extern const UINT nx_crypto_hash_key_size; -static UCHAR nx_crypto_hmac_output[64]; -static NX_CRYPTO_SHA256_HMAC nx_crypto_fips_hmac; - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _nx_crypto_hardware_rand_initialize PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Timothy Stapko, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function initializes hardware random number generator. */ -/* The following processors are supported: */ -/* STM32F407 */ -/* STM32F417 */ -/* STM32F429 */ -/* STM32F439 */ -/* STM32F469 */ -/* STM32F479 */ -/* STM32L475 */ -/* STM32L476 */ -/* */ -/* INPUT */ -/* */ -/* None */ -/* */ -/* OUTPUT */ -/* */ -/* None */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* _nx_crypto_method_self_test */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Timothy Stapko Initial Version 6.0 */ -/* 09-30-2020 Timothy Stapko Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -NX_CRYPTO_KEEP void _nx_crypto_hardware_rand_initialize_stm32f4(void) -{ - -unsigned int device_id; - - /* Read device ID. */ - device_id = DBGMCU_IDCODE & DBGMCU_IDCODE_DEV_ID_MASK; - - if (device_id == DEV_ID_L47x) - { - - /* Enable clock for the RNG. */ - STM32L4_RCC_AHB2ENR |= STM32L4_RCC_AHB2ENR_RNGEN; - } - else - { - - /* Enable clock for the RNG. */ - STM32F4_RCC_AHB2ENR |= STM32F4_RCC_AHB2ENR_RNGEN; - } - - /* Enable the random number generator. */ - STM32_RNG_CR = STM32_RNG_CR_RNGEN; -} - -NX_CRYPTO_KEEP INT nx_crypto_hardware_rand(VOID) -{ - - /* Wait for data ready. */ - while((STM32_RNG_SR & STM32_RNG_SR_DRDY) == 0); - - /* Return the random number. */ - return STM32_RNG_DR; -} - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* __aeabi_memcpy PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Timothy Stapko, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function performs memory copy function for the FIPS 140-2 */ -/* compliance build. */ -/* */ -/* INPUT */ -/* */ -/* dest Pointer to the destination */ -/* memory */ -/* value value (in byte) to set to the */ -/* memory location */ -/* size Number of bytes to copy */ -/* */ -/* OUTPUT */ -/* */ -/* void * Pointer to the destination */ -/* memory */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Timothy Stapko Initial Version 6.0 */ -/* 09-30-2020 Timothy Stapko Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -NX_CRYPTO_KEEP __nounwind __interwork __softfp __aapcs_core void __aeabi_memcpy (void *dest, const void *src, size_t size) -{ - char *from, *to; - unsigned int i; - - from = (char*)src; - to = (char*)dest; - - for(i = 0; i < size; i++) - { - to[i] = from[i]; - } -} - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* __aeabi_memcpy4 PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Timothy Stapko, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function performs memory copy function for the FIPS 140-2 */ -/* compliance build. */ -/* */ -/* INPUT */ -/* */ -/* dest Pointer to the destination */ -/* memory */ -/* value value (in byte) to set to the */ -/* memory location */ -/* size Number of bytes to copy */ -/* */ -/* OUTPUT */ -/* */ -/* void * Pointer to the destination */ -/* memory */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Timothy Stapko Initial Version 6.0 */ -/* 09-30-2020 Timothy Stapko Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -NX_CRYPTO_KEEP __nounwind __interwork __softfp __aapcs_core void __aeabi_memcpy4 (void *dest, const void *src, size_t size) -{ - char *from, *to; - unsigned int i; - - from = (char*)src; - to = (char*)dest; - - for(i = 0; i < size; i++) - { - to[i] = from[i]; - } -} - - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* __aeabi_memcpy8 PORTABLE C */ -/* 6.1 */ -/* AUTHOR */ -/* */ -/* Timothy Stapko, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This function performs memory copy function for the FIPS 140-2 */ -/* compliance build. */ -/* */ -/* INPUT */ -/* */ -/* dest Pointer to the destination */ -/* memory */ -/* value value (in byte) to set to the */ -/* memory location */ -/* size Number of bytes to copy */ -/* */ -/* OUTPUT */ -/* */ -/* void * Pointer to the destination */ -/* memory */ -/* */ -/* CALLS */ -/* */ -/* None */ -/* */ -/* CALLED BY */ -/* */ -/* */ -/* RELEASE HISTORY */ -/* */ -/* DATE NAME DESCRIPTION */ -/* */ -/* 05-19-2020 Timothy Stapko Initial Version 6.0 */ -/* 09-30-2020 Timothy Stapko Modified comment(s), */ -/* resulting in version 6.1 */ -/* */ -/**************************************************************************/ -NX_CRYPTO_KEEP __nounwind __interwork __softfp __aapcs_core void __aeabi_memcpy8 (void *dest, const void *src, size_t size) -{ - char *from, *to; - unsigned int i; - - from = (char*)src; - to = (char*)dest; - - for(i = 0; i < size; i++) - { - to[i] = from[i]; - } -} - -NX_CRYPTO_KEEP UINT _nx_crypto_integrity_test(void) -{ -UINT status; - - status = _nx_crypto_method_hmac_sha256_operation(NX_CRYPTO_AUTHENTICATE, /* op */ - (VOID*)&nx_crypto_fips_hmac, - &crypto_method_hmac_sha256, /* Method */ - (UCHAR*)nx_crypto_hash_key, - nx_crypto_hash_key_size, - (UCHAR*)&_nx_crypto_module_program_begin, - (ULONG)_nx_crypto_module_hash_value - (ULONG)&_nx_crypto_module_program_begin, - NX_CRYPTO_NULL, /* iv_ptr, not used */ - nx_crypto_hmac_output, sizeof(nx_crypto_hmac_output), - &nx_crypto_fips_hmac, sizeof(nx_crypto_fips_hmac), - NX_CRYPTO_NULL, NX_CRYPTO_NULL); - NX_CRYPTO_INTEGRITY_TEST_CHECK(status) - - status = (UINT)NX_CRYPTO_MEMCMP(nx_crypto_hmac_output, _nx_crypto_module_hash_value, 32); - NX_CRYPTO_INTEGRITY_TEST_CHECK(status); - - return(status); -} - -#endif diff --git a/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c b/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c index dcba54aa..9a545d55 100644 --- a/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c +++ b/crypto_libraries/src/nx_crypto_pkcs1_v1.5.c @@ -189,7 +189,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_pkcs1_v1_5_verify PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -221,6 +221,9 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* corrected the operation, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_pkcs1_v1_5_verify(UCHAR *message, UINT message_length, @@ -263,7 +266,7 @@ UINT status; } /* Decrypt the signature by the public key to get EM1 */ - status = (ctx -> public_cipher_method) -> nx_crypto_operation(NX_CRYPTO_ENCRYPT, + status = (ctx -> public_cipher_method) -> nx_crypto_operation(NX_CRYPTO_DECRYPT, NX_CRYPTO_NULL, ctx -> public_cipher_method, public_key, diff --git a/crypto_libraries/src/nx_crypto_sha2.c b/crypto_libraries/src/nx_crypto_sha2.c index 4434cb6c..452cd89c 100644 --- a/crypto_libraries/src/nx_crypto_sha2.c +++ b/crypto_libraries/src/nx_crypto_sha2.c @@ -46,6 +46,9 @@ const ULONG _sha2_round_constants[64] = #define SMALL_SIGMA_0(x) (RIGHT_SHIFT_CIRCULAR((x), 7) ^ RIGHT_SHIFT_CIRCULAR((x), 18) ^ ((x) >> 3)) #define SMALL_SIGMA_1(x) (RIGHT_SHIFT_CIRCULAR((x), 17) ^ RIGHT_SHIFT_CIRCULAR((x), 19) ^ ((x) >> 10)) +#define W0(t) ((((ULONG)buffer[(t) * 4]) << 24) | (((ULONG)buffer[((t) * 4) + 1]) << 16) | (((ULONG)buffer[((t) * 4) + 2]) << 8) | ((ULONG)buffer[((t) * 4) + 3])) +#define W16(t) (SMALL_SIGMA_1(w[(t) - 2]) + w[(t) - 7] + SMALL_SIGMA_0(w[(t) - 15]) + w[(t) - 16]) + /* Define the padding array. This is used to pad the message such that its length is 64 bits shy of being a multiple of 512 bits long. */ const UCHAR _nx_crypto_sha256_padding[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -271,7 +274,7 @@ ULONG needed_fill_bytes; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_sha256_digest_calculate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -308,24 +311,23 @@ ULONG needed_fill_bytes; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP UINT _nx_crypto_sha256_digest_calculate(NX_CRYPTO_SHA256 *context, UCHAR *digest, UINT algorithm) { -UCHAR bit_count_string[8]; +UINT bit_count_string[2]; ULONG current_byte_count; ULONG padding_bytes; /* Move the lower portion of the bit count into the array. */ - bit_count_string[0] = (UCHAR)(context -> nx_sha256_bit_count[1] >> 24); - bit_count_string[1] = (UCHAR)(context -> nx_sha256_bit_count[1] >> 16); - bit_count_string[2] = (UCHAR)(context -> nx_sha256_bit_count[1] >> 8); - bit_count_string[3] = (UCHAR)(context -> nx_sha256_bit_count[1]); - bit_count_string[4] = (UCHAR)(context -> nx_sha256_bit_count[0] >> 24); - bit_count_string[5] = (UCHAR)(context -> nx_sha256_bit_count[0] >> 16); - bit_count_string[6] = (UCHAR)(context -> nx_sha256_bit_count[0] >> 8); - bit_count_string[7] = (UCHAR)(context -> nx_sha256_bit_count[0]); + bit_count_string[0] = context -> nx_sha256_bit_count[1]; + NX_CRYPTO_CHANGE_ULONG_ENDIAN(bit_count_string[0]); + bit_count_string[1] = context -> nx_sha256_bit_count[0]; + NX_CRYPTO_CHANGE_ULONG_ENDIAN(bit_count_string[1]); /* Calculate the current byte count. */ current_byte_count = (context -> nx_sha256_bit_count[0] >> 3) & 0x3F; @@ -337,7 +339,7 @@ ULONG padding_bytes; _nx_crypto_sha256_update(context, (UCHAR*)_nx_crypto_sha256_padding, padding_bytes); /* Add the in the length. */ - _nx_crypto_sha256_update(context, bit_count_string, 8); + _nx_crypto_sha256_update(context, (UCHAR*)bit_count_string, 8); /* Now store the digest in the caller specified destination. */ digest[0] = (UCHAR)(context -> nx_sha256_states[0] >> 24); @@ -391,7 +393,7 @@ ULONG padding_bytes; /* FUNCTION RELEASE */ /* */ /* _nx_crypto_sha256_process_buffer PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* */ /* AUTHOR */ /* */ @@ -427,6 +429,9 @@ ULONG padding_bytes; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* improved performance, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ NX_CRYPTO_KEEP VOID _nx_crypto_sha256_process_buffer(NX_CRYPTO_SHA256 *context, UCHAR buffer[64]) @@ -440,21 +445,6 @@ ULONG a, b, c, d, e, f, g, h; /* Setup pointers to the word array. */ w = context -> nx_sha256_word_array; - /* Initialize the first 16 words of the word array, taking care of the - endian issues at the same time. */ - for (t = 0; t < 16; t++) - { - /* Setup each entry. */ - w[t] = (((ULONG)buffer[t * 4]) << 24) | (((ULONG)buffer[(t * 4) + 1]) << 16) | (((ULONG)buffer[(t * 4) + 2]) << 8) | ((ULONG)buffer[(t * 4) + 3]); - } - - /* Setup the remaining entries of the word array. */ - for (t = 16; t < 64; t++) - { - /* Setup each entry. */ - w[t] = SMALL_SIGMA_1(w[t - 2]) + w[t - 7] + SMALL_SIGMA_0(w[t - 15]) + w[t - 16]; - } - /* Initialize the state variables. */ a = context -> nx_sha256_states[0]; b = context -> nx_sha256_states[1]; @@ -466,20 +456,115 @@ ULONG a, b, c, d, e, f, g, h; h = context -> nx_sha256_states[7]; /* Now, perform Round operations. */ - for (t = 0; t < 64; t++) + for (t = 0; t < 16; t += 8) { + + /* Setup each entry. */ + w[t] = W0(t); temp1 = h + LARGE_SIGMA_1(e) + CH_FUNC(e, f, g) + _sha2_round_constants[t] + w[t]; temp2 = LARGE_SIGMA_0(a) + MAJ_FUNC(a, b, c); - h = g; - g = f; - f = e; - e = d + temp1; - d = c; - c = b; - b = a; + d = d + temp1; + h = temp1 + temp2; + + w[t + 1] = W0(t + 1); + temp1 = g + LARGE_SIGMA_1(d) + CH_FUNC(d, e, f) + _sha2_round_constants[t + 1] + w[t + 1]; + temp2 = LARGE_SIGMA_0(h) + MAJ_FUNC(h, a, b); + c = c + temp1; + g = temp1 + temp2; + + w[t + 2] = W0(t + 2); + temp1 = f + LARGE_SIGMA_1(c) + CH_FUNC(c, d, e) + _sha2_round_constants[t + 2] + w[t + 2]; + temp2 = LARGE_SIGMA_0(g) + MAJ_FUNC(g, h, a); + b = b + temp1; + f = temp1 + temp2; + + w[t + 3] = W0(t + 3); + temp1 = e + LARGE_SIGMA_1(b) + CH_FUNC(b, c, d) + _sha2_round_constants[t + 3] + w[t + 3]; + temp2 = LARGE_SIGMA_0(f) + MAJ_FUNC(f, g, h); + a = a + temp1; + e = temp1 + temp2; + + w[t + 4] = W0(t + 4); + temp1 = d + LARGE_SIGMA_1(a) + CH_FUNC(a, b, c) + _sha2_round_constants[t + 4] + w[t + 4]; + temp2 = LARGE_SIGMA_0(e) + MAJ_FUNC(e, f, g); + h = h + temp1; + d = temp1 + temp2; + + + w[t + 5] = W0(t + 5); + temp1 = c + LARGE_SIGMA_1(h) + CH_FUNC(h, a, b) + _sha2_round_constants[t + 5] + w[t + 5]; + temp2 = LARGE_SIGMA_0(d) + MAJ_FUNC(d, e, f); + g = g + temp1; + c = temp1 + temp2; + + w[t + 6] = W0(t + 6); + temp1 = b + LARGE_SIGMA_1(g) + CH_FUNC(g, h, a) + _sha2_round_constants[t + 6] + w[t + 6]; + temp2 = LARGE_SIGMA_0(c) + MAJ_FUNC(c, d, e); + f = f + temp1; + b = temp1 + temp2; + + w[t + 7] = W0(t + 7); + temp1 = a + LARGE_SIGMA_1(f) + CH_FUNC(f, g, h) + _sha2_round_constants[t + 7] + w[t + 7]; + temp2 = LARGE_SIGMA_0(b) + MAJ_FUNC(b, c, d); + e = e + temp1; a = temp1 + temp2; } + for (; t < 64; t += 8) + { + + /* Setup each entry. */ + w[t] = W16(t); + temp1 = h + LARGE_SIGMA_1(e) + CH_FUNC(e, f, g) + _sha2_round_constants[t] + w[t]; + temp2 = LARGE_SIGMA_0(a) + MAJ_FUNC(a, b, c); + d = d + temp1; + h = temp1 + temp2; + + w[t + 1] = W16(t + 1); + temp1 = g + LARGE_SIGMA_1(d) + CH_FUNC(d, e, f) + _sha2_round_constants[t + 1] + w[t + 1]; + temp2 = LARGE_SIGMA_0(h) + MAJ_FUNC(h, a, b); + c = c + temp1; + g = temp1 + temp2; + + w[t + 2] = W16(t + 2); + temp1 = f + LARGE_SIGMA_1(c) + CH_FUNC(c, d, e) + _sha2_round_constants[t + 2] + w[t + 2]; + temp2 = LARGE_SIGMA_0(g) + MAJ_FUNC(g, h, a); + b = b + temp1; + f = temp1 + temp2; + + w[t + 3] = W16(t + 3); + temp1 = e + LARGE_SIGMA_1(b) + CH_FUNC(b, c, d) + _sha2_round_constants[t + 3] + w[t + 3]; + temp2 = LARGE_SIGMA_0(f) + MAJ_FUNC(f, g, h); + a = a + temp1; + e = temp1 + temp2; + + w[t + 4] = W16(t + 4); + temp1 = d + LARGE_SIGMA_1(a) + CH_FUNC(a, b, c) + _sha2_round_constants[t + 4] + w[t + 4]; + temp2 = LARGE_SIGMA_0(e) + MAJ_FUNC(e, f, g); + h = h + temp1; + d = temp1 + temp2; + + + w[t + 5] = W16(t + 5); + temp1 = c + LARGE_SIGMA_1(h) + CH_FUNC(h, a, b) + _sha2_round_constants[t + 5] + w[t + 5]; + temp2 = LARGE_SIGMA_0(d) + MAJ_FUNC(d, e, f); + g = g + temp1; + c = temp1 + temp2; + + w[t + 6] = W16(t + 6); + temp1 = b + LARGE_SIGMA_1(g) + CH_FUNC(g, h, a) + _sha2_round_constants[t + 6] + w[t + 6]; + temp2 = LARGE_SIGMA_0(c) + MAJ_FUNC(c, d, e); + f = f + temp1; + b = temp1 + temp2; + + w[t + 7] = W16(t + 7); + temp1 = a + LARGE_SIGMA_1(f) + CH_FUNC(f, g, h) + _sha2_round_constants[t + 7] + w[t + 7]; + temp2 = LARGE_SIGMA_0(b) + MAJ_FUNC(b, c, d); + e = e + temp1; + a = temp1 + temp2; + + } + /* Save the resulting in this SHA256 context. */ context -> nx_sha256_states[0] += a; context -> nx_sha256_states[1] += b; diff --git a/docs/netx-duo-features.png b/docs/netx-duo-features.png new file mode 100644 index 00000000..aade102d Binary files /dev/null and b/docs/netx-duo-features.png differ diff --git a/nx_secure/CMakeLists.txt b/nx_secure/CMakeLists.txt index b225f781..f9599ddb 100644 --- a/nx_secure/CMakeLists.txt +++ b/nx_secure/CMakeLists.txt @@ -64,8 +64,19 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_session_start.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_session_trusted_certificate_add.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_session_trusted_certificate_remove.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_session_sliding_window_check.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_session_sliding_window_update.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_dtls_verify_mac.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_generate_client_key_exchange.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_generate_master_secret.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_generate_premaster_secret.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_generate_server_key_exchange.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_generate_session_keys.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_module_hash_compute.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_process_client_key_exchange.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_process_server_key_exchange.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_remote_certificate_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_session_keys_set.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_1_3_client_handshake.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_1_3_crypto_init.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_1_3_finished_hash_generate.c @@ -163,6 +174,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_iv_size_get.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_keys_set.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_packet_buffer_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_packet_pool_set.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_protocol_version_override.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_receive.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_session_receive_records.c @@ -180,6 +192,8 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_trusted_certificate_add.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_trusted_certificate_remove.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_tls_verify_mac.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_trusted_certificate_add.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_verify_mac.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_asn1_tlv_block_parse.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_certificate_chain_verify.c @@ -200,6 +214,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_extended_key_usage_extension_parse.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_extension_find.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_find_certificate_methods.c + ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_find_curve_method.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_free_certificate_get.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_key_usage_extension_parse.c ${CMAKE_CURRENT_LIST_DIR}/src/nx_secure_x509_local_certificate_find.c @@ -269,6 +284,7 @@ target_sources(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_delete.c ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_end.c ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_packet_buffer_set.c + ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_packet_pool_set.c ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_protocol_version_override.c ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_receive.c ${CMAKE_CURRENT_LIST_DIR}/src/nxe_secure_tls_session_renegotiate.c diff --git a/nx_secure/inc/nx_secure_dtls.h b/nx_secure/inc/nx_secure_dtls.h index c1de4f47..207d4207 100644 --- a/nx_secure/inc/nx_secure_dtls.h +++ b/nx_secure/inc/nx_secure_dtls.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_secure_dtls.h PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -43,6 +43,14 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* updated cookie handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ @@ -104,6 +112,8 @@ extern "C" { #define NX_SECURE_DTLS_COOKIE_LENGTH 32 #endif /* NX_SECURE_DTLS_COOKIE_LENGTH */ +/* The cookie size limit for DTLS 1.2 clinet. */ +#define NX_SECURE_DTLS_MAX_COOKIE_LENGTH 255 /* Event flag masks for DTLS retransmit thread. */ #define NX_SECURE_DTLS_ALL_EVENTS ((ULONG)0xFFFFFFFF) /* All event flags */ @@ -136,6 +146,8 @@ typedef struct NX_SECURE_DTLS_SESSION_STRUCT USHORT nx_secure_dtls_cookie_length; UCHAR nx_secure_dtls_cookie[NX_SECURE_DTLS_COOKIE_LENGTH]; + UCHAR *nx_secure_dtls_client_cookie_ptr; + /* The DTLS handshake messages have a sequence number that is incremented with each message sent. */ USHORT nx_secure_dtls_local_handshake_sequence; @@ -173,6 +185,9 @@ typedef struct NX_SECURE_DTLS_SESSION_STRUCT /* Pointer to our UDP packet receive queue. */ NX_PACKET *nx_secure_dtls_receive_queue_head; + /* Bitfield used for sliding window checks. */ + ULONG nx_secure_dtls_sliding_window; + /* Pointer to the thread waiting for packet. */ TX_THREAD *nx_secure_dtls_thread_suspended; @@ -437,7 +452,7 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length, + UINT *header_size, UINT *message_length, UINT *message_seq, UINT *fragment_offset, UINT *fragment_length); @@ -446,6 +461,8 @@ UINT _nx_secure_dtls_process_header(NX_SECURE_DTLS_SESSION *dtls_session, NX_PAC ULONG record_offset, USHORT *message_type, UINT *length, UCHAR *header_data, USHORT *header_length); +UINT _nx_secure_dtls_session_sliding_window_check(NX_SECURE_DTLS_SESSION *dtls_session, ULONG *sequence_number); +UINT _nx_secure_dtls_session_sliding_window_update(NX_SECURE_DTLS_SESSION *dtls_session, ULONG *sequence_number); UINT _nx_secure_dtls_process_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr, ULONG record_offset, ULONG *bytes_processed, ULONG wait_option); @@ -463,7 +480,7 @@ UINT _nx_secure_dtls_send_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET UCHAR record_type, ULONG wait_option); UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, - ULONG wait_option); + UINT data_length, ULONG wait_option); UINT _nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet); diff --git a/nx_secure/inc/nx_secure_tls.h b/nx_secure/inc/nx_secure_tls.h index 7eb5892d..419690bd 100644 --- a/nx_secure/inc/nx_secure_tls.h +++ b/nx_secure/inc/nx_secure_tls.h @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_secure_tls.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -52,6 +52,55 @@ /* bug, fixed certificate */ /* buffer allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* updated product constants, */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.5 */ +/* 04-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.6 */ +/* 06-02-2021 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.7 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* added state to cleanup */ +/* session cipher, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* support to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* enabled AEAD for TLS 1.3, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* updated product constants, */ +/* fixed compiler errors when */ +/* TX_SAFETY_CRITICAL is */ +/* enabled, increased default */ +/* pre-master sec size for PSK,*/ +/* updated alert message for */ +/* downgrade protection, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and added*/ +/* custom secret generation, */ +/* fixed renegotiation when */ +/* receiving in non-block mode,*/ +/* added function to set packet*/ +/* pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -72,11 +121,14 @@ extern "C" { #endif /* Include the ThreadX and port-specific data type file. */ +#include "tx_port.h" #ifdef NX_SECURE_SOURCE_CODE +#ifndef TX_SAFETY_CRITICAL #ifndef TX_DISABLE_ERROR_CHECKING #define TX_DISABLE_ERROR_CHECKING #endif +#endif #ifndef NX_DISABLE_ERROR_CHECKING #define NX_DISABLE_ERROR_CHECKING #endif @@ -97,7 +149,7 @@ extern "C" { #include "nx_secure_x509.h" -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) +#if defined(NX_SECURE_TLS_ENABLE_TLS_1_3) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) #ifndef NX_SECURE_ENABLE_AEAD_CIPHER #define NX_SECURE_ENABLE_AEAD_CIPHER #endif /* NX_SECURE_ENABLE_AEAD_CIPHER */ @@ -111,7 +163,7 @@ extern "C" { #define AZURE_RTOS_NETX_SECURE #define NETX_SECURE_MAJOR_VERSION 6 -#define NETX_SECURE_MINOR_VERSION 1 +#define NETX_SECURE_MINOR_VERSION 2 #define NETX_SECURE_PATCH_VERSION 0 /* The following symbols are defined for backward compatibility reasons. */ @@ -139,6 +191,14 @@ extern "C" { #define NX_SECURE_MEMMOVE memmove #endif /* NX_SECURE_MEMMOVE */ +#ifndef NX_SECURE_HASH_METADATA_CLONE +#define NX_SECURE_HASH_METADATA_CLONE NX_SECURE_MEMCPY +#endif /* NX_SECURE_HASH_METADATA_CLONE */ + +#ifndef NX_SECURE_HASH_CLONE_CLEANUP +#define NX_SECURE_HASH_CLONE_CLEANUP(x, y) +#endif /* NX_SECURE_HASH_CLONE_CLEANUP */ + /* Map NX_SECURE_CALLER_CHECKING_EXTERNS to NX_CALLER_CHECKING_EXTERNS, which is defined in nx_port.h.*/ @@ -248,6 +308,7 @@ extern "C" { #define NX_SECURE_TLS_RECORD_OVERFLOW 0x151 /* Received a TLSCiphertext record that had a length too long. */ #define NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED 0x152 /* Received a fragmented handshake message - take appropriate action at a higher level of the state machine. */ #define NX_SECURE_TLS_TRANSMIT_LOCKED 0x153 /* Another thread is transmitting. */ +#define NX_SECURE_TLS_DOWNGRADE_DETECTED 0x154 /* Detected an inappropriate TLS version downgrade by TLS 1.3 client. */ /* NX_CONTINUE is a symbol defined in NetX Duo 5.10. For backward compatibility, this symbol is defined here */ #if ((__NETXDUO_MAJOR_VERSION__ == 5) && (__NETXDUO_MINOR_VERSION__ == 9)) @@ -301,6 +362,9 @@ extern "C" { #define NX_SECURE_TLS_CLIENT_STATE_ENCRYPTED_EXTENSIONS 12 /* Client received and processed an encrypted extensions handshake message. */ #define NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY 13 /* A HelloRetryRequest has been received. We need to resend ClientHello. */ +#define NX_SECURE_TLS_HANDSHAKE_NO_FRAGMENT 0 /* There is no fragmented handshake message. */ +#define NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT 1 /* Received a fragmented handshake message. */ + /* TLS Alert message numbers from RFC 5246. */ #define NX_SECURE_TLS_ALERT_CLOSE_NOTIFY 0 #define NX_SECURE_TLS_ALERT_UNEXPECTED_MESSAGE 10 @@ -604,17 +668,11 @@ typedef struct NX_SECURE_VERSIONS_LIST_STRUCT #define NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENT_FINISHED (3) #define NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED (4) -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -#ifndef NX_SECURE_TLS_PREMASTER_SIZE -#define NX_SECURE_TLS_PREMASTER_SIZE (68) /* The pre-master secret should be at least 66 bytes for ECDH/ECDHE with secp521r1. */ -#endif -#else /* !NX_SECURE_ENABLE_ECC_CIPHERSUITE */ -#ifndef NX_SECURE_TLS_PREMASTER_SIZE -#define NX_SECURE_TLS_PREMASTER_SIZE (48) /* The pre-master secret is 48 bytes, except for PSK ciphersuites for which it may be more. */ -#endif -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #define NX_SECURE_TLS_RSA_PREMASTER_SIZE (48) /* The size of RSA encrypted pre-master secret. */ +#define NX_SECURE_TLS_EC_PREMASTER_SIZE (68) /* The size of pre-master secret for EC. */ +#ifndef NX_SECURE_TLS_MASTER_SIZE #define NX_SECURE_TLS_MASTER_SIZE (48) /* The master secret is also 48 bytes. */ +#endif #define NX_SECURE_TLS_MAX_KEY_SIZE (32) /* Maximum size of a session key in bytes. */ #define NX_SECURE_TLS_MAX_IV_SIZE (16) /* Maximum size of a session initialization vector in bytes. */ #define NX_SECURE_TLS_SESSION_ID_SIZE (256) /* Maximum size of a session ID value used for renegotiation in bytes. */ @@ -655,7 +713,9 @@ typedef struct NX_SECURE_VERSIONS_LIST_STRUCT * get the actual key values. We need to size the key material according to the maximum amount of * key material needed by any of the supported ciphersuites, times 2 because there are separate keys for * client and server. */ +#ifndef NX_SECURE_TLS_KEY_MATERIAL_SIZE #define NX_SECURE_TLS_KEY_MATERIAL_SIZE (2 * (NX_SECURE_TLS_MAX_HASH_SIZE + NX_SECURE_TLS_MAX_KEY_SIZE + NX_SECURE_TLS_MAX_IV_SIZE)) +#endif /* PSK-specific defines. If PSK is disabled, don't bring PSK types into the build. */ #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -678,6 +738,9 @@ typedef struct NX_SECURE_VERSIONS_LIST_STRUCT #define NX_SECURE_TLS_MAX_PSK_NONCE_SIZE (255) #endif +/* The pre-master secret size should be at least (2 * NX_SECURE_TLS_MAX_PSK_SIZE + 4) bytes for PSK cipher suites. */ +#define NX_SECURE_TLS_MIN_PREMASTER_SIZE_PSK (2 * NX_SECURE_TLS_MAX_PSK_SIZE + 4) + /* This structure holds the data for Pre-Shared Keys (PSKs) for use with the TLS PSK ciphersuites. The actual keys are generated from this data as part of the TLS handshake, but the user must provide this seed and @@ -733,6 +796,28 @@ typedef struct NX_SECURE_TLS_PSK_STORE_STRUCT #endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ +#ifndef NX_SECURE_TLS_PREMASTER_SIZE + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +#define NX_SECURE_TLS_MIN_PREMASTER_SIZE NX_SECURE_TLS_EC_PREMASTER_SIZE /* The pre-master secret should be at least 66 bytes for ECDH/ECDHE with secp521r1. */ +#else +#define NX_SECURE_TLS_MIN_PREMASTER_SIZE NX_SECURE_TLS_RSA_PREMASTER_SIZE /* The pre-master secret should be at least 48 bytes. */ +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + +#if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) + +#if NX_SECURE_TLS_MIN_PREMASTER_SIZE_PSK > NX_SECURE_TLS_MIN_PREMASTER_SIZE +#define NX_SECURE_TLS_PREMASTER_SIZE NX_SECURE_TLS_MIN_PREMASTER_SIZE_PSK /* The pre-master secret should be at least NX_SECURE_TLS_MIN_PREMASTER_SIZE_PSK bytes for PSK cipher suites. */ +#else +#define NX_SECURE_TLS_PREMASTER_SIZE NX_SECURE_TLS_MIN_PREMASTER_SIZE +#endif + +#else +#define NX_SECURE_TLS_PREMASTER_SIZE NX_SECURE_TLS_MIN_PREMASTER_SIZE +#endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || (NX_SECURE_TLS_TLS_1_3_ENABLED) */ + +#endif + /* TLS Ciphersuite lookup table. Contains all pertinent information for ciphersuites used in TLS operations. * The lookup is based on the first field, which will contain the defined TLS value for the ciphersuite. */ typedef struct NX_SECURE_TLS_CIPHERSUITE_INFO_STRUCT @@ -790,13 +875,13 @@ typedef struct NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA_STRUCT USHORT nx_secure_tls_ecdhe_private_key_length; /* Private key for ECDHE. */ - UCHAR nx_secure_tls_ecdhe_private_key[NX_SECURE_TLS_PREMASTER_SIZE]; + UCHAR nx_secure_tls_ecdhe_private_key[NX_SECURE_TLS_EC_PREMASTER_SIZE]; /* Length of the public key. */ USHORT nx_secure_tls_ecdhe_public_key_length; /* Public key for ECDHE. */ - UCHAR nx_secure_tls_ecdhe_public_key[4 * NX_SECURE_TLS_PREMASTER_SIZE]; + UCHAR nx_secure_tls_ecdhe_public_key[4 * NX_SECURE_TLS_EC_PREMASTER_SIZE]; } NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA; @@ -1074,6 +1159,21 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT ULONG nx_secure_tls_packet_buffer_size; ULONG nx_secure_tls_packet_buffer_original_size; + /* The number of bytes copied into packet/message buffer. */ + ULONG nx_secure_tls_packet_buffer_bytes_copied; + + /* The exepected number of bytes for an incoming handshake record. */ + ULONG nx_secure_tls_handshake_record_expected_length; + + /* Whether a handshake message is fragmented across several records. */ + USHORT nx_secure_tls_handshake_record_fragment_state; + + /* The offset of current record to be processed. */ + ULONG nx_secure_tls_record_offset; + + /* The prcessed number of bytes in current tls record. */ + ULONG nx_secure_tls_bytes_processed; + /* What type of socket is this? Client or server? */ UINT nx_secure_tls_socket_type; @@ -1094,12 +1194,16 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT USHORT nx_secure_tls_protocol_version_override; /* The highest supported protocol version obtained through negotiation. */ - USHORT nx_secure_tls_negotiated_highest_protocol_version; + USHORT nx_secure_tls_negotiated_highest_protocol_version; /* State of local and remote encryption - post ChangeCipherSpec. */ UCHAR nx_secure_tls_remote_session_active; UCHAR nx_secure_tls_local_session_active; + /* State of whether the client and server session cipher is initialized. */ + UCHAR nx_secure_tls_session_cipher_client_initialized; + UCHAR nx_secure_tls_session_cipher_server_initialized; + /* Chosen ciphersuite. */ const NX_SECURE_TLS_CIPHERSUITE_INFO *nx_secure_tls_session_ciphersuite; @@ -1125,6 +1229,10 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT the data in the extension is verified during secure renegotiation. */ USHORT nx_secure_tls_secure_renegotiation_verified; + /* This flag indicates that a server instance has requested a renegotiation + so we can differentiate between client initiated and server initiated. */ + USHORT nx_secure_tls_server_renegotiation_requested; + /* The verify data is named "remote" and "local" since it can be used by both TLS Client and TLS Server instances. */ UCHAR nx_secure_tls_remote_verify_data[NX_SECURE_TLS_FINISHED_HASH_SIZE]; @@ -1165,6 +1273,9 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT /* Flag to enable/disable session renegotiation at application's choosing. */ USHORT nx_secure_tls_renegotation_enabled; + + /* Flag to indicate that the local host initiated the renegotiation. */ + USHORT nx_secure_tls_local_initiated_renegotiation; #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ #ifndef NX_SECURE_TLS_SERVER_DISABLED @@ -1272,6 +1383,54 @@ typedef struct NX_SECURE_TLS_SESSION_STRUCT UINT nx_secure_tls_signature_algorithm; #endif + + /* Functions that can be replaced to implement custom key generation. */ + UINT (*nx_secure_generate_premaster_secret)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT session_type, USHORT *received_remote_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, VOID *tls_ecc_curves); + UINT (*nx_secure_generate_master_secret)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *pre_master_sec, UINT pre_master_sec_size, UCHAR *master_sec, + VOID *prf_metadata, ULONG prf_metadata_size); + UINT (*nx_secure_generate_session_keys)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *master_sec, VOID *prf_metadata, ULONG prf_metadata_size); + UINT (*nx_secure_session_keys_set)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UINT key_material_data_size, UINT is_client, UCHAR *session_cipher_initialized, + VOID *session_cipher_metadata, VOID **session_cipher_handler, ULONG session_cipher_metadata_size); +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + UINT(*nx_secure_process_server_key_exchange)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_CRYPTO *tls_crypto_table, + USHORT protocol_version, UCHAR *packet_buffer, UINT message_length, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); + UINT(*nx_secure_generate_client_key_exchange)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size); +#endif +#ifndef NX_SECURE_TLS_SERVER_DISABLED + UINT(*nx_secure_process_client_key_exchange)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + UCHAR *packet_buffer, UINT message_length, USHORT *received_remote_credentials, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); + UINT(*nx_secure_generate_server_key_exchange)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3, + NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); +#endif + UINT (*nx_secure_verify_mac)(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, UCHAR *mac_secret, ULONG sequence_num[NX_SECURE_TLS_SEQUENCE_NUMBER_SIZE], + UCHAR *header_data, USHORT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT *length, + VOID *hash_mac_metadata, ULONG hash_mac_metadata_size); + UINT (*nx_secure_remote_certificate_verify)(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate, ULONG current_time); + UINT (*nx_secure_trusted_certificate_add)(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate); } NX_SECURE_TLS_SESSION; /* TLS record types. */ @@ -1354,11 +1513,11 @@ UINT _nx_secure_tls_handshake_hash_init(NX_SECURE_TLS_SESSION *tls_session); UINT _nx_secure_tls_handshake_hash_update(NX_SECURE_TLS_SESSION *tls_session, UCHAR *data, UINT length); UINT _nx_secure_tls_handshake_process(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option); -UINT _nx_secure_tls_hash_record(NX_SECURE_TLS_SESSION *tls_session, +UINT _nx_secure_tls_hash_record(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, ULONG sequence_num[NX_SECURE_TLS_SEQUENCE_NUMBER_SIZE], UCHAR *header, UINT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT length, UCHAR *record_hash, UINT *hash_length, - UCHAR *mac_secret); + UCHAR *mac_secret, VOID *metadata, ULONG metadata_size); UINT _nx_secure_tls_key_material_init(NX_SECURE_TLS_KEY_MATERIAL *key_material); VOID _nx_secure_tls_map_error_to_alert(UINT error_number, UINT *alert_number, UINT *alert_level); @@ -1390,7 +1549,7 @@ UINT _nx_secure_tls_process_header(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET ULONG record_offset, USHORT *message_type, UINT *length, UCHAR *header_data, USHORT *header_length); UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length); + UINT *header_size, UINT *message_length); UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr, ULONG *bytes_processed, ULONG wait_option); UINT _nx_secure_tls_process_remote_certificate(NX_SECURE_TLS_SESSION *tls_session, @@ -1467,10 +1626,15 @@ UINT _nx_secure_tls_session_receive_records(NX_SECURE_TLS_SESSION *tls_session, UINT _nx_secure_tls_verify_mac(NX_SECURE_TLS_SESSION *tls_session, UCHAR *header_data, USHORT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT *length); #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -UINT _nx_secure_tls_ecc_generate_keys(NX_SECURE_TLS_SESSION *tls_session, UINT ecc_named_curve, USHORT sign_key, - UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data); -UINT _nx_secure_tls_find_curve_method(NX_SECURE_TLS_SESSION *tls_session, - USHORT named_curve, const NX_CRYPTO_METHOD **curve_method, UINT *curve_priority); +UINT _nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3, + NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + NX_SECURE_TLS_ECC *tls_ecc_curves, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT ecc_named_curve, USHORT sign_key, + UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size); +UINT _nx_secure_tls_find_curve_method(NX_SECURE_TLS_ECC *tls_ecc, USHORT named_curve, + const NX_CRYPTO_METHOD **curve_method, UINT *curve_priority); UINT _nx_secure_tls_proc_clienthello_sec_sa_extension(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_TLS_HELLO_EXTENSION *exts, UINT num_extensions, @@ -1540,6 +1704,8 @@ UINT _nx_secure_tls_session_delete(NX_SECURE_TLS_SESSION *tls_session); UINT _nx_secure_tls_session_end(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option); UINT _nx_secure_tls_session_packet_buffer_set(NX_SECURE_TLS_SESSION *session_ptr, UCHAR *buffer_ptr, ULONG buffer_size); +UINT _nx_secure_tls_session_packet_pool_set(NX_SECURE_TLS_SESSION *tls_session, + NX_PACKET_POOL *packet_pool); UINT _nx_secure_tls_session_protocol_version_override(NX_SECURE_TLS_SESSION *tls_session, USHORT protocol_version); UINT _nx_secure_tls_session_receive(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET **packet_ptr_ptr, @@ -1573,7 +1739,7 @@ UINT _nx_secure_tls_packet_allocate(NX_SECURE_TLS_SESSION *tls_session, NX_PACKE #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) UINT _nx_secure_tls_psk_add(NX_SECURE_TLS_SESSION *tls_session, UCHAR *pre_shared_key, UINT psk_length, UCHAR *psk_identity, UINT identity_length, UCHAR *hint, UINT hint_length); -UINT _nx_secure_tls_psk_find(NX_SECURE_TLS_SESSION *tls_session, UCHAR **psk_data, UINT *psk_length, +UINT _nx_secure_tls_psk_find(NX_SECURE_TLS_CREDENTIALS *tls_credentials, UCHAR **psk_data, UINT *psk_length, UCHAR *psk_identity_hint, UINT identity_length, UINT *psk_store_index); UINT _nx_secure_tls_client_psk_set(NX_SECURE_TLS_SESSION *tls_session, UCHAR *pre_shared_key, UINT psk_length, UCHAR *psk_identity, UINT identity_length, UCHAR *hint, UINT hint_length); @@ -1632,6 +1798,8 @@ UINT _nxe_secure_tls_session_delete(NX_SECURE_TLS_SESSION *tls_session); UINT _nxe_secure_tls_session_end(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option); UINT _nxe_secure_tls_session_packet_buffer_set(NX_SECURE_TLS_SESSION *session_ptr, UCHAR *buffer_ptr, ULONG buffer_size); +UINT _nxe_secure_tls_session_packet_pool_set(NX_SECURE_TLS_SESSION *tls_session, + NX_PACKET_POOL *packet_pool); UINT _nxe_secure_tls_session_protocol_version_override(NX_SECURE_TLS_SESSION *tls_session, USHORT protocol_version); UINT _nxe_secure_tls_session_receive(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET **packet_ptr_ptr, @@ -1671,6 +1839,52 @@ UINT _nxe_secure_tls_client_psk_set(NX_SECURE_TLS_SESSION *tls_session, UCHAR *p UCHAR *psk_identity, UINT identity_length, UCHAR *hint, UINT hint_length); #endif +UINT _nx_secure_process_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_CRYPTO *tls_crypto_table, + USHORT protocol_version, UCHAR *packet_buffer, UINT message_length, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); +UINT _nx_secure_process_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + UCHAR *packet_buffer, UINT message_length, USHORT *received_remote_credentials, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); +UINT _nx_secure_generate_premaster_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT session_type, USHORT *received_remote_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, VOID *tls_ecc_curves); +UINT _nx_secure_generate_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size); +UINT _nx_secure_generate_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3, + NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves); +UINT _nx_secure_generate_master_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *pre_master_sec, UINT pre_master_sec_size, UCHAR *master_sec, + VOID *prf_metadata, ULONG prf_metadata_size); +UINT _nx_secure_generate_session_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *master_sec, VOID *prf_metadata, ULONG prf_metadata_size); +UINT _nx_secure_session_keys_set(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UINT key_material_data_size, UINT is_client, UCHAR *session_cipher_initialized, + VOID *session_cipher_metadata, VOID **session_cipher_handler, ULONG session_cipher_metadata_size); +UINT _nx_secure_verify_mac(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, UCHAR *mac_secret, ULONG sequence_num[NX_SECURE_TLS_SEQUENCE_NUMBER_SIZE], + UCHAR *header_data, USHORT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT *length, + VOID *hash_mac_metadata, ULONG hash_mac_metadata_size); +UINT _nx_secure_remote_certificate_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate, ULONG current_time); +UINT _nx_secure_trusted_certificate_add(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate); +#ifdef NX_SECURE_CUSTOM_SECRET_GENERATION +UINT nx_secure_custom_secret_generation_init(NX_SECURE_TLS_SESSION *tls_session); +#endif + /* TLS component data declarations follow. */ /* Determine if the initialization function of this component is including diff --git a/nx_secure/inc/nx_secure_tls_api.h b/nx_secure/inc/nx_secure_tls_api.h index ab180e1b..0aa62ca0 100644 --- a/nx_secure/inc/nx_secure_tls_api.h +++ b/nx_secure/inc/nx_secure_tls_api.h @@ -26,7 +26,7 @@ /* APPLICATION INTERFACE DEFINITION RELEASE */ /* */ /* nx_secure_tls_api.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -44,6 +44,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and added*/ +/* API to set packet pool, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -94,6 +97,7 @@ extern "C" { #define nx_secure_tls_session_delete _nx_secure_tls_session_delete #define nx_secure_tls_session_end _nx_secure_tls_session_end #define nx_secure_tls_session_packet_buffer_set _nx_secure_tls_session_packet_buffer_set +#define nx_secure_tls_session_packet_pool_set _nx_secure_tls_session_packet_pool_set #define nx_secure_tls_session_protocol_version_override _nx_secure_tls_session_protocol_version_override #define nx_secure_tls_session_receive _nx_secure_tls_session_receive #define nx_secure_tls_session_renegotiate _nx_secure_tls_session_renegotiate @@ -136,6 +140,7 @@ extern "C" { #define nx_secure_tls_session_delete _nxe_secure_tls_session_delete #define nx_secure_tls_session_end _nxe_secure_tls_session_end #define nx_secure_tls_session_packet_buffer_set _nxe_secure_tls_session_packet_buffer_set +#define nx_secure_tls_session_packet_pool_set _nxe_secure_tls_session_packet_pool_set #define nx_secure_tls_session_protocol_version_override _nxe_secure_tls_session_protocol_version_override #define nx_secure_tls_session_receive _nxe_secure_tls_session_receive #define nx_secure_tls_session_renegotiate _nxe_secure_tls_session_renegotiate @@ -218,6 +223,8 @@ UINT nx_secure_tls_session_delete(NX_SECURE_TLS_SESSION *tls_session); UINT nx_secure_tls_session_end(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option); UINT nx_secure_tls_session_packet_buffer_set(NX_SECURE_TLS_SESSION *session_ptr, UCHAR *buffer_ptr, ULONG buffer_size); +UINT nx_secure_tls_session_packet_pool_set(NX_SECURE_TLS_SESSION *tls_session, + NX_PACKET_POOL *packet_pool); UINT nx_secure_tls_session_protocol_version_override(NX_SECURE_TLS_SESSION *tls_session, USHORT protocol_version); UINT nx_secure_tls_session_receive(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET **packet_ptr_ptr, diff --git a/nx_secure/inc/nx_secure_user_sample.h b/nx_secure/inc/nx_secure_user_sample.h index aba811b3..7b1c66d6 100644 --- a/nx_secure/inc/nx_secure_user_sample.h +++ b/nx_secure/inc/nx_secure_user_sample.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_secure_user.h PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* */ /* AUTHOR */ /* */ @@ -48,6 +48,16 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* macro to disable client */ +/* initiated renegotiation for */ +/* TLS server instances, */ +/* resulting in version 6.1.9 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* macro to custom secret size,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -93,11 +103,12 @@ #define NX_SECURE_ENABLE_PSK_CIPHERSUITES */ -/* NX_SECURE_AEAD_CIPHER_CHECK AEAD ciphersuites other than AES-CCM or AES-GCM. +/* NX_SECURE_AEAD_CIPHER_CHECK allows to detect user-implemented AEAD algorithms other than AES-CCM or + AES-GCM. It can be defined like #define NX_SECURE_AEAD_CIPHER_CHECK(a) ((a) == NEW_ALGORITHM_ID). It works only when NX_SECURE_ENABLE_AEAD_CIPHER is defined. By default this feature is not enabled. */ /* - #define NX_SECURE_AEAD_CIPHER_CHECK + #define NX_SECURE_AEAD_CIPHER_CHECK(a) NX_FALSE */ /* NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES enables self signed certificates. By default @@ -251,12 +262,24 @@ #define NX_SECURE_TLS_MINIMUM_MESSAGE_BUFFER_SIZE 4000 */ -/* NX_SECURE_TLS_PREMASTER_SIZE defines the sie of pre-master secret. +/* NX_SECURE_TLS_PREMASTER_SIZE defines the size of pre-master secret. The default value is 48. */ /* #define NX_SECURE_TLS_PREMASTER_SIZE 48 */ +/* NX_SECURE_TLS_MASTER_SIZE defines the size of master secret. + The default value is 48. */ +/* + #define NX_SECURE_TLS_MASTER_SIZE 48 +*/ + +/* NX_SECURE_TLS_KEY_MATERIAL_SIZE defines the size of key material. + The default value is (2 * (NX_SECURE_TLS_MAX_HASH_SIZE + NX_SECURE_TLS_MAX_KEY_SIZE + NX_SECURE_TLS_MAX_IV_SIZE)). */ +/* + #define NX_SECURE_TLS_KEY_MATERIAL_SIZE (2 * (NX_SECURE_TLS_MAX_HASH_SIZE + NX_SECURE_TLS_MAX_KEY_SIZE + NX_SECURE_TLS_MAX_IV_SIZE)) +*/ + /* NX_SECURE_TLS_CLIENT_DISABLED disables TLS server. By default TLS server is enabled. */ /* #define NX_SECURE_TLS_SERVER_DISABLED @@ -287,6 +310,20 @@ #define NX_SECURE_TLS_REQUIRE_RENEGOTIATION_EXT */ +/* NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION disables client-initiated renegotiation for TLS + servers. In some instances, client-initiated renegotiation can become a possible denial-of-service + vulnerability. */ +/* + #define NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION +*/ + +/* NX_SECURE_CUSTOM_SECRET_GENERATION enables the user to pass pointers of customized secret generation functions to + TLS in the user defined nx_secure_custom_secret_generation_init function. This will allow TLS to use customized + secret generation functions. */ +/* + #define NX_SECURE_CUSTOM_SECRET_GENERATION +*/ + /* NX_SECURE_X509_DISABLE_CRL disables X509 Certificate Revocation List check. By default this feature is enabled. */ /* @@ -305,4 +342,16 @@ #define NX_SECURE_X509_USE_EXTENDED_DISTINGUISHED_NAMES */ -#endif /* SRC_NX_SECURE_USER_H */ \ No newline at end of file +/* If the handshake hash state cannot be copied using memory copy on metadata, + NX_SECURE_HASH_METADATA_CLONE should be defined to a function that clones the hash state. + UINT nx_crypto_hash_clone(VOID *dest_metadata, VOID *source_metadata, ULONG length); + #define NX_SECURE_HASH_METADATA_CLONE nx_crypto_hash_clone +*/ + +/* If cleaning up is required for the handshake hash crypto after being cloned, + NX_SECURE_HASH_CLONE_CLEANUP macro should be defined to a clean up function: + UINT nx_crypto_clone_cleanup(VOID *metadata, ULONG length); + #define NX_SECURE_HASH_CLONE_CLEANUP nx_crypto_clone_cleanup +*/ + +#endif /* SRC_NX_SECURE_USER_H */ diff --git a/nx_secure/inc/nx_secure_x509.h b/nx_secure/inc/nx_secure_x509.h index f50e0300..a0189ed8 100644 --- a/nx_secure/inc/nx_secure_x509.h +++ b/nx_secure/inc/nx_secure_x509.h @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -26,7 +26,7 @@ /* COMPONENT DEFINITION RELEASE */ /* */ /* nx_secure_x509.h PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -44,6 +44,21 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed key usage bit order, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* supported hardware EC */ +/* private key, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* ignored public key in EC */ +/* private key, */ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* checked expiration for all */ +/* the certs in the chain, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -61,6 +76,46 @@ extern "C" { #include "nx_crypto.h" +/* Enable ECC by default. */ +#ifndef NX_SECURE_DISABLE_ECC_CIPHERSUITE +#ifndef NX_SECURE_ENABLE_ECC_CIPHERSUITE +#define NX_SECURE_ENABLE_ECC_CIPHERSUITE +#endif +#else +#undef NX_SECURE_ENABLE_ECC_CIPHERSUITE +#endif + +#ifndef NX_SECURE_CALLER_CHECKING_EXTERNS +#ifdef NX_CRYPTO_STANDALONE_ENABLE +#define NX_SECURE_CALLER_CHECKING_EXTERNS +#else +#define NX_SECURE_CALLER_CHECKING_EXTERNS NX_CALLER_CHECKING_EXTERNS +#endif +#endif + +#ifndef NX_THREADS_ONLY_CALLER_CHECKING +#ifdef NX_CRYPTO_STANDALONE_ENABLE +#define NX_THREADS_ONLY_CALLER_CHECKING +#endif +#endif + +/* Define memcpy, memset and memcmp functions used internal. */ +#ifndef NX_SECURE_MEMCPY +#define NX_SECURE_MEMCPY memcpy +#endif /* NX_SECURE_MEMCPY */ + +#ifndef NX_SECURE_MEMCMP +#define NX_SECURE_MEMCMP memcmp +#endif /* NX_SECURE_MEMCMP */ + +#ifndef NX_SECURE_MEMSET +#define NX_SECURE_MEMSET memset +#endif /* NX_SECURE_MEMSET */ + +#ifndef NX_SECURE_MEMMOVE +#define NX_SECURE_MEMMOVE memmove +#endif /* NX_SECURE_MEMMOVE */ + /* Define extensions used for user defined actions during X509 parse. */ #ifndef NX_SECURE_X509_PARSE_CERTIFICATE_EXTENSION #define NX_SECURE_X509_PARSE_CERTIFICATE_EXTENSION @@ -117,6 +172,18 @@ extern "C" { #define NX_SECURE_X509_EXT_KEY_USAGE_NOT_FOUND 0x19F /* In parsing an ExtendedKeyUsage extension, the specified usage was not found. */ #define NX_SECURE_X509_KEY_USAGE_ERROR 0x1A0 /* For use with key usage extensions - return this to indicate an error at the application level with key usage. */ +/* Return values from TLS. */ +#define NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER 0x1A1 /* A certificate provided by a server specified a public-key operation we do not support. */ +#define NX_SECURE_X509_INVALID_CERTIFICATE 0x1A2 /* An X509 certificate did not parse correctly. */ +#define NX_SECURE_X509_UNKNOWN_CERT_SIG_ALGORITHM 0x1A3 /* A certificate during verification had an unsupported signature algorithm. */ +#define NX_SECURE_X509_CERTIFICATE_SIG_CHECK_FAILED 0x1A4 /* A certificate signature verification check failed - certificate data did not match signature. */ +#define NX_SECURE_X509_INVALID_SELF_SIGNED_CERT 0x1A5 /* The remote host sent a self-signed certificate and NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES is not defined. */ +#define NX_SECURE_X509_ISSUER_CERTIFICATE_NOT_FOUND 0x1A6 /* A remote certificate was received with an issuer not in the local trusted store. */ +#define NX_SECURE_X509_NO_CERT_SPACE_ALLOCATED 0x1A7 /* No certificate space was allocated for incoming remote certificates. */ +#define NX_SECURE_X509_INSUFFICIENT_CERT_SPACE 0x1A8 /* Not enough certificate buffer space allocated for a certificate. */ +#define NX_SECURE_X509_CERT_ID_DUPLICATE 0x1A9 /* Tried to add a certificate with a numeric ID that was already used - needs to be unique. */ +#define NX_SECURE_X509_MISSING_CRYPTO_ROUTINE 0x1AA /* In attempting to perform a cryptographic operation, an entry in the ciphersuite table (or one of its function pointers) was NULL. */ + /* Defines for working with private key types. */ #define NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK (0xFFFF0000) @@ -124,6 +191,7 @@ extern "C" { #define NX_SECURE_X509_KEY_TYPE_NONE 0x00000000 /* Default value for no key. */ #define NX_SECURE_X509_KEY_TYPE_RSA_PKCS1_DER 0x00000001 /* DER-encoded PKCS-1 RSA private key. */ #define NX_SECURE_X509_KEY_TYPE_EC_DER 0x00000002 /* DER-encoded EC private key. */ +#define NX_SECURE_X509_KEY_TYPE_HARDWARE 0x00000003 /* Hardware private key */ /* ASN.1 Format: @@ -479,13 +547,6 @@ typedef struct NX_SECURE_EC_PRIVATE_KEY_STRUCT /* Size of the EC private key. */ USHORT nx_secure_ec_private_key_length; - /* Public key for EC. */ - /* This field is optional and it can be NX_NULL. */ - const UCHAR *nx_secure_ec_public_key; - - /* Size of the key used by the algorithm. */ - USHORT nx_secure_ec_public_key_length; - /* Named curve used. */ UINT nx_secure_ec_named_curve; @@ -759,6 +820,8 @@ UINT _nx_secure_x509_pkcs1_rsa_private_key_parse(const UCHAR *buffer, UINT lengt UINT _nx_secure_x509_ec_private_key_parse(const UCHAR *buffer, UINT length, UINT *bytes_processed, NX_SECURE_EC_PRIVATE_KEY *ec_key); +UINT _nx_secure_x509_find_curve_method(USHORT named_curve, const NX_CRYPTO_METHOD **curve_method); + #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ /* CRL parsing. */ @@ -877,7 +940,7 @@ UINT _nx_secure_x509_certificate_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, /* Verify a given certificate chain to see if the end-entity certificate can be traced through the chain to a trust anchor. */ UINT _nx_secure_x509_certificate_chain_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, - NX_SECURE_X509_CERT *certificate); + NX_SECURE_X509_CERT *certificate, ULONG current_time); /* Parse an OID string, returning an internally-used constant (defined above) for use in other parsing. */ VOID _nx_secure_x509_oid_parse(const UCHAR *oid, ULONG length, UINT *oid_value); diff --git a/nx_secure/ports/nx_secure_port.h b/nx_secure/ports/nx_secure_port.h index 501532cf..32b23984 100644 --- a/nx_secure/ports/nx_secure_port.h +++ b/nx_secure/ports/nx_secure_port.h @@ -69,7 +69,7 @@ #ifdef NX_SECURE_SYSTEM_INIT CHAR _nx_secure_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Secure Generic Version G6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Secure Generic Version G6.2.0 *"; #else extern CHAR _nx_secure_version_id[]; #endif diff --git a/nx_secure/src/nx_secure_crypto_rng_self_test.c b/nx_secure/src/nx_secure_crypto_rng_self_test.c index b7808e8b..96895cda 100644 --- a/nx_secure/src/nx_secure_crypto_rng_self_test.c +++ b/nx_secure/src/nx_secure_crypto_rng_self_test.c @@ -31,14 +31,14 @@ #define NX_SECURE_RNG_CHECK_COUNT 3 #endif /* NX_SECURE_RNG_CHECK_COUNT */ -UINT _nx_secure_crypto_rng_self_test(); +UINT _nx_secure_crypto_rng_self_test(VOID); /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_crypto_rng_self_test PORTABLE C */ -/* 6.1 */ +/* 6.1.5 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,9 +71,12 @@ UINT _nx_secure_crypto_rng_self_test(); /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 03-02-2021 Yuxin Zhou Modified comment(s), and */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ /* */ /**************************************************************************/ -UINT _nx_secure_crypto_rng_self_test() +UINT _nx_secure_crypto_rng_self_test(VOID) { #ifdef NX_SECURE_POWER_ON_SELF_TEST_MODULE_INTEGRITY_CHECK UINT results[NX_SECURE_RNG_CHECK_COUNT]; diff --git a/nx_secure/src/nx_secure_dtls_client_handshake.c b/nx_secure/src/nx_secure_dtls_client_handshake.c index a6ad765e..54bc4595 100644 --- a/nx_secure/src/nx_secure_dtls_client_handshake.c +++ b/nx_secure/src/nx_secure_dtls_client_handshake.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,7 +72,6 @@ /* _nx_secure_tls_generate_premaster_secret */ /* Generate premaster secret */ /* _nx_secure_tls_handshake_hash_update Update Finished hash */ -/* _nx_secure_tls_map_error_to_alert Map internal error to alert */ /* _nx_secure_tls_process_certificate_request */ /* Process certificate request */ /* _nx_secure_tls_process_finished Process Finished message */ @@ -81,7 +80,6 @@ /* _nx_secure_tls_process_server_key_exchange */ /* Process ServerKeyExchange */ /* _nx_secure_tls_process_serverhello Process ServerHello */ -/* _nx_secure_tls_send_alert Send DTLS alert */ /* _nx_secure_tls_send_certificate Send DTLS certificate */ /* _nx_secure_tls_send_certificate_verify */ /* Send certificate verify */ @@ -110,6 +108,17 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, added null */ +/* pointer checking, */ +/* resulting in version 6.1.3 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* removed duplicated alert, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, @@ -118,14 +127,11 @@ UINT _nx_secure_dtls_client_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHA #ifndef NX_SECURE_TLS_CLIENT_DISABLED UINT status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UCHAR *data_start = NX_NULL; NX_PACKET *send_packet = NX_NULL; NX_PACKET_POOL *packet_pool; -UINT error_number; -UINT alert_number; -UINT alert_level; UINT message_seq; UINT fragment_offset; UINT fragment_length; @@ -146,6 +152,7 @@ NX_SECURE_TLS_SESSION *tls_session; while (data_length > 0) { + header_bytes = data_length; /* First, process the handshake message to get our state and any data therein. */ status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes, @@ -162,13 +169,19 @@ NX_SECURE_TLS_SESSION *tls_session; * - Once fragment is reassembled, check message sequence for repeats */ - /* For now, if we see a repeated message sequence, assume an unnecessary retransmission and ignore. */ + /* If we see a repeated message sequence, assume an unnecessary retransmission and ignore. */ if (message_seq < dtls_session -> nx_secure_dtls_remote_handshake_sequence) { /* Re-transmitted message. */ return(NX_SUCCESS); } + /* Check the fragment_length with the lenght of packet buffer. */ + if ((header_bytes + fragment_length) > data_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Check available area of buffer. */ if ((fragment_offset + fragment_length) > tls_session -> nx_secure_tls_packet_buffer_size || (header_bytes + message_length) > tls_session -> nx_secure_tls_packet_buffer_size) @@ -176,6 +189,12 @@ NX_SECURE_TLS_SESSION *tls_session; return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); } + /* If this message sequence isn't what we expect, continue reading packets. */ + if(message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence) + { + return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE); + } + /* If we have a new sequence number, we have a new record (may be fragmented). Unless the sequence number is 0, which means it is the first record. */ if (message_seq > dtls_session -> nx_secure_dtls_remote_handshake_sequence || (message_seq == 0 && fragment_offset == 0)) @@ -185,6 +204,11 @@ NX_SECURE_TLS_SESSION *tls_session; dtls_session -> nx_secure_dtls_fragment_length = message_length; } + if (fragment_length > dtls_session -> nx_secure_dtls_fragment_length) + { + return(NX_SECURE_TLS_INVALID_PACKET); + } + /* When we receive a message fragment, subtract it from the current fragment length. */ dtls_session -> nx_secure_dtls_fragment_length -= fragment_length; @@ -204,9 +228,9 @@ NX_SECURE_TLS_SESSION *tls_session; dtls_session -> nx_secure_dtls_expected_handshake_sequence = 0; } - /* If the recontructed message has a sequence number less than the expected, it's + /* If the recontructed message has a sequence not equal to the expected, it's a retransmission we need to ignore. */ - if (message_seq < dtls_session -> nx_secure_dtls_expected_handshake_sequence) + if (message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence) { return(NX_SUCCESS); } @@ -336,24 +360,8 @@ NX_SECURE_TLS_SESSION *tls_session; /* Check for errors in processing messages. */ if (status != NX_SECURE_TLS_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - } - return(error_number); + return(status); } /* Now take any actions based on state set in the message processing. */ @@ -381,7 +389,7 @@ NX_SECURE_TLS_SESSION *tls_session; /* Get ClientHello packet from header of transmit queue. */ send_packet = dtls_session -> nx_secure_dtls_transmit_sent_head; - if (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE)) + if ((send_packet == NX_NULL) || (send_packet -> nx_packet_queue_next != ((NX_PACKET *)NX_DRIVER_TX_DONE))) { /* Invalid packet. */ @@ -567,33 +575,15 @@ NX_SECURE_TLS_SESSION *tls_session; } /* If we have an error at this point, we have experienced a problem in sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ + handshake messages, which is some type of internal issue. */ if (status != NX_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - } - - return(error_number); + return(status); } - /* Advance the buffer pointer past the message. */ - packet_buffer += (message_length + header_bytes); + /* Advance the buffer pointer past the fragment. */ + packet_buffer += (fragment_length + header_bytes); } /* End while. */ return(NX_SUCCESS); #else /* TLS Client disabled. */ diff --git a/nx_secure/src/nx_secure_dtls_process_clienthello.c b/nx_secure/src/nx_secure_dtls_process_clienthello.c index dae013b1..08fb37be 100644 --- a/nx_secure/src/nx_secure_dtls_process_clienthello.c +++ b/nx_secure/src/nx_secure_dtls_process_clienthello.c @@ -40,7 +40,7 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_clienthello PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -90,6 +90,10 @@ static UINT _nx_secure_dtls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_IN /* renegotiation bug, */ /* improved negotiation logic, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, @@ -243,6 +247,12 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; compression_methods_length = packet_buffer[0]; packet_buffer += 1; + /* Message length overflow. */ + if (((UINT)(packet_buffer - packet_buffer_start + compression_methods_length)) > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Make sure NULL compression method is supported. */ status = NX_SECURE_TLS_BAD_COMPRESSION_METHOD; for (i = 0; i < compression_methods_length; ++i) diff --git a/nx_secure/src/nx_secure_dtls_process_handshake_header.c b/nx_secure/src/nx_secure_dtls_process_handshake_header.c index ec08cc95..69fe356d 100644 --- a/nx_secure/src/nx_secure_dtls_process_handshake_header.c +++ b/nx_secure/src/nx_secure_dtls_process_handshake_header.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_handshake_header PORTABLE C */ -/* 6.1 */ +/* 6.1.3 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -45,7 +45,8 @@ /* */ /* packet_buffer Pointer to incoming packet */ /* message_type Return message type value */ -/* header_size Return size of header */ +/* header_size Input size of packet buffer */ +/* Return size of header */ /* message_length Return length of message */ /* message_seq Return sequence of message */ /* fragment_offset Return offset of fragment */ @@ -71,13 +72,24 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length, + UINT *header_size, UINT *message_length, UINT *message_seq, UINT *fragment_offset, UINT *fragment_length) { + + /* Check buffer length. */ + if (*header_size < NX_SECURE_DTLS_HANDSHAKE_HEADER_SIZE) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* The message being passed in to this function should already be stripped of the TLS header so the first byte in the packet/record is our handshake message type. */ *message_type = packet_buffer[0]; diff --git a/nx_secure/src/nx_secure_dtls_process_header.c b/nx_secure/src/nx_secure_dtls_process_header.c index 7a153bf4..1d10044f 100644 --- a/nx_secure/src/nx_secure_dtls_process_header.c +++ b/nx_secure/src/nx_secure_dtls_process_header.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_header PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_header(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr, @@ -146,16 +149,15 @@ NX_SECURE_TLS_SESSION *tls_session; * To handle the message ordering properly, the epochs must match (the CCS * message changes the epoch after being sent or received so new messages * should all have the new epoch). When the epochs match, the sequence numbers - * can be compared. We have 3 cases to handle: + * can be compared. We have 2 cases to handle: * 1) The incoming sequence number is less than or equal to the local count. - * - This is a retransmission of an earlier message and should be ignored. - * 2) The incoming sequence is equal to the local count + 1 - * - This is the valid next message in the sequence - * 3) The incoming sequence is greater than the local count + 1 + * - This is a retransmission of an earlier message and should be ignored (handshake) + * - If the earlier message was NOT seen, check the sliding window to accept/ignore + * 2) The incoming sequence is greater than the local count + 1 * - A message was dropped. We need to handle the out-of-order - * message, either by ignoring it (and waiting for the retransmission) - * or by buffering the message until we get to the proper - * sequence number. + * message. + * - During the handshake, accept this record as the next valid message + * - During the session, accept and update the sliding window. */ @@ -185,37 +187,89 @@ NX_SECURE_TLS_SESSION *tls_session; /* Now check the sequence number against what we already received to see if it is a new message or a retransmission from the remote host. */ - if (remote_sequence_number[0] > 0 || remote_sequence_number[1] > 0) + + /* Sliding window (RFC 6347, Section 4.1.2.6): + Duplicates are rejected through the use of a sliding receive window. + (How the window is implemented is a local matter, but the following + text describes the functionality that the implementation must + exhibit.) A minimum window size of 32 MUST be supported, but a + window size of 64 is preferred and SHOULD be employed as the default. + Another window size (larger than the minimum) MAY be chosen by the + receiver. (The receiver does not notify the sender of the window + size.) + + The "right" edge of the window represents the highest validated + sequence number value received on this session. Records that contain + sequence numbers lower than the "left" edge of the window are + rejected. Packets falling within the window are checked against a + list of received packets within the window. An efficient means for + performing this check, based on the use of a bit mask, is described + in Section 3.4.3 of [ESP]. + + If the received record falls within the window and is new, or if the + packet is to the right of the window, then the receiver proceeds to + MAC verification. If the MAC validation fails, the receiver MUST + discard the received record as invalid. The receive window is + updated only if the MAC verification succeeds. + */ + + /* Handshake messages. No sliding window check. */ + if (remote_epoch == 0 && (remote_sequence_number[0] > 0 || remote_sequence_number[1] > 0)) { if (remote_sequence_number[0] < tls_session -> nx_secure_tls_remote_sequence_number[0] || - remote_sequence_number[1] < tls_session -> nx_secure_tls_remote_sequence_number[1]) + remote_sequence_number[1] <= tls_session -> nx_secure_tls_remote_sequence_number[1]) { - /* We already saw this message! */ + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); + return(NX_SECURE_TLS_REPEAT_MESSAGE_RECEIVED); } - else if (remote_sequence_number[1] != (tls_session -> nx_secure_tls_remote_sequence_number[1] + 1)) + + /* Update the current sequence number to match what we just received. */ + tls_session -> nx_secure_tls_remote_sequence_number[0] = remote_sequence_number[0]; + tls_session -> nx_secure_tls_remote_sequence_number[1] = remote_sequence_number[1]; + + /* The sequence number is larger than our current. This is a valid handshake record or + out-of-order newer application data record. Update the current sequence number after the MAC check. */ + /* Swap back now that comparisons are done. */ + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); + + } + else if (remote_epoch > 0 && (remote_sequence_number[0] > 0 || remote_sequence_number[1] > 0)) + { + /* Changed our Epoch, so new sequence number */ + if (remote_sequence_number[0] < tls_session -> nx_secure_tls_remote_sequence_number[0] || + remote_sequence_number[1] <= tls_session -> nx_secure_tls_remote_sequence_number[1]) { - /* Out-of-order message - we missed a datagram! */ - NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); - NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); - return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE); + /* Incoming number is less than the "right" side of our sliding window. Check if + it falls in the sliding window (greater than the "left" side and not seen yet). */ + status = _nx_secure_dtls_session_sliding_window_check(dtls_session, remote_sequence_number); + + if(status == NX_FALSE) + { + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); + return(NX_SECURE_TLS_REPEAT_MESSAGE_RECEIVED); + } } - else - { - /* Update the current sequence number to match what we just received. */ - tls_session -> nx_secure_tls_remote_sequence_number[0] = remote_sequence_number[0]; - tls_session -> nx_secure_tls_remote_sequence_number[1] = remote_sequence_number[1]; - /* Swap back now that comparisons are done. */ - NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); - NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); + /* Update the sliding window with the new sequence number. This updates the sequence number as well. */ + status = _nx_secure_dtls_session_sliding_window_update(dtls_session, remote_sequence_number); + + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[0]); + NX_CHANGE_ULONG_ENDIAN(tls_session -> nx_secure_tls_remote_sequence_number[1]); + + if(status != NX_SUCCESS) + { + return(status); } + } else if (remote_epoch == 0) { - + /* Remote epoch of 0 with sequence number of 0 indicates start of new session. */ #ifndef NX_SECURE_TLS_CLIENT_DISABLED if ((tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT) && (tls_session -> nx_secure_tls_client_state != NX_SECURE_TLS_CLIENT_STATE_IDLE)) @@ -246,10 +300,9 @@ NX_SECURE_TLS_SESSION *tls_session; { /* Check the record's protocol version against the current session. */ status = _nx_secure_tls_check_protocol_version(tls_session, protocol_version, NX_SECURE_DTLS); - return(status); } - return(NX_SUCCESS); + return(status); } #endif /* NX_SECURE_ENABLE_DTLS */ diff --git a/nx_secure/src/nx_secure_dtls_process_helloverifyrequest.c b/nx_secure/src/nx_secure_dtls_process_helloverifyrequest.c index 1a25cba2..59953a41 100644 --- a/nx_secure/src/nx_secure_dtls_process_helloverifyrequest.c +++ b/nx_secure/src/nx_secure_dtls_process_helloverifyrequest.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_helloverifyrequest PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* updated cookie handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_helloverifyrequest(NX_SECURE_DTLS_SESSION *dtls_session, @@ -90,18 +93,20 @@ UINT length; dtls_session -> nx_secure_dtls_cookie_length = packet_buffer[length]; length += 1; - if (dtls_session -> nx_secure_dtls_cookie_length > sizeof(dtls_session -> nx_secure_dtls_cookie)) + if (dtls_session -> nx_secure_dtls_cookie_length > NX_SECURE_DTLS_MAX_COOKIE_LENGTH) { + dtls_session -> nx_secure_dtls_cookie_length = 0; return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } if ((3u + dtls_session -> nx_secure_dtls_cookie_length) > message_length) { + dtls_session -> nx_secure_dtls_cookie_length = 0; return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } - /* Save off the cookie. */ - NX_SECURE_MEMCPY(dtls_session -> nx_secure_dtls_cookie, &packet_buffer[length], dtls_session -> nx_secure_dtls_cookie_length); /* Use case of memcpy is verified. */ + /* Save off the cookie pointer. */ + dtls_session -> nx_secure_dtls_client_cookie_ptr = &packet_buffer[length]; /* Set our state to indicate we sucessfully parsed the HelloVerifyRequest. */ dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_HELLO_VERIFY; diff --git a/nx_secure/src/nx_secure_dtls_process_record.c b/nx_secure/src/nx_secure_dtls_process_record.c index 906eb1e1..dfcb1065 100644 --- a/nx_secure/src/nx_secure_dtls_process_record.c +++ b/nx_secure/src/nx_secure_dtls_process_record.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_process_record PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -80,6 +80,13 @@ /* adjusted logic for TLS */ /* modifications, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_process_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr, @@ -94,6 +101,8 @@ UINT message_length; UCHAR *packet_data; NX_SECURE_TLS_SESSION *tls_session; UCHAR epoch_seq_num[8]; +ULONG seq_num_rewind[2]; +ULONG window_rewind; NX_PACKET *decrypted_packet; /* Basic state machine: @@ -108,6 +117,10 @@ NX_PACKET *decrypted_packet; header_length = NX_SECURE_DTLS_RECORD_HEADER_SIZE; + /* Save the sequence number in case we reject a record (e.g. handshake message missing). */ + seq_num_rewind[0] = tls_session -> nx_secure_tls_remote_sequence_number[0]; + seq_num_rewind[1] = tls_session -> nx_secure_tls_remote_sequence_number[1]; + window_rewind = dtls_session -> nx_secure_dtls_sliding_window; /* Process the DTLS record header, which will set the state. */ status = _nx_secure_dtls_process_header(dtls_session, packet_ptr, record_offset, &message_type, &message_length, header_data, &header_length); @@ -192,14 +205,16 @@ NX_PACKET *decrypted_packet; /* Check to see if decryption or verification failed. */ if(error_status != NX_SECURE_TLS_SUCCESS) { - /* Decryption failed. */ + /* Decryption failed. Rewind the sequence number and sliding window. */ + tls_session -> nx_secure_tls_remote_sequence_number[0] = seq_num_rewind[0]; + tls_session -> nx_secure_tls_remote_sequence_number[1] = seq_num_rewind[1]; + dtls_session -> nx_secure_dtls_sliding_window = window_rewind; return(error_status); } /* Check to see if decryption or verification failed. */ if (status == NX_SECURE_TLS_SUCCESS) { - /* Copy data to original packet to keep IP header available. */ /* Note: At the point of this memcpy the plaintext should never be larger than the cipher. Assertion check is to protect against future changes inadvertently causing an overflow. */ @@ -225,11 +240,17 @@ NX_PACKET *decrypted_packet; case NX_SECURE_TLS_CHANGE_CIPHER_SPEC: /* Received a ChangeCipherSpec message - from now on all messages from remote host will be encrypted using the session keys. */ - _nx_secure_tls_process_changecipherspec(tls_session, packet_data, message_length); - - - /* New epoch if we receive a CCS message. */ - dtls_session -> nx_secure_dtls_remote_epoch = (USHORT)(dtls_session -> nx_secure_dtls_remote_epoch + 1); + status = _nx_secure_tls_process_changecipherspec(tls_session, packet_data, message_length); + if(status != NX_SUCCESS) + { + /* Received out-of-order CCS message. */ + status = NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE; + } + else + { + /* New epoch if we receive a CCS message. */ + dtls_session -> nx_secure_dtls_remote_epoch = (USHORT)(dtls_session -> nx_secure_dtls_remote_epoch + 1); + } break; case NX_SECURE_TLS_ALERT: @@ -246,7 +267,7 @@ NX_PACKET *decrypted_packet; /* The socket is a TLS server, so process incoming handshake messages in that context. */ if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) { - status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, wait_option); + status = _nx_secure_dtls_server_handshake(dtls_session, packet_data, message_length, wait_option); } #endif #ifndef NX_SECURE_TLS_CLIENT_DISABLED @@ -275,6 +296,17 @@ NX_PACKET *decrypted_packet; break; } + /* If we received an out-of-order handshake message, rewind the sequence number. */ + if(status == NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE) + { + /* Handshake message was not what we expected, so rewind the sequence number. */ + tls_session -> nx_secure_tls_remote_sequence_number[0] = seq_num_rewind[0]; + tls_session -> nx_secure_tls_remote_sequence_number[1] = seq_num_rewind[1]; + dtls_session -> nx_secure_dtls_sliding_window = window_rewind; + status = NX_CONTINUE; + } + + return(status); } #endif /* NX_SECURE_ENABLE_DTLS */ diff --git a/nx_secure/src/nx_secure_dtls_retransmit_queue_flush.c b/nx_secure/src/nx_secure_dtls_retransmit_queue_flush.c index f5a70af5..97804965 100644 --- a/nx_secure/src/nx_secure_dtls_retransmit_queue_flush.c +++ b/nx_secure/src/nx_secure_dtls_retransmit_queue_flush.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_retransmit_queue_flush PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* released packet securely, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed packet leak, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ VOID _nx_secure_dtls_retransmit_queue_flush(NX_SECURE_DTLS_SESSION *dtls_session) @@ -92,8 +95,7 @@ NX_PACKET *next_packet_ptr; /* Loop to clear all the packets out. */ while (packet_ptr && - (packet_ptr != (NX_PACKET *)NX_PACKET_ENQUEUED) && - (packet_ptr -> nx_packet_queue_next == (NX_PACKET *)NX_DRIVER_TX_DONE)) + (packet_ptr != (NX_PACKET *)NX_PACKET_ENQUEUED)) { /* Disable interrupts. */ diff --git a/nx_secure/src/nx_secure_dtls_send_clienthello.c b/nx_secure/src/nx_secure_dtls_send_clienthello.c index b89d0fb5..9d75d985 100644 --- a/nx_secure/src/nx_secure_dtls_send_clienthello.c +++ b/nx_secure/src/nx_secure_dtls_send_clienthello.c @@ -39,7 +39,7 @@ static UINT _nx_secure_dtls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SE /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_send_clienthello PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -81,6 +81,9 @@ static UINT _nx_secure_dtls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SE /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 01-31-2022 Yuxin Zhou Modified comment(s), and */ +/* updated cookie handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_send_clienthello(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet) @@ -171,10 +174,10 @@ USHORT protocol_version; /* Move the data to insert cookie. */ NX_SECURE_MEMMOVE(packet_buffer + dtls_session -> nx_secure_dtls_cookie_length, - packet_buffer, (UINT)(send_packet -> nx_packet_append_ptr - packet_buffer)); + packet_buffer, (UINT)(send_packet -> nx_packet_append_ptr - packet_buffer)); /* Use case of memmove is verified. */ /* Set cookie. */ - NX_SECURE_MEMCPY(packet_buffer, dtls_session -> nx_secure_dtls_cookie, + NX_SECURE_MEMCPY(packet_buffer, dtls_session -> nx_secure_dtls_client_cookie_ptr, dtls_session -> nx_secure_dtls_cookie_length); /* Use case of memcpy is verified. */ length += dtls_session -> nx_secure_dtls_cookie_length; diff --git a/nx_secure/src/nx_secure_dtls_send_record.c b/nx_secure/src/nx_secure_dtls_send_record.c index 24fd00ae..d3cc68b0 100644 --- a/nx_secure/src/nx_secure_dtls_send_record.c +++ b/nx_secure/src/nx_secure_dtls_send_record.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_send_record PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -86,6 +86,9 @@ /* verified memcpy use cases, */ /* released packet securely, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked seq number overflow,*/ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_send_record(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *send_packet, @@ -169,6 +172,14 @@ UCHAR epoch_seq_num[8]; { /* Check for overflow of the 32-bit number. */ tls_session -> nx_secure_tls_local_sequence_number[1]++; + + if (tls_session -> nx_secure_tls_local_sequence_number[1] == 0) + { + + /* Check for overflow of the 64-bit unsigned number. As it should not reach here + in practical, we return a general error to prevent overflow theoretically. */ + return(NX_NOT_SUCCESSFUL); + } } tls_session -> nx_secure_tls_local_sequence_number[0]++; diff --git a/nx_secure/src/nx_secure_dtls_server_handshake.c b/nx_secure/src/nx_secure_dtls_server_handshake.c index b437bf33..b1f2482d 100644 --- a/nx_secure/src/nx_secure_dtls_server_handshake.c +++ b/nx_secure/src/nx_secure_dtls_server_handshake.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_server_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -48,6 +48,7 @@ /* */ /* dtls_session TLS control block */ /* packet_buffer Pointer into record buffer */ +/* data_length Length of data */ /* wait_option Controls timeout actions */ /* */ /* OUTPUT */ @@ -72,11 +73,9 @@ /* _nx_secure_tls_generate_keys Generate session keys */ /* _nx_secure_tls_handshake_hash_init Initialize Finished hash */ /* _nx_secure_tls_handshake_hash_update Update Finished hash */ -/* _nx_secure_tls_map_error_to_alert Map internal error to alert */ /* _nx_secure_tls_process_client_key_exchange */ /* Process key exchange */ /* _nx_secure_tls_process_finished Process Finished message */ -/* _nx_secure_tls_send_alert Send TLS alert */ /* _nx_secure_tls_send_certificate Send TLS certificate */ /* _nx_secure_tls_send_changecipherspec Send ChangeCipherSpec */ /* _nx_secure_tls_send_finished Send Finished message */ @@ -110,15 +109,25 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* removed duplicated alert, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_server_handshake(NX_SECURE_DTLS_SESSION *dtls_session, UCHAR *packet_buffer, - ULONG wait_option) + UINT data_length, ULONG wait_option) { #ifndef NX_SECURE_TLS_SERVER_DISABLED UINT status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT message_seq; UINT fragment_offset; @@ -127,10 +136,7 @@ NX_PACKET *send_packet; NX_PACKET_POOL *packet_pool; UCHAR *packet_start; NX_SECURE_TLS_SESSION *tls_session; -UINT error_number; -UINT alert_number; -UINT alert_level; -UCHAR *fragment_buffer; +UCHAR *fragment_buffer; /* Basic state machine for handshake: @@ -150,6 +156,8 @@ UCHAR *fragment_buffer; /* Use the TLS packet buffer for fragment processing. */ fragment_buffer = tls_session->nx_secure_tls_packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ status = _nx_secure_dtls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length, &message_seq, &fragment_offset, &fragment_length); @@ -158,24 +166,22 @@ UCHAR *fragment_buffer; { /* For now, if we see a repeated message sequence, assume an unnecessary retransmission and ignore. */ /* Don't ignore sequence 0 - it's a new handshake request! */ - if (message_seq < dtls_session -> nx_secure_dtls_expected_handshake_sequence) + if (message_seq < dtls_session -> nx_secure_dtls_remote_handshake_sequence) { + /* Re-transmitted message. */ return(NX_CONTINUE); } - /* If we have a new sequence number, we have a new record (may be fragmented). Unless - the sequence number is 0, which means it is the first record. */ - if (message_seq != dtls_session -> nx_secure_dtls_remote_handshake_sequence || (message_seq == 0 && fragment_offset == 0)) + /* When we receive a message fragment, subtract it from the current fragment length. */ + if ((header_bytes + fragment_length) > data_length) { - /* New record starting, reset the fragment length and handshake sequence number. */ - dtls_session -> nx_secure_dtls_remote_handshake_sequence = message_seq; - dtls_session -> nx_secure_dtls_fragment_length = message_length; + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } - /* When we receive a message fragment, subtract it from the current fragment length. */ - if (fragment_length > dtls_session -> nx_secure_dtls_fragment_length) + /* Check the fragment_length with the lenght of packet buffer. */ + if ((header_bytes + fragment_length) > data_length) { - return(1); + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } /* Check available area of buffer. */ @@ -185,6 +191,27 @@ UCHAR *fragment_buffer; return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); } + /* If this message sequence isn't what we expect, continue reading packets. */ + if(message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence) + { + return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE); + } + + /* If we have a new sequence number, we have a new record (may be fragmented). Unless + the sequence number is 0, which means it is the first record. */ + if (message_seq > dtls_session -> nx_secure_dtls_remote_handshake_sequence || (message_seq == 0 && fragment_offset == 0)) + { + /* New record starting, reset the fragment length and handshake sequence number. */ + dtls_session -> nx_secure_dtls_remote_handshake_sequence = message_seq; + dtls_session -> nx_secure_dtls_fragment_length = message_length; + } + + if (fragment_length > dtls_session -> nx_secure_dtls_fragment_length) + { + return(NX_SECURE_TLS_INVALID_PACKET); + } + + /* When we receive a message fragment, subtract it from the current fragment length. */ dtls_session -> nx_secure_dtls_fragment_length -= fragment_length; /* Copy the fragment data (minus the header) into the reassembly buffer. */ @@ -203,9 +230,9 @@ UCHAR *fragment_buffer; dtls_session -> nx_secure_dtls_expected_handshake_sequence = 0; } - /* If the recontructed message has a sequence number less than the expected, it's - a retransmission we need to ignore. */ - if (message_seq < dtls_session -> nx_secure_dtls_expected_handshake_sequence) + /* If the recontructed message has a sequence number not equal to the expected, it's + a retransmission or out-of-order message we need to ignore. */ + if (message_seq != dtls_session -> nx_secure_dtls_expected_handshake_sequence) { return(NX_CONTINUE); } @@ -332,22 +359,8 @@ UCHAR *fragment_buffer; /* Check for errors in processing messages. */ if (status != NX_SECURE_TLS_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - return(error_number); + return(status); } /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them, @@ -590,32 +603,6 @@ UCHAR *fragment_buffer; } - /* If we have an error at this point, we have experienced a problem in sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ - if (status != NX_SUCCESS) - { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_dtls_packet_allocate(dtls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - _nx_secure_dtls_send_record(dtls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - } - - return(error_number); - } - return(status); #else /* TLS Server disabled. */ diff --git a/nx_secure/src/nx_secure_dtls_session_cache.c b/nx_secure/src/nx_secure_dtls_session_cache.c index 1f35e4b0..c9bafa71 100644 --- a/nx_secure/src/nx_secure_dtls_session_cache.c +++ b/nx_secure/src/nx_secure_dtls_session_cache.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* nx_secure_dtls_session_cache_delete PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,6 +66,10 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler errors when */ +/* IPv4 is disabled, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ VOID nx_secure_dtls_session_cache_delete(NX_SECURE_DTLS_SERVER *dtls_server, NXD_ADDRESS *ip_address, UINT remote_port, UINT local_port) @@ -95,6 +99,7 @@ UINT i; { continue; } +#ifndef NX_DISABLE_IPV4 if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { if (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v4 != @@ -103,13 +108,18 @@ UINT i; continue; } } +#endif /* !NX_DISABLE_IPV4 */ + #ifdef FEATURE_NX_IPV6 - else if ((session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] != ip_address -> nxd_ip_address.v6[0]) || - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] != ip_address -> nxd_ip_address.v6[1]) || - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] != ip_address -> nxd_ip_address.v6[2]) || - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] != ip_address -> nxd_ip_address.v6[3])) + if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) { - continue; + if ((session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] != ip_address -> nxd_ip_address.v6[0]) || + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] != ip_address -> nxd_ip_address.v6[1]) || + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] != ip_address -> nxd_ip_address.v6[2]) || + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] != ip_address -> nxd_ip_address.v6[3])) + { + continue; + } } #endif /* FEATURE_NX_IPV6 */ @@ -225,7 +235,7 @@ UINT i; /* FUNCTION RELEASE */ /* */ /* nx_secure_dtls_session_cache_find PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -263,6 +273,10 @@ UINT i; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler errors when */ +/* IPv4 is disabled, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT nx_secure_dtls_session_cache_find(NX_SECURE_DTLS_SERVER *dtls_server, NX_SECURE_DTLS_SESSION **dtls_session, NXD_ADDRESS *ip_address, UINT remote_port, UINT local_port) @@ -301,6 +315,7 @@ UINT i; } /* Check actual remote IP address value. */ +#ifndef NX_DISABLE_IPV4 if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { if (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v4 == @@ -315,19 +330,24 @@ UINT i; return(NX_SUCCESS); } } +#endif /* !NX_DISABLE_IPV4 */ + #ifdef FEATURE_NX_IPV6 - else if ((session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] == ip_address -> nxd_ip_address.v6[0]) && - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] == ip_address -> nxd_ip_address.v6[1]) && - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] == ip_address -> nxd_ip_address.v6[2]) && - (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] == ip_address -> nxd_ip_address.v6[3])) + if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) { + if ((session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] == ip_address -> nxd_ip_address.v6[0]) && + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] == ip_address -> nxd_ip_address.v6[1]) && + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] == ip_address -> nxd_ip_address.v6[2]) && + (session_array[i].nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] == ip_address -> nxd_ip_address.v6[3])) + { - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); + /* Release the protection. */ + tx_mutex_put(&_nx_secure_tls_protection); - /* Return the session. */ - *dtls_session = &session_array[i]; - return(NX_SUCCESS); + /* Return the session. */ + *dtls_session = &session_array[i]; + return(NX_SUCCESS); + } } #endif /* FEATURE_NX_IPV6 */ } diff --git a/nx_secure/src/nx_secure_dtls_session_end.c b/nx_secure/src/nx_secure_dtls_session_end.c index a310e60b..e9c37420 100644 --- a/nx_secure/src/nx_secure_dtls_session_end.c +++ b/nx_secure/src/nx_secure_dtls_session_end.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_session_end PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* released packet securely, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_session_end(NX_SECURE_DTLS_SESSION *dtls_session, UINT wait_option) @@ -105,6 +108,16 @@ NX_SECURE_TLS_SESSION *tls_session; tls_session -> nx_secure_record_decrypted_packet = NX_NULL; } + /* If the remote session is already finished, don't try to send. */ + if(!dtls_session -> nx_secure_dtls_tls_session.nx_secure_tls_remote_session_active) + { + /* Reset the TLS state so this socket can be reused. */ + tx_mutex_put(&_nx_secure_tls_protection); + status = _nx_secure_dtls_session_reset(dtls_session); + return(status); + } + + /* Release the protection before suspending on nx_packet_allocate. */ tx_mutex_put(&_nx_secure_tls_protection); @@ -114,7 +127,7 @@ NX_SECURE_TLS_SESSION *tls_session; /* Check for errors in allocating packet. */ if (status != NX_SUCCESS) { - + _nx_secure_dtls_session_reset(dtls_session); return(status); } @@ -129,8 +142,9 @@ NX_SECURE_TLS_SESSION *tls_session; if (status) { - - /* Release the protection. */ + /* Failed to send, release the packet. */ + nx_secure_tls_packet_release(send_packet); + _nx_secure_dtls_session_reset(dtls_session); tx_mutex_put(&_nx_secure_tls_protection); return(status); } @@ -138,22 +152,29 @@ NX_SECURE_TLS_SESSION *tls_session; /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); - /* Wait for the CloseNotify response. */ - while (status != NX_SECURE_TLS_ALERT_RECEIVED) + /* See if we recevied the CloseNotify, or if we need to wait. */ + if(tls_session -> nx_secure_tls_received_alert_level != NX_SECURE_TLS_ALERT_LEVEL_WARNING && + tls_session -> nx_secure_tls_received_alert_value != NX_SECURE_TLS_ALERT_CLOSE_NOTIFY) { + while (status != NX_SECURE_TLS_ALERT_RECEIVED) + { + /* Wait for the CloseNotify response. */ + /* Get the protection after nx_packet_allocate. */ + tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - status = _nx_secure_dtls_session_receive(dtls_session, &incoming_packet, wait_option); + status = _nx_secure_dtls_session_receive(dtls_session, &incoming_packet, wait_option); - if (status == NX_SUCCESS) - { + /* Release the protection. */ + tx_mutex_put(&_nx_secure_tls_protection); + if (status == NX_SECURE_TLS_CLOSE_NOTIFY_RECEIVED) + { + status = NX_SUCCESS; + break; + } /* Release the alert packet. */ nx_secure_tls_packet_release(incoming_packet); } - else if ((status == NX_NO_PACKET) || (status == NX_SECURE_TLS_SESSION_UNINITIALIZED)) - { - break; - } } /* Save error status for return below. */ @@ -162,7 +183,7 @@ NX_SECURE_TLS_SESSION *tls_session; /* Reset the TLS state so this socket can be reused. */ status = _nx_secure_dtls_session_reset(dtls_session); - if(error_status != NX_SECURE_TLS_ALERT_RECEIVED) + if(error_status != NX_SECURE_TLS_ALERT_RECEIVED && error_status != NX_SECURE_TLS_CLOSE_NOTIFY_RECEIVED) { status = error_status; } diff --git a/nx_secure/src/nx_secure_dtls_session_receive.c b/nx_secure/src/nx_secure_dtls_session_receive.c index ce286236..b3899282 100644 --- a/nx_secure/src/nx_secure_dtls_session_receive.c +++ b/nx_secure/src/nx_secure_dtls_session_receive.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_session_receive PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -80,6 +80,13 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* released packet securely, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* fixed out-of-order handling,*/ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler errors when */ +/* IPv4 is disabled, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_session_receive(NX_SECURE_DTLS_SESSION *dtls_session, @@ -227,6 +234,7 @@ UINT source_port; } else { +#ifndef NX_DISABLE_IPV4 if (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_version == NX_IP_VERSION_V4) { @@ -236,8 +244,10 @@ UINT source_port; status = NX_CONTINUE; } } +#endif /* !NX_DISABLE_IPV4 */ + #ifdef FEATURE_NX_IPV6 - else if (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_version == NX_IP_VERSION_V6) + if (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_version == NX_IP_VERSION_V6) { /* Compare the IPv6 address. */ @@ -332,9 +342,19 @@ UINT source_port; /* Clear out the packet, we don't want any of the data in it. */ nx_secure_tls_packet_release(packet_ptr); - if (status != NX_CONTINUE) + if (status == NX_SECURE_TLS_ALERT_RECEIVED) + { + /* See if the alert was a CloseNotify */ + if(tls_session -> nx_secure_tls_received_alert_level == NX_SECURE_TLS_ALERT_LEVEL_WARNING && + tls_session -> nx_secure_tls_received_alert_value == NX_SECURE_TLS_ALERT_CLOSE_NOTIFY) + { + /* Close the connection */ + status = NX_SECURE_TLS_CLOSE_NOTIFY_RECEIVED; + } + /* Dont send alert to remote host if we recevied an alert */ + } + else if (status != NX_CONTINUE) { - /* Error status, send alert back to remote host. */ /* Get our alert number and level from our status. */ error_number = status; diff --git a/nx_secure/src/nx_secure_dtls_session_reset.c b/nx_secure/src/nx_secure_dtls_session_reset.c index 66698635..9df313cf 100644 --- a/nx_secure/src/nx_secure_dtls_session_reset.c +++ b/nx_secure/src/nx_secure_dtls_session_reset.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_session_reset PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* released packet securely, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* updated cookie handling, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_session_reset(NX_SECURE_DTLS_SESSION *dtls_session) @@ -96,6 +99,7 @@ NX_PACKET *next_packet_ptr; /* Reset the cookie. */ dtls_session -> nx_secure_dtls_cookie_length = 0; NX_SECURE_MEMSET(dtls_session -> nx_secure_dtls_cookie, 0, sizeof(dtls_session -> nx_secure_dtls_cookie)); + dtls_session -> nx_secure_dtls_client_cookie_ptr = NX_NULL; /* Reset the fragment length. */ dtls_session -> nx_secure_dtls_fragment_length = 0; diff --git a/nx_secure/src/nx_secure_dtls_session_send.c b/nx_secure/src/nx_secure_dtls_session_send.c index 07a5837b..01de1eeb 100644 --- a/nx_secure/src/nx_secure_dtls_session_send.c +++ b/nx_secure/src/nx_secure_dtls_session_send.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_dtls_session_send PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -69,6 +69,10 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* fixed compiler errors when */ +/* IPv4 is disabled, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_dtls_session_send(NX_SECURE_DTLS_SESSION *dtls_session, NX_PACKET *packet_ptr, @@ -98,32 +102,41 @@ UINT status; /* IP address and port don't match - probably caller error. */ return(NX_SECURE_TLS_SEND_ADDRESS_MISMATCH); } - else if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) + else { - if (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v4 != ip_address -> nxd_ip_address.v4) +#ifndef NX_DISABLE_IPV4 + if (ip_address -> nxd_ip_version == NX_IP_VERSION_V4) { + if (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v4 != ip_address -> nxd_ip_address.v4) + { - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); + /* Release the protection. */ + tx_mutex_put(&_nx_secure_tls_protection); - /* IP address and port don't match - probably caller error. */ - return(NX_SECURE_TLS_SEND_ADDRESS_MISMATCH); + /* IP address and port don't match - probably caller error. */ + return(NX_SECURE_TLS_SEND_ADDRESS_MISMATCH); + } } - } -#ifdef FEATURE_NX_IPV6 - else if ((dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] != ip_address -> nxd_ip_address.v6[0]) || - (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] != ip_address -> nxd_ip_address.v6[1]) || - (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] != ip_address -> nxd_ip_address.v6[2]) || - (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] != ip_address -> nxd_ip_address.v6[3])) - { +#endif /* !NX_DISABLE_IPV4 */ - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); - - /* IP address and port don't match - probably caller error. */ - return(NX_SECURE_TLS_SEND_ADDRESS_MISMATCH); - } +#ifdef FEATURE_NX_IPV6 + if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + if ((dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[0] != ip_address -> nxd_ip_address.v6[0]) || + (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[1] != ip_address -> nxd_ip_address.v6[1]) || + (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[2] != ip_address -> nxd_ip_address.v6[2]) || + (dtls_session -> nx_secure_dtls_remote_ip_address.nxd_ip_address.v6[3] != ip_address -> nxd_ip_address.v6[3])) + { + + /* Release the protection. */ + tx_mutex_put(&_nx_secure_tls_protection); + + /* IP address and port don't match - probably caller error. */ + return(NX_SECURE_TLS_SEND_ADDRESS_MISMATCH); + } + } #endif /* FEATURE_NX_IPV6 */ + } status = _nx_secure_dtls_send_record(dtls_session, packet_ptr, NX_SECURE_TLS_APPLICATION_DATA, NX_WAIT_FOREVER); diff --git a/nx_secure/src/nx_secure_dtls_session_sliding_window_check.c b/nx_secure/src/nx_secure_dtls_session_sliding_window_check.c new file mode 100644 index 00000000..36159201 --- /dev/null +++ b/nx_secure/src/nx_secure_dtls_session_sliding_window_check.c @@ -0,0 +1,140 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Datagram Transport Layer Security (DTLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_dtls.h" + + +#ifdef NX_SECURE_ENABLE_DTLS +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_dtls_process_sliding_window_check PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks a received record against the DTLS sliding */ +/* window used to validate incoming DTLS records. If the sequence */ +/* number of a received DTLS record is less than the "right" side of */ +/* the window but greater than the "left" side and not a repeat of */ +/* another record, the record is accepted (RFC 6347 Section 4.1.2.6). */ +/* NOTE: sequence numbers must be in target endian format before */ +/* calling this routine! */ +/* */ +/* INPUT */ +/* */ +/* dtls_session Pointer to DTLS control block */ +/* sequence_number Incoming sequence number */ +/* */ +/* OUTPUT */ +/* */ +/* status True/False - record is OK */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Timothy Stapko Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ + +UINT _nx_secure_dtls_session_sliding_window_check(NX_SECURE_DTLS_SESSION *dtls_session, ULONG *sequence_number) +{ +ULONG window; +ULONG delta; +ULONG mask; +NX_SECURE_TLS_SESSION *tls_session; + + /* Extract TLS session for sequence numbers and window from DTLS session. */ + tls_session = &dtls_session -> nx_secure_dtls_tls_session; + window = dtls_session -> nx_secure_dtls_sliding_window; + + /* See if the incoming number is inside the window. */ + if (sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0] && + sequence_number[1] == tls_session -> nx_secure_tls_remote_sequence_number[1]) + { + /* Equal to our current - this is a repeat. */ + return(NX_FALSE); + } + + /* See if the incoming number is larger than the last one we saw. */ + if (sequence_number[0] > tls_session -> nx_secure_tls_remote_sequence_number[0] || + (sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0] && + sequence_number[1] > tls_session -> nx_secure_tls_remote_sequence_number[1])) + { + /* Incoming sequence number is bigger than last seen. This is OK, new sequence number. + Outside window to the "right" side. */ + return(NX_TRUE); + } + + /* Compare sequence numbers. At this point, the incoming number is less than the last seen + but we need to know if it fits into the window. */ + delta = 0; + if(sequence_number[0] + 1 == tls_session -> nx_secure_tls_remote_sequence_number[0]) + { + /* Incoming number is less than last seen, but upper halves don't match so adjust. */ + delta = (0xFFFFFFFFul - sequence_number[1]) + tls_session -> nx_secure_tls_remote_sequence_number[1]; + } + else if(sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0]) + { + /* Top halves match, just subtract. */ + delta = tls_session -> nx_secure_tls_remote_sequence_number[1] - sequence_number[1]; + } + else + { + /* Incoming number is significantly smaller than expected (delta of top half is > 1) + so really outside the window to the left. */ + return(NX_FALSE); + } + + + /* Now we can check the delta against the window. (delta represents a *bit* position in the window). */ + if(delta > (sizeof(window) * 8)) + { + /* Delta is larger than window size - record fell off the left side. */ + return(NX_FALSE); + } + + /* Sequence number is inside the sliding window, check the bitfield. */ + mask = 0x1ul << delta; + if(window & mask) + { + /* Saw this one already! */ + return(NX_FALSE); + } + + /* If we get here, the record was in the window but not yet seen. */ + return(NX_TRUE); +} +#endif \ No newline at end of file diff --git a/nx_secure/src/nx_secure_dtls_session_sliding_window_update.c b/nx_secure/src/nx_secure_dtls_session_sliding_window_update.c new file mode 100644 index 00000000..e54d934f --- /dev/null +++ b/nx_secure/src/nx_secure_dtls_session_sliding_window_update.c @@ -0,0 +1,147 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Datagram Transport Layer Security (DTLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_dtls.h" + + +#ifdef NX_SECURE_ENABLE_DTLS +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_dtls_session_sliding_window_update PORTABLE C */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function updates the DTLS sliding window used to validate */ +/* incoming DTLS application records. If the sequence number of a */ +/* received DTLS record is less than the "right" side of the window but*/ +/* greater than the "left" side and not a repeat of another record, the*/ +/* record is accepted (RFC 6347 Section 4.1.2.6). */ +/* */ +/* INPUT */ +/* */ +/* dtls_session Pointer to DTLS control block */ +/* sequence_number New "right" side of window */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* */ +/* CALLED BY */ +/* */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 01-31-2022 Timothy Stapko Initial Version 6.1.10 */ +/* */ +/**************************************************************************/ + +UINT _nx_secure_dtls_session_sliding_window_update(NX_SECURE_DTLS_SESSION *dtls_session, ULONG *sequence_number) +{ +ULONG delta; +ULONG mask; +NX_SECURE_TLS_SESSION *tls_session; + + /* Extract TLS session for sequence numbers from DTLS session. */ + tls_session = &dtls_session -> nx_secure_dtls_tls_session; + + /* The incoming sequence number is assumed to be OK, so update window accordingly. */ + + + /* Double check new sequence number. */ + if (sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0] && + sequence_number[1] == tls_session -> nx_secure_tls_remote_sequence_number[1]) + { + /* Equal to our current - this is a repeat. */ + return(NX_SECURE_TLS_OUT_OF_ORDER_MESSAGE); + } + + /* See if the incoming number is smaller than the last one we saw. */ + if (sequence_number[0] < tls_session -> nx_secure_tls_remote_sequence_number[0] || + (sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0] && + sequence_number[1] < tls_session -> nx_secure_tls_remote_sequence_number[1])) + { + delta = 0; + if(sequence_number[0] == tls_session -> nx_secure_tls_remote_sequence_number[0]) + { + /* Upper halves match so just subtract. */ + delta = tls_session -> nx_secure_tls_remote_sequence_number[1] - sequence_number[1]; + } + else + { + /* Top halves don't match, adjust before subtract. */ + delta = (0xFFFFFFFFul - sequence_number[1]) + tls_session -> nx_secure_tls_remote_sequence_number[1]; + } + + /* Incoming sequence number is smaller than last seen. Update the bitfield without shifting. */ + mask = 0x1ul << delta; + dtls_session -> nx_secure_dtls_sliding_window = dtls_session -> nx_secure_dtls_sliding_window | mask; + } + else + { + /* Compare sequence numbers. At this point, the incoming number is greater than the last seen + so we can update the window. */ + if(sequence_number[0] > tls_session -> nx_secure_tls_remote_sequence_number[0]) + { + /* Upper halves don't match so adjust delta accordingly. */ + delta = (0xFFFFFFFFul - tls_session -> nx_secure_tls_remote_sequence_number[1]) + sequence_number[1]; + } + else + { + /* Top halves match, just subtract. */ + delta = sequence_number[1] - tls_session -> nx_secure_tls_remote_sequence_number[1]; + } + + /* Now we can update the window. (delta represents a *bit* position in the window). */ + if(delta > (sizeof(dtls_session -> nx_secure_dtls_sliding_window) * 8)) + { + /* Delta is larger than window size - just clear it out. */ + dtls_session -> nx_secure_dtls_sliding_window = 1; + } + else + { + /* Delta is within the window size, just left-shift to new position. */ + dtls_session -> nx_secure_dtls_sliding_window <<= delta; + dtls_session -> nx_secure_dtls_sliding_window |= 0x1; + } + + /* Update the sequence number to reflect the window change. */ + tls_session -> nx_secure_tls_remote_sequence_number[1] = sequence_number[1]; + tls_session -> nx_secure_tls_remote_sequence_number[0] = sequence_number[0]; + } + + + return(NX_SUCCESS); +} +#endif \ No newline at end of file diff --git a/nx_secure/src/nx_secure_generate_client_key_exchange.c b/nx_secure/src/nx_secure_generate_client_key_exchange.c new file mode 100644 index 00000000..bb30d5a6 --- /dev/null +++ b/nx_secure/src/nx_secure_generate_client_key_exchange.c @@ -0,0 +1,322 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" + +static UCHAR _nx_secure_client_padded_pre_master[600]; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_generate_client_key_exchange PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function encrypts the Pre-Master Secret (generated earlier) */ +/* and populates the buffer with the complete ClientKeyExchange */ +/* message (to be sent by the caller). It also will send ephemeral */ +/* keys for ciphersuites that require them. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ +/* data_buffer Pointer to output buffer */ +/* buffer_length Length of data buffer */ +/* output_size Size of data written to buffer*/ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* public_auth_metadata Metadata for public auth */ +/* public_auth_metadata_size Size of public auth metadata */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_x509_remote_endpoint_certificate_get */ +/* Get cert for remote host */ +/* [nx_crypto_operation] Public-key ciphers */ +/* [nx_crypto_init] Initialize Crypto Method */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_send_client_key_exchange */ +/* Send ClientKeyExchange */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_generate_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size) +{ +UINT status; +UINT data_size; +UCHAR *encrypted_data_ptr; +UCHAR rand_byte; +UINT i; +const NX_CRYPTO_METHOD *public_cipher_method; +NX_SECURE_X509_CERT *remote_certificate; +VOID *handler = NX_NULL; +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE +NX_CRYPTO_EXTENDED_OUTPUT extended_output; +#endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */ + + /* Send a ClientKeyExchange message. + * Structure: + * | 2 | | + * | Length | Encrypted Pre-Master Secret | + * + * ECDHE ephemeral key structure: + * | 2 | | + * | Length | EC Diffie-Hellman Client Params | + */ + +#ifndef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + NX_PARAMETER_NOT_USED(public_auth_metadata); + NX_PARAMETER_NOT_USED(public_auth_metadata_size); +#endif + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + 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) + { + 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)) + { + + /* 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 */ + { + + /* Pointer to the output encrypted pre-master secret. */ + encrypted_data_ptr = &data_buffer[2]; + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + /* 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))) + { + + /* Packet buffer too small. */ + return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); + } + + /* Send the PSK Identity string to the remote server along with its length. */ + NX_SECURE_MEMCPY(encrypted_data_ptr, 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. */ + + /* Make sure our size is correct. */ + data_size = tls_credentials -> nx_secure_tls_client_psk.nx_secure_tls_psk_id_size; + + /* Put the length into our outgoing packet buffer. */ + data_buffer[0] = (UCHAR)((data_size & 0xFF00) >> 8); + data_buffer[1] = (UCHAR)(data_size & 0x00FF); + + data_size += 2; + } + else +#endif +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) + { + data_size = 0; + public_cipher_method = ciphersuite -> nx_secure_tls_public_auth; + + extended_output.nx_crypto_extended_output_data = data_buffer; + extended_output.nx_crypto_extended_output_length_in_byte = buffer_length; + extended_output.nx_crypto_extended_output_actual_size = 0; + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_KEY_EXCHANGE_GENERATE, + handler, + (NX_CRYPTO_METHOD*)public_cipher_method, + NX_NULL, 0, + NX_NULL, 0, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if (status) + { + return(status); + } + + data_size += extended_output.nx_crypto_extended_output_actual_size; + } + else +#endif + { + + /* Extract the data to be verified from the remote certificate processed earlier. */ + status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, + &remote_certificate); + + if (status) + { + + /* No certificate found, error! */ + return(NX_SECURE_TLS_NO_CERT_SPACE_ALLOCATED); + } + + /* Get the public cipher method from the ciphersuite. */ + public_cipher_method = ciphersuite -> nx_secure_tls_public_cipher; + + /* If using RSA, the length is equal to the key size. */ + data_size = remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length; + + /* check data_size */ + if ((data_size < NX_SECURE_TLS_RSA_PREMASTER_SIZE + 1) || + (buffer_length < (2u + data_size))) + { + + /* Invalid certificate modulus length. */ + return(NX_SECURE_TLS_INVALID_CERTIFICATE); + } + + /* PKCS#1 v1.5 padding. The scheme is to start with the block type (0x00, 0x02 for PKCS#1) + then pad with non-zero bytes (random is cryptographically more secure), followed with + a single 0 byte right before the payload, which comes at the end of the RSA block. */ + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0x0, sizeof(_nx_secure_client_padded_pre_master)); + _nx_secure_client_padded_pre_master[1] = 0x2; /* Block type is 0x00, 0x02 */ + for (i = 2; i < (data_size - NX_SECURE_TLS_RSA_PREMASTER_SIZE - 1); ++i) + { + /* PKCS#1 padding must be random, but CANNOT be 0. */ + do + { + rand_byte = (UCHAR)NX_RAND(); + } while (rand_byte == 0); + _nx_secure_client_padded_pre_master[i] = rand_byte; + } + + /* Now put the pre-master data into the padded buffer - must be at the end. */ + NX_SECURE_MEMCPY(&_nx_secure_client_padded_pre_master[data_size - NX_SECURE_TLS_RSA_PREMASTER_SIZE], + tls_key_material -> nx_secure_tls_pre_master_secret, NX_SECURE_TLS_RSA_PREMASTER_SIZE); /* Use case of memcpy is verified. */ + + if (public_cipher_method -> nx_crypto_init != NX_NULL) + { + /* Initialize the crypto method with public key. */ + status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, + (UCHAR *)remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, + (NX_CRYPTO_KEY_SIZE)(remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), + &handler, + public_cipher_metadata, + public_cipher_metadata_size); + + if(status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + + if (public_cipher_method -> nx_crypto_operation != NX_NULL) + { + /* Now encrypt the pre-master secret using the public key provided by the remote host + and place the result in the outgoing packet buffer. */ + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, + handler, + (NX_CRYPTO_METHOD*)public_cipher_method, + (UCHAR *)remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent, + (NX_CRYPTO_KEY_SIZE)(remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), + _nx_secure_client_padded_pre_master, + data_size, + NX_NULL, + encrypted_data_ptr, + data_size, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + + if (public_cipher_method -> nx_crypto_cleanup) + { + status = public_cipher_method -> nx_crypto_cleanup(public_cipher_metadata); + + if(status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + + /* Put the length into our outgoing packet buffer. */ + data_buffer[0] = (UCHAR)((data_size & 0xFF00) >> 8); + data_buffer[1] = (UCHAR)(data_size & 0x00FF); + + data_size += 2; + } + } + + /* Let the caller know how many bytes we wrote. +2 for the length we just added. */ + *output_size = data_size; + +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(NX_SECURE_TLS_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_generate_master_secret.c b/nx_secure/src/nx_secure_generate_master_secret.c new file mode 100644 index 00000000..361f910f --- /dev/null +++ b/nx_secure/src/nx_secure_generate_master_secret.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) - Generate Session Keys */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" +#ifdef NX_SECURE_ENABLE_DTLS +#include "nx_secure_dtls.h" +#endif /* NX_SECURE_ENABLE_DTLS */ + +/* This local static buffer needs to be large enough to hold both the server random and the client random. */ +static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE << 1]; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_generate_master_secret PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function generates the session keys used by TLS to encrypt */ +/* the data being transmitted. It uses data gathered during the TLS */ +/* handshake to generate a block of "key material" that is split into */ +/* the various keys needed for each session. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* session_prf_method Pointer to PRF crypto method */ +/* tls_key_material TLS key material */ +/* pre_master_sec Pointer to pre-master secret */ +/* pre_master_sec_size Size of pre-master secret */ +/* master_sec Pointer to master secret */ +/* prf_metadata Metadata for PRF crypto method*/ +/* prf_metadata_size Size of PRF metadata */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* [nx_crypto_init] Initialize crypto */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_generate_keys Generate session keys */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_generate_master_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *pre_master_sec, UINT pre_master_sec_size, UCHAR *master_sec, + VOID *prf_metadata, ULONG prf_metadata_size) +{ +; +UINT status; +VOID *handler = NX_NULL; + + NX_PARAMETER_NOT_USED(protocol_version); + + /* Generate the session keys using the parameters obtained in the handshake. + By this point all the information needed to generate the TLS session key + material should have been gathered and stored in the TLS socket structure. */ + + /* Generate the Master Secret from the Pre-Master Secret. + From the RFC (TLS 1.1, TLS 1.2): + + master_secret = PRF(pre_master_secret, "master secret", + ClientHello.random + ServerHello.random) [0..47]; + + The master secret is always exactly 48 bytes in length. The length + of the premaster secret will vary depending on key exchange method. + */ + + /* The generation of key material is different between RSA and DH. */ + if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE + || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK +#endif +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE +#endif + ) + { + /* Concatenate random values to feed into PRF. */ + NX_SECURE_MEMCPY(_nx_secure_tls_gen_keys_random, tls_key_material -> nx_secure_tls_client_random, + NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&_nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE], + tls_key_material -> nx_secure_tls_server_random, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + + /* Generate the master secret using the pre-master secret, the defined TLS label, and the concatenated + random values. */ + + /* If we don't have a PRF method, the version is wrong! */ + if (session_prf_method == NX_NULL) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(NX_SECURE_TLS_PROTOCOL_VERSION_CHANGED); + } + + /* Use the PRF to generate the master secret. */ + if (session_prf_method -> nx_crypto_init != NX_NULL) + { + status = session_prf_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_prf_method, + pre_master_sec, (NX_CRYPTO_KEY_SIZE)pre_master_sec_size, + &handler, + prf_metadata, + prf_metadata_size); + + if(status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + + if (session_prf_method -> nx_crypto_operation != NX_NULL) + { + status = session_prf_method -> nx_crypto_operation(NX_CRYPTO_PRF, + handler, + (NX_CRYPTO_METHOD*)session_prf_method, + (UCHAR *)"master secret", + 13, + _nx_secure_tls_gen_keys_random, + 64, + NX_NULL, + master_sec, + 48, + prf_metadata, + prf_metadata_size, + NX_NULL, + NX_NULL); + +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); +#endif /* NX_SECURE_KEY_CLEAR */ + + if(status != NX_CRYPTO_SUCCESS) + { + /* Secrets cleared above. */ + return(status); + } + } + + if (session_prf_method -> nx_crypto_cleanup) + { + status = session_prf_method -> nx_crypto_cleanup(prf_metadata); + + if(status != NX_CRYPTO_SUCCESS) + { + /* All secrets cleared above. */ + return(status); + } + } + } + else + { + /* The chosen cipher is not supported. Likely an internal error since negotiation has already finished. */ + return(NX_SECURE_TLS_UNSUPPORTED_CIPHER); + } + + 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 new file mode 100644 index 00000000..2cc9dd28 --- /dev/null +++ b/nx_secure/src/nx_secure_generate_premaster_secret.c @@ -0,0 +1,322 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_generate_premaster_secret PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function generates the Pre-Master Secret for TLS Client */ +/* instances. It is sent to the remote host and used as the seed for */ +/* session key generation. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ +/* session_type Server or client session */ +/* received_remote_credentials Indicates credentials received*/ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* tls_ecc_curves ECC curves */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_tls_psk_find Find PSK from store */ +/* _nx_secure_tls_find_curve_method Find named curve used */ +/* [nx_crypto_init] Initialize crypto */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_generate_premaster_secret */ +/* Generate pre-master secret */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_generate_premaster_secret(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT session_type, USHORT *received_remote_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, VOID *tls_ecc_curves) +{ +UINT *buffer_ptr; +UINT i; +UINT status = NX_SECURE_TLS_SUCCESS; +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES +UCHAR *psk_data; +UINT psk_length; +UINT index; +#endif +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +NX_SECURE_X509_CERT *server_certificate; +const NX_CRYPTO_METHOD *curve_method_cert; +const NX_CRYPTO_METHOD *ecdh_method; +NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; +VOID *handler = NX_NULL; +NX_CRYPTO_EXTENDED_OUTPUT extended_output; +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + +#ifndef NX_SECURE_ENABLE_ECC_CIPHERSUITE + NX_PARAMETER_NOT_USED(public_cipher_metadata); + NX_PARAMETER_NOT_USED(public_cipher_metadata_size); + NX_PARAMETER_NOT_USED(tls_ecc_curves); +#endif +#ifndef NX_SECURE_ENABLE_PSK_CIPHERSUITES + NX_PARAMETER_NOT_USED(session_type); + NX_PARAMETER_NOT_USED(ciphersuite); + NX_PARAMETER_NOT_USED(tls_credentials); + NX_PARAMETER_NOT_USED(public_cipher_metadata); + NX_PARAMETER_NOT_USED(public_cipher_metadata_size); + NX_PARAMETER_NOT_USED(tls_ecc_curves); +#ifndef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + NX_PARAMETER_NOT_USED(received_remote_credentials); +#endif +#endif + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) + { + + return(NX_SECURE_TLS_SUCCESS); + } + else if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH) + { + /* Get reference to remote server certificate so we can find out the named curve. */ + status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, + &server_certificate); + if (status) + { + /* No certificate found, error! */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + + ec_pubkey = &server_certificate -> nx_secure_x509_public_key.ec_public_key; + + /* Find out which named curve the remote certificate is using. */ + status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); + + if(status != NX_SUCCESS) + { + return(status); + } + + ecdh_method = ciphersuite -> nx_secure_tls_public_cipher; + if (ecdh_method -> nx_crypto_operation == NX_NULL) + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + if (ecdh_method -> nx_crypto_init != NX_NULL) + { + status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method, + NX_NULL, + 0, + &handler, + public_cipher_metadata, + public_cipher_metadata_size); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL, + NX_NULL, 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + /* Store public key in the nx_secure_tls_new_key_material_data. */ + extended_output.nx_crypto_extended_output_data = &tls_key_material -> nx_secure_tls_new_key_material_data[1]; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_new_key_material_data) - 1; + extended_output.nx_crypto_extended_output_actual_size = 0; + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + NX_NULL, 0, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_key_material -> nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size; + + extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret); + extended_output.nx_crypto_extended_output_actual_size = 0; + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, + ec_pubkey -> nx_secure_ec_public_key_length, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; + + if (ecdh_method -> nx_crypto_cleanup) + { + status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + return(NX_SECURE_TLS_SUCCESS); + } +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + /* Check for PSK ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) + { + /* 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; + } + 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); + + if (status != NX_SUCCESS) + { + return(status); + } + } + + /* From RFC 4279: + The premaster secret is formed as follows: if the PSK is N octets + long, concatenate a uint16 with the value N, N zero octets, a second + uint16 with the value N, and the PSK itself. + | 2 | | 2 | | + | N | 0 | N | PSK | + */ + index = 0; + + if ((2 + psk_length + 2 + psk_length) > sizeof(tls_key_material -> nx_secure_tls_pre_master_secret)) + { + + /* No more PSK space. */ + return(NX_SECURE_TLS_NO_MORE_PSK_SPACE); + } + + tls_key_material -> nx_secure_tls_pre_master_secret[0] = (UCHAR)(psk_length >> 8); + tls_key_material -> nx_secure_tls_pre_master_secret[1] = (UCHAR)psk_length; + index += 2; + + NX_SECURE_MEMSET(&tls_key_material -> nx_secure_tls_pre_master_secret[index], 0, psk_length); + index += psk_length; + + tls_key_material -> nx_secure_tls_pre_master_secret[index] = (UCHAR)(psk_length >> 8); + tls_key_material -> nx_secure_tls_pre_master_secret[index + 1] = (UCHAR)psk_length; + index += 2; + + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_pre_master_secret[index], psk_data, psk_length); /* Use case of memcpy is verified. */ + index += psk_length; + + /* Save the pre-master secret size for later use. */ + tls_key_material -> nx_secure_tls_pre_master_secret_size = 2 + psk_length + 2 + psk_length; + + /* We are using PSK for our credentials and now that we have generated keys we can consider the + remote host's credentials to have been received. */ + *received_remote_credentials = NX_TRUE; + + return(NX_SECURE_TLS_SUCCESS); + } +#endif + +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + /* When using ECJ-PAKE ciphersuite, pre-master secret is already generated. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) + { + /* If using EC-JPAKE, credentials are passed differently - if we get here credentials should be OK. */ + *received_remote_credentials = NX_TRUE; + + return(NX_SECURE_TLS_SUCCESS); + } +#endif + + /* Generate the Pre-Master Secret that is used to generate the key material + used in the session. For TLS 1.1, the secret consists of two bytes + representing the highest protocol version the client supports, followed + by 46 random bytes. */ + buffer_ptr = (UINT *)tls_key_material -> nx_secure_tls_pre_master_secret; + + /* Generate 48 bytes of random data, fill in the version afterwards. */ + for (i = 0; i < 12; i++) + { + /* Fill with 12 ULONG randoms, then fix first two bytes to protocol version after. */ + *(buffer_ptr + i) = (UINT)NX_RAND(); + } + + /* First two bytes are newest version supported by client . */ + buffer_ptr[0] = ((ULONG)protocol_version << 16) | (buffer_ptr[0] & 0x0000FFFF); + NX_CHANGE_ULONG_ENDIAN(buffer_ptr[0]); + + tls_key_material -> nx_secure_tls_pre_master_secret_size = 48; + + return(status); +} + diff --git a/nx_secure/src/nx_secure_generate_server_key_exchange.c b/nx_secure/src/nx_secure_generate_server_key_exchange.c new file mode 100644 index 00000000..cc4e6c03 --- /dev/null +++ b/nx_secure/src/nx_secure_generate_server_key_exchange.c @@ -0,0 +1,245 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_generate_server_key_exchange PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function generates a ServerKeyExchange message, which is used */ +/* when the chosen ciphersuite requires additional information for key */ +/* generation, such as when using Diffie-Hellman ciphers. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* tls_1_3 Whether TLS 1.3 is chosen */ +/* tls_crypto_table TLS crypto methods */ +/* tls_handshake_hash Metadata for handshake hash */ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ +/* data_buffer Pointer to output buffer */ +/* buffer_length Length of data buffer */ +/* output_size Size of data written to buffer*/ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* public_auth_metadata Metadata for public auth */ +/* public_auth_metadata_size Size of public auth metadata */ +/* tls_ecc_curves ECC curves */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_tls_ecc_generate_keys Generate keys for ECC exchange*/ +/* [nx_crypto_init] Initialize Crypto Method */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_send_server_key_exchange */ +/* Send ServerKeyExchange */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_generate_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3, + NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + UCHAR *data_buffer, ULONG buffer_length, ULONG *output_size, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves) +{ +UINT length; + +#if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) +UINT status; +#endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES +USHORT identity_length; +UCHAR *identity; +#endif + +#if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) +VOID *handler = NX_NULL; +USHORT named_curve; +NX_CRYPTO_METHOD *crypto_method; +NX_CRYPTO_EXTENDED_OUTPUT extended_output; +#endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; +#endif + + + /* Build up the server key exchange message. Structure: + * | 2 | | + * | Key data length | Key data (opaque) | + */ + +#ifndef NX_SECURE_ENABLE_ECC_CIPHERSUITE + NX_PARAMETER_NOT_USED(ciphersuite); + NX_PARAMETER_NOT_USED(protocol_version); + NX_PARAMETER_NOT_USED(tls_1_3); + NX_PARAMETER_NOT_USED(tls_crypto_table); + NX_PARAMETER_NOT_USED(tls_handshake_hash); + NX_PARAMETER_NOT_USED(tls_key_material); + NX_PARAMETER_NOT_USED(tls_credentials); + NX_PARAMETER_NOT_USED(data_buffer); + NX_PARAMETER_NOT_USED(buffer_length); + NX_PARAMETER_NOT_USED(public_cipher_metadata); + NX_PARAMETER_NOT_USED(public_cipher_metadata_size); + NX_PARAMETER_NOT_USED(public_auth_metadata); + NX_PARAMETER_NOT_USED(public_auth_metadata_size); + NX_PARAMETER_NOT_USED(tls_ecc_curves); +#endif + + length = 0; + + /* In the future, any Diffie-Hellman-based ciphersuites will populate this message with key + data. RSA ciphersuites do not use this message. */ + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + + /* Check for PSK ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) + { + /* If PSK is being used, the server sends an identity value to the client so + the client can respond with the appropriate PSK. */ + + /* Get identity hint and length. */ + identity = tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint; + identity_length = (USHORT)tls_credentials -> nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint_size; + + if ((identity_length + 2u) > buffer_length) + { + + /* Packet buffer too small. */ + return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); + } + + /* Use identity hint length for key data length. */ + data_buffer[length] = (UCHAR)((identity_length & 0xFF00) >> 8); + data_buffer[length + 1] = (UCHAR)(identity_length & 0x00FF); + length = (USHORT)(length + 2); + + /* Extract the identity hint and put it into the packet buffer. */ + NX_SECURE_MEMCPY(&data_buffer[length], identity, identity_length); /* Use case of memcpy is verified. */ + + /* Advance our total length. */ + length = (USHORT)(length + identity_length); + } +#endif + +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + + /* Check for ECJ-PAKE ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) + { + + if (buffer_length < 3) + { + + /* Packet buffer too small. */ + return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); + } + + /* ECCurveType: named_curve (3). */ + data_buffer[length] = NX_CRYPTO_EC_CURVE_TYPE_NAMED_CURVE; + length += 1; + + /* NamedCurve: secp256r1 (23) */ + named_curve = (USHORT)NX_CRYPTO_EC_SECP256R1; + data_buffer[length] = (UCHAR)((named_curve >> 8) & 0xFF); + data_buffer[length + 1] = (UCHAR)(named_curve & 0xFF); + length += 2; + + extended_output.nx_crypto_extended_output_data = &data_buffer[length]; + extended_output.nx_crypto_extended_output_length_in_byte = buffer_length - length; + extended_output.nx_crypto_extended_output_actual_size = 0; + + crypto_method = (NX_CRYPTO_METHOD*)ciphersuite -> nx_secure_tls_public_auth; + status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_GENERATE, + handler, + crypto_method, + NX_NULL, 0, + NX_NULL, 0, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if (status) + { + return(status); + } + length += extended_output.nx_crypto_extended_output_actual_size; + } +#endif + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + /* Check for ECDHE ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) + { + ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_key_material -> nx_secure_tls_new_key_material_data; + + length = buffer_length; + + status = _nx_secure_tls_ecc_generate_keys(ciphersuite, protocol_version, tls_1_3, + tls_crypto_table, tls_handshake_hash, (NX_SECURE_TLS_ECC *)tls_ecc_curves, + tls_key_material, tls_credentials, ecdhe_data -> nx_secure_tls_ecdhe_named_curve, NX_TRUE, + data_buffer, &length, ecdhe_data, public_cipher_metadata, public_cipher_metadata_size, + public_auth_metadata, public_auth_metadata_size); + + if (status != NX_SUCCESS) + { + return(status); + } + } +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + + + /* Finally, we let the caller know the length . */ + *output_size = length; + + return(NX_SECURE_TLS_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_generate_session_keys.c b/nx_secure/src/nx_secure_generate_session_keys.c new file mode 100644 index 00000000..13de306b --- /dev/null +++ b/nx_secure/src/nx_secure_generate_session_keys.c @@ -0,0 +1,206 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) - Generate Session Keys */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" +#ifdef NX_SECURE_ENABLE_DTLS +#include "nx_secure_dtls.h" +#endif /* NX_SECURE_ENABLE_DTLS */ + +/* This local static buffer needs to be large enough to hold both the server random and the client random. */ +static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE << 1]; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_generate_session_keys PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function generates the session keys used by TLS to encrypt */ +/* the data being transmitted. It uses data gathered during the TLS */ +/* handshake to generate a block of "key material" that is split into */ +/* the various keys needed for each session. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* session_prf_method Pointer to PRF crypto method */ +/* tls_key_material TLS key material */ +/* master_sec Pointer to master secret */ +/* prf_metadata Metadata for PRF crypto method*/ +/* prf_metadata_size Size of PRF metadata */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* [nx_crypto_init] Initialize crypto */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_generate_keys Generate session keys */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_generate_session_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + const NX_CRYPTO_METHOD *session_prf_method, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UCHAR *master_sec, VOID *prf_metadata, ULONG prf_metadata_size) +{ +UCHAR *key_block; /* Maximum ciphersuite key size - AES_256_CBC_SHA, 2x32 byte keys + 2x20 byte MAC secrets + 2x16 IVs. */ +UINT key_block_size; +UINT key_size; +UINT hash_size; +UINT iv_size; +UINT status; +const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; +VOID *handler = NX_NULL; + + NX_PARAMETER_NOT_USED(protocol_version); + + key_block_size = 0; + + /* Working pointer into our new key material block since we are generating new keys. */ + key_block = tls_key_material -> nx_secure_tls_new_key_material_data; + + + /* Get our session cipher method so we can get key sizes. */ + session_cipher_method = ciphersuite -> nx_secure_tls_session_cipher; + + + /* Lookup ciphersuite data for key size. We need 2 keys for each session. */ + key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3; + + /* Lookup ciphersuite data for hash size - used for the MAC secret. */ + hash_size = ciphersuite -> nx_secure_tls_hash_size; + + /* Lookup initialization vector size. */ + iv_size = session_cipher_method -> nx_crypto_IV_size_in_bits >> 3; + + /* Now calculate block size. Need client and server for each key, hash, and iv. Note that + key size and iv size may be zero depending on the ciphersuite, particularly when using + the NULL ciphers. */ + key_block_size = 2 * (key_size + hash_size + iv_size); + + /* Now generate keys from the master secret we obtained above. */ + /* From the RFC (TLS 1.1): + To generate the key material, compute + + key_block = PRF(SecurityParameters.master_secret, + "key expansion", + SecurityParameters.server_random + + SecurityParameters.client_random); + + until enough output has been generated. Then the key_block is + partitioned as follows: + + client_write_MAC_secret[SecurityParameters.hash_size] + server_write_MAC_secret[SecurityParameters.hash_size] + client_write_key[SecurityParameters.key_material_length] + server_write_key[SecurityParameters.key_material_length] + */ + + /* The order of the randoms is reversed from that used for the master secret + when generating the key block. */ + NX_SECURE_MEMCPY(_nx_secure_tls_gen_keys_random, tls_key_material -> nx_secure_tls_server_random, + NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&_nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE], + tls_key_material -> nx_secure_tls_client_random, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + + /* Key expansion uses the PRF to generate a block of key material from the master secret (generated + above) and the client and server random values transmitted during the initial hello negotiation. */ + if (session_prf_method -> nx_crypto_init != NX_NULL) + { + status = session_prf_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_prf_method, + master_sec, 48, + &handler, + prf_metadata, + prf_metadata_size); + + if(status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + + if (session_prf_method -> nx_crypto_operation != NX_NULL) + { + status = session_prf_method -> nx_crypto_operation(NX_CRYPTO_PRF, + handler, + (NX_CRYPTO_METHOD*)session_prf_method, + (UCHAR *)"key expansion", + 13, + _nx_secure_tls_gen_keys_random, + 64, + NX_NULL, + key_block, + key_block_size, + prf_metadata, + prf_metadata_size, + NX_NULL, + NX_NULL); + +#ifdef NX_SECURE_KEY_CLEAR + /* We now have a key block, clear our temporary secrets buffer. */ + NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); +#endif /* NX_SECURE_KEY_CLEAR */ + + if(status != NX_CRYPTO_SUCCESS) + { + /* Secrets cleared above. */ + return(status); + } + } + + if (session_prf_method -> nx_crypto_cleanup) + { + status = session_prf_method -> nx_crypto_cleanup(prf_metadata); + + if(status != NX_CRYPTO_SUCCESS) + { + /* Secrets cleared above. */ + return(status); + } + } + + return(NX_SECURE_TLS_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_process_client_key_exchange.c b/nx_secure/src/nx_secure_process_client_key_exchange.c new file mode 100644 index 00000000..d8083337 --- /dev/null +++ b/nx_secure/src/nx_secure_process_client_key_exchange.c @@ -0,0 +1,571 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" + +static UCHAR _nx_secure_client_padded_pre_master[600]; + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_process_client_key_exchange PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes an incoming ClientKeyExchange message, */ +/* which contains the encrypted Pre-Master Secret. This function */ +/* decrypts the Pre-Master Secret and saves it in the TLS session */ +/* control block for use in generating session key material later. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* packet_buffer Pointer to message data */ +/* message_length Length of message data (bytes)*/ +/* received_remote_credentials Indicates credentials received*/ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* public_auth_metadata Metadata for public auth */ +/* public_auth_metadata_size Size of public auth metadata */ +/* tls_ecc_curves ECC curves */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_generate_premaster_secret Generate the shared secret */ +/* used to generate keys later */ +/* _nx_secure_x509_local_device_certificate_get */ +/* Get the local certificate */ +/* for its keys */ +/* _nx_secure_tls_find_curve_method Find named curve used */ +/* [nx_crypto_init] Initialize crypto */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_process_client_key_exchange */ +/* Process ClientKeyExchange */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_process_client_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, + UCHAR *packet_buffer, UINT message_length, USHORT *received_remote_credentials, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves) +{ +USHORT length; +UINT status; +UCHAR *encrypted_pre_master_secret; +const NX_CRYPTO_METHOD *public_cipher_method; +NX_SECURE_X509_CERT *local_certificate; +UINT user_defined_key; +VOID *handler = NX_NULL; +UCHAR rand_byte; +UINT i; +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +NX_SECURE_EC_PRIVATE_KEY *ec_privkey; +NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; +NX_CRYPTO_EXTENDED_OUTPUT extended_output; +const NX_CRYPTO_METHOD *curve_method; +const NX_CRYPTO_METHOD *ecdh_method; +UCHAR *private_key; +UINT private_key_length; +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + +#ifndef NX_SECURE_ENABLE_PSK_CIPHERSUITES + NX_PARAMETER_NOT_USED(received_remote_credentials); +#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ +#ifndef NX_SECURE_ENABLE_ECC_CIPHERSUITE + NX_PARAMETER_NOT_USED(tls_ecc_curves); +#endif + NX_PARAMETER_NOT_USED(protocol_version); + NX_PARAMETER_NOT_USED(public_auth_metadata); + NX_PARAMETER_NOT_USED(public_auth_metadata_size); + + /* Process key material. The contents of the handshake record differ according to the + ciphersuite chosen in the Client/Server Hello negotiation. */ + +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + /* Check for ECJ-PAKE ciphersuites and generate the pre-master-secret. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) + { + + tls_key_material -> nx_secure_tls_pre_master_secret_size = 32; + + public_cipher_method = ciphersuite -> nx_secure_tls_public_auth; + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_KEY_EXCHANGE_PROCESS, + handler, + (NX_CRYPTO_METHOD *)public_cipher_method, + NX_NULL, 0, + packet_buffer, + message_length, + NX_NULL, + tls_key_material -> nx_secure_tls_pre_master_secret, + tls_key_material -> nx_secure_tls_pre_master_secret_size, + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if (status) + { + return(status); + } + + if (public_cipher_method -> nx_crypto_cleanup) + { + status = public_cipher_method -> nx_crypto_cleanup(public_auth_metadata); + + if (status) + { + return(status); + } + } + } + else +#endif + { + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + /* Check for PSK ciphersuites and generate the pre-master-secret. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) + { + 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); + } + } + else +#endif +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + 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) + { + length = packet_buffer[0]; + + if ((UINT)length + 1 > message_length) + { + /* The public key length is larger than the header indicated. */ + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH) + { + /* Get the local certificate. */ + if (tls_credentials -> nx_secure_tls_active_certificate != NX_NULL) + { + local_certificate = tls_credentials -> nx_secure_tls_active_certificate; + } + else + { + /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */ + status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, + NX_NULL, &local_certificate); + if (status != NX_SUCCESS) + { + local_certificate = NX_NULL; + } + } + + if (local_certificate == NX_NULL) + { + /* No certificate found, error! */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + + ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key; + + /* Find out which named curve the local certificate is using. */ + status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method, NX_NULL); + + if (status != NX_SUCCESS) + { + return(status); + } + + private_key = (UCHAR *)ec_privkey -> nx_secure_ec_private_key; + private_key_length = ec_privkey -> nx_secure_ec_private_key_length; + } + else + { + ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_key_material -> nx_secure_tls_new_key_material_data; + + /* Find out which named curve the we are using. */ + status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)ecdhe_data -> nx_secure_tls_ecdhe_named_curve, &curve_method, NX_NULL); + + if (status != NX_SUCCESS) + { + return(status); + } + + private_key = ecdhe_data -> nx_secure_tls_ecdhe_private_key; + private_key_length = ecdhe_data -> nx_secure_tls_ecdhe_private_key_length; + } + + if (curve_method == NX_NULL) + { + /* No named curve is selected. */ + return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); + } + + ecdh_method = ciphersuite -> nx_secure_tls_public_cipher; + if (ecdh_method -> nx_crypto_operation == NX_NULL) + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + if (ecdh_method -> nx_crypto_init != NX_NULL) + { + status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD *)ecdh_method, + NX_NULL, + 0, + &handler, + public_cipher_metadata, + public_cipher_metadata_size); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, + (NX_CRYPTO_METHOD *)ecdh_method, NX_NULL, 0, + (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, + NX_NULL, 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + /* Import the private key to the ECDH context. */ + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler, + (NX_CRYPTO_METHOD *)ecdh_method, + private_key, private_key_length << 3, + NX_NULL, 0, NX_NULL, + NX_NULL, + 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret); + extended_output.nx_crypto_extended_output_actual_size = 0; + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, + (NX_CRYPTO_METHOD *)ecdh_method, NX_NULL, 0, + &packet_buffer[1], + length, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; + + if (ecdh_method -> nx_crypto_cleanup) + { + status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + } + else +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + { /* Certificate-based authentication. */ + + if (message_length < 2) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + /* Get pre-master-secret length. */ + length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]); + packet_buffer += 2; + + if ((UINT)length + 2 > message_length) + { + /* The payload is larger than the header indicated. */ + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + /* Pointer to the encrypted pre-master secret in our packet buffer. */ + encrypted_pre_master_secret = &packet_buffer[0]; + + + if (ciphersuite -> nx_secure_tls_ciphersuite == TLS_NULL_WITH_NULL_NULL) + { + /* Special case - NULL ciphersuite. No keys are generated. */ + if (length > sizeof(tls_key_material -> nx_secure_tls_pre_master_secret)) + { + length = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret); + } + NX_SECURE_MEMCPY(tls_key_material -> nx_secure_tls_pre_master_secret, encrypted_pre_master_secret, length); /* Use case of memcpy is verified. */ + tls_key_material -> nx_secure_tls_pre_master_secret_size = length; + } + + /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */ + status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, + NX_NULL, &local_certificate); + + if (status) + { + /* No certificate found, error! */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + + /* Get the public cipher method pointer for this session. */ + public_cipher_method = ciphersuite -> nx_secure_tls_public_cipher; + + /* Check for user-defined key types. */ + user_defined_key = NX_FALSE; + if (((local_certificate -> nx_secure_x509_private_key_type & NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK) != 0x0) || + (local_certificate -> nx_secure_x509_private_key_type == NX_SECURE_X509_KEY_TYPE_HARDWARE)) + { + user_defined_key = NX_TRUE; + } + + /* See if we are using RSA. Separate from other methods (e.g. ECC, DH) for proper handling of padding. */ + if (public_cipher_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA && + local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA) + { + /* Check for user-defined keys. */ + if (user_defined_key) + { + /* A user-defined key is passed directly into the crypto routine. */ + status = public_cipher_method -> nx_crypto_operation(local_certificate -> nx_secure_x509_private_key_type, + NX_NULL, + (NX_CRYPTO_METHOD *)public_cipher_method, + (UCHAR *)local_certificate -> nx_secure_x509_private_key.user_key.key_data, + (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.user_key.key_length), + encrypted_pre_master_secret, + length, + NX_NULL, + _nx_secure_client_padded_pre_master, + sizeof(_nx_secure_client_padded_pre_master), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + else + { + /* Generic RSA operation, use pre-parsed RSA key data. */ + if (public_cipher_method -> nx_crypto_init != NX_NULL) + { + /* Initialize the crypto method with public key. */ + status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD *)public_cipher_method, + (UCHAR *)local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, + (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), + &handler, + public_cipher_metadata, + public_cipher_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + if (public_cipher_method -> nx_crypto_operation != NX_NULL) + { + + + /* Check for P and Q in the private key. If they are present, we can use them to + speed up RSA using the Chinese Remainder Theorem version of the algorithm. */ + if (local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p != NX_NULL && + local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q != NX_NULL) + { + + + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_P, + handler, + (NX_CRYPTO_METHOD *)public_cipher_method, + NX_NULL, + 0, + (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p, + local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p_length, + NX_NULL, + NX_NULL, + 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_Q, + handler, + (NX_CRYPTO_METHOD *)public_cipher_method, + NX_NULL, + 0, + (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q, + local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q_length, + NX_NULL, + NX_NULL, + 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + } + + /* Decrypt the pre-master-secret using the private key provided by the user + and place the result in the session key material space in our socket. */ + status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, + handler, + (NX_CRYPTO_METHOD *)public_cipher_method, + (UCHAR *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent, + (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3), + encrypted_pre_master_secret, + length, + NX_NULL, + _nx_secure_client_padded_pre_master, + sizeof(_nx_secure_client_padded_pre_master), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + } + + if (public_cipher_method -> nx_crypto_cleanup) + { + status = public_cipher_method -> nx_crypto_cleanup(public_cipher_metadata); + + if (status != NX_CRYPTO_SUCCESS) + { +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(status); + } + } + } + + if (length < NX_SECURE_TLS_RSA_PREMASTER_SIZE + 3) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + /* Check padding - first 2 bytes should be 0x00, 0x02 for PKCS#1 padding. A 0x00 byte should immediately + precede the data. */ + if (_nx_secure_client_padded_pre_master[0] != 0x00 || + _nx_secure_client_padded_pre_master[1] != 0x02 || + _nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE - 1] != 0x00) + { + + /* Invalid padding. To avoid Bleichenbacher's attack, use random numbers to + generate premaster secret and continue the operation (which will be properly + taken care of later in _nx_secure_tls_process_finished()). + + This is described in RFC 5246, section 7.4.7.1, page 58-59. */ + + /* Generate premaster secret using random numbers. */ + for (i = 0; i < NX_SECURE_TLS_RSA_PREMASTER_SIZE; ++i) + { + + /* PKCS#1 padding must be random, but CANNOT be 0. */ + do + { + rand_byte = (UCHAR)NX_RAND(); + } while (rand_byte == 0); + tls_key_material -> nx_secure_tls_pre_master_secret[i] = rand_byte; + } + } + else + { + + /* Extract the 48 bytes of the actual pre-master secret from the data we just decrypted, stripping the padding, which + comes at the beginning of the decrypted block (the pre-master secret is the last 48 bytes. */ + NX_SECURE_MEMCPY(tls_key_material -> nx_secure_tls_pre_master_secret, + &_nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE], NX_SECURE_TLS_RSA_PREMASTER_SIZE); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_pre_master_secret_size = NX_SECURE_TLS_RSA_PREMASTER_SIZE; + } /* End RSA-specific section. */ + else + { + /* Unknown or invalid public cipher. */ + return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + } + } + } +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); +#endif /* NX_SECURE_KEY_CLEAR */ + + return(NX_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_process_server_key_exchange.c b/nx_secure/src/nx_secure_process_server_key_exchange.c new file mode 100644 index 00000000..54f1bcfe --- /dev/null +++ b/nx_secure/src/nx_secure_process_server_key_exchange.c @@ -0,0 +1,957 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" +#ifdef NX_SECURE_ENABLE_DTLS +#include "nx_secure_dtls.h" +#endif /* NX_SECURE_ENABLE_DTLS */ + +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE +static UCHAR hash[64]; /* We concatenate MD5 and SHA-1 hashes into this buffer, OR SHA-256, SHA-384, SHA512. */ +static UCHAR decrypted_signature[512]; +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_process_server_key_exchange PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes an incoming ServerKeyExchange message, */ +/* which is sent by the remote TLS Server host when certain */ +/* ciphersuites (e.g. those using Diffie-Hellman) are used. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* tls_crypto_table TLS crypto methods */ +/* protocol_version Selected TLS version */ +/* packet_buffer Pointer to message data */ +/* message_length Length of message data (bytes)*/ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ +/* tls_handshake_hash Metadata for handshake hash */ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* public_auth_metadata Metadata for public auth */ +/* public_auth_metadata_size Size of public auth metadata */ +/* tls_ecc_curves ECC curves */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_tls_find_curve_method Find named curve used */ +/* _nx_secure_x509_remote_endpoint_certificate_get */ +/* Get remote host certificate */ +/* _nx_secure_x509_find_certificate_methods */ +/* Find certificate methods */ +/* _nx_secure_x509_pkcs7_decode Decode the PKCS#7 signature */ +/* [nx_crypto_init] Crypto initialization */ +/* [nx_crypto_operation] Crypto operation */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_process_server_key_exchange */ +/* Process ServerKeyExchange */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_process_server_key_exchange(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_CRYPTO *tls_crypto_table, + USHORT protocol_version, UCHAR *packet_buffer, UINT message_length, + NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, NX_SECURE_TLS_CREDENTIALS *tls_credentials, + NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size, VOID *tls_ecc_curves) +{ + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES +USHORT length; +#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ +#if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || \ + (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)) +UINT status; + +#endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ +#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) +VOID *handler = NX_NULL; +#endif +#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) +const NX_CRYPTO_METHOD *curve_method; +const NX_CRYPTO_METHOD *ecdh_method; +NX_SECURE_X509_CERT *certificate; +NX_CRYPTO_EXTENDED_OUTPUT extended_output; +UINT key_length; +UCHAR *key; +const NX_CRYPTO_METHOD *curve_method_cert; +const NX_CRYPTO_METHOD *hash_method; +const NX_CRYPTO_METHOD *auth_method; +USHORT signature_length; +NX_SECURE_X509_CRYPTO *crypto_methods; +UINT sig_oid_length; +const UCHAR *sig_oid; +UINT decrypted_hash_length; +const UCHAR *decrypted_hash; +UINT compare_result; +NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; +UCHAR *current_buffer; +UCHAR hash_algorithm; +UCHAR signature_algorithm; +USHORT signature_algorithm_id; +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +UINT i; +#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ +#endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ + +#if !defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || (!NX_SECURE_TLS_TLS_1_0_ENABLED && !NX_SECURE_TLS_TLS_1_1_ENABLED) + NX_PARAMETER_NOT_USED(tls_crypto_table); + NX_PARAMETER_NOT_USED(protocol_version); + NX_PARAMETER_NOT_USED(ciphersuite); + NX_PARAMETER_NOT_USED(tls_key_material); + NX_PARAMETER_NOT_USED(tls_credentials); + NX_PARAMETER_NOT_USED(tls_handshake_hash); + NX_PARAMETER_NOT_USED(public_cipher_metadata); + NX_PARAMETER_NOT_USED(public_cipher_metadata_size); + NX_PARAMETER_NOT_USED(public_auth_metadata); + NX_PARAMETER_NOT_USED(public_auth_metadata_size); + NX_PARAMETER_NOT_USED(tls_ecc_curves); +#endif + + NX_PARAMETER_NOT_USED(packet_buffer); + NX_PARAMETER_NOT_USED(message_length); + + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + /* Check for PSK ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) + { + + /* Get identity hint length. */ + length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]); + packet_buffer += 2; + + if (length > message_length || length > NX_SECURE_TLS_MAX_PSK_ID_SIZE) + { + /* The payload is larger than the header indicated. */ + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + /* Extract the identity hint and save in the TLS Session. Then when pre-master is generated + in client_handshake, we can do the right thing... */ + NX_SECURE_MEMCPY(tls_credentials -> nx_secure_tls_remote_psk_id, &packet_buffer[0], length); /* Use case of memcpy is verified. */ + tls_credentials -> nx_secure_tls_remote_psk_id_size = length; + return(NX_SECURE_TLS_SUCCESS); + + + } +#endif + +#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE + /* Check for ECJ-PAKE ciphersuites. */ + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) + { + /* Make sure curve type is named_curve (3). */ + if (packet_buffer[0] != 3) + { + return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT); + } + + /* Only secp256r1 (23) is supported. */ + if (packet_buffer[1] != 0 || packet_buffer[2] != 23) + { + return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); + } + + packet_buffer += 3; + + + tls_key_material -> nx_secure_tls_pre_master_secret_size = 32; + + status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_PROCESS, + &handler, + (NX_CRYPTO_METHOD *)ciphersuite -> nx_secure_tls_public_auth, + NX_NULL, 0, + packet_buffer, + message_length, + NX_NULL, + tls_key_material -> nx_secure_tls_pre_master_secret, + tls_key_material -> nx_secure_tls_pre_master_secret_size, + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if (status) + { + return(status); + } + + if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup) + { + status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup(public_auth_metadata); + } + + return(status); + } +#endif + +#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + if ((ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE)) + { + + if (message_length < 4) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + /* Make sure curve type is named_curve (3). */ + if (packet_buffer[0] != 3) + { + return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT); + } + + /* Find out which named curve the server is using. */ + status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)((packet_buffer[1] << 8) + packet_buffer[2]), &curve_method, NX_NULL); + + if (status != NX_SUCCESS) + { + + /* The remote server is using an unsupported curve. */ + return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); + } + + current_buffer = &packet_buffer[3]; + + /* Get reference to remote server certificate so we can get the public key for signature verification. */ + status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, + &certificate); + if (status) + { + /* No certificate found, error! */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + + key_length = current_buffer[0]; + key = ¤t_buffer[1]; + + current_buffer += key_length + 1; + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +#ifdef NX_SECURE_ENABLE_DTLS + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0) +#else + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) +#endif /* NX_SECURE_ENABLE_DTLS */ + { + if ((UINT)key_length + 6 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + hash_algorithm = NX_SECURE_TLS_HASH_ALGORITHM_SHA1; + if (certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC) + { + signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; + } + else + { + signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA; + } + } + else +#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ + { + if ((UINT)key_length + 8 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + + hash_algorithm = current_buffer[0]; + signature_algorithm = current_buffer[1]; + current_buffer += 2; + } + + /* Find out the hash algorithm used for the signature. */ + /* Map signature algorithm to internal ID. */ + _nx_secure_tls_get_signature_algorithm_id(((UINT)(hash_algorithm << 8) + signature_algorithm), + &signature_algorithm_id); + + /* Get the cypto method. */ + status = _nx_secure_x509_find_certificate_methods(certificate, + signature_algorithm_id, + &crypto_methods); + if (status) + { + return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM); + } + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +#ifdef NX_SECURE_ENABLE_DTLS + if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0)) +#else + if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) +#endif /* NX_SECURE_ENABLE_DTLS */ + { + + /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */ + hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; + } + else +#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ + { + hash_method = crypto_methods -> nx_secure_x509_hash_method; + } + + + /* Calculate the hash: SHA(ClientHello.random + ServerHello.random + + ServerKeyExchange.params); */ + if (hash_method -> nx_crypto_init) + { + status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + &handler, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + if (hash_method -> nx_crypto_operation != NX_NULL) + { + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + else + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + tls_key_material -> nx_secure_tls_client_random, + 32, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + tls_key_material -> nx_secure_tls_server_random, + 32, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + packet_buffer, + (ULONG)(4 + key_length), + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + hash, + hash_method -> nx_crypto_ICV_size_in_bits >> 3, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + if (hash_method -> nx_crypto_cleanup) + { + status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + handler = NX_NULL; + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +#ifdef NX_SECURE_ENABLE_DTLS + if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0)) +#else + if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) +#endif /* NX_SECURE_ENABLE_DTLS */ + { + hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;; + + /* Calculate the hash: SHA(ClientHello.random + ServerHello.random + + ServerKeyExchange.params); */ + if (hash_method -> nx_crypto_init) + { + status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + &handler, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + if (hash_method -> nx_crypto_operation != NX_NULL) + { + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + else + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + tls_key_material -> nx_secure_tls_client_random, + 32, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + tls_key_material -> nx_secure_tls_server_random, + 32, + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + packet_buffer, + (ULONG)(4 + key_length), + NX_NULL, + NX_NULL, + 0, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, + handler, + (NX_CRYPTO_METHOD*)hash_method, + NX_NULL, + 0, + NX_NULL, + 0, + NX_NULL, + &hash[16], + hash_method -> nx_crypto_ICV_size_in_bits >> 3, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, + NX_NULL, + NX_NULL); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + if (hash_method -> nx_crypto_cleanup) + { + status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch); + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + handler = NX_NULL; + } +#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ + + signature_length = (USHORT)((current_buffer[0] << 8) + current_buffer[1]); + current_buffer += 2; + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +#ifdef NX_SECURE_ENABLE_DTLS + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0) +#else + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) +#endif /* NX_SECURE_ENABLE_DTLS */ + { + if ((UINT)signature_length + key_length + 6 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + } + else +#endif + { + if ((UINT)signature_length + key_length + 8 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + } + + /* Verify the signature. */ + auth_method = ciphersuite -> nx_secure_tls_public_auth; + + if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && + (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA || + auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA)) + { + /* Verify the RSA signature. */ + + if (auth_method -> nx_crypto_init != NX_NULL) + { + /* Initialize the crypto method with public key. */ + status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method, + (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, + (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), + &handler, + public_auth_metadata, + public_auth_metadata_size); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + if (auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA) + { + status = auth_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, + handler, + (NX_CRYPTO_METHOD*)auth_method, + (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent, + (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), + current_buffer, + signature_length, + NX_NULL, + decrypted_signature, + sizeof(decrypted_signature), + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + if (auth_method -> nx_crypto_cleanup) + { + status = auth_method -> nx_crypto_cleanup(public_auth_metadata); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + handler = NX_NULL; + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) +#ifdef NX_SECURE_ENABLE_DTLS + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0) +#else + if (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) +#endif /* NX_SECURE_ENABLE_DTLS */ + { + if (signature_length < 39) + { + return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); + } + + /* Block type is 0x00, 0x01 for signatures */ + if (decrypted_signature[0] != 0x0 && decrypted_signature[1] != 0x1) + { + /* Unknown block type. */ + return(NX_SECURE_TLS_PADDING_CHECK_FAILED); + } + + /* Check padding. */ + for (i = 2; i < (UINT)(signature_length - 37); ++i) + { + if (decrypted_signature[i] != (UCHAR)0xFF) + { + /* Bad padding value. */ + return(NX_SECURE_TLS_PADDING_CHECK_FAILED); + } + } + + /* Make sure we actually saw a NULL byte. */ + if (decrypted_signature[i] != 0x00) + { + return(NX_SECURE_TLS_PADDING_CHECK_FAILED); + } + + decrypted_hash = &decrypted_signature[i + 1]; + decrypted_hash_length = 36; + } + else +#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ + { + /* Decode the decrypted signature. */ + status = _nx_secure_x509_pkcs7_decode(decrypted_signature, signature_length, &sig_oid, &sig_oid_length, + &decrypted_hash, &decrypted_hash_length); + if (status != NX_SUCCESS) + { + return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); + } + + if (decrypted_hash_length != (hash_method -> nx_crypto_ICV_size_in_bits >> 3)) + { + return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); + } + } + + /* Compare generated hash with decrypted hash. */ + compare_result = (UINT)NX_SECURE_MEMCMP(hash, decrypted_hash, decrypted_hash_length); + +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(hash, 0, sizeof(hash)); + NX_SECURE_MEMSET(decrypted_signature, 0, sizeof(decrypted_signature)); +#endif /* NX_SECURE_KEY_CLEAR */ + + if (compare_result != 0) + { + return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); + } + } + else if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA && + auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA) + { + /* Verify the ECDSA signature. */ + + ec_pubkey = &certificate -> nx_secure_x509_public_key.ec_public_key; + + /* Find out which named curve the remote certificate is using. */ + status = _nx_secure_tls_find_curve_method((NX_SECURE_TLS_ECC *)tls_ecc_curves, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); + + if(status != NX_SUCCESS) + { + + /* The remote certificate is using an unsupported curve. */ + return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); + } + + if (auth_method -> nx_crypto_init != NX_NULL) + { + status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method, + (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, + (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), + &handler, + public_auth_metadata, + public_auth_metadata_size); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + if (auth_method -> nx_crypto_operation == NX_NULL) + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + status = auth_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, + (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0, + (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL, + NX_NULL, 0, + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + status = auth_method -> nx_crypto_operation(NX_CRYPTO_VERIFY, handler, + (NX_CRYPTO_METHOD*)auth_method, + (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, + (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), + hash, + hash_method -> nx_crypto_ICV_size_in_bits >> 3, + NX_NULL, + current_buffer, + signature_length, + public_auth_metadata, + public_auth_metadata_size, + NX_NULL, NX_NULL); + + if (status == NX_CRYPTO_AUTHENTICATION_FAILED) + { + return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); + } + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + if (auth_method -> nx_crypto_cleanup) + { + status = auth_method -> nx_crypto_cleanup(public_auth_metadata); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + } + else + { + /* The signature hash algorithm used by the server is not supported. */ + return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM); + } + + ecdh_method = ciphersuite -> nx_secure_tls_public_cipher; + if (ecdh_method -> nx_crypto_operation == NX_NULL) + { + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + } + + if (ecdh_method -> nx_crypto_init != NX_NULL) + { + status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method, + NX_NULL, + 0, + &handler, + public_cipher_metadata, + public_cipher_metadata_size); + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, + NX_NULL, 0, + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + /* Store public key in the nx_secure_tls_new_key_material_data. */ + extended_output.nx_crypto_extended_output_data = &tls_key_material -> nx_secure_tls_new_key_material_data[1]; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_new_key_material_data) - 1; + extended_output.nx_crypto_extended_output_actual_size = 0; + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + NX_NULL, 0, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + /* Store the length in the first octet. */ + tls_key_material -> nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size; + + extended_output.nx_crypto_extended_output_data = tls_key_material -> nx_secure_tls_pre_master_secret; + extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_key_material -> nx_secure_tls_pre_master_secret); + extended_output.nx_crypto_extended_output_actual_size = 0; + status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, + (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, + key, key_length, NX_NULL, + (UCHAR *)&extended_output, + sizeof(extended_output), + public_cipher_metadata, + public_cipher_metadata_size, + NX_NULL, NX_NULL); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_key_material -> nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; + + if (ecdh_method -> nx_crypto_cleanup) + { + status = ecdh_method -> nx_crypto_cleanup(public_cipher_metadata); + } + + return(status); + } +#endif /* NX_SECURE_TLS_CLIENT_DISABLED */ +#endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ + + /* No key exchange should be received by the current cipher suite. */ + return(NX_SECURE_TLS_UNEXPECTED_MESSAGE); +} + +#endif diff --git a/nx_secure/src/nx_secure_remote_certificate_verify.c b/nx_secure/src/nx_secure_remote_certificate_verify.c new file mode 100644 index 00000000..0f6a57de --- /dev/null +++ b/nx_secure/src/nx_secure_remote_certificate_verify.c @@ -0,0 +1,110 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" +#include "nx_secure_x509.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_remote_certificate_verify PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function verifies the authenticity of a certificate provided */ +/* by the remote host by checking its digital signature against the */ +/* trusted store, checking the certificate's validity period, and */ +/* optionally checking the Common Name against the Top-Level Domain */ +/* (TLD) name used to access the remote host. */ +/* */ +/* INPUT */ +/* */ +/* store Pointer to certificate store */ +/* certificate Pointer to cert chain */ +/* current_time Current timestamp */ +/* */ +/* OUTPUT */ +/* */ +/* status Certificate validity status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_x509_certificate_chain_verify */ +/* Verify cert against stores */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_remote_certificate_verify */ +/* Verify the server certificate */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_remote_certificate_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate, ULONG current_time) +{ +UINT status; + + /* Now verify our remote certificate chain. If the certificate can be linked to an issuer in the trusted store + through an issuer chain, this function will return NX_SUCCESS. */ + status = _nx_secure_x509_certificate_chain_verify(store, certificate, current_time); + + if (status != NX_SUCCESS) + { + + /* Translate some X.509 return values into TLS return values. NX_SECURE_X509_CERTIFICATE_NOT_FOUND is removed + as _nx_secure_x509_certificate_chain_verify() will not return this value. */ + switch (status) + { + case NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER: + return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + case NX_SECURE_X509_UNKNOWN_CERT_SIG_ALGORITHM: + return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM); + case NX_SECURE_X509_CERTIFICATE_SIG_CHECK_FAILED: + return(NX_SECURE_TLS_CERTIFICATE_SIG_CHECK_FAILED); +#ifndef NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES + case NX_SECURE_X509_INVALID_SELF_SIGNED_CERT: + return(NX_SECURE_TLS_INVALID_SELF_SIGNED_CERT); +#endif + case NX_SECURE_X509_ISSUER_CERTIFICATE_NOT_FOUND: + return(NX_SECURE_TLS_ISSUER_CERTIFICATE_NOT_FOUND); + case NX_SECURE_X509_MISSING_CRYPTO_ROUTINE: + return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + default: + return(status); + } + } + + return(status); +} + diff --git a/nx_secure/src/nx_secure_session_keys_set.c b/nx_secure/src/nx_secure_session_keys_set.c new file mode 100644 index 00000000..ceae910e --- /dev/null +++ b/nx_secure/src/nx_secure_session_keys_set.c @@ -0,0 +1,228 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) - Generate Session Keys */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_session_keys_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the session keys for a TLS session following the */ +/* sending or receiving of a ChangeCipherSpec message. In */ +/* renegotiation handshakes, two separate set of session keys will be */ +/* in use simultaneously so we need this to be able to separate which */ +/* keys are actually in use. */ +/* */ +/* Once the keys are set, this function initializes the appropriate */ +/* session cipher with the new key set. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* tls_key_material TLS key material */ +/* key_material_data_size Length of key material */ +/* is_client Indicate keys for client */ +/* session_cipher_initialized Whether cipher is initialized */ +/* session_cipher_metadata Metadata for session cipher */ +/* session_cipher_handler Session cipher handler */ +/* session_cipher_metadata_size Size of session metadata */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* [nx_crypto_init] Initialize crypto */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_session_keys_set Set session keys */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_session_keys_set(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + UINT key_material_data_size, UINT is_client, UCHAR *session_cipher_initialized, + VOID *session_cipher_metadata, VOID **session_cipher_handler, ULONG session_cipher_metadata_size) +{ +UINT status; +UCHAR *key_block; /* Maximum ciphersuite key size - AES_256_CBC_SHA, 2x32 byte keys + 2x20 byte MAC secrets + 2x16 IVs. */ +UINT key_size; +UINT hash_size; +UINT iv_size; +UINT key_offset; +UCHAR *write_key; +const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; + + /* The key material should have already been generated by nx_secure_tls_generate_keys once all + * key generation data was available. This simply switches the appropriate key data over to the active + * key block */ + + /* Working pointers into our key material blocks. */ + key_block = tls_key_material -> nx_secure_tls_key_material_data; + + /* Get our session cipher method so we can get key sizes. */ + session_cipher_method = ciphersuite -> nx_secure_tls_session_cipher; + + /* Lookup ciphersuite data for key size. We need 2 keys for each session. */ + key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3; + + /* Lookup ciphersuite data for hash size - used for the MAC secret. */ + hash_size = ciphersuite -> nx_secure_tls_hash_size; + + /* Lookup initialization vector size. */ + iv_size = session_cipher_method -> nx_crypto_IV_size_in_bits >> 3; + + /* Partition the key block into our keys and secrets following the TLS spec.*/ + key_offset = 0; + + if (((hash_size + key_size + iv_size) << 1) > key_material_data_size) + { + + /* No space for key material data. */ + return(NX_SECURE_TLS_CRYPTO_KEYS_TOO_LARGE); + } + + /* First, the mac secrets. Check for non-zero in the (unlikely) event we are using a NULL hash. */ + if (hash_size > 0) + { + + /* Copy new client mac secret over if setting client keys. */ + if (is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], hash_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_client_write_mac_secret = key_block + key_offset; + key_offset += hash_size; + + /* Copy new server mac secret if setting server keys. */ + if (!is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], hash_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_server_write_mac_secret = key_block + key_offset; + key_offset += hash_size; + } + + /* Now the keys. Check for non-zero size in the event we are using a NULL cipher (usually for debugging). */ + if (key_size > 0) + { + /* Copy new client session key if setting client keys. */ + if (is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], key_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_client_write_key = key_block + key_offset; + key_offset += key_size; + + /* Copy new server session key if setting server keys. */ + if (!is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], key_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_server_write_key = key_block + key_offset; + key_offset += key_size; + } + + /* Finally, the IVs. Many ciphers don't use IV's so the iv_size is often zero. */ + if (iv_size > 0) + { + /* Copy new client IV if setting client keys. */ + if (is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], iv_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_client_iv = key_block + key_offset; + key_offset += iv_size; + + /* Copy new server IV if setting server keys. */ + if (!is_client) + { + NX_SECURE_MEMCPY(&tls_key_material -> nx_secure_tls_key_material_data[key_offset], + &tls_key_material -> nx_secure_tls_new_key_material_data[key_offset], iv_size); /* Use case of memcpy is verified. */ + } + tls_key_material -> nx_secure_tls_server_iv = key_block + key_offset; + } + + /* Initialize the crypto method used in the session cipher. */ + if (session_cipher_method -> nx_crypto_init != NULL) + { + /* Set client write key. */ + if (*session_cipher_initialized && session_cipher_method -> nx_crypto_cleanup) + { + status = session_cipher_method -> nx_crypto_cleanup(session_cipher_metadata); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + *session_cipher_initialized = 0; + } + + if (is_client) + { + write_key = tls_key_material -> nx_secure_tls_client_write_key; + } + else + { + write_key = tls_key_material -> nx_secure_tls_server_write_key; + } + + status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, + write_key, + session_cipher_method -> nx_crypto_key_size_in_bits, + session_cipher_handler, + session_cipher_metadata, + session_cipher_metadata_size); + + *session_cipher_initialized = 1; + + if(status != NX_CRYPTO_SUCCESS) + { + return(status); + } + } + + return(NX_SECURE_TLS_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c index fcb16303..9e39bd63 100644 --- a/nx_secure/src/nx_secure_tls_1_3_client_handshake.c +++ b/nx_secure/src/nx_secure_tls_1_3_client_handshake.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -108,6 +108,18 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* updated alert message for */ +/* downgrade protection, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ @@ -141,15 +153,12 @@ UINT _nx_secure_tls_1_3_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH #ifndef NX_SECURE_TLS_CLIENT_DISABLED UINT status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT packet_buffer_length = data_length; UCHAR *packet_start; NX_PACKET *send_packet = NX_NULL; NX_PACKET_POOL *packet_pool; -UINT error_number; -UINT alert_number; -UINT alert_level; const NX_CRYPTO_METHOD *method_ptr = NX_NULL; const UCHAR *server_random; @@ -215,13 +224,24 @@ const UCHAR *server_random; * so we can hash it. */ packet_start = packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); - /* Check for fragmented records. */ + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } + + /* Check for fragmented message. */ if((message_length + header_bytes) > data_length) { - /* Incomplete record! We need to obtain the next fragment. */ + /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */ + tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes; + + tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT; + return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); } @@ -267,7 +287,7 @@ const UCHAR *server_random; if (NX_SECURE_MEMCMP(&(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[24]), server_random, 8) == 0) { - status = NX_SECURE_TLS_UNKNOWN_TLS_VERSION; + status = NX_SECURE_TLS_DOWNGRADE_DETECTED; } else { @@ -368,29 +388,8 @@ const UCHAR *server_random; /* Check for errors in processing messages. */ if (status != NX_SECURE_TLS_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - - if (status != NX_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } - } - return(error_number); + return(status); } /* Now take any actions based on state set in the message processing. */ @@ -668,34 +667,11 @@ const UCHAR *server_random; } /* If we have an error at this point, we have experienced a problem in sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ + handshake messages, which is some type of internal issue. */ if (status != NX_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - - if (status != NX_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } - } - return(error_number); + return(status); } /* Advance the buffer pointer past the message. */ diff --git a/nx_secure/src/nx_secure_tls_1_3_crypto_init.c b/nx_secure/src/nx_secure_tls_1_3_crypto_init.c index 49abb961..5f5fa50e 100644 --- a/nx_secure/src/nx_secure_tls_1_3_crypto_init.c +++ b/nx_secure/src/nx_secure_tls_1_3_crypto_init.c @@ -33,7 +33,7 @@ extern NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_crypto_init PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,9 @@ extern NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -103,17 +106,24 @@ NX_SECURE_TLS_ECC *ecc_info; ecdhe_data = &tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i]; /* Save off the curve ID so we can select the server's chosen key/curve later. */ - ecdhe_data->nx_secure_tls_ecdhe_named_curve = ecc_info -> nx_secure_tls_ecc_supported_groups[i]; + ecdhe_data -> nx_secure_tls_ecdhe_named_curve = ecc_info -> nx_secure_tls_ecc_supported_groups[i]; /* Output the public key to our handshake data structure - we need the length of that buffer. */ - length = sizeof(ecdhe_data->nx_secure_tls_ecdhe_public_key); + length = sizeof(ecdhe_data -> nx_secure_tls_ecdhe_public_key); /* Generate ECC keys and store in our TLS session. */ - status = _nx_secure_tls_ecc_generate_keys(tls_session, ecdhe_data -> nx_secure_tls_ecdhe_named_curve, NX_FALSE, - ecdhe_data->nx_secure_tls_ecdhe_public_key, &length, ecdhe_data); + status = _nx_secure_tls_ecc_generate_keys(tls_session -> nx_secure_tls_session_ciphersuite, tls_session -> nx_secure_tls_protocol_version, + tls_session -> nx_secure_tls_1_3, tls_session -> nx_secure_tls_crypto_table, + &tls_session -> nx_secure_tls_handshake_hash, ecc_info, &tls_session -> nx_secure_tls_key_material, + &tls_session -> nx_secure_tls_credentials, ecdhe_data -> nx_secure_tls_ecdhe_named_curve, NX_FALSE, + ecdhe_data -> nx_secure_tls_ecdhe_public_key, &length, ecdhe_data, + tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, + tls_session -> nx_secure_public_auth_metadata_size); /* Set the actual length of the generated key. */ - ecdhe_data->nx_secure_tls_ecdhe_public_key_length = (USHORT)length; + ecdhe_data -> nx_secure_tls_ecdhe_public_key_length = (USHORT)length; if (status != NX_SUCCESS) { diff --git a/nx_secure/src/nx_secure_tls_1_3_generate_keys.c b/nx_secure/src/nx_secure_tls_1_3_generate_keys.c index 06b5f269..c7bfea6b 100644 --- a/nx_secure/src/nx_secure_tls_1_3_generate_keys.c +++ b/nx_secure/src/nx_secure_tls_1_3_generate_keys.c @@ -169,7 +169,7 @@ UINT is_resumption_psk = NX_FALSE; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_generate_handshake_keys PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -200,6 +200,9 @@ UINT is_resumption_psk = NX_FALSE; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* cleanup for session cipher, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -373,6 +376,17 @@ UINT hash_size; /* Initialize the crypto method used in the session cipher. */ if (session_cipher_method -> nx_crypto_init != NULL) { + if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup) + { + status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_session -> nx_secure_tls_session_cipher_client_initialized = 0; + } + /* Set client write key. */ status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key, @@ -386,6 +400,19 @@ UINT hash_size; return(status); } + tls_session -> nx_secure_tls_session_cipher_client_initialized = 1; + + if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup) + { + status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_session -> nx_secure_tls_session_cipher_server_initialized = 0; + } + /* Set server write key. */ status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key, @@ -398,6 +425,8 @@ UINT hash_size; { return(status); } + + tls_session -> nx_secure_tls_session_cipher_server_initialized = 1; } return(NX_SUCCESS); diff --git a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c index 20eacdfe..60aaaeca 100644 --- a/nx_secure/src/nx_secure_tls_1_3_server_handshake.c +++ b/nx_secure/src/nx_secure_tls_1_3_server_handshake.c @@ -30,8 +30,8 @@ /* */ /* FUNCTION RELEASE */ /* */ -/* _nx_secure_tls_server_handshake PORTABLE C */ -/* 6.1 */ +/* _nx_secure_tls_1_3_server_handshake PORTABLE C */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -59,7 +59,6 @@ /* _nx_secure_tls_generate_keys Generate session keys */ /* _nx_secure_tls_handshake_hash_init Initialize Finished hash */ /* _nx_secure_tls_handshake_hash_update Update Finished hash */ -/* _nx_secure_tls_map_error_to_alert Map internal error to alert */ /* _nx_secure_tls_packet_allocate Allocate internal TLS packet */ /* _nx_secure_tls_process_client_key_exchange */ /* Process ClientKeyExchange */ @@ -69,7 +68,6 @@ /* Process handshake header */ /* _nx_secure_tls_process_remote_certificate */ /* Process server certificate */ -/* _nx_secure_tls_send_alert Send TLS alert */ /* _nx_secure_tls_send_certificate Send TLS certificate */ /* _nx_secure_tls_send_certificate_request */ /* Send TLS CertificateRequest */ @@ -99,6 +97,21 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* removed duplicated alert, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* fixed handling of multiple */ +/* handshake messages, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -108,14 +121,11 @@ UINT _nx_secure_tls_1_3_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCH #ifndef NX_SECURE_TLS_SERVER_DISABLED UINT status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; NX_PACKET *send_packet; NX_PACKET_POOL *packet_pool; UCHAR *packet_start; -UINT error_number; -UINT alert_number; -UINT alert_level; NX_SECURE_TLS_SERVER_STATE old_server_state; /* Basic state machine for handshake: @@ -171,231 +181,177 @@ NX_SECURE_TLS_SERVER_STATE old_server_state; client) and provide key confirmation and handshake integrity. */ - - /* Save a pointer to the start of our packet for the hash that happens below. */ - packet_start = packet_buffer; - - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); - - /* Check for fragmented records. */ - if((message_length + header_bytes) > data_length) + /* Loop through multiple messages in a single record. This can happen if the remote host + packs multiple handshake messages into a single TLS record. */ + while (data_length > 0) { - /* Incomplete record! We need to obtain the next fragment. */ - return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); - } - - /* Advance the buffer pointer past the handshake header. */ - packet_buffer += header_bytes; - /* Get reference to the packet pool so we can allocate a packet for all send operations. */ - packet_pool = tls_session -> nx_secure_tls_packet_pool; + /* Save a pointer to the start of our packet for the hash that happens below. */ + packet_start = packet_buffer; - /* Process the message itself information from the header. */ - status = NX_SECURE_TLS_SUCCESS; - switch (message_type) - { - case NX_SECURE_TLS_CLIENT_HELLO: - old_server_state = tls_session -> nx_secure_tls_server_state; - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_IDLE; + header_bytes = data_length; - /* Client is establishing a TLS session with our server. */ - status = _nx_secure_tls_process_clienthello(tls_session, packet_buffer, message_length); + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); - if(status != NX_SUCCESS) + if (status != NX_SECURE_TLS_SUCCESS) { - break; + return(status); } - if (tls_session -> nx_secure_tls_1_3 == NX_FALSE) + /* Check for fragmented message. */ + if((message_length + header_bytes) > data_length) { + /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */ + tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes; - /* Negotiate a version of TLS prior to TLS 1.3. */ - return(NX_SUCCESS); - } + tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT; - if (old_server_state == NX_SECURE_TLS_SERVER_STATE_IDLE) - { - - /* Initialize the handshake hash - we should have chosen a ciphersuite, so we can - * initialize the hash state now using the chosen hash. */ - _nx_secure_tls_handshake_hash_init(tls_session); + return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); } - if (tls_session -> nx_secure_tls_server_state != NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY) - { - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO; - } - break; -#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY - case NX_SECURE_TLS_CERTIFICATE_MSG: - /* Client sent certificate message (in response to a request from us. Process it now. */ - status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, data_length); + /* Advance the buffer pointer past the handshake header. */ + packet_buffer += header_bytes; - /* If client sends an empty Certificate message, server should abort the handshake with a "certificate_required" alert. */ - if (status == NX_SECURE_TLS_EMPTY_REMOTE_CERTIFICATE_RECEIVED) - { - status = NX_SECURE_TLS_CERTIFICATE_REQUIRED; - } + /* Get reference to the packet pool so we can allocate a packet for all send operations. */ + packet_pool = tls_session -> nx_secure_tls_packet_pool; - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE; - break; - case NX_SECURE_TLS_CERTIFICATE_VERIFY: - /* Client has responded to a certificate request with a CertificateVerify message. */ - status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length); + /* Reduce total length by the size of this message. */ + data_length -= (message_length + header_bytes); - if(status == NX_SUCCESS) + /* Process the message itself information from the header. */ + status = NX_SECURE_TLS_SUCCESS; + switch (message_type) { - /* If remote certificate verification was a success, we have received credentials - from the remote host and may now pass Finished message processing once received. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; - } + case NX_SECURE_TLS_CLIENT_HELLO: + old_server_state = tls_session -> nx_secure_tls_server_state; + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_IDLE; - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY; - break; -#endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */ - case NX_SECURE_TLS_FINISHED: - - /* Save the transcript hash to this point for processing Finished. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); - if(status != NX_SUCCESS) - { - break; - } - - /* Final handshake message from the client, process it (verify the client handshake hash). */ - status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length); - if(status != NX_SUCCESS) - { - break; - } + /* Client is establishing a TLS session with our server. */ + status = _nx_secure_tls_process_clienthello(tls_session, packet_buffer, message_length); - /* Save the transcript hash to this point for key generation - Server Finished was processed so save it. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENT_FINISHED, NX_TRUE); - if(status != NX_SUCCESS) - { - break; - } - - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE; - break; -/* Invalid message types in tls 1.3. - case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE: - case NX_SECURE_TLS_HELLO_VERIFY_REQUEST: - case NX_SECURE_TLS_HELLO_REQUEST: - case NX_SECURE_TLS_SERVER_HELLO: - case NX_SECURE_TLS_SERVER_KEY_EXCHANGE: - case NX_SECURE_TLS_CERTIFICATE_REQUEST: - case NX_SECURE_TLS_SERVER_HELLO_DONE: - case NX_SECURE_TLS_CERTIFICATE_URL: - case NX_SECURE_TLS_CERTIFICATE_STATUS: -*/ - default: - /* The message received was not a valid TLS server handshake message, send alert and return. */ - status = NX_SECURE_TLS_HANDSHAKE_FAILURE; - break; - } - - /* Check for errors in processing messages. */ - if (status != NX_SECURE_TLS_SUCCESS) - { - /* If we encountered an error in message processing set the state to the error condition. */ - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR; - } - else - { - /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them, - we do not worry about them here because these are only messages received from the client at this point. - Hashes include the handshake layer header but not the record layer header. */ - _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes)); - if((message_type == NX_SECURE_TLS_CLIENT_HELLO) && (tls_session -> nx_secure_tls_server_state != NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY)) - { - /* Save the transcript hash for ClientHello - ClientHello was processed so we now have a ciphersuite and know what - our hash method is. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_TRUE); if(status != NX_SUCCESS) { - return status; + break; } - } - } - /* Now take any actions based on state set in the message processing. */ - switch (tls_session -> nx_secure_tls_server_state) - { - case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO: - /* We have received and processed a client hello. Now respond to the client appropriately. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + if (tls_session -> nx_secure_tls_1_3 == NX_FALSE) + { - if (status != NX_SUCCESS) - { - break; - } + /* Negotiate a version of TLS prior to TLS 1.3. */ + return(NX_SUCCESS); + } - status = _nx_secure_tls_send_serverhello(tls_session, send_packet); + if (old_server_state == NX_SECURE_TLS_SERVER_STATE_IDLE) + { + + /* Initialize the handshake hash - we should have chosen a ciphersuite, so we can + * initialize the hash state now using the chosen hash. */ + _nx_secure_tls_handshake_hash_init(tls_session); + } - if (status != NX_SUCCESS) - { + if (tls_session -> nx_secure_tls_server_state != NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY) + { + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO; + } break; - } +#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY + case NX_SECURE_TLS_CERTIFICATE_MSG: + /* Client sent certificate message (in response to a request from us. Process it now. */ + status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, data_length); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); + /* If client sends an empty Certificate message, server should abort the handshake with a "certificate_required" alert. */ + if (status == NX_SECURE_TLS_EMPTY_REMOTE_CERTIFICATE_RECEIVED) + { + status = NX_SECURE_TLS_CERTIFICATE_REQUIRED; + } - if (status != NX_SUCCESS) - { + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE; break; - } + case NX_SECURE_TLS_CERTIFICATE_VERIFY: + /* Client has responded to a certificate request with a CertificateVerify message. */ + status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length); + if(status == NX_SUCCESS) + { + /* If remote certificate verification was a success, we have received credentials + from the remote host and may now pass Finished message processing once received. */ + tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; + } - /* Save the transcript hash to this point for key generation - ServerHello was sent so use it. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVERHELLO, NX_TRUE); - if(status != NX_SUCCESS) - { + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY; break; - } - - NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL); - +#endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */ + case NX_SECURE_TLS_FINISHED: - /* In TLS 1.3, we now have enough information to generate the handshake encryption keys and start encrypting messages. */ - /* Generate TLS 1.3 keys and secrets for the handshake. */ - status = _nx_secure_tls_1_3_generate_handshake_keys(tls_session); - if(status != NX_SUCCESS) - { - break; - } + /* Save the transcript hash to this point for processing Finished. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); + if(status != NX_SUCCESS) + { + break; + } - /* Now turn on encryption. We have generated the handshake keys so the rest of the handshake is encrypted. */ - tls_session -> nx_secure_tls_local_session_active = 1; - tls_session -> nx_secure_tls_remote_session_active = 1; + /* Final handshake message from the client, process it (verify the client handshake hash). */ + status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length); + if(status != NX_SUCCESS) + { + break; + } - /* Send encrypted server extensions (if any) here. */ - - /* We have now started the encrypted TLS 1.3 handshake. Send encrypted extensions now. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + /* Save the transcript hash to this point for key generation - Server Finished was processed so save it. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENT_FINISHED, NX_TRUE); + if(status != NX_SUCCESS) + { + break; + } - if (status != NX_SUCCESS) - { + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE; + break; +/* Invalid message types in tls 1.3. + case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE: + case NX_SECURE_TLS_HELLO_VERIFY_REQUEST: + case NX_SECURE_TLS_HELLO_REQUEST: + case NX_SECURE_TLS_SERVER_HELLO: + case NX_SECURE_TLS_SERVER_KEY_EXCHANGE: + case NX_SECURE_TLS_CERTIFICATE_REQUEST: + case NX_SECURE_TLS_SERVER_HELLO_DONE: + case NX_SECURE_TLS_CERTIFICATE_URL: + case NX_SECURE_TLS_CERTIFICATE_STATUS: +*/ + default: + /* The message received was not a valid TLS server handshake message, send alert and return. */ + status = NX_SECURE_TLS_HANDSHAKE_FAILURE; break; } - status = _nx_secure_tls_send_encrypted_extensions(tls_session, send_packet); - - if (status != NX_SUCCESS) + /* Check for errors in processing messages. */ + if (status != NX_SECURE_TLS_SUCCESS) { - break; + /* If we encountered an error in message processing set the state to the error condition. */ + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR; } - - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_ENCRYPTED_EXTENSIONS, wait_option); - if (status != NX_SUCCESS) + else { - break; + /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them, + we do not worry about them here because these are only messages received from the client at this point. + Hashes include the handshake layer header but not the record layer header. */ + _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes)); + if((message_type == NX_SECURE_TLS_CLIENT_HELLO) && (tls_session -> nx_secure_tls_server_state != NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY)) + { + /* Save the transcript hash for ClientHello - ClientHello was processed so we now have a ciphersuite and know what + our hash method is. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_TRUE); + if(status != NX_SUCCESS) + { + return status; + } + } } -#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY - /* Application has requested that we request and verify the remote Client certificate. */ - if (tls_session -> nx_secure_tls_verify_client_certificate) + /* Now take any actions based on state set in the message processing. */ + switch (tls_session -> nx_secure_tls_server_state) { - /* Allocate a packet for our certificate request message. */ + case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO: + /* We have received and processed a client hello. Now respond to the client appropriately. */ status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); if (status != NX_SUCCESS) @@ -403,52 +359,46 @@ NX_SECURE_TLS_SERVER_STATE old_server_state; break; } - /* Populate our packet with the desired message (CertificateRequest). */ - status = _nx_secure_tls_send_certificate_request(tls_session, send_packet); - NX_ASSERT(status == NX_SUCCESS); + status = _nx_secure_tls_send_serverhello(tls_session, send_packet); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option); if (status != NX_SUCCESS) { break; } - } - else -#endif - { - /* Server is not expecting credentials, so indicate that we have received the client's credentials - to pass Finished processing. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; - } -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* For PSK ciphersuites, don't send the certificate message. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK && - tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size == 0) - { -#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); if (status != NX_SUCCESS) { break; } - _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option); - if (status != NX_SUCCESS) + + /* Save the transcript hash to this point for key generation - ServerHello was sent so use it. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVERHELLO, NX_TRUE); + if(status != NX_SUCCESS) { break; } - /* Save the transcript hash up to the certificate for the CertificateVerify (next message to send). */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE, NX_TRUE); + NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL); + + + /* In TLS 1.3, we now have enough information to generate the handshake encryption keys and start encrypting messages. */ + /* Generate TLS 1.3 keys and secrets for the handshake. */ + status = _nx_secure_tls_1_3_generate_handshake_keys(tls_session); if(status != NX_SUCCESS) { break; } + /* Now turn on encryption. We have generated the handshake keys so the rest of the handshake is encrypted. */ + tls_session -> nx_secure_tls_local_session_active = 1; + tls_session -> nx_secure_tls_remote_session_active = 1; + /* Send encrypted server extensions (if any) here. */ + + /* We have now started the encrypted TLS 1.3 handshake. Send encrypted extensions now. */ status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); if (status != NX_SUCCESS) @@ -456,170 +406,228 @@ NX_SECURE_TLS_SERVER_STATE old_server_state; break; } - _nx_secure_tls_send_certificate_verify(tls_session, send_packet); + status = _nx_secure_tls_send_encrypted_extensions(tls_session, send_packet); + if (status != NX_SUCCESS) + { + break; + } - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_VERIFY, wait_option); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_ENCRYPTED_EXTENSIONS, wait_option); if (status != NX_SUCCESS) { break; } +#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY + /* Application has requested that we request and verify the remote Client certificate. */ + if (tls_session -> nx_secure_tls_verify_client_certificate) + { + /* Allocate a packet for our certificate request message. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + + if (status != NX_SUCCESS) + { + break; + } + + /* Populate our packet with the desired message (CertificateRequest). */ + status = _nx_secure_tls_send_certificate_request(tls_session, send_packet); + NX_ASSERT(status == NX_SUCCESS); + + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option); + if (status != NX_SUCCESS) + { + break; + } + } + else +#endif + { + /* Server is not expecting credentials, so indicate that we have received the client's credentials + to pass Finished processing. */ + tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; + } #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - } -#endif + /* For PSK ciphersuites, don't send the certificate message. */ + if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK && + tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size == 0) + { +#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - /* Save the transcript hash to this point for generating Finished. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); - if(status != NX_SUCCESS) - { - break; - } + if (status != NX_SUCCESS) + { + break; + } - /* We have completed sending everything from the server side and generated our session keys, now send the Finished. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - if (status != NX_SUCCESS) - { - break; - } + _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option); + if (status != NX_SUCCESS) + { + break; + } - /* Populate the packet with our Finished Message. */ - _nx_secure_tls_send_finished(tls_session, send_packet); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option); - if(status != NX_SUCCESS) - { - break; - } + /* Save the transcript hash up to the certificate for the CertificateVerify (next message to send). */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE, NX_TRUE); + if(status != NX_SUCCESS) + { + break; + } - /* Save the finished message now - overwrite previous hash. */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); - if(status != NX_SUCCESS) - { - break; - } - /* Re-generate TLS 1.3 keys and secrets including the Server Finished message for the application data session. */ - status = _nx_secure_tls_1_3_generate_session_keys(tls_session); - if(status != NX_SUCCESS) - { - break; - } + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - /* In TLS 1.3, the server sends everything in a single flight - ServerHello through Finished, so - * no need to go into the other states. */ + if (status != NX_SUCCESS) + { + break; + } - /* Now switch to the session keys for our local session since we have sent the Server Finished message. */ - status = _nx_secure_tls_1_3_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL); - if(status != NX_SUCCESS) - { - break; - } + _nx_secure_tls_send_certificate_verify(tls_session, send_packet); - /* We still need to process the Client responses - certificate (if needed), and Finished. */ - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT; - break; - case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY: - /* We have received and processed a client hello retry requst. Now respond to the client appropriately. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_VERIFY, wait_option); + if (status != NX_SUCCESS) + { + break; + } - if (status != NX_SUCCESS) - { - break; - } - status = _nx_secure_tls_send_serverhello(tls_session, send_packet); +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + } +#endif - if (status != NX_SUCCESS) - { - break; - } + /* Save the transcript hash to this point for generating Finished. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); + if(status != NX_SUCCESS) + { + break; + } + + /* We have completed sending everything from the server side and generated our session keys, now send the Finished. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + if (status != NX_SUCCESS) + { + break; + } + + /* Populate the packet with our Finished Message. */ + _nx_secure_tls_send_finished(tls_session, send_packet); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option); + if(status != NX_SUCCESS) + { + break; + } + + /* Save the finished message now - overwrite previous hash. */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_SERVER_FINISHED, NX_TRUE); + if(status != NX_SUCCESS) + { + break; + } + + /* Re-generate TLS 1.3 keys and secrets including the Server Finished message for the application data session. */ + status = _nx_secure_tls_1_3_generate_session_keys(tls_session); + if(status != NX_SUCCESS) + { + break; + } + + /* In TLS 1.3, the server sends everything in a single flight - ServerHello through Finished, so + * no need to go into the other states. */ + + /* Now switch to the session keys for our local session since we have sent the Server Finished message. */ + status = _nx_secure_tls_1_3_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL); + if(status != NX_SUCCESS) + { + break; + } + + /* We still need to process the Client responses - certificate (if needed), and Finished. */ + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT; - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); - break; - case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE: - - /* Save the transcript hash up to the certificate for the CertificateVerify (next message to send). */ - status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE, NX_TRUE); - break; - case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY: - /* We processed the certificate above, do nothing. */ - break; - case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE: - - /* Now switch to the session keys for our remote session since we have processed the Finished from the Client. */ - status = _nx_secure_tls_1_3_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_REMOTE); - if(status != NX_SUCCESS) - { break; - } + case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY: + /* We have received and processed a client hello retry requst. Now respond to the client appropriately. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - /* Post-Auth server messages (if any) are sent here. */ + if (status != NX_SUCCESS) + { + break; + } - /* For session resumption, send a NewSessionTicket message to allow for resumption PSK to be generated. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - if (status != NX_SUCCESS) - { + status = _nx_secure_tls_send_serverhello(tls_session, send_packet); + + if (status != NX_SUCCESS) + { + break; + } + + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); break; - } + case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE: - /* Populate the packet with our NewSessionTicket Message. */ - status = _nx_secure_tls_send_newsessionticket(tls_session, send_packet); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_NEW_SESSION_TICKET, wait_option); - if(status != NX_SUCCESS) - { + /* Save the transcript hash up to the certificate for the CertificateVerify (next message to send). */ + status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE, NX_TRUE); break; - } + case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY: + /* We processed the certificate above, do nothing. */ + break; + case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE: - /* If we get here, the Client Finished was processed without errors and the handshake is complete. */ - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED; - break; -/* case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE: // tls 1.3: No CLIENT_KEY_EXCHANGE message! - */ - default: /* NX_SECURE_TLS_SERVER_STATE_ERROR */ - /* Default is to break out of the switch because either we encountered an error or - we are in an invalid state. DO NOT change the value of "status" here because - we need its value in the alert processing below. NOTE: we should never - get to this branch with status == NX_SUCCESS because the state will only - be set to NX_SECURE_TLS_SERVER_STATE_ERROR if status indicates an error. */ - NX_ASSERT(status != NX_SUCCESS); - break; - } - - - /* If we have an error at this point, we have experienced a problem in processing or sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ - if (status != NX_SUCCESS) - { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); + /* Now switch to the session keys for our remote session since we have processed the Finished from the Client. */ + status = _nx_secure_tls_1_3_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_REMOTE); + if(status != NX_SUCCESS) + { + break; + } - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); + /* Post-Auth server messages (if any) are sent here. */ + + /* For session resumption, send a NewSessionTicket message to allow for resumption PSK to be generated. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + if (status != NX_SUCCESS) + { + break; + } - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); + /* Populate the packet with our NewSessionTicket Message. */ + status = _nx_secure_tls_send_newsessionticket(tls_session, send_packet); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_NEW_SESSION_TICKET, wait_option); + if(status != NX_SUCCESS) + { + break; + } - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); + /* If we get here, the Client Finished was processed without errors and the handshake is complete. */ + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED; + break; +/* case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE: // tls 1.3: No CLIENT_KEY_EXCHANGE message! + */ + default: /* NX_SECURE_TLS_SERVER_STATE_ERROR */ + /* Default is to break out of the switch because either we encountered an error or + we are in an invalid state. DO NOT change the value of "status" here because + we need its value in the alert processing below. NOTE: we should never + get to this branch with status == NX_SUCCESS because the state will only + be set to NX_SECURE_TLS_SERVER_STATE_ERROR if status indicates an error. */ + NX_ASSERT(status != NX_SUCCESS); + break; + } - if (status == NX_SUCCESS) + /* If we have an error at this point, we have experienced a problem in sending + handshake messages, which is some type of internal issue. */ + if (status != NX_SUCCESS) { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - if (status != NX_SECURE_TLS_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } + return(status); } - return(error_number); - } + /* Advance the buffer pointer past the message. */ + packet_buffer += message_length; + } /* End while. */ - return(status); + return(NX_SUCCESS); #else /* TLS Server disabled. */ /* We don't use the parameters since this is an error case. */ diff --git a/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c b/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c index ba1b5912..55089aa5 100644 --- a/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c +++ b/nx_secure/src/nx_secure_tls_1_3_session_keys_set.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_session_keys_set PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,6 +74,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* cleanup for session cipher, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE @@ -170,15 +173,39 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; /* Set client write key. */ if (is_client) { + if (tls_session -> nx_secure_tls_session_cipher_client_initialized && session_cipher_method -> nx_crypto_cleanup) + { + status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_client); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_session -> nx_secure_tls_session_cipher_client_initialized = 0; + } + status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key, session_cipher_method -> nx_crypto_key_size_in_bits, &tls_session -> nx_secure_session_cipher_handler_client, tls_session -> nx_secure_session_cipher_metadata_area_client, tls_session -> nx_secure_session_cipher_metadata_size); + + tls_session -> nx_secure_tls_session_cipher_client_initialized = 1; } else { + if (tls_session -> nx_secure_tls_session_cipher_server_initialized && session_cipher_method -> nx_crypto_cleanup) + { + status = session_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_session_cipher_metadata_area_server); + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + tls_session -> nx_secure_tls_session_cipher_server_initialized = 0; + } + /* Set server write key. */ status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key, @@ -186,6 +213,8 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; &tls_session -> nx_secure_session_cipher_handler_server, tls_session -> nx_secure_session_cipher_metadata_area_server, tls_session -> nx_secure_session_cipher_metadata_size); + + tls_session -> nx_secure_tls_session_cipher_server_initialized = 1; } if (status != NX_CRYPTO_SUCCESS) { diff --git a/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c b/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c index 378cbe93..38a2de0b 100644 --- a/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c +++ b/nx_secure/src/nx_secure_tls_1_3_transcript_hash_save.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_1_3_transcript_hash_save PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,6 +66,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -107,9 +110,9 @@ CHAR *metadata; { /* Copy over the handshake hash state into a local structure to do the intermediate calculation. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch; } @@ -141,6 +144,11 @@ CHAR *metadata; NX_NULL); } + if (need_copy) + { + NX_SECURE_HASH_CLONE_CLEANUP(metadata, tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + } + return(status); } diff --git a/nx_secure/src/nx_secure_tls_client_handshake.c b/nx_secure/src/nx_secure_tls_client_handshake.c index fb269fd1..46832915 100644 --- a/nx_secure/src/nx_secure_tls_client_handshake.c +++ b/nx_secure/src/nx_secure_tls_client_handshake.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_client_handshake PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -60,7 +60,6 @@ /* _nx_secure_tls_generate_premaster_secret */ /* Generate premaster secret */ /* _nx_secure_tls_handshake_hash_update Update Finished hash */ -/* _nx_secure_tls_map_error_to_alert Map internal error to alert */ /* _nx_secure_tls_packet_allocate Allocate internal TLS packet */ /* _nx_secure_tls_process_certificate_request */ /* Process certificate request */ @@ -74,7 +73,6 @@ /* _nx_secure_tls_process_serverhello Process ServerHello */ /* _nx_secure_tls_remote_certificate_free_all */ /* Free all remote certificates */ -/* _nx_secure_tls_send_alert Send TLS alert */ /* _nx_secure_tls_send_certificate Send TLS certificate */ /* _nx_secure_tls_send_certificate_verify */ /* Send certificate verify */ @@ -107,6 +105,20 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 03-02-2021 Timothy Stapko Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.5 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* removed duplicated alert, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -116,15 +128,12 @@ UINT _nx_secure_tls_client_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR * UINT status; UINT temp_status; USHORT message_type = NX_SECURE_TLS_INVALID_MESSAGE; -USHORT header_bytes; +UINT header_bytes; UINT message_length; UINT packet_buffer_length = data_length; UCHAR *packet_start; NX_PACKET *send_packet = NX_NULL; NX_PACKET_POOL *packet_pool; -UINT error_number; -UINT alert_number; -UINT alert_level; const NX_CRYPTO_METHOD *method_ptr = NX_NULL; @@ -142,13 +151,24 @@ const NX_CRYPTO_METHOD * so we can hash it. */ packet_start = packet_buffer; + header_bytes = data_length; + /* First, process the handshake message to get our state and any data therein. */ - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); + + if (status != NX_SECURE_TLS_SUCCESS) + { + return(status); + } - /* Check for fragmented records. */ + /* Check for fragmented message. */ if((message_length + header_bytes) > data_length) { - /* Incomplete record! We need to obtain the next fragment. */ + /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */ + tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes; + + tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT; + return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); } @@ -289,29 +309,8 @@ const NX_CRYPTO_METHOD /* Check for errors in processing messages. */ if (status != NX_SECURE_TLS_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - - if (status != NX_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } - } - return(error_number); + return(status); } /* Now take any actions based on state set in the message processing. */ @@ -326,7 +325,6 @@ const NX_CRYPTO_METHOD /* This means an error was encountered at some point in processing a valid message. At this point the alert was sent, so just return a status indicating as much. */ return(NX_SECURE_TLS_HANDSHAKE_FAILURE); - break; #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION case NX_SECURE_TLS_CLIENT_STATE_HELLO_REQUEST: /* Server sent a hello request, indicating it wants to restart the handshake process with a new ClientHello. */ @@ -573,34 +571,11 @@ const NX_CRYPTO_METHOD } /* If we have an error at this point, we have experienced a problem in sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ + handshake messages, which is some type of internal issue. */ if (status != NX_SUCCESS) { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); - - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) - { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - - if (status != NX_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } - } - return(error_number); + return(status); } /* Advance the buffer pointer past the message. */ diff --git a/nx_secure/src/nx_secure_tls_ecc_generate_keys.c b/nx_secure/src/nx_secure_tls_ecc_generate_keys.c index d8c8f1bf..5d2e1e23 100644 --- a/nx_secure/src/nx_secure_tls_ecc_generate_keys.c +++ b/nx_secure/src/nx_secure_tls_ecc_generate_keys.c @@ -47,7 +47,7 @@ static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[] = {0x30, 0x51, 0x30, 0x0d, /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_ecc_generate_keys PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,12 +68,23 @@ static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[] = {0x30, 0x51, 0x30, 0x0d, /* */ /* INPUT */ /* */ -/* tls_session TLS control block */ +/* ciphersuite Selected cipher suite */ +/* protocol_version Selected TLS version */ +/* tls_1_3 Whether TLS 1.3 is chosen */ +/* tls_crypto_table TLS crypto methods */ +/* tls_handshake_hash Metadata for handshake hash */ +/* tls_ecc_curves ECC curves */ +/* tls_key_material TLS key material */ +/* tls_credentials TLS credentials */ /* ecc_named_curve IANA ECC curve identifier */ /* sign_key True/False generate signature */ /* public_key Signed ECC public key */ /* public_key_size Size of public key */ /* ecc_data ECC data (incl. private key) */ +/* public_cipher_metadata Metadata for public cipher */ +/* public_cipher_metadata_size Size of public cipher metadata*/ +/* public_auth_metadata Metadata for public auth */ +/* public_auth_metadata_size Size of public auth metadata */ /* */ /* OUTPUT */ /* */ @@ -96,10 +107,21 @@ static const UCHAR _NX_CRYPTO_DER_OID_SHA_512[] = {0x30, 0x51, 0x30, 0x0d, /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), removed */ +/* internal unreachable logic, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -UINT _nx_secure_tls_ecc_generate_keys(NX_SECURE_TLS_SESSION *tls_session, UINT ecc_named_curve, USHORT sign_key, - UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data) +UINT _nx_secure_tls_ecc_generate_keys(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, USHORT protocol_version, UCHAR tls_1_3, + NX_SECURE_TLS_CRYPTO *tls_crypto_table, NX_SECURE_TLS_HANDSHAKE_HASH *tls_handshake_hash, + NX_SECURE_TLS_ECC *tls_ecc_curves, NX_SECURE_TLS_KEY_MATERIAL *tls_key_material, + NX_SECURE_TLS_CREDENTIALS *tls_credentials, UINT ecc_named_curve, USHORT sign_key, + UCHAR *public_key, UINT *public_key_size, NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_data, + VOID *public_cipher_metadata, ULONG public_cipher_metadata_size, + VOID *public_auth_metadata, ULONG public_auth_metadata_size) { UINT length; UINT output_size; @@ -122,24 +144,27 @@ NX_SECURE_EC_PRIVATE_KEY *ec_privkey; NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; USHORT signature_algorithm_id; +#if !(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED) + NX_PARAMETER_NOT_USED(protocol_version); +#endif + +#if !(NX_SECURE_TLS_TLS_1_3_ENABLED) || (!(NX_SECURE_TLS_TLS_1_0_ENABLED) && !(NX_SECURE_TLS_TLS_1_1_ENABLED)) + NX_PARAMETER_NOT_USED(tls_1_3); + NX_PARAMETER_NOT_USED(tls_crypto_table); +#endif + #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(tls_session->nx_secure_tls_1_3) + if(tls_1_3) { - ecdhe_method = tls_session->nx_secure_tls_crypto_table->nx_secure_tls_ecdhe_method; + ecdhe_method = tls_crypto_table -> nx_secure_tls_ecdhe_method; } else #endif { - if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) - { - - /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */ - return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); - } /* Generate ECDHE key pair using ECDHE crypto method. */ - ecdhe_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher; + ecdhe_method = ciphersuite -> nx_secure_tls_public_cipher; } /* Make sure we have a method to use. */ @@ -149,19 +174,14 @@ USHORT signature_algorithm_id; } /* Set the curve we are using. */ - ecc_data->nx_secure_tls_ecdhe_named_curve = ecc_named_curve; + ecc_data -> nx_secure_tls_ecdhe_named_curve = ecc_named_curve; /* Find out which named curve the we are using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)ecc_named_curve, &curve_method, NX_NULL); + status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)ecc_named_curve, &curve_method, NX_NULL); if(status != NX_SUCCESS) { return(status); } - if (curve_method == NX_NULL) - { - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - if (ecdhe_method -> nx_crypto_init != NX_NULL) { @@ -169,8 +189,8 @@ USHORT signature_algorithm_id; NX_NULL, 0, &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); + public_cipher_metadata, + public_cipher_metadata_size); if(status != NX_CRYPTO_SUCCESS) { return(status); @@ -181,8 +201,8 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0, (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, + public_cipher_metadata, + public_cipher_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -196,7 +216,7 @@ USHORT signature_algorithm_id; *public_key_size = 0; #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(!tls_session->nx_secure_tls_1_3) + if(!tls_1_3) #endif { /* ECCurveType: named_curve (3). */ @@ -212,7 +232,7 @@ USHORT signature_algorithm_id; /* Generate the key pair and output the public key. */ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(tls_session->nx_secure_tls_1_3) + if(tls_1_3) { extended_output.nx_crypto_extended_output_data = &public_key[length]; extended_output.nx_crypto_extended_output_length_in_byte = output_size - length; @@ -229,8 +249,8 @@ USHORT signature_algorithm_id; NX_NULL, 0, NX_NULL, (UCHAR *)&extended_output, sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, + public_cipher_metadata, + public_cipher_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -238,7 +258,7 @@ USHORT signature_algorithm_id; } #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(!tls_session->nx_secure_tls_1_3) + if(!tls_1_3) #endif { /* Put the length into the buffer before the key data. */ @@ -259,8 +279,8 @@ USHORT signature_algorithm_id; NX_NULL, 0, NX_NULL, (UCHAR *)&extended_output, sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, + public_cipher_metadata, + public_cipher_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -273,7 +293,7 @@ USHORT signature_algorithm_id; /* Cleanup the ECC crypto state. */ if (ecdhe_method -> nx_crypto_cleanup) { - status = ecdhe_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); + status = ecdhe_method -> nx_crypto_cleanup(public_cipher_metadata); if(status != NX_CRYPTO_SUCCESS) { return(status); @@ -284,14 +304,14 @@ USHORT signature_algorithm_id; if(sign_key == NX_TRUE) { /* Get the local certificate. */ - if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL) + if (tls_credentials -> nx_secure_tls_active_certificate != NX_NULL) { - certificate = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate; + certificate = tls_credentials -> nx_secure_tls_active_certificate; } else { /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */ - status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, + status = _nx_secure_x509_local_device_certificate_get(&tls_credentials -> nx_secure_tls_certificate_store, NX_NULL, &certificate); if (status != NX_SUCCESS) { @@ -323,18 +343,18 @@ USHORT signature_algorithm_id; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0)) #else if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) #endif /* NX_SECURE_ENABLE_DTLS */ { /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */ - hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; + hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; } else #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ @@ -352,8 +372,8 @@ USHORT signature_algorithm_id; NX_NULL, 0, &handler, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size); + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size); if(status != NX_CRYPTO_SUCCESS) { @@ -373,8 +393,8 @@ USHORT signature_algorithm_id; NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -393,13 +413,13 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)hash_method, NX_NULL, 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, + tls_key_material -> nx_secure_tls_client_random, 32, NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -413,13 +433,13 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)hash_method, NX_NULL, 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, + tls_key_material -> nx_secure_tls_server_random, 32, NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -438,8 +458,8 @@ USHORT signature_algorithm_id; NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -458,8 +478,8 @@ USHORT signature_algorithm_id; NX_NULL, hash, hash_length, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -470,7 +490,7 @@ USHORT signature_algorithm_id; if (hash_method -> nx_crypto_cleanup) { - status = hash_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch); + status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch); if(status != NX_CRYPTO_SUCCESS) { @@ -482,16 +502,16 @@ USHORT signature_algorithm_id; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0)) #else if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) #endif /* NX_SECURE_ENABLE_DTLS */ { - hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;; + hash_method = tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;; /* Calculate the hash: SHA(ClientHello.random + ServerHello.random + ServerKeyExchange.params); */ @@ -501,8 +521,8 @@ USHORT signature_algorithm_id; NX_NULL, 0, &handler, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size); + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size); if(status != NX_CRYPTO_SUCCESS) { @@ -522,8 +542,8 @@ USHORT signature_algorithm_id; NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -542,13 +562,13 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)hash_method, NX_NULL, 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, + tls_key_material -> nx_secure_tls_client_random, 32, NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -562,13 +582,13 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)hash_method, NX_NULL, 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, + tls_key_material -> nx_secure_tls_server_random, 32, NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -587,8 +607,8 @@ USHORT signature_algorithm_id; NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -607,8 +627,8 @@ USHORT signature_algorithm_id; NX_NULL, &hash[16], hash_method -> nx_crypto_ICV_size_in_bits >> 3, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch, + tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch_size, NX_NULL, NX_NULL); @@ -619,7 +639,7 @@ USHORT signature_algorithm_id; if (hash_method -> nx_crypto_cleanup) { - status = hash_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch); + status = hash_method -> nx_crypto_cleanup(tls_handshake_hash -> nx_secure_tls_handshake_hash_scratch); if(status != NX_CRYPTO_SUCCESS) { @@ -632,12 +652,12 @@ USHORT signature_algorithm_id; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS - if (tls_session -> nx_secure_tls_protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 && - tls_session -> nx_secure_tls_protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1 && - tls_session -> nx_secure_tls_protocol_version != NX_SECURE_DTLS_VERSION_1_0) + if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 && + protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1 && + protocol_version != NX_SECURE_DTLS_VERSION_1_0) #else - if (tls_session -> nx_secure_tls_protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 && - tls_session -> nx_secure_tls_protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1) + if (protocol_version != NX_SECURE_TLS_VERSION_TLS_1_0 && + protocol_version != NX_SECURE_TLS_VERSION_TLS_1_1) #endif /* NX_SECURE_ENABLE_DTLS */ #endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ { @@ -649,7 +669,7 @@ USHORT signature_algorithm_id; } /* Sign the hash. */ - auth_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth; + auth_method = ciphersuite -> nx_secure_tls_public_auth; if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA || auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA)) @@ -664,13 +684,13 @@ USHORT signature_algorithm_id; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + protocol_version == NX_SECURE_DTLS_VERSION_1_0)) #else if ((ecc_data -> nx_secure_tls_ecdhe_signature_algorithm & 0xFF) == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) + (protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) #endif /* NX_SECURE_ENABLE_DTLS */ { hash_length += hash_method -> nx_crypto_ICV_size_in_bits >> 3; @@ -728,13 +748,14 @@ USHORT signature_algorithm_id; _nx_secure_padded_signature[0] = 0x0; _nx_secure_padded_signature[1] = 0x1; _nx_secure_padded_signature[signature_offset - 1] = 0x0; +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (der_encoding_length > 0) +#endif { NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], der_encoding, der_encoding_length); /* Use case of memcpy is verified. */ signature_offset += der_encoding_length; } NX_CRYPTO_MEMCPY(&_nx_secure_padded_signature[signature_offset], hash, hash_length); /* Use case of memcpy is verified. */ - if (auth_method -> nx_crypto_init != NX_NULL) { /* Initialize the crypto method with public key. */ @@ -742,14 +763,13 @@ USHORT signature_algorithm_id; (UCHAR *)certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, (NX_CRYPTO_KEY_SIZE)(certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), &handler, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size); + public_auth_metadata, + public_auth_metadata_size); if (status != NX_CRYPTO_SUCCESS) { return(status); } } - if (auth_method -> nx_crypto_operation != NX_NULL) { /* Sign the hash we just generated using our local RSA private key (associated with our local cert). */ @@ -763,8 +783,8 @@ USHORT signature_algorithm_id; NX_NULL, &public_key[length], signature_length, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, + public_auth_metadata, + public_auth_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -776,7 +796,7 @@ USHORT signature_algorithm_id; if (auth_method -> nx_crypto_cleanup) { - status = auth_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); + status = auth_method -> nx_crypto_cleanup(public_auth_metadata); if(status != NX_CRYPTO_SUCCESS) { @@ -791,17 +811,11 @@ USHORT signature_algorithm_id; ec_pubkey = &certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the local certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); + status = _nx_secure_tls_find_curve_method(tls_ecc_curves, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); if(status != NX_SUCCESS) { return(status); } - if (curve_method_cert == NX_NULL) - { - - /* The local certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } if (auth_method -> nx_crypto_init != NX_NULL) { @@ -809,8 +823,8 @@ USHORT signature_algorithm_id; (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), &handler, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size); + public_auth_metadata, + public_auth_metadata_size); if (status != NX_CRYPTO_SUCCESS) { return(status); @@ -825,8 +839,8 @@ USHORT signature_algorithm_id; (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0, (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL, NX_NULL, 0, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, + public_auth_metadata, + public_auth_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -845,8 +859,8 @@ USHORT signature_algorithm_id; hash_method -> nx_crypto_ICV_size_in_bits >> 3, NX_NULL, (UCHAR *)&extended_output, sizeof(extended_output), - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, + public_auth_metadata, + public_auth_metadata_size, NX_NULL, NX_NULL); if (status != NX_CRYPTO_SUCCESS) { @@ -855,7 +869,7 @@ USHORT signature_algorithm_id; if (auth_method -> nx_crypto_cleanup) { - status = auth_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); + status = auth_method -> nx_crypto_cleanup(public_auth_metadata); if(status != NX_CRYPTO_SUCCESS) { diff --git a/nx_secure/src/nx_secure_tls_ecc_initialize.c b/nx_secure/src/nx_secure_tls_ecc_initialize.c index 638f3127..60b9d602 100644 --- a/nx_secure/src/nx_secure_tls_ecc_initialize.c +++ b/nx_secure/src/nx_secure_tls_ecc_initialize.c @@ -26,14 +26,23 @@ #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; +#ifndef NX_SECURE_DISABLE_X509 +/* Supported named curves. */ +extern const USHORT *_nx_secure_x509_ecc_supported_groups; + +/* Number of supported named curves. */ +extern USHORT _nx_secure_x509_ecc_supported_groups_count; + +/* Corresponding crypto methods for the supported named curve. */ +extern const NX_CRYPTO_METHOD **_nx_secure_x509_ecc_curves; +#endif /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_ecc_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,6 +77,9 @@ NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), added */ +/* ECC curve table in X509, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_ecc_initialize(NX_SECURE_TLS_SESSION *tls_session, @@ -79,9 +91,11 @@ UINT _nx_secure_tls_ecc_initialize(NX_SECURE_TLS_SESSION *tls_session, tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_supported_groups_count = supported_group_count; tls_session -> nx_secure_tls_ecc.nx_secure_tls_ecc_curves = curves; - _nx_secure_tls_ecc_info.nx_secure_tls_ecc_supported_groups = supported_groups; - _nx_secure_tls_ecc_info.nx_secure_tls_ecc_supported_groups_count = supported_group_count; - _nx_secure_tls_ecc_info.nx_secure_tls_ecc_curves = curves; +#ifndef NX_SECURE_DISABLE_X509 + _nx_secure_x509_ecc_supported_groups = supported_groups; + _nx_secure_x509_ecc_supported_groups_count = supported_group_count; + _nx_secure_x509_ecc_curves = curves; +#endif return(NX_SUCCESS); } diff --git a/nx_secure/src/nx_secure_tls_find_curve_method.c b/nx_secure/src/nx_secure_tls_find_curve_method.c index b561a02e..b1173266 100644 --- a/nx_secure/src/nx_secure_tls_find_curve_method.c +++ b/nx_secure/src/nx_secure_tls_find_curve_method.c @@ -26,14 +26,12 @@ #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -extern NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_find_curve_method PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -77,8 +75,6 @@ extern NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; /* Send CertificateVerify */ /* _nx_secure_tls_send_server_key_exchange */ /* Send ServerKeyExchange */ -/* _nx_secure_x509_certificate_verify Verify a certificate */ -/* _nx_secure_x509_crl_verify Verify revocation list */ /* */ /* RELEASE HISTORY */ /* */ @@ -88,30 +84,27 @@ extern NX_SECURE_TLS_ECC _nx_secure_tls_ecc_info; /* 09-30-2020 Timothy Stapko Modified comment(s), added */ /* curve priority return value,*/ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), added */ +/* ECC curve table in X509, */ +/* resulting in version 6.1.6 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -UINT _nx_secure_tls_find_curve_method(NX_SECURE_TLS_SESSION *tls_session, - USHORT named_curve, const NX_CRYPTO_METHOD **curve_method, UINT *curve_priority) +UINT _nx_secure_tls_find_curve_method(NX_SECURE_TLS_ECC *tls_ecc, USHORT named_curve, + const NX_CRYPTO_METHOD **curve_method, UINT *curve_priority) { USHORT i; -NX_SECURE_TLS_ECC *ecc_info; - - if (tls_session == NX_NULL) - { - ecc_info = &_nx_secure_tls_ecc_info; - } - else - { - ecc_info = &(tls_session -> nx_secure_tls_ecc); - } *curve_method = NX_NULL; + /* Find out the curve method for the named curve. */ - for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++) + for (i = 0; i < tls_ecc -> nx_secure_tls_ecc_supported_groups_count; i++) { - if (named_curve == ecc_info -> nx_secure_tls_ecc_supported_groups[i]) + if (named_curve == tls_ecc -> nx_secure_tls_ecc_supported_groups[i]) { - *curve_method = ecc_info -> nx_secure_tls_ecc_curves[i]; + *curve_method = tls_ecc -> nx_secure_tls_ecc_curves[i]; /* The index in the supported list is the curve priority: lower value == higher priority. */ if(curve_priority != NX_NULL) diff --git a/nx_secure/src/nx_secure_tls_finished_hash_generate.c b/nx_secure/src/nx_secure_tls_finished_hash_generate.c index 05cb2ecc..4961b2cb 100644 --- a/nx_secure/src/nx_secure_tls_finished_hash_generate.c +++ b/nx_secure/src/nx_secure_tls_finished_hash_generate.c @@ -33,7 +33,7 @@ static UCHAR handshake_hash[16 + 20]; /* We concatenate MD5 and SHA-1 hashes int /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_finished_hash_generate PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,6 +72,9 @@ static UCHAR handshake_hash[16 + 20]; /* We concatenate MD5 and SHA-1 hashes int /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_finished_hash_generate(NX_SECURE_TLS_SESSION *tls_session, @@ -133,9 +136,9 @@ UINT hash_size = 0; #endif /* NX_SECURE_ENABLE_DTLS */ { /* Copy over the handshake hash state into scratch space to do the intermediate calculation. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, /* lgtm[cpp/banned-api-usage-required-any] */ + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ /* Finalize the handshake message hash that we started at the beginning of the handshake. */ method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method; @@ -158,16 +161,20 @@ UINT hash_size = 0; NX_NULL, NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } } else { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE; } + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite, * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */ method_ptr = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_prf; @@ -186,15 +193,11 @@ UINT hash_size = 0; tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) #endif /* NX_SECURE_ENABLE_DTLS */ { - /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in - first, then MD5. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ + /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ /* Finalize the handshake message hashes that we started at the beginning of the handshake. */ method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; @@ -218,17 +221,23 @@ UINT hash_size = 0; metadata_size, NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } } else { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE; + } + + NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); } + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ + method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method; handler = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_handler; metadata = tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch; @@ -251,14 +260,18 @@ UINT hash_size = 0; NX_NULL, NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } + } else { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE; + } + + NX_SECURE_HASH_CLONE_CLEANUP(metadata, metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); } /* TLS 1.0 and TLS 1.1 use the same PRF. */ diff --git a/nx_secure/src/nx_secure_tls_generate_keys.c b/nx_secure/src/nx_secure_tls_generate_keys.c index 6666c335..df5939b6 100644 --- a/nx_secure/src/nx_secure_tls_generate_keys.c +++ b/nx_secure/src/nx_secure_tls_generate_keys.c @@ -27,15 +27,13 @@ #include "nx_secure_dtls.h" #endif /* NX_SECURE_ENABLE_DTLS */ -/* This local static buffer needs to be large enough to hold both the server random and the client random. */ -static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE + NX_SECURE_TLS_RANDOM_SIZE]; /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_generate_keys PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -57,8 +55,8 @@ static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE + NX_SECUR /* */ /* CALLS */ /* */ -/* [nx_crypto_init] Initialize crypto */ -/* [nx_crypto_operation] Crypto operation */ +/* [nx_secure_generate_master_secret] Generate master secrets */ +/* [nx_secure_generate_session_keys] Generate session keys */ /* */ /* CALLED BY */ /* */ @@ -75,6 +73,9 @@ static UCHAR _nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE + NX_SECUR /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_generate_keys(NX_SECURE_TLS_SESSION *tls_session) @@ -82,27 +83,14 @@ UINT _nx_secure_tls_generate_keys(NX_SECURE_TLS_SESSION *tls_session) UCHAR *pre_master_sec; UINT pre_master_sec_size; UCHAR *master_sec; -UCHAR *key_block; /* Maximum ciphersuite key size - AES_256_CBC_SHA, 2x32 byte keys + 2x20 byte MAC secrets + 2x16 IVs. */ -UINT key_block_size; -UINT key_size; -UINT hash_size; -UINT iv_size; UINT status; -const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; const NX_CRYPTO_METHOD *session_prf_method = NX_NULL; const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite; -VOID *handler = NX_NULL; /* Generate the session keys using the parameters obtained in the handshake. By this point all the information needed to generate the TLS session key material should have been gathered and stored in the TLS socket structure. */ - key_block_size = 0; - - /* Working pointer into our new key material block since we are generating new keys. */ - key_block = tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data; - - /* Generate the Master Secret from the Pre-Master Secret. From the RFC (TLS 1.1, TLS 1.2): @@ -122,241 +110,60 @@ VOID *handler = NX_NULL; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } - /* Get our session cipher method so we can get key sizes. */ - session_cipher_method = ciphersuite -> nx_secure_tls_session_cipher; - - /* The generation of key material is different between RSA and DH. */ - if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE - || ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK -#endif -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - || ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE -#endif - ) - { - pre_master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; - pre_master_sec_size = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size; - master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_master_secret; + pre_master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; + pre_master_sec_size = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size; + master_sec = tls_session -> nx_secure_tls_key_material.nx_secure_tls_master_secret; - /* Concatenate random values to feed into PRF. */ - NX_SECURE_MEMCPY(_nx_secure_tls_gen_keys_random, tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, - NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(&_nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE], - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ - /* Generate the master secret using the pre-master secret, the defined TLS label, and the concatenated - random values. */ #if (NX_SECURE_TLS_TLS_1_2_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) + if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || + tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) #else - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) + if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) #endif /* NX_SECURE_ENABLE_DTLS */ - { - /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite, - * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */ - session_prf_method = ciphersuite -> nx_secure_tls_prf; - } + { + /* For TLS 1.2, the PRF is defined by the ciphersuite. However, if we are using an older ciphersuite, + * default to the TLS 1.2 default PRF, which uses SHA-256-HMAC. */ + session_prf_method = ciphersuite -> nx_secure_tls_prf; + } #endif #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0) + if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || + tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0) #else - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) + if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || + tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) #endif /* NX_SECURE_ENABLE_DTLS */ - { - /* TLS 1.0 and TLS 1.1 use the same PRF. */ - session_prf_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_prf_1_method; - } -#endif - /* If we don't have a PRF method, the version is wrong! */ - if (session_prf_method == NX_NULL) - { -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(NX_SECURE_TLS_PROTOCOL_VERSION_CHANGED); - } - - /* Use the PRF to generate the master secret. */ - if (session_prf_method -> nx_crypto_init != NX_NULL) - { - status = session_prf_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_prf_method, - pre_master_sec, (NX_CRYPTO_KEY_SIZE)pre_master_sec_size, - &handler, - tls_session -> nx_secure_tls_prf_metadata_area, - tls_session -> nx_secure_tls_prf_metadata_size); - - if(status != NX_CRYPTO_SUCCESS) - { -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(status); - } - } - - if (session_prf_method -> nx_crypto_operation != NX_NULL) - { - status = session_prf_method -> nx_crypto_operation(NX_CRYPTO_PRF, - handler, - (NX_CRYPTO_METHOD*)session_prf_method, - (UCHAR *)"master secret", - 13, - _nx_secure_tls_gen_keys_random, - 64, - NX_NULL, - master_sec, - 48, - tls_session -> nx_secure_tls_prf_metadata_area, - tls_session -> nx_secure_tls_prf_metadata_size, - NX_NULL, - NX_NULL); - -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); -#endif /* NX_SECURE_KEY_CLEAR */ - - if(status != NX_CRYPTO_SUCCESS) - { - /* Secrets cleared above. */ - return(status); - } - } - - if (session_prf_method -> nx_crypto_cleanup) - { - status = session_prf_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_prf_metadata_area); - - if(status != NX_CRYPTO_SUCCESS) - { - /* All secrets cleared above. */ - return(status); - } - } - } - else { - /* The chosen cipher is not supported. Likely an internal error since negotiation has already finished. */ - return(NX_SECURE_TLS_UNSUPPORTED_CIPHER); + /* TLS 1.0 and TLS 1.1 use the same PRF. */ + session_prf_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_prf_1_method; } +#endif - /* Clear out the Pre-Master Secret (we don't need it anymore and keeping it in memory is dangerous). */ -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(pre_master_sec, 0x0, sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret)); -#endif /* NX_SECURE_KEY_CLEAR */ - - /* Lookup ciphersuite data for key size. We need 2 keys for each session. */ - key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3; - - /* Lookup ciphersuite data for hash size - used for the MAC secret. */ - hash_size = ciphersuite -> nx_secure_tls_hash_size; - - /* Lookup initialization vector size. */ - iv_size = session_cipher_method -> nx_crypto_IV_size_in_bits >> 3; - - /* Now calculate block size. Need client and server for each key, hash, and iv. Note that - key size and iv size may be zero depending on the ciphersuite, particularly when using - the NULL ciphers. */ - key_block_size = 2 * (key_size + hash_size + iv_size); - - /* Now generate keys from the master secret we obtained above. */ - /* From the RFC (TLS 1.1): - To generate the key material, compute - - key_block = PRF(SecurityParameters.master_secret, - "key expansion", - SecurityParameters.server_random + - SecurityParameters.client_random); - - until enough output has been generated. Then the key_block is - partitioned as follows: - - client_write_MAC_secret[SecurityParameters.hash_size] - server_write_MAC_secret[SecurityParameters.hash_size] - client_write_key[SecurityParameters.key_material_length] - server_write_key[SecurityParameters.key_material_length] - */ - - /* The order of the randoms is reversed from that used for the master secret - when generating the key block. */ - NX_SECURE_MEMCPY(_nx_secure_tls_gen_keys_random, tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, - NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(&_nx_secure_tls_gen_keys_random[NX_SECURE_TLS_RANDOM_SIZE], - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + status = tls_session -> nx_secure_generate_master_secret(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method, + &tls_session -> nx_secure_tls_key_material, pre_master_sec, pre_master_sec_size, + master_sec, tls_session -> nx_secure_tls_prf_metadata_area, + tls_session -> nx_secure_tls_prf_metadata_size); - /* Key expansion uses the PRF to generate a block of key material from the master secret (generated - above) and the client and server random values transmitted during the initial hello negotiation. */ - if (session_prf_method -> nx_crypto_init != NX_NULL) + if (status != NX_SECURE_TLS_SUCCESS) { - status = session_prf_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_prf_method, - master_sec, 48, - &handler, - tls_session -> nx_secure_tls_prf_metadata_area, - tls_session -> nx_secure_tls_prf_metadata_size); - - if(status != NX_CRYPTO_SUCCESS) - { -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); -#endif /* NX_SECURE_KEY_CLEAR */ - return(status); - } + return(status); } - if (session_prf_method -> nx_crypto_operation != NX_NULL) - { - status = session_prf_method -> nx_crypto_operation(NX_CRYPTO_PRF, - handler, - (NX_CRYPTO_METHOD*)session_prf_method, - (UCHAR *)"key expansion", - 13, - _nx_secure_tls_gen_keys_random, - 64, - NX_NULL, - key_block, - key_block_size, - tls_session -> nx_secure_tls_prf_metadata_area, - tls_session -> nx_secure_tls_prf_metadata_size, - NX_NULL, - NX_NULL); - + /* Clear out the Pre-Master Secret (we don't need it anymore and keeping it in memory is dangerous). */ #ifdef NX_SECURE_KEY_CLEAR - /* We now have a key block, clear our temporary secrets buffer. */ - NX_SECURE_MEMSET(_nx_secure_tls_gen_keys_random, 0, sizeof(_nx_secure_tls_gen_keys_random)); + NX_SECURE_MEMSET(pre_master_sec, 0x0, sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret)); #endif /* NX_SECURE_KEY_CLEAR */ - if(status != NX_CRYPTO_SUCCESS) - { - /* Secrets cleared above. */ - return(status); - } - } - - if (session_prf_method -> nx_crypto_cleanup) - { - status = session_prf_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_prf_metadata_area); - - if(status != NX_CRYPTO_SUCCESS) - { - /* Secrets cleared above. */ - return(status); - } - } - return(NX_SECURE_TLS_SUCCESS); + status = tls_session -> nx_secure_generate_session_keys(ciphersuite, tls_session -> nx_secure_tls_protocol_version, session_prf_method, + &tls_session -> nx_secure_tls_key_material, master_sec, tls_session -> nx_secure_tls_prf_metadata_area, + tls_session -> nx_secure_tls_prf_metadata_size); + return(status); } diff --git a/nx_secure/src/nx_secure_tls_generate_premaster_secret.c b/nx_secure/src/nx_secure_tls_generate_premaster_secret.c index e04963e5..f1140aca 100644 --- a/nx_secure/src/nx_secure_tls_generate_premaster_secret.c +++ b/nx_secure/src/nx_secure_tls_generate_premaster_secret.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_generate_premaster_secret PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -51,10 +51,8 @@ /* */ /* CALLS */ /* */ -/* _nx_secure_tls_psk_find Find PSK from store */ -/* _nx_secure_tls_find_curve_method Find named curve used */ -/* [nx_crypto_init] Initialize crypto */ -/* [nx_crypto_operation] Crypto operation */ +/* _nx_secure_tls_protocol_version_get Get current TLS version to use*/ +/* [nx_secure_generate_premaster_secret] Generate pre-master secret */ /* */ /* CALLED BY */ /* */ @@ -72,27 +70,18 @@ /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), removed */ +/* internal unreachable logic, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_generate_premaster_secret(NX_SECURE_TLS_SESSION *tls_session, UINT id) { -UINT *buffer_ptr; -UINT i; -UINT status = NX_SECURE_TLS_SUCCESS; -USHORT protocol_version; -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES -UCHAR *psk_data; -UINT psk_length; -UINT index; -#endif -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -NX_SECURE_X509_CERT *server_certificate; -const NX_CRYPTO_METHOD *curve_method_cert; -const NX_CRYPTO_METHOD *ecdh_method; -NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; -VOID *handler = NX_NULL; -NX_CRYPTO_EXTENDED_OUTPUT extended_output; -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ +UINT status; +USHORT protocol_version; if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -101,217 +90,23 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) - { - - return(NX_SECURE_TLS_SUCCESS); - } - else if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH) - { - /* Get reference to remote server certificate so we can find out the named curve. */ - status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - &server_certificate); - if (status || server_certificate == NX_NULL) - { - /* No certificate found, error! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); - } - - ec_pubkey = &server_certificate -> nx_secure_x509_public_key.ec_public_key; - - /* Find out which named curve the remote certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); - - if(status != NX_SUCCESS) - { - return(status); - } - - if (curve_method_cert == NX_NULL) - { - /* The remote certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - - ecdh_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher; - if (ecdh_method -> nx_crypto_operation == NX_NULL) - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - if (ecdh_method -> nx_crypto_init != NX_NULL) - { - status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method, - NX_NULL, - 0, - &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, - (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - /* Store public key in the nx_secure_tls_new_key_material_data. */ - extended_output.nx_crypto_extended_output_data = &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[1]; - extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data) - 1; - extended_output.nx_crypto_extended_output_actual_size = 0; - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler, - (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, - NX_NULL, 0, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size; - - extended_output.nx_crypto_extended_output_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; - extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret); - extended_output.nx_crypto_extended_output_actual_size = 0; - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, - (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, - (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, - ec_pubkey -> nx_secure_ec_public_key_length, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; - - if (ecdh_method -> nx_crypto_cleanup) - { - status = ecdh_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - return(NX_SECURE_TLS_SUCCESS); - } -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* Check for PSK ciphersuites. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) - { - /* Now, using the identity as a key, find the PSK in our PSK store. */ - if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) - { - /* Server just uses its PSK. */ - psk_data = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_data; - psk_length = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_data_size; - } - else - { - /* Client has to search for the PSK based on the identity hint. */ - status = _nx_secure_tls_psk_find(tls_session, &psk_data, &psk_length, tls_session -> nx_secure_tls_credentials.nx_secure_tls_remote_psk_id, - tls_session -> nx_secure_tls_credentials.nx_secure_tls_remote_psk_id_size, NX_NULL); - - if (status != NX_SUCCESS) - { - return(status); - } - } - - /* From RFC 4279: - The premaster secret is formed as follows: if the PSK is N octets - long, concatenate a uint16 with the value N, N zero octets, a second - uint16 with the value N, and the PSK itself. - | 2 | | 2 | | - | N | 0 | N | PSK | - */ - index = 0; - - if ((2 + psk_length + 2 + psk_length) > sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret)) - { - - /* No more PSK space. */ - return(NX_SECURE_TLS_NO_MORE_PSK_SPACE); - } - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[0] = (UCHAR)(psk_length >> 8); - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[1] = (UCHAR)psk_length; - index += 2; - - NX_SECURE_MEMSET(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[index], 0, psk_length); - index += psk_length; - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[index] = (UCHAR)(psk_length >> 8); - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[index + 1] = (UCHAR)psk_length; - index += 2; - - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[index], psk_data, psk_length); /* Use case of memcpy is verified. */ - index += psk_length; - - /* Save the pre-master secret size for later use. */ - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = 2 + psk_length + 2 + psk_length; - - /* We are using PSK for our credentials and now that we have generated keys we can consider the - remote host's credentials to have been received. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; - - return(NX_SECURE_TLS_SUCCESS); - } -#endif + _nx_secure_tls_protocol_version_get(tls_session, &protocol_version, id); -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - /* When using ECJ-PAKE ciphersuite, pre-master secret is already generated. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) - { - /* If using EC-JPAKE, credentials are passed differently - if we get here credentials should be OK. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + status = tls_session -> nx_secure_generate_premaster_secret(tls_session -> nx_secure_tls_session_ciphersuite, protocol_version, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + tls_session -> nx_secure_tls_socket_type, + &tls_session -> nx_secure_tls_received_remote_credentials, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, &tls_session -> nx_secure_tls_ecc); +#else + status = tls_session -> nx_secure_generate_premaster_secret(tls_session -> nx_secure_tls_session_ciphersuite, protocol_version, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + tls_session -> nx_secure_tls_socket_type, + &tls_session -> nx_secure_tls_received_remote_credentials, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, NX_NULL); - return(NX_SECURE_TLS_SUCCESS); - } #endif - /* Generate the Pre-Master Secret that is used to generate the key material - used in the session. For TLS 1.1, the secret consists of two bytes - representing the highest protocol version the client supports, followed - by 46 random bytes. */ - buffer_ptr = (UINT *)tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; - - /* Generate 48 bytes of random data, fill in the version afterwards. */ - for (i = 0; i < 12; i++) - { - /* Fill with 12 ULONG randoms, then fix first two bytes to protocol version after. */ - *(buffer_ptr + i) = (UINT)NX_RAND(); - } - - /* First two bytes are newest version supported by client . */ - _nx_secure_tls_protocol_version_get(tls_session, &protocol_version, id); - buffer_ptr[0] = ((ULONG)protocol_version << 16) | (buffer_ptr[0] & 0x0000FFFF); - NX_CHANGE_ULONG_ENDIAN(buffer_ptr[0]); - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = 48; - return(status); } diff --git a/nx_secure/src/nx_secure_tls_handshake_hash_update.c b/nx_secure/src/nx_secure_tls_handshake_hash_update.c index b973cadb..f3fe383f 100644 --- a/nx_secure/src/nx_secure_tls_handshake_hash_update.c +++ b/nx_secure/src/nx_secure_tls_handshake_hash_update.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_handshake_hash_update PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,6 +73,11 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_handshake_hash_update(NX_SECURE_TLS_SESSION *tls_session, UCHAR *data, @@ -83,6 +88,7 @@ const NX_CRYPTO_METHOD *method_ptr; #if (NX_SECURE_TLS_TLS_1_3_ENABLED) UINT hash_length; +USHORT hello_retry_process = 0; #endif #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -122,10 +128,23 @@ UINT hash_length; NX_NULL, NX_NULL); + /* See if we have recieved or are sending a hello retry message - we need to process the hash differently. */ +#ifndef NX_SECURE_TLS_SERVER_DISABLED + if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) + { + hello_retry_process = (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY); + } +#endif +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT) + { + hello_retry_process = (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY); + } +#endif + /* Modify message buffer - replace message with hash used for HelloRetryRequest processing. */ if ((status == NX_SUCCESS) && - ((tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY)|| - (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY)) && + (hello_retry_process) && (data[0] == NX_SECURE_TLS_CLIENT_HELLO) && (length > NX_SECURE_TLS_HANDSHAKE_HEADER_SIZE)) { diff --git a/nx_secure/src/nx_secure_tls_hash_record.c b/nx_secure/src/nx_secure_tls_hash_record.c index 567cb8e4..fba0e278 100644 --- a/nx_secure/src/nx_secure_tls_hash_record.c +++ b/nx_secure/src/nx_secure_tls_hash_record.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_hash_record PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,22 +73,26 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* supported chained packet, */ /* resulting in version 6.1 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* fixed compiler warning, */ +/* resulting in version 6.1.7 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* adjusted parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -UINT _nx_secure_tls_hash_record(NX_SECURE_TLS_SESSION *tls_session, +UINT _nx_secure_tls_hash_record(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, ULONG sequence_num[NX_SECURE_TLS_SEQUENCE_NUMBER_SIZE], UCHAR *header, UINT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT length, UCHAR *record_hash, UINT *hash_length, - UCHAR *mac_secret) + UCHAR *mac_secret, VOID *metadata, ULONG metadata_size) { -UINT hash_size; -UINT status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE;; -const NX_CRYPTO_METHOD *authentication_method; -UCHAR adjusted_sequence_num[8]; -VOID *metadata; -UINT metadata_size; -VOID *handler = NX_NULL; -ULONG current_length; +UINT hash_size; +UINT status = NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE; +const NX_CRYPTO_METHOD *authentication_method; +UCHAR adjusted_sequence_num[8]; +VOID *handler = NX_NULL; +ULONG current_length; NX_PARAMETER_NOT_USED(header_length); @@ -102,20 +106,11 @@ ULONG current_length; */ - if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) - { - - /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */ - return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); - } - /* Get our authentication method from the ciphersuite. */ - authentication_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash; - metadata = tls_session -> nx_secure_hash_mac_metadata_area; - metadata_size = tls_session -> nx_secure_hash_mac_metadata_size; + authentication_method = ciphersuite -> nx_secure_tls_hash; /* Get the hash size and MAC secret for our current session. */ - hash_size = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash_size; + hash_size = ciphersuite -> nx_secure_tls_hash_size; /* Correct the endianness of our sequence number before hashing. */ adjusted_sequence_num[0] = (UCHAR)(sequence_num[1] >> 24); diff --git a/nx_secure/src/nx_secure_tls_key_material_init.c b/nx_secure/src/nx_secure_tls_key_material_init.c index 7ea0483a..8c28ceb5 100644 --- a/nx_secure/src/nx_secure_tls_key_material_init.c +++ b/nx_secure/src/nx_secure_tls_key_material_init.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_key_material_init PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -61,31 +61,16 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* cleared all key material, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_key_material_init(NX_SECURE_TLS_KEY_MATERIAL *key_material) { - /* Clear out key blocks individually - we may need to keep some key data - * around in the future for things like session re-negotiation/resumption. */ - - NX_SECURE_MEMSET(key_material -> nx_secure_tls_client_random, 0, NX_SECURE_TLS_RANDOM_SIZE); - - NX_SECURE_MEMSET(key_material -> nx_secure_tls_server_random, 0, NX_SECURE_TLS_RANDOM_SIZE); - - NX_SECURE_MEMSET(key_material -> nx_secure_tls_pre_master_secret, 0, NX_SECURE_TLS_PREMASTER_SIZE); - key_material -> nx_secure_tls_pre_master_secret_size = 0; - - NX_SECURE_MEMSET(key_material -> nx_secure_tls_master_secret, 0, NX_SECURE_TLS_MASTER_SIZE); - - NX_SECURE_MEMSET(key_material -> nx_secure_tls_key_material_data, 0, NX_SECURE_TLS_KEY_MATERIAL_SIZE); - NX_SECURE_MEMSET(key_material -> nx_secure_tls_new_key_material_data, 0, NX_SECURE_TLS_KEY_MATERIAL_SIZE); - -#if(NX_SECURE_TLS_TLS_1_3_ENABLED) - NX_SECURE_MEMSET(&key_material->nx_secure_tls_key_secrets, 0, sizeof(NX_SECURE_TLS_KEY_SECRETS)); - NX_SECURE_MEMSET(key_material->nx_secure_tls_ecc_key_data, 0, sizeof(key_material->nx_secure_tls_ecc_key_data)); - key_material->nx_secure_tls_handshake_cache_length = 0; -#endif + /* Clear out the entire key material. */ + NX_SECURE_MEMSET(key_material, 0, sizeof(NX_SECURE_TLS_KEY_MATERIAL)); return(NX_SECURE_TLS_SUCCESS); } diff --git a/nx_secure/src/nx_secure_tls_local_certificate_add.c b/nx_secure/src/nx_secure_tls_local_certificate_add.c index 96e73769..f5b4a9ef 100644 --- a/nx_secure/src/nx_secure_tls_local_certificate_add.c +++ b/nx_secure/src/nx_secure_tls_local_certificate_add.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_local_certificate_add PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_local_certificate_add(NX_SECURE_TLS_SESSION *tls_session, @@ -99,6 +102,12 @@ UINT status; /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERT_ID_DUPLICATE) + { + return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + } + return(status); } diff --git a/nx_secure/src/nx_secure_tls_local_certificate_find.c b/nx_secure/src/nx_secure_tls_local_certificate_find.c index 168747d5..8d61f3c8 100644 --- a/nx_secure/src/nx_secure_tls_local_certificate_find.c +++ b/nx_secure/src/nx_secure_tls_local_certificate_find.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_local_certificate_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_local_certificate_find(NX_SECURE_TLS_SESSION *tls_session, @@ -97,6 +100,12 @@ NX_SECURE_X509_DISTINGUISHED_NAME name; /* Find the certificate using it's name. */ status = _nx_secure_x509_certificate_list_find(&list_head, &name, 0, certificate); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) + { + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + /* Return completion status. */ return(status); } diff --git a/nx_secure/src/nx_secure_tls_local_certificate_remove.c b/nx_secure/src/nx_secure_tls_local_certificate_remove.c index 528c5e5e..e622c932 100644 --- a/nx_secure/src/nx_secure_tls_local_certificate_remove.c +++ b/nx_secure/src/nx_secure_tls_local_certificate_remove.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_local_certificate_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_local_certificate_remove(NX_SECURE_TLS_SESSION *tls_session, UCHAR *common_name, @@ -91,6 +94,12 @@ NX_SECURE_X509_DISTINGUISHED_NAME name; /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) + { + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + return(status); } diff --git a/nx_secure/src/nx_secure_tls_map_error_to_alert.c b/nx_secure/src/nx_secure_tls_map_error_to_alert.c index 1cde8b2a..bf2a69a8 100644 --- a/nx_secure/src/nx_secure_tls_map_error_to_alert.c +++ b/nx_secure/src/nx_secure_tls_map_error_to_alert.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_map_error_to_alert PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -55,11 +55,7 @@ /* */ /* CALLED BY */ /* */ -/* _nx_secure_dtls_client_handshake DTLS client state machine */ -/* _nx_secure_dtls_server_handshake DTLS server state machine */ /* _nx_secure_dtls_session_receive Receive DTLS data */ -/* _nx_secure_tls_client_handshake TLS client state machine */ -/* _nx_secure_tls_server_handshake TLS server state machine */ /* _nx_secure_tls_session_receive_records */ /* Receive TLS records */ /* */ @@ -71,6 +67,13 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* updated alert message for */ +/* downgrade protection, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ VOID _nx_secure_tls_map_error_to_alert(UINT error_number, UINT *alert_number, UINT *alert_level) @@ -135,6 +138,7 @@ VOID _nx_secure_tls_map_error_to_alert(UINT error_number, UINT *alert_number, UI case NX_SECURE_X509_WRONG_SIGNATURE_METHOD: case NX_SECURE_X509_INVALID_DATE_FORMAT: case NX_SECURE_X509_ASN1_LENGTH_TOO_LONG: + case NX_SECURE_X509_CERTIFICATE_NOT_FOUND: case NX_SECURE_X509_PKCS7_PARSING_FAILED: /* Deliberate fall-through. */ *alert_number = NX_SECURE_TLS_ALERT_BAD_CERTIFICATE; *alert_level = NX_SECURE_TLS_ALERT_LEVEL_FATAL; @@ -172,6 +176,7 @@ VOID _nx_secure_tls_map_error_to_alert(UINT error_number, UINT *alert_number, UI case NX_SECURE_TLS_BAD_COMPRESSION_METHOD: /* Deliberate fall-through. */ case NX_SECURE_TLS_1_3_UNKNOWN_CIPHERSUITE: case NX_SECURE_TLS_BAD_SERVERHELLO_KEYSHARE: + case NX_SECURE_TLS_DOWNGRADE_DETECTED: *alert_number = NX_SECURE_TLS_ALERT_ILLEGAL_PARAMETER; *alert_level = NX_SECURE_TLS_ALERT_LEVEL_FATAL; break; diff --git a/nx_secure/src/nx_secure_tls_metadata_size_calculate.c b/nx_secure/src/nx_secure_tls_metadata_size_calculate.c index c55043ab..db57b14b 100644 --- a/nx_secure/src/nx_secure_tls_metadata_size_calculate.c +++ b/nx_secure/src/nx_secure_tls_metadata_size_calculate.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_metadata_size_calculate PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -65,6 +65,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comment(s), and */ +/* improved the code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_metadata_size_calculate(const NX_SECURE_TLS_CRYPTO *crypto_table, @@ -95,11 +98,6 @@ const NX_CRYPTO_METHOD *crypto_method_sha1; const NX_CRYPTO_METHOD *crypto_method_sha256; #endif - if (crypto_table == NX_NULL) - { - return(NX_PTR_ERROR); - } - #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) crypto_method_md5 = crypto_table -> nx_secure_tls_handshake_hash_md5_method; crypto_method_sha1 = crypto_table -> nx_secure_tls_handshake_hash_sha1_method; diff --git a/nx_secure/src/nx_secure_tls_newest_supported_version.c b/nx_secure/src/nx_secure_tls_newest_supported_version.c index 33e2049b..0c627d77 100644 --- a/nx_secure/src/nx_secure_tls_newest_supported_version.c +++ b/nx_secure/src/nx_secure_tls_newest_supported_version.c @@ -196,7 +196,7 @@ USHORT highest_version_not_greater_than_client_version = 0; } } - /* No versions of TLS have been enabled. Set protocol to 0 to indicate failure. */ + /* No versions of TLS have been enabled. Set protocol to 0 to indicate failure. */ if (highest_version == 0) { (*protocol_version) = 0; @@ -219,14 +219,14 @@ USHORT highest_version_not_greater_than_client_version = 0; if ((*protocol_version) < highest_version && (*protocol_version) > lowest_version) { (*protocol_version) = highest_version_not_greater_than_client_version; - } + } else { (*protocol_version) = 0; } } - session_ptr -> nx_secure_tls_negotiated_highest_protocol_version = (*protocol_version); + session_ptr -> nx_secure_tls_negotiated_highest_protocol_version = (*protocol_version); return; } diff --git a/nx_secure/src/nx_secure_tls_packet_allocate.c b/nx_secure/src/nx_secure_tls_packet_allocate.c index 18ec4ac2..abf8f286 100644 --- a/nx_secure/src/nx_secure_tls_packet_allocate.c +++ b/nx_secure/src/nx_secure_tls_packet_allocate.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_packet_allocate PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,6 +73,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* fixed the packet leak, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_packet_allocate(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET_POOL *pool_ptr, @@ -105,6 +108,7 @@ USHORT iv_size; /* Packet buffer is too small. */ nx_packet_release(*packet_ptr); + *packet_ptr = NX_NULL; return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); } @@ -120,6 +124,10 @@ USHORT iv_size; if (status != NX_SUCCESS) { + + /* Fail to get the size of the IV. */ + nx_packet_release(*packet_ptr); + *packet_ptr = NX_NULL; return(status); } diff --git a/nx_secure/src/nx_secure_tls_process_certificate_request.c b/nx_secure/src/nx_secure_tls_process_certificate_request.c index b5650647..c89c400b 100644 --- a/nx_secure/src/nx_secure_tls_process_certificate_request.c +++ b/nx_secure/src/nx_secure_tls_process_certificate_request.c @@ -33,7 +33,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_certificate_request PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_certificate_request(NX_SECURE_TLS_SESSION *tls_session, @@ -181,6 +184,11 @@ UINT extension_type; if (tls_session -> nx_secure_tls_1_3) { + if (message_length < 1 || (UINT)packet_buffer[0] + 3 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Skip certificate request context. */ length = length + 1 + packet_buffer[length]; @@ -225,7 +233,7 @@ UINT extension_type; length += 1; /* Make sure what we extracted makes sense. */ - if (cert_types_length > message_length) + if (cert_types_length + 1 > message_length) { return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } @@ -259,6 +267,11 @@ UINT extension_type; if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) #endif /* NX_SECURE_ENABLE_DTLS */ { + if (length + 2 > message_length) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* Extract the count of algorithms from the incoming data. */ sign_algs_length = (UINT)((packet_buffer[length] << 8) + packet_buffer[length + 1]); length = length + 2; diff --git a/nx_secure/src/nx_secure_tls_process_certificate_verify.c b/nx_secure/src/nx_secure_tls_process_certificate_verify.c index 41ab0e36..3e5e4e49 100644 --- a/nx_secure/src/nx_secure_tls_process_certificate_verify.c +++ b/nx_secure/src/nx_secure_tls_process_certificate_verify.c @@ -39,7 +39,7 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09 /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_certificate_verify PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -85,6 +85,18 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09 /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unnecessary code, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_certificate_verify(NX_SECURE_TLS_SESSION *tls_session, @@ -95,7 +107,7 @@ UINT data_size = 0; USHORT signature_algorithm; UINT signature_length = 0; UINT i; -INT compare_value; +INT compare_value = 1; /* Initialized to 1 to ensure that we fail if anything goes wrong with the comparison. */ UCHAR *received_signature = NX_NULL; UCHAR *working_ptr; NX_SECURE_X509_CRYPTO *crypto_methods; @@ -156,7 +168,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, &client_certificate); - if (status || client_certificate == NX_NULL) + if (status) { /* No certificate found, error! */ return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); @@ -197,7 +209,9 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; status = _nx_secure_x509_find_certificate_methods(client_certificate, signature_algorithm, &crypto_methods); if (status != NX_SUCCESS) { - return(status); + + /* Translate some X.509 return values into TLS return values. */ + return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM); } #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -211,7 +225,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; - The content to be signed */ - UCHAR *transcript_hash = tls_session->nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE]; + UCHAR *transcript_hash = tls_session -> nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE]; /* Set octet padding bytes. */ NX_SECURE_MEMSET(&handshake_hash[0], 0x20, 64); @@ -346,9 +360,9 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; /* Generate a hash of all sent and received handshake messages to this point (not a Finished hash!). */ /* Copy over the handshake hash state into a local structure to do the intermediate calculation. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, /* lgtm[cpp/banned-api-usage-required-any] */ + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ /* Use SHA-256 for now... */ hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method; @@ -368,14 +382,16 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size, NX_NULL, NX_NULL); + } - if (status != NX_CRYPTO_SUCCESS) - { - /* Something failed in the hash calculation. */ - return(status); - } + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + /* Something failed in the hash calculation. */ + return(status); } - } #endif @@ -393,15 +409,11 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; /* Signature size is the size of SHA-1 (20) + MD5 (16). */ signature_length = 36; - /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in - first, then MD5. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ + /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ /* Finalize the handshake message hashes that we started at the beginning of the handshake. */ hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; @@ -422,14 +434,23 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size, NX_NULL, NX_NULL); + } - if (status != NX_CRYPTO_SUCCESS) - { - /* Something failed in the hash calculation. */ - return(status); - } + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + + /* Something failed in the hash calculation. */ + return(status); } + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ + hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method; if (hash_method -> nx_crypto_operation != NX_NULL) { @@ -448,14 +469,20 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - /* Something failed in the hash calculation. */ + + } + + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + + /* Something failed in the hash calculation. */ #ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash)); -#endif /* NX_SECURE_KEY_CLEAR */ - return(status); - } + NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash)); +#endif /* NX_SECURE_KEY_CLEAR */ + return(status); } } #endif @@ -481,11 +508,11 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; /* Use RSA? */ if (client_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA) { -#if (NX_SECURE_TLS_TLS_1_2_ENABLED) +#if (NX_SECURE_TLS_TLS_1_2_ENABLED || NX_SECURE_TLS_TLS_1_3_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) -#else +#elif (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) #endif /* NX_SECURE_ENABLE_DTLS */ { @@ -635,14 +662,11 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; /* Check the received handshake hash against what we generated above. */ - /* Assure that we fail if anything goes wrong with the comparison. */ - compare_value = 1; - -#if (NX_SECURE_TLS_TLS_1_2_ENABLED) +#if (NX_SECURE_TLS_TLS_1_2_ENABLED || NX_SECURE_TLS_TLS_1_3_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) -#else +#elif (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) #endif /* NX_SECURE_ENABLE_DTLS */ { @@ -683,11 +707,11 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; { /* Verify the ECDSA signature. */ -#if (NX_SECURE_TLS_TLS_1_2_ENABLED) +#if (NX_SECURE_TLS_TLS_1_2_ENABLED || NX_SECURE_TLS_TLS_1_3_ENABLED) #ifdef NX_SECURE_ENABLE_DTLS if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) -#else +#elif (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) #endif /* NX_SECURE_ENABLE_DTLS */ { @@ -747,24 +771,16 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; ec_pubkey = &client_certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the remote certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); + status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); -#ifdef NX_SECURE_KEY_CLEAR - if(status != NX_SUCCESS || curve_method_cert == NX_NULL) + if (status != NX_SUCCESS) { +#ifdef NX_SECURE_KEY_CLEAR /* Clear secrets on errors. */ NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash)); NX_SECURE_MEMSET(_nx_secure_decrypted_signature, 0, sizeof(_nx_secure_decrypted_signature)); - } #endif /* NX_SECURE_KEY_CLEAR */ - if (status != NX_SUCCESS) - { - return(status); - } - - if (curve_method_cert == NX_NULL) - { /* The remote certificate is using an unsupported curve. */ return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); } @@ -845,7 +861,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash)); NX_SECURE_MEMSET(_nx_secure_decrypted_signature, 0, sizeof(_nx_secure_decrypted_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ +#endif /* NX_SECURE_KEY_CLEAR */ return(status); } } @@ -854,7 +870,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ else { - /* Unknown or unsupported public-key operation. + /* Unknown or unsupported public-key operation. No secrets to clear. */ return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); } diff --git a/nx_secure/src/nx_secure_tls_process_client_key_exchange.c b/nx_secure/src/nx_secure_tls_process_client_key_exchange.c index 53091a40..08bbba10 100644 --- a/nx_secure/src/nx_secure_tls_process_client_key_exchange.c +++ b/nx_secure/src/nx_secure_tls_process_client_key_exchange.c @@ -24,14 +24,12 @@ #include "nx_secure_tls.h" -static UCHAR _nx_secure_client_padded_pre_master[600]; - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_client_key_exchange PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -56,15 +54,8 @@ static UCHAR _nx_secure_client_padded_pre_master[600]; /* */ /* CALLS */ /* */ -/* _nx_secure_tls_generate_premaster_secret */ -/* Generate the shared secret */ -/* used to generate keys later */ -/* _nx_secure_x509_local_device_certificate_get */ -/* Get the local certificate */ -/* for its keys */ -/* _nx_secure_tls_find_curve_method Find named curve used */ -/* [nx_crypto_init] Initialize crypto */ -/* [nx_crypto_operation] Crypto operation */ +/* [nx_secure_process_client_key_exchange] */ +/* Process ClientKeyExchange */ /* */ /* CALLED BY */ /* */ @@ -80,33 +71,25 @@ static UCHAR _nx_secure_client_padded_pre_master[600]; /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* supported hardware EC */ +/* private key, */ +/* resulting in version 6.1.7 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_client_key_exchange(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, UINT message_length, UINT id) { -USHORT length; -UINT status; -UCHAR *encrypted_pre_master_secret; -const NX_CRYPTO_METHOD *public_cipher_method; -NX_SECURE_X509_CERT *local_certificate; -UINT user_defined_key; -VOID *handler = NX_NULL; -UCHAR rand_byte; -UINT i; -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -NX_SECURE_EC_PRIVATE_KEY *ec_privkey; -NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; -NX_CRYPTO_EXTENDED_OUTPUT extended_output; -const NX_CRYPTO_METHOD *curve_method; -const NX_CRYPTO_METHOD *ecdh_method; -UCHAR *private_key; -UINT private_key_length; -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ +#ifndef NX_SECURE_TLS_SERVER_DISABLED +UINT status; -#ifndef NX_SECURE_ENABLE_PSK_CIPHERSUITES NX_PARAMETER_NOT_USED(id); -#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -115,443 +98,42 @@ UINT private_key_length; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE /* Process key material. The contents of the handshake record differ according to the ciphersuite chosen in the Client/Server Hello negotiation. */ + status = tls_session -> nx_secure_process_client_key_exchange(tls_session -> nx_secure_tls_session_ciphersuite, tls_session -> nx_secure_tls_protocol_version, + packet_buffer, message_length, &tls_session -> nx_secure_tls_received_remote_credentials, &tls_session -> nx_secure_tls_key_material, + &tls_session -> nx_secure_tls_credentials, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, + tls_session -> nx_secure_public_auth_metadata_size, + &tls_session -> nx_secure_tls_ecc); -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - /* Check for ECJ-PAKE ciphersuites and generate the pre-master-secret. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) - { - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = 32; - - public_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth; - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_KEY_EXCHANGE_PROCESS, - tls_session -> nx_secure_public_auth_handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - NX_NULL, 0, - packet_buffer, - message_length, - NX_NULL, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if (status) - { - return(status); - } - - if (public_cipher_method -> nx_crypto_cleanup) - { - status = public_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); - - if (status) - { - return(status); - } - } - } - else -#endif - { - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* Check for PSK ciphersuites and generate the pre-master-secret. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) - { - status = _nx_secure_tls_generate_premaster_secret(tls_session, id); +#else - if (status != NX_SUCCESS) - { - return(status); - } - } - else + /* Process key material. The contents of the handshake record differ according to the + ciphersuite chosen in the Client/Server Hello negotiation. */ + status = tls_session -> nx_secure_process_client_key_exchange(tls_session -> nx_secure_tls_session_ciphersuite, tls_session -> nx_secure_tls_protocol_version, + packet_buffer, message_length, &tls_session -> nx_secure_tls_received_remote_credentials, &tls_session -> nx_secure_tls_key_material, + &tls_session -> nx_secure_tls_credentials, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, + tls_session -> nx_secure_public_auth_metadata_size, + NX_NULL); #endif -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH || - tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) - { - length = packet_buffer[0]; - - if (length > message_length) - { - /* The public key length is larger than the header indicated. */ - return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); - } - - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH) - { - /* Get the local certificate. */ - if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate != NX_NULL) - { - local_certificate = tls_session -> nx_secure_tls_credentials.nx_secure_tls_active_certificate; - } - else - { - /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */ - status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - NX_NULL, &local_certificate); - if (status != NX_SUCCESS) - { - local_certificate = NX_NULL; - } - } - - if (local_certificate == NX_NULL) - { - /* No certificate found, error! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); - } - - ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key; - - /* Find out which named curve the local certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method, NX_NULL); - - if(status != NX_SUCCESS) - { - return(status); - } - - private_key = (UCHAR *)ec_privkey -> nx_secure_ec_private_key; - private_key_length = ec_privkey -> nx_secure_ec_private_key_length; - } - else - { - ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data; - - /* Find out which named curve the we are using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)ecdhe_data -> nx_secure_tls_ecdhe_named_curve, &curve_method, NX_NULL); - - if(status != NX_SUCCESS) - { - return(status); - } - - private_key = ecdhe_data -> nx_secure_tls_ecdhe_private_key; - private_key_length = ecdhe_data -> nx_secure_tls_ecdhe_private_key_length; - } - - if (curve_method == NX_NULL) - { - /* No named curve is selected. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - - ecdh_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher; - if (ecdh_method -> nx_crypto_operation == NX_NULL) - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - if (ecdh_method -> nx_crypto_init != NX_NULL) - { - status = ecdh_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdh_method, - NX_NULL, - 0, - &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, - (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - /* Import the private key to the ECDH context. */ - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler, - (NX_CRYPTO_METHOD*)ecdh_method, - private_key, private_key_length << 3, - NX_NULL, 0, NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - extended_output.nx_crypto_extended_output_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; - extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret); - extended_output.nx_crypto_extended_output_actual_size = 0; - status = ecdh_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, - (NX_CRYPTO_METHOD*)ecdh_method, NX_NULL, 0, - &packet_buffer[1], - length, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; - - if (ecdh_method -> nx_crypto_cleanup) - { - status = ecdh_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - } - else -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - { /* Certificate-based authentication. */ - /* Get pre-master-secret length. */ - length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]); - packet_buffer += 2; + return(status); - if (length > message_length) - { - /* The payload is larger than the header indicated. */ - return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); - } - - /* Pointer to the encrypted pre-master secret in our packet buffer. */ - encrypted_pre_master_secret = &packet_buffer[0]; - - - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_ciphersuite == TLS_NULL_WITH_NULL_NULL) - { - /* Special case - NULL ciphersuite. No keys are generated. */ - if (length > sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret)) - { - length = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret); - } - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret, encrypted_pre_master_secret, length); /* Use case of memcpy is verified. */ - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = length; - } - - /* Get reference to local device certificate. NX_NULL is passed for name to get default entry. */ - status = _nx_secure_x509_local_device_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - NX_NULL, &local_certificate); - - if (status) - { - /* No certificate found, error! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); - } - - /* Get the public cipher method pointer for this session. */ - public_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher; - - /* Check for user-defined key types. */ - user_defined_key = NX_FALSE; - if ((local_certificate -> nx_secure_x509_private_key_type & NX_SECURE_X509_KEY_TYPE_USER_DEFINED_MASK) != 0x0) - { - user_defined_key = NX_TRUE; - } - - /* See if we are using RSA. Separate from other methods (e.g. ECC, DH) for proper handling of padding. */ - if (public_cipher_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA && - local_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA) - { - /* Check for user-defined keys. */ - if (user_defined_key) - { - /* A user-defined key is passed directly into the crypto routine. */ - status = public_cipher_method -> nx_crypto_operation(local_certificate -> nx_secure_x509_private_key_type, - NX_NULL, - (NX_CRYPTO_METHOD*)public_cipher_method, - (UCHAR *)local_certificate -> nx_secure_x509_private_key.user_key.key_data, - (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.user_key.key_length), - encrypted_pre_master_secret, - length, - NX_NULL, - _nx_secure_client_padded_pre_master, - sizeof(_nx_secure_client_padded_pre_master), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - else - { - /* Generic RSA operation, use pre-parsed RSA key data. */ - if (public_cipher_method -> nx_crypto_init != NX_NULL) - { - /* Initialize the crypto method with public key. */ - status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, - (UCHAR *)local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, - (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), - &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - if (public_cipher_method -> nx_crypto_operation != NX_NULL) - { - - - /* Check for P and Q in the private key. If they are present, we can use them to - speed up RSA using the Chinese Remainder Theorem version of the algorithm. */ - if (local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p != NX_NULL && - local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q != NX_NULL) - { - - - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_P, - handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - NX_NULL, - 0, - (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p, - local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_p_length, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_SET_PRIME_Q, - handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - NX_NULL, - 0, - (VOID *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q, - local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_prime_q_length, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - } - - /* Decrypt the pre-master-secret using the private key provided by the user - and place the result in the session key material space in our socket. */ - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, - handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - (UCHAR *)local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent, - (NX_CRYPTO_KEY_SIZE)(local_certificate -> nx_secure_x509_private_key.rsa_private_key.nx_secure_rsa_private_exponent_length << 3), - encrypted_pre_master_secret, - length, - NX_NULL, - _nx_secure_client_padded_pre_master, - sizeof(_nx_secure_client_padded_pre_master), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - } - - if (public_cipher_method -> nx_crypto_cleanup) - { - status = public_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); - - if(status != NX_CRYPTO_SUCCESS) - { -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(status); - } - } - } - - /* Check padding - first 2 bytes should be 0x00, 0x02 for PKCS#1 padding. A 0x00 byte should immediately - precede the data. */ - if (_nx_secure_client_padded_pre_master[0] != 0x00 || - _nx_secure_client_padded_pre_master[1] != 0x02 || - _nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE - 1] != 0x00) - { - - /* Invalid padding. To avoid Bleichenbacher's attack, use random numbers to - generate premaster secret and continue the operation (which will be properly - taken care of later in _nx_secure_tls_process_finished()). - - This is described in RFC 5246, section 7.4.7.1, page 58-59. */ - - /* Generate premaster secret using random numbers. */ - for (i = 0; i < NX_SECURE_TLS_RSA_PREMASTER_SIZE; ++i) - { - - /* PKCS#1 padding must be random, but CANNOT be 0. */ - do - { - rand_byte = (UCHAR)NX_RAND(); - } while (rand_byte == 0); - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret[i] = rand_byte; - } - } - else - { +#else - /* Extract the 48 bytes of the actual pre-master secret from the data we just decrypted, stripping the padding, which - comes at the beginning of the decrypted block (the pre-master secret is the last 48 bytes. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret, - &_nx_secure_client_padded_pre_master[length - NX_SECURE_TLS_RSA_PREMASTER_SIZE], NX_SECURE_TLS_RSA_PREMASTER_SIZE); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = NX_SECURE_TLS_RSA_PREMASTER_SIZE; - } /* End RSA-specific section. */ - else - { - /* Unknown or invalid public cipher. */ - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); - } - } - } -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ + NX_PARAMETER_NOT_USED(packet_buffer); + NX_PARAMETER_NOT_USED(message_length); + NX_PARAMETER_NOT_USED(id); -#ifdef NX_SECURE_TLS_SERVER_DISABLED /* If TLS Server is disabled and we have processed a ClientKeyExchange, something is wrong... */ tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR; return(NX_SECURE_TLS_INVALID_STATE); -#else - return(NX_SUCCESS); + #endif } diff --git a/nx_secure/src/nx_secure_tls_process_clienthello.c b/nx_secure/src/nx_secure_tls_process_clienthello.c index 64124884..c677f1b7 100644 --- a/nx_secure/src/nx_secure_tls_process_clienthello.c +++ b/nx_secure/src/nx_secure_tls_process_clienthello.c @@ -36,7 +36,7 @@ static UINT _nx_secure_tls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INF /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_clienthello PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -91,6 +91,17 @@ static UINT _nx_secure_tls_check_ciphersuite(const NX_SECURE_TLS_CIPHERSUITE_INF /* fixed renegotiation bug, */ /* improved negotiation logic, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* ability to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the bug of processing */ +/* extensions, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), fixed */ +/* TLS 1.3 version negotiation,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_clienthello(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -122,6 +133,7 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3; +USHORT no_extension = NX_FALSE; #endif /* Structure of ClientHello: @@ -152,8 +164,16 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 } #endif -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION - if (tls_session -> nx_secure_tls_renegotation_enabled && tls_session -> nx_secure_tls_secure_renegotiation) +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) + /* If Client initiated renegotiation is enabled, handle the renegotiation + handshake if appropriate. Otherwise return "no renegotiation allowed" error. */ + if (tls_session -> nx_secure_tls_renegotation_enabled && tls_session -> nx_secure_tls_secure_renegotiation +#if defined(NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION) + /* If client initiated renegotiation is disabled for TLS servers, only allow + server-initiated renegotiations requested by the server itself. */ + && tls_session -> nx_secure_tls_server_renegotiation_requested +#endif + ) { tls_session -> nx_secure_tls_renegotiation_handshake = NX_TRUE; @@ -177,7 +197,11 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 return(status); } } - } + + /* We don't want any more clienthellos to come in after this - only the first one + in response to our original request. */ + tls_session -> nx_secure_tls_server_renegotiation_requested = NX_FALSE; + } else #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ { @@ -229,7 +253,7 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 tls_session -> nx_secure_tls_protocol_version = protocol_version; /* Save off the random value for key generation later. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, &packet_buffer[length], NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, &packet_buffer[length], NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ length += NX_SECURE_TLS_RANDOM_SIZE; /* Extract the session ID if there is one. */ @@ -245,7 +269,7 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 tls_session -> nx_secure_tls_session_id_length = session_id_length; if (session_id_length > 0) { - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[length], session_id_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[length], session_id_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ length += session_id_length; } @@ -338,9 +362,46 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 } } } + else + { + num_extensions = 0; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + no_extension = NX_TRUE; +#endif + } + } + else + { + num_extensions = 0; +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + no_extension = NX_TRUE; +#endif } -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + if ((tls_session -> nx_secure_tls_1_3) && (no_extension == NX_TRUE)) + { + + /* Negotiate a version of TLS prior to TLS 1.3. */ + if (tls_session -> nx_secure_tls_protocol_version_override == 0) + { + tls_session -> nx_secure_tls_1_3 = NX_FALSE; +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) + tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE; +#endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ + + return(NX_SUCCESS); + } + else + { + + /* Protocol version is overridden to TLS 1.3. */ + return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION); + } + } +#endif + +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) if ((tls_session -> nx_secure_tls_renegotiation_handshake) && (!tls_session -> nx_secure_tls_secure_renegotiation_verified)) { @@ -443,7 +504,7 @@ USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3 } } -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) if (cipher_entry == TLS_EMPTY_RENEGOTIATION_INFO_SCSV) { if (tls_session -> nx_secure_tls_renegotiation_handshake) diff --git a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c index 1d3468de..91922c58 100644 --- a/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c +++ b/nx_secure/src/nx_secure_tls_process_clienthello_extensions.c @@ -24,14 +24,14 @@ #include "nx_secure_tls.h" -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) static UINT _nx_secure_tls_proc_clienthello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, UINT extension_length); #endif -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) static UINT _nx_secure_tls_proc_clienthello_keyshare_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, USHORT extension_length); @@ -42,6 +42,7 @@ static UINT _nx_secure_tls_proc_clienthello_supported_versions_extension(NX_SECU static VOID _nx_secure_tls_proc_clienthello_signature_algorithms_extension(NX_SECURE_TLS_SESSION *tls_session, const UCHAR *packet_buffer, USHORT extension_length); + #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSION *tls_session, const UCHAR *packet_buffer, USHORT extension_length, const UCHAR *client_hello_buffer, UINT client_hello_length); @@ -54,7 +55,7 @@ static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSI /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_clienthello_extensions PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -100,6 +101,10 @@ static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSI /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* ability to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_clienthello_extensions(NX_SECURE_TLS_SESSION *tls_session, @@ -112,11 +117,11 @@ UINT offset; UINT max_extensions; USHORT extension_id; UINT extension_length; -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; #endif -#ifdef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) || defined(NX_SECURE_TLS_DISABLE_CLIENT_INITIATED_RENEGOTIATION) NX_PARAMETER_NOT_USED(tls_session); #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ @@ -152,12 +157,12 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; if((offset + extension_length) > message_length) { return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); - } + } /* Parse the extension. */ switch (extension_id) { -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) case NX_SECURE_TLS_EXTENSION_SECURE_RENEGOTIATION: status = _nx_secure_tls_proc_clienthello_sec_reneg_extension(tls_session, &packet_buffer[offset], @@ -170,9 +175,9 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; break; #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) case NX_SECURE_TLS_EXTENSION_KEY_SHARE: - if(tls_session->nx_secure_tls_1_3) + if(tls_session -> nx_secure_tls_1_3) { /* If TLS 1.3, process the key share extension. */ status = _nx_secure_tls_proc_clienthello_keyshare_extension(tls_session, @@ -187,7 +192,7 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; /* TLS 1.2 and earlier: ignore extension. */ break; case NX_SECURE_TLS_EXTENSION_SUPPORTED_VERSIONS: - if(tls_session->nx_secure_tls_1_3) + if(tls_session -> nx_secure_tls_1_3) { /* Process the TLS 1.3 supported_versions extension. */ @@ -206,7 +211,7 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; break; #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES case NX_SECURE_TLS_EXTENSION_PRE_SHARED_KEY: - if(tls_session->nx_secure_tls_1_3) + if(tls_session -> nx_secure_tls_1_3) { /* Process the TLS 1.3 PSK extension. */ @@ -252,15 +257,15 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; offset += extension_length; } -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if((tls_session->nx_secure_tls_1_3) && (supported_version != NX_SECURE_TLS_VERSION_TLS_1_3)) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) + if((tls_session -> nx_secure_tls_1_3) && (supported_version != NX_SECURE_TLS_VERSION_TLS_1_3)) { /* Negotiate a version of TLS prior to TLS 1.3. */ if (tls_session -> nx_secure_tls_protocol_version_override == 0) { tls_session -> nx_secure_tls_1_3 = NX_FALSE; -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE; #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ tls_session -> nx_secure_tls_protocol_version = supported_version; @@ -284,7 +289,7 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_proc_clienthello_sec_reneg_extension PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -322,9 +327,13 @@ USHORT supported_version = tls_session -> nx_secure_tls_protocol_version; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* ability to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) static UINT _nx_secure_tls_proc_clienthello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, UINT extension_length) @@ -436,7 +445,7 @@ INT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_proc_clienthello_sec_sa_extension PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -478,6 +487,14 @@ INT compare_value; /* 09-30-2020 Timothy Stapko Modified comment(s), added */ /* curve priority logic, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE @@ -497,7 +514,7 @@ USHORT groups_len; const NX_CRYPTO_METHOD *curve_method; UINT curve_priority; UINT new_curve_priority = 0; -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) NX_SECURE_TLS_ECC *ecc_info; UINT signature_algorithm_exist = NX_FALSE; #endif @@ -517,7 +534,7 @@ UCHAR expected_signature = 0; if (cert_curve) { - status = _nx_secure_tls_find_curve_method(tls_session, cert_curve, &curve_method, NX_NULL); + status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, cert_curve, &curve_method, NX_NULL); if (status == NX_SUCCESS && curve_method != NX_NULL) { *cert_curve_supported = NX_TRUE; @@ -530,7 +547,7 @@ UCHAR expected_signature = 0; { expected_signature = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; } - else if (cert->nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA) + else if (cert -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_RSA) { expected_signature = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA; } @@ -560,7 +577,7 @@ UCHAR expected_signature = 0; { group = (USHORT)((groups[j] << 8) + groups[j + 1]); - status = _nx_secure_tls_find_curve_method(tls_session, group, &curve_method, &new_curve_priority); + status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, group, &curve_method, &new_curve_priority); if ((status == NX_CRYTPO_MISSING_ECC_CURVE) || (new_curve_priority > curve_priority)) { @@ -576,7 +593,7 @@ UCHAR expected_signature = 0; *selected_curve = group; curve_priority = new_curve_priority; -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) if (tls_session -> nx_secure_tls_1_3 && (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY)) { @@ -588,7 +605,7 @@ UCHAR expected_signature = 0; for (k = 0; k < ecc_info -> nx_secure_tls_ecc_supported_groups_count; k++) { /* Find the matching group in the keys we generated and saved. */ - if(group == tls_session->nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[k].nx_secure_tls_ecdhe_named_curve) + if(group == tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[k].nx_secure_tls_ecdhe_named_curve) { /* Store selected ECDHE key data index. */ @@ -614,7 +631,7 @@ UCHAR expected_signature = 0; case NX_SECURE_TLS_EXTENSION_SIGNATURE_ALGORITHMS: /* This extension is not meaningful for TLS versions prior to 1.2. */ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) if (tls_session -> nx_secure_tls_1_3) { _nx_secure_tls_proc_clienthello_signature_algorithms_extension(tls_session, @@ -622,7 +639,7 @@ UCHAR expected_signature = 0; exts[i].nx_secure_tls_extension_data_length); signature_algorithm_exist = NX_TRUE; } - else + else #endif #if (NX_SECURE_TLS_TLS_1_2_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) @@ -676,9 +693,9 @@ UCHAR expected_signature = 0; } } -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) - /* RFC8446 4.2.3: If a server is authenticating via a certificate and - the client has not sent a "signature_algorithms" extension, +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) + /* RFC8446 4.2.3: If a server is authenticating via a certificate and + the client has not sent a "signature_algorithms" extension, then the server MUST abort the handshake with a "missing_extension" alert. */ if ((cert != NX_NULL) && (tls_session -> nx_secure_tls_1_3)) { @@ -704,7 +721,7 @@ UCHAR expected_signature = 0; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_proc_clienthello_keyshare_extension PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -739,9 +756,20 @@ UCHAR expected_signature = 0; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), removed */ +/* public key format checking, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) extern NX_CRYPTO_METHOD crypto_method_ecdhe; @@ -755,9 +783,8 @@ USHORT offset; USHORT key_share_length; USHORT key_group; USHORT key_length; -UCHAR legacy_form; NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_key_data; -UCHAR *pubkey; +UCHAR *pubkey = NX_NULL; UCHAR *private_key; UINT private_key_length; NX_CRYPTO_EXTENDED_OUTPUT extended_output; @@ -799,12 +826,12 @@ NX_SECURE_TLS_ECC *ecc_info; /* Get the key share length. */ key_share_length = (USHORT)((packet_buffer[offset] << 8) + packet_buffer[offset + 1]); offset = (USHORT)(offset + 2); - + if(offset + key_share_length > extension_length) { return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } - + /* Loop through the list of keys looking for a supported group. */ while(offset < extension_length && ecc_key_data == NX_NULL) { @@ -833,10 +860,10 @@ NX_SECURE_TLS_ECC *ecc_info; for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++) { /* Find the matching group in the keys we generated and saved. */ - if(key_group == tls_session->nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve) + if(key_group == tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve) { /* Got a matching key/curve combo, get a pointer to the selected key data. */ - ecc_key_data = &tls_session->nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i]; + ecc_key_data = &tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i]; /* Extract the remote public key from our packet. */ pubkey = &packet_buffer[offset]; @@ -859,18 +886,8 @@ NX_SECURE_TLS_ECC *ecc_info; return(NX_SUCCESS); } - /* Extract the legacy form value. NOTE: the form must be included in the ECC calculations below - so don't advance the offset! */ - legacy_form = pubkey[0]; - - if(legacy_form != 0x4) - { - /* In TLS 1.3, the only valid form is 0x4. */ - return(NX_SECURE_TLS_BAD_CLIENTHELLO_KEYSHARE); - } - /* Get the curve method to initialize the remote public key data. */ - _nx_secure_tls_find_curve_method(tls_session, key_group, &curve_method, NX_NULL); + _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, key_group, &curve_method, NX_NULL); if (curve_method == NX_NULL) { @@ -915,8 +932,8 @@ NX_SECURE_TLS_ECC *ecc_info; } /* Import the private key to the ECDH context. */ - private_key = &ecc_key_data->nx_secure_tls_ecdhe_private_key[0]; - private_key_length = ecc_key_data->nx_secure_tls_ecdhe_private_key_length; + private_key = &ecc_key_data -> nx_secure_tls_ecdhe_private_key[0]; + private_key_length = ecc_key_data -> nx_secure_tls_ecdhe_private_key_length; status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_KEY_PAIR_IMPORT, handler, (NX_CRYPTO_METHOD*)ecdhe_method, @@ -1063,7 +1080,7 @@ ULONG offset; /* */ /* _nx_secure_tls_proc_clienthello_signature_algorithms_extension */ /* PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1099,6 +1116,11 @@ ULONG offset; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ static VOID _nx_secure_tls_proc_clienthello_signature_algorithms_extension(NX_SECURE_TLS_SESSION *tls_session, @@ -1200,7 +1222,7 @@ NX_SECURE_X509_CERT *local_certificate = NX_NULL; tls_session -> nx_secure_tls_signature_algorithm = sign_alg; } -#endif +#endif /* NX_SECURE_TLS_TLS_1_3_ENABLED */ /**************************************************************************/ /* */ @@ -1289,7 +1311,7 @@ VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_clienthello_psk_extension PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1323,6 +1345,9 @@ VOID _nx_secure_tls_get_signature_algorithm_id(UINT signature_algorithm, USHORT /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) @@ -1330,7 +1355,7 @@ static UINT _nx_secure_tls_process_clienthello_psk_extension(NX_SECURE_TLS_SESSI USHORT extension_length, const UCHAR *client_hello_buffer, UINT client_hello_length) { UINT list_length; -UCHAR *psk_data; +UCHAR *psk_data = NX_NULL; UINT psk_length; UCHAR binder_len; UINT psk_index; @@ -1421,7 +1446,7 @@ NX_SECURE_TLS_PSK_STORE *psk_store; } /* Get our PSK store for easy access. */ - psk_store = tls_session->nx_secure_tls_credentials.nx_secure_tls_psk_store; + psk_store = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store; binder_total = 0; psk_index = 0; @@ -1451,7 +1476,7 @@ NX_SECURE_TLS_PSK_STORE *psk_store; age = (UINT)((packet_buffer[offset] << 24) + (packet_buffer[offset + 1] << 16) + (packet_buffer[offset + 2] << 8) + packet_buffer[offset + 3]); offset += 4; - + /* Only support external PSKs (no session resumption). */ if(age != 0) { @@ -1526,7 +1551,7 @@ NX_SECURE_TLS_PSK_STORE *psk_store; { return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); } - + /* Subtract the binder length and field from the total. */ binder_total--; binder_total -= binder_len; @@ -1562,9 +1587,9 @@ NX_SECURE_TLS_PSK_STORE *psk_store; { /* Save the handshake hash state. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ } /* Hash the ClientHello, adding the TLS record header. */ @@ -1576,17 +1601,31 @@ NX_SECURE_TLS_PSK_STORE *psk_store; /* Save the transcript hash for the ClientHello, which is used in generating the PSK binders. */ status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_FALSE); - if(status != NX_SUCCESS) + if (status != NX_SUCCESS) { + + if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size) + { + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + } + return(status); } /* Restore the original metadata(ClientHello1 and HelloRetryRequest) from scratch buffer. */ if (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size) { - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); } /* Generate the binder for our selected PSK. */ @@ -1609,8 +1648,8 @@ NX_SECURE_TLS_PSK_STORE *psk_store; } /* Make sure the Client PSK is initialized for later key generation. */ - NX_SECURE_MEMCPY(tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data, psk_data, psk_length); /* Use case of memcpy is verified. */ - tls_session->nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size = psk_length; + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data, psk_data, psk_length); /* Use case of memcpy is verified. */ + tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_data_size = psk_length; return(NX_SUCCESS); } diff --git a/nx_secure/src/nx_secure_tls_process_finished.c b/nx_secure/src/nx_secure_tls_process_finished.c index 9e896255..751bb6ca 100644 --- a/nx_secure/src/nx_secure_tls_process_finished.c +++ b/nx_secure/src/nx_secure_tls_process_finished.c @@ -157,7 +157,7 @@ UINT is_server; #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION /* If we are doing secure renegotiation as per RFC 5746, we need to save off the generated verify data now. For TLS 1.0-1.2 this is 12 bytes. If SSLv3 is ever used, it will be 36 bytes. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_remote_verify_data, generated_hash, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_remote_verify_data, generated_hash, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ /* The finished verify data is always 12 bytes (*except for SSLv3) - compare to see if the Finished hash matches the recevied hash. */ diff --git a/nx_secure/src/nx_secure_tls_process_handshake_header.c b/nx_secure/src/nx_secure_tls_process_handshake_header.c index b28a398e..35eea643 100644 --- a/nx_secure/src/nx_secure_tls_process_handshake_header.c +++ b/nx_secure/src/nx_secure_tls_process_handshake_header.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_handshake_header PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -46,7 +46,8 @@ /* */ /* packet_buffer Pointer to incoming packet */ /* message_type Return message type value */ -/* header_size Return size of header */ +/* header_size Input size of packet buffer */ +/* Return size of header */ /* message_length Return length of message */ /* */ /* OUTPUT */ @@ -69,12 +70,25 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unused code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *message_type, - USHORT *header_size, UINT *message_length) + UINT *header_size, UINT *message_length) { + /* Check buffer length. */ + if (*header_size < 4) + { + return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); + } + /* The message being passed in to this function should already be stripped of the TLS header so the first byte in the packet/record is our handshake message type. */ *message_type = packet_buffer[0]; @@ -82,7 +96,6 @@ UINT _nx_secure_tls_process_handshake_header(UCHAR *packet_buffer, USHORT *messa /* Get the length of the TLS data. */ *message_length = (UINT)((packet_buffer[0] << 16) + (packet_buffer[1] << 8) + packet_buffer[2]); - packet_buffer += 3; /* We have extracted 4 bytes of the header. */ *header_size = 4; diff --git a/nx_secure/src/nx_secure_tls_process_record.c b/nx_secure/src/nx_secure_tls_process_record.c index 113819d0..60a440d2 100644 --- a/nx_secure/src/nx_secure_tls_process_record.c +++ b/nx_secure/src/nx_secure_tls_process_record.c @@ -31,7 +31,7 @@ static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr); /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_record PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -84,6 +84,24 @@ static VOID _nx_secure_tls_packet_trim(NX_PACKET *packet_ptr); /* supported chained packet, */ /* fixed compiler warnings, */ /* resulting in version 6.1 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), checked */ +/* TLS state before processing,*/ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* TLS 1.3 compile issue, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unnecessary code, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* checked seq number overflow,*/ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *packet_ptr, @@ -126,6 +144,18 @@ NX_PACKET *decrypted_packet; status = NX_CONTINUE; *bytes_processed = 0; + /* Make sure the TLS socket is not closed. */ + if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_NONE) + { + + /* Session already closed. Release the packet. */ + if (packet_ptr != NX_NULL) + { + nx_packet_release(packet_ptr); + } + return(NX_SECURE_TLS_INVALID_STATE); + } + /* Process the packet. */ if (packet_ptr != NX_NULL) { @@ -153,6 +183,15 @@ NX_PACKET *decrypted_packet; } } + /* Reset nx_secure_tls_packet_buffer_bytes_copied if there is no fragmented message to be processed. */ + if (tls_session->nx_secure_tls_handshake_record_fragment_state == NX_SECURE_TLS_HANDSHAKE_NO_FRAGMENT) + { + tls_session->nx_secure_tls_packet_buffer_bytes_copied = 0; + } + + /* Get packet from record queue. */ + packet_ptr = tls_session -> nx_secure_record_queue_header; + /* Process multiple records per packet. */ while (status == NX_CONTINUE) { @@ -165,8 +204,14 @@ NX_PACKET *decrypted_packet; } decrypted_packet = NX_NULL; - /* Get packet from record queue. */ - packet_ptr = tls_session -> nx_secure_record_queue_header; + /* Retrieve the saved record offset when more TCP packet is received for this one record. */ + if (tls_session -> nx_secure_tls_record_offset) + { + record_offset = tls_session -> nx_secure_tls_record_offset; + tls_session -> nx_secure_tls_record_offset = 0; + *bytes_processed = tls_session -> nx_secure_tls_bytes_processed; + tls_session -> nx_secure_tls_bytes_processed = 0; + } /* Process the TLS record header, which will set the state. */ status = _nx_secure_tls_process_header(tls_session, packet_ptr, record_offset, &message_type, &message_length, header_data, &header_length); @@ -189,12 +234,15 @@ NX_PACKET *decrypted_packet; if ((header_length + record_offset + message_length) > packet_ptr -> nx_packet_length) { - /* Wait more TCP packets for this one record. */ + /* Wait more TCP packets for this one record, save record_offset and bytes_processed for next record processing. */ + tls_session -> nx_secure_tls_record_offset = record_offset; + tls_session -> nx_secure_tls_bytes_processed = *bytes_processed; return(NX_CONTINUE); } /* Update the number of bytes we processed. */ *bytes_processed += (ULONG)header_length + message_length; + tls_session -> nx_secure_tls_bytes_processed = *bytes_processed; record_offset += (ULONG)header_length; record_offset_next = record_offset + message_length; @@ -280,6 +328,14 @@ NX_PACKET *decrypted_packet; { /* Check for overflow of the 32-bit unsigned number. */ tls_session -> nx_secure_tls_remote_sequence_number[1]++; + + if (tls_session -> nx_secure_tls_remote_sequence_number[1] == 0) + { + + /* Check for overflow of the 64-bit unsigned number. As it should not reach here + in practical, we return a general error to prevent overflow theoretically. */ + return(NX_NOT_SUCCESSFUL); + } } tls_session -> nx_secure_tls_remote_sequence_number[0]++; } @@ -338,7 +394,7 @@ NX_PACKET *decrypted_packet; /* For message other than application data, extract to packet buffer to make sure all data are in contiguous memory. */ /* Check available area of buffer. */ packet_data = tls_session -> nx_secure_tls_packet_buffer; - if (message_length > tls_session -> nx_secure_tls_packet_buffer_size) + if (tls_session->nx_secure_tls_packet_buffer_bytes_copied + message_length > tls_session -> nx_secure_tls_packet_buffer_size) { return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); } @@ -346,20 +402,46 @@ NX_PACKET *decrypted_packet; if (decrypted_packet == NX_NULL) { status = nx_packet_data_extract_offset(packet_ptr, record_offset, - tls_session -> nx_secure_tls_packet_buffer, + tls_session -> nx_secure_tls_packet_buffer + tls_session->nx_secure_tls_packet_buffer_bytes_copied, message_length, &bytes_copied); } else { status = nx_packet_data_extract_offset(decrypted_packet, 0, - tls_session -> nx_secure_tls_packet_buffer, + tls_session -> nx_secure_tls_packet_buffer + tls_session->nx_secure_tls_packet_buffer_bytes_copied, message_length, &bytes_copied); } - if (status || (bytes_copied != message_length)) + if (status) { return(NX_SECURE_TLS_INVALID_PACKET); } + + tls_session -> nx_secure_tls_packet_buffer_bytes_copied += bytes_copied; + + /* fragment is assembled, or continue to process another message in the same record, or need to read a new TCP packet. */ + if (tls_session->nx_secure_tls_handshake_record_fragment_state == NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT) + { + + if (tls_session -> nx_secure_tls_packet_buffer_bytes_copied > tls_session->nx_secure_tls_handshake_record_expected_length) + { + return(NX_SECURE_TLS_INVALID_PACKET); + } + /* All fragments are received and copied to tls_session -> nx_secure_tls_packet_buffer. */ + else if (tls_session -> nx_secure_tls_packet_buffer_bytes_copied == tls_session->nx_secure_tls_handshake_record_expected_length) + { + tls_session->nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_NO_FRAGMENT; + message_length = tls_session->nx_secure_tls_handshake_record_expected_length; + tls_session->nx_secure_tls_handshake_record_expected_length = 0; + } + else + { + /* process another message in the same record. */ + record_offset += message_length; + status = NX_CONTINUE; + continue; + } + } } switch (message_type) @@ -371,6 +453,13 @@ NX_PACKET *decrypted_packet; break; case NX_SECURE_TLS_ALERT: + + if (message_length < 2) + { + status = NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH; + break; + } + /* We have received an alert. Check what the alert was and take appropriate action. */ /* The alert level is the first octet in the alert. The alert number is the second. */ if(packet_data[0] == NX_SECURE_TLS_ALERT_LEVEL_FATAL) @@ -386,7 +475,7 @@ NX_PACKET *decrypted_packet; status = NX_SECURE_TLS_ALERT_RECEIVED; break; case NX_SECURE_TLS_HANDSHAKE: -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_CLIENT_DISABLED) /* TLS 1.3 can send post-handshake messages with TLS HANDSHAKE record type. Process those separately. */ if(tls_session->nx_secure_tls_1_3 && tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED) { @@ -449,8 +538,31 @@ NX_PACKET *decrypted_packet; { status = _nx_secure_tls_client_handshake(tls_session, packet_data, message_length, wait_option); } + } + #endif + + if (status == NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED) + { + /* Update record_offset.*/ + record_offset = record_offset_next; + + /* Check if reaching the end of this TCP packet. */ + if (record_offset == packet_ptr -> nx_packet_length) + { + /* Wait more TCP packets for this one record, save record_offset and bytes_processed for next record processing. */ + tls_session -> nx_secure_tls_record_offset = record_offset; + tls_session -> nx_secure_tls_bytes_processed = *bytes_processed; + return(NX_CONTINUE); + } + else + { + /* Did not reach the end, continue to process this packet. */ + status = NX_CONTINUE; + } + } + break; case NX_SECURE_TLS_APPLICATION_DATA: /* The remote host is sending application data records now. Pass decrypted data back diff --git a/nx_secure/src/nx_secure_tls_process_remote_certificate.c b/nx_secure/src/nx_secure_tls_process_remote_certificate.c index 929a3b6a..32d29886 100644 --- a/nx_secure/src/nx_secure_tls_process_remote_certificate.c +++ b/nx_secure/src/nx_secure_tls_process_remote_certificate.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_remote_certificate PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -81,6 +81,12 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Timothy Stapko Modified comment(s), */ +/* removed unnecessary code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_remote_certificate(NX_SECURE_TLS_SESSION *tls_session, @@ -224,7 +230,7 @@ ULONG cert_buf_size; /* Copy the certificate from the packet buffer into our allocated certificate space. */ certificate -> nx_secure_x509_certificate_raw_data_length = cert_length; - NX_SECURE_MEMCPY(certificate -> nx_secure_x509_certificate_raw_data, &packet_buffer[length], cert_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(certificate -> nx_secure_x509_certificate_raw_data, &packet_buffer[length], cert_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } length += cert_length; @@ -240,6 +246,13 @@ ULONG cert_buf_size; /* Make sure we parsed a valid certificate. */ if (status != NX_SUCCESS) { + + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER) + { + return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + } + return(status); } @@ -278,6 +291,13 @@ ULONG cert_buf_size; /* Make sure we parsed a valid certificate. */ if (status != NX_SUCCESS) { + + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERT_ID_DUPLICATE) + { + return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + } + return(status); } @@ -298,11 +318,8 @@ ULONG cert_buf_size; /* ======================== Save off the endpoint certificate for later use. =============================*/ /* Get the endpoint from the certificates we just parsed. */ status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - &certificate); - if(status != NX_SUCCESS) - { - return(status); - } + &certificate); + NX_ASSERT(status == NX_SUCCESS); /* If the endpoint certificate was NOT allocated by the user application, we need to make a copy and save it for later use. */ @@ -334,13 +351,6 @@ ULONG cert_buf_size; cert_buffer = &tls_session -> nx_secure_tls_packet_buffer[data_length]; cert_buf_size = tls_session -> nx_secure_tls_packet_buffer_size - data_length; - if (cert_buf_size < sizeof(NX_SECURE_X509_CERT)) - { - - /* Not enough space to allocate the X.509 structure. */ - return(NX_SECURE_TLS_INSUFFICIENT_CERT_SPACE); - } - /* Get space for the parsing structure. */ cert_buf_size -= sizeof(NX_SECURE_X509_CERT); certificate = (NX_SECURE_X509_CERT*)(&cert_buffer[cert_buf_size]); @@ -366,35 +376,26 @@ ULONG cert_buf_size; /* Copy the certificate data to the end of the certificate buffer or use an allocated certificate. */ certificate -> nx_secure_x509_certificate_raw_data_length = endpoint_length; - NX_SECURE_MEMCPY(certificate->nx_secure_x509_certificate_raw_data, endpoint_raw_ptr, endpoint_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(certificate->nx_secure_x509_certificate_raw_data, endpoint_raw_ptr, endpoint_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); /* Re-parse the certificate using the original data. */ status = _nx_secure_x509_certificate_parse(certificate -> nx_secure_x509_certificate_raw_data, endpoint_length, &bytes_processed, certificate); + NX_ASSERT(status == NX_SUCCESS); /* Get the protection. */ tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - /* Make sure we parsed a valid certificate. */ - if (status != NX_SUCCESS) - { - return(status); - } /* Re-add the remote endpoint certificate for later use. */ status = _nx_secure_x509_certificate_list_add(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store.nx_secure_x509_remote_certificates, - certificate, NX_TRUE); - - if (status != NX_SUCCESS) - { - return(status); - } + certificate, NX_TRUE); + NX_ASSERT(status == NX_SUCCESS); /* Make sure the certificate has it's cipher table initialized. */ certificate -> nx_secure_x509_cipher_table = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table; - certificate -> nx_secure_x509_cipher_table_size = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table_size; + certificate -> nx_secure_x509_cipher_table_size = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_x509_cipher_table_size; } #ifdef NX_SECURE_TLS_CLIENT_DISABLED /* If TLS Client is disabled and we have processed a ServerCertificate message, something is wrong... */ diff --git a/nx_secure/src/nx_secure_tls_process_server_key_exchange.c b/nx_secure/src/nx_secure_tls_process_server_key_exchange.c index 9e5494b6..ce577bb0 100644 --- a/nx_secure/src/nx_secure_tls_process_server_key_exchange.c +++ b/nx_secure/src/nx_secure_tls_process_server_key_exchange.c @@ -24,21 +24,13 @@ #include "nx_secure_tls.h" -#ifdef NX_SECURE_ENABLE_DTLS -#include "nx_secure_dtls.h" -#endif /* NX_SECURE_ENABLE_DTLS */ - -#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_TLS_CLIENT_DISABLED) -static UCHAR hash[64]; /* We concatenate MD5 and SHA-1 hashes into this buffer, OR SHA-256, SHA-384, SHA512. */ -static UCHAR decrypted_signature[512]; -#endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) && !defined(NX_SECURE_TLS_CLIENT_DISABLED) */ /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_server_key_exchange PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -84,6 +76,15 @@ static UCHAR decrypted_signature[512]; /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unnecessary code, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), improved */ +/* buffer length verification, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_server_key_exchange(NX_SECURE_TLS_SESSION *tls_session, @@ -91,46 +92,11 @@ UINT _nx_secure_tls_process_server_key_exchange(NX_SECURE_TLS_SESSION *tls_sessi { #if !defined(NX_SECURE_TLS_CLIENT_DISABLED) - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES -USHORT length; -#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ +UINT status; #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || \ (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)) -UINT status; const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite; #endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ -#if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) -const NX_CRYPTO_METHOD *curve_method; -const NX_CRYPTO_METHOD *curve_method_cert; -const NX_CRYPTO_METHOD *ecdhe_method; -const NX_CRYPTO_METHOD *hash_method; -const NX_CRYPTO_METHOD *auth_method; -VOID *handler = NX_NULL; -UCHAR pubkey_length; -UCHAR *pubkey; -USHORT signature_length; -NX_SECURE_X509_CERT *server_certificate; -NX_SECURE_X509_CRYPTO *crypto_methods; -UINT sig_oid_length; -const UCHAR *sig_oid; -UINT decrypted_hash_length; -const UCHAR *decrypted_hash; -UINT compare_result; -NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; -NX_CRYPTO_EXTENDED_OUTPUT extended_output; -UCHAR *current_buffer; -UCHAR hash_algorithm; -UCHAR signature_algorithm; -USHORT signature_algorithm_id; -#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) -UINT i; -#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ -#endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ - - NX_PARAMETER_NOT_USED(tls_session); - NX_PARAMETER_NOT_USED(packet_buffer); - NX_PARAMETER_NOT_USED(message_length); #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || \ (defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE)) @@ -144,73 +110,6 @@ UINT i; } #endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* Check for PSK ciphersuites. */ - if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) - { - /* Get identity hint length. */ - length = (USHORT)((packet_buffer[0] << 8) + (USHORT)packet_buffer[1]); - packet_buffer += 2; - - if (length > message_length || length > NX_SECURE_TLS_MAX_PSK_ID_SIZE) - { - /* The payload is larger than the header indicated. */ - return(NX_SECURE_TLS_INCORRECT_MESSAGE_LENGTH); - } - - /* Extract the identity hint and save in the TLS Session. Then when pre-master is generated - in client_handshake, we can do the right thing... */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_credentials.nx_secure_tls_remote_psk_id, &packet_buffer[0], length); /* Use case of memcpy is verified. */ - tls_session -> nx_secure_tls_credentials.nx_secure_tls_remote_psk_id_size = length; - - return(NX_SECURE_TLS_SUCCESS); - } -#endif - -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - /* Check for ECJ-PAKE ciphersuites. */ - if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) - { - /* Make sure curve type is named_curve (3). */ - if (packet_buffer[0] != 3) - { - return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT); - } - - /* Only secp256r1 (23) is supported. */ - if (packet_buffer[1] != 0 || packet_buffer[2] != 23) - { - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - - packet_buffer += 3; - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = 32; - - status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_PROCESS, - tls_session -> nx_secure_public_auth_handler, - (NX_CRYPTO_METHOD*)ciphersuite -> nx_secure_tls_public_auth, - NX_NULL, 0, - packet_buffer, - message_length, - NX_NULL, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if (status) - { - return(status); - } - - if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup) - { - status = ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); - } - - return(status); - } -#endif #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) @@ -223,701 +122,32 @@ UINT i; tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_SERVER_KEY_EXCHANGE; - /* Make sure curve type is named_curve (3). */ - if (packet_buffer[0] != 3) - { - return(NX_SECURE_TLS_UNSUPPORTED_ECC_FORMAT); - } - - /* Find out which named curve the server is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)((packet_buffer[1] << 8) + packet_buffer[2]), &curve_method, NX_NULL); - - if(status != NX_SUCCESS) - { - return(status); - } - - if (curve_method == NX_NULL) - { - /* The remote server is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - - current_buffer = &packet_buffer[3]; - - /* Get reference to remote server certificate so we can get the public key for signature verification. */ - status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - &server_certificate); - if (status || server_certificate == NX_NULL) - { - /* No certificate found, error! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); - } - - pubkey_length = current_buffer[0]; - pubkey = ¤t_buffer[1]; - - current_buffer += pubkey_length + 1; - -#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) -#ifdef NX_SECURE_ENABLE_DTLS - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0) -#else - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) -#endif /* NX_SECURE_ENABLE_DTLS */ - { - hash_algorithm = NX_SECURE_TLS_HASH_ALGORITHM_SHA1; - if (server_certificate -> nx_secure_x509_public_algorithm == NX_SECURE_TLS_X509_TYPE_EC) - { - signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA; - } - else - { - signature_algorithm = NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA; - } - } - else -#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ - { - hash_algorithm = current_buffer[0]; - signature_algorithm = current_buffer[1]; - current_buffer += 2; - } - - /* Find out the hash algorithm used for the signature. */ - /* Map signature algorithm to internal ID. */ - _nx_secure_tls_get_signature_algorithm_id(((UINT)(hash_algorithm << 8) + signature_algorithm), - &signature_algorithm_id); - - /* Get the cypto method. */ - status = _nx_secure_x509_find_certificate_methods(server_certificate, - signature_algorithm_id, - &crypto_methods); - if (status) - { - return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM); - } - -#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) -#ifdef NX_SECURE_ENABLE_DTLS - if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)) -#else - if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) -#endif /* NX_SECURE_ENABLE_DTLS */ - { - - /* TLS 1.0 and TLS 1.1 use MD5 + SHA1 hash for RSA signatures. */ - hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; - } - else -#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ - { - hash_method = crypto_methods -> nx_secure_x509_hash_method; - } - - - /* Calculate the hash: SHA(ClientHello.random + ServerHello.random + - ServerKeyExchange.params); */ - if (hash_method -> nx_crypto_init) - { - status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - &handler, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - if (hash_method -> nx_crypto_operation != NX_NULL) - { - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - NX_NULL, - 0, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - else - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, - 32, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, - 32, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - packet_buffer, - (ULONG)(4 + pubkey_length), - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - NX_NULL, - 0, - NX_NULL, - hash, - hash_method -> nx_crypto_ICV_size_in_bits >> 3, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - if (hash_method -> nx_crypto_cleanup) - { - status = hash_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - handler = NX_NULL; - -#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) -#ifdef NX_SECURE_ENABLE_DTLS - if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0)) -#else - if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1)) -#endif /* NX_SECURE_ENABLE_DTLS */ - { - hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method;; - - /* Calculate the hash: SHA(ClientHello.random + ServerHello.random + - ServerKeyExchange.params); */ - if (hash_method -> nx_crypto_init) - { - status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - &handler, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - if (hash_method -> nx_crypto_operation != NX_NULL) - { - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_INITIALIZE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - NX_NULL, - 0, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - else - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, - 32, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, - 32, - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_UPDATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - packet_buffer, - (ULONG)(4 + pubkey_length), - NX_NULL, - NX_NULL, - 0, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - status = hash_method -> nx_crypto_operation(NX_CRYPTO_HASH_CALCULATE, - handler, - (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, - 0, - NX_NULL, - 0, - NX_NULL, - &hash[16], - hash_method -> nx_crypto_ICV_size_in_bits >> 3, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch_size, - NX_NULL, - NX_NULL); - - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - if (hash_method -> nx_crypto_cleanup) - { - status = hash_method -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch); - - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - handler = NX_NULL; - } -#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ - - signature_length = (USHORT)((current_buffer[0] << 8) + current_buffer[1]); - current_buffer += 2; - - /* Verify the signature. */ - auth_method = ciphersuite -> nx_secure_tls_public_auth; - - if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_RSA && - (auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_RSA || - auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA)) - { - /* Verify the RSA signature. */ - - if (auth_method -> nx_crypto_init != NX_NULL) - { - /* Initialize the crypto method with public key. */ - status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method, - (UCHAR *)server_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, - (NX_CRYPTO_KEY_SIZE)(server_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), - &handler, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - if (auth_method -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_RSA) - { - status = auth_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, - handler, - (NX_CRYPTO_METHOD*)auth_method, - (UCHAR *)server_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent, - (NX_CRYPTO_KEY_SIZE)(server_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), - current_buffer, - signature_length, - NX_NULL, - decrypted_signature, - sizeof(decrypted_signature), - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } + } - if (auth_method -> nx_crypto_cleanup) - { - status = auth_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - handler = NX_NULL; + status = tls_session -> nx_secure_process_server_key_exchange(tls_session -> nx_secure_tls_session_ciphersuite, tls_session -> nx_secure_tls_crypto_table, + tls_session -> nx_secure_tls_protocol_version, packet_buffer, message_length, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + &tls_session -> nx_secure_tls_handshake_hash, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, tls_session -> nx_secure_public_auth_metadata_size, + &tls_session -> nx_secure_tls_ecc); -#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) -#ifdef NX_SECURE_ENABLE_DTLS - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_0) #else - if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_0 || - tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) -#endif /* NX_SECURE_ENABLE_DTLS */ - { - if (signature_length < 39) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - - /* Block type is 0x00, 0x01 for signatures */ - if (decrypted_signature[0] != 0x0 && decrypted_signature[1] != 0x1) - { - /* Unknown block type. */ - return(NX_SECURE_TLS_PADDING_CHECK_FAILED); - } - - /* Check padding. */ - for (i = 2; i < (UINT)(signature_length - 37); ++i) - { - if (decrypted_signature[i] != (UCHAR)0xFF) - { - /* Bad padding value. */ - return(NX_SECURE_TLS_PADDING_CHECK_FAILED); - } - } - - /* Make sure we actually saw a NULL byte. */ - if (decrypted_signature[i] != 0x00) - { - return(NX_SECURE_TLS_PADDING_CHECK_FAILED); - } - - decrypted_hash = &decrypted_signature[i + 1]; - decrypted_hash_length = 36; - } - else -#endif /* NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED */ - { - /* Decode the decrypted signature. */ - status = _nx_secure_x509_pkcs7_decode(decrypted_signature, signature_length, &sig_oid, &sig_oid_length, - &decrypted_hash, &decrypted_hash_length); - if (status != NX_SUCCESS) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - - if (decrypted_hash_length != (hash_method -> nx_crypto_ICV_size_in_bits >> 3)) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - } - - /* Compare generated hash with decrypted hash. */ - compare_result = (UINT)NX_SECURE_MEMCMP(hash, decrypted_hash, decrypted_hash_length); - -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(hash, 0, sizeof(hash)); - NX_SECURE_MEMSET(decrypted_signature, 0, sizeof(decrypted_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ - - if (compare_result != 0) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - } - else if (signature_algorithm == NX_SECURE_TLS_SIGNATURE_ALGORITHM_ECDSA && - auth_method -> nx_crypto_algorithm == NX_CRYPTO_DIGITAL_SIGNATURE_ECDSA) - { - /* Verify the ECDSA signature. */ - - ec_pubkey = &server_certificate -> nx_secure_x509_public_key.ec_public_key; - - /* Find out which named curve the remote certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); - - if(status != NX_SUCCESS) - { - return(status); - } - - if (curve_method_cert == NX_NULL) - { - /* The remote certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } - - if (auth_method -> nx_crypto_init != NX_NULL) - { - status = auth_method -> nx_crypto_init((NX_CRYPTO_METHOD*)auth_method, - (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, - (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), - &handler, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - if (auth_method -> nx_crypto_operation == NX_NULL) - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - status = auth_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)auth_method, NX_NULL, 0, - (UCHAR *)curve_method_cert, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - if (packet_buffer + message_length < current_buffer + signature_length) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - - status = auth_method -> nx_crypto_operation(NX_CRYPTO_VERIFY, handler, - (NX_CRYPTO_METHOD*)auth_method, - (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, - (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), - hash, - hash_method -> nx_crypto_ICV_size_in_bits >> 3, - NX_NULL, - current_buffer, - signature_length, - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - - if (status == NX_CRYPTO_AUTHENTICATION_FAILED) - { - return(NX_SECURE_TLS_SIGNATURE_VERIFICATION_ERROR); - } - - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - if (auth_method -> nx_crypto_cleanup) - { - status = auth_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_auth_metadata_area); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - } - else - { - /* The signature hash algorithm used by the server is not supported. */ - return(NX_SECURE_TLS_UNSUPPORTED_SIGNATURE_ALGORITHM); - } - - ecdhe_method = ciphersuite -> nx_secure_tls_public_cipher; - if (ecdhe_method -> nx_crypto_operation == NX_NULL) - { - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); - } - - if (ecdhe_method -> nx_crypto_init != NX_NULL) - { - status = ecdhe_method -> nx_crypto_init((NX_CRYPTO_METHOD*)ecdhe_method, - NX_NULL, - 0, - &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } - } - - status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0, - (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - /* Store public key in the nx_secure_tls_new_key_material_data. */ - extended_output.nx_crypto_extended_output_data = &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[1]; - extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data) - 1; - extended_output.nx_crypto_extended_output_actual_size = 0; - status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_SETUP, handler, - (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0, - NX_NULL, 0, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - /* Store the length in the first octet. */ - tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[0] = (UCHAR)extended_output.nx_crypto_extended_output_actual_size; - - extended_output.nx_crypto_extended_output_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret; - extended_output.nx_crypto_extended_output_length_in_byte = sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret); - extended_output.nx_crypto_extended_output_actual_size = 0; - status = ecdhe_method -> nx_crypto_operation(NX_CRYPTO_DH_CALCULATE, handler, - (NX_CRYPTO_METHOD*)ecdhe_method, NX_NULL, 0, - pubkey, pubkey_length, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - if (status != NX_CRYPTO_SUCCESS) - { - return(status); - } - - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret_size = extended_output.nx_crypto_extended_output_actual_size; - - if (ecdhe_method -> nx_crypto_cleanup) - { - status = ecdhe_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); - } - - return(status); - } + status = tls_session -> nx_secure_process_server_key_exchange(tls_session -> nx_secure_tls_session_ciphersuite, tls_session -> nx_secure_tls_crypto_table, + tls_session -> nx_secure_tls_protocol_version, packet_buffer, message_length, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + &tls_session -> nx_secure_tls_handshake_hash, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, tls_session -> nx_secure_public_auth_metadata_size, + NX_NULL); #endif /* defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ - /* No server key exchange should be received by the current cipher suite. */ - return(NX_SECURE_TLS_UNEXPECTED_MESSAGE); + return(status); #else /* !define(NX_SECURE_TLS_CLIENT_DISABLED) */ - /* If Client TLS is disabled and we recieve a server key exchange, error! */ + /* If Client TLS is disabled and we recieve a server key exchange, error! */ NX_PARAMETER_NOT_USED(tls_session); NX_PARAMETER_NOT_USED(packet_buffer); NX_PARAMETER_NOT_USED(message_length); diff --git a/nx_secure/src/nx_secure_tls_process_serverhello.c b/nx_secure/src/nx_secure_tls_process_serverhello.c index f2ac0688..5d36b39d 100644 --- a/nx_secure/src/nx_secure_tls_process_serverhello.c +++ b/nx_secure/src/nx_secure_tls_process_serverhello.c @@ -32,7 +32,7 @@ extern const UCHAR _nx_secure_tls_hello_retry_request_random[32]; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_serverhello PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -78,11 +78,18 @@ extern const UCHAR _nx_secure_tls_hello_retry_request_random[32]; /* verified memcpy use cases, */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* TLS 1.3 compilation issue, */ +/* resulting in version 6.1.9 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), fixed */ +/* TLS 1.3 version negotiation,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_serverhello(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, UINT message_length) { +#ifndef NX_SECURE_TLS_CLIENT_DISABLED UINT length; UCHAR compression_method; USHORT version, total_extensions_length; @@ -93,6 +100,7 @@ NX_SECURE_TLS_HELLO_EXTENSION extension_data[NX_SECURE_TLS_HELLO_EXTENSI UINT num_extensions; #if (NX_SECURE_TLS_TLS_1_3_ENABLED) USHORT tls_1_3 = tls_session -> nx_secure_tls_1_3; +USHORT no_extension = NX_FALSE; NX_SECURE_TLS_SERVER_STATE old_client_state = tls_session -> nx_secure_tls_client_state; tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_IDLE; @@ -159,7 +167,7 @@ NX_SECURE_TLS_SERVER_STATE old_client_state = tls_session -> nx_secur { /* Set the Server random data, used in key generation. First 4 bytes is GMT time. */ - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[0], &packet_buffer[length], NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random[0], &packet_buffer[length], NX_SECURE_TLS_RANDOM_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } length += NX_SECURE_TLS_RANDOM_SIZE; @@ -175,7 +183,7 @@ NX_SECURE_TLS_SERVER_STATE old_client_state = tls_session -> nx_secur /* Session ID follows. */ if (tls_session -> nx_secure_tls_session_id_length > 0) { - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[length], tls_session -> nx_secure_tls_session_id_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_session_id, &packet_buffer[length], tls_session -> nx_secure_tls_session_id_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ length += tls_session -> nx_secure_tls_session_id_length; } @@ -254,7 +262,41 @@ NX_SECURE_TLS_SERVER_STATE old_client_state = tls_session -> nx_secur } } } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + else + { + no_extension = NX_TRUE; + } +#endif + } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + else + { + no_extension = NX_TRUE; + } + + if ((tls_session -> nx_secure_tls_1_3) && (no_extension == NX_TRUE)) + { + + /* Server negotiates a version of TLS prior to TLS 1.3. */ + if (tls_session -> nx_secure_tls_protocol_version_override == 0) + { + tls_session -> nx_secure_tls_1_3 = NX_FALSE; +#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION + tls_session -> nx_secure_tls_renegotation_enabled = NX_TRUE; +#endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ + + return(NX_SUCCESS); + } + else + { + + /* Protocol version is overridden to TLS 1.3. */ + return(NX_SECURE_TLS_UNSUPPORTED_TLS_VERSION); + } + } +#endif #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION #ifdef NX_SECURE_TLS_REQUIRE_RENEGOTIATION_EXT @@ -311,5 +353,13 @@ NX_SECURE_TLS_SERVER_STATE old_client_state = tls_session -> nx_secur return(NX_SUCCESS); #endif +#else /* NX_SECURE_TLS_SERVER_DISABLED */ + /* If Server TLS is disabled and we recieve a serverhello, error! */ + NX_PARAMETER_NOT_USED(tls_session); + NX_PARAMETER_NOT_USED(packet_buffer); + NX_PARAMETER_NOT_USED(message_length); + + return(NX_SECURE_TLS_UNEXPECTED_MESSAGE); +#endif } diff --git a/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c b/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c index 7e2d9f97..b2b28a38 100644 --- a/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c +++ b/nx_secure/src/nx_secure_tls_process_serverhello_extensions.c @@ -24,6 +24,9 @@ #include "nx_secure_tls.h" +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + + #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION static UINT _nx_secure_tls_proc_serverhello_sec_reneg_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -51,12 +54,14 @@ static UINT _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(NX_SECURE_TLS_SE USHORT *extension_length, UINT message_length); #endif +#endif /* NX_SECURE_TLS_CLIENT_DISABLED */ + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_process_serverhello_extensions PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -102,6 +107,9 @@ static UINT _nx_secure_tls_proc_serverhello_ecjpake_key_kp_pair(NX_SECURE_TLS_SE /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* TLS 1.3 compilation issue, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_process_serverhello_extensions(NX_SECURE_TLS_SESSION *tls_session, @@ -109,6 +117,8 @@ UINT _nx_secure_tls_process_serverhello_extensions(NX_SECURE_TLS_SESSION *tls_se NX_SECURE_TLS_HELLO_EXTENSION *extensions, UINT *num_extensions) { +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + UINT status; #ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE @@ -175,7 +185,7 @@ USHORT supported_version = tls_session -> nx_secu #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE case NX_SECURE_TLS_EXTENSION_KEY_SHARE: - if(tls_session->nx_secure_tls_1_3) + if (tls_session -> nx_secure_tls_1_3) { /* Process the TLS 1.3 key share extension. */ status = _nx_secure_tls_proc_serverhello_keyshare_extension(tls_session, &packet_buffer[offset], &extension_length, message_length - offset); @@ -199,7 +209,7 @@ USHORT supported_version = tls_session -> nx_secu break; #endif case NX_SECURE_TLS_EXTENSION_SUPPORTED_VERSIONS: - if(tls_session->nx_secure_tls_1_3) + if (tls_session -> nx_secure_tls_1_3) { /* Process the TLS 1.3 supported_versions extension. */ @@ -232,7 +242,7 @@ USHORT supported_version = tls_session -> nx_secu } /* Store the pointer of cookie. */ - /* Note: Cookie data is stored in ServerHello packet buffer. This buffer should not be released + /* Note: Cookie data is stored in ServerHello packet buffer. This buffer should not be released or overwrote before Cookie is copied to ClientHello. */ if (tls_session -> nx_secure_tls_1_3) { @@ -330,7 +340,7 @@ USHORT supported_version = tls_session -> nx_secu #endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(tls_session->nx_secure_tls_1_3) + if (tls_session -> nx_secure_tls_1_3) { if (supported_version != NX_SECURE_TLS_VERSION_TLS_1_3) { @@ -363,9 +373,21 @@ USHORT supported_version = tls_session -> nx_secu #endif return(status); +#else + /* If Client TLS is disabled and we recieve a server key exchange, error! */ + NX_PARAMETER_NOT_USED(tls_session); + NX_PARAMETER_NOT_USED(packet_buffer); + NX_PARAMETER_NOT_USED(message_length); + NX_PARAMETER_NOT_USED(extensions); + NX_PARAMETER_NOT_USED(num_extensions); + + return(NX_SECURE_TLS_UNEXPECTED_MESSAGE); +#endif } +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -740,7 +762,7 @@ INT compare_value; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_proc_serverhello_keyshare_extension PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -777,6 +799,12 @@ INT compare_value; /* 09-30-2020 Timothy Stapko Modified comment(s), update */ /* ECC find curve method, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), removed */ +/* public key format checking, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -792,7 +820,6 @@ UINT i; ULONG offset; USHORT key_group; USHORT key_length; -UCHAR legacy_form; NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecc_key_data; UCHAR *pubkey; UCHAR *private_key; @@ -836,7 +863,7 @@ NX_SECURE_TLS_ECC *ecc_info; for (i = 0; i < ecc_info -> nx_secure_tls_ecc_supported_groups_count; i++) { /* Find the matchin group in the keys we generated and saved. */ - if(key_group != tls_session->nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve) + if (key_group != tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data[i].nx_secure_tls_ecdhe_named_curve) { continue; } @@ -852,7 +879,7 @@ NX_SECURE_TLS_ECC *ecc_info; } /* Got a matching key/curve combo, get a pointer to the selected key data. */ - ecc_key_data = tls_session->nx_secure_tls_key_material.nx_secure_tls_ecc_key_data; + ecc_key_data = tls_session -> nx_secure_tls_key_material.nx_secure_tls_ecc_key_data; if (*extension_length < 4) { @@ -867,21 +894,11 @@ NX_SECURE_TLS_ECC *ecc_info; } offset = (USHORT)(offset + 2); - /* Extract the legacy form value. NOTE: the form must be included in the ECC calculations below - so don't advance the offset! */ - legacy_form = packet_buffer[offset]; - - if(legacy_form != 0x4) - { - /* In TLS 1.3, the only valid form is 0x4. */ - return(NX_SECURE_TLS_BAD_SERVERHELLO_KEYSHARE); - } - /* Initialize the remote public key in our session. */ pubkey = &packet_buffer[offset]; /* Get the curve method to initialize the remote public key data. */ - _nx_secure_tls_find_curve_method(tls_session, key_group, &curve_method, NX_NULL); + _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, key_group, &curve_method, NX_NULL); if (curve_method == NX_NULL) { @@ -1068,3 +1085,4 @@ ULONG offset; } #endif +#endif /* NX_SECURE_TLS_CLIENT_DISABLED */ diff --git a/nx_secure/src/nx_secure_tls_psk_add.c b/nx_secure/src/nx_secure_tls_psk_add.c index 165acfd0..ad26b412 100644 --- a/nx_secure/src/nx_secure_tls_psk_add.c +++ b/nx_secure/src/nx_secure_tls_psk_add.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_psk_add PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,6 +72,9 @@ /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* fixed PSK size verification,*/ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) @@ -89,8 +92,8 @@ UINT current_index; /* Make sure we have space to add the PSK and its identity data. */ if ((current_index + 1) < NX_SECURE_TLS_MAX_PSK_KEYS && - psk_length < NX_SECURE_TLS_MAX_PSK_SIZE && - identity_length < NX_SECURE_TLS_MAX_PSK_ID_SIZE && + psk_length <= NX_SECURE_TLS_MAX_PSK_SIZE && + identity_length <= NX_SECURE_TLS_MAX_PSK_ID_SIZE && hint_length <= NX_SECURE_TLS_MAX_PSK_ID_SIZE) { /* Save off the PSK and its length. */ diff --git a/nx_secure/src/nx_secure_tls_psk_find.c b/nx_secure/src/nx_secure_tls_psk_find.c index fabdda8f..608704b7 100644 --- a/nx_secure/src/nx_secure_tls_psk_find.c +++ b/nx_secure/src/nx_secure_tls_psk_find.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_psk_find PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -42,7 +42,7 @@ /* */ /* INPUT */ /* */ -/* tls_session Pointer to TLS Session */ +/* tls_credentials TLS credentials */ /* psk_data Pointer to PSK data */ /* psk_length Length of PSK data */ /* psk_identity_hint PSK identity hint data */ @@ -60,8 +60,7 @@ /* */ /* CALLED BY */ /* */ -/* _nx_secure_tls_generate_premaster_secret */ -/* Generate the shared secret */ +/* _nx_secure_generate_premaster_secret Generate the shared secret */ /* used to generate keys later */ /* */ /* RELEASE HISTORY */ @@ -71,10 +70,13 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) -UINT _nx_secure_tls_psk_find(NX_SECURE_TLS_SESSION *tls_session, UCHAR **psk_data, UINT *psk_length, +UINT _nx_secure_tls_psk_find(NX_SECURE_TLS_CREDENTIALS *tls_credentials, UCHAR **psk_data, UINT *psk_length, UCHAR *psk_identity_hint, UINT identity_length, UINT *psk_store_index) { UINT psk_list_size; @@ -84,20 +86,20 @@ UINT i; /* Get the protection. */ tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - psk_list_size = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_count; + psk_list_size = tls_credentials -> nx_secure_tls_psk_count; if ((psk_identity_hint[0] == 0) && (psk_list_size > 0)) { /* No hint from server. Return the first associated PSK. */ - *psk_data = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_data; - *psk_length = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_data_size; + *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; if(psk_store_index != NX_NULL) { *psk_store_index = 0; - } - + } + /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); @@ -108,21 +110,21 @@ UINT i; for (i = 0; i < psk_list_size; ++i) { /* Save off the PSK and its length. */ - compare_val = (UINT)NX_SECURE_MEMCMP(tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[i].nx_secure_tls_psk_id_hint, psk_identity_hint, identity_length); + compare_val = (UINT)NX_SECURE_MEMCMP(tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_id_hint, psk_identity_hint, identity_length); /* See if the identity matched, and the length is the same (without the length, we could have a matching prefix which could be a possible attack vector... */ - if (compare_val == 0 && identity_length == tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[i].nx_secure_tls_psk_id_hint_size) + if (compare_val == 0 && identity_length == tls_credentials -> nx_secure_tls_psk_store[i].nx_secure_tls_psk_id_hint_size) { /* Found a matching identity, return the associated PSK. */ - *psk_data = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[i].nx_secure_tls_psk_data; - *psk_length = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[i].nx_secure_tls_psk_data_size; + *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; if(psk_store_index != NX_NULL) { *psk_store_index = i; } - + /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); diff --git a/nx_secure/src/nx_secure_tls_record_payload_decrypt.c b/nx_secure/src/nx_secure_tls_record_payload_decrypt.c index 8918181a..b0d040db 100644 --- a/nx_secure/src/nx_secure_tls_record_payload_decrypt.c +++ b/nx_secure/src/nx_secure_tls_record_payload_decrypt.c @@ -49,7 +49,7 @@ extern UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_S /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_record_payload_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -101,6 +101,9 @@ extern UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_S /* verified memcpy use cases, */ /* supported chained packet, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_record_payload_decrypt(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *encrypted_packet, @@ -367,7 +370,7 @@ UCHAR nonce[13]; iv, iv_size, &bytes_copied); if (status || (bytes_copied != iv_size)) { - return(status); + return(NX_SECURE_TLS_INVALID_PACKET); } offset += iv_size; @@ -415,7 +418,7 @@ UCHAR nonce[13]; message_length = (*decrypted_packet) -> nx_packet_length; status = nx_packet_data_extract_offset(*decrypted_packet, message_length - 1, &padding_length, 1, &bytes_copied); - if (status || (bytes_copied != 1)) + if (status) { nx_secure_tls_packet_release(*decrypted_packet); return(NX_SECURE_TLS_PADDING_CHECK_FAILED); @@ -429,7 +432,7 @@ UCHAR nonce[13]; /* Check all padding values. */ offset = (UINT)(message_length - (UINT)(1 + padding_length)); - while ((offset < (message_length - 1)) && (status == NX_SUCCESS)) + while (offset < (message_length - 1)) { copy_size = (UCHAR)(((message_length - 1) - offset) & 0xFF); if (copy_size > sizeof(_nx_secure_tls_record_block_buffer)) @@ -439,11 +442,7 @@ UCHAR nonce[13]; status = nx_packet_data_extract_offset(*decrypted_packet, offset, _nx_secure_tls_record_block_buffer, copy_size, &bytes_copied); - if (status) - { - nx_secure_tls_packet_release(*decrypted_packet); - return(NX_SECURE_TLS_PADDING_CHECK_FAILED); - } + NX_ASSERT(status == NX_SUCCESS); offset += bytes_copied; @@ -486,7 +485,7 @@ UCHAR nonce[13]; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_record_chained_packet_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -532,6 +531,9 @@ UCHAR nonce[13]; /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_tls_record_chained_packet_decrypt(NX_SECURE_TLS_SESSION *tls_session, @@ -622,14 +624,6 @@ const NX_CRYPTO_METHOD *session_cipher_method; return(status); } - if (bytes_processed > message_length) - { - - /* Error. We should never hit here. */ - nx_secure_tls_packet_release(packet_ptr); - return(NX_SECURE_TLS_INVALID_PACKET); - } - offset += bytes_processed; message_length -= bytes_processed; } @@ -651,7 +645,7 @@ const NX_CRYPTO_METHOD *session_cipher_method; if (status || (bytes_copied != icv_size)) { nx_secure_tls_packet_release(packet_ptr); - return(status); + return(NX_SECURE_TLS_INVALID_PACKET); } } @@ -690,7 +684,7 @@ const NX_CRYPTO_METHOD *session_cipher_method; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_record_packet_decrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -735,6 +729,9 @@ const NX_CRYPTO_METHOD *session_cipher_method; /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Timothy Stapko Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), fixed */ +/* the issue of endless loop, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_tls_record_packet_decrypt(NX_SECURE_TLS_SESSION *tls_session, @@ -855,7 +852,7 @@ UINT original_offset = offset; /* Decrypt output to packet directly. */ output = packet_ptr -> nx_packet_append_ptr; - if (block_size) + if ((block_size) && (decrypted_length > block_size)) { /* Get rounded length. */ @@ -875,7 +872,7 @@ UINT original_offset = offset; if (session_cipher_method -> nx_crypto_operation == NX_NULL) { - NX_SECURE_MEMCPY(output, input, length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(output, input, length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } else { diff --git a/nx_secure/src/nx_secure_tls_record_payload_encrypt.c b/nx_secure/src/nx_secure_tls_record_payload_encrypt.c index 7552ea87..799b7b3d 100644 --- a/nx_secure/src/nx_secure_tls_record_payload_encrypt.c +++ b/nx_secure/src/nx_secure_tls_record_payload_encrypt.c @@ -36,7 +36,7 @@ UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_SIZE]; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_record_payload_encrypt PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -77,6 +77,14 @@ UCHAR _nx_secure_tls_record_block_buffer[NX_SECURE_TLS_MAX_CIPHER_BLOCK_SIZE]; /* fixed data copy in chained */ /* packet, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), called */ +/* NX_CRYPTO_ENCRYPT_CALCULATE */ +/* to finalize the encryption */ +/* of this record, resulting */ +/* in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_record_payload_encrypt(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet, @@ -96,6 +104,8 @@ ULONG remainder_length; UINT data_offset = 0; VOID *handler = NX_NULL; VOID *crypto_method_metadata; +UINT icv_size = 0; +UCHAR *icv_ptr = NX_NULL; if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -193,7 +203,7 @@ VOID *crypto_method_metadata; { /* New IV is the last encrypted block of the output. */ - NX_SECURE_MEMCPY(iv, ¤t_packet -> nx_packet_prepend_ptr[current_length + data_offset - iv_size], + NX_SECURE_MEMCPY(iv, ¤t_packet -> nx_packet_prepend_ptr[current_length + data_offset - iv_size], /* lgtm[cpp/banned-api-usage-required-any] */ iv_size); /* Use case of memcpy is verified. */ } } @@ -250,7 +260,7 @@ VOID *crypto_method_metadata; */ /* Offset for remainder bytes is rounded_length + data_offset. */ - NX_SECURE_MEMCPY(&_nx_secure_tls_record_block_buffer[0], + NX_SECURE_MEMCPY(&_nx_secure_tls_record_block_buffer[0], /* lgtm[cpp/banned-api-usage-required-any] */ ¤t_packet -> nx_packet_prepend_ptr[rounded_length + data_offset], remainder_length); /* Use case of memcpy is verified. */ copy_length = (ULONG)(current_packet -> nx_packet_next -> nx_packet_append_ptr - @@ -259,7 +269,7 @@ VOID *crypto_method_metadata; { copy_length = (ULONG)(block_size - remainder_length); } - NX_SECURE_MEMCPY(&_nx_secure_tls_record_block_buffer[remainder_length], + NX_SECURE_MEMCPY(&_nx_secure_tls_record_block_buffer[remainder_length], /* lgtm[cpp/banned-api-usage-required-any] */ current_packet -> nx_packet_next -> nx_packet_prepend_ptr, copy_length); /* Use case of memcpy is verified. */ @@ -288,9 +298,9 @@ VOID *crypto_method_metadata; } /* Copy data from temporary buffer back into packets. */ - NX_SECURE_MEMCPY(¤t_packet -> nx_packet_prepend_ptr[rounded_length + data_offset], + NX_SECURE_MEMCPY(¤t_packet -> nx_packet_prepend_ptr[rounded_length + data_offset], /* lgtm[cpp/banned-api-usage-required-any] */ &_nx_secure_tls_record_block_buffer[0], remainder_length); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(current_packet -> nx_packet_next -> nx_packet_prepend_ptr, + NX_SECURE_MEMCPY(current_packet -> nx_packet_next -> nx_packet_prepend_ptr, /* lgtm[cpp/banned-api-usage-required-any] */ &_nx_secure_tls_record_block_buffer[remainder_length], copy_length); /* Use case of memcpy is verified. */ @@ -299,7 +309,7 @@ VOID *crypto_method_metadata; { /* New IV is the last encrypted block of the output. */ - NX_SECURE_MEMCPY(iv, &_nx_secure_tls_record_block_buffer, iv_size); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(iv, &_nx_secure_tls_record_block_buffer, iv_size); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } #ifdef NX_SECURE_KEY_CLEAR @@ -320,17 +330,22 @@ VOID *crypto_method_metadata; current_packet = current_packet -> nx_packet_next; } while (current_packet != NX_NULL); -#ifdef NX_SECURE_ENABLE_AEAD_CIPHER if (session_cipher_method -> nx_crypto_ICV_size_in_bits > 0) { + + /* Get icv_size and icv_ptr for AEAD cipher */ if ((session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3) > sizeof(_nx_secure_tls_record_block_buffer)) { return(NX_SIZE_ERROR); } - /* Get TAG. */ - status = session_cipher_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT_CALCULATE, + icv_size = session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3; + icv_ptr = _nx_secure_tls_record_block_buffer; + } + + /* Call NX_CRYPTO_ENCRYPT_CALCULATE to finalize the encryption of this record. */ + status = session_cipher_method -> nx_crypto_operation(NX_CRYPTO_ENCRYPT_CALCULATE, handler, (NX_CRYPTO_METHOD*)session_cipher_method, NX_NULL, @@ -338,26 +353,26 @@ VOID *crypto_method_metadata; NX_NULL, 0, NX_NULL, - _nx_secure_tls_record_block_buffer, - (session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3), + icv_ptr, + icv_size, crypto_method_metadata, tls_session -> nx_secure_session_cipher_metadata_size, NX_NULL, NX_NULL); - if (status) - { - return(status); - } - - status = nx_packet_data_append(send_packet, _nx_secure_tls_record_block_buffer, - (session_cipher_method -> nx_crypto_ICV_size_in_bits >> 3), - tls_session -> nx_secure_tls_packet_pool, NX_WAIT_FOREVER); - if (status) - { - return(status); - } + if (status) + { + return(status); } -#endif /* NX_SECURE_ENABLE_AEAD_CIPHER */ + if (icv_ptr && icv_size) + { + + /* Append data for AEAD cipher */ + status = nx_packet_data_append(send_packet, icv_ptr, icv_size, + tls_session -> nx_secure_tls_packet_pool, NX_WAIT_FOREVER); + + return(status); + } + return(NX_SUCCESS); } @@ -366,7 +381,7 @@ VOID *crypto_method_metadata; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_record_data_encrypt_init PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -405,6 +420,9 @@ VOID *crypto_method_metadata; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_tls_record_data_encrypt_init(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet, @@ -637,7 +655,7 @@ UINT message_length; /* IV size is equal to the AES block size. Copy our IV into our data buffer at the head of the payload. */ - NX_SECURE_MEMCPY(send_packet -> nx_packet_prepend_ptr, iv, iv_size); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(send_packet -> nx_packet_prepend_ptr, iv, iv_size); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ *data_offset = iv_size; } @@ -686,10 +704,7 @@ UINT message_length; NX_SECURE_MEMSET(_nx_secure_tls_record_block_buffer, 0, block_size); #endif /* NX_SECURE_KEY_CLEAR */ - if (status) - { - return(status); - } + return(status); } return(NX_SUCCESS); 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 b1f66e8c..e83ee1cb 100644 --- a/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c +++ b/nx_secure/src/nx_secure_tls_remote_certificate_allocate.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_remote_certificate_allocate PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -80,6 +80,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_remote_certificate_allocate(NX_SECURE_TLS_SESSION *tls_session, @@ -105,6 +108,12 @@ UINT status; /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERT_ID_DUPLICATE) + { + return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + } + return(status); } diff --git a/nx_secure/src/nx_secure_tls_remote_certificate_buffer_allocate.c b/nx_secure/src/nx_secure_tls_remote_certificate_buffer_allocate.c index 9ce6508d..9044b68c 100644 --- a/nx_secure/src/nx_secure_tls_remote_certificate_buffer_allocate.c +++ b/nx_secure/src/nx_secure_tls_remote_certificate_buffer_allocate.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_remote_certificate_buffer_allocate PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -79,6 +79,12 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* removed parameter checking, */ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), added */ +/* assert to check for zero, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_remote_certificate_buffer_allocate(NX_SECURE_TLS_SESSION *tls_session, UINT certs_number, VOID *certificate_buffer, ULONG buffer_size) @@ -94,11 +100,13 @@ UINT count; metadata_size = sizeof(NX_SECURE_X509_CERT) * certs_number; /* Check that buffer is large enough. */ - if(buffer_size < metadata_size || certs_number == 0 || buffer_size == 0) + if(buffer_size < metadata_size) { return(NX_INVALID_PARAMETERS); } + NX_ASSERT(certs_number != 0); + /* Calculate the per-certificate size allocated from the buffer. */ cert_buffer_size = (buffer_size - metadata_size) / certs_number; diff --git a/nx_secure/src/nx_secure_tls_remote_certificate_free.c b/nx_secure/src/nx_secure_tls_remote_certificate_free.c index 276f711a..d8c06c31 100644 --- a/nx_secure/src/nx_secure_tls_remote_certificate_free.c +++ b/nx_secure/src/nx_secure_tls_remote_certificate_free.c @@ -22,7 +22,6 @@ #define NX_SECURE_SOURCE_CODE - /* Include necessary system files. */ #include "nx_secure_tls.h" @@ -32,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_remote_certificate_free PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,6 +73,13 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), fixed */ /* certificate allocation bug, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved code coverage */ +/* results, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_remote_certificate_free(NX_SECURE_TLS_SESSION *tls_session, @@ -93,11 +99,17 @@ NX_SECURE_X509_CERT *certificate; /* Find the certificate using it's name. */ status = _nx_secure_x509_certificate_list_find(&list_head, name, 0, &certificate); - if (status != NX_SUCCESS) + /* Now status can only be NX_SECURE_X509_CERTIFICATE_NOT_FOUND or NX_SECURE_X509_SUCCESS as + "&list_head" and "&certificate" are not NULL. + Translate X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) { - return(status); + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); } + /* Make sure status is NX_SECURE_X509_SUCCESS here. */ + NX_ASSERT(status == NX_SECURE_X509_SUCCESS); + /* Remove the certificate from the remote store. */ _nx_secure_x509_store_certificate_remove(store, name, NX_SECURE_X509_CERT_LOCATION_REMOTE, 0); @@ -110,6 +122,13 @@ NX_SECURE_X509_CERT *certificate; if (status != NX_SUCCESS) { + + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERT_ID_DUPLICATE) + { + return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + } + return(status); } } diff --git a/nx_secure/src/nx_secure_tls_remote_certificate_verify.c b/nx_secure/src/nx_secure_tls_remote_certificate_verify.c index 8b0c8f2f..e0ed984d 100644 --- a/nx_secure/src/nx_secure_tls_remote_certificate_verify.c +++ b/nx_secure/src/nx_secure_tls_remote_certificate_verify.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_remote_certificate_verify PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -53,11 +53,9 @@ /* */ /* CALLS */ /* */ -/* _nx_secure_x509_certificate_chain_verify */ -/* Verify cert against stores */ -/* _nx_secure_x509_expiration_check Verify expiration of cert */ /* _nx_secure_x509_remote_endpoint_certificate_get */ /* Get remote host certificate */ +/* [nx_secure_remote_certificate_verify] Verify the remote certificate */ /* [nx_secure_tls_session_certificate_callback] */ /* Session certificate callback */ /* [nx_secure_tls_session_time_function] Session time callback */ @@ -74,6 +72,20 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* improved code coverage */ +/* results, */ +/* resulting in version 6.1.10 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked expiration for all */ +/* the certs in the chain, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_remote_certificate_verify(NX_SECURE_TLS_SESSION *tls_session) @@ -116,19 +128,11 @@ ULONG current_time; { /* Get the current time from our callback. */ current_time = tls_session -> nx_secure_tls_session_time_function(); - - /* Check the remote certificate against the current time. */ - status = _nx_secure_x509_expiration_check(remote_certificate, current_time); - - if (status != NX_SUCCESS) - { - return(status); - } } /* Now verify our remote certificate chain. If the certificate can be linked to an issuer in the trusted store through an issuer chain, this function will return NX_SUCCESS. */ - status = _nx_secure_x509_certificate_chain_verify(store, remote_certificate); + status = tls_session -> nx_secure_remote_certificate_verify(store, remote_certificate, current_time); if (status != NX_SUCCESS) { diff --git a/nx_secure/src/nx_secure_tls_send_certificate.c b/nx_secure/src/nx_secure_tls_send_certificate.c index 354495b7..f2335c03 100644 --- a/nx_secure/src/nx_secure_tls_send_certificate.c +++ b/nx_secure/src/nx_secure_tls_send_certificate.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_certificate PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,7 +73,12 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ -/* */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Zhen Kong Modified comment(s), removed */ +/* unreachable error code, */ +/* resulting in version 6.1.11 */ /**************************************************************************/ UINT _nx_secure_tls_send_certificate(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet, ULONG wait_option) @@ -118,7 +123,7 @@ UINT extensions_length; /* See if this is a TLS client sending a certificate in response to a certificate request from the remote server. */ if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT && - (status == NX_SECURE_TLS_CERTIFICATE_NOT_FOUND)) + (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND)) { /* If this is a TLS client, as per the RFC we can have no certificate assigned in which case our response to the server that has requested our certificate will contain @@ -133,8 +138,10 @@ UINT extensions_length; { if (status) { - /* No certificate found, error! */ - return(status); + + /* _nx_secure_x509_local_device_certificate_get can only return + NX_SECURE_X509_CERTIFICATE_NOT_FOUND in this case. */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); } } diff --git a/nx_secure/src/nx_secure_tls_send_certificate_verify.c b/nx_secure/src/nx_secure_tls_send_certificate_verify.c index a8d5c517..ff7e068e 100644 --- a/nx_secure/src/nx_secure_tls_send_certificate_verify.c +++ b/nx_secure/src/nx_secure_tls_send_certificate_verify.c @@ -40,7 +40,7 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09 /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_certificate_verify PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -88,6 +88,22 @@ static const UCHAR _NX_SECURE_OID_SHA256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09 /* ECC find curve method, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* supported hardware EC */ +/* private key, */ +/* resulting in version 6.1.7 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Zhen Kong Modified comment(s), removed */ +/* unreachable code and branch,*/ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* updated parameters list, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_certificate_verify(NX_SECURE_TLS_SESSION *tls_session, @@ -119,6 +135,7 @@ const CHAR client_context[] = "TLS 1.3, client CertificateVerify\0"; /* Includes const NX_CRYPTO_METHOD *curve_method_cert; NX_SECURE_EC_PRIVATE_KEY *ec_privkey; NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; +NX_SECURE_EC_PRIVATE_KEY ec_hardware_privkey; NX_CRYPTO_EXTENDED_OUTPUT extended_output; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ @@ -173,8 +190,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; but in that case we shouldn't be trying to send a CertificateVerify. */ if (status) { - /* The local certificate was not found. */ - return(status); + + /* Translate X.509 return values into TLS return values. */ + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); } #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -214,11 +232,14 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; status = _nx_secure_x509_find_certificate_methods(local_certificate, signature_algorithm, &crypto_methods); if (status != NX_SUCCESS) { - return(status); + + /* Translate X.509 return values into TLS return values. */ + return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM); + } #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - if(tls_session->nx_secure_tls_1_3) + if(tls_session -> nx_secure_tls_1_3) { /* TLS 1.3 certificate verify uses a different scheme. The signature is calculated over a concatenation of the following (RFC 8446): @@ -228,7 +249,7 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; - The content to be signed */ - UCHAR *transcript_hash = tls_session->nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE]; + UCHAR *transcript_hash = tls_session -> nx_secure_tls_key_material.nx_secure_tls_transcript_hashes[NX_SECURE_TLS_TRANSCRIPT_IDX_CERTIFICATE]; /* Set octet padding bytes. */ NX_SECURE_MEMSET(&handshake_hash[0], 0x20, 64); @@ -359,9 +380,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; /* Generate a hash of all sent and received handshake messages to this point (not a Finished hash!). */ /* Copy over the handshake hash state into a local structure to do the intermediate calculation. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, /* lgtm[cpp/banned-api-usage-required-any] */ + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ /* Use SHA-256 for now... */ hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method; @@ -383,10 +404,13 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; NX_NULL); } - if(status != NX_CRYPTO_SUCCESS) + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) { return(status); - } + } } #endif @@ -401,15 +425,11 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_1) #endif /* NX_SECURE_ENABLE_DTLS */ { - /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. Copy SHA-1 in - first, then MD5. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ + /* Copy over the handshake hash metadata into scratch metadata area to do the intermediate calculation. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); /* Use case of memcpy is verified. */ /* Finalize the handshake message hashes that we started at the beginning of the handshake. */ hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; @@ -431,12 +451,21 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; NX_NULL, NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } } + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch + + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); + } + + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); /* Use case of memcpy is verified. */ + hash_method = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method; if (hash_method -> nx_crypto_operation != NX_NULL) { @@ -455,10 +484,14 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; NX_NULL, NX_NULL); - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } + } + + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size); + + if (status != NX_CRYPTO_SUCCESS) + { + return(status); } } #endif @@ -509,7 +542,11 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) #else + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) +#endif + #endif /* NX_SECURE_ENABLE_DTLS */ { /* Signature algorithm used. */ @@ -540,10 +577,10 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; working_ptr = &_nx_secure_padded_signature[data_size - signature_length]; /* Copy in the DER encoding. */ - NX_SECURE_MEMCPY(&working_ptr[0], _NX_SECURE_OID_SHA256, 19); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&working_ptr[0], _NX_SECURE_OID_SHA256, 19); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Now put the data into the padded buffer - must be at the end. */ - NX_SECURE_MEMCPY(&working_ptr[19], handshake_hash, 32); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&working_ptr[19], handshake_hash, 32); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } #endif @@ -584,7 +621,7 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; #endif #ifdef NX_SECURE_KEY_CLEAR - /* At this point, the handshake_hash has been copied into _nx_secure_padded_signature and + /* At this point, the handshake_hash has been copied into _nx_secure_padded_signature and is no longer needed so we can clear it here. */ NX_SECURE_MEMSET(handshake_hash, 0, sizeof(handshake_hash)); #endif /* NX_SECURE_KEY_CLEAR */ @@ -621,9 +658,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ +#endif /* NX_SECURE_KEY_CLEAR */ return(status); - } + } } else { @@ -643,9 +680,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ +#endif /* NX_SECURE_KEY_CLEAR */ return(status); - } + } } if (public_cipher_method -> nx_crypto_operation != NX_NULL) @@ -669,9 +706,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ +#endif /* NX_SECURE_KEY_CLEAR */ return(status); - } + } } if (public_cipher_method -> nx_crypto_cleanup) @@ -682,9 +719,9 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(_nx_secure_padded_signature, 0, sizeof(_nx_secure_padded_signature)); -#endif /* NX_SECURE_KEY_CLEAR */ +#endif /* NX_SECURE_KEY_CLEAR */ return(status); - } + } } } @@ -705,7 +742,11 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2 || tls_session -> nx_secure_tls_protocol_version == NX_SECURE_DTLS_VERSION_1_2) #else + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_protocol_version == NX_SECURE_TLS_VERSION_TLS_1_2) +#endif + #endif /* NX_SECURE_ENABLE_DTLS */ { #if (NX_SECURE_TLS_TLS_1_3_ENABLED) @@ -745,11 +786,23 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; } #endif - ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key; + /* Check for hardware key types before encrypting the hash to produce the signature. */ + if(local_certificate -> nx_secure_x509_private_key_type == NX_SECURE_X509_KEY_TYPE_HARDWARE) + { + /* The certificate private key is stored in a secure element or similar. Just pass the private/user key data to the driver. */ + ec_hardware_privkey.nx_secure_ec_private_key = local_certificate -> nx_secure_x509_private_key.user_key.key_data; + ec_hardware_privkey.nx_secure_ec_private_key_length = (USHORT)local_certificate -> nx_secure_x509_private_key.user_key.key_length; + ec_hardware_privkey.nx_secure_ec_named_curve = local_certificate -> nx_secure_x509_public_key.ec_public_key.nx_secure_ec_named_curve; + ec_privkey = &ec_hardware_privkey; + } + else + { + ec_privkey = &local_certificate -> nx_secure_x509_private_key.ec_private_key; + } ec_pubkey = &local_certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the local certificate is using. */ - status = _nx_secure_tls_find_curve_method(tls_session, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); + status = _nx_secure_tls_find_curve_method(&tls_session -> nx_secure_tls_ecc, (USHORT)(ec_privkey -> nx_secure_ec_named_curve), &curve_method_cert, NX_NULL); #ifdef NX_SECURE_KEY_CLEAR if(status != NX_SUCCESS || curve_method_cert == NX_NULL) @@ -760,16 +813,11 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; } #endif /* NX_SECURE_KEY_CLEAR */ - + /* curve_method_cert is set to NX_NULL if status != NX_SUCCESS */ if(status != NX_SUCCESS) { return(status); } - if (curve_method_cert == NX_NULL) - { - /* The local certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_ECC_CURVE); - } if (public_cipher_method -> nx_crypto_init != NX_NULL) { diff --git a/nx_secure/src/nx_secure_tls_send_client_key_exchange.c b/nx_secure/src/nx_secure_tls_send_client_key_exchange.c index 7515c441..5828f905 100644 --- a/nx_secure/src/nx_secure_tls_send_client_key_exchange.c +++ b/nx_secure/src/nx_secure_tls_send_client_key_exchange.c @@ -25,14 +25,12 @@ #include "nx_secure_tls.h" -static UCHAR _nx_secure_client_padded_pre_master[600]; - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_client_key_exchange PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -55,10 +53,8 @@ static UCHAR _nx_secure_client_padded_pre_master[600]; /* */ /* CALLS */ /* */ -/* _nx_secure_x509_remote_endpoint_certificate_get */ -/* Get cert for remote host */ -/* [nx_crypto_operation] Public-key ciphers */ -/* [nx_crypto_init] Initialize Crypto Method */ +/* [nx_secure_generate_client_key_exchange] */ +/* Generate ClientKeyExchange */ /* _nx_secure_tls_remote_certificate_free_all */ /* Free all remote certificates */ /* */ @@ -75,35 +71,23 @@ static UCHAR _nx_secure_client_padded_pre_master[600]; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Zhen Kong Modified comment(s), improved */ +/* internal logic to check data*/ +/* size and then improved code */ +/* coverage, resulting in */ +/* version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_client_key_exchange(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet) { -UINT status; -UINT data_size; -UCHAR *encrypted_data_ptr; -UCHAR *packet_buffer; -UCHAR rand_byte; -UINT i; -const NX_CRYPTO_METHOD *public_cipher_method; -NX_SECURE_X509_CERT *remote_certificate; -VOID *handler = NX_NULL; -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE -NX_CRYPTO_EXTENDED_OUTPUT extended_output; -#endif /* NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE */ - - /* Send a ClientKeyExchange message. - * Structure: - * | 2 | | - * | Length | Encrypted Pre-Master Secret | - * - * ECDHE ephemeral key structure: - * | 2 | | - * | Length | EC Diffie-Hellman Client Params | - */ - - packet_buffer = send_packet -> nx_packet_append_ptr; +#if !defined(NX_SECURE_TLS_CLIENT_DISABLED) +UINT status; +ULONG data_size = 0; +ULONG buffer_length; if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -112,217 +96,30 @@ NX_CRYPTO_EXTENDED_OUTPUT extended_output; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDH || - tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) - { - data_size = (UINT)(1 + tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[0]); - - if ((data_size > sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data)) || - (data_size > ((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)))) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); - /* Packet buffer too small. */ - return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); - } - - NX_SECURE_MEMCPY(packet_buffer, tls_session -> nx_secure_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 */ + buffer_length = (ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr); + + status = tls_session -> nx_secure_generate_client_key_exchange(tls_session -> nx_secure_tls_session_ciphersuite, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + send_packet -> nx_packet_append_ptr, + buffer_length, + &data_size, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, + tls_session -> nx_secure_public_auth_metadata_size); + if (status) { - - /* Pointer to the output encrypted pre-master secret. */ - encrypted_data_ptr = &packet_buffer[2]; - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* Check for PSK ciphersuites. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) - { - if ((tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint_size > - sizeof(tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint)) || - (tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_hint_size > - (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) - 2))) - { - - /* Packet buffer too small. */ - return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); - } - - /* Send the PSK Identity string to the remote server along with its length. */ - NX_SECURE_MEMCPY(encrypted_data_ptr, tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id, - tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_size); /* Use case of memcpy is verified. */ - - /* Make sure our size is correct. */ - data_size = tls_session -> nx_secure_tls_credentials.nx_secure_tls_client_psk.nx_secure_tls_psk_id_size; - - /* Put the length into our outgoing packet buffer. */ - packet_buffer[0] = (UCHAR)((data_size & 0xFF00) >> 8); - packet_buffer[1] = (UCHAR)(data_size & 0x00FF); - - data_size += 2; - } - else -#endif -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) - { - data_size = 0; - public_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth; - - extended_output.nx_crypto_extended_output_data = packet_buffer; - extended_output.nx_crypto_extended_output_length_in_byte = - (ULONG)send_packet -> nx_packet_data_end - (ULONG)packet_buffer; - extended_output.nx_crypto_extended_output_actual_size = 0; - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_CLIENT_KEY_EXCHANGE_GENERATE, - tls_session -> nx_secure_public_auth_handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - NX_NULL, 0, - NX_NULL, 0, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if (status) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); - return(status); - } - - data_size += extended_output.nx_crypto_extended_output_actual_size; - } - else -#endif - { - - /* Extract the data to be verified from the remote certificate processed earlier. */ - status = _nx_secure_x509_remote_endpoint_certificate_get(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, - &remote_certificate); - - if (status) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); - - /* No certificate found, error! */ - return(NX_SECURE_TLS_NO_CERT_SPACE_ALLOCATED); - } - - /* Get the public cipher method from the ciphersuite. */ - public_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher; - - /* If using RSA, the length is equal to the key size. */ - data_size = remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length; - - /* PKCS#1 v1.5 padding. The scheme is to start with the block type (0x00, 0x02 for PKCS#1) - then pad with non-zero bytes (random is cryptographically more secure), followed with - a single 0 byte right before the payload, which comes at the end of the RSA block. */ - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0x0, sizeof(_nx_secure_client_padded_pre_master)); - _nx_secure_client_padded_pre_master[1] = 0x2; /* Block type is 0x00, 0x02 */ - for (i = 2; i < (data_size - NX_SECURE_TLS_RSA_PREMASTER_SIZE - 1); ++i) - { - /* PKCS#1 padding must be random, but CANNOT be 0. */ - do - { - rand_byte = (UCHAR)NX_RAND(); - } while (rand_byte == 0); - _nx_secure_client_padded_pre_master[i] = rand_byte; - } - - if ((data_size < NX_SECURE_TLS_RSA_PREMASTER_SIZE) || - (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr)) < (2u + data_size))) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); - - /* Invalid certificate modulus length. */ - return(NX_SECURE_TLS_INVALID_CERTIFICATE); - } - - /* Now put the pre-master data into the padded buffer - must be at the end. */ - NX_SECURE_MEMCPY(&_nx_secure_client_padded_pre_master[data_size - NX_SECURE_TLS_RSA_PREMASTER_SIZE], - tls_session -> nx_secure_tls_key_material.nx_secure_tls_pre_master_secret, NX_SECURE_TLS_RSA_PREMASTER_SIZE); /* Use case of memcpy is verified. */ - - if (public_cipher_method -> nx_crypto_init != NX_NULL) - { - /* Initialize the crypto method with public key. */ - status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, - (UCHAR *)remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus, - (NX_CRYPTO_KEY_SIZE)(remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length << 3), - &handler, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size); - - if(status != NX_CRYPTO_SUCCESS) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(status); - } - } - - if (public_cipher_method -> nx_crypto_operation != NX_NULL) - { - /* Now encrypt the pre-master secret using the public key provided by the remote host - and place the result in the outgoing packet buffer. */ - status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, - handler, - (NX_CRYPTO_METHOD*)public_cipher_method, - (UCHAR *)remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent, - (NX_CRYPTO_KEY_SIZE)(remote_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), - _nx_secure_client_padded_pre_master, - data_size, - NX_NULL, - encrypted_data_ptr, - data_size, - tls_session -> nx_secure_public_cipher_metadata_area, - tls_session -> nx_secure_public_cipher_metadata_size, - NX_NULL, NX_NULL); - - if(status != NX_CRYPTO_SUCCESS) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(status); - } - } - - if (public_cipher_method -> nx_crypto_cleanup) - { - status = public_cipher_method -> nx_crypto_cleanup(tls_session -> nx_secure_public_cipher_metadata_area); - - if(status != NX_CRYPTO_SUCCESS) - { - _nx_secure_tls_remote_certificate_free_all(tls_session); -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ - - return(status); - } - } - - /* Put the length into our outgoing packet buffer. */ - packet_buffer[0] = (UCHAR)((data_size & 0xFF00) >> 8); - packet_buffer[1] = (UCHAR)(data_size & 0x00FF); - - data_size += 2; - } + _nx_secure_tls_remote_certificate_free_all(tls_session); + return(status); } - /* Let the caller know how many bytes we wrote. +2 for the length we just added. */ send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + data_size; send_packet -> nx_packet_length = send_packet -> nx_packet_length + data_size; -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_nx_secure_client_padded_pre_master, 0, sizeof(_nx_secure_client_padded_pre_master)); -#endif /* NX_SECURE_KEY_CLEAR */ - return(NX_SECURE_TLS_SUCCESS); +#else + NX_PARAMETER_NOT_USED(tls_session); + NX_PARAMETER_NOT_USED(send_packet); + return(NX_SECURE_TLS_INVALID_STATE); +#endif } diff --git a/nx_secure/src/nx_secure_tls_send_clienthello.c b/nx_secure/src/nx_secure_tls_send_clienthello.c index 43bc4fb0..5c834c0c 100644 --- a/nx_secure/src/nx_secure_tls_send_clienthello.c +++ b/nx_secure/src/nx_secure_tls_send_clienthello.c @@ -38,7 +38,7 @@ UINT _nx_secure_tls_send_clienthello_psk_extension(NX_SECURE_TLS_SESSION *tls_se /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_clienthello PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -81,6 +81,9 @@ UINT _nx_secure_tls_send_clienthello_psk_extension(NX_SECURE_TLS_SESSION *tls_se /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-25-2022 Zhen Kong Modified comment(s), removed */ +/* the code to copy session */ +/* id, resulting in version 6.1.11*/ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_clienthello(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet) @@ -174,7 +177,7 @@ ULONG extension_length, total_extensions_length; gmt_time = tls_session -> nx_secure_tls_session_time_function(); } NX_CHANGE_ULONG_ENDIAN(gmt_time); - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) if (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HELLO_RETRY) @@ -197,23 +200,16 @@ ULONG extension_length, total_extensions_length; } /* Copy the random data into the packet. */ - NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, + NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random, /* lgtm[cpp/banned-api-usage-required-any] */ sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random)); /* Use case of memcpy is verified. */ } length += sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_random); - /* Session ID length is one byte. */ + /* Session ID length is one byte. As session resumption is not implemented yet, ClientHello doesn't include Session ID now. */ tls_session -> nx_secure_tls_session_id_length = 0; packet_buffer[length] = tls_session -> nx_secure_tls_session_id_length; length++; - /* Session ID follows. */ - if (tls_session -> nx_secure_tls_session_id_length > 0) - { - NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_session_id, tls_session -> nx_secure_tls_session_id_length); /* Use case of memcpy is verified. */ - length += tls_session -> nx_secure_tls_session_id_length; - } - /* TLS 1.0-1.2. */ ciphersuites_length_ptr = &packet_buffer[length]; length += 2; diff --git a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c index 8184f830..bb1c19d4 100644 --- a/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c +++ b/nx_secure/src/nx_secure_tls_send_clienthello_extensions.c @@ -34,10 +34,12 @@ static UINT _nx_secure_tls_send_clienthello_sig_extension(NX_SECURE_TLS_SESSION UCHAR *packet_buffer, ULONG *packet_offset, USHORT *extension_length, ULONG available_size); +#ifndef NX_SECURE_TLS_SNI_EXTENSION_DISABLED static UINT _nx_secure_tls_send_clienthello_sni_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_offset, USHORT *extension_length, ULONG available_size); +#endif #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE static UINT _nx_secure_tls_send_clienthello_sec_spf_extensions(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_offset, @@ -82,7 +84,7 @@ static UINT _nx_secure_tls_send_clienthello_sec_reneg_extension(NX_SECURE_TLS_SE /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_clienthello_extensions PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -131,6 +133,9 @@ static UINT _nx_secure_tls_send_clienthello_sec_reneg_extension(NX_SECURE_TLS_SE /* verified memcpy use cases, */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yajun Xia Modified comment(s), */ +/* added exception case, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_clienthello_extensions(NX_SECURE_TLS_SESSION *tls_session, @@ -150,6 +155,10 @@ UINT status; &length, &extension_length, available_size); + if (status != NX_SUCCESS) + { + return(status); + } total_extensions_length = (USHORT)(total_extensions_length + extension_length); #endif @@ -269,7 +278,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_clienthello_sig_extension PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -307,6 +316,9 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unused code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_tls_send_clienthello_sig_extension(NX_SECURE_TLS_SESSION *tls_session, @@ -383,7 +395,6 @@ NX_SECURE_X509_CRYPTO *cipher_table; packet_buffer[ext_pos] = (UCHAR)((sighash_len & 0xFF00) >> 8); packet_buffer[ext_pos + 1] = (UCHAR)(sighash_len & 0x00FF); - ext_pos += 2; /* Return our updated packet offset. */ *extension_length = ext_len; @@ -826,7 +837,7 @@ USHORT named_curve; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_clienthello_psk_extension PORTABLE C */ -/* 6.1 */ +/* 6.1.8 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -865,6 +876,9 @@ USHORT named_curve; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* hash clone and cleanup, */ +/* resulting in version 6.1.8 */ /* */ /**************************************************************************/ @@ -1071,9 +1085,9 @@ NX_SECURE_TLS_PSK_STORE *psk_store; { /* Save the handshake hash state. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ } /* Hash the ClientHello up to its current point. */ @@ -1087,17 +1101,30 @@ NX_SECURE_TLS_PSK_STORE *psk_store; /* Save the transcript hash for the ClientHello, which is used in generating the PSK binders. */ status = _nx_secure_tls_1_3_transcript_hash_save(tls_session, NX_SECURE_TLS_TRANSCRIPT_IDX_CLIENTHELLO, NX_FALSE); - if(status != NX_SUCCESS) + if (status != NX_SUCCESS) { + + if (tls_session -> nx_secure_tls_client_state != NX_SECURE_TLS_CLIENT_STATE_IDLE) + { + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + } + return(status); } /* Restore the original metadata(ClientHello1 and HelloRetryRequest) from scratch buffer. */ if (tls_session -> nx_secure_tls_client_state != NX_SECURE_TLS_CLIENT_STATE_IDLE) { - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); + + NX_SECURE_HASH_METADATA_CLONE(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); /* Use case of memcpy is verified. */ + + NX_SECURE_HASH_CLONE_CLEANUP(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_scratch, + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata_size); } /* Loop through all IDs and set the binders accordingly. */ @@ -1405,7 +1432,7 @@ UINT data_length; offset += 2; /* Write the name into the packet. */ - NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_sni_extension_server_name -> nx_secure_x509_dns_name, data_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_sni_extension_server_name -> nx_secure_x509_dns_name, data_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ offset += data_length; /* Return the amount of data we wrote. */ @@ -1580,7 +1607,7 @@ UINT data_length; offset++; /* Copy the verify data into the packet. */ - NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_local_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_local_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ offset += NX_SECURE_TLS_FINISHED_HASH_SIZE; } diff --git a/nx_secure/src/nx_secure_tls_send_finished.c b/nx_secure/src/nx_secure_tls_send_finished.c index 22695b83..b9ef2293 100644 --- a/nx_secure/src/nx_secure_tls_send_finished.c +++ b/nx_secure/src/nx_secure_tls_send_finished.c @@ -119,7 +119,7 @@ UINT is_server; #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION /* If we are doing secure renegotiation as per RFC 5746, we need to save off the generated verify data now. For TLS 1.0-1.2 this is 12 bytes. If SSLv3 is ever used, it will be 36 bytes. */ - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_local_verify_data, send_packet -> nx_packet_append_ptr, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_local_verify_data, send_packet -> nx_packet_append_ptr, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ #endif /* The finished verify data is always 12 bytes for TLS 1.2 and earlier. */ diff --git a/nx_secure/src/nx_secure_tls_send_handshake_record.c b/nx_secure/src/nx_secure_tls_send_handshake_record.c index 6576f020..17eba189 100644 --- a/nx_secure/src/nx_secure_tls_send_handshake_record.c +++ b/nx_secure/src/nx_secure_tls_send_handshake_record.c @@ -138,7 +138,7 @@ UINT buffer_offset; if (handshake_type == NX_SECURE_TLS_CLIENT_HELLO) #endif /* (NX_SECURE_TLS_TLS_1_3_ENABLED) */ { - NX_SECURE_MEMCPY(&tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache[buffer_offset], + NX_SECURE_MEMCPY(&tls_session->nx_secure_tls_key_material.nx_secure_tls_handshake_cache[buffer_offset], /* lgtm[cpp/banned-api-usage-required-any] */ current_packet -> nx_packet_prepend_ptr, (UINT)length); /* Use case of memcpy is verified. */ /* Advance the length. */ diff --git a/nx_secure/src/nx_secure_tls_send_record.c b/nx_secure/src/nx_secure_tls_send_record.c index a8ceff01..a825cfcc 100644 --- a/nx_secure/src/nx_secure_tls_send_record.c +++ b/nx_secure/src/nx_secure_tls_send_record.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_record PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -84,6 +84,18 @@ /* fixed race condition for */ /* multithread transmission, */ /* resulting in version 6.1 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* resulting in version 6.1.7 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), */ +/* used wait forever on */ +/* transmission mutex, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked seq number overflow,*/ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_record(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet, @@ -116,7 +128,7 @@ NX_PACKET *current_packet; tx_mutex_put(&_nx_secure_tls_protection); /* Get transmit mutex first. */ - status = tx_mutex_get(&(tls_session -> nx_secure_tls_session_transmit_mutex), wait_option); + status = tx_mutex_get(&(tls_session -> nx_secure_tls_session_transmit_mutex), TX_WAIT_FOREVER); tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); @@ -160,10 +172,6 @@ NX_PACKET *current_packet; send_packet -> nx_packet_length += iv_size; } - /* Back off the prepend_ptr for TLS Record header. Note the packet_length field is adjusted - prior to nx_tcp_socket_send() below. */ - //send_packet -> nx_packet_prepend_ptr -= NX_SECURE_TLS_RECORD_HEADER_SIZE; - /* Ensure there is enough room for the record header. */ if ((ULONG)(send_packet -> nx_packet_prepend_ptr - send_packet -> nx_packet_data_start) < NX_SECURE_TLS_RECORD_HEADER_SIZE) { @@ -196,14 +204,7 @@ NX_PACKET *current_packet; if (tls_session -> nx_secure_tls_local_session_active) { /*************************************************************************************************************/ - - if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) - { - - /* Likely internal error since at this point ciphersuite negotiation was theoretically completed. */ - tx_mutex_put(&(tls_session -> nx_secure_tls_session_transmit_mutex)); - return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); - } + NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL) #if (NX_SECURE_TLS_TLS_1_3_ENABLED) /* TLS 1.3 records have the record type appended in a single byte. */ @@ -320,6 +321,14 @@ NX_PACKET *current_packet; { /* Check for overflow of the 32-bit number. */ tls_session -> nx_secure_tls_local_sequence_number[1]++; + + if (tls_session -> nx_secure_tls_local_sequence_number[1] == 0) + { + + /* Check for overflow of the 64-bit unsigned number. As it should not reach here + in practical, we return a general error to prevent overflow theoretically. */ + return(NX_NOT_SUCCESSFUL); + } } tls_session -> nx_secure_tls_local_sequence_number[0]++; } diff --git a/nx_secure/src/nx_secure_tls_send_server_key_exchange.c b/nx_secure/src/nx_secure_tls_send_server_key_exchange.c index deb981c4..d1208452 100644 --- a/nx_secure/src/nx_secure_tls_send_server_key_exchange.c +++ b/nx_secure/src/nx_secure_tls_send_server_key_exchange.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_server_key_exchange PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -51,9 +51,8 @@ /* */ /* CALLS */ /* */ -/* _nx_secure_tlx_ecc_generate_keys Generate keys for ECC exchange*/ -/* [nx_crypto_init] Initialize Crypto Method */ -/* [nx_crypto_operation] Crypto operation */ +/* [nx_secure_generate_server_key_exchange] */ +/* Generate ServerKeyExchange */ /* */ /* CALLED BY */ /* */ @@ -68,35 +67,21 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_server_key_exchange(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet) { -UINT length; +#ifndef NX_SECURE_TLS_SERVER_DISABLED +ULONG length; const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite; -#if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) UINT status; -#endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ +VOID *tls_ecc_curves = NX_NULL; +UCHAR tls_1_3 = 0; -#if defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) -UCHAR *packet_buffer; -#endif /* defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) || defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) || defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) */ - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES -USHORT identity_length; -UCHAR *identity; -#endif - -#if defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) -USHORT named_curve; -NX_CRYPTO_METHOD *crypto_method; -NX_CRYPTO_EXTENDED_OUTPUT extended_output; -#endif /* defined(NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE) */ - -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; -#endif /* Build up the server key exchange message. Structure: @@ -114,112 +99,30 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; length = 0; - /* In the future, any Diffie-Hellman-based ciphersuites will populate this message with key - data. RSA ciphersuites do not use this message. */ - -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - - /* Get a pointer to fill our packet. */ - packet_buffer = send_packet -> nx_packet_append_ptr; - - /* Check for PSK ciphersuites. */ - if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK) - { - /* If PSK is being used, the server sends an identity value to the client so - the client can respond with the appropriate PSK. */ - - /* Get identity hint and length. */ - identity = tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint; - identity_length = (USHORT)tls_session -> nx_secure_tls_credentials.nx_secure_tls_psk_store[0].nx_secure_tls_psk_id_hint_size; - - if ((identity_length + 2u) > ((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)packet_buffer)) - { - - /* Packet buffer too small. */ - return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); - } - - /* Use identity hint length for key data length. */ - packet_buffer[length] = (UCHAR)((identity_length & 0xFF00) >> 8); - packet_buffer[length + 1] = (UCHAR)(identity_length & 0x00FF); - length = (USHORT)(length + 2); - - /* Extract the identity hint and put it into the packet buffer. */ - NX_SECURE_MEMCPY(&packet_buffer[length], identity, identity_length); /* Use case of memcpy is verified. */ - - /* Advance our total length. */ - length = (USHORT)(length + identity_length); - } +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + tls_ecc_curves = &tls_session -> nx_secure_tls_ecc; #endif -#ifdef NX_SECURE_ENABLE_ECJPAKE_CIPHERSUITE - - /* Check for ECJ-PAKE ciphersuites. */ - if (ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECJPAKE) - { - - /* Get a pointer to fill our packet. */ - packet_buffer = send_packet -> nx_packet_append_ptr; - - if (((ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(&packet_buffer[length])) < 3) - { - - /* Packet buffer too small. */ - return(NX_SECURE_TLS_PACKET_BUFFER_TOO_SMALL); - } - - /* ECCurveType: named_curve (3). */ - packet_buffer[length] = 3; - length += 1; - - /* NamedCurve: secp256r1 (23) */ - named_curve = (USHORT)NX_CRYPTO_EC_SECP256R1; - packet_buffer[length] = (UCHAR)((named_curve >> 8) & 0xFF); - packet_buffer[length + 1] = (UCHAR)(named_curve & 0xFF); - length += 2; - - extended_output.nx_crypto_extended_output_data = &packet_buffer[length]; - extended_output.nx_crypto_extended_output_length_in_byte = - (ULONG)send_packet -> nx_packet_data_end - (ULONG)&packet_buffer[length]; - extended_output.nx_crypto_extended_output_actual_size = 0; - - crypto_method = (NX_CRYPTO_METHOD*)ciphersuite -> nx_secure_tls_public_auth; - status = crypto_method -> nx_crypto_operation(NX_CRYPTO_ECJPAKE_SERVER_KEY_EXCHANGE_GENERATE, - &tls_session -> nx_secure_public_auth_handler, - crypto_method, - NX_NULL, 0, - NX_NULL, 0, NX_NULL, - (UCHAR *)&extended_output, - sizeof(extended_output), - tls_session -> nx_secure_public_auth_metadata_area, - tls_session -> nx_secure_public_auth_metadata_size, - NX_NULL, NX_NULL); - if (status) - { - return(status); - } - length += extended_output.nx_crypto_extended_output_actual_size; - } +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + tls_1_3 = tls_session -> nx_secure_tls_1_3; #endif -#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - /* Check for ECDHE ciphersuites. */ - if (ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE) + status = tls_session -> nx_secure_generate_server_key_exchange(ciphersuite, tls_session -> nx_secure_tls_protocol_version, tls_1_3, + tls_session -> nx_secure_tls_crypto_table, &tls_session -> nx_secure_tls_handshake_hash, + &tls_session -> nx_secure_tls_key_material, &tls_session -> nx_secure_tls_credentials, + send_packet -> nx_packet_append_ptr, + (ULONG)(send_packet -> nx_packet_data_end) - (ULONG)(send_packet -> nx_packet_append_ptr), + &length, tls_session -> nx_secure_public_cipher_metadata_area, + tls_session -> nx_secure_public_cipher_metadata_size, + tls_session -> nx_secure_public_auth_metadata_area, + tls_session -> nx_secure_public_auth_metadata_size, + tls_ecc_curves); + + if (status) { - ecdhe_data = (NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *)tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data; - packet_buffer = send_packet -> nx_packet_append_ptr; - length = (UINT)(send_packet->nx_packet_data_end - send_packet->nx_packet_append_ptr); - - status = _nx_secure_tls_ecc_generate_keys(tls_session, ecdhe_data -> nx_secure_tls_ecdhe_named_curve, NX_TRUE, - packet_buffer, &length, ecdhe_data); - - if (status != NX_SUCCESS) - { - return(status); - } + return(status); } -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ /* Finally, we have a complete length and can adjust our packet accordingly. */ @@ -227,5 +130,10 @@ NX_SECURE_TLS_ECDHE_HANDSHAKE_DATA *ecdhe_data; send_packet -> nx_packet_length = send_packet -> nx_packet_length + length; return(NX_SECURE_TLS_SUCCESS); +#else + NX_PARAMETER_NOT_USED(tls_session); + NX_PARAMETER_NOT_USED(send_packet); + return(NX_SECURE_TLS_INVALID_STATE); +#endif } diff --git a/nx_secure/src/nx_secure_tls_send_serverhello.c b/nx_secure/src/nx_secure_tls_send_serverhello.c index 66049bc8..8ab3a460 100644 --- a/nx_secure/src/nx_secure_tls_send_serverhello.c +++ b/nx_secure/src/nx_secure_tls_send_serverhello.c @@ -47,7 +47,7 @@ const UCHAR _nx_secure_tls_1_1_random[8] = /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_serverhello PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -85,10 +85,16 @@ const UCHAR _nx_secure_tls_1_1_random[8] = /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_serverhello(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET *send_packet) { +#ifndef NX_SECURE_TLS_SERVER_DISABLED ULONG length; UINT gmt_time; UINT random_value; @@ -134,7 +140,7 @@ UINT status; } NX_CHANGE_ULONG_ENDIAN(gmt_time); - NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, (UCHAR *)&gmt_time, sizeof(gmt_time)); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ #if (NX_SECURE_TLS_TLS_1_3_ENABLED) if (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_SEND_HELLO_RETRY) @@ -187,7 +193,7 @@ UINT status; } /* Copy the random data into the packet. */ - NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, + NX_SECURE_MEMCPY(&packet_buffer[length], tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random, /* lgtm[cpp/banned-api-usage-required-any] */ sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random)); /* Use case of memcpy is verified. */ length += sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_random); @@ -243,6 +249,17 @@ UINT status; send_packet -> nx_packet_append_ptr = send_packet -> nx_packet_append_ptr + length; send_packet -> nx_packet_length = send_packet -> nx_packet_length + length; - return(status); + return(status); +#else + + NX_PARAMETER_NOT_USED(send_packet); + + /* If TLS Server is disabled and we have processed a ClientKeyExchange, something is wrong... */ + tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_ERROR; + + /* Server is disabled, we shouldn't be sending a ServerHello - error! */ + return(NX_SECURE_TLS_INVALID_STATE); +#endif + } diff --git a/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c b/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c index 0f5b2574..0339c209 100644 --- a/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c +++ b/nx_secure/src/nx_secure_tls_send_serverhello_extensions.c @@ -32,7 +32,7 @@ static UINT _nx_secure_tls_send_serverhello_sec_reneg_extension(NX_SECURE_TLS_SE ULONG available_size); #endif -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) static UINT _nx_secure_tls_send_serverhello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_offset, USHORT *extension_length, @@ -56,7 +56,7 @@ static UINT _nx_secure_tls_send_serverhello_psk_extension(NX_SECURE_TLS_SESSION /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_serverhello_extensions PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -96,6 +96,9 @@ static UINT _nx_secure_tls_send_serverhello_psk_extension(NX_SECURE_TLS_SESSION /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unused code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_send_serverhello_extensions(NX_SECURE_TLS_SESSION *tls_session, @@ -104,7 +107,7 @@ UINT _nx_secure_tls_send_serverhello_extensions(NX_SECURE_TLS_SESSION *tls_sessi { ULONG length = *packet_offset; UCHAR *extension_offset; -#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) || (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) || ((NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED)) USHORT extension_length = 0; #endif /* !defined(NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION) || (NX_SECURE_TLS_TLS_1_3_ENABLED) */ USHORT total_extensions_length; @@ -130,7 +133,7 @@ UINT status = NX_SUCCESS; total_extensions_length = 0; #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) /* Renegotiation is deprecated in TLS 1.3 so don't send extension. */ if(!tls_session->nx_secure_tls_1_3) #endif @@ -148,7 +151,7 @@ UINT status = NX_SUCCESS; #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) if(tls_session->nx_secure_tls_1_3) { @@ -198,7 +201,6 @@ UINT status = NX_SUCCESS; { /* No extensions written, back up our pointer and length. */ length -= 2; - packet_buffer = extension_offset; } else { @@ -363,9 +365,9 @@ UINT data_length; offset++; /* Copy the verify data into the packet. */ - NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_remote_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_remote_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ offset += NX_SECURE_TLS_FINISHED_HASH_SIZE; - NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_local_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(&packet_buffer[offset], tls_session -> nx_secure_tls_local_verify_data, NX_SECURE_TLS_FINISHED_HASH_SIZE); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ offset += NX_SECURE_TLS_FINISHED_HASH_SIZE; } @@ -427,7 +429,7 @@ UINT data_length; /* resulting in version 6.1 */ /* */ /**************************************************************************/ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) static UINT _nx_secure_tls_send_serverhello_supported_versions_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_offset, USHORT *extension_length, ULONG available_size) @@ -490,7 +492,7 @@ UINT data_length; /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_send_serverhello_key_share_extension PORTABLE C */ -/* 6.1 */ +/* 6.1.9 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -529,14 +531,20 @@ UINT data_length; /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), fixed */ +/* compilation issue with */ +/* TLS 1.3 and disabling TLS */ +/* server, */ +/* resulting in version 6.1.9 */ /* */ /**************************************************************************/ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && !defined(NX_SECURE_TLS_SERVER_DISABLED) static UINT _nx_secure_tls_send_serverhello_key_share_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_offset, USHORT *extension_length, ULONG available_size) { +#ifndef NX_SECURE_TLS_SERVER_DISABLED ULONG offset; ULONG length_offset; USHORT ext; @@ -716,6 +724,10 @@ USHORT named_curve; return(NX_SUCCESS); +#else + /* Server is disabled, we shouldn't be processing a ClientHello - error! */ + return(NX_SECURE_TLS_INVALID_STATE); +#endif } #endif @@ -765,7 +777,7 @@ USHORT named_curve; /* */ /**************************************************************************/ -#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined (NX_SECURE_ENABLE_PSK_CIPHERSUITES) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) && defined (NX_SECURE_ENABLE_PSK_CIPHERSUITES) && !defined(NX_SECURE_TLS_SERVER_DISABLED) static UINT _nx_secure_tls_send_serverhello_psk_extension(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, ULONG *packet_length, USHORT *extension_length, ULONG available_size) diff --git a/nx_secure/src/nx_secure_tls_server_certificate_find.c b/nx_secure/src/nx_secure_tls_server_certificate_find.c index 56386960..21fb4614 100644 --- a/nx_secure/src/nx_secure_tls_server_certificate_find.c +++ b/nx_secure/src/nx_secure_tls_server_certificate_find.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_server_certificate_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +70,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_server_certificate_find(NX_SECURE_TLS_SESSION *tls_session, @@ -80,6 +83,12 @@ UINT status; /* Find and return the certificate based on its ID. */ status = _nx_secure_x509_local_certificate_find(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, certificate, cert_id); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) + { + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + /* Return completion status. */ return(status); } diff --git a/nx_secure/src/nx_secure_tls_server_certificate_remove.c b/nx_secure/src/nx_secure_tls_server_certificate_remove.c index 62ae5eb8..54bab91f 100644 --- a/nx_secure/src/nx_secure_tls_server_certificate_remove.c +++ b/nx_secure/src/nx_secure_tls_server_certificate_remove.c @@ -32,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_server_certificate_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -69,6 +69,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_server_certificate_remove(NX_SECURE_TLS_SESSION *tls_session, UINT cert_id) @@ -79,6 +82,12 @@ UINT status; status = _nx_secure_x509_store_certificate_remove(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, NX_NULL, NX_SECURE_X509_CERT_LOCATION_LOCAL, cert_id); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) + { + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + /* Return completion status. */ return(status); } diff --git a/nx_secure/src/nx_secure_tls_server_handshake.c b/nx_secure/src/nx_secure_tls_server_handshake.c index 729410e2..6a747bea 100644 --- a/nx_secure/src/nx_secure_tls_server_handshake.c +++ b/nx_secure/src/nx_secure_tls_server_handshake.c @@ -31,7 +31,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_server_handshake PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -59,7 +59,6 @@ /* _nx_secure_tls_generate_keys Generate session keys */ /* _nx_secure_tls_handshake_hash_init Initialize Finished hash */ /* _nx_secure_tls_handshake_hash_update Update Finished hash */ -/* _nx_secure_tls_map_error_to_alert Map internal error to alert */ /* _nx_secure_tls_packet_allocate Allocate internal TLS packet */ /* _nx_secure_tls_process_client_key_exchange */ /* Process ClientKeyExchange */ @@ -69,7 +68,6 @@ /* Process handshake header */ /* _nx_secure_tls_process_remote_certificate */ /* Process server certificate */ -/* _nx_secure_tls_send_alert Send TLS alert */ /* _nx_secure_tls_send_certificate Send TLS certificate */ /* _nx_secure_tls_send_certificate_request */ /* Send TLS CertificateRequest */ @@ -99,6 +97,21 @@ /* fixed certificate buffer */ /* allocation, */ /* resulting in version 6.1 */ +/* 12-31-2020 Timothy Stapko Modified comment(s), */ +/* improved buffer length */ +/* verification, */ +/* resulting in version 6.1.3 */ +/* 02-02-2021 Timothy Stapko Modified comment(s), added */ +/* support for fragmented TLS */ +/* Handshake messages, */ +/* resulting in version 6.1.4 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), */ +/* removed duplicated alert, */ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* fixed handling of multiple */ +/* handshake messages, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR *packet_buffer, @@ -108,14 +121,11 @@ UINT _nx_secure_tls_server_handshake(NX_SECURE_TLS_SESSION *tls_session, UCHAR * UINT status; UINT temp_status; USHORT message_type; -USHORT header_bytes; +UINT header_bytes; UINT message_length; NX_PACKET *send_packet; NX_PACKET_POOL *packet_pool; UCHAR *packet_start; -UINT error_number; -UINT alert_number; -UINT alert_level; const NX_CRYPTO_METHOD *method_ptr = NX_NULL; /* Basic state machine for handshake: @@ -124,140 +134,131 @@ const NX_CRYPTO_METHOD *method_ptr = NX_NULL; * 3. Follow up with whatever actions are needed. */ - /* Save a pointer to the start of our packet for the hash that happens below. */ - packet_start = packet_buffer; - - _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); - - /* Check for fragmented records. */ - if((message_length + header_bytes) > data_length) + /* Loop through multiple messages in a single record. This can happen if the remote host + packs multiple handshake messages into a single TLS record. */ + while (data_length > 0) { - /* Incomplete record! We need to obtain the next fragment. */ - return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); - } - /* Advance the buffer pointer past the handshake header. */ - packet_buffer += header_bytes; + /* Save a pointer to the start of our packet for the hash that happens below. */ + packet_start = packet_buffer; - /* Get reference to the packet pool so we can allocate a packet for all send operations. */ - packet_pool = tls_session -> nx_secure_tls_packet_pool; + header_bytes = data_length; - /* We need to hash all of the handshake messages that we receive and send. If this message is a ClientHello, - then we need to initialize the hashes (TLS 1.1 uses both MD5 and SHA-1). The final hash is generated - in the "Finished" message. */ - if (message_type == NX_SECURE_TLS_CLIENT_HELLO) - { - /* Initialize the handshake hashes used for the Finished message. */ - _nx_secure_tls_handshake_hash_init(tls_session); - } + status = _nx_secure_tls_process_handshake_header(packet_buffer, &message_type, &header_bytes, &message_length); - /* Process the message itself information from the header. */ - status = NX_SECURE_TLS_SUCCESS; - switch (message_type) - { - case NX_SECURE_TLS_CLIENT_HELLO: - /* Client is establishing a TLS session with our server. */ - status = _nx_secure_tls_process_clienthello(tls_session, packet_buffer, message_length); - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO; - break; -#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY - case NX_SECURE_TLS_CERTIFICATE_MSG: - /* Client sent certificate message (in response to a request from us. Process it now. */ - status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, data_length); - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE; - break; - case NX_SECURE_TLS_CERTIFICATE_VERIFY: - /* Client has responded to a certificate request with a CertificateVerify message. */ - status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length); - - if(status == NX_SUCCESS) + if (status != NX_SECURE_TLS_SUCCESS) { - /* If remote certificate verification was a success, we have received credentials - from the remote host and may now pass Finished message processing once received. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; + return(status); } - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY; - break; -#endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */ - case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE: - /* Received a client key exchange message, meaning it is time to generate keys if we can. */ - status = _nx_secure_tls_process_client_key_exchange(tls_session, packet_buffer, message_length, NX_SECURE_TLS); - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE; - - if (status == NX_SECURE_TLS_SUCCESS) + /* Check for fragmented message. */ + if((message_length + header_bytes) > data_length) { - /* Generate our key material from the data collected thus far and put it all into our - socket structure. */ - status = _nx_secure_tls_generate_keys(tls_session); + /* Incomplete message! A single message is fragmented across several records. We need to obtain the next fragment. */ + tls_session -> nx_secure_tls_handshake_record_expected_length = message_length + header_bytes; + + tls_session -> nx_secure_tls_handshake_record_fragment_state = NX_SECURE_TLS_HANDSHAKE_RECEIVED_FRAGMENT; + + return(NX_SECURE_TLS_HANDSHAKE_FRAGMENT_RECEIVED); } - break; - case NX_SECURE_TLS_FINISHED: - /* Final handshake message from the client, process it (verify the client handshake hash). */ - status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length); - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE; - break; - case NX_SECURE_TLS_HELLO_VERIFY_REQUEST: - case NX_SECURE_TLS_HELLO_REQUEST: - case NX_SECURE_TLS_SERVER_HELLO: - case NX_SECURE_TLS_SERVER_KEY_EXCHANGE: - case NX_SECURE_TLS_CERTIFICATE_REQUEST: - case NX_SECURE_TLS_SERVER_HELLO_DONE: - case NX_SECURE_TLS_CERTIFICATE_URL: - case NX_SECURE_TLS_CERTIFICATE_STATUS: - default: - /* The message received was not a valid TLS server handshake message, send alert and return. */ - status = NX_SECURE_TLS_UNEXPECTED_MESSAGE; - break; - } - - /* Check for errors in processing messages. */ - if (status != NX_SECURE_TLS_SUCCESS) - { - /* If we encountered an error in message processing set the state to the error condition. */ - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR; - } - else - { - /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them, - we do not worry about them here because these are only messages received from the client at this point. - Hashes include the handshake layer header but not the record layer header. */ - _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes)); - } - - /* Now take any actions based on state set in the message processing. */ - switch (tls_session -> nx_secure_tls_server_state) - { - case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO: - /* We have received and processed a client hello. Now respond to the client appropriately. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - if (status != NX_SUCCESS) + /* Advance the buffer pointer past the handshake header. */ + packet_buffer += header_bytes; + + /* Get reference to the packet pool so we can allocate a packet for all send operations. */ + packet_pool = tls_session -> nx_secure_tls_packet_pool; + + /* We need to hash all of the handshake messages that we receive and send. If this message is a ClientHello, + then we need to initialize the hashes (TLS 1.1 uses both MD5 and SHA-1). The final hash is generated + in the "Finished" message. */ + if (message_type == NX_SECURE_TLS_CLIENT_HELLO) { - break; + /* Initialize the handshake hashes used for the Finished message. */ + _nx_secure_tls_handshake_hash_init(tls_session); } - status = _nx_secure_tls_send_serverhello(tls_session, send_packet); + /* Reduce total length by the size of this message. */ + data_length -= (message_length + header_bytes); - if (status != NX_SUCCESS) + /* Process the message itself information from the header. */ + status = NX_SECURE_TLS_SUCCESS; + switch (message_type) { + case NX_SECURE_TLS_CLIENT_HELLO: + /* Client is establishing a TLS session with our server. */ + status = _nx_secure_tls_process_clienthello(tls_session, packet_buffer, message_length); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_SEND_HELLO; break; - } +#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY + case NX_SECURE_TLS_CERTIFICATE_MSG: + /* Client sent certificate message (in response to a request from us. Process it now. */ + status = _nx_secure_tls_process_remote_certificate(tls_session, packet_buffer, message_length, data_length); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE; + break; + case NX_SECURE_TLS_CERTIFICATE_VERIFY: + /* Client has responded to a certificate request with a CertificateVerify message. */ + status = _nx_secure_tls_process_certificate_verify(tls_session, packet_buffer, message_length); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); + if(status == NX_SUCCESS) + { + /* If remote certificate verification was a success, we have received credentials + from the remote host and may now pass Finished message processing once received. */ + tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; + } - if (status != NX_SUCCESS) - { + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY; + break; +#endif /* NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY */ + case NX_SECURE_TLS_CLIENT_KEY_EXCHANGE: + /* Received a client key exchange message, meaning it is time to generate keys if we can. */ + status = _nx_secure_tls_process_client_key_exchange(tls_session, packet_buffer, message_length, NX_SECURE_TLS); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE; + + if (status == NX_SECURE_TLS_SUCCESS) + { + /* Generate our key material from the data collected thus far and put it all into our + socket structure. */ + status = _nx_secure_tls_generate_keys(tls_session); + } + break; + case NX_SECURE_TLS_FINISHED: + /* Final handshake message from the client, process it (verify the client handshake hash). */ + status = _nx_secure_tls_process_finished(tls_session, packet_buffer, message_length); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE; + break; + case NX_SECURE_TLS_HELLO_VERIFY_REQUEST: + case NX_SECURE_TLS_HELLO_REQUEST: + case NX_SECURE_TLS_SERVER_HELLO: + case NX_SECURE_TLS_SERVER_KEY_EXCHANGE: + case NX_SECURE_TLS_CERTIFICATE_REQUEST: + case NX_SECURE_TLS_SERVER_HELLO_DONE: + case NX_SECURE_TLS_CERTIFICATE_URL: + case NX_SECURE_TLS_CERTIFICATE_STATUS: + default: + /* The message received was not a valid TLS server handshake message, send alert and return. */ + status = NX_SECURE_TLS_UNEXPECTED_MESSAGE; break; } - NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL); + /* Check for errors in processing messages. */ + if (status != NX_SECURE_TLS_SUCCESS) + { + /* If we encountered an error in message processing set the state to the error condition. */ + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_ERROR; + } + else + { + /* Hash this handshake message. We do not hash HelloRequest messages, but since only the server will send them, + we do not worry about them here because these are only messages received from the client at this point. + Hashes include the handshake layer header but not the record layer header. */ + _nx_secure_tls_handshake_hash_update(tls_session, packet_start, (UINT)(message_length + header_bytes)); + } -#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - /* For PSK ciphersuites, don't send the certificate message. */ - if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK) + /* Now take any actions based on state set in the message processing. */ + switch (tls_session -> nx_secure_tls_server_state) { -#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ + case NX_SECURE_TLS_SERVER_STATE_SEND_HELLO: + /* We have received and processed a client hello. Now respond to the client appropriately. */ status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); if (status != NX_SUCCESS) @@ -265,55 +266,108 @@ const NX_CRYPTO_METHOD *method_ptr = NX_NULL; break; } - _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option); + status = _nx_secure_tls_send_serverhello(tls_session, send_packet); + + if (status != NX_SUCCESS) + { + break; + } + + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO, wait_option); + if (status != NX_SUCCESS) { break; } + NX_ASSERT(tls_session -> nx_secure_tls_session_ciphersuite != NX_NULL); + #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - } + /* For PSK ciphersuites, don't send the certificate message. */ + if (tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm != NX_CRYPTO_KEY_EXCHANGE_PSK) + { +#endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + + if (status != NX_SUCCESS) + { + break; + } + + _nx_secure_tls_send_certificate(tls_session, send_packet, wait_option); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_MSG, wait_option); + if (status != NX_SUCCESS) + { + break; + } + +#ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES + } #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ #if defined(NX_SECURE_ENABLE_ECC_CIPHERSUITE) || defined(NX_SECURE_ENABLE_PSK_CIPHERSUITES) - if (NX_FALSE + if (NX_FALSE #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE - || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE + || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_cipher -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_ECDHE #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ #ifdef NX_SECURE_ENABLE_PSK_CIPHERSUITES - || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK + || tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_public_auth -> nx_crypto_algorithm == NX_CRYPTO_KEY_EXCHANGE_PSK #endif /* NX_SECURE_ENABLE_PSK_CIPHERSUITES */ - ) - { - /* PSK and ECDHE ciphersuites use the ServerKeyExchange message to send cryptographic information. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - - if (status != NX_SUCCESS) + ) { - break; + /* PSK and ECDHE ciphersuites use the ServerKeyExchange message to send cryptographic information. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + + if (status != NX_SUCCESS) + { + break; + } + + /* This is a PSK ciphersuite so we always send a ServerKeyExchange message. */ + status = _nx_secure_tls_send_server_key_exchange(tls_session, send_packet); + if (status != NX_SUCCESS) + { + break; + } + + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_KEY_EXCHANGE, wait_option); + if (status != NX_SUCCESS) + { + break; + } } +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE || NX_CRYPTO_KEY_EXCHANGE_PSK */ - /* This is a PSK ciphersuite so we always send a ServerKeyExchange message. */ - status = _nx_secure_tls_send_server_key_exchange(tls_session, send_packet); - if (status != NX_SUCCESS) +#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY + /* Application has requested that we request and verify the remote Client certificate. */ + if (tls_session -> nx_secure_tls_verify_client_certificate) { - break; + /* Allocate a packet for our certificate request message. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + + if (status != NX_SUCCESS) + { + break; + } + + /* Populate our packet with the desired message (CertificateRequest). */ + status = _nx_secure_tls_send_certificate_request(tls_session, send_packet); + NX_ASSERT(status == NX_SUCCESS); + + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option); + if (status != NX_SUCCESS) + { + break; + } } - - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_KEY_EXCHANGE, wait_option); - if (status != NX_SUCCESS) + else +#endif { - break; + /* Server is not expecting credentials, so indicate that we have received the client's credentials + to pass Finished processing. */ + tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; } - } -#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE || NX_CRYPTO_KEY_EXCHANGE_PSK */ - -#ifdef NX_SECURE_ENABLE_CLIENT_CERTIFICATE_VERIFY - /* Application has requested that we request and verify the remote Client certificate. */ - if (tls_session -> nx_secure_tls_verify_client_certificate) - { - /* Allocate a packet for our certificate request message. */ + /* Allocate a new packet for the ServerHelloDone. */ status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); if (status != NX_SUCCESS) @@ -321,193 +375,148 @@ const NX_CRYPTO_METHOD *method_ptr = NX_NULL; break; } - /* Populate our packet with the desired message (CertificateRequest). */ - status = _nx_secure_tls_send_certificate_request(tls_session, send_packet); - NX_ASSERT(status == NX_SUCCESS); + /* Server hello done message is 0 bytes, but it still has a TLS header so don't modify the length here. */ + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO_DONE, wait_option); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_CERTIFICATE_REQUEST, wait_option); if (status != NX_SUCCESS) { break; } - } - else -#endif - { - /* Server is not expecting credentials, so indicate that we have received the client's credentials - to pass Finished processing. */ - tls_session -> nx_secure_tls_received_remote_credentials = NX_TRUE; - } - /* Allocate a new packet for the ServerHelloDone. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - if (status != NX_SUCCESS) - { - break; - } - /* Server hello done message is 0 bytes, but it still has a TLS header so don't modify the length here. */ - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_SERVER_HELLO_DONE, wait_option); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT; - if (status != NX_SUCCESS) - { break; - } - - - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HELLO_SENT; - - break; - case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE: - /* We processed the certificate above, do nothing. */ - break; - case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY: - /* We processed the certificate above, do nothing. */ - break; - case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE: - break; - case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE: + case NX_SECURE_TLS_SERVER_STATE_CLIENT_CERTIFICATE: + /* We processed the certificate above, do nothing. */ + break; + case NX_SECURE_TLS_SERVER_STATE_CERTIFICATE_VERIFY: + /* We processed the certificate above, do nothing. */ + break; + case NX_SECURE_TLS_SERVER_STATE_KEY_EXCHANGE: + break; + case NX_SECURE_TLS_SERVER_STATE_FINISH_HANDSHAKE: - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); + /* Release the protection before suspending on nx_packet_allocate. */ + tx_mutex_put(&_nx_secure_tls_protection); - /* We have received everything we need to complete the handshake and keys have been - * generated above. Now end the handshake with a ChangeCipherSpec (indicating following - * messages are encrypted) and the encrypted Finished message. */ + /* We have received everything we need to complete the handshake and keys have been + * generated above. Now end the handshake with a ChangeCipherSpec (indicating following + * messages are encrypted) and the encrypted Finished message. */ - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); + status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); + /* Get the protection after nx_packet_allocate. */ + tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - if (status != NX_SUCCESS) - { - break; - } + if (status != NX_SUCCESS) + { + break; + } - _nx_secure_tls_send_changecipherspec(tls_session, send_packet); + _nx_secure_tls_send_changecipherspec(tls_session, send_packet); - /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */ - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option); + /* ChangeCipherSpec is NOT a handshake message, so send as a normal TLS record. */ + status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_CHANGE_CIPHER_SPEC, wait_option); - if (status != NX_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - break; - } + if (status != NX_SUCCESS) + { + nx_secure_tls_packet_release(send_packet); + break; + } - /* Reset the sequence number now that we are starting a new session. */ - NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number)); + /* Reset the sequence number now that we are starting a new session. */ + NX_SECURE_MEMSET(tls_session -> nx_secure_tls_local_sequence_number, 0, sizeof(tls_session -> nx_secure_tls_local_sequence_number)); - /* The local session is now active since we sent the changecipherspec message. - NOTE: Do not set the keys until after the changecipherspec message has been passed to the send record - routine - this call causes encryption and hashing to happen on records. ChangeCipherSpec should be the last - un-encrypted/un-hashed record sent. For a renegotiation handshake, CCS is the last message encrypted using - the original session keys. */ + /* The local session is now active since we sent the changecipherspec message. + NOTE: Do not set the keys until after the changecipherspec message has been passed to the send record + routine - this call causes encryption and hashing to happen on records. ChangeCipherSpec should be the last + un-encrypted/un-hashed record sent. For a renegotiation handshake, CCS is the last message encrypted using + the original session keys. */ - /* Set our local session keys since we sent a CCS message. */ - status = _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL); + /* Set our local session keys since we sent a CCS message. */ + status = _nx_secure_tls_session_keys_set(tls_session, NX_SECURE_TLS_KEY_SET_LOCAL); - if (status != NX_SUCCESS) - { - break; - } + if (status != NX_SUCCESS) + { + break; + } - /* We processed the incoming finished message above, so now we can send our own finished message. */ - status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); - if (status != NX_SUCCESS) - { - break; - } + /* We processed the incoming finished message above, so now we can send our own finished message. */ + status = _nx_secure_tls_allocate_handshake_packet(tls_session, packet_pool, &send_packet, wait_option); + if (status != NX_SUCCESS) + { + break; + } - _nx_secure_tls_send_finished(tls_session, send_packet); - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option); + _nx_secure_tls_send_finished(tls_session, send_packet); + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_FINISHED, wait_option); - /* For server, cleanup hash handler after sent the finished message to server. */ + /* For server, cleanup hash handler after sent the finished message to server. */ #if (NX_SECURE_TLS_TLS_1_2_ENABLED) - method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method; + method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha256_method; - if (method_ptr -> nx_crypto_cleanup != NX_NULL) - { - temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata); - if(temp_status != NX_CRYPTO_SUCCESS) + if (method_ptr -> nx_crypto_cleanup != NX_NULL) { - status = temp_status; - } + temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha256_metadata); + if(temp_status != NX_CRYPTO_SUCCESS) + { + status = temp_status; + } - } + } #endif /* (NX_SECURE_TLS_TLS_1_2_ENABLED) */ #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) - method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; - if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL) - { - temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata); - if(temp_status != NX_CRYPTO_SUCCESS) + method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_md5_method; + if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL) { - status = temp_status; - } + temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata); + if(temp_status != NX_CRYPTO_SUCCESS) + { + status = temp_status; + } - } + } - method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method; - if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL) - { - temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata); - if(temp_status != NX_CRYPTO_SUCCESS) + method_ptr = tls_session -> nx_secure_tls_crypto_table -> nx_secure_tls_handshake_hash_sha1_method; + if (method_ptr != NX_NULL && method_ptr -> nx_crypto_cleanup != NX_NULL) { - status = temp_status; - } + temp_status = method_ptr -> nx_crypto_cleanup(tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata); + if(temp_status != NX_CRYPTO_SUCCESS) + { + status = temp_status; + } - } + } #endif /* (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) */ - tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED; - - break; - default: /* NX_SECURE_TLS_SERVER_STATE_ERROR */ - /* Default is to break out of the switch because either we encountered an error or - we are in an invalid state. DO NOT change the value of "status" here because - we need its value in the alert processing below. NOTE: we should never - get to this branch with status == NX_SUCCESS because the state will only - be set to NX_SECURE_TLS_SERVER_STATE_ERROR if status indicates an error. */ - NX_ASSERT(status != NX_SUCCESS); - break; - } - - - /* If we have an error at this point, we have experienced a problem in processing or sending - handshake messages, which is some type of internal issue. Send an alert - back to the remote host indicating the error. */ - if (status != NX_SUCCESS) - { - /* Get our alert number and level from our status. */ - error_number = status; - _nx_secure_tls_map_error_to_alert(error_number, &alert_number, &alert_level); - - /* Release the protection before suspending on nx_packet_allocate. */ - tx_mutex_put(&_nx_secure_tls_protection); - - status = _nx_secure_tls_packet_allocate(tls_session, packet_pool, &send_packet, wait_option); + tls_session -> nx_secure_tls_server_state = NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED; - /* Get the protection after nx_packet_allocate. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - - if (status == NX_SUCCESS) + break; + default: /* NX_SECURE_TLS_SERVER_STATE_ERROR */ + /* Default is to break out of the switch because either we encountered an error or + we are in an invalid state. DO NOT change the value of "status" here because + we need its value in the alert processing below. NOTE: we should never + get to this branch with status == NX_SUCCESS because the state will only + be set to NX_SECURE_TLS_SERVER_STATE_ERROR if status indicates an error. */ + NX_ASSERT(status != NX_SUCCESS); + break; + } + + /* If we have an error at this point, we have experienced a problem in sending + handshake messages, which is some type of internal issue. */ + if (status != NX_SUCCESS) { - _nx_secure_tls_send_alert(tls_session, send_packet, (UCHAR)alert_number, (UCHAR)alert_level); - status = _nx_secure_tls_send_record(tls_session, send_packet, NX_SECURE_TLS_ALERT, wait_option); - if (status != NX_SECURE_TLS_SUCCESS) - { - nx_secure_tls_packet_release(send_packet); - } + return(status); } + + /* Advance the buffer pointer past the message. */ + packet_buffer += message_length; + } /* End while. */ - return(error_number); - } - - return(status); + return(NX_SUCCESS); #else /* TLS Server disabled. */ /* We don't use the parameters since this is an error case. */ diff --git a/nx_secure/src/nx_secure_tls_session_create_ext.c b/nx_secure/src/nx_secure_tls_session_create_ext.c index f5393c3e..ded70287 100644 --- a/nx_secure/src/nx_secure_tls_session_create_ext.c +++ b/nx_secure/src/nx_secure_tls_session_create_ext.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_create_ext PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -82,6 +82,16 @@ /* added ECC initialization, */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), and */ +/* added null pointer checking,*/ +/* resulting in version 6.1.10 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* added null pointer checking,*/ +/* removed unused code, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and added*/ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ @@ -527,6 +537,11 @@ ULONG metadata_size_sha256 = 0; /* Coming from the old-style API. Don't allocate crypto table. */ crypto_table = tls_session->nx_secure_tls_crypto_table; + if (crypto_table == NX_NULL) + { + return(NX_PTR_ERROR); + } + /* Start by assuming all versions are enabled, remove versions without the appropriate ciphers. */ tls_session->nx_secure_tls_supported_versions = NX_SECURE_TLS_BITFIELD_VERSIONS_ALL; } @@ -631,19 +646,15 @@ ULONG metadata_size_sha256 = 0; supported_groups[i] = (USHORT)(curve_crypto_list[i] -> nx_crypto_algorithm & 0xFFFF); } - status = _nx_secure_tls_ecc_initialize(tls_session, supported_groups, ecc_curves_count, (const NX_CRYPTO_METHOD **)curve_crypto_list); - if (status != NX_SUCCESS) - { - return(status); - } + _nx_secure_tls_ecc_initialize(tls_session, supported_groups, ecc_curves_count, (const NX_CRYPTO_METHOD **)curve_crypto_list); } #endif } /* Get working pointers to our crypto methods. */ - ciphersuite_table = crypto_table->nx_secure_tls_ciphersuite_lookup_table; - ciphersuite_table_size = crypto_table->nx_secure_tls_ciphersuite_lookup_table_size; + ciphersuite_table = crypto_table -> nx_secure_tls_ciphersuite_lookup_table; + ciphersuite_table_size = crypto_table -> nx_secure_tls_ciphersuite_lookup_table_size; cert_crypto = crypto_table -> nx_secure_tls_x509_cipher_table; cert_crypto_size = crypto_table -> nx_secure_tls_x509_cipher_table_size; @@ -651,31 +662,42 @@ ULONG metadata_size_sha256 = 0; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) crypto_method_md5 = crypto_table -> nx_secure_tls_handshake_hash_md5_method; crypto_method_sha1 = crypto_table -> nx_secure_tls_handshake_hash_sha1_method; - metadata_size_md5 = crypto_method_md5 -> nx_crypto_metadata_area_size; - metadata_size_sha1 = crypto_method_sha1 -> nx_crypto_metadata_area_size; - /* Align metadata size to four bytes. */ - if (metadata_size_md5 & 0x3) + if (crypto_method_md5 != NX_NULL) { - metadata_size_md5 += 4 - (metadata_size_md5 & 0x3); + metadata_size_md5 = crypto_method_md5 -> nx_crypto_metadata_area_size; + + /* Align metadata size to four bytes. */ + if (metadata_size_md5 & 0x3) + { + metadata_size_md5 += 4 - (metadata_size_md5 & 0x3); + } } - if (metadata_size_sha1 & 0x3) + if (crypto_method_sha1 != NX_NULL) { - metadata_size_sha1 += 4 - (metadata_size_sha1 & 0x3); + metadata_size_sha1 = crypto_method_sha1 -> nx_crypto_metadata_area_size; + + if (metadata_size_sha1 & 0x3) + { + metadata_size_sha1 += 4 - (metadata_size_sha1 & 0x3); + } } #endif #if (NX_SECURE_TLS_TLS_1_2_ENABLED) crypto_method_sha256 = crypto_table -> nx_secure_tls_handshake_hash_sha256_method; - metadata_size_sha256 = crypto_method_sha256 -> nx_crypto_metadata_area_size; - - if (metadata_size_sha256 & 0x3) + if (crypto_method_sha256 != NX_NULL) { - metadata_size_sha256 += 4 - (metadata_size_sha256 & 0x3); + metadata_size_sha256 = crypto_method_sha256 -> nx_crypto_metadata_area_size; + + if (metadata_size_sha256 & 0x3) + { + metadata_size_sha256 += 4 - (metadata_size_sha256 & 0x3); + } } #endif #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - tls_session->nx_secure_tls_1_3_supported = NX_FALSE; + tls_session -> nx_secure_tls_1_3_supported = NX_FALSE; #endif /* Loop through the ciphersuite table and find the largest metadata for each type of cipher. */ @@ -751,9 +773,12 @@ ULONG metadata_size_sha256 = 0; max_handshake_hash_scratch_size = metadata_size_md5 + metadata_size_sha1; } - if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size) + if (crypto_table -> nx_secure_tls_prf_1_method != NX_NULL) { - max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size; + if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size) + { + max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_prf_1_method -> nx_crypto_metadata_area_size; + } } } #endif @@ -766,17 +791,25 @@ ULONG metadata_size_sha256 = 0; max_handshake_hash_scratch_size = metadata_size_sha256; } - if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_sha256_method -> nx_crypto_metadata_area_size) + if ((crypto_table -> nx_secure_tls_prf_sha256_method != NX_NULL) && + (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_prf_sha256_method -> nx_crypto_metadata_area_size)) { max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_prf_sha256_method -> nx_crypto_metadata_area_size; } #endif #if (NX_SECURE_TLS_TLS_1_3_ENABLED) - max_handshake_hash_scratch_size += crypto_table -> nx_secure_tls_hmac_method -> nx_crypto_metadata_area_size; - if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size) + if (crypto_table -> nx_secure_tls_hmac_method != NX_NULL) + { + max_handshake_hash_scratch_size += crypto_table -> nx_secure_tls_hmac_method -> nx_crypto_metadata_area_size; + } + + if (crypto_table -> nx_secure_tls_hkdf_method != NX_NULL) { - max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size; + if (max_tls_prf_metadata_size < crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size) + { + max_tls_prf_metadata_size = crypto_table -> nx_secure_tls_hkdf_method -> nx_crypto_metadata_area_size; + } } #endif @@ -851,11 +884,11 @@ ULONG metadata_size_sha256 = 0; #if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) if (tls_session -> nx_secure_tls_supported_versions & (USHORT)(NX_SECURE_TLS_BITFIELD_VERSION_1_0 | NX_SECURE_TLS_BITFIELD_VERSION_1_1)) { - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata = &metadata_area[offset]; + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata = &metadata_area[offset]; tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_md5_metadata_size = metadata_size_md5; offset += metadata_size_md5; - tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata = &metadata_area[offset]; + tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata = &metadata_area[offset]; tls_session -> nx_secure_tls_handshake_hash.nx_secure_tls_handshake_hash_sha1_metadata_size = metadata_size_sha1; offset += metadata_size_sha1; } @@ -897,7 +930,6 @@ ULONG metadata_size_sha256 = 0; /* TLS PRF metadata. */ tls_session -> nx_secure_tls_prf_metadata_area = &metadata_area[offset]; tls_session -> nx_secure_tls_prf_metadata_size = max_tls_prf_metadata_size; - offset += max_tls_prf_metadata_size; /* Place the new TLS control block on the list of created TLS. */ if (_nx_secure_tls_created_ptr) @@ -927,7 +959,7 @@ ULONG metadata_size_sha256 = 0; #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION #if (NX_SECURE_TLS_TLS_1_3_ENABLED) /* Flag to indicate when a session renegotiation is enabled. Enabled by default. */ - if(tls_session->nx_secure_tls_1_3) + if (tls_session -> nx_secure_tls_1_3) { tls_session -> nx_secure_tls_renegotation_enabled = NX_FALSE; } @@ -938,6 +970,33 @@ ULONG metadata_size_sha256 = 0; } #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ + /* Set the secret generation functions to the default implementation. */ + tls_session -> nx_secure_generate_premaster_secret = _nx_secure_generate_premaster_secret; + tls_session -> nx_secure_generate_master_secret = _nx_secure_generate_master_secret; + tls_session -> nx_secure_generate_session_keys = _nx_secure_generate_session_keys; + tls_session -> nx_secure_session_keys_set = _nx_secure_session_keys_set; +#ifndef NX_SECURE_TLS_CLIENT_DISABLED + tls_session -> nx_secure_process_server_key_exchange = _nx_secure_process_server_key_exchange; + tls_session -> nx_secure_generate_client_key_exchange = _nx_secure_generate_client_key_exchange; +#endif +#ifndef NX_SECURE_TLS_SERVER_DISABLED + tls_session -> nx_secure_process_client_key_exchange = _nx_secure_process_client_key_exchange; + tls_session -> nx_secure_generate_server_key_exchange = _nx_secure_generate_server_key_exchange; +#endif + tls_session -> nx_secure_verify_mac = _nx_secure_verify_mac; + tls_session -> nx_secure_remote_certificate_verify = _nx_secure_remote_certificate_verify; + tls_session -> nx_secure_trusted_certificate_add = _nx_secure_trusted_certificate_add; + +#ifdef NX_SECURE_CUSTOM_SECRET_GENERATION + + /* Customized secret generation functions can be set by the user in nx_secure_custom_secret_generation_init. */ + status = nx_secure_custom_secret_generation_init(tls_session); + if (status != NX_SUCCESS) + { + return(status); + } +#endif + /* Set ID to check initialization status. */ tls_session -> nx_secure_tls_id = NX_SECURE_TLS_ID; diff --git a/nx_secure/src/nx_secure_tls_session_keys_set.c b/nx_secure/src/nx_secure_tls_session_keys_set.c index a632cf8f..e99072d8 100644 --- a/nx_secure/src/nx_secure_tls_session_keys_set.c +++ b/nx_secure/src/nx_secure_tls_session_keys_set.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_keys_set PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -57,7 +57,7 @@ /* */ /* CALLS */ /* */ -/* [nx_crypto_init] Initialize crypto */ +/* [nx_secure_session_keys_set] Set session keys */ /* */ /* CALLED BY */ /* */ @@ -76,23 +76,22 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* cleanup for session cipher, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE UINT _nx_secure_tls_session_keys_set(NX_SECURE_TLS_SESSION *tls_session, USHORT key_set) { -UINT status; -UCHAR *key_block; /* Maximum ciphersuite key size - AES_256_CBC_SHA, 2x32 byte keys + 2x20 byte MAC secrets + 2x16 IVs. */ -UINT key_size; -UINT hash_size; -UINT iv_size; -UINT key_offset; -UINT is_client; -const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; - - /* The key material should have already been generated by nx_secure_tls_generate_keys once all - * key generation data was available. This simply switches the appropriate key data over to the active - * key block */ +UINT status; +UINT is_client; if (key_set == NX_SECURE_TLS_KEY_SET_LOCAL) { @@ -103,9 +102,6 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; tls_session -> nx_secure_tls_remote_session_active = 1; } - /* Working pointers into our key material blocks. */ - key_block = tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data; - /* See if we are setting server or client keys. */ if ((key_set == NX_SECURE_TLS_KEY_SET_REMOTE && tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT) || (key_set == NX_SECURE_TLS_KEY_SET_LOCAL && tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER)) @@ -120,7 +116,6 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; } - if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -128,124 +123,24 @@ const NX_CRYPTO_METHOD *session_cipher_method = NX_NULL; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } - /* Get our session cipher method so we can get key sizes. */ - session_cipher_method = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_session_cipher; - - /* Lookup ciphersuite data for key size. We need 2 keys for each session. */ - key_size = session_cipher_method -> nx_crypto_key_size_in_bits >> 3; - - /* Lookup ciphersuite data for hash size - used for the MAC secret. */ - hash_size = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash_size; - - /* Lookup initialization vector size. */ - iv_size = session_cipher_method -> nx_crypto_IV_size_in_bits >> 3; - - /* Partition the key block into our keys and secrets following the TLS spec.*/ - key_offset = 0; - - if (((hash_size + key_size + iv_size) << 1) > sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data)) - { - - /* No space for key material data. */ - return(NX_SECURE_TLS_CRYPTO_KEYS_TOO_LARGE); - } - - /* First, the mac secrets. Check for non-zero in the (unlikely) event we are using a NULL hash. */ - if (hash_size > 0) + /* Set client or server write key. */ + if (is_client) { - - /* Copy new client mac secret over if setting client keys. */ - if (is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], hash_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_mac_secret = &key_block[key_offset]; - key_offset += hash_size; - - /* Copy new server mac secret if setting server keys. */ - if (!is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], hash_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_mac_secret = &key_block[key_offset]; - key_offset += hash_size; - } - - /* Now the keys. Check for non-zero size in the event we are using a NULL cipher (usually for debugging). */ - if (key_size > 0) - { - /* Copy new client session key if setting client keys. */ - if (is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], key_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key = &key_block[key_offset]; - key_offset += key_size; - - /* Copy new server session key if setting server keys. */ - if (!is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], key_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key = &key_block[key_offset]; - key_offset += key_size; + status = tls_session -> nx_secure_session_keys_set(tls_session -> nx_secure_tls_session_ciphersuite, &tls_session -> nx_secure_tls_key_material, + sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data), + is_client, &tls_session -> nx_secure_tls_session_cipher_client_initialized, + tls_session -> nx_secure_session_cipher_metadata_area_client, &tls_session -> nx_secure_session_cipher_handler_client, + tls_session -> nx_secure_session_cipher_metadata_size); } - - /* Finally, the IVs. Many ciphers don't use IV's so the iv_size is often zero. */ - if (iv_size > 0) - { - /* Copy new client IV if setting client keys. */ - if (is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], iv_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_iv = &key_block[key_offset]; - key_offset += iv_size; - - /* Copy new server IV if setting server keys. */ - if (!is_client) - { - NX_SECURE_MEMCPY(&tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data[key_offset], - &tls_session -> nx_secure_tls_key_material.nx_secure_tls_new_key_material_data[key_offset], iv_size); /* Use case of memcpy is verified. */ - } - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_iv = &key_block[key_offset]; - key_offset += iv_size; - } - - /* Initialize the crypto method used in the session cipher. */ - if (session_cipher_method -> nx_crypto_init != NULL) + else { - /* Set client write key. */ - if (is_client) - { - status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_client_write_key, - session_cipher_method -> nx_crypto_key_size_in_bits, - &tls_session -> nx_secure_session_cipher_handler_client, - tls_session -> nx_secure_session_cipher_metadata_area_client, - tls_session -> nx_secure_session_cipher_metadata_size); - } - else - { - /* Set server write key. */ - status = session_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)session_cipher_method, - tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_key, - session_cipher_method -> nx_crypto_key_size_in_bits, - &tls_session -> nx_secure_session_cipher_handler_server, - tls_session -> nx_secure_session_cipher_metadata_area_server, - tls_session -> nx_secure_session_cipher_metadata_size); - } - if(status != NX_CRYPTO_SUCCESS) - { - return(status); - } + status = tls_session -> nx_secure_session_keys_set(tls_session -> nx_secure_tls_session_ciphersuite, &tls_session -> nx_secure_tls_key_material, + sizeof(tls_session -> nx_secure_tls_key_material.nx_secure_tls_key_material_data), + is_client, &tls_session -> nx_secure_tls_session_cipher_server_initialized, + tls_session -> nx_secure_session_cipher_metadata_area_server, &tls_session -> nx_secure_session_cipher_handler_server, + tls_session -> nx_secure_session_cipher_metadata_size); } - return(NX_SECURE_TLS_SUCCESS); + return(status); } diff --git a/nx_secure/src/nx_secure_tls_session_packet_pool_set.c b/nx_secure/src/nx_secure_tls_session_packet_pool_set.c new file mode 100644 index 00000000..4f4921bb --- /dev/null +++ b/nx_secure/src/nx_secure_tls_session_packet_pool_set.c @@ -0,0 +1,75 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_tls_session_packet_pool_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets the packet pool to be used by the TLS stack to */ +/* allocate outgoing packets. */ +/* */ +/* INPUT */ +/* */ +/* tls_session TLS control block */ +/* packet_pool Pointer to the packet pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_tls_session_packet_pool_set(NX_SECURE_TLS_SESSION *tls_session, + NX_PACKET_POOL *packet_pool) +{ + /* Set the packet pool in the TLS session. */ + tls_session -> nx_secure_tls_packet_pool = packet_pool; + + return(NX_SUCCESS); +} + diff --git a/nx_secure/src/nx_secure_tls_session_receive.c b/nx_secure/src/nx_secure_tls_session_receive.c index 75505b2e..d6fc28e9 100644 --- a/nx_secure/src/nx_secure_tls_session_receive.c +++ b/nx_secure/src/nx_secure_tls_session_receive.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_receive PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,15 +70,19 @@ /* supported chained packet, */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), added */ +/* conditional TLS 1.3 build, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and */ +/* fixed renegotiation when */ +/* receiving in non-block mode,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_session_receive(NX_SECURE_TLS_SESSION *tls_session, NX_PACKET **packet_ptr_ptr, ULONG wait_option) { UINT status; -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION -UINT local_initiated_renegotiation = NX_FALSE; -#endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ /* Session receive logic: * 1. Receive incoming packets @@ -90,24 +94,6 @@ UINT local_initiated_renegotiation = NX_FALSE; */ -#ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION -#ifndef NX_SECURE_TLS_CLIENT_DISABLED - if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_CLIENT && - tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_RENEGOTIATING) - { - local_initiated_renegotiation = NX_TRUE; - } -#endif - -#ifndef NX_SECURE_TLS_SERVER_DISABLED - if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER && - tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_HELLO_REQUEST) - { - local_initiated_renegotiation = NX_TRUE; - } -#endif -#endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ - /* Try receiving records from the remote host. */ status = _nx_secure_tls_session_receive_records(tls_session, packet_ptr_ptr, wait_option); @@ -117,9 +103,6 @@ UINT local_initiated_renegotiation = NX_FALSE; if (status == NX_SUCCESS && tls_session -> nx_secure_tls_renegotiation_handshake) { - /* Clear flag to prevent infinite recursion. */ - tls_session -> nx_secure_tls_renegotiation_handshake = NX_FALSE; - /* Process the handshake. */ status = _nx_secure_tls_handshake_process(tls_session, wait_option); @@ -128,25 +111,28 @@ UINT local_initiated_renegotiation = NX_FALSE; return(status); } + /* Clear flag to prevent infinite recursion. */ + tls_session -> nx_secure_tls_renegotiation_handshake = NX_FALSE; + /* If this renegotiation was initiated by us, don't receive additional data as that will be up to the application. */ - if (!local_initiated_renegotiation) + if (!tls_session -> nx_secure_tls_local_initiated_renegotiation) { /* Handle any data that followed the re-negotiation handshake. */ status = _nx_secure_tls_session_receive_records(tls_session, packet_ptr_ptr, wait_option); } + tls_session -> nx_secure_tls_local_initiated_renegotiation = NX_FALSE; } else #endif /* NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION */ { - if (status == NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED) +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + /* Continue processing while we are receiving post-handshake messages. */ + while (status == NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED) { - /* Continue processing while we are receiving post-handshake messages. */ - while (status == NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED) - { - status = _nx_secure_tls_session_receive_records(tls_session, packet_ptr_ptr, wait_option); - } + status = _nx_secure_tls_session_receive_records(tls_session, packet_ptr_ptr, wait_option); } +#endif /* NX_SECURE_TLS_TLS_1_3_ENABLED */ } diff --git a/nx_secure/src/nx_secure_tls_session_receive_records.c b/nx_secure/src/nx_secure_tls_session_receive_records.c index 2daaa972..6ce34535 100644 --- a/nx_secure/src/nx_secure_tls_session_receive_records.c +++ b/nx_secure/src/nx_secure_tls_session_receive_records.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_receive_records PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -77,6 +77,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* supported chained packet, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), added */ +/* conditional TLS 1.3 build, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_session_receive_records(NX_SECURE_TLS_SESSION *tls_session, @@ -146,7 +149,11 @@ UCHAR handshake_finished = NX_FALSE; } /* Cleanup if the record processing was successful or if we have a renegotiation attempt. */ - if (status == NX_SUCCESS || status == NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED) + if (status == NX_SUCCESS +#if (NX_SECURE_TLS_TLS_1_3_ENABLED) + || status == NX_SECURE_TLS_POST_HANDSHAKE_RECEIVED +#endif /* (NX_SECURE_TLS_TLS_1_3_ENABLED) */ + ) { /* Remove processed packets. Data in released packet will be cleared by nx_secure_tls_packet_release. */ diff --git a/nx_secure/src/nx_secure_tls_session_renegotiate.c b/nx_secure/src/nx_secure_tls_session_renegotiate.c index a8d935ef..8cebba4e 100644 --- a/nx_secure/src/nx_secure_tls_session_renegotiate.c +++ b/nx_secure/src/nx_secure_tls_session_renegotiate.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_renegotiate PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -87,13 +87,27 @@ /* supported chained packet, */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), */ +/* fixed packet leak bug, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* option to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), changed */ +/* an error to assert, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and */ +/* fixed renegotiation when */ +/* receiving in non-block mode,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ #ifndef NX_SECURE_TLS_DISABLE_SECURE_RENEGOTIATION UINT _nx_secure_tls_session_renegotiate(NX_SECURE_TLS_SESSION *tls_session, UINT wait_option) { UINT status = NX_NOT_SUCCESSFUL; -NX_PACKET *incoming_packet; +NX_PACKET *incoming_packet = NX_NULL; NX_PACKET *send_packet; /* Get the protection. */ @@ -144,6 +158,7 @@ NX_PACKET *send_packet; /* This is a renegotiation handshake so indicate that to the stack. */ tls_session -> nx_secure_tls_client_state = NX_SECURE_TLS_CLIENT_STATE_RENEGOTIATING; + tls_session -> nx_secure_tls_local_initiated_renegotiation = NX_TRUE; /* On a session resumption free all certificates for the new session. * SESSION RESUMPTION: if session resumption is enabled, don't free!! @@ -196,6 +211,17 @@ NX_PACKET *send_packet; break; } } + + if (incoming_packet != NX_NULL) + { + nx_secure_tls_packet_release(incoming_packet); + } + + if (tls_session -> nx_secure_tls_client_state == NX_SECURE_TLS_CLIENT_STATE_HANDSHAKE_FINISHED) + { + tls_session -> nx_secure_tls_local_initiated_renegotiation = NX_FALSE; + tls_session -> nx_secure_tls_renegotiation_handshake = NX_FALSE; + } } #endif @@ -216,15 +242,19 @@ NX_PACKET *send_packet; return(status); } + /* We are requesting a renegotiation from the server side - we need to know if we requested + the renegotiation when the ClientHello comes in so we can reject client-initiated renegotiation + if the user so chooses. */ + tls_session -> nx_secure_tls_server_renegotiation_requested = NX_TRUE; + /* Populate our packet with HelloRequest data. */ status = _nx_secure_tls_send_hellorequest(tls_session, send_packet); + NX_ASSERT(status == NX_SUCCESS); - if (status == NX_SUCCESS) - { + tls_session -> nx_secure_tls_local_initiated_renegotiation = NX_TRUE; - /* Send the HelloRequest to kick things off. */ - status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_HELLO_REQUEST, wait_option); - } + /* Send the HelloRequest to kick things off. */ + status = _nx_secure_tls_send_handshake_record(tls_session, send_packet, NX_SECURE_TLS_HELLO_REQUEST, wait_option); /* If anything after the allocate fails, we need to release our packet. */ if (status != NX_SUCCESS) @@ -257,6 +287,17 @@ NX_PACKET *send_packet; break; } } + + if (incoming_packet != NX_NULL) + { + nx_secure_tls_packet_release(incoming_packet); + } + + if (tls_session -> nx_secure_tls_server_state == NX_SECURE_TLS_SERVER_STATE_HANDSHAKE_FINISHED) + { + tls_session -> nx_secure_tls_local_initiated_renegotiation = NX_FALSE; + tls_session -> nx_secure_tls_renegotiation_handshake = NX_FALSE; + } } #endif diff --git a/nx_secure/src/nx_secure_tls_session_reset.c b/nx_secure/src/nx_secure_tls_session_reset.c index 5446592e..f825ff03 100644 --- a/nx_secure/src/nx_secure_tls_session_reset.c +++ b/nx_secure/src/nx_secure_tls_session_reset.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_reset PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,17 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed renegotiation bug, */ /* resulting in version 6.1 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), added */ +/* cleanup for session cipher, */ +/* resulting in version 6.1.8 */ +/* 10-15-2021 Timothy Stapko Modified comment(s), added */ +/* option to disable client */ +/* initiated renegotiation, */ +/* resulting in version 6.1.9 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), and */ +/* fixed renegotiation when */ +/* receiving in non-block mode,*/ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_session_reset(NX_SECURE_TLS_SESSION *session_ptr) @@ -125,6 +136,8 @@ UINT temp_status; /* Sessions are not active when we start the socket. */ session_ptr -> nx_secure_tls_remote_session_active = 0; session_ptr -> nx_secure_tls_local_session_active = 0; + session_ptr -> nx_secure_tls_session_cipher_client_initialized = 0; + session_ptr -> nx_secure_tls_session_cipher_server_initialized = 0; /* Set the current ciphersuite to TLS_NULL_WITH_NULL_NULL which is the * specified ciphersuite for the handshake (pre-change cipher spec). */ @@ -159,6 +172,8 @@ UINT temp_status; /* Flag to indicate when a session renegotiation is taking place. */ session_ptr -> nx_secure_tls_renegotiation_handshake = NX_FALSE; session_ptr -> nx_secure_tls_secure_renegotiation_verified = NX_FALSE; + session_ptr -> nx_secure_tls_server_renegotiation_requested = NX_FALSE; + session_ptr -> nx_secure_tls_local_initiated_renegotiation = NX_FALSE; #endif /* Flag to indicate when credentials have been received from the remote host. */ diff --git a/nx_secure/src/nx_secure_tls_session_sni_extension_parse.c b/nx_secure/src/nx_secure_tls_session_sni_extension_parse.c index 4f2b4cff..f2b04f11 100644 --- a/nx_secure/src/nx_secure_tls_session_sni_extension_parse.c +++ b/nx_secure/src/nx_secure_tls_session_sni_extension_parse.c @@ -132,7 +132,7 @@ UINT offset; } /* Name and lengths check out, save off the name data. */ - NX_SECURE_MEMCPY(dns_name -> nx_secure_x509_dns_name, &data_ptr[offset], dns_name -> nx_secure_x509_dns_name_length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(dns_name -> nx_secure_x509_dns_name, &data_ptr[offset], dns_name -> nx_secure_x509_dns_name_length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ /* Success! */ return(NX_SUCCESS); diff --git a/nx_secure/src/nx_secure_tls_session_sni_extension_set.c b/nx_secure/src/nx_secure_tls_session_sni_extension_set.c index 4deb657b..bf2c148a 100644 --- a/nx_secure/src/nx_secure_tls_session_sni_extension_set.c +++ b/nx_secure/src/nx_secure_tls_session_sni_extension_set.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_sni_extension_set PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,15 +66,25 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), */ +/* fix compile error, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_session_sni_extension_set(NX_SECURE_TLS_SESSION *tls_session, NX_SECURE_X509_DNS_NAME *dns_name) { +#ifndef NX_SECURE_TLS_SNI_EXTENSION_DISABLED /* Set the pointer to the SNI DNS name so it can be sent in the ClientHello. */ tls_session -> nx_secure_tls_sni_extension_server_name = dns_name; return(NX_SUCCESS); +#else + NX_PARAMETER_NOT_USED(tls_session); + NX_PARAMETER_NOT_USED(dns_name); + + return(NX_NOT_ENABLED); +#endif } diff --git a/nx_secure/src/nx_secure_tls_session_start.c b/nx_secure/src/nx_secure_tls_session_start.c index 89b7c5b5..d9108921 100644 --- a/nx_secure/src/nx_secure_tls_session_start.c +++ b/nx_secure/src/nx_secure_tls_session_start.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_session_start PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -77,6 +77,12 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* supported chained packet, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), removed */ +/* internal unreachable logic, */ +/* resulting in version 6.1.11 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom packet pool support, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_session_start(NX_SECURE_TLS_SESSION *tls_session, NX_TCP_SOCKET *tcp_socket, @@ -91,8 +97,11 @@ NX_PACKET *send_packet; /* Get the protection. */ tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - /* Assign the packet pool from which TLS will allocate internal message packets. */ - tls_session -> nx_secure_tls_packet_pool = tcp_socket -> nx_tcp_socket_ip_ptr -> nx_ip_default_packet_pool; + if (!tls_session -> nx_secure_tls_packet_pool) + { + /* Assign the packet pool from which TLS will allocate internal message packets. */ + tls_session -> nx_secure_tls_packet_pool = tcp_socket -> nx_tcp_socket_ip_ptr -> nx_ip_default_packet_pool; + } /* Assign the TCP socket to the TLS session. */ tls_session -> nx_secure_tls_tcp_socket = tcp_socket; @@ -184,7 +193,7 @@ NX_PACKET *send_packet; or an error/timeout occurs. */ status = _nx_secure_tls_handshake_process(tls_session, wait_option); - if ((status == NX_CONTINUE) && (wait_option == 0)) + if (status == NX_CONTINUE) { /* It is non blocking mode. */ diff --git a/nx_secure/src/nx_secure_tls_trusted_certificate_add.c b/nx_secure/src/nx_secure_tls_trusted_certificate_add.c index d4029e39..bf6f5166 100644 --- a/nx_secure/src/nx_secure_tls_trusted_certificate_add.c +++ b/nx_secure/src/nx_secure_tls_trusted_certificate_add.c @@ -29,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_trusted_certificate_add PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -58,8 +58,8 @@ /* */ /* tx_mutex_get Get protection mutex */ /* tx_mutex_put Put protection mutex */ -/* _nx_secure_x509_store_certificate_add Add certificate to trusted */ -/* store */ +/* [nx_secure_trusted_certificate_add] Add certificate to trusted */ +/* store */ /* */ /* CALLED BY */ /* */ @@ -72,6 +72,12 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_trusted_certificate_add(NX_SECURE_TLS_SESSION *tls_session, @@ -98,9 +104,7 @@ UINT status; /* 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, - NX_SECURE_X509_CERT_LOCATION_TRUSTED); - + status = tls_session -> nx_secure_trusted_certificate_add(&tls_session -> nx_secure_tls_credentials.nx_secure_tls_certificate_store, certificate); /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); diff --git a/nx_secure/src/nx_secure_tls_trusted_certificate_remove.c b/nx_secure/src/nx_secure_tls_trusted_certificate_remove.c index 1c71e61e..4af8904e 100644 --- a/nx_secure/src/nx_secure_tls_trusted_certificate_remove.c +++ b/nx_secure/src/nx_secure_tls_trusted_certificate_remove.c @@ -30,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_trusted_certificate_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,6 +68,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* updated X.509 return value, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_trusted_certificate_remove(NX_SECURE_TLS_SESSION *tls_session, @@ -92,6 +95,12 @@ NX_SECURE_X509_DISTINGUISHED_NAME name; /* Release the protection. */ tx_mutex_put(&_nx_secure_tls_protection); + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERTIFICATE_NOT_FOUND) + { + return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + } + return(status); } diff --git a/nx_secure/src/nx_secure_tls_verify_mac.c b/nx_secure/src/nx_secure_tls_verify_mac.c index 75a83b40..509d98cd 100644 --- a/nx_secure/src/nx_secure_tls_verify_mac.c +++ b/nx_secure/src/nx_secure_tls_verify_mac.c @@ -24,15 +24,12 @@ #include "nx_secure_tls.h" -static UCHAR _generated_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; -static UCHAR _received_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; - /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_tls_verify_mac PORTABLE C */ -/* 6.1 */ +/* 6.2.0 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -60,7 +57,7 @@ static UCHAR _received_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; /* */ /* CALLS */ /* */ -/* _nx_secure_tls_hash_record Generate payload data hash */ +/* [nx_secure_verify_mac] Verify record MAC checksum */ /* */ /* CALLED BY */ /* */ @@ -76,18 +73,22 @@ static UCHAR _received_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; /* verified memcpy use cases, */ /* supported chained packet, */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked seq number overflow,*/ +/* resulting in version 6.1.12 */ +/* 10-31-2022 Yanwu Cai Modified comment(s), added */ +/* custom secret generation, */ +/* resulting in version 6.2.0 */ /* */ /**************************************************************************/ UINT _nx_secure_tls_verify_mac(NX_SECURE_TLS_SESSION *tls_session, UCHAR *header_data, USHORT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT *length) { UCHAR *mac_secret; -USHORT hash_size; -INT compare_result; -USHORT data_length; -UINT hash_length; -UCHAR header[6]; -ULONG bytes_copied; +UINT status; if (tls_session -> nx_secure_tls_session_ciphersuite == NX_NULL) { @@ -96,9 +97,6 @@ ULONG bytes_copied; return(NX_SECURE_TLS_UNKNOWN_CIPHERSUITE); } - /* Get the hash size and MAC secret for our current session. */ - hash_size = tls_session -> nx_secure_tls_session_ciphersuite -> nx_secure_tls_hash_size; - /* Select our proper MAC secret for hashing. */ if (tls_session -> nx_secure_tls_socket_type == NX_SECURE_TLS_SESSION_TYPE_SERVER) { @@ -111,94 +109,9 @@ ULONG bytes_copied; mac_secret = tls_session -> nx_secure_tls_key_material.nx_secure_tls_server_write_mac_secret; } - /* Check for 0-length records. With nothing to hash, don't continue to hash generation. */ - if (hash_size >= *length) - { - - if (header_data[0] == (UCHAR)(NX_SECURE_TLS_APPLICATION_DATA) && - *length == hash_size) - { - /* BEAST attack mitigation. In TLS 1.0 and SSLv3, the implicit IV enables the BEAST - attack. Some implementations counter the attack by sending an empty record which - has the effect of resetting the IVs. We normally don't allow empty records since there - is no data to hash, but in this case we want to allow it. */ - *length = 0; - - /* Increment the sequence number. */ - if ((tls_session -> nx_secure_tls_remote_sequence_number[0] + 1) == 0) - { - /* Check for overflow of the 32-bit unsigned number. */ - tls_session -> nx_secure_tls_remote_sequence_number[1]++; - } - tls_session -> nx_secure_tls_remote_sequence_number[0]++; - - return(NX_SUCCESS); - } - - /* The record data was smaller than the selected hash... Error. */ - return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); - } - - /* Adjust our length so we only hash the record data, not the hash as well. */ - data_length = (USHORT)(*length - hash_size); - - /* Copy the header data into our local buffer so we can change it if we need to. */ - if (header_length > sizeof(header)) - { - return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); - } - NX_SECURE_MEMCPY(header, header_data, header_length); /* Use case of memcpy is verified. */ - - /* Adjust the length in the header to match the length of the data before the hash was added. */ - header[3] = (UCHAR)((data_length >> 8) & 0x00FF); - header[4] = (UCHAR)(data_length & 0x00FF); - - /* Generate the hash on the plaintext data. */ - _nx_secure_tls_hash_record(tls_session, tls_session -> nx_secure_tls_remote_sequence_number, header, header_length, - packet_ptr, offset, data_length, _generated_hash, &hash_length, mac_secret); - - /* Increment the sequence number. */ - if ((tls_session -> nx_secure_tls_remote_sequence_number[0] + 1) == 0) - { - /* Check for overflow of the 32-bit unsigned number. */ - tls_session -> nx_secure_tls_remote_sequence_number[1]++; - } - tls_session -> nx_secure_tls_remote_sequence_number[0]++; - - if (hash_size == 0) - { - - /* For ciphersuite without explict hash, just return success. */ - return(NX_SECURE_TLS_SUCCESS); - } - - /* Now, compare the hash we generated to the one we received. */ - if (nx_packet_data_extract_offset(packet_ptr, - offset + data_length, - _received_hash, hash_size, &bytes_copied) || - (bytes_copied != hash_size)) - { - - /* The record data was smaller than the selected hash... Error. */ - return(NX_SECURE_TLS_PADDING_CHECK_FAILED); - } - compare_result = NX_SECURE_MEMCMP(_received_hash, _generated_hash, hash_size); - -#ifdef NX_SECURE_KEY_CLEAR - NX_SECURE_MEMSET(_generated_hash, 0, sizeof(_generated_hash)); -#endif /* NX_SECURE_KEY_CLEAR */ - - /* Before we return, adjust our data size so the caller will only see data, not the hash. */ - *length = data_length; - - /* If the hashes match, we are all good. Otherwise we have a problem. */ - if (compare_result == 0) - { - return(NX_SECURE_TLS_SUCCESS); - } - else - { - return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); - } + status = tls_session -> nx_secure_verify_mac(tls_session -> nx_secure_tls_session_ciphersuite, mac_secret, tls_session -> nx_secure_tls_remote_sequence_number, + header_data, header_length, packet_ptr, offset, length, + tls_session -> nx_secure_hash_mac_metadata_area, tls_session -> nx_secure_hash_mac_metadata_size); + return(status); } diff --git a/nx_secure/src/nx_secure_trusted_certificate_add.c b/nx_secure/src/nx_secure_trusted_certificate_add.c new file mode 100644 index 00000000..ae604285 --- /dev/null +++ b/nx_secure/src/nx_secure_trusted_certificate_add.c @@ -0,0 +1,93 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" +#include "nx_secure_x509.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_trusted_certificate_add PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adds an initialized NX_SECURE_TLS_CERTIFICATE to a */ +/* TLS session for use as a trusted Root Certificate - the certificate */ +/* is used to verify incoming certificates from the remote host, by */ +/* matching the incoming certificate's Issuer Common Name field with */ +/* that of the certificates in the Trusted Store to find the trusted */ +/* key used to verify that the incoming certificate is valid. */ +/* The function may be called repeatedly to add multiple certificates */ +/* to the internal linked-list. */ +/* */ +/* INPUT */ +/* */ +/* store Pointer to certificate store */ +/* certificate Pointer to certificate */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_x509_store_certificate_add Add certificate to trusted */ +/* store */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_trusted_certificate_add(NX_SECURE_X509_CERTIFICATE_STORE *store, + NX_SECURE_X509_CERT *certificate) +{ +UINT status; + + + /* Add the certificate to the TLS session credentials X509 store. */ + status = _nx_secure_x509_store_certificate_add(certificate, store, + NX_SECURE_X509_CERT_LOCATION_TRUSTED); + + /* Translate some X.509 return values into TLS return values. */ + if (status == NX_SECURE_X509_CERT_ID_DUPLICATE) + { + return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + } + + + + return(status); +} + diff --git a/nx_secure/src/nx_secure_verify_mac.c b/nx_secure/src/nx_secure_verify_mac.c new file mode 100644 index 00000000..15780618 --- /dev/null +++ b/nx_secure/src/nx_secure_verify_mac.c @@ -0,0 +1,214 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_tls.h" + +static UCHAR _generated_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; +static UCHAR _received_hash[NX_SECURE_TLS_MAX_HASH_SIZE]; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_verify_mac PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function verifies the Message Authentication Code (MAC) that */ +/* is included in encrypted TLS records. It hashes the incoming */ +/* message data and then compares it to the MAC in the received */ +/* record. If there is a mismatch, then the record has been corrupted */ +/* in transit and represents a possible security breach. */ +/* */ +/* INPUT */ +/* */ +/* ciphersuite Selected cipher suite */ +/* mac_secret Key used for MAC generation */ +/* sequence_num Record sequence number */ +/* header_data TLS record header data */ +/* header_length Length of header data */ +/* packet_ptr TLS record packet */ +/* offset Offset to TLS record in packet*/ +/* length Length of payload data */ +/* hash_mac_metadata Metadata for hash mac crypto */ +/* hash_mac_metadata_size Size of hash mac metadata */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_tls_hash_record Generate payload data hash */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_tls_verify_mac Verify record MAC checksum */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_verify_mac(const NX_SECURE_TLS_CIPHERSUITE_INFO *ciphersuite, UCHAR *mac_secret, ULONG sequence_num[NX_SECURE_TLS_SEQUENCE_NUMBER_SIZE], + UCHAR *header_data, USHORT header_length, NX_PACKET *packet_ptr, ULONG offset, UINT *length, + VOID *hash_mac_metadata, ULONG hash_mac_metadata_size) +{ + +USHORT hash_size; +INT compare_result; +USHORT data_length; +UINT hash_length; +UCHAR header[6]; +ULONG bytes_copied; + + + + /* Get the hash size and MAC secret for our current session. */ + hash_size = ciphersuite -> nx_secure_tls_hash_size; + + /* Check for 0-length records. With nothing to hash, don't continue to hash generation. */ + if (hash_size >= *length) + { + + if (header_data[0] == (UCHAR)(NX_SECURE_TLS_APPLICATION_DATA) && + *length == hash_size) + { + /* BEAST attack mitigation. In TLS 1.0 and SSLv3, the implicit IV enables the BEAST + attack. Some implementations counter the attack by sending an empty record which + has the effect of resetting the IVs. We normally don't allow empty records since there + is no data to hash, but in this case we want to allow it. */ + *length = 0; + + /* Increment the sequence number. */ + if ((sequence_num[0] + 1) == 0) + { + /* Check for overflow of the 32-bit unsigned number. */ + sequence_num[1]++; + + if (sequence_num[1] == 0) + { + + /* Check for overflow of the 64-bit unsigned number. As it should not reach here + in practical, we return a general error to prevent overflow theoretically. */ + return(NX_NOT_SUCCESSFUL); + } + + } + sequence_num[0]++; + + return(NX_SUCCESS); + } + + /* The record data was smaller than the selected hash... Error. */ + return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); + } + + /* Adjust our length so we only hash the record data, not the hash as well. */ + data_length = (USHORT)(*length - hash_size); + + /* Copy the header data into our local buffer so we can change it if we need to. */ + if (header_length > sizeof(header)) + { + return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); + } + NX_SECURE_MEMCPY(header, header_data, header_length); /* Use case of memcpy is verified. */ + + /* Adjust the length in the header to match the length of the data before the hash was added. */ + header[3] = (UCHAR)((data_length >> 8) & 0x00FF); + header[4] = (UCHAR)(data_length & 0x00FF); + + /* Generate the hash on the plaintext data. */ + _nx_secure_tls_hash_record(ciphersuite, sequence_num, header, header_length, + packet_ptr, offset, data_length, _generated_hash, &hash_length, mac_secret, + hash_mac_metadata, hash_mac_metadata_size); + + /* Increment the sequence number. */ + if ((sequence_num[0] + 1) == 0) + { + /* Check for overflow of the 32-bit unsigned number. */ + sequence_num[1]++; + + if (sequence_num[1] == 0) + { + + /* Check for overflow of the 64-bit unsigned number. As it should not reach here + in practical, we return a general error to prevent overflow theoretically. */ + return(NX_NOT_SUCCESSFUL); + } + + } + sequence_num[0]++; + + if (hash_size == 0) + { + + /* For ciphersuite without explict hash, just return success. */ + return(NX_SECURE_TLS_SUCCESS); + } + + /* Now, compare the hash we generated to the one we received. */ + if (nx_packet_data_extract_offset(packet_ptr, + offset + data_length, + _received_hash, hash_size, &bytes_copied)) + + { + + /* The record data was smaller than the selected hash... Error. */ + return(NX_SECURE_TLS_PADDING_CHECK_FAILED); + } + + if (bytes_copied != hash_size) + { + + /* The record data was smaller than the selected hash... Error. */ + return(NX_SECURE_TLS_PADDING_CHECK_FAILED); + } + + compare_result = NX_SECURE_MEMCMP(_received_hash, _generated_hash, hash_size); + +#ifdef NX_SECURE_KEY_CLEAR + NX_SECURE_MEMSET(_generated_hash, 0, sizeof(_generated_hash)); +#endif /* NX_SECURE_KEY_CLEAR */ + + /* Before we return, adjust our data size so the caller will only see data, not the hash. */ + *length = data_length; + + /* If the hashes match, we are all good. Otherwise we have a problem. */ + if (compare_result == 0) + { + return(NX_SECURE_TLS_SUCCESS); + } + else + { + return(NX_SECURE_TLS_HASH_MAC_VERIFY_FAILURE); + } +} + diff --git a/nx_secure/src/nx_secure_x509.c b/nx_secure/src/nx_secure_x509.c index 61ea7619..5a232ac9 100644 --- a/nx_secure/src/nx_secure_x509.c +++ b/nx_secure/src/nx_secure_x509.c @@ -15,17 +15,14 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" -#include -#include static UINT _nx_secure_x509_parse_cert_data(const UCHAR *buffer, ULONG length, UINT *bytes_processed, NX_SECURE_X509_CERT *cert); @@ -58,7 +55,7 @@ static UINT _nx_secure_x509_extract_oid_data(const UCHAR *buffer, UINT oid, UINT /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -105,6 +102,12 @@ static UINT _nx_secure_x509_extract_oid_data(const UCHAR *buffer, UINT oid, UINT /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Timothy Stapko Modified comment(s), */ +/* added parameter checking, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_parse(const UCHAR *buffer, UINT length, UINT *bytes_processed, @@ -167,6 +170,12 @@ UINT status; * - At the lowest level, all parsing will be done by the ASN.1 TLV block parser. */ + + if (cert == NX_CRYPTO_NULL) + { + return(NX_CRYPTO_PTR_ERROR); + } + /* 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); @@ -225,8 +234,7 @@ UINT status; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ ) { - /* Release the protection. */ - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + return(NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER); } /* Successfully parsed an X509 certificate. */ @@ -241,7 +249,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_extract_oid_data PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -282,6 +290,10 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Timothy Stapko Modified comment(s), */ +/* removed parameter checking, */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_x509_extract_oid_data(const UCHAR *buffer, UINT oid, UINT oid_param, ULONG length, @@ -297,15 +309,9 @@ UINT status; #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; #else - NX_PARAMETER_NOT_USED(oid_param); + NX_CRYPTO_PARAMETER_NOT_USED(oid_param); #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - NX_ASSERT(cert != NX_NULL); - - /* IMPORTANT NOTE: This function MUST handle a NULL value for the "cert" parameter - we need to parse the - * certificate data no matter what, and in some cases we might want to parse past the data rather than saving - * it off in the cert structure. By passing the structure as NULL, this function should just pass over the parsed data. - */ status = _nx_secure_x509_asn1_tlv_block_parse(buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); if (status != 0) @@ -359,7 +365,7 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; * This is due to the modulus being encoded as an ASN.1 bit string, which may * require padding bits to get to a multiple of 8 for byte alignment. The byte * represents the number of padding bits, but in X509 it should always be 0. */ - cert -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus = &tlv_data[1]; + cert -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus = tlv_data + 1; cert -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_modulus_length = (USHORT)(tlv_length - 1); /* Finally the public exponent. */ @@ -699,7 +705,7 @@ const UCHAR *tlv_data; ULONG header_length; UINT status; - NX_PARAMETER_NOT_USED(cert); + NX_CRYPTO_PARAMETER_NOT_USED(cert); /* Parse a TLV block and get information to continue parsing. */ status = _nx_secure_x509_asn1_tlv_block_parse(buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); @@ -789,7 +795,7 @@ const UCHAR *tlv_data; ULONG header_length; UINT status; - NX_PARAMETER_NOT_USED(cert); + NX_CRYPTO_PARAMETER_NOT_USED(cert); /* Parse a TLV block and get information to continue parsing. */ status = _nx_secure_x509_asn1_tlv_block_parse(buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); @@ -877,7 +883,7 @@ const UCHAR *tlv_data; UINT oid; ULONG header_length; UINT status; -UCHAR oid_found = NX_FALSE; +UCHAR oid_found = NX_CRYPTO_FALSE; /* The signature algorithm is an OID and has optionally associated parameters. */ *bytes_processed = 0; @@ -919,7 +925,7 @@ UCHAR oid_found = NX_FALSE; cert -> nx_secure_x509_signature_algorithm = oid; - oid_found = NX_TRUE; + oid_found = NX_CRYPTO_TRUE; } else if (tlv_type == NX_SECURE_ASN_TAG_NULL) { @@ -934,7 +940,7 @@ UCHAR oid_found = NX_FALSE; tlv_data = &tlv_data[tlv_length]; } - if (oid_found == NX_TRUE) + if (oid_found == NX_CRYPTO_TRUE) { return(NX_SECURE_X509_SUCCESS); } @@ -1085,7 +1091,7 @@ ULONG header_length; UINT status; const UCHAR *current_buffer; - NX_PARAMETER_NOT_USED(cert); + NX_CRYPTO_PARAMETER_NOT_USED(cert); /* First, parse the sequence. */ status = _nx_secure_x509_asn1_tlv_block_parse(buffer, &length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); @@ -1427,7 +1433,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_parse_unique_ids PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1464,6 +1470,9 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_x509_parse_unique_ids(const UCHAR *buffer, ULONG length, @@ -1478,7 +1487,7 @@ UINT status; const UCHAR *current_buffer; UINT processed_id; - NX_PARAMETER_NOT_USED(cert); + NX_CRYPTO_PARAMETER_NOT_USED(cert); /* Extract unique identifiers for issuer and subject, if present. */ /* issuerUniqueID ::= ASN.1 Bit String OPTIONAL @@ -1499,19 +1508,19 @@ UINT processed_id; /* If we process either ID, then we need to do a version check (v2 or v3 only). If neither is encountered skip the version check. */ - processed_id = NX_FALSE; + processed_id = NX_CRYPTO_FALSE; /* Check for the OPTIONAL issuer unique ID. */ if (tlv_type_class == NX_SECURE_ASN_TAG_CLASS_CONTEXT && tlv_type == NX_SECURE_X509_TAG_ISSUER_UNIQUE_ID) { /* We processed an ID, mark for version check. */ - processed_id = NX_TRUE; + processed_id = NX_CRYPTO_TRUE; /* The field is an IMPLICIT bit string, so the data just follows the context-specific tag. */ /* Save off a pointer to the issuer unique identifier data and its length. */ - cert -> nx_secure_x509_issuer_identifier = &tlv_data[1]; + cert -> nx_secure_x509_issuer_identifier = tlv_data + 1; cert -> nx_secure_x509_issuer_identifier_length = (USHORT)(tlv_length - 1); /* Return the number of bytes we processed. */ @@ -1539,12 +1548,12 @@ UINT processed_id; { /* We processed an ID, mark for version check. */ - processed_id = NX_TRUE; + processed_id = NX_CRYPTO_TRUE; /* The field is an IMPLICIT bit string, so the data just follows the context-specific tag. */ /* Save off a pointer to the issuer unique identifier data and its length. */ - cert -> nx_secure_x509_subject_identifier = &tlv_data[1]; + cert -> nx_secure_x509_subject_identifier = tlv_data + 1; cert -> nx_secure_x509_subject_identifier_length = (USHORT)(tlv_length - 1); /* Return the number of bytes we processed. */ @@ -1690,7 +1699,7 @@ UINT status; /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_parse_signature_data PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -1731,6 +1740,9 @@ UINT status; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_x509_parse_signature_data(const UCHAR *buffer, ULONG length, @@ -1766,7 +1778,7 @@ UINT status; * This is due to the data being encoded as an ASN.1 bit string, which may * require padding bits to get to a multiple of 8 for byte alignment. The byte * represents the number of padding bits, but in X509 it should always be 0. */ - cert -> nx_secure_x509_signature_data = &tlv_data[1]; + cert -> nx_secure_x509_signature_data = tlv_data + 1; cert -> nx_secure_x509_signature_data_length = tlv_length - 1; /* Return the number of bytes we processed. */ diff --git a/nx_secure/src/nx_secure_x509_asn1_tlv_block_parse.c b/nx_secure/src/nx_secure_x509_asn1_tlv_block_parse.c index da8545f1..4f9f0f04 100644 --- a/nx_secure/src/nx_secure_x509_asn1_tlv_block_parse.c +++ b/nx_secure/src/nx_secure_x509_asn1_tlv_block_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_asn1_tlv_block_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -122,6 +121,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_asn1_tlv_block_parse(const UCHAR *buffer, ULONG *buffer_length, USHORT *tlv_type, diff --git a/nx_secure/src/nx_secure_x509_certificate_chain_verify.c b/nx_secure/src/nx_secure_x509_certificate_chain_verify.c index 5cd2203f..9af44600 100644 --- a/nx_secure/src/nx_secure_x509_certificate_chain_verify.c +++ b/nx_secure/src/nx_secure_x509_certificate_chain_verify.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_chain_verify PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,10 +70,20 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* reorganized internal logic, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked expiration for all */ +/* the certs in the chain, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_chain_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, - NX_SECURE_X509_CERT *certificate) + NX_SECURE_X509_CERT *certificate, ULONG current_time) { UINT status; NX_SECURE_X509_CERT *current_certificate; @@ -92,16 +101,19 @@ INT compare_result; /* Get working pointer to certificate chain entry. */ current_certificate = certificate; - if (current_certificate == NX_NULL) - { - return(NX_PTR_ERROR); - } - - while (current_certificate != NX_NULL) + while (current_certificate != NX_CRYPTO_NULL) { /* Check the certificate expiration against the current time. */ + if (current_time != 0) + { + status = _nx_secure_x509_expiration_check(current_certificate, current_time); + if (status != NX_SECURE_X509_SUCCESS) + { + return(status); + } + } /* See if the certificate is self-signed or not. */ compare_result = _nx_secure_x509_distinguished_name_compare(¤t_certificate -> nx_secure_x509_distinguished_name, @@ -112,16 +124,16 @@ INT compare_result; /* Find the certificate issuer in the store. */ status = _nx_secure_x509_store_certificate_find(store, ¤t_certificate -> nx_secure_x509_issuer, 0, &issuer_certificate, &issuer_location); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { - return(NX_SECURE_TLS_ISSUER_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_ISSUER_CERTIFICATE_NOT_FOUND); } } else { #ifndef NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES /* The certificate is self-signed. If we don't allow that, return error. */ - return(NX_SECURE_TLS_INVALID_SELF_SIGNED_CERT); + return(NX_SECURE_X509_INVALID_SELF_SIGNED_CERT); #else /* Certificate is self-signed and we are configured to accept them. */ issuer_certificate = current_certificate; @@ -142,7 +154,7 @@ INT compare_result; then continue the verification process. */ if (issuer_location == NX_SECURE_X509_CERT_LOCATION_TRUSTED) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } #ifdef NX_SECURE_ALLOW_SELF_SIGNED_CERTIFICATES @@ -152,12 +164,12 @@ INT compare_result; /* Check for self-signed certificate in trusted store. */ status = _nx_secure_x509_store_certificate_find(store, ¤t_certificate -> nx_secure_x509_distinguished_name, 0, &issuer_certificate, &issuer_location); - if(status == NX_SUCCESS && issuer_location == NX_SECURE_X509_CERT_LOCATION_TRUSTED) + if(status == NX_SECURE_X509_SUCCESS && issuer_location == NX_SECURE_X509_CERT_LOCATION_TRUSTED) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Self-signed certificate is not trusted. */ - return(NX_SECURE_X509_CHAIN_VERIFY_FAILURE); + break; } #endif } @@ -166,7 +178,7 @@ INT compare_result; current_certificate = issuer_certificate; } /* End while. */ - /* Certificate is valid. */ + /* Certificate is invalid. */ return(NX_SECURE_X509_CHAIN_VERIFY_FAILURE); } diff --git a/nx_secure/src/nx_secure_x509_certificate_initialize.c b/nx_secure/src/nx_secure_x509_certificate_initialize.c index 5b184631..5c88f3c8 100644 --- a/nx_secure/src/nx_secure_x509_certificate_initialize.c +++ b/nx_secure/src/nx_secure_x509_certificate_initialize.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,14 +29,14 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.7 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function initializes an NX_SECURE_X509_CERTI */ +/* This function initializes an NX_SECURE_X509_CERT */ /* structure with a DER-encoded X509 digital certificate, and */ /* in the case of a server or client local certificate, the */ /* associated private key. */ @@ -84,8 +83,6 @@ /* _nx_secure_x509_pkcs1_rsa_private_key_parse */ /* Parse RSA key (PKCS#1 format) */ /* _nx_secure_x509_ec_private_key_parse Parse EC key */ -/* tx_mutex_get Get protection mutex */ -/* tx_mutex_put Put protection mutex */ /* */ /* CALLED BY */ /* */ @@ -99,6 +96,16 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 03-02-2021 Timothy Stapko Modified comment(s), */ +/* removed unnecessary mutex, */ +/* resulting in version 6.1.5 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 06-02-2021 Timothy Stapko Modified comment(s), */ +/* supported hardware EC */ +/* private key, */ +/* resulting in version 6.1.7 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_initialize(NX_SECURE_X509_CERT *certificate, @@ -114,14 +121,11 @@ UINT bytes_processed; NX_SECURE_EC_PRIVATE_KEY *ec_key; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - /* Get the protection. */ - tx_mutex_get(&_nx_secure_tls_protection, TX_WAIT_FOREVER); - NX_SECURE_MEMSET(certificate, 0, sizeof(NX_SECURE_X509_CERT)); /* Set up the certificate with raw data. */ certificate -> nx_secure_x509_certificate_raw_data_length = length; - if (raw_data_buffer == NX_NULL) + if (raw_data_buffer == NX_CRYPTO_NULL) { /* No buffer was passed in so just point to the certificate itself. */ certificate -> nx_secure_x509_certificate_raw_buffer_size = length; @@ -132,14 +136,12 @@ NX_SECURE_EC_PRIVATE_KEY *ec_key; /* Make sure we have enough space in the buffer for the certificate. */ if (length > buffer_size) { - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); - return(NX_SECURE_TLS_INSUFFICIENT_CERT_SPACE); + return(NX_SECURE_X509_INSUFFICIENT_CERT_SPACE); } /* Use the caller-supplied buffer for the certificate. */ certificate -> nx_secure_x509_certificate_raw_buffer_size = buffer_size; certificate -> nx_secure_x509_certificate_raw_data = raw_data_buffer; - NX_SECURE_MEMCPY(certificate -> nx_secure_x509_certificate_raw_data, certificate_data, length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(certificate -> nx_secure_x509_certificate_raw_data, certificate_data, length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ } /* Parse the DER-encoded X509 certificate to extract the public key data. @@ -152,9 +154,7 @@ NX_SECURE_EC_PRIVATE_KEY *ec_key; if (status != 0) { - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); - return(NX_SECURE_TLS_INVALID_CERTIFICATE); + return(NX_SECURE_X509_INVALID_CERTIFICATE); } /* If the optional private key is supplied, save it for later use. */ @@ -184,6 +184,12 @@ NX_SECURE_EC_PRIVATE_KEY *ec_key; status = _nx_secure_x509_ec_private_key_parse(private_key, priv_len, &bytes_processed, ec_key); break; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ + + case NX_SECURE_X509_KEY_TYPE_HARDWARE: + certificate -> nx_secure_x509_private_key.user_key.key_data = private_key; + certificate -> nx_secure_x509_private_key.user_key.key_length = priv_len; + status = NX_SUCCESS; + break; case NX_SECURE_X509_KEY_TYPE_NONE: default: /* Unknown or invalid key type, return error. */ @@ -194,25 +200,21 @@ NX_SECURE_EC_PRIVATE_KEY *ec_key; /* See if we had any issues in parsing. */ if (status != 0) { - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); return(status); } } /* We have a private key, this is a server or client identity certificate. */ - certificate -> nx_secure_x509_certificate_is_identity_cert = NX_TRUE; + certificate -> nx_secure_x509_certificate_is_identity_cert = NX_CRYPTO_TRUE; } else { /* No private key? Cannot be an identity certificate. */ - certificate -> nx_secure_x509_certificate_is_identity_cert = NX_FALSE; + certificate -> nx_secure_x509_certificate_is_identity_cert = NX_CRYPTO_FALSE; } certificate -> nx_secure_x509_next_certificate = NULL; - /* Release the protection. */ - tx_mutex_put(&_nx_secure_tls_protection); - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_certificate_list_add.c b/nx_secure/src/nx_secure_x509_certificate_list_add.c index 877356ff..94c97bda 100644 --- a/nx_secure/src/nx_secure_x509_certificate_list_add.c +++ b/nx_secure/src/nx_secure_x509_certificate_list_add.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_list_add PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -75,6 +74,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_list_add(NX_SECURE_X509_CERT **list_head, @@ -98,13 +100,17 @@ INT compare_result; current_cert = *list_head; previous_cert = current_cert; - while (current_cert != NX_NULL) + while (current_cert != NX_CRYPTO_NULL) { if (current_cert == certificate) { /* Oops, tried to add the same certificate twice (would lead to circular list)! */ +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_INVALID_PARAMETER); +#else return(NX_INVALID_PARAMETERS); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* If the certificate has a non-zero identifier, make sure the identifier wasn't added yet! */ @@ -112,7 +118,7 @@ INT compare_result; current_cert -> nx_secure_x509_cert_identifier == certificate -> nx_secure_x509_cert_identifier) { /* Duplicate ID found - don't add to the list! */ - return(NX_SECURE_TLS_CERT_ID_DUPLICATE); + return(NX_SECURE_X509_CERT_ID_DUPLICATE); } /* We want to be able to add duplicate entries to some of the certificate stores (e.g. the @@ -126,7 +132,11 @@ INT compare_result; if (compare_result == 0) { /* A certificate with the same distinguished name was already added to this list. */ +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_INVALID_PARAMETER); +#else return(NX_INVALID_PARAMETERS); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } } @@ -140,6 +150,6 @@ INT compare_result; certificate -> nx_secure_x509_next_certificate = NULL; } - return(NX_SECURE_TLS_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_certificate_list_find.c b/nx_secure/src/nx_secure_x509_certificate_list_find.c index f129a3ee..340143f1 100644 --- a/nx_secure/src/nx_secure_x509_certificate_list_find.c +++ b/nx_secure/src/nx_secure_x509_certificate_list_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_list_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,6 +73,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_list_find(NX_SECURE_X509_CERT **list_head, @@ -86,27 +88,35 @@ INT compare_result; /* Find out NULL pointers. */ - if (certificate == NX_NULL) + if (certificate == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Return NULL if certificate not found. */ - *certificate = NX_NULL; + *certificate = NX_CRYPTO_NULL; - if (list_head == NX_NULL) + if (list_head == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Walk the list until we find a certificate with a matching CN. Use a two-level pointer so we can modify the cert easily. */ current_cert = *list_head; - while (current_cert != NX_NULL) + while (current_cert != NX_CRYPTO_NULL) { /* If name is passed as NX_NULL, use the cert_id to match. */ - if (name == NX_NULL) + if (name == NX_CRYPTO_NULL) { /* Check the cert_id against the ID in the certificate. */ compare_result = (current_cert -> nx_secure_x509_cert_identifier == cert_id) ? 0 : 1; @@ -121,13 +131,13 @@ INT compare_result; if (!compare_result) { *certificate = current_cert; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Advance our current certificate pointer. */ current_cert = current_cert -> nx_secure_x509_next_certificate; } - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } diff --git a/nx_secure/src/nx_secure_x509_certificate_list_remove.c b/nx_secure/src/nx_secure_x509_certificate_list_remove.c index 0b279c98..f67f5028 100644 --- a/nx_secure/src/nx_secure_x509_certificate_list_remove.c +++ b/nx_secure/src/nx_secure_x509_certificate_list_remove.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -23,14 +23,14 @@ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" +#include "nx_secure_x509.h" /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_list_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -67,6 +67,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_list_remove(NX_SECURE_X509_CERT **list_head, @@ -76,20 +79,25 @@ NX_SECURE_X509_CERT **current_cert; INT compare_result; /* Check to see if the head of the certificates list is NULL. */ - if (list_head == NX_NULL) + if (list_head == NX_CRYPTO_NULL) { + /* Our certificate pointer was NULL, so return error. */ +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } else { /* Walk the list until we find a certificate with a matching CN. */ current_cert = list_head; - while ((*current_cert) != NX_NULL) + while ((*current_cert) != NX_CRYPTO_NULL) { /* If name is passed as NX_NULL, use the cert_id to match. */ - if (name == NX_NULL) + if (name == NX_CRYPTO_NULL) { /* Check the cert_id against the ID in the certificate. */ compare_result = ((*current_cert) -> nx_secure_x509_cert_identifier == cert_id) ? 0 : 1; @@ -106,7 +114,7 @@ INT compare_result; *current_cert = (*current_cert) -> nx_secure_x509_next_certificate; /* We are OK to quit now, we removed the certificate. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Advance our current certificate pointers. */ @@ -114,6 +122,6 @@ INT compare_result; } } - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } diff --git a/nx_secure/src/nx_secure_x509_certificate_revocation_list_parse.c b/nx_secure/src/nx_secure_x509_certificate_revocation_list_parse.c index 8ea595e0..e17a5a88 100644 --- a/nx_secure/src/nx_secure_x509_certificate_revocation_list_parse.c +++ b/nx_secure/src/nx_secure_x509_certificate_revocation_list_parse.c @@ -15,17 +15,14 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" -#include -#include #ifndef NX_SECURE_X509_DISABLE_CRL /* Helper functions. */ @@ -55,7 +52,7 @@ static UINT _nx_secure_x509_crl_extensions_parse(const UCHAR *buffer, ULONG leng /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_revocation_list_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -97,6 +94,9 @@ static UINT _nx_secure_x509_crl_extensions_parse(const UCHAR *buffer, ULONG leng /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_revocation_list_parse(const UCHAR *buffer, UINT length, @@ -471,7 +471,7 @@ const UCHAR *tlv_data; UINT oid; ULONG header_length; UINT status; -UCHAR oid_found = NX_FALSE; +UCHAR oid_found = NX_CRYPTO_FALSE; /* The signature algorithm is a sequence of OIDs that is terminated by a NULL ASN.1 tag. */ *bytes_processed = 0; @@ -513,7 +513,7 @@ UCHAR oid_found = NX_FALSE; crl -> nx_secure_x509_crl_signature_algorithm = (USHORT)oid; - oid_found = NX_TRUE; + oid_found = NX_CRYPTO_TRUE; } else if (tlv_type == NX_SECURE_ASN_TAG_NULL) { @@ -528,7 +528,7 @@ UCHAR oid_found = NX_FALSE; tlv_data = &tlv_data[tlv_length]; } - if (oid_found == NX_TRUE) + if (oid_found == NX_CRYPTO_TRUE) { return(NX_SECURE_X509_SUCCESS); } @@ -543,7 +543,7 @@ UCHAR oid_found = NX_FALSE; /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_crl_signature_data_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -581,6 +581,9 @@ UCHAR oid_found = NX_FALSE; /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* improved internal logic, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_x509_crl_signature_data_parse(const UCHAR *buffer, ULONG length, @@ -612,7 +615,7 @@ UINT status; * This is due to the data being encoded as an ASN.1 bit string, which may * require padding bits to get to a multiple of 8 for byte alignment. The byte * represents the number of padding bits, but in X509 it should always be 0. */ - crl -> nx_secure_x509_crl_signature_data = &tlv_data[1]; + crl -> nx_secure_x509_crl_signature_data = tlv_data + 1; crl -> nx_secure_x509_crl_signature_data_length = tlv_length - 1; /* Return the number of bytes we processed. */ @@ -882,7 +885,7 @@ const UCHAR *current_buffer; /* The "nextUpdate" field is optional, so if we don't parse a time type here, that is OK. */ if ((tlv_type != NX_SECURE_ASN_TAG_UTC_TIME && tlv_type != NX_SECURE_ASN_TAG_GENERALIZED_TIME) || tlv_type_class != NX_SECURE_ASN_TAG_CLASS_UNIVERSAL) { - crl -> nx_secure_x509_crl_next_update = NX_NULL; + crl -> nx_secure_x509_crl_next_update = NX_CRYPTO_NULL; crl -> nx_secure_x509_crl_next_update_length = 0; return(NX_SECURE_X509_SUCCESS); } @@ -1040,8 +1043,8 @@ const UCHAR *current_buffer; ULONG header_length; UINT status; - NX_PARAMETER_NOT_USED(bytes_processed); - NX_PARAMETER_NOT_USED(crl); + NX_CRYPTO_PARAMETER_NOT_USED(bytes_processed); + NX_CRYPTO_PARAMETER_NOT_USED(crl); current_buffer = buffer; diff --git a/nx_secure/src/nx_secure_x509_certificate_verify.c b/nx_secure/src/nx_secure_x509_certificate_verify.c index cb218cee..37a488c1 100644 --- a/nx_secure/src/nx_secure_x509_certificate_verify.c +++ b/nx_secure/src/nx_secure_x509_certificate_verify.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" static UCHAR generated_hash[64]; /* We need to be able to hold the entire generated hash - SHA-512 = 64 bytes. */ @@ -35,7 +34,7 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_certificate_verify PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -62,7 +61,7 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* _nx_secure_x509_pkcs7_decode Decode the PKCS#7 signature */ /* _nx_secure_x509_find_certificate_methods */ /* Find certificate methods */ -/* _nx_secure_tls_find_curve_method Find named curve used */ +/* _nx_secure_x509_find_curve_method Find named curve used */ /* _nx_secure_x509_asn1_tlv_block_parse Parse ASN.1 block */ /* */ /* CALLED BY */ @@ -79,6 +78,12 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* ECC find curve method, */ /* add KeyUsage check, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* removed unnecessary code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_certificate_verify(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -99,7 +104,7 @@ UINT hash_length; const NX_CRYPTO_METHOD *hash_method; const NX_CRYPTO_METHOD *public_cipher_method; NX_SECURE_X509_CRYPTO *crypto_methods; -VOID *handler = NX_NULL; +VOID *handler = NX_CRYPTO_NULL; #ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK USHORT key_usage_bitfield = 0; #endif @@ -108,14 +113,14 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; const NX_CRYPTO_METHOD *curve_method; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - NX_PARAMETER_NOT_USED(store); + NX_CRYPTO_PARAMETER_NOT_USED(store); #ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK /* Before we do any crypto verification, we need to check the KeyUsage extension. */ status = _nx_secure_x509_key_usage_extension_parse(issuer_certificate, &key_usage_bitfield); /* If extension is not present, we don't need to verify per RFC 5280. */ - if(NX_SUCCESS == status) + if(NX_SECURE_X509_SUCCESS == status) { /* The issuer cert has a KeyUsage extension - check the KeyCertSign bit. */ if(!(key_usage_bitfield & NX_SECURE_X509_KEY_USAGE_KEY_CERT_SIGN)) @@ -133,7 +138,7 @@ const NX_CRYPTO_METHOD *curve_method; /* Find certificate crypto methods for this certificate. */ status = _nx_secure_x509_find_certificate_methods(certificate, (USHORT)certificate -> nx_secure_x509_signature_algorithm, &crypto_methods); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -148,7 +153,7 @@ const NX_CRYPTO_METHOD *curve_method; if (hash_method -> nx_crypto_init) { status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, - NX_NULL, + NX_CRYPTO_NULL, 0, &handler, certificate -> nx_secure_x509_hash_metadata_area, @@ -161,21 +166,21 @@ const NX_CRYPTO_METHOD *curve_method; } /* We need to generate a hash of this certificate in order to verify it against our trusted store. */ - if (hash_method -> nx_crypto_operation != NX_NULL) + if (hash_method -> nx_crypto_operation != NX_CRYPTO_NULL) { status = hash_method -> nx_crypto_operation(NX_CRYPTO_VERIFY, handler, (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, + NX_CRYPTO_NULL, 0, (UCHAR *)certificate_verify_data, verify_data_length, - NX_NULL, + NX_CRYPTO_NULL, generated_hash, sizeof(generated_hash), certificate -> nx_secure_x509_hash_metadata_area, certificate -> nx_secure_x509_hash_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if(status != NX_CRYPTO_SUCCESS) { @@ -216,7 +221,7 @@ const NX_CRYPTO_METHOD *curve_method; return(NX_SECURE_X509_WRONG_SIGNATURE_METHOD); } - if (public_cipher_method -> nx_crypto_init != NX_NULL) + if (public_cipher_method -> nx_crypto_init != NX_CRYPTO_NULL) { /* Initialize the crypto method with public key. */ status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, @@ -236,7 +241,7 @@ const NX_CRYPTO_METHOD *curve_method; } } - if (public_cipher_method -> nx_crypto_operation != NX_NULL) + if (public_cipher_method -> nx_crypto_operation != NX_CRYPTO_NULL) { status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, handler, @@ -245,12 +250,12 @@ const NX_CRYPTO_METHOD *curve_method; (NX_CRYPTO_KEY_SIZE)(issuer_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), (UCHAR *)signature_data, signature_length, - NX_NULL, + NX_CRYPTO_NULL, decrypted_signature, sizeof(decrypted_signature), certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if(status != NX_CRYPTO_SUCCESS) { @@ -282,7 +287,7 @@ const NX_CRYPTO_METHOD *curve_method; &decrypted_hash, &decrypted_hash_length); #ifdef NX_SECURE_KEY_CLEAR - if(status != NX_SUCCESS || decrypted_hash_length != hash_length) + if(status != NX_SECURE_X509_SUCCESS || decrypted_hash_length != hash_length) { /* Clear secrets state on errors. */ NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); @@ -290,7 +295,7 @@ const NX_CRYPTO_METHOD *curve_method; } #endif /* NX_SECURE_KEY_CLEAR */ - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -311,7 +316,7 @@ const NX_CRYPTO_METHOD *curve_method; /* If the comparision worked, return success. */ if (compare_result == 0) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE @@ -328,10 +333,10 @@ const NX_CRYPTO_METHOD *curve_method; ec_pubkey = &issuer_certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the remote certificate is using. */ - status = _nx_secure_tls_find_curve_method(NX_NULL, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method, NX_NULL); + status = _nx_secure_x509_find_curve_method((USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method); #ifdef NX_SECURE_KEY_CLEAR - if(status != NX_SUCCESS || curve_method == NX_NULL) + if(status != NX_SECURE_X509_SUCCESS || curve_method == NX_CRYPTO_NULL) { /* Clear secrets on errors. */ NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); @@ -339,18 +344,12 @@ const NX_CRYPTO_METHOD *curve_method; #endif /* NX_SECURE_KEY_CLEAR */ - if(status != NX_SUCCESS) + if(status != NX_SECURE_X509_SUCCESS) { return(status); } - if (curve_method == NX_NULL) - { - /* The issuer certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); - } - - if (public_cipher_method -> nx_crypto_init != NX_NULL) + if (public_cipher_method -> nx_crypto_init != NX_CRYPTO_NULL) { status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, @@ -367,22 +366,22 @@ const NX_CRYPTO_METHOD *curve_method; return(status); } } - if (public_cipher_method -> nx_crypto_operation == NX_NULL) + if (public_cipher_method -> nx_crypto_operation == NX_CRYPTO_NULL) { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); #endif /* NX_SECURE_KEY_CLEAR */ - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + return(NX_SECURE_X509_MISSING_CRYPTO_ROUTINE); } status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)public_cipher_method, NX_NULL, 0, - (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, + (NX_CRYPTO_METHOD*)public_cipher_method, NX_CRYPTO_NULL, 0, + (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_CRYPTO_NULL, + NX_CRYPTO_NULL, 0, certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if (status != NX_CRYPTO_SUCCESS) { #ifdef NX_SECURE_KEY_CLEAR @@ -398,25 +397,25 @@ const NX_CRYPTO_METHOD *curve_method; (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), generated_hash, hash_method -> nx_crypto_ICV_size_in_bits >> 3, - NX_NULL, + NX_CRYPTO_NULL, (UCHAR *)signature_data, signature_length, certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); #endif /* NX_SECURE_KEY_CLEAR */ if (status == NX_CRYPTO_SUCCESS) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ else { - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + return(NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER); } #ifdef NX_SECURE_KEY_CLEAR @@ -424,6 +423,6 @@ const NX_CRYPTO_METHOD *curve_method; #endif /* NX_SECURE_KEY_CLEAR */ /* Comparison failed, return error. */ - return(NX_SECURE_TLS_CERTIFICATE_SIG_CHECK_FAILED); + return(NX_SECURE_X509_CERTIFICATE_SIG_CHECK_FAILED); } diff --git a/nx_secure/src/nx_secure_x509_common_name_dns_check.c b/nx_secure/src/nx_secure_x509_common_name_dns_check.c index ca11ad10..a1e0f6bd 100644 --- a/nx_secure/src/nx_secure_x509_common_name_dns_check.c +++ b/nx_secure/src/nx_secure_x509_common_name_dns_check.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_common_name_dns_check PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -82,6 +81,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_common_name_dns_check(NX_SECURE_X509_CERT *certificate, const UCHAR *dns_tld, @@ -102,21 +104,21 @@ NX_SECURE_X509_EXTENSION alt_name_extension; if (compare_value == 0) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Find the subject alt name extension in the certificate. */ status = _nx_secure_x509_extension_find(certificate, &alt_name_extension, NX_SECURE_TLS_X509_TYPE_SUBJECT_ALT_NAME); /* See if extension present - it is OK if not present! */ - if (status == NX_SUCCESS) + if (status == NX_SECURE_X509_SUCCESS) { /* Extract the subject alt name string from the parsed extension. */ status = _nx_secure_x509_subject_alt_names_find(&alt_name_extension, dns_tld, dns_tld_length, NX_SECURE_X509_SUB_ALT_NAME_TAG_DNSNAME); - if (status == NX_SUCCESS) + if (status == NX_SECURE_X509_SUCCESS) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } diff --git a/nx_secure/src/nx_secure_x509_crl_revocation_check.c b/nx_secure/src/nx_secure_x509_crl_revocation_check.c index cd5ed851..fd713ffd 100644 --- a/nx_secure/src/nx_secure_x509_crl_revocation_check.c +++ b/nx_secure/src/nx_secure_x509_crl_revocation_check.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -36,7 +35,7 @@ static UINT _nx_secure_x509_crl_parse_entry(const UCHAR *buffer, ULONG length, U /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_crl_revocation_check PORTABLE C */ -/* 6.1 */ +/* 6.1.12 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -88,6 +87,20 @@ static UINT _nx_secure_x509_crl_parse_entry(const UCHAR *buffer, ULONG length, U /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 08-02-2021 Timothy Stapko Modified comment(s), */ +/* fixed compiler warnings, */ +/* resulting in version 6.1.8 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), */ +/* modified to improve code */ +/* coverage result, */ +/* resulting in version 6.1.11 */ +/* 07-29-2022 Yuxin Zhou Modified comment(s), and */ +/* checked expiration for all */ +/* the certs in the chain, */ +/* resulting in version 6.1.12 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_crl_revocation_check(const UCHAR *crl_data, UINT crl_length, @@ -104,7 +117,7 @@ UINT length; const UCHAR *current_buffer; NX_SECURE_X509_CERT *issuer_certificate; UINT issuer_location; -const UCHAR *serial_number; +const UCHAR *serial_number = NX_NULL; UINT serial_number_length; NX_SECURE_MEMSET(&crl, 0, sizeof(NX_SECURE_X509_CRL)); @@ -112,7 +125,7 @@ UINT serial_number_length; /* First, parse the CRL. */ status = _nx_secure_x509_certificate_revocation_list_parse(crl_data, crl_length, &crl_bytes, &crl); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -131,15 +144,15 @@ UINT serial_number_length; /* First, get the issuer certificate. If we have a valid store and CRL, the issuer should be available. */ status = _nx_secure_x509_store_certificate_find(store, &crl.nx_secure_x509_crl_issuer, 0, &issuer_certificate, &issuer_location); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } /* Now, check that the issuer is valid. */ - status = _nx_secure_x509_certificate_chain_verify(store, issuer_certificate); + status = _nx_secure_x509_certificate_chain_verify(store, issuer_certificate, 0); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -147,7 +160,7 @@ UINT serial_number_length; /* Now, verify that the CRL itself is OK. */ status = _nx_secure_x509_crl_verify(certificate, &crl, store, issuer_certificate); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -173,16 +186,13 @@ UINT serial_number_length; /* Parse an entry in the revokedCertificates list and get back the serial number. */ status = _nx_secure_x509_crl_parse_entry(current_buffer, length, &bytes_processed, &serial_number, &serial_number_length); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } /* Make sure we don't run past the end of the sequence if one of the entries was too big. */ - if (length < bytes_processed) - { - return(NX_SECURE_X509_ASN1_LENGTH_TOO_LONG); - } + NX_ASSERT(bytes_processed <= length); /* Compare the serial number we got from the list (if it exists) to the one in our certificate. */ compare_value = NX_SECURE_MEMCMP(serial_number, certificate -> nx_secure_x509_serial_number, @@ -201,13 +211,17 @@ UINT serial_number_length; } /* If we get here, the CRL was good and the certificate has not been revoked. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); #else /* NX_SECURE_X509_DISABLE_CRL */ - NX_PARAMETER_NOT_USED(crl_data); - NX_PARAMETER_NOT_USED(crl_length); - NX_PARAMETER_NOT_USED(store); - NX_PARAMETER_NOT_USED(certificate); + NX_CRYPTO_PARAMETER_NOT_USED(crl_data); + NX_CRYPTO_PARAMETER_NOT_USED(crl_length); + NX_CRYPTO_PARAMETER_NOT_USED(store); + NX_CRYPTO_PARAMETER_NOT_USED(certificate); +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_FORMAT_NOT_SUPPORTED); +#else return(NX_NOT_SUPPORTED); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ #endif /* NX_SECURE_X509_DISABLE_CRL */ } diff --git a/nx_secure/src/nx_secure_x509_crl_verify.c b/nx_secure/src/nx_secure_x509_crl_verify.c index a2c8aae7..5199a077 100644 --- a/nx_secure/src/nx_secure_x509_crl_verify.c +++ b/nx_secure/src/nx_secure_x509_crl_verify.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" #ifndef NX_SECURE_X509_DISABLE_CRL @@ -35,7 +34,7 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_crl_verify PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -66,7 +65,7 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* _nx_secure_x509_pkcs7_decode Decode the PKCS#7 signature */ /* _nx_secure_x509_find_certificate_methods */ /* Find certificate methods */ -/* _nx_secure_tls_find_curve_method Find named curve used */ +/* _nx_secure_x509_find_curve_method Find named curve used */ /* _nx_secure_x509_asn1_tlv_block_parse Parse ASN.1 block */ /* */ /* CALLED BY */ @@ -82,6 +81,9 @@ static UCHAR decrypted_signature[512]; /* This needs to hold the entire decrypte /* ECC find curve method, */ /* add KeyUsage check, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_crl_verify(NX_SECURE_X509_CERT *certificate, NX_SECURE_X509_CRL *crl, @@ -102,7 +104,7 @@ UINT hash_length; const NX_CRYPTO_METHOD *hash_method; const NX_CRYPTO_METHOD *public_cipher_method; NX_SECURE_X509_CRYPTO *crypto_methods; -VOID *handler = NX_NULL; +VOID *handler = NX_CRYPTO_NULL; #ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK USHORT key_usage_bitfield = 0; #endif @@ -111,14 +113,14 @@ NX_SECURE_EC_PUBLIC_KEY *ec_pubkey; const NX_CRYPTO_METHOD *curve_method; #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ - NX_PARAMETER_NOT_USED(store); + NX_CRYPTO_PARAMETER_NOT_USED(store); #ifndef NX_SECURE_X509_DISABLE_KEY_USAGE_CHECK /* Before we do any crypto verification, we need to check the KeyUsage extension. */ status = _nx_secure_x509_key_usage_extension_parse(issuer_certificate, &key_usage_bitfield); /* If extension is not present, we don't need to verify per RFC 5280. */ - if(NX_SUCCESS == status) + if(NX_SECURE_X509_SUCCESS == status) { /* The issuer cert has a KeyUsage extension - check the CRLSign bit. */ if(!(key_usage_bitfield & NX_SECURE_X509_KEY_USAGE_CRL_SIGN)) @@ -136,7 +138,7 @@ const NX_CRYPTO_METHOD *curve_method; /* Find certificate crypto methods for this certificate. */ status = _nx_secure_x509_find_certificate_methods(certificate, crl -> nx_secure_x509_crl_signature_algorithm, &crypto_methods); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -148,7 +150,7 @@ const NX_CRYPTO_METHOD *curve_method; if (hash_method -> nx_crypto_init) { status = hash_method -> nx_crypto_init((NX_CRYPTO_METHOD*)hash_method, - NX_NULL, + NX_CRYPTO_NULL, 0, &handler, certificate -> nx_secure_x509_hash_metadata_area, @@ -161,21 +163,21 @@ const NX_CRYPTO_METHOD *curve_method; } /* We need to generate a hash of this CRL in order to verify it against our trusted store. */ - if (hash_method -> nx_crypto_operation != NX_NULL) + if (hash_method -> nx_crypto_operation != NX_CRYPTO_NULL) { status = hash_method -> nx_crypto_operation(NX_CRYPTO_VERIFY, handler, (NX_CRYPTO_METHOD*)hash_method, - NX_NULL, + NX_CRYPTO_NULL, 0, (UCHAR *)crl_verify_data, verify_data_length, - NX_NULL, + NX_CRYPTO_NULL, generated_hash, sizeof(generated_hash), certificate -> nx_secure_x509_hash_metadata_area, certificate -> nx_secure_x509_hash_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if(status != NX_CRYPTO_SUCCESS) { @@ -216,7 +218,7 @@ const NX_CRYPTO_METHOD *curve_method; return(NX_SECURE_X509_WRONG_SIGNATURE_METHOD); } - if (public_cipher_method -> nx_crypto_init != NX_NULL) + if (public_cipher_method -> nx_crypto_init != NX_CRYPTO_NULL) { /* Initialize the crypto method with public key. */ status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, @@ -235,7 +237,7 @@ const NX_CRYPTO_METHOD *curve_method; } } - if (public_cipher_method -> nx_crypto_operation != NX_NULL) + if (public_cipher_method -> nx_crypto_operation != NX_CRYPTO_NULL) { status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_DECRYPT, handler, @@ -244,12 +246,12 @@ const NX_CRYPTO_METHOD *curve_method; (NX_CRYPTO_KEY_SIZE)(issuer_certificate -> nx_secure_x509_public_key.rsa_public_key.nx_secure_rsa_public_exponent_length << 3), (UCHAR *)signature_data, signature_length, - NX_NULL, + NX_CRYPTO_NULL, decrypted_signature, sizeof(decrypted_signature), certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if(status != NX_CRYPTO_SUCCESS) { @@ -280,7 +282,7 @@ const NX_CRYPTO_METHOD *curve_method; &decrypted_hash, &decrypted_hash_length); #ifdef NX_SECURE_KEY_CLEAR - if(status != NX_SUCCESS || decrypted_hash_length != hash_length) + if(status != NX_SECURE_X509_SUCCESS || decrypted_hash_length != hash_length) { /* Clear secrets on errors. */ NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); @@ -288,7 +290,7 @@ const NX_CRYPTO_METHOD *curve_method; } #endif /* NX_SECURE_KEY_CLEAR */ - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -309,7 +311,7 @@ const NX_CRYPTO_METHOD *curve_method; /* If the comparision worked, return success. */ if (compare_result == 0) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE @@ -329,28 +331,28 @@ const NX_CRYPTO_METHOD *curve_method; ec_pubkey = &issuer_certificate -> nx_secure_x509_public_key.ec_public_key; /* Find out which named curve the remote certificate is using. */ - status = _nx_secure_tls_find_curve_method(NX_NULL, (USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method, NX_NULL); + status = _nx_secure_x509_find_curve_method((USHORT)(ec_pubkey -> nx_secure_ec_named_curve), &curve_method); #ifdef NX_SECURE_KEY_CLEAR - if(status != NX_SUCCESS || curve_method == NX_NULL) + if(status != NX_SECURE_X509_SUCCESS || curve_method == NX_CRYPTO_NULL) { /* Clear secrets on errors. */ NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); } #endif /* NX_SECURE_KEY_CLEAR */ - if(status != NX_SUCCESS) + if(status != NX_SECURE_X509_SUCCESS) { return(status); } - if (curve_method == NX_NULL) + if (curve_method == NX_CRYPTO_NULL) { /* The issuer certificate is using an unsupported curve. */ - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + return(NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER); } - if (public_cipher_method -> nx_crypto_init != NX_NULL) + if (public_cipher_method -> nx_crypto_init != NX_CRYPTO_NULL) { status = public_cipher_method -> nx_crypto_init((NX_CRYPTO_METHOD*)public_cipher_method, (UCHAR *)ec_pubkey -> nx_secure_ec_public_key, @@ -366,21 +368,21 @@ const NX_CRYPTO_METHOD *curve_method; return(status); } } - if (public_cipher_method -> nx_crypto_operation == NX_NULL) + if (public_cipher_method -> nx_crypto_operation == NX_CRYPTO_NULL) { #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); #endif /* NX_SECURE_KEY_CLEAR */ - return(NX_SECURE_TLS_MISSING_CRYPTO_ROUTINE); + return(NX_SECURE_X509_MISSING_CRYPTO_ROUTINE); } status = public_cipher_method -> nx_crypto_operation(NX_CRYPTO_EC_CURVE_SET, handler, - (NX_CRYPTO_METHOD*)public_cipher_method, NX_NULL, 0, - (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_NULL, - NX_NULL, 0, + (NX_CRYPTO_METHOD*)public_cipher_method, NX_CRYPTO_NULL, 0, + (UCHAR *)curve_method, sizeof(NX_CRYPTO_METHOD *), NX_CRYPTO_NULL, + NX_CRYPTO_NULL, 0, certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); if (status != NX_CRYPTO_SUCCESS) { #ifdef NX_SECURE_KEY_CLEAR @@ -396,25 +398,25 @@ const NX_CRYPTO_METHOD *curve_method; (NX_CRYPTO_KEY_SIZE)(ec_pubkey -> nx_secure_ec_public_key_length << 3), generated_hash, hash_method -> nx_crypto_ICV_size_in_bits >> 3, - NX_NULL, + NX_CRYPTO_NULL, (UCHAR *)signature_data, signature_length, certificate -> nx_secure_x509_public_cipher_metadata_area, certificate -> nx_secure_x509_public_cipher_metadata_size, - NX_NULL, NX_NULL); + NX_CRYPTO_NULL, NX_CRYPTO_NULL); #ifdef NX_SECURE_KEY_CLEAR NX_SECURE_MEMSET(generated_hash, 0, sizeof(generated_hash)); #endif /* NX_SECURE_KEY_CLEAR */ if (status == NX_CRYPTO_SUCCESS) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ else { - return(NX_SECURE_TLS_UNSUPPORTED_PUBLIC_CIPHER); + return(NX_SECURE_X509_UNSUPPORTED_PUBLIC_CIPHER); } #ifdef NX_SECURE_KEY_CLEAR diff --git a/nx_secure/src/nx_secure_x509_distinguished_name_compare.c b/nx_secure/src/nx_secure_x509_distinguished_name_compare.c index 051d45f0..9a08eede 100644 --- a/nx_secure/src/nx_secure_x509_distinguished_name_compare.c +++ b/nx_secure/src/nx_secure_x509_distinguished_name_compare.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" static INT _nx_secure_x509_distinguished_name_field_compare(const UCHAR *field1, UINT length1, @@ -33,7 +32,7 @@ static INT _nx_secure_x509_distinguished_name_field_compare(const UCHAR *field1, /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_distinguished_name_compare PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -88,6 +87,9 @@ static INT _nx_secure_x509_distinguished_name_field_compare(const UCHAR *field1, /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ INT _nx_secure_x509_distinguished_name_compare(NX_SECURE_X509_DISTINGUISHED_NAME *name, diff --git a/nx_secure/src/nx_secure_x509_distinguished_name_parse.c b/nx_secure/src/nx_secure_x509_distinguished_name_parse.c index 41ac6717..bbfbc9df 100644 --- a/nx_secure/src/nx_secure_x509_distinguished_name_parse.c +++ b/nx_secure/src/nx_secure_x509_distinguished_name_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" static UINT _nx_secure_x509_extract_name_oid_data(const UCHAR *buffer, UINT oid, ULONG length, @@ -34,7 +33,7 @@ static UINT _nx_secure_x509_extract_name_oid_data(const UCHAR *buffer, UINT oid, /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_distinguished_name_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -75,6 +74,9 @@ static UINT _nx_secure_x509_extract_name_oid_data(const UCHAR *buffer, UINT oid, /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_distinguished_name_parse(const UCHAR *buffer, UINT length, UINT *bytes_processed, diff --git a/nx_secure/src/nx_secure_x509_dns_name_initialize.c b/nx_secure/src/nx_secure_x509_dns_name_initialize.c index 6b9ef500..e4397a73 100644 --- a/nx_secure/src/nx_secure_x509_dns_name_initialize.c +++ b/nx_secure/src/nx_secure_x509_dns_name_initialize.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -25,7 +25,6 @@ /* Include necessary system files. */ -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -33,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_dns_name_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ /* buffer length verification, */ /* verified memcpy use cases, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_dns_name_initialize(NX_SECURE_X509_DNS_NAME *dns_name, @@ -83,11 +85,11 @@ UINT _nx_secure_x509_dns_name_initialize(NX_SECURE_X509_DNS_NAME *dns_name, } /* Copy the name string into the entry structure. */ - NX_SECURE_MEMCPY(dns_name -> nx_secure_x509_dns_name, name_string, length); /* Use case of memcpy is verified. */ + NX_SECURE_MEMCPY(dns_name -> nx_secure_x509_dns_name, name_string, length); /* Use case of memcpy is verified. lgtm[cpp/banned-api-usage-required-any] */ dns_name -> nx_secure_x509_dns_name_length = length; /* Return completion status. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_ec_private_key_parse.c b/nx_secure/src/nx_secure_x509_ec_private_key_parse.c index 08c52d09..9751ca6e 100644 --- a/nx_secure/src/nx_secure_x509_ec_private_key_parse.c +++ b/nx_secure/src/nx_secure_x509_ec_private_key_parse.c @@ -15,17 +15,16 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" +#include "nx_secure_x509.h" #ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE -#include "nx_secure_x509.h" /**************************************************************************/ @@ -33,7 +32,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_ec_private_key_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,13 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* ignored public key in EC */ +/* private key, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_ec_private_key_parse(const UCHAR *buffer, UINT length, @@ -216,68 +222,7 @@ USHORT version; _nx_secure_x509_oid_parse(tlv_data, tlv_length, &ec_key -> nx_secure_ec_named_curve); } - if (seq_length == 0) - { - /* The public key is not present. */ - if (ec_key != NULL) - { - ec_key -> nx_secure_ec_public_key = NX_NULL; - ec_key -> nx_secure_ec_public_key_length = 0; - } - - return(NX_SECURE_X509_SUCCESS); - } - - /* Advance our working pointer past the last field. */ - tlv_data = &tlv_data[tlv_length]; - - /* Parse our next field, the public key. */ - status = _nx_secure_x509_asn1_tlv_block_parse(tlv_data, (ULONG *)&length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); - - /* Make sure we parsed the block alright. */ - if (status != 0) - { - return(status); - } - - if (tlv_type != 1 || tlv_type_class != NX_SECURE_ASN_TAG_CLASS_CONTEXT) - { - return(NX_SECURE_PKCS1_INVALID_PRIVATE_KEY); - } - - /* Update byte count. */ - *bytes_processed += header_length; - seq_length = tlv_length; - - /* Parse the publicKey. */ - status = _nx_secure_x509_asn1_tlv_block_parse(tlv_data, &seq_length, &tlv_type, &tlv_type_class, &tlv_length, &tlv_data, &header_length); - - /* Make sure we parsed the block alright. */ - if (status != 0) - { - return(status); - } - - if (tlv_type != NX_SECURE_ASN_TAG_BIT_STRING || tlv_type_class != NX_SECURE_ASN_TAG_CLASS_UNIVERSAL) - { - return(NX_SECURE_PKCS1_INVALID_PRIVATE_KEY); - } - - /* Update byte count. */ - *bytes_processed += (header_length + tlv_length); - - /* The value is a bitstring. */ - if (ec_key != NULL) - { - if (tlv_data[0] == 0) - { - tlv_data++; - tlv_length--; - } - ec_key -> nx_secure_ec_public_key = tlv_data; - ec_key -> nx_secure_ec_public_key_length = (USHORT)tlv_length; - } - + /* The optional public key is ignored. */ return(NX_SECURE_X509_SUCCESS); } #endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ diff --git a/nx_secure/src/nx_secure_x509_expiration_check.c b/nx_secure/src/nx_secure_x509_expiration_check.c index 99115b3f..e43971b1 100644 --- a/nx_secure/src/nx_secure_x509_expiration_check.c +++ b/nx_secure/src/nx_secure_x509_expiration_check.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Local helper function. */ @@ -34,7 +33,7 @@ static UINT _nx_secure_x509_asn1_time_to_unix_convert(const UCHAR *asn1_time, US /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_expiration_check PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ static UINT _nx_secure_x509_asn1_time_to_unix_convert(const UCHAR *asn1_time, US /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_expiration_check(NX_SECURE_X509_CERT *certificate, ULONG current_time) @@ -81,7 +83,7 @@ UINT status; /* First, convert the X.509 ASN.1 time format into 32-bit UINX-epoch format of the "not before" field. */ status = _nx_secure_x509_asn1_time_to_unix_convert(certificate -> nx_secure_x509_not_before, certificate -> nx_secure_x509_not_before_length, certificate -> nx_secure_x509_validity_format, ¬_before); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -89,7 +91,7 @@ UINT status; /* Convert the "not after" time field. */ status = _nx_secure_x509_asn1_time_to_unix_convert(certificate -> nx_secure_x509_not_after, certificate -> nx_secure_x509_not_after_length, certificate -> nx_secure_x509_validity_format, ¬_after); - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -108,14 +110,14 @@ UINT status; return(NX_SECURE_X509_CERTIFICATE_NOT_YET_VALID); } - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Helper function to convert the ASN.1 time formats into UNIX epoch time for comparison. */ -#define date_2_chars_to_int(buffer, index) (LONG)(((buffer[index] - '0') * 10) + (buffer[index + 1] - '0')) +#define date_2_chars_to_int(buffer, index) (ULONG)(((buffer[index] - '0') * 10) + (buffer[index + 1] - '0')) /* Array indexed on month - 1 gives the total number of days in all previous months (through last day of previous month). Leap years are handled in the logic below and are not reflected in this array. */ @@ -127,7 +129,7 @@ static const UINT days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 24 /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_asn1_time_to_unix_convert PORTABLE C */ -/* 6.1 */ +/* 6.1.11 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -163,15 +165,20 @@ static const UINT days_before_month[12] = {0, 31, 59, 90, 120, 151, 181, 212, 24 /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* changed LONG to ULONG to */ +/* extend the time range, */ +/* removed unused code, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ static UINT _nx_secure_x509_asn1_time_to_unix_convert(const UCHAR *asn1_time, USHORT asn1_length, USHORT format, ULONG *unix_time) { -LONG year, month, day, hour, minute, second; +ULONG year, month, day, hour, minute, second; UINT index; - NX_PARAMETER_NOT_USED(asn1_length); + NX_CRYPTO_PARAMETER_NOT_USED(asn1_length); index = 0; /* See what format we are using. */ @@ -206,7 +213,6 @@ UINT index; hour -= date_2_chars_to_int(asn1_time, index); index += 2; minute -= date_2_chars_to_int(asn1_time, index); - index += 2; } else if (asn1_time[index] == '-') { @@ -214,7 +220,6 @@ UINT index; hour += date_2_chars_to_int(asn1_time, index); index += 2; minute += date_2_chars_to_int(asn1_time, index); - index += 2; } else { @@ -250,13 +255,13 @@ UINT index; /* Finally, calculate the number of seconds from the extracted values. */ day += year * 365; - day += (LONG)days_before_month[month - 1]; + day += days_before_month[month - 1]; hour += day * 24; minute += hour * 60; second += minute * 60; /* Finally, return the converted time. */ - *unix_time = (ULONG)second; + *unix_time = second; } else if (format == NX_SECURE_ASN_TAG_GENERALIZED_TIME) { @@ -272,6 +277,6 @@ UINT index; return(NX_SECURE_X509_INVALID_DATE_FORMAT); } - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_extended_key_usage_extension_parse.c b/nx_secure/src/nx_secure_x509_extended_key_usage_extension_parse.c index dbb30f6f..cc40e955 100644 --- a/nx_secure/src/nx_secure_x509_extended_key_usage_extension_parse.c +++ b/nx_secure/src/nx_secure_x509_extended_key_usage_extension_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_extended_key_usage_extension_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -69,6 +68,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_extended_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, @@ -100,7 +102,7 @@ NX_SECURE_X509_EXTENSION key_usage_extension; status = _nx_secure_x509_extension_find(certificate, &key_usage_extension, NX_SECURE_TLS_X509_TYPE_EXTENDED_KEY_USAGE); /* See if extension present - it is OK if not present! */ - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -155,7 +157,7 @@ NX_SECURE_X509_EXTENSION key_usage_extension; /* If our OID matches the passed-in key usage OID type, success! */ if (usage_oid == key_usage) { - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } current_buffer += tlv_length; diff --git a/nx_secure/src/nx_secure_x509_extension_find.c b/nx_secure/src/nx_secure_x509_extension_find.c index a212a43c..ef1e189a 100644 --- a/nx_secure/src/nx_secure_x509_extension_find.c +++ b/nx_secure/src/nx_secure_x509_extension_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_extension_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -75,6 +74,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_extension_find(NX_SECURE_X509_CERT *certificate, @@ -91,7 +93,7 @@ const UCHAR *tlv_data; const UCHAR *current_buffer; ULONG header_length; UINT status; -UINT found_extension = NX_FALSE; +UINT found_extension = NX_CRYPTO_FALSE; /* Now, parse the extensions. */ /* Extension ASN.1 format: @@ -158,13 +160,13 @@ UINT found_extension = NX_FALSE; current_buffer = tlv_data + tlv_length; /* We found a matching extension, break out and populate the return structure. */ - found_extension = NX_TRUE; + found_extension = NX_CRYPTO_TRUE; break; } } /* End while loop. */ /* Did we find the extension we were looking for? */ - if (found_extension != NX_TRUE) + if (found_extension != NX_CRYPTO_TRUE) { return(NX_SECURE_X509_EXTENSION_NOT_FOUND); } @@ -181,7 +183,7 @@ UINT found_extension = NX_FALSE; /* Now check out what we got. Possibly a boolean for the critical flag, but if it isn't there, then it's default is FALSE. */ - critical_flag = NX_FALSE; + critical_flag = NX_CRYPTO_FALSE; if (tlv_type == NX_SECURE_ASN_TAG_BOOLEAN) { /* The boolean is in the data we extracted. Convert ASN.1 boolean TRUE (all bits set) to integer 1. */ diff --git a/nx_secure/src/nx_secure_x509_find_certificate_methods.c b/nx_secure/src/nx_secure_x509_find_certificate_methods.c index d7d12e46..7627ad24 100644 --- a/nx_secure/src/nx_secure_x509_find_certificate_methods.c +++ b/nx_secure/src/nx_secure_x509_find_certificate_methods.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** Transport Layer Security (TLS) */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -23,7 +23,6 @@ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_find_certificate_methods PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,6 +71,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_find_certificate_methods(NX_SECURE_X509_CERT *cert, USHORT signature_algorithm, @@ -86,12 +88,12 @@ SHORT index; if (cert -> nx_secure_x509_cipher_table[index].nx_secure_x509_crypto_identifier == signature_algorithm) { *crypto_methods = &cert -> nx_secure_x509_cipher_table[index]; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } } /* No entry found, crypto routines unknown. */ - *crypto_methods = NX_NULL; - return(NX_SECURE_TLS_UNKNOWN_CERT_SIG_ALGORITHM); + *crypto_methods = NX_CRYPTO_NULL; + return(NX_SECURE_X509_UNKNOWN_CERT_SIG_ALGORITHM); } diff --git a/nx_secure/src/nx_secure_x509_find_curve_method.c b/nx_secure/src/nx_secure_x509_find_curve_method.c new file mode 100644 index 00000000..c9ac968d --- /dev/null +++ b/nx_secure/src/nx_secure_x509_find_curve_method.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** X.509 Digital Certificates */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + +#include "nx_secure_x509.h" + +#ifdef NX_SECURE_ENABLE_ECC_CIPHERSUITE + +/* Supported named curves. */ +const USHORT *_nx_secure_x509_ecc_supported_groups; + +/* Number of supported named curves. */ +USHORT _nx_secure_x509_ecc_supported_groups_count; + +/* Corresponding crypto methods for the supported named curve. */ +const NX_CRYPTO_METHOD **_nx_secure_x509_ecc_curves; + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nx_secure_x509_find_curve_method PORTABLE C */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* Timothy Stapko, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function finds the curve method for the specified named curve */ +/* ID. */ +/* */ +/* INPUT */ +/* */ +/* named_curve Named curve ID */ +/* curve_method Pointer to hold the curve */ +/* method */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _nx_secure_x509_certificate_verify Verify a certificate */ +/* _nx_secure_x509_crl_verify Verify revocation list */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 04-02-2021 Timothy Stapko Initial Version 6.1.6 */ +/* */ +/**************************************************************************/ +UINT _nx_secure_x509_find_curve_method(USHORT named_curve, const NX_CRYPTO_METHOD **curve_method) +{ +USHORT i; + + /* Find out the curve method for the named curve. */ + for (i = 0; i < _nx_secure_x509_ecc_supported_groups_count; i++) + { + if (named_curve == _nx_secure_x509_ecc_supported_groups[i]) + { + *curve_method = _nx_secure_x509_ecc_curves[i]; + return(NX_SECURE_X509_SUCCESS); + } + } + + *curve_method = NX_CRYPTO_NULL; + return(NX_CRYTPO_MISSING_ECC_CURVE); +} +#endif /* NX_SECURE_ENABLE_ECC_CIPHERSUITE */ diff --git a/nx_secure/src/nx_secure_x509_free_certificate_get.c b/nx_secure/src/nx_secure_x509_free_certificate_get.c index ba6ef730..3148640f 100644 --- a/nx_secure/src/nx_secure_x509_free_certificate_get.c +++ b/nx_secure/src/nx_secure_x509_free_certificate_get.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_free_certificate_get PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -67,6 +66,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_free_certificate_get(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -77,10 +79,10 @@ NX_SECURE_X509_CERT *list_head; /* Get the first certificate in the remote store. */ list_head = store -> nx_secure_x509_free_certificates; - if (list_head == NX_NULL) + if (list_head == NX_CRYPTO_NULL) { /* No certificates in this store! */ - return(NX_SECURE_TLS_NO_CERT_SPACE_ALLOCATED); + return(NX_SECURE_X509_NO_CERT_SPACE_ALLOCATED); } /* Use first entry in store. */ @@ -88,8 +90,8 @@ NX_SECURE_X509_CERT *list_head; /* Remove the certificate from the store. */ store -> nx_secure_x509_free_certificates = (*certificate) -> nx_secure_x509_next_certificate; - (*certificate) -> nx_secure_x509_next_certificate = NX_NULL; + (*certificate) -> nx_secure_x509_next_certificate = NX_CRYPTO_NULL; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_key_usage_extension_parse.c b/nx_secure/src/nx_secure_x509_key_usage_extension_parse.c index f1485181..67188d52 100644 --- a/nx_secure/src/nx_secure_x509_key_usage_extension_parse.c +++ b/nx_secure/src/nx_secure_x509_key_usage_extension_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_key_usage_extension_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,6 +67,9 @@ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* fixed parsing issue, */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, USHORT *bitfield) @@ -104,7 +106,7 @@ NX_SECURE_X509_EXTENSION key_usage_extension; status = _nx_secure_x509_extension_find(certificate, &key_usage_extension, NX_SECURE_TLS_X509_TYPE_KEY_USAGE); /* See if extension present - it is OK if not present! */ - if (status != NX_SUCCESS) + if (status != NX_SECURE_X509_SUCCESS) { return(status); } @@ -141,6 +143,6 @@ NX_SECURE_X509_EXTENSION key_usage_extension; *bitfield = (USHORT)((tlv_data[1] << 8) + tlv_data[0]); - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_local_certificate_find.c b/nx_secure/src/nx_secure_x509_local_certificate_find.c index 08864a01..649b4c5a 100644 --- a/nx_secure/src/nx_secure_x509_local_certificate_find.c +++ b/nx_secure/src/nx_secure_x509_local_certificate_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_local_certificate_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -68,6 +67,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_local_certificate_find(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -79,28 +81,28 @@ NX_SECURE_X509_CERT *current_cert; /* Get the first certificate in the local store. */ list_head = store -> nx_secure_x509_local_certificates; - if (list_head == NX_NULL) + if (list_head == NX_CRYPTO_NULL) { /* No certificates in this store! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } /* Walk the list until we find a certificate that has a matching ID. */ current_cert = list_head; - while (current_cert != NX_NULL) + while (current_cert != NX_CRYPTO_NULL) { if (current_cert -> nx_secure_x509_cert_identifier == cert_id) { /* We found a match, return it. */ - if (certificate != NX_NULL) + if (certificate != NX_CRYPTO_NULL) { /* If certificate is NULL, just return that one was found, but nothing to return. */ *certificate = current_cert; } /* We are OK to quit now, we found the certificate. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Advance our current certificate pointer. */ @@ -108,6 +110,6 @@ NX_SECURE_X509_CERT *current_cert; } /* No matching certificates in this store! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } diff --git a/nx_secure/src/nx_secure_x509_local_device_certificate_get.c b/nx_secure/src/nx_secure_x509_local_device_certificate_get.c index 001f8b31..ee74a52f 100644 --- a/nx_secure/src/nx_secure_x509_local_device_certificate_get.c +++ b/nx_secure/src/nx_secure_x509_local_device_certificate_get.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_local_device_certificate_get PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -76,6 +75,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_local_device_certificate_get(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -89,32 +91,32 @@ NX_SECURE_X509_CERT *current_cert; /* Get the first certificate in the local store. */ list_head = store -> nx_secure_x509_local_certificates; - if (list_head == NX_NULL) + if (list_head == NX_CRYPTO_NULL) { /* No certificates in this store! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } - /* If the name is NX_NULL, search for identity certificates. */ - if (name == NX_NULL) + /* If the name is NX_CRYPTO_NULL, search for identity certificates. */ + if (name == NX_CRYPTO_NULL) { /* Walk the list until we find a certificate that is an identity certificate for this device (it has a private RSA key). */ current_cert = list_head; - while (current_cert != NX_NULL) + while (current_cert != NX_CRYPTO_NULL) { - if (current_cert -> nx_secure_x509_certificate_is_identity_cert == NX_TRUE) + if (current_cert -> nx_secure_x509_certificate_is_identity_cert == NX_CRYPTO_TRUE) { /* We found a match, return it. */ - if (certificate != NX_NULL) + if (certificate != NX_CRYPTO_NULL) { /* If certificate is NULL, just return that we found one. */ *certificate = current_cert; } /* We are OK to quit now, we found the certificate. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Advance our current certificate pointer. */ @@ -122,7 +124,7 @@ NX_SECURE_X509_CERT *current_cert; } /* No valid certificates in this store! */ - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } /* At this point, we have a list and a name. Find the certificate with diff --git a/nx_secure/src/nx_secure_x509_oid_parse.c b/nx_secure/src/nx_secure_x509_oid_parse.c index f409e4e1..35c42f94 100644 --- a/nx_secure/src/nx_secure_x509_oid_parse.c +++ b/nx_secure/src/nx_secure_x509_oid_parse.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -23,10 +23,7 @@ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" -#include -#include /* OIDs for X509 items @@ -234,7 +231,7 @@ static const UINT _nx_secure_x509_oid_map_size = sizeof(_nx_secure_x509_oid_map) /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_oid_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -283,6 +280,9 @@ static const UINT _nx_secure_x509_oid_map_size = sizeof(_nx_secure_x509_oid_map) /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ VOID _nx_secure_x509_oid_parse(const UCHAR *oid, ULONG length, UINT *oid_value) diff --git a/nx_secure/src/nx_secure_x509_pkcs1_rsa_private_key_parse.c b/nx_secure/src/nx_secure_x509_pkcs1_rsa_private_key_parse.c index ab6d2a61..55d6bdd1 100644 --- a/nx_secure/src/nx_secure_x509_pkcs1_rsa_private_key_parse.c +++ b/nx_secure/src/nx_secure_x509_pkcs1_rsa_private_key_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" static VOID _nx_secure_asn1_parse_unsigned_integer(const UCHAR *data, ULONG length, @@ -33,7 +32,7 @@ static VOID _nx_secure_asn1_parse_unsigned_integer(const UCHAR *data, ULONG leng /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_pkcs1_rsa_private_key_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -72,6 +71,9 @@ static VOID _nx_secure_asn1_parse_unsigned_integer(const UCHAR *data, ULONG leng /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_pkcs1_rsa_private_key_parse(const UCHAR *buffer, UINT length, diff --git a/nx_secure/src/nx_secure_x509_pkcs7_decode.c b/nx_secure/src/nx_secure_x509_pkcs7_decode.c index 23964e99..b4e948bf 100644 --- a/nx_secure/src/nx_secure_x509_pkcs7_decode.c +++ b/nx_secure/src/nx_secure_x509_pkcs7_decode.c @@ -23,7 +23,6 @@ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_pkcs7_decode PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,6 +73,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_pkcs7_decode(const UCHAR *signature_pointer, UINT signature_length, @@ -84,11 +86,11 @@ UINT i; USHORT tlv_type; USHORT tlv_type_class; ULONG tlv_length; -const UCHAR *tlv_data = NX_NULL; +const UCHAR *tlv_data = NX_CRYPTO_NULL; ULONG header_length; ULONG seq_length; UINT status; -const UCHAR *signature_data = NX_NULL; +const UCHAR *signature_data = NX_CRYPTO_NULL; ULONG remaining_length; /* Certificate signatures encrypted with RSA use PKCS#7 encoding (RFC 5652) which @@ -206,6 +208,6 @@ ULONG remaining_length; *hash_length = tlv_length; /* Signature is valid. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_remote_endpoint_certificate_get.c b/nx_secure/src/nx_secure_x509_remote_endpoint_certificate_get.c index 3d25db86..bad9bf19 100644 --- a/nx_secure/src/nx_secure_x509_remote_endpoint_certificate_get.c +++ b/nx_secure/src/nx_secure_x509_remote_endpoint_certificate_get.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_remote_endpoint_certificate_get PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,6 +73,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_remote_endpoint_certificate_get(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -89,7 +91,7 @@ INT compare_value; list_head = store -> nx_secure_x509_remote_certificates; candidate = list_head; - if (candidate == NX_NULL) + if (candidate == NX_CRYPTO_NULL) { /* No remote certificates in this store! */ return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); @@ -98,11 +100,11 @@ INT compare_value; /* At this point, we have multiple certificates in the remote store. We need to loop to find the one that isn't an issuer for the others. The list should almost always be short (< 5 entries) so optimization isn't critical. */ - while (candidate -> nx_secure_x509_next_certificate != NX_NULL) + while (candidate -> nx_secure_x509_next_certificate != NX_CRYPTO_NULL) { compare_cert = list_head; - while (compare_cert != NX_NULL) + while (compare_cert != NX_CRYPTO_NULL) { /* Search the entire list for this certificate's distinguished name in the issuer fields. */ compare_value = _nx_secure_x509_distinguished_name_compare(&candidate -> nx_secure_x509_distinguished_name, @@ -118,7 +120,7 @@ INT compare_value; compare_cert = compare_cert -> nx_secure_x509_next_certificate; } - if (compare_cert != NX_NULL) + if (compare_cert != NX_CRYPTO_NULL) { /* Advance the pointer to the next entry in the list. */ candidate = candidate -> nx_secure_x509_next_certificate; @@ -136,6 +138,6 @@ INT compare_value; /* No matter what we found, it is a certificate so return success - if the certificate is invalid for any reason, that will be caught during certificate verification. */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } diff --git a/nx_secure/src/nx_secure_x509_store_certificate_add.c b/nx_secure/src/nx_secure_x509_store_certificate_add.c index bf54f8b5..b5ebe8d1 100644 --- a/nx_secure/src/nx_secure_x509_store_certificate_add.c +++ b/nx_secure/src/nx_secure_x509_store_certificate_add.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_store_certificate_add PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -74,22 +73,29 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_store_certificate_add(NX_SECURE_X509_CERT *certificate, NX_SECURE_X509_CERTIFICATE_STORE *store, UINT location) { UINT status; -NX_SECURE_X509_CERT **store_ptr = NX_NULL; -UINT duplicates_ok = NX_FALSE; +NX_SECURE_X509_CERT **store_ptr = NX_CRYPTO_NULL; +UINT duplicates_ok = NX_CRYPTO_FALSE; /* Certificate and store must be non-NULL. */ - if (certificate == NX_NULL || store == NX_NULL) + if (certificate == NX_CRYPTO_NULL || store == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } - status = NX_SUCCESS; + status = NX_SECURE_X509_SUCCESS; /* Pick our store based on location. */ switch (location) @@ -108,18 +114,22 @@ UINT duplicates_ok = NX_FALSE; break; case NX_SECURE_X509_CERT_LOCATION_FREE: store_ptr = &store -> nx_secure_x509_free_certificates; - duplicates_ok = NX_TRUE; + duplicates_ok = NX_CRYPTO_TRUE; break; case NX_SECURE_X509_CERT_LOCATION_NONE: /* Deliberate fall-through. */ default: +#ifdef NX_CRYPTO_STANDALONE_ENABLE + status = NX_CRYPTO_INVALID_PARAMETER; +#else status = NX_INVALID_PARAMETERS; +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ break; } /* If we are adding a certificate with a numeric identifier, it is OK to add duplicates. */ if (certificate -> nx_secure_x509_cert_identifier != 0) { - duplicates_ok = NX_TRUE; + duplicates_ok = NX_CRYPTO_TRUE; } /* Invalid certificate location or other issue. */ diff --git a/nx_secure/src/nx_secure_x509_store_certificate_find.c b/nx_secure/src/nx_secure_x509_store_certificate_find.c index f0c6843e..404dcdba 100644 --- a/nx_secure/src/nx_secure_x509_store_certificate_find.c +++ b/nx_secure/src/nx_secure_x509_store_certificate_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_store_certificate_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_store_certificate_find(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -80,41 +82,45 @@ UINT _nx_secure_x509_store_certificate_find(NX_SECURE_X509_CERTIFICATE_STORE *st UINT status; /* Name and store must be non-NULL. */ - if (name == NX_NULL || store == NX_NULL || certificate == NX_NULL || location == NX_NULL) + if (name == NX_CRYPTO_NULL || store == NX_CRYPTO_NULL || certificate == NX_CRYPTO_NULL || location == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Search each location in turn. */ /* Start with trusted certificates - if we find one, we are probably done! */ status = _nx_secure_x509_certificate_list_find(&store -> nx_secure_x509_trusted_certificates, name, cert_id, certificate); - if (status == NX_SUCCESS) + if (status == NX_SECURE_X509_SUCCESS) { *location = NX_SECURE_X509_CERT_LOCATION_TRUSTED; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Next, local certificates. */ status = _nx_secure_x509_certificate_list_find(&store -> nx_secure_x509_local_certificates, name, cert_id, certificate); - if (status == NX_SUCCESS) + if (status == NX_SECURE_X509_SUCCESS) { *location = NX_SECURE_X509_CERT_LOCATION_LOCAL; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* Finally, check remote certs. */ status = _nx_secure_x509_certificate_list_find(&store -> nx_secure_x509_remote_certificates, name, cert_id, certificate); - if (status == NX_SUCCESS) + if (status == NX_SECURE_X509_SUCCESS) { *location = NX_SECURE_X509_CERT_LOCATION_REMOTE; - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } /* If we get here, the certificate was not found in any of the stores. */ *location = NX_SECURE_X509_CERT_LOCATION_NONE; - return(NX_SECURE_TLS_CERTIFICATE_NOT_FOUND); + return(NX_SECURE_X509_CERTIFICATE_NOT_FOUND); } diff --git a/nx_secure/src/nx_secure_x509_store_certificate_remove.c b/nx_secure/src/nx_secure_x509_store_certificate_remove.c index 97b33790..c400c9e5 100644 --- a/nx_secure/src/nx_secure_x509_store_certificate_remove.c +++ b/nx_secure/src/nx_secure_x509_store_certificate_remove.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /**************************************************************************/ @@ -30,7 +29,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_store_certificate_remove PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -78,6 +77,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_store_certificate_remove(NX_SECURE_X509_CERTIFICATE_STORE *store, @@ -85,15 +87,19 @@ UINT _nx_secure_x509_store_certificate_remove(NX_SECURE_X509_CERTIFICATE_STORE * UINT location, UINT cert_id) { UINT status; -NX_SECURE_X509_CERT **store_ptr = NX_NULL; +NX_SECURE_X509_CERT **store_ptr = NX_CRYPTO_NULL; /* Store must be non-NULL. */ - if (store == NX_NULL) + if (store == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } - status = NX_SUCCESS; + status = NX_SECURE_X509_SUCCESS; /* Pick our store based on location. */ switch (location) @@ -112,7 +118,11 @@ NX_SECURE_X509_CERT **store_ptr = NX_NULL; break; case NX_SECURE_X509_CERT_LOCATION_NONE: /* Deliberate fall-through. */ default: +#ifdef NX_CRYPTO_STANDALONE_ENABLE + status = NX_CRYPTO_INVALID_PARAMETER; +#else status = NX_INVALID_PARAMETERS; +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ break; } diff --git a/nx_secure/src/nx_secure_x509_subject_alt_names_find.c b/nx_secure/src/nx_secure_x509_subject_alt_names_find.c index a71e6478..0e46b1f0 100644 --- a/nx_secure/src/nx_secure_x509_subject_alt_names_find.c +++ b/nx_secure/src/nx_secure_x509_subject_alt_names_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_subject_alt_names_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nx_secure_x509_subject_alt_names_find(NX_SECURE_X509_EXTENSION *extension, const UCHAR *name, @@ -196,7 +198,7 @@ INT compare_value; if (compare_value == 0) { /* We found a match! */ - return(NX_SUCCESS); + return(NX_SECURE_X509_SUCCESS); } current_buffer += tlv_length; diff --git a/nx_secure/src/nx_secure_x509_wildcard_compare.c b/nx_secure/src/nx_secure_x509_wildcard_compare.c index cc35e3fa..e72cc735 100644 --- a/nx_secure/src/nx_secure_x509_wildcard_compare.c +++ b/nx_secure/src/nx_secure_x509_wildcard_compare.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" @@ -31,7 +30,7 @@ /* FUNCTION RELEASE */ /* */ /* _nx_secure_x509_wildcard_compare PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +70,9 @@ /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ INT _nx_secure_x509_wildcard_compare(const UCHAR *dns_name, UINT dns_name_len, diff --git a/nx_secure/src/nxe_secure_tls_session_packet_pool_set.c b/nx_secure/src/nxe_secure_tls_session_packet_pool_set.c new file mode 100644 index 00000000..f69caee0 --- /dev/null +++ b/nx_secure/src/nxe_secure_tls_session_packet_pool_set.c @@ -0,0 +1,96 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Secure Component */ +/** */ +/** Transport Layer Security (TLS) */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define NX_SECURE_SOURCE_CODE + + +#include "nx_secure_tls.h" + +/* Bring in externs for caller checking code. */ + +NX_SECURE_CALLER_CHECKING_EXTERNS + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _nxe_secure_tls_session_packet_pool_set PORTABLE C */ +/* 6.2.0 */ +/* AUTHOR */ +/* */ +/* Yanwu Cai, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors when setting the packet pool. */ +/* */ +/* INPUT */ +/* */ +/* tls_session TLS control block */ +/* packet_pool Pointer to the packet pool */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _nx_secure_tls_session_packet_pool_set */ +/* Actual packet pool set */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Yanwu Cai Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ +UINT _nxe_secure_tls_session_packet_pool_set(NX_SECURE_TLS_SESSION *tls_session, + NX_PACKET_POOL *packet_pool) +{ +UINT status; + + + if (tls_session == NX_NULL) + { + return(NX_PTR_ERROR); + } + + /* Make sure the session is initialized. */ + if(tls_session -> nx_secure_tls_id != NX_SECURE_TLS_ID) + { + return(NX_SECURE_TLS_SESSION_UNINITIALIZED); + } + + /* Check for appropriate caller. */ + NX_THREADS_ONLY_CALLER_CHECKING + + /* We want to be able to set the packet pool to NX_NULL to use the default packet pool, so don't check for it. */ + status = _nx_secure_tls_session_packet_pool_set(tls_session, packet_pool); + + return(status); +} + diff --git a/nx_secure/src/nxe_secure_tls_session_x509_client_verify_configure.c b/nx_secure/src/nxe_secure_tls_session_x509_client_verify_configure.c index 414c2b32..b93d2a25 100644 --- a/nx_secure/src/nxe_secure_tls_session_x509_client_verify_configure.c +++ b/nx_secure/src/nxe_secure_tls_session_x509_client_verify_configure.c @@ -36,7 +36,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_tls_session_x509_client_verify_configure PORTABLE C */ -/* 6.1 */ +/* 6.1.10 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -73,6 +73,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 01-31-2022 Timothy Stapko Modified comment(s), */ +/* removed redundant checking, */ +/* resulting in version 6.1.10 */ /* */ /**************************************************************************/ UINT _nxe_secure_tls_session_x509_client_verify_configure(NX_SECURE_TLS_SESSION *tls_session, UINT certs_number, VOID *certificate_buffer, ULONG buffer_size) @@ -109,7 +112,7 @@ UINT cert_buffer_size; metadata_size = sizeof(NX_SECURE_X509_CERT) * certs_number; /* Check that buffer is large enough. */ - if(buffer_size < metadata_size || certs_number == 0 || buffer_size == 0) + if(buffer_size < metadata_size || certs_number == 0) { return(NX_INVALID_PARAMETERS); } diff --git a/nx_secure/src/nxe_secure_x509_certificate_initialize.c b/nx_secure/src/nxe_secure_x509_certificate_initialize.c index 6722ae8a..47808a6d 100644 --- a/nx_secure/src/nxe_secure_x509_certificate_initialize.c +++ b/nx_secure/src/nxe_secure_x509_certificate_initialize.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -25,8 +25,8 @@ /* Include necessary system files. */ -#include "nx_secure_tls.h" #include "nx_secure_x509.h" + /* Bring in externs for caller checking code. */ NX_SECURE_CALLER_CHECKING_EXTERNS @@ -36,7 +36,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_certificate_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -77,6 +77,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_certificate_initialize(NX_SECURE_X509_CERT *certificate, UCHAR *certificate_data, @@ -86,9 +89,13 @@ UINT _nxe_secure_x509_certificate_initialize(NX_SECURE_X509_CERT *certificate, U { UINT status; - if ((certificate == NX_NULL) || (certificate_data == NX_NULL) || (length == 0)) + if ((certificate == NX_CRYPTO_NULL) || (certificate_data == NX_CRYPTO_NULL) || (length == 0)) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/nx_secure/src/nxe_secure_x509_common_name_dns_check.c b/nx_secure/src/nxe_secure_x509_common_name_dns_check.c index 4787c1a3..1830fc2f 100644 --- a/nx_secure/src/nxe_secure_x509_common_name_dns_check.c +++ b/nx_secure/src/nxe_secure_x509_common_name_dns_check.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Bring in externs for caller checking code. */ @@ -34,7 +33,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_common_name_dns_check PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_common_name_dns_check(NX_SECURE_X509_CERT *certificate, const UCHAR *dns_tld, @@ -78,9 +80,13 @@ UINT _nxe_secure_x509_common_name_dns_check(NX_SECURE_X509_CERT *certificate, co UINT status; /* Check for pointer errors. */ - if ((certificate == NX_NULL) || (dns_tld == NX_NULL) || (dns_tld_length == 0)) + if ((certificate == NX_CRYPTO_NULL) || (dns_tld == NX_CRYPTO_NULL) || (dns_tld_length == 0)) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/nx_secure/src/nxe_secure_x509_crl_revocation_check.c b/nx_secure/src/nxe_secure_x509_crl_revocation_check.c index 837e3984..c7d4a65a 100644 --- a/nx_secure/src/nxe_secure_x509_crl_revocation_check.c +++ b/nx_secure/src/nxe_secure_x509_crl_revocation_check.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Bring in externs for caller checking code. */ @@ -34,7 +33,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_crl_revocation_check PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_crl_revocation_check(const UCHAR *crl_data, UINT crl_length, @@ -79,9 +81,13 @@ UINT _nxe_secure_x509_crl_revocation_check(const UCHAR *crl_data, UINT crl_lengt UINT status; /* Check for pointer errors. */ - if ((certificate == NX_NULL) || (crl_data == NX_NULL) || (crl_length == 0) || (store == NX_NULL)) + if ((certificate == NX_CRYPTO_NULL) || (crl_data == NX_CRYPTO_NULL) || (crl_length == 0) || (store == NX_CRYPTO_NULL)) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/nx_secure/src/nxe_secure_x509_dns_name_initialize.c b/nx_secure/src/nxe_secure_x509_dns_name_initialize.c index e5edd93e..5c586cb4 100644 --- a/nx_secure/src/nxe_secure_x509_dns_name_initialize.c +++ b/nx_secure/src/nxe_secure_x509_dns_name_initialize.c @@ -15,7 +15,7 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ @@ -25,8 +25,8 @@ /* Include necessary system files. */ -#include "nx_secure_tls.h" #include "nx_secure_x509.h" + /* Bring in externs for caller checking code. */ NX_SECURE_CALLER_CHECKING_EXTERNS @@ -36,7 +36,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_dns_name_initialize PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,6 +71,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_dns_name_initialize(NX_SECURE_X509_DNS_NAME *dns_name, @@ -78,9 +81,13 @@ UINT _nxe_secure_x509_dns_name_initialize(NX_SECURE_X509_DNS_NAME *dns_name, { UINT status; - if (dns_name == NX_NULL) + if (dns_name == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } if (length > NX_SECURE_X509_DNS_NAME_MAX) diff --git a/nx_secure/src/nxe_secure_x509_extended_key_usage_extension_parse.c b/nx_secure/src/nxe_secure_x509_extended_key_usage_extension_parse.c index 29dfdf29..10c744ed 100644 --- a/nx_secure/src/nxe_secure_x509_extended_key_usage_extension_parse.c +++ b/nx_secure/src/nxe_secure_x509_extended_key_usage_extension_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Bring in externs for caller checking code. */ @@ -35,7 +34,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_extended_key_usage_extension_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_extended_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, @@ -77,9 +79,13 @@ UINT _nxe_secure_x509_extended_key_usage_extension_parse(NX_SECURE_X509_CERT *ce { UINT status; - if (certificate == NX_NULL) + if (certificate == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/nx_secure/src/nxe_secure_x509_extension_find.c b/nx_secure/src/nxe_secure_x509_extension_find.c index c87dcccb..42cd2efc 100644 --- a/nx_secure/src/nxe_secure_x509_extension_find.c +++ b/nx_secure/src/nxe_secure_x509_extension_find.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Bring in externs for caller checking code. */ @@ -35,7 +34,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_extension_find PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -70,6 +69,9 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_extension_find(NX_SECURE_X509_CERT *certificate, @@ -77,9 +79,13 @@ UINT _nxe_secure_x509_extension_find(NX_SECURE_X509_CERT *certificate, { UINT status; - if (certificate == NX_NULL || extension == NX_NULL) + if (certificate == NX_CRYPTO_NULL || extension == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/nx_secure/src/nxe_secure_x509_key_usage_extension_parse.c b/nx_secure/src/nxe_secure_x509_key_usage_extension_parse.c index f46e9b48..516992a9 100644 --- a/nx_secure/src/nxe_secure_x509_key_usage_extension_parse.c +++ b/nx_secure/src/nxe_secure_x509_key_usage_extension_parse.c @@ -15,14 +15,13 @@ /** */ /** NetX Secure Component */ /** */ -/** X509 Digital Certificates */ +/** X.509 Digital Certificates */ /** */ /**************************************************************************/ /**************************************************************************/ #define NX_SECURE_SOURCE_CODE -#include "nx_secure_tls.h" #include "nx_secure_x509.h" /* Bring in externs for caller checking code. */ @@ -35,7 +34,7 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* FUNCTION RELEASE */ /* */ /* _nxe_secure_x509_key_usage_extension_parse PORTABLE C */ -/* 6.1 */ +/* 6.1.6 */ /* AUTHOR */ /* */ /* Timothy Stapko, Microsoft Corporation */ @@ -71,15 +70,22 @@ NX_SECURE_CALLER_CHECKING_EXTERNS /* 05-19-2020 Timothy Stapko Initial Version 6.0 */ /* 09-30-2020 Timothy Stapko Modified comment(s), */ /* resulting in version 6.1 */ +/* 04-02-2021 Timothy Stapko Modified comment(s), */ +/* removed dependency on TLS, */ +/* resulting in version 6.1.6 */ /* */ /**************************************************************************/ UINT _nxe_secure_x509_key_usage_extension_parse(NX_SECURE_X509_CERT *certificate, USHORT *bitfield) { UINT status; - if (certificate == NX_NULL || bitfield == NX_NULL) + if (certificate == NX_CRYPTO_NULL || bitfield == NX_CRYPTO_NULL) { +#ifdef NX_CRYPTO_STANDALONE_ENABLE + return(NX_CRYPTO_PTR_ERROR); +#else return(NX_PTR_ERROR); +#endif /* NX_CRYPTO_STANDALONE_ENABLE */ } /* Check for appropriate caller. */ diff --git a/ports/arc_em/metaware/inc/nx_port.h b/ports/arc_em/metaware/inc/nx_port.h index f7e2578f..9a9b75d2 100644 --- a/ports/arc_em/metaware/inc/nx_port.h +++ b/ports/arc_em/metaware/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h ARCv2_EM/MetaWare */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARCv2_EM/MetaWare Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARCv2_EM/MetaWare Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/arc_hs/metaware/inc/nx_port.h b/ports/arc_hs/metaware/inc/nx_port.h index b835210d..568c26fc 100644 --- a/ports/arc_hs/metaware/inc/nx_port.h +++ b/ports/arc_hs/metaware/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h ARC_HS/MetaWare */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARC_HS/MetaWare Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo ARC_HS/MetaWare Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a15/gnu/inc/nx_port.h b/ports/cortex_a15/gnu/inc/nx_port.h index af0f5bda..ffca9192 100644 --- a/ports/cortex_a15/gnu/inc/nx_port.h +++ b/ports/cortex_a15/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A15/GNU */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A15/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A15/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a5/ac5/inc/nx_port.h b/ports/cortex_a5/ac5/inc/nx_port.h index 49b9b833..4f2a0a7a 100644 --- a/ports/cortex_a5/ac5/inc/nx_port.h +++ b/ports/cortex_a5/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A5/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a5/gnu/inc/nx_port.h b/ports/cortex_a5/gnu/inc/nx_port.h index e94fc150..692795c7 100644 --- a/ports/cortex_a5/gnu/inc/nx_port.h +++ b/ports/cortex_a5/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A5/GNU */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a5/iar/inc/nx_port.h b/ports/cortex_a5/iar/inc/nx_port.h index a9d949f0..f08481e4 100644 --- a/ports/cortex_a5/iar/inc/nx_port.h +++ b/ports/cortex_a5/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A5/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a5x/ac6/inc/nx_port.h b/ports/cortex_a5x/ac6/inc/nx_port.h index 711b3683..56d247d1 100644 --- a/ports/cortex_a5x/ac6/inc/nx_port.h +++ b/ports/cortex_a5x/ac6/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A5x/AC6 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5x/AC6 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A5x/AC6 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a7/ac5/inc/nx_port.h b/ports/cortex_a7/ac5/inc/nx_port.h index d1785f33..83d31c22 100644 --- a/ports/cortex_a7/ac5/inc/nx_port.h +++ b/ports/cortex_a7/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A7/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a7/gnu/inc/nx_port.h b/ports/cortex_a7/gnu/inc/nx_port.h index 45eb3696..40ad9764 100644 --- a/ports/cortex_a7/gnu/inc/nx_port.h +++ b/ports/cortex_a7/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A7/GNU */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a7/iar/inc/nx_port.h b/ports/cortex_a7/iar/inc/nx_port.h index f65a5347..1ab441b3 100644 --- a/ports/cortex_a7/iar/inc/nx_port.h +++ b/ports/cortex_a7/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A7/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A7/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a8/ac5/inc/nx_port.h b/ports/cortex_a8/ac5/inc/nx_port.h index 0d4cd364..194fbee2 100644 --- a/ports/cortex_a8/ac5/inc/nx_port.h +++ b/ports/cortex_a8/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A8/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a8/gnu/inc/nx_port.h b/ports/cortex_a8/gnu/inc/nx_port.h index 457b8302..6b5b1ef1 100644 --- a/ports/cortex_a8/gnu/inc/nx_port.h +++ b/ports/cortex_a8/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A8/GNU */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a8/iar/inc/nx_port.h b/ports/cortex_a8/iar/inc/nx_port.h index cd913da5..84188bde 100644 --- a/ports/cortex_a8/iar/inc/nx_port.h +++ b/ports/cortex_a8/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A8/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A8/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a9/ac5/inc/nx_port.h b/ports/cortex_a9/ac5/inc/nx_port.h index 59740ab2..c315586b 100644 --- a/ports/cortex_a9/ac5/inc/nx_port.h +++ b/ports/cortex_a9/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A9/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a9/gnu/inc/nx_port.h b/ports/cortex_a9/gnu/inc/nx_port.h index 9f619662..2281ac9d 100644 --- a/ports/cortex_a9/gnu/inc/nx_port.h +++ b/ports/cortex_a9/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A9/GNU */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a9/iar/inc/nx_port.h b/ports/cortex_a9/iar/inc/nx_port.h index 02ff7a2c..e5365a04 100644 --- a/ports/cortex_a9/iar/inc/nx_port.h +++ b/ports/cortex_a9/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A9/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_a9/rvds/inc/nx_port.h b/ports/cortex_a9/rvds/inc/nx_port.h index 59740ab2..c315586b 100644 --- a/ports/cortex_a9/rvds/inc/nx_port.h +++ b/ports/cortex_a9/rvds/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-A9/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-A9/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m0/ac5/inc/nx_port.h b/ports/cortex_m0/ac5/inc/nx_port.h index a2547cb3..a41a792e 100644 --- a/ports/cortex_m0/ac5/inc/nx_port.h +++ b/ports/cortex_m0/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M0/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m0/gnu/inc/nx_port.h b/ports/cortex_m0/gnu/inc/nx_port.h index 129bbabd..228408ba 100644 --- a/ports/cortex_m0/gnu/inc/nx_port.h +++ b/ports/cortex_m0/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M0/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,9 @@ /* corrected the code of */ /* getting system state, */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -70,16 +73,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -194,7 +187,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m0/iar/CMakeLists.txt b/ports/cortex_m0/iar/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m0/iar/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m0/iar/inc/nx_port.h b/ports/cortex_m0/iar/inc/nx_port.h index 5112ddfd..81215448 100644 --- a/ports/cortex_m0/iar/inc/nx_port.h +++ b/ports/cortex_m0/iar/inc/nx_port.h @@ -181,7 +181,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M0/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m23/ac5/inc/nx_port.h b/ports/cortex_m23/ac5/inc/nx_port.h new file mode 100644 index 00000000..deef1cc4 --- /dev/null +++ b/ports/cortex_m23/ac5/inc/nx_port.h @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/AC5 */ +/* 6.1.11 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/AC5 Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m23/gnu/inc/nx_port.h b/ports/cortex_m23/gnu/inc/nx_port.h new file mode 100644 index 00000000..a9768ffe --- /dev/null +++ b/ports/cortex_m23/gnu/inc/nx_port.h @@ -0,0 +1,192 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/GNU */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/GNU Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m23/iar/inc/nx_port.h b/ports/cortex_m23/iar/inc/nx_port.h new file mode 100644 index 00000000..8965d77c --- /dev/null +++ b/ports/cortex_m23/iar/inc/nx_port.h @@ -0,0 +1,190 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M23/IAR */ +/* 6.1.3 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M23/IAR Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m3/ac5/inc/nx_port.h b/ports/cortex_m3/ac5/inc/nx_port.h index 116ace77..934aa5af 100644 --- a/ports/cortex_m3/ac5/inc/nx_port.h +++ b/ports/cortex_m3/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M3/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m3/gnu/inc/nx_port.h b/ports/cortex_m3/gnu/inc/nx_port.h index 7b624a36..adf0b46c 100644 --- a/ports/cortex_m3/gnu/inc/nx_port.h +++ b/ports/cortex_m3/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M3/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,9 @@ /* corrected the code of */ /* getting system state, */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -70,16 +73,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -194,7 +187,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m3/iar/CMakeLists.txt b/ports/cortex_m3/iar/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m3/iar/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m3/iar/inc/nx_port.h b/ports/cortex_m3/iar/inc/nx_port.h index 3b28987b..701a8e58 100644 --- a/ports/cortex_m3/iar/inc/nx_port.h +++ b/ports/cortex_m3/iar/inc/nx_port.h @@ -181,7 +181,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m3/keil/inc/nx_port.h b/ports/cortex_m3/keil/inc/nx_port.h index fca8d55d..7ad37009 100644 --- a/ports/cortex_m3/keil/inc/nx_port.h +++ b/ports/cortex_m3/keil/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M3/Keil */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/Keil Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M3/Keil Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m33/ac5/inc/nx_port.h b/ports/cortex_m33/ac5/inc/nx_port.h new file mode 100644 index 00000000..ba75cf0a --- /dev/null +++ b/ports/cortex_m33/ac5/inc/nx_port.h @@ -0,0 +1,216 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/AC5 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ +/* xx-xx-xxxx Scott Larson Modified comment(s), and */ +/* fixed whitespace, */ +/* resulting in version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC5 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m33/ac6/CMakeLists.txt b/ports/cortex_m33/ac6/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m33/ac6/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m33/ac6/inc/nx_port.h b/ports/cortex_m33/ac6/inc/nx_port.h new file mode 100644 index 00000000..f85fdbb9 --- /dev/null +++ b/ports/cortex_m33/ac6/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/AC6 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/AC6 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m33/gnu/CMakeLists.txt b/ports/cortex_m33/gnu/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m33/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m33/gnu/inc/nx_port.h b/ports/cortex_m33/gnu/inc/nx_port.h new file mode 100644 index 00000000..d71635c3 --- /dev/null +++ b/ports/cortex_m33/gnu/inc/nx_port.h @@ -0,0 +1,193 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/GNU */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* xx-xx-xxxx Scott Larson Modified comment(s), and */ +/* fixed whitespace, */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/GNU Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m33/iar/inc/nx_port.h b/ports/cortex_m33/iar/inc/nx_port.h new file mode 100644 index 00000000..82fa52d7 --- /dev/null +++ b/ports/cortex_m33/iar/inc/nx_port.h @@ -0,0 +1,193 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M33/IAR */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* xx-xx-xxxx Scott Larson Modified comment(s), and */ +/* fixed whitespace, */ +/* resulting in version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) arg = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) arg = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M33/IAR Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m4/ac5/inc/nx_port.h b/ports/cortex_m4/ac5/inc/nx_port.h index 176f16b1..95195c4e 100644 --- a/ports/cortex_m4/ac5/inc/nx_port.h +++ b/ports/cortex_m4/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M4/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m4/gnu/inc/nx_port.h b/ports/cortex_m4/gnu/inc/nx_port.h index 78cf2369..cc8de360 100644 --- a/ports/cortex_m4/gnu/inc/nx_port.h +++ b/ports/cortex_m4/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M4/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,9 @@ /* corrected the code of */ /* getting system state, */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -70,16 +73,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -194,7 +187,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m4/iar/CMakeLists.txt b/ports/cortex_m4/iar/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m4/iar/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m4/iar/inc/nx_port.h b/ports/cortex_m4/iar/inc/nx_port.h index 4538d36c..ff0174f1 100644 --- a/ports/cortex_m4/iar/inc/nx_port.h +++ b/ports/cortex_m4/iar/inc/nx_port.h @@ -181,7 +181,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m4/keil/inc/nx_port.h b/ports/cortex_m4/keil/inc/nx_port.h index a4fa4b8c..807ce5d4 100644 --- a/ports/cortex_m4/keil/inc/nx_port.h +++ b/ports/cortex_m4/keil/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M4/Keil */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/Keil Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M4/Keil Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m55/ac5/inc/nx_port.h b/ports/cortex_m55/ac5/inc/nx_port.h new file mode 100644 index 00000000..1db6bfcd --- /dev/null +++ b/ports/cortex_m55/ac5/inc/nx_port.h @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M55/AC5 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC5 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m55/ac6/CMakeLists.txt b/ports/cortex_m55/ac6/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m55/ac6/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m55/ac6/inc/nx_port.h b/ports/cortex_m55/ac6/inc/nx_port.h new file mode 100644 index 00000000..415f6f13 --- /dev/null +++ b/ports/cortex_m55/ac6/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M55/AC6 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/AC6 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m55/gnu/CMakeLists.txt b/ports/cortex_m55/gnu/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m55/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m55/gnu/inc/nx_port.h b/ports/cortex_m55/gnu/inc/nx_port.h new file mode 100644 index 00000000..a1202357 --- /dev/null +++ b/ports/cortex_m55/gnu/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M55/GNU */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/GNU Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m55/iar/inc/nx_port.h b/ports/cortex_m55/iar/inc/nx_port.h new file mode 100644 index 00000000..bfc7a599 --- /dev/null +++ b/ports/cortex_m55/iar/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M55/IAR */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M55/IAR Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m7/ac5/inc/nx_port.h b/ports/cortex_m7/ac5/inc/nx_port.h index 0f7ec299..4a68bb20 100644 --- a/ports/cortex_m7/ac5/inc/nx_port.h +++ b/ports/cortex_m7/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M7/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m7/ac6/inc/nx_port.h b/ports/cortex_m7/ac6/inc/nx_port.h new file mode 100644 index 00000000..7f8e4b75 --- /dev/null +++ b/ports/cortex_m7/ac6/inc/nx_port.h @@ -0,0 +1,189 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M7/AC6 */ +/* 6.2.0 */ +/* */ +/* AUTHOR */ +/* */ +/* Tiejun Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Tiejun Zhou Initial Version 6.2.0 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/AC6 Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/cortex_m7/gnu/inc/nx_port.h b/ports/cortex_m7/gnu/inc/nx_port.h index e464dfc4..bc7c9a79 100644 --- a/ports/cortex_m7/gnu/inc/nx_port.h +++ b/ports/cortex_m7/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-M7/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,9 @@ /* corrected the code of */ /* getting system state, */ /* resulting in version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -70,16 +73,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -194,7 +187,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m7/iar/CMakeLists.txt b/ports/cortex_m7/iar/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m7/iar/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m7/iar/inc/nx_port.h b/ports/cortex_m7/iar/inc/nx_port.h index e95e5da5..1023f83f 100644 --- a/ports/cortex_m7/iar/inc/nx_port.h +++ b/ports/cortex_m7/iar/inc/nx_port.h @@ -181,7 +181,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M7/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_m85/ac5/inc/nx_port.h b/ports/cortex_m85/ac5/inc/nx_port.h new file mode 100644 index 00000000..93269270 --- /dev/null +++ b/ports/cortex_m85/ac5/inc/nx_port.h @@ -0,0 +1,209 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M85/AC5 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC5 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m85/ac6/CMakeLists.txt b/ports/cortex_m85/ac6/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m85/ac6/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m85/ac6/inc/nx_port.h b/ports/cortex_m85/ac6/inc/nx_port.h new file mode 100644 index 00000000..07a826c5 --- /dev/null +++ b/ports/cortex_m85/ac6/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M85/AC6 */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/AC6 Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m85/gnu/CMakeLists.txt b/ports/cortex_m85/gnu/CMakeLists.txt new file mode 100644 index 00000000..75c79531 --- /dev/null +++ b/ports/cortex_m85/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m85/gnu/inc/nx_port.h b/ports/cortex_m85/gnu/inc/nx_port.h new file mode 100644 index 00000000..a0f8a268 --- /dev/null +++ b/ports/cortex_m85/gnu/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M85/GNU */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __builtin_bswap32(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __builtin_bswap16(arg) + + +#ifndef htonl +#define htonl(val) __builtin_bswap32(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __builtin_bswap32(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __builtin_bswap16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __builtin_bswap16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/GNU Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_m85/iar/inc/nx_port.h b/ports/cortex_m85/iar/inc/nx_port.h new file mode 100644 index 00000000..25257594 --- /dev/null +++ b/ports/cortex_m85/iar/inc/nx_port.h @@ -0,0 +1,188 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h Cortex-M85/IAR */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-xxxx Scott Larson Initial Version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) (arg) = __REV(arg) +#define NX_CHANGE_USHORT_ENDIAN(arg) (arg) = __REV16(arg) + + +#ifndef htonl +#define htonl(val) __REV(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __REV(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __REV16(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __REV16(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-M85/IAR Version 6.x *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif diff --git a/ports/cortex_r4/ac5/inc/nx_port.h b/ports/cortex_r4/ac5/inc/nx_port.h index 989d3986..9729c34d 100644 --- a/ports/cortex_r4/ac5/inc/nx_port.h +++ b/ports/cortex_r4/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R4/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r4/ac6/inc/nx_port.h b/ports/cortex_r4/ac6/inc/nx_port.h index 81ecd034..31c473ab 100644 --- a/ports/cortex_r4/ac6/inc/nx_port.h +++ b/ports/cortex_r4/ac6/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R4/AC6 */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -66,16 +69,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -190,7 +183,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC6 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/AC6 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r4/gnu/inc/nx_port.h b/ports/cortex_r4/gnu/inc/nx_port.h index 4e898b4b..b9041395 100644 --- a/ports/cortex_r4/gnu/inc/nx_port.h +++ b/ports/cortex_r4/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R4/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -66,16 +69,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -190,7 +183,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r4/iar/inc/nx_port.h b/ports/cortex_r4/iar/inc/nx_port.h index f600f9ee..15a86ab1 100644 --- a/ports/cortex_r4/iar/inc/nx_port.h +++ b/ports/cortex_r4/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R4/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R4/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r5/ac5/inc/nx_port.h b/ports/cortex_r5/ac5/inc/nx_port.h index 02118e47..dd770faa 100644 --- a/ports/cortex_r5/ac5/inc/nx_port.h +++ b/ports/cortex_r5/ac5/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R5/AC5 */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/AC5 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/AC5 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r5/gnu/inc/nx_port.h b/ports/cortex_r5/gnu/inc/nx_port.h index 492ee8ea..b3560b8e 100644 --- a/ports/cortex_r5/gnu/inc/nx_port.h +++ b/ports/cortex_r5/gnu/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R5/GNU */ -/* 6.1 */ +/* 6.x */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ /* */ /**************************************************************************/ @@ -66,16 +69,6 @@ #define NX_LITTLE_ENDIAN 1 -/* By default IPv6 is enabled. */ - -#ifndef FEATURE_NX_IPV6 -#define FEATURE_NX_IPV6 -#endif /* FEATURE_NX_IPV6 */ - -#ifdef NX_DISABLE_IPV6 -#undef FEATURE_NX_IPV6 -#endif /* !NX_DISABLE_IPV6 */ - #include #include #include @@ -190,7 +183,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Cortex-R5/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Cortex-R5/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/cortex_r5/iar/inc/nx_port.h b/ports/cortex_r5/iar/inc/nx_port.h index bbe48f2d..3706ec4a 100644 --- a/ports/cortex_r5/iar/inc/nx_port.h +++ b/ports/cortex_r5/iar/inc/nx_port.h @@ -26,7 +26,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* nx_port.h Cortex-R5/IAR */ -/* 6.1 */ +/* 6.1.11 */ /* */ /* AUTHOR */ /* */ @@ -43,6 +43,9 @@ /* DATE NAME DESCRIPTION */ /* */ /* 09-30-2020 Yuxin Zhou Initial Version 6.1 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ /* */ /**************************************************************************/ @@ -86,19 +89,19 @@ #ifdef NX_LITTLE_ENDIAN #define NX_CHANGE_ULONG_ENDIAN(arg) \ { \ - ULONG i; \ - ULONG tmp; \ - i = (UINT)arg; \ - /* i = A, B, C, D */ \ - tmp = i ^ (((i) >> 16) | (i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ - tmp &= 0xff00ffff; \ - /* tmp = A^C, 0, C^A, D^B */ \ - i = ((i) >> 8) | (i<<24); \ - /* i = D, A, B, C */ \ - i = i ^ ((tmp) >> 8); \ - /* i = D, C, B, A */ \ - arg = i; \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) @@ -201,7 +204,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/IAR Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Cortex-R5/IAR Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/linux/gnu/inc/nx_port.h b/ports/linux/gnu/inc/nx_port.h index 9c5cd997..72991ffc 100644 --- a/ports/linux/gnu/inc/nx_port.h +++ b/ports/linux/gnu/inc/nx_port.h @@ -88,15 +88,15 @@ ULONG _i; \ ULONG _tmp; \ _i = (UINT)arg; \ - /* i = A, B, C, D */ \ + /* _i = A, B, C, D */ \ _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ - /* tmp = i ^ (i ROR 16) = A^C, B^D, C^A, D^B */ \ + /* tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B*/ \ _tmp &= 0xff00ffff; \ /* tmp = A^C, 0, C^A, D^B */ \ _i = ((_i) >> 8) | (_i<<24); \ - /* i = D, A, B, C */ \ + /* _i = D, A, B, C */ \ _i = _i ^ ((_tmp) >> 8); \ - /* i = D, C, B, A */ \ + /* _i = D, C, B, A */ \ arg = _i; \ } #define NX_CHANGE_USHORT_ENDIAN(a) a = ((USHORT)((a >> 8) | (a << 8)) & 0xFFFF) @@ -200,7 +200,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Linux/GNU Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Linux/GNU Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/ports/mips/gnu/inc/nx_port.h b/ports/mips/gnu/inc/nx_port.h new file mode 100644 index 00000000..49307740 --- /dev/null +++ b/ports/mips/gnu/inc/nx_port.h @@ -0,0 +1,200 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h PIC32x/Microchip */ +/* 6.2.0 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 10-31-2022 Zhen Kong Initial PIC32x/Microchip */ +/* Support Version 6.2.0 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + + +/* Default to little endian, since this is what most MIPS targets are. */ + +#define NX_LITTLE_ENDIAN + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 1ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) (a = (((a >> 8) | (a << 8)) & 0xFFFF)) + +#ifndef htonl +#define htonl(val) ((((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF)) +#endif /* htonl */ + +#ifndef ntohl +#define ntohl(val) ((((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF) | (((val) >> 24) & 0x000000FF) ) +#endif /* htonl */ + +#ifndef htons +#define htons(val) NX_CHANGE_USHORT_ENDIAN(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) NX_CHANGE_USHORT_ENDIAN(val) +#endif /*htons */ + +#else + +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ + +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG TX_THREAD_GET_SYSTEM_STATE(); + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG TX_THREAD_GET_SYSTEM_STATE(); + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo PIC32x/MPLAB Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif \ No newline at end of file diff --git a/ports/rxv2/ccrx/inc/nx_port.h b/ports/rxv2/ccrx/inc/nx_port.h new file mode 100644 index 00000000..348707dc --- /dev/null +++ b/ports/rxv2/ccrx/inc/nx_port.h @@ -0,0 +1,217 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/CCRX */ +/* 6.x */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ +/* xx-xx-xxxx Yajun Xia Modified comment(s), */ +/* removed duplicated macros, */ +/* resulting in version 6.x */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/CCRX Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/rxv2/gnu/CMakeLists.txt b/ports/rxv2/gnu/CMakeLists.txt new file mode 100644 index 00000000..9a68d3ef --- /dev/null +++ b/ports/rxv2/gnu/CMakeLists.txt @@ -0,0 +1,9 @@ +target_sources(${PROJECT_NAME} PRIVATE + # {{BEGIN_TARGET_SOURCES}} + + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/rxv2/gnu/inc/nx_port.h b/ports/rxv2/gnu/inc/nx_port.h new file mode 100644 index 00000000..97b364ac --- /dev/null +++ b/ports/rxv2/gnu/inc/nx_port.h @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/GNU */ +/* 6.1.11 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/GNU Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/rxv2/iar/inc/nx_port.h b/ports/rxv2/iar/inc/nx_port.h new file mode 100644 index 00000000..aac75f6f --- /dev/null +++ b/ports/rxv2/iar/inc/nx_port.h @@ -0,0 +1,213 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* nx_port.h RXv2/IAR */ +/* 6.1.11 */ +/* */ +/* AUTHOR */ +/* */ +/* Yuxin Zhou, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the NetX */ +/* real-time TCP/IP function identically on a variety of different */ +/* processor architectures. */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Yuxin Zhou Initial Version 6.1.3 */ +/* 04-25-2022 Yuxin Zhou Modified comment(s), and */ +/* renamed temporary variable, */ +/* resulting in version 6.1.11 */ +/* */ +/**************************************************************************/ + +#ifndef NX_PORT_H +#define NX_PORT_H + +/* Determine if the optional NetX user define file should be used. */ + +#ifdef NX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in nx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "nx_user.h" +#endif + + +/* Default to little endian, since this is what most ARM targets are. */ + +#define NX_LITTLE_ENDIAN 1 + + +#include +#include +#include + + +/* Define various constants for the port. */ + +#ifndef NX_IP_PERIODIC_RATE +#define NX_IP_PERIODIC_RATE 100 /* Default IP periodic rate of 1 second for + ports with 10ms timer interrupts. This + value may be defined instead at the + command line and this value will not be + used. */ +#endif + + +/* Define macros that swap the endian for little endian ports. */ + +#ifdef NX_LITTLE_ENDIAN +#define NX_CHANGE_ULONG_ENDIAN(arg) \ + { \ + ULONG _i; \ + ULONG _tmp; \ + _i = (UINT)arg; \ + /* _i = A, B, C, D */ \ + _tmp = _i ^ (((_i) >> 16) | (_i << 16)); \ + /* _tmp = _i ^ (_i ROR 16) = A^C, B^D, C^A, D^B */ \ + _tmp &= 0xff00ffff; \ + /* _tmp = A^C, 0, C^A, D^B */ \ + _i = ((_i) >> 8) | (_i<<24); \ + /* _i = D, A, B, C */ \ + _i = _i ^ ((_tmp) >> 8); \ + /* _i = D, C, B, A */ \ + arg = _i; \ + } +#define NX_CHANGE_USHORT_ENDIAN(a) a = (((a >> 8) | (a << 8)) & 0xFFFF) + + +#define __SWAP32__(val) ((((val) & 0xFF000000) >> 24 ) | (((val) & 0x00FF0000) >> 8) \ + | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) + +#define __SWAP16__(val) ((((val) & 0xFF00) >> 8) | (((val) & 0x00FF) << 8)) + + +#ifndef htonl +#define htonl(val) __SWAP32__(val) +#endif /* htonl */ +#ifndef ntohl +#define ntohl(val) __SWAP32__(val) +#endif /* htonl */ + +#ifndef htons +#define htons(val) __SWAP16__(val) +#endif /*htons */ + +#ifndef ntohs +#define ntohs(val) __SWAP16__(val) +#endif /*htons */ + +#else +#define NX_CHANGE_ULONG_ENDIAN(a) +#define NX_CHANGE_USHORT_ENDIAN(a) + +#ifndef htons +#define htons(val) (val) +#endif /* htons */ + +#ifndef ntohs +#define ntohs(val) (val) +#endif /* ntohs */ + +#ifndef ntohl +#define ntohl(val) (val) +#endif + +#ifndef htonl +#define htonl(val) (val) +#endif /* htonl */ +#endif + + +/* Define several macros for the error checking shell in NetX. */ + +#ifndef TX_TIMER_PROCESS_IN_ISR + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern TX_THREAD _tx_timer_thread; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) || \ + (_tx_thread_current_ptr == &_tx_timer_thread)) \ + return(NX_CALLER_ERROR); + + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()) || (_tx_thread_current_ptr == &_tx_timer_thread))) \ + return(NX_CALLER_ERROR); + + +#else + + + +#define NX_CALLER_CHECKING_EXTERNS extern TX_THREAD *_tx_thread_current_ptr; \ + extern volatile ULONG _tx_thread_system_state; + +#define NX_THREADS_ONLY_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) || \ + (_tx_thread_current_ptr == TX_NULL)) \ + return(NX_CALLER_ERROR); + +#define NX_INIT_AND_THREADS_CALLER_CHECKING if (((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0)))) \ + return(NX_CALLER_ERROR); + +#define NX_NOT_ISR_CALLER_CHECKING if ((TX_THREAD_GET_SYSTEM_STATE()) && (TX_THREAD_GET_SYSTEM_STATE() < ((ULONG) 0xF0F0F0F0))) \ + return(NX_CALLER_ERROR); + +#define NX_THREAD_WAIT_CALLER_CHECKING if ((wait_option) && \ + ((_tx_thread_current_ptr == NX_NULL) || (TX_THREAD_GET_SYSTEM_STATE()))) \ + return(NX_CALLER_ERROR); + +#endif + + +/* Define the version ID of NetX. This may be utilized by the application. */ + +#ifdef NX_SYSTEM_INIT +CHAR _nx_version_id[] = + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo RXv2/IAR Version 6.2.0 *"; +#else +extern CHAR _nx_version_id[]; +#endif + +#endif + diff --git a/ports/win32/vs_2019/inc/nx_port.h b/ports/win32/vs_2019/inc/nx_port.h index 8a8d9448..3ddaf4b4 100644 --- a/ports/win32/vs_2019/inc/nx_port.h +++ b/ports/win32/vs_2019/inc/nx_port.h @@ -201,7 +201,7 @@ #ifdef NX_SYSTEM_INIT CHAR _nx_version_id[] = - "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Win32/VS2019 Version 6.1 *"; + "Copyright (c) Microsoft Corporation. All rights reserved. * NetX Duo Win32/VS2019 Version 6.2.0 *"; #else extern CHAR _nx_version_id[]; #endif diff --git a/samples/demo_mqtt_client.c b/samples/demo_mqtt_client.c index dfaee330..6005e20d 100644 --- a/samples/demo_mqtt_client.c +++ b/samples/demo_mqtt_client.c @@ -111,7 +111,17 @@ UINT topic_length, message_length; printf("Error in creating MQTT client: 0x%02x\n", status); error_counter++; } - + +#ifdef NXD_MQTT_OVER_WEBSOCKET + status = nxd_mqtt_client_websocket_set(&mqtt_client, (UCHAR *)"test.mosquitto.org", sizeof("test.mosquitto.org") - 1, + (UCHAR *)"/mqtt", sizeof("/mqtt") - 1); + if (status) + { + printf("Error in setting MQTT over WebSocket: 0x%02x\r\n", status); + error_counter++; + } +#endif /* NXD_MQTT_OVER_WEBSOCKET */ + /* Register the disconnect notification function. */ nxd_mqtt_client_disconnect_notify_set(&mqtt_client, my_disconnect_func); diff --git a/samples/demo_netx_duo_lwm2m_client.c b/samples/demo_netx_duo_lwm2m_client.c new file mode 100644 index 00000000..1a33ac15 --- /dev/null +++ b/samples/demo_netx_duo_lwm2m_client.c @@ -0,0 +1,1383 @@ +/* + * This is a demonstration of the NetX LWM2M Client. + */ + +#include "nx_api.h" +#include "nx_lwm2m_client.h" + +#ifndef SAMPLE_DHCP_DISABLE +#include "nxd_dhcp_client.h" +#endif /* SAMPLE_DHCP_DISABLE */ + +#ifndef SAMPLE_DNS_DISABLE +#include "nxd_dns.h" +#endif /* SAMPLE_DNS_DISABLE */ + +#ifdef NX_SECURE_ENABLE_DTLS +#include "nx_secure_dtls_api.h" +#include "nx_crypto_aes.h" +#include "nx_crypto_sha2.h" +#include "nx_crypto_tls_prf_sha256.h" +#endif /* NX_SECURE_ENABLE_DTLS */ + + +/* Enable LWM2M Bootstrap to start Client Initiated Bootstrap. */ +//#define BOOTSTRAP + +/* LwM2M Client endpoint. */ +#ifndef LWM2M_CLIENT_ENDPOINT +#define LWM2M_CLIENT_ENDPOINT "nxlwm2mclient" +#endif /* LWM2M_CLIENT_ENDPOINT */ + +/* IP address of LwM2M Server or LwM2M Bootstrap Server. */ +#ifndef LWM2M_SERVER_ADDRESS +#define LWM2M_SERVER_ADDRESS IP_ADDRESS(23, 97, 187, 154) +#endif /* LWM2M_SERVER_ADDRESS*/ + +/* Port of LwM2M Server or LwM2M Bootstrap Server. */ +#ifndef LWM2M_SERVER_PORT +#define LWM2M_SERVER_PORT 5683 +#endif /* LWM2M_SERVER_PORT*/ + +#ifndef LWM2M_BOOTSTRAP_SERVER_PORT +#define LWM2M_BOOTSTRAP_SERVER_PORT 5783 +#endif /* LWM2M_BOOTSTRAP_SERVER_PORT*/ + +#ifndef LWM2M_SERVER_DTLS_PORT +#define LWM2M_SERVER_DTLS_PORT 5684 +#endif /* LWM2M_SERVER_DTLS_PORT*/ + +#ifndef LWM2M_BOOTSTRAP_SERVER_DTLS_PORT +#define LWM2M_BOOTSTRAP_SERVER_DTLS_PORT 5784 +#endif /* LWM2M_BOOTSTRAP_SERVER_DTLS_PORT */ + +/* LwM2M server ID */ +#ifndef LWM2M_SERVER_ID +#define LWM2M_SERVER_ID 1234 +#endif /* LWM2M_SERVER_ID */ + +/* Use DTLS to establish a secure DTLS connection with LwM2M Server or LwM2M Bootstrap Server. + Note: NX_SECURE_ENABLE_DTLS must be defined, and configure the identity and key. */ +//#define USE_DTLS + +#ifdef NX_SECURE_ENABLE_DTLS +#ifndef LWM2M_DTLS_IDENTITY +#define LWM2M_DTLS_IDENTITY "Identity" +#endif /* LWM2M_DTLS_IDENTITY */ + +/* LWM2M_DTLS_KEY */ +#ifndef LWM2M_DTLS_KEY +#define LWM2M_DTLS_KEY "Key" +#endif /* LWM2M_DTLS_KEY */ +#endif /* NX_SECURE_ENABLE_DTLS */ + + +/* Define the ThreadX and NetX object control blocks... */ +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; +#ifndef SAMPLE_DHCP_DISABLE +static NX_DHCP dhcp_client; +#endif /* SAMPLE_DHCP_DISABLE */ +#ifndef SAMPLE_DNS_DISABLE +static NX_DNS dns_client; +#endif /* SAMPLE_DNS_DISABLE */ + +/* Define the IP thread's stack area. */ +static ULONG ip_thread_stack[2048 / sizeof(ULONG)]; + +/* Define packet pool for the demonstration. */ +static ULONG packet_pool_area[((1536 + sizeof(NX_PACKET)) * 32) / sizeof(ULONG)]; + +/* Define the ARP cache area. */ +static ULONG arp_space_area[512 / sizeof(ULONG)]; + +/* Define an error counter. */ +static ULONG error_counter; + +/* Define application thread. */ +static TX_THREAD main_thread; +static ULONG main_stack[4096 / sizeof(ULONG)]; + +#ifdef BOOTSTRAP +static TX_SEMAPHORE semaphore_bootstarp_finish; +#endif /* BOOTSTRAP */ + +#ifdef NX_SECURE_ENABLE_DTLS + +/* Declare the NULL encrypt */ +extern NX_CRYPTO_METHOD crypto_method_null; + +/* Declare the AES-CCM-8 encrytion method. */ +extern NX_CRYPTO_METHOD crypto_method_aes_ccm_8; + +/* Declare the SHA256 hash method */ +extern NX_CRYPTO_METHOD crypto_method_sha256; + +/* Declare the TLSv1.2 default PRF hash method */ +extern NX_CRYPTO_METHOD crypto_method_tls_prf_sha256; + +/* Declare the MD5 hash method */ +extern NX_CRYPTO_METHOD crypto_method_md5; + +/* Declare the SHA1 hash method */ +extern NX_CRYPTO_METHOD crypto_method_sha1; + +/* Declare the TLSv1.0/1.1 PRF hash method */ +extern NX_CRYPTO_METHOD crypto_method_tls_prf_1; + +/* Declare a placeholder for PSK. */ +extern NX_CRYPTO_METHOD crypto_method_auth_psk; + +/* Lookup table used to map ciphersuites to cryptographic routines. */ +NX_SECURE_TLS_CIPHERSUITE_INFO crypto_ciphersuite_lookup_table[] = +{ + /* Ciphersuite, public cipher, public_auth, session cipher & cipher mode, iv size, key size, hash method, hash size, TLS PRF */ + {TLS_PSK_WITH_AES_128_CCM_8, &crypto_method_null, &crypto_method_auth_psk, &crypto_method_aes_ccm_8, 16, 16, &crypto_method_null, 0, &crypto_method_tls_prf_sha256}, +}; + +/* Define the object we can pass into TLS. */ +const NX_SECURE_TLS_CRYPTO crypto_tls_ciphers = +{ + /* Ciphersuite lookup table and size. */ + crypto_ciphersuite_lookup_table, + sizeof(crypto_ciphersuite_lookup_table) / sizeof(NX_SECURE_TLS_CIPHERSUITE_INFO), + +#ifndef NX_SECURE_DISABLE_X509 + /* X.509 certificate cipher table and size. */ + NX_NULL, + 0, +#endif + +#if (NX_SECURE_TLS_TLS_1_0_ENABLED || NX_SECURE_TLS_TLS_1_1_ENABLED) + &crypto_method_md5, + &crypto_method_sha1, + &crypto_method_tls_prf_1, +#endif + +#if (NX_SECURE_TLS_TLS_1_2_ENABLED) + &crypto_method_sha256, + &crypto_method_tls_prf_sha256 +#endif +}; + +static NX_SECURE_DTLS_SESSION dtls_session; +static UCHAR dtls_metadata_buffer[10 * 1024]; +static UCHAR dtls_packet_buffer[5 * 1024]; +#endif /* NX_SECURE_ENABLE_DTLS */ + +#ifndef SAMPLE_DHCP_DISABLE +#define IPV4_ADDRESS IP_ADDRESS(0, 0, 0, 0) +#define IPV4_NETWORK_MASK IP_ADDRESS(0, 0, 0, 0) +#else +#define IPV4_ADDRESS IP_ADDRESS(10, 1, 0, 212) +#define IPV4_NETWORK_MASK IP_ADDRESS(255, 255, 0, 0) +#define IPV4_GATEWAY_ADDR IP_ADDRESS(10, 1, 0, 1) +#define DNS_SERVER_ADDRESS IP_ADDRESS(10, 1, 0, 1) +#endif /* SAMPLE_DHCP_DISABLE */ + +#ifndef SAMPLE_DNS_DISABLE +static CHAR host_buffer[256]; +#endif /* SAMPLE_DNS_DISABLE */ + +/* Define the Temperature IPSO Resources IDs */ +#define IPSO_TEMPERATURE_OBJECT_ID 3303 +#define IPSO_RESOURCE_MIN_VALUE 5601 +#define IPSO_RESOURCE_MAX_VALUE 5602 +#define IPSO_RESOURCE_RESET_MINMAX 5605 +#define IPSO_RESOURCE_VALUE 5700 +#define IPSO_RESOURCE_UNITS 5701 + +/* Define the Actuation IPSO Resources IDs */ +#define IPSO_ACTUATION_OBJECT_ID 3306 +#define IPSO_RESOURCE_ONOFF 5850 + +/* Define the Temperature Object Instance structure */ +typedef struct +{ + /* The LWM2M Object Instance */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE object_instance; + + /* Resources Data */ + NX_LWM2M_FLOAT32 temperature; + NX_LWM2M_FLOAT32 min_temperature; + NX_LWM2M_FLOAT32 max_temperature; + +} IPSO_TEMPERATURE_INSTANCE; + +/* Define the Actuation Object Instance structure */ +typedef struct +{ + /* The LWM2M Object Instance */ + NX_LWM2M_CLIENT_OBJECT_INSTANCE object_instance; + + /* Resources Data */ + NX_LWM2M_BOOL onoff; + +} IPSO_ACTUATION_INSTANCE; + +/* LWM2M Client data */ +NX_LWM2M_CLIENT client; +ULONG client_stack[4096 / sizeof(ULONG)]; +NX_LWM2M_CLIENT_SESSION session; +NX_LWM2M_CLIENT_FIRMWARE firmware; + +/* Custom Object Data */ +NX_LWM2M_CLIENT_OBJECT temperature_object; +IPSO_TEMPERATURE_INSTANCE temperature_instance; +NX_LWM2M_CLIENT_OBJECT actuation_object; +IPSO_ACTUATION_INSTANCE actuation_instance; +IPSO_ACTUATION_INSTANCE actuation_instance_new; +UINT actuation_instance_new_created = NX_FALSE; + +/* Device Object */ +const CHAR manufacturer[] = "Microsoft Corporation"; + +/* Firmware Update Object (emulation) */ +int firmware_timer = 0; +int firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE; +int firmware_version_number = 1; +const CHAR firmware_name[] = "Test Firmware"; +CHAR firmware_version[] = "Version 1"; + +/***** Substitute your ethernet driver entry function here *********/ +#ifndef NETWORK_DRIVER +#define NETWORK_DRIVER _nx_ram_network_driver +#endif +extern VOID NETWORK_DRIVER(NX_IP_DRIVER *driver_req_ptr); + +#ifndef SAMPLE_DHCP_DISABLE +static void dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + +#ifndef SAMPLE_DNS_DISABLE +static UINT dns_create(); +#endif /* SAMPLE_DNS_DISABLE */ + +#ifdef NX_SECURE_ENABLE_DTLS +static UINT dtls_setup(NX_SECURE_DTLS_SESSION *dtls_session_ptr, UCHAR *key, UINT key_len, UCHAR *identity, UINT identity_len); +#endif /* NX_SECURE_ENABLE_DTLS */ + +static UINT uri_parse(const char *uri, NXD_ADDRESS *ip_addr, UINT *udp_port); + +/* + * Custom Object implementations + */ + +/* IPSO Temperature */ +/* Define the 'Read' Method */ +UINT ipso_temperature_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +IPSO_TEMPERATURE_INSTANCE *temp = ((IPSO_TEMPERATURE_INSTANCE *) instance_ptr); +UINT i; +NX_LWM2M_ID resource_id; + + for (i = 0 ; i < resource_count; i++) + { + nx_lwm2m_client_resource_info_get(&resource[i], &resource_id, NX_NULL); + switch (resource_id) + { + + case IPSO_RESOURCE_MIN_VALUE: + + /* return the minimum measured temperature value */ + nx_lwm2m_client_resource_float32_set(&resource[i], temp -> min_temperature); + break; + + case IPSO_RESOURCE_MAX_VALUE: + + /* return the maximum measured temperature value */ + nx_lwm2m_client_resource_float32_set(&resource[i], temp -> max_temperature); + break; + + case IPSO_RESOURCE_VALUE: + + /* return the temperature value */ + nx_lwm2m_client_resource_float32_set(&resource[i], temp -> temperature); + break; + + case IPSO_RESOURCE_RESET_MINMAX: + + /* Not readable */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + case IPSO_RESOURCE_UNITS: + + /* return the temperature units */ + nx_lwm2m_client_resource_string_set(&resource[i], "Cel", 3); + break; + + default: + + /* unknown resource ID */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + +/* Define the 'Discover' method */ +UINT ipso_temperature_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *resource_count) +{ + if (*resource_count < 5) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* return the list of supported resources IDs */ + *resource_count = 5; + nx_lwm2m_client_resource_info_set(&resources[0], IPSO_RESOURCE_MIN_VALUE, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ); + nx_lwm2m_client_resource_info_set(&resources[1], IPSO_RESOURCE_MAX_VALUE, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ); + nx_lwm2m_client_resource_info_set(&resources[2], IPSO_RESOURCE_RESET_MINMAX, NX_LWM2M_CLIENT_RESOURCE_OPERATION_EXECUTABLE); + nx_lwm2m_client_resource_info_set(&resources[3], IPSO_RESOURCE_VALUE, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ); + nx_lwm2m_client_resource_info_set(&resources[4], IPSO_RESOURCE_UNITS, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ); + + return(NX_SUCCESS); +} + +/* Define the 'Execute' method */ +UINT ipso_temperature_execute(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, const CHAR *args_ptr, UINT args_length) +{ +IPSO_TEMPERATURE_INSTANCE *temp = ((IPSO_TEMPERATURE_INSTANCE *) instance_ptr); +NX_LWM2M_CLIENT_RESOURCE value; +NX_LWM2M_ID resource_id; + + /* Get resource id */ + nx_lwm2m_client_resource_info_get(resource, &resource_id, NX_NULL); + + switch (resource_id) + { + + case IPSO_RESOURCE_MIN_VALUE: + case IPSO_RESOURCE_MAX_VALUE: + case IPSO_RESOURCE_VALUE: + case IPSO_RESOURCE_UNITS: + + /* read-only resource */ + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + + case IPSO_RESOURCE_RESET_MINMAX: + + /* reset min/max values to current temperature */ + nx_lwm2m_client_resource_float32_set(&value, temp -> temperature); + if (temp -> min_temperature != temp -> temperature) + { + temp -> min_temperature = temp -> temperature; + nx_lwm2m_client_resource_info_set(&value, IPSO_RESOURCE_MIN_VALUE, NX_NULL); + nx_lwm2m_client_object_resource_changed(object_ptr, instance_ptr, &value); + } + if (temp -> max_temperature != temp -> temperature) + { + temp -> max_temperature = temp -> temperature; + nx_lwm2m_client_resource_info_set(&value, IPSO_RESOURCE_MAX_VALUE, NX_NULL); + nx_lwm2m_client_object_resource_changed(object_ptr, instance_ptr, &value); + } + + break; + + default: + + /* unknown resource ID */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + + return(NX_SUCCESS); +} + +/* Define the operation callback function of Temperature Object */ +UINT ipso_temperature_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return ipso_temperature_read(object_ptr, object_instance_ptr, resource, *resource_count); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return ipso_temperature_discover(object_ptr, object_instance_ptr, resource, resource_count); + + case NX_LWM2M_CLIENT_OBJECT_EXECUTE: + + /* Call execute function */ + return ipso_temperature_execute(object_ptr, object_instance_ptr, resource, args_ptr, args_length); + default: + + /*Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + } +} + +/* Update the temperature */ +void ipso_temperature_update() +{ +NX_LWM2M_FLOAT32 temp; +NX_LWM2M_CLIENT_RESOURCE value; + + /* Simulate some temperature variation */ + switch (NX_RAND() % 10) + { + case 0: + + temp = temperature_instance.temperature + 0.1f; + break; + + case 1: + + temp = temperature_instance.temperature - 0.1f; + break; + + default: + + temp = temperature_instance.temperature; + break; + } + + if (temp != temperature_instance.temperature) + { + + /* update object value */ + temperature_instance.temperature = temp; + nx_lwm2m_client_resource_info_set(&value, IPSO_RESOURCE_VALUE, NX_NULL); + nx_lwm2m_client_resource_float32_set(&value, temp); + nx_lwm2m_client_object_resource_changed(&temperature_object, &(temperature_instance.object_instance), &value); + + /* update min/max */ + if (temp < temperature_instance.min_temperature) + { + temperature_instance.min_temperature = temp; + nx_lwm2m_client_resource_info_set(&value, IPSO_RESOURCE_MIN_VALUE, NX_NULL); + nx_lwm2m_client_object_resource_changed(&temperature_object, &(temperature_instance.object_instance), &value); + } + if (temp > temperature_instance.max_temperature) + { + temperature_instance.max_temperature = temp; + nx_lwm2m_client_resource_info_set(&value, IPSO_RESOURCE_MAX_VALUE, NX_NULL); + nx_lwm2m_client_object_resource_changed(&temperature_object, &(temperature_instance.object_instance), &value); + } + } +} + +/* IPSO Actuation */ +/* Define the 'Read' Method */ +UINT ipso_actuation_read(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +IPSO_ACTUATION_INSTANCE *act = ((IPSO_ACTUATION_INSTANCE *) instance_ptr); +UINT i; +NX_LWM2M_ID resource_id; + + for (i = 0 ; i < resource_count; i++) + { + nx_lwm2m_client_resource_info_get(&resource[i], &resource_id, NX_NULL); + switch (resource_id) + { + + case IPSO_RESOURCE_ONOFF: + + /* return the on/off value */ + nx_lwm2m_client_resource_boolean_set(&resource[i], act -> onoff); + break; + + default: + + /* unknown resource ID */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + +/* Define the 'Discover' method */ +UINT ipso_actuation_discover(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resources, UINT *resource_count) +{ + if (*resource_count < 1) + { + return(NX_LWM2M_CLIENT_BUFFER_TOO_SMALL); + } + + /* return the list of supported resources IDs */ + *resource_count = 1; + nx_lwm2m_client_resource_info_set(&resources[0], IPSO_RESOURCE_ONOFF, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ_WRITE); + + return(NX_SUCCESS); +} + +/* Define the 'Write' method */ +UINT ipso_actuation_write(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count, UINT flags) +{ +IPSO_ACTUATION_INSTANCE *act = ((IPSO_ACTUATION_INSTANCE *) instance_ptr); +UINT ret; +NX_LWM2M_BOOL onoff; +UINT i; +NX_LWM2M_ID resource_id; + + for (i = 0 ; i < resource_count; i++) + { + nx_lwm2m_client_resource_info_get(&resource[i], &resource_id, NX_NULL); + switch (resource_id) + { + + case IPSO_RESOURCE_ONOFF: + + /* assign on/off boolean value */ + ret = nx_lwm2m_client_resource_boolean_get(&resource[i], &onoff); + if (ret != NX_SUCCESS) + { + /* invalid value type */ + return(ret); + } + if (onoff != act->onoff) + { + act->onoff = onoff; + + printf("Set actuation switch %s\n", onoff ? "On" : "Off"); + } + break; + + default: + + /* unknown resource ID */ + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + +/* Define the 'Create' method */ +UINT ipso_actuation_create(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_ID *instance_id, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +UINT status; + + /* Check if there is free instance */ + if (actuation_instance_new_created) + { + return(NX_LWM2M_CLIENT_NO_MEMORY); + } + + status = ipso_actuation_write(object_ptr, &(actuation_instance_new.object_instance), resource, resource_count, NX_NULL); + if (status) + { + return(status); + } + + /* Add a new instance */ + status = nx_lwm2m_client_object_instance_add(object_ptr, &(actuation_instance_new.object_instance), instance_id); + if (status) + { + return(status); + } + + actuation_instance_new_created = NX_TRUE; + return(NX_SUCCESS); +} + +/* Define the 'Delete' method */ +UINT ipso_actuation_delete(NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *instance_ptr) +{ +UINT status; + + /* Only support deleting the created new instance */ + if (!actuation_instance_new_created || instance_ptr != &(actuation_instance_new.object_instance)) + { + return(NX_LWM2M_CLIENT_METHOD_NOT_ALLOWED); + } + + /* Remove the instance from instance list */ + status = nx_lwm2m_client_object_instance_remove(object_ptr, instance_ptr); + if (status) + { + return(status); + } + + actuation_instance_new_created = NX_FALSE; + return(status); +} + +/* Define the operation callback function of Actuation Object */ +UINT ipso_actuation_operation(UINT operation, NX_LWM2M_CLIENT_OBJECT *object_ptr, NX_LWM2M_CLIENT_OBJECT_INSTANCE *object_instance_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ +UINT write_op; + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return ipso_actuation_read(object_ptr, object_instance_ptr, resource, *resource_count); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + return ipso_actuation_discover(object_ptr, object_instance_ptr, resource, resource_count); + case NX_LWM2M_CLIENT_OBJECT_WRITE: + + /* Get the type of write operation */ + write_op = *(UINT *)args_ptr; + + /* Call write function */ + return ipso_actuation_write(object_ptr, object_instance_ptr, resource, *resource_count, write_op); + case NX_LWM2M_CLIENT_OBJECT_CREATE: + + /* Call create function */ + return ipso_actuation_create(object_ptr, (NX_LWM2M_ID *)args_ptr, resource, *resource_count); + case NX_LWM2M_CLIENT_OBJECT_DELETE: + + /* Call delete function */ + return ipso_actuation_delete(object_ptr, object_instance_ptr); + default: + + /* Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + } +} + +/* Define the 'Read' method */ +UINT device_read(NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT resource_count) +{ +UINT i; +NX_LWM2M_ID resource_id; + + for (i = 0; i < resource_count; i++) + { + nx_lwm2m_client_resource_info_get(&resource[i], &resource_id, NX_NULL); + switch (resource_id) + { + case NX_LWM2M_CLIENT_DEVICE_MANUFACTURER_ID: + + /* return 'Manufacturer' string */ + nx_lwm2m_client_resource_string_set(&resource[i], (CHAR *)manufacturer, sizeof(manufacturer) - 1); + break; + + default: + + return(NX_LWM2M_CLIENT_NOT_FOUND); + } + } + + return(NX_SUCCESS); +} + +/* Define the operation callback function of Device Object */ +UINT device_operation(UINT operation, NX_LWM2M_CLIENT *client_ptr, NX_LWM2M_CLIENT_RESOURCE *resource, UINT *resource_count, VOID *args_ptr, UINT args_length) +{ + + switch (operation) + { + case NX_LWM2M_CLIENT_OBJECT_READ: + + /* Call read function */ + return device_read(client_ptr, resource, *resource_count); + case NX_LWM2M_CLIENT_OBJECT_DISCOVER: + + /* Call discover function */ + *resource_count = 1; + nx_lwm2m_client_resource_info_set(resource, NX_LWM2M_CLIENT_DEVICE_MANUFACTURER_ID, NX_LWM2M_CLIENT_RESOURCE_OPERATION_READ); + return(NX_SUCCESS); + default: + + /* Unsupported operation */ + return(NX_LWM2M_CLIENT_NOT_SUPPORTED); + } +} + +/* Firmware Package URI callback */ +UINT firmware_package_uri(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, const CHAR *uri, UINT uri_length) +{ + + if (uri_length == 0) + { + printf("Firmware package URI: Cancel Download\n"); + + /* cancel package download */ + firmware_timer = 0; + firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE; + + nx_lwm2m_client_firmware_state_set(firmware_ptr, NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE); + nx_lwm2m_client_firmware_result_set(firmware_ptr, NX_LWM2M_CLIENT_FIRMWARE_RESULT_INIT); + } + else if (firmware_timer != 0) + { + printf("Firmware package URI: Download already in progress!\n"); + + /* download in progress */ + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); + } + else + { + static CHAR tmp[256]; + if (uri_length > 255) + { + uri_length = 255; + } + if (uri_length > 0) + { + memcpy(tmp, uri, uri_length); /* Use case of memcpy is verified. */ + } + tmp[uri_length] = 0; + printf("Firmware package URI: start downloading '%s'...\n", tmp); + + /* Emulate the firmware "downloading" */ + firmware_timer = 30; + firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADING; + + nx_lwm2m_client_firmware_state_set(firmware_ptr, NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADING); + nx_lwm2m_client_firmware_result_set(firmware_ptr, NX_LWM2M_CLIENT_FIRMWARE_RESULT_INIT); + } + + return(NX_SUCCESS); +} + +/* Firmware Update callback */ +UINT firmware_update(NX_LWM2M_CLIENT_FIRMWARE *firmware_ptr, NX_LWM2M_BOOL update_objects, const CHAR *args_ptr, UINT args_length) +{ + if (firmware_state == NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADED) + { + printf("Firmware update: start updating firmware...\n"); + + /* Emulate the firmware "updating" */ + firmware_timer = 15; + firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_UPDATING; + + nx_lwm2m_client_firmware_state_set(firmware_ptr, NX_LWM2M_CLIENT_FIRMWARE_STATE_UPDATING); + + return(NX_SUCCESS); + } + + printf("Firmware update: cannot update firmware: invalid state.\n"); + + return(NX_LWM2M_CLIENT_NOT_ACCEPTABLE); +} + +/* Update the firmware state */ +void firmware_state_update() +{ + + /* firmware update timers */ + if (firmware_timer != 0) + { + if (--firmware_timer == 0) + { + if (firmware_state == NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADING) + { + printf("Firmware update: package downloaded!\n"); + firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADED; + + nx_lwm2m_client_firmware_state_set(&firmware, NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADED); + } + else + { + printf("Firmware update: updated!\n"); + firmware_state = NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE; + + nx_lwm2m_client_firmware_state_set(&firmware, NX_LWM2M_CLIENT_FIRMWARE_STATE_IDLE); + nx_lwm2m_client_firmware_result_set(&firmware, NX_LWM2M_CLIENT_FIRMWARE_RESULT_SUCCESS); + + /* Update firmware version */ + firmware_version_number++; + firmware_version[sizeof(firmware_version) - 2] = firmware_version_number + '0'; + nx_lwm2m_client_firmware_package_info_set(&firmware, firmware_name, sizeof(firmware_name) - 1, firmware_version, sizeof(firmware_version) - 1); + } + } + else if (firmware_timer % 5 == 0) + { + printf("Firmware update: %s...\n", firmware_state == NX_LWM2M_CLIENT_FIRMWARE_STATE_DOWNLOADING ? "downloading" : "updating"); + } + } + +} + +/* Define the session state callback */ +void session_callback(NX_LWM2M_CLIENT_SESSION *session_ptr, UINT state) +{ + printf("LWM2M Callback: -> %d\n", state); + + switch (state) + { + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_REQUESTING: + + printf("Start client initiated bootstrap\n"); + break; + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_INITIATED: + + printf("Got message from boostrap server\n"); + break; + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_FINISHED: + + /* Bootstrap session done, we can register to the LWM2M Server */ + printf( "Boostrap finished.\n"); +#ifdef BOOTSTRAP + tx_semaphore_put(&semaphore_bootstarp_finish); +#endif + break; + + case NX_LWM2M_CLIENT_SESSION_BOOTSTRAP_ERROR: + + /* Failed to Bootstrap the LWM2M Client. */ + printf( "Failed to boostrap device, error=%02x\n", nx_lwm2m_client_session_error_get(session_ptr)); + break; + + case NX_LWM2M_CLIENT_SESSION_REGISTERED: + + /* Registration to the LWM2M Client done. */ + printf( "LWM2M device registered.\n"); + break; + + case NX_LWM2M_CLIENT_SESSION_DISABLED: + + /* Registration to the LWM2M Client done. */ + printf( "LWM2M device disabled.\n"); + break; + + case NX_LWM2M_CLIENT_SESSION_DEREGISTERED: + + /* Registration to the LWM2M Client done. */ + printf( "LWM2M device deregistered.\n"); + break; + + case NX_LWM2M_CLIENT_SESSION_ERROR: + + /* Failed to register to the LWM2M Client. */ + printf( "Failed to register device, error=%02x\n", nx_lwm2m_client_session_error_get(session_ptr)); + break; + } +} + +/* Application main thread */ +void application_thread(ULONG info) +{ + +NX_LWM2M_ID server_id = 0; +NXD_ADDRESS server_addr; +UINT udp_port = 0; +UINT status; + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES && defined (BOOTSTRAP) +CHAR *server_uri = NX_NULL; +UINT server_uri_len = 0; +UCHAR security_mode = 0; +#ifdef USE_DTLS +UCHAR *pub_key_or_id = NX_NULL; +UINT pub_key_or_id_len = 0; +UCHAR *secret_key = NX_NULL; +UINT secret_key_len = 0; +#endif /* USE_DTLS */ +#endif /* BOOTSTRAP */ + +#ifndef SAMPLE_DHCP_DISABLE + dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + +#ifndef SAMPLE_DNS_DISABLE + /* Create DNS instance. */ + dns_create(); +#endif /* SAMPLE_DNS_DISABLE */ + + /* Create the LWM2M client */ + status = nx_lwm2m_client_create(&client, &ip_0, &pool_0, LWM2M_CLIENT_ENDPOINT, sizeof(LWM2M_CLIENT_ENDPOINT) - 1, NX_NULL, 0, NX_LWM2M_CLIENT_BINDING_U, client_stack, sizeof(client_stack), 4); + if (status) + { + return; + } + + /* Define our custom objects: */ + /* Add Temperature Object */ + status = nx_lwm2m_client_object_add(&client, &temperature_object, IPSO_TEMPERATURE_OBJECT_ID, ipso_temperature_operation); + if (status) + { + return; + } + + /* Define a single instance */ + temperature_instance.temperature = 22.5f; + temperature_instance.min_temperature = temperature_instance.temperature; + temperature_instance.max_temperature = temperature_instance.temperature; + status = nx_lwm2m_client_object_instance_add(&temperature_object, &temperature_instance.object_instance, NX_NULL); + if (status) + { + return; + } + + /* Add Actuation Object */ + status = nx_lwm2m_client_object_add(&client, &actuation_object, IPSO_ACTUATION_OBJECT_ID, ipso_actuation_operation); + if (status) + { + return; + } + + /* Define a single instance */ + actuation_instance.onoff = NX_FALSE; + status = nx_lwm2m_client_object_instance_add(&actuation_object, &actuation_instance.object_instance, NX_NULL); + if (status) + { + return; + } + + /* Add firmware update object */ + status = nx_lwm2m_client_firmware_create(&firmware, &client, NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_HTTP|NX_LWM2M_CLIENT_FIRMWARE_PROTOCOL_HTTPS, NX_NULL, firmware_package_uri, firmware_update); + if (status) + { + return; + } + + /* Set firmware info */ + nx_lwm2m_client_firmware_package_info_set(&firmware, firmware_name, sizeof(firmware_name) - 1, firmware_version, sizeof(firmware_version) - 1); + + /* Setup device object callback */ + nx_lwm2m_client_device_callback_set(&client, device_operation); + + /* Create a session */ + status = nx_lwm2m_client_session_create(&session, &client, session_callback); + if (status) + { + return; + } + + /* start bootstrap/lwm2m session */ + server_addr.nxd_ip_version = NX_IP_VERSION_V4; + server_addr.nxd_ip_address.v4 = LWM2M_SERVER_ADDRESS; + +#ifdef NX_SECURE_ENABLE_DTLS + + /* Create the DTLS Client Session. */ + dtls_setup(&dtls_session, LWM2M_DTLS_KEY, sizeof(LWM2M_DTLS_KEY) - 1, LWM2M_DTLS_IDENTITY, sizeof(LWM2M_DTLS_IDENTITY) - 1); +#endif /* NX_SECURE_ENABLE_DTLS */ + +#if NX_LWM2M_CLIENT_MAX_SECURITY_INSTANCES && defined (BOOTSTRAP) + +#ifdef USE_DTLS + printf("Start boostraping with DTLS\r\n"); + status = nx_lwm2m_client_session_bootstrap_dtls(&session, 0, &server_addr, LWM2M_BOOTSTRAP_SERVER_DTLS_PORT, &dtls_session); +#else + printf("Start boostraping\r\n"); + status = nx_lwm2m_client_session_bootstrap(&session, 0, &server_addr, LWM2M_BOOTSTRAP_SERVER_PORT); +#endif + if (status) + { + return; + } + + tx_semaphore_get(&semaphore_bootstarp_finish, NX_WAIT_FOREVER); + + /* Get the info for register */ +#ifdef USE_DTLS + status = nx_lwm2m_client_session_register_info_get(&session, NX_LWM2M_CLIENT_RESERVED_ID, &server_id, &server_uri, &server_uri_len, &security_mode, &pub_key_or_id, &pub_key_or_id_len, NX_NULL, NX_NULL, &secret_key, &secret_key_len); + if (status || (security_mode != NX_LWM2M_CLIENT_SECURITY_MODE_PRE_SHARED_KEY)) + { + return; + } +#else + status = nx_lwm2m_client_session_register_info_get(&session, NX_LWM2M_CLIENT_RESERVED_ID, &server_id, &server_uri, &server_uri_len, &security_mode, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL, NX_NULL); + if (status || (security_mode != NX_LWM2M_CLIENT_SECURITY_MODE_NOSEC)) + { + return; + } +#endif + + printf("Got LWM2M server info, uri='%s', id=%d\r\n", server_uri, server_id); + + /* Get IP address and UDP port from server URI */ + status = uri_parse(server_uri, &server_addr, &udp_port); + if (status) + { + return; + } + +#ifdef USE_DTLS + + /* Re-create the DTLS Client Session. */ + nx_secure_dtls_session_delete(&dtls_session); + dtls_setup(&dtls_session, secret_key, secret_key_len, pub_key_or_id, pub_key_or_id_len); +#endif /* USE_DTLS */ + +#else /* !BOOTSTRAP */ + + /* Set the info for register */ + server_id = LWM2M_SERVER_ID; + +#ifdef USE_DTLS + udp_port = LWM2M_SERVER_DTLS_PORT; +#else + udp_port = LWM2M_SERVER_PORT; +#endif /* USE_DTLS */ + +#endif /* BOOTSTRAP */ + +#ifdef USE_DTLS + printf("Register to LWM2M server with DTLS\r\n"); + status = nx_lwm2m_client_session_register_dtls(&session, server_id, &server_addr, udp_port, &dtls_session); +#else + printf("Register to LWM2M server\r\n"); + status = nx_lwm2m_client_session_register(&session, server_id, &server_addr, udp_port); +#endif /* USE_DTLS */ + if (status) + { + return; + } + + /* Application main loop */ + while (1) + { + + /* application code... */ + tx_thread_sleep(NX_IP_PERIODIC_RATE); + + /* Update the firmware state */ + firmware_state_update(); + + /* Update the temperature */ + ipso_temperature_update(); + } + + /* Terminate the LWM2M Client */ + nx_lwm2m_client_delete(&client); +} + +void main(void) +{ + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +void tx_application_define(void *first_unused_memory) +{ +UINT status; + + /* Initialize the NetX system. */ + nx_system_initialize(); + + /* Create a packet pool. */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, (ULONG*)(((int)packet_pool_area + 15) & ~15) , sizeof(packet_pool_area)); + + /* Check for pool creation error. */ + if (status) + error_counter++; + + /* Create an IP instance. */ + status = nx_ip_create(&ip_0, + "NetX IP Instance 0", + IPV4_ADDRESS, + IPV4_NETWORK_MASK, + &pool_0, + NETWORK_DRIVER, + (UCHAR*)ip_thread_stack, + sizeof(ip_thread_stack), + 1); + + /* Check for IP create errors. */ + if (status) + error_counter++; + + /* Enable ARP and supply ARP cache memory for IP Instance 0. */ + status = nx_arp_enable(&ip_0, (void *)arp_space_area, sizeof(arp_space_area)); + + /* Check for ARP enable errors. */ + if (status) + error_counter++; + + /* Check for IP gateway errors. */ + if (status) + error_counter++; + + /* Enable ICMP. */ + status = nxd_icmp_enable(&ip_0); + + /* Check for errors. */ + if (status) + error_counter++; + + /* Enable TCP traffic. */ + status = nx_tcp_enable(&ip_0); + + /* Check for TCP enable errors. */ + if (status) + error_counter++; + + /* Enable UDP traffic. */ + status = nx_udp_enable(&ip_0); + + /* Check for UDP enable errors. */ + if (status) + error_counter++; + +#ifdef BOOTSTRAP + tx_semaphore_create(&semaphore_bootstarp_finish, "semaphore bootstarp finish", 0); +#endif /* BOOTSTRAP */ + + /* Create the main thread. */ + tx_thread_create(&main_thread, "main thread", application_thread, 0, + main_stack, sizeof(main_stack), + 3, 3, TX_NO_TIME_SLICE, TX_AUTO_START); +} + +/* DHCP */ +#ifndef SAMPLE_DHCP_DISABLE +void dhcp_wait(void) +{ + +ULONG actual_status; +ULONG ip_address; +ULONG network_mask; +ULONG gw_address; + + printf("DHCP In Progress...\n"); + + /* Create the DHCP instance. */ + nx_dhcp_create(&dhcp_client, &ip_0, "dhcp_client"); + + /* Start the DHCP Client. */ + nx_dhcp_start(&dhcp_client); + + /* Wait util address is solved. */ + nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER); + + /* Get IP address. */ + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + nx_ip_gateway_address_get(&ip_0, &gw_address); + + /* Output IP address. */ + printf("IP address: %d.%d.%d.%d\r\nMask: %d.%d.%d.%d\r\nGateway: %d.%d.%d.%d\r\n", + (ip_address >> 24), + (ip_address >> 16 & 0xFF), + (ip_address >> 8 & 0xFF), + (ip_address & 0xFF), + (network_mask >> 24), + (network_mask >> 16 & 0xFF), + (network_mask >> 8 & 0xFF), + (network_mask & 0xFF), + (gw_address >> 24), + (gw_address >> 16 & 0xFF), + (gw_address >> 8 & 0xFF), + (gw_address & 0xFF)); +} +#endif /* SAMPLE_DHCP_DISABLE */ + +#ifndef SAMPLE_DNS_DISABLE +/* DNS. */ +static UINT dns_create() +{ + +UINT status; +ULONG dns_server_address[3]; +UINT dns_server_address_size = 12; + + /* Create a DNS instance for the Client. Note this function will create + the DNS Client packet pool for creating DNS message packets intended + for querying its DNS server. */ + status = nx_dns_create(&dns_client, &ip_0, (UCHAR *)"DNS Client"); + if (status) + { + return(status); + } + + /* Is the DNS client configured for the host application to create the packet pool? */ +#ifdef NX_DNS_CLIENT_USER_CREATE_PACKET_POOL + + /* Yes, use the packet pool created above which has appropriate payload size + for DNS messages. */ + status = nx_dns_packet_pool_set(&dns_client, ip_0.nx_ip_default_packet_pool); + if (status) + { + nx_dns_delete(&dns_client); + return(status); + } +#endif /* NX_DNS_CLIENT_USER_CREATE_PACKET_POOL */ + +#ifndef SAMPLE_DHCP_DISABLE + /* Retrieve DNS server address. */ + nx_dhcp_interface_user_option_retrieve(&dhcp_client, 0, NX_DHCP_OPTION_DNS_SVR, (UCHAR *)(dns_server_address), + &dns_server_address_size); +#else + dns_server_address[0] = DNS_SERVER_ADDRESS; +#endif /* SAMPLE_DHCP_DISABLE */ + + /* Add an IPv4 server address to the Client list. */ + status = nx_dns_server_add(&dns_client, dns_server_address[0]); + if (status) + { + nx_dns_delete(&dns_client); + return(status); + } + + /* Output DNS Server address. */ + printf("DNS Server address: %lu.%lu.%lu.%lu\r\n", + (dns_server_address[0] >> 24), + (dns_server_address[0] >> 16 & 0xFF), + (dns_server_address[0] >> 8 & 0xFF), + (dns_server_address[0] & 0xFF)); + + return(NX_SUCCESS); +} +#endif /* SAMPLE_DNS_DISABLE */ + +/* LwM2M server uri parse. */ +static UINT uri_parse(const char *uri, NXD_ADDRESS *ip_addr, UINT *udp_port) +{ +#ifndef SAMPLE_DNS_DISABLE +UINT i; +UINT dot_count = 0; +UINT temp = 0; +ULONG ip_address = 0; +UCHAR address_found = NX_FALSE; + + /* coap-URI = "coap:" "//" host [ ":" port ] path-abempty [ "?" query ] + coaps-URI = "coaps:" "//" host [ ":" port ] path-abempty [ "?" query ] */ + if (memcmp(uri, "coap://", sizeof("coap://") - 1) == 0) + { + + /* Set the host ptr. */ + uri += (sizeof("coap://") - 1); + *udp_port = LWM2M_SERVER_PORT; + } + else if (memcmp(uri, "coaps://", sizeof("coaps://") - 1) == 0) + { + + /* Set the host ptr. */ + uri += (sizeof("coaps://") - 1); + *udp_port = LWM2M_SERVER_DTLS_PORT; + } + else + { + return(NX_NOT_SUCCESSFUL); + } + + /* Try to detect whether the host is numerical IP address. */ + for (i = 0; ; i++) + { + + if (uri[i] >= '0' && uri[i] <= '9') + { + temp = temp * 10 + (uri[i] - '0'); + if (temp > 0xFF ) + { + break; + } + } + else if (uri[i] == '.') + { + if (dot_count++ == 3) + { + break; + } + ip_address = (ip_address << 8) + temp; + temp = 0; + } + else if (uri[i] == ':' || uri[i] == '/' || uri[i] == '\0') + { + if (dot_count != 3) + { + break; + } + ip_address = (ip_address << 8) + temp; + + /* Set the address. */ + ip_addr -> nxd_ip_version = NX_IP_VERSION_V4; + ip_addr -> nxd_ip_address.v4 = ip_address; + address_found = NX_TRUE; + break; + } + else + { + break; + } + } + + /* Split host and port. */ + while(1) + { + if (uri[i] == ':' || uri[i] == '/' || uri[i] == '\0') + { + + /* Store the host uri. */ + if (i == 0 || i >= 255) + { + return(NX_NOT_SUCCESSFUL); + } + memcpy(host_buffer, uri, i); /* Use case of memcpy is verified. */ + host_buffer[i] = NX_NULL; + + if (uri[i] == ':') + { + temp = 0; + i++; + + /* Get port number. */ + while (uri[i] >= '0' && uri[i] <= '9') + { + temp = temp * 10 + (uri[i++] - '0'); + if (temp > 0xFFFF) + { + break; + } + } + + if (temp > 0 && temp <= 0xFFFF) + { + *udp_port = temp; + } + } + break; + } + + i++; + } + + /* Check if found the address. */ + if (address_found == NX_FALSE) + { + + /* Resolve the host name by DNS. */ + if (nxd_dns_host_by_name_get(&dns_client, (UCHAR *)host_buffer, ip_addr, NX_IP_PERIODIC_RATE, NX_IP_VERSION_V4)) + return(NX_NOT_SUCCESSFUL); + } +#else + + /* XXX parse URI for real... */ + ip_addr -> nxd_ip_version = NX_IP_VERSION_V4; + ip_addr -> nxd_ip_address.v4 = LWM2M_SERVER_ADDRESS; + +#ifdef USE_DTLS + *udp_port = LWM2M_SERVER_DTLS_PORT; +#else + *udp_port = LWM2M_SERVER_PORT; +#endif /* USE_DTLS */ + +#endif /* SAMPLE_DNS_DISABLE */ + + return(NX_SUCCESS); +} + +#ifdef NX_SECURE_ENABLE_DTLS +static UINT dtls_setup(NX_SECURE_DTLS_SESSION *dtls_session_ptr, UCHAR *key, UINT key_len, UCHAR *identity, UINT identity_len) +{ +UINT status; + + /* Create the DTLS Client Session. */ + status = nx_secure_dtls_session_create(dtls_session_ptr, &crypto_tls_ciphers, + dtls_metadata_buffer, sizeof(dtls_metadata_buffer), + dtls_packet_buffer, sizeof(dtls_packet_buffer), 0, NX_NULL, 0); + if (status) + { + return(status); + } + + /* Set the PSK. */ + status = nx_secure_tls_psk_add(&(dtls_session_ptr -> nx_secure_dtls_tls_session), + key, key_len, identity, identity_len, NX_NULL, 0); + status += nx_secure_tls_client_psk_set(&(dtls_session_ptr -> nx_secure_dtls_tls_session), + key, key_len, identity, identity_len, NX_NULL, 0); + if (status) + { + nx_secure_dtls_session_delete(dtls_session_ptr); + return(status); + } + + return(NX_SUCCESS); +} +#endif /* NX_SECURE_ENABLE_DTLS */ \ No newline at end of file diff --git a/samples/demo_netx_duo_ptp_client.c b/samples/demo_netx_duo_ptp_client.c new file mode 100644 index 00000000..cb77b07d --- /dev/null +++ b/samples/demo_netx_duo_ptp_client.c @@ -0,0 +1,271 @@ +/* + This is a small demo of the NetX Duo PTP client on the high-performance NetX Duo TCP/IP stack. + This demo relies on ThreadX, NetX Duo and NetX Duo PTP client API to execute the Precision Time + Protocol. + + */ + +#include +#include "nx_api.h" +#include "nxd_ptp_client.h" + +#ifndef SAMPLE_DHCP_DISABLE +#include "nxd_dhcp_client.h" +#endif /* SAMPLE_DHCP_DISABLE */ + +#define PTP_THREAD_PRIORITY 2 + +/* Define the ThreadX and NetX object control blocks... */ +static TX_THREAD thread_0; +static NX_PACKET_POOL pool_0; +static NX_IP ip_0; +#ifndef SAMPLE_DHCP_DISABLE +static NX_DHCP dhcp_client; +#endif /* SAMPLE_DHCP_DISABLE */ +static NX_PTP_CLIENT ptp_client; + +/* Define the IP thread's stack area. */ +static ULONG ip_thread_stack[2048 / sizeof(ULONG)]; + +/* Define packet pool for the demonstration. */ +static ULONG packet_pool_area[((1536 + sizeof(NX_PACKET)) * 32) / sizeof(ULONG)]; + +/* Define the ARP cache area. */ +static ULONG arp_space_area[512 / sizeof(ULONG)]; + +/* Define the main thread. */ +static ULONG thread_0_stack[2048 / sizeof(ULONG)]; +static ULONG ptp_stack[2048 / sizeof(ULONG)]; + +/* Define an error counter. */ +static ULONG error_counter; + +/* Define ptp utc offset. */ +static SHORT ptp_utc_offset = 0; + +#ifndef SAMPLE_DHCP_DISABLE +#define IPV4_ADDRESS IP_ADDRESS(0, 0, 0, 0) +#define IPV4_NETWORK_MASK IP_ADDRESS(0, 0, 0, 0) +#else +#define IPV4_ADDRESS IP_ADDRESS(10, 1, 0, 212) +#define IPV4_NETWORK_MASK IP_ADDRESS(255, 255, 0, 0) +#define IPV4_GATEWAY_ADDR IP_ADDRESS(10, 1, 0, 1) +#define DNS_SERVER_ADDRESS IP_ADDRESS(10, 1, 0, 1) +#endif /* SAMPLE_DHCP_DISABLE */ + +/* Define the main thread entry point. */ +static VOID thread_0_entry(ULONG thread_input); + +/* PTP handler. */ +static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data); + +#ifndef SAMPLE_DHCP_DISABLE +static void dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + +/***** Substitute your ethernet driver entry function here *********/ +#ifndef NETWORK_DRIVER +#define NETWORK_DRIVER _nx_ram_network_driver +#endif +extern VOID NETWORK_DRIVER(NX_IP_DRIVER *driver_req_ptr); + +#ifndef CLOCK_CALLBACK +#define CLOCK_CALLBACK nx_ptp_client_soft_clock_callback +#endif +extern UINT CLOCK_CALLBACK(NX_PTP_CLIENT *client_ptr, UINT operation, + NX_PTP_TIME *time_ptr, NX_PACKET *packet_ptr, + VOID *callback_data); + +#ifdef HARDWARE_SETUP +extern VOID HARDWARE_SETUP(); +#endif + +int main() +{ +#ifdef HARDWARE_SETUP + HARDWARE_SETUP(); +#endif + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); + return 0; +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +UINT status; + + + /* Initialize the NetX system. */ + nx_system_initialize(); + + /* Create a packet pool. */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", 1536, (ULONG*)(((int)packet_pool_area + 15) & ~15) , sizeof(packet_pool_area)); + + /* Check for pool creation error. */ + if (status) + error_counter++; + + /* Create an IP instance. */ + status = nx_ip_create(&ip_0, + "NetX IP Instance 0", + IPV4_ADDRESS, + IPV4_NETWORK_MASK, + &pool_0, + NETWORK_DRIVER, + (UCHAR*)ip_thread_stack, + sizeof(ip_thread_stack), + 1); + + /* Check for IP create errors. */ + if (status) + error_counter++; + + /* Enable ARP and supply ARP cache memory for IP Instance 0. */ + status = nx_arp_enable(&ip_0, (void *)arp_space_area, sizeof(arp_space_area)); + + /* Check for ARP enable errors. */ + if (status) + error_counter++; + + /* Enable TCP traffic. */ + status = nx_tcp_enable(&ip_0); + + /* Check for TCP enable errors. */ + if (status) + error_counter++; + + /* Enable UDP traffic. */ + status = nx_udp_enable(&ip_0); + + /* Check for UDP enable errors. */ + if (status) + error_counter++; + + /* Enable ICMP. */ + status = nx_icmp_enable(&ip_0); + + /* Check for errors. */ + if (status) + error_counter++; + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + thread_0_stack, sizeof(thread_0_stack), + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/* Define the test threads. */ +void thread_0_entry(ULONG thread_input) +{ + +NX_PTP_TIME tm; +NX_PTP_DATE_TIME date; + +#ifndef SAMPLE_DHCP_DISABLE + dhcp_wait(); +#endif /* SAMPLE_DHCP_DISABLE */ + + /* Create the PTP client instance */ + nx_ptp_client_create(&ptp_client, &ip_0, 0, &pool_0, + PTP_THREAD_PRIORITY, (UCHAR *)ptp_stack, sizeof(ptp_stack), + CLOCK_CALLBACK, NX_NULL); + + /* start the PTP client */ + nx_ptp_client_start(&ptp_client, NX_NULL, 0, 0, 0, ptp_event_callback, NX_NULL); + + while(1) + { + + /* read the PTP clock */ + nx_ptp_client_time_get(&ptp_client, &tm); + + /* convert PTP time to UTC date and time */ + nx_ptp_client_utility_convert_time_to_date(&tm, -ptp_utc_offset, &date); + + /* display the current time */ + printf("%2u/%02u/%u %02u:%02u:%02u.%09lu\r\n", date.day, date.month, date.year, date.hour, date.minute, date.second, date.nanosecond); + + tx_thread_sleep(NX_IP_PERIODIC_RATE); + } +} + +static UINT ptp_event_callback(NX_PTP_CLIENT *ptp_client_ptr, UINT event, VOID *event_data, VOID *callback_data) +{ + NX_PARAMETER_NOT_USED(callback_data); + + switch (event) + { + case NX_PTP_CLIENT_EVENT_MASTER: + { + printf("new MASTER clock!\r\n"); + break; + } + + case NX_PTP_CLIENT_EVENT_SYNC: + { + nx_ptp_client_sync_info_get((NX_PTP_CLIENT_SYNC *)event_data, NX_NULL, &ptp_utc_offset); + printf("SYNC event: utc offset=%d\r\n", ptp_utc_offset); + break; + } + + case NX_PTP_CLIENT_EVENT_TIMEOUT: + { + printf("Master clock TIMEOUT!\r\n"); + break; + } + default: + { + break; + } + } + + return 0; +} + +/* DHCP */ +#ifndef SAMPLE_DHCP_DISABLE +void dhcp_wait(void) +{ + +ULONG actual_status; +ULONG ip_address; +ULONG network_mask; +ULONG gw_address; + + printf("DHCP In Progress...\r\n"); + + /* Create the DHCP instance. */ + nx_dhcp_create(&dhcp_client, &ip_0, "dhcp_client"); + + /* Start the DHCP Client. */ + nx_dhcp_start(&dhcp_client); + + /* Wait util address is solved. */ + nx_ip_status_check(&ip_0, NX_IP_ADDRESS_RESOLVED, &actual_status, NX_WAIT_FOREVER); + + /* Get IP address. */ + nx_ip_address_get(&ip_0, &ip_address, &network_mask); + nx_ip_gateway_address_get(&ip_0, &gw_address); + + /* Output IP address. */ + printf("IP address: %d.%d.%d.%d\r\nMask: %d.%d.%d.%d\r\nGateway: %d.%d.%d.%d\r\n", + (INT)(ip_address >> 24), + (INT)(ip_address >> 16 & 0xFF), + (INT)(ip_address >> 8 & 0xFF), + (INT)(ip_address & 0xFF), + (INT)(network_mask >> 24), + (INT)(network_mask >> 16 & 0xFF), + (INT)(network_mask >> 8 & 0xFF), + (INT)(network_mask & 0xFF), + (INT)(gw_address >> 24), + (INT)(gw_address >> 16 & 0xFF), + (INT)(gw_address >> 8 & 0xFF), + (INT)(gw_address & 0xFF)); +} +#endif /* SAMPLE_DHCP_DISABLE */ \ No newline at end of file diff --git a/samples/demo_netx_pppoe_server.c b/samples/demo_netx_pppoe_server.c index c7a88075..0ceffdf8 100644 --- a/samples/demo_netx_pppoe_server.c +++ b/samples/demo_netx_pppoe_server.c @@ -372,6 +372,8 @@ void ppp_server_packet_send(NX_PACKET *packet_ptr) UINT interfaceHandle = 0; #ifdef NX_PPPOE_SERVER_SESSION_CONTROL_ENABLE +NX_PACKET *temp_packet = packet_ptr; + while(packet_ptr) { @@ -381,6 +383,8 @@ UINT interfaceHandle = 0; /* Move to the next packet structure. */ packet_ptr = packet_ptr -> nx_packet_next; } + + nx_packet_transmit_release(temp_packet); #else /* Directly Call PPPoE send function to send out the data through PPPoE module. */ nx_pppoe_server_session_packet_send(&pppoe_server, interfaceHandle, packet_ptr); diff --git a/samples/demo_netxduo_https.c b/samples/demo_netxduo_https.c index 4c1f2a61..c4553a67 100644 --- a/samples/demo_netxduo_https.c +++ b/samples/demo_netxduo_https.c @@ -352,6 +352,7 @@ static NX_SECURE_X509_CERT remote_certificate, remote_issuer; static UCHAR remote_cert_buffer[2000]; static UCHAR remote_issuer_buffer[2000]; +/* For TLS Web servers, define NX_SECURE_ENABLE_AEAD_CIPHER in NetX Crypto to allow web browsers to connect using AES_128_GCM cipher suites. */ extern const NX_SECURE_TLS_CRYPTO nx_crypto_tls_ciphers; #endif /*NX_WEB_HTTPS_ENABLE */ diff --git a/utility/CMakeLists.txt b/utility/CMakeLists.txt new file mode 100644 index 00000000..99f6e16e --- /dev/null +++ b/utility/CMakeLists.txt @@ -0,0 +1,16 @@ +# Each protocol handler is listed below. If you want +# to disable some / all of these, comment out the block(s) in question + +if(NXD_ENABLE_FILE_SERVERS) + target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/iperf/nx_iperf.c + + # {{END_TARGET_SOURCES}} + ) + + target_include_directories(${PROJECT_NAME} PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/iperf + ) +endif() \ No newline at end of file diff --git a/utility/iperf/demo_iperf.c b/utility/iperf/demo_iperf.c new file mode 100644 index 00000000..b26fd7d9 --- /dev/null +++ b/utility/iperf/demo_iperf.c @@ -0,0 +1,167 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX IPerf stack Component */ +/** */ +/** This is a small demo of the high-performance NetX IPerf stack. */ +/** */ +/**************************************************************************/ +/**************************************************************************/ +#include "tx_api.h" +#include "nx_api.h" + +/* Define demo stack size. */ +#define NX_PACKET_POOL_SIZE ((1536 + sizeof(NX_PACKET)) * 30) +#define DEMO_STACK_SIZE 2048 +#define HTTP_STACK_SIZE 2048 +#define IPERF_STACK_SIZE 2048 + +/* Define the ThreadX and NetX object control blocks... */ +TX_THREAD thread_0; +NX_PACKET_POOL pool_0; +NX_IP ip_0; + +UCHAR *pointer; +UCHAR *http_stack; +UCHAR *iperf_stack; +#ifdef FEATURE_NX_IPV6 +NXD_ADDRESS ipv6_address; +#endif + +/* Define the counters used in the demo application... */ +ULONG error_counter; + +/* Define thread prototypes. */ +VOID thread_0_entry(ULONG thread_input); +extern VOID nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR* http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size); + +/***** Substitute your ethernet driver entry function here *********/ +extern VOID _nx_ram_network_driver(NX_IP_DRIVER*); + + +/* Define main entry point. */ +int main() +{ + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +/* Define what the initial system looks like. */ +void tx_application_define(void *first_unused_memory) +{ + +UINT status; + + /* Setup the working pointer. */ + pointer = (UCHAR *) first_unused_memory; + + /* Initialize the NetX system. */ + nx_system_initialize(); + + /* Create a packet pool. */ + status = nx_packet_pool_create(&pool_0, "NetX Main Packet Pool", + (1536 + sizeof(NX_PACKET)), + pointer, NX_PACKET_POOL_SIZE); + pointer = pointer + NX_PACKET_POOL_SIZE; + + /* Check for packet pool create errors. */ + if (status) + error_counter++; + + /* Create an IP instance. */ + status = nx_ip_create(&ip_0, "NetX IP Instance 0", IP_ADDRESS(192, 168, 100, 18), 0xFFFFFF00UL, &pool_0, _nx_ram_network_driver, + pointer, 2048, 1); + pointer = pointer + 2048; + + /* Check for IP create errors. */ + if (status) + error_counter++; + + /* Enable ARP and supply ARP cache memory for IP Instance 0. */ + status = nx_arp_enable(&ip_0, (void *) pointer, 1024); + pointer = pointer + 1024; + + /* Check for ARP enable errors. */ + if (status) + error_counter++; + + /* Enable ICMP */ + status = nx_icmp_enable(&ip_0); + + /* Check for ICMP enable errors. */ + if(status) + error_counter++; + + /* Enable UDP traffic. */ + status = nx_udp_enable(&ip_0); + + /* Check for UDP enable errors. */ + if (status) + error_counter++; + + /* Enable TCP traffic. */ + status = nx_tcp_enable(&ip_0); + + /* Check for TCP enable errors. */ + if (status) + error_counter++; + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + DEMO_STACK_SIZE; + +#ifdef FEATURE_NX_IPV6 + /* Set up the IPv6 address here. */ + ipv6_address.nxd_ip_address.v6[3] = 0x3; + ipv6_address.nxd_ip_address.v6[2] = 0x0; + ipv6_address.nxd_ip_address.v6[1] = 0x0; + ipv6_address.nxd_ip_address.v6[0] = 0xfe800000; + ipv6_address.nxd_ip_version = NX_IP_VERSION_V6; + + /* Enable ICMPv6 services. */ + status = nxd_icmp_enable(&ip_0); + if (status) + error_counter++; + + /* Enable IPv6 services. */ + status = nxd_ipv6_enable(&ip_0); + if (status) + error_counter++; + + status = nxd_ipv6_address_set(&ip_0, 0, &ipv6_address, 10, NX_NULL); + if (status) + error_counter++; +#endif +} + +/* Define the test threads. */ +void thread_0_entry(ULONG thread_input) +{ +#ifdef FEATURE_NX_IPV6 + tx_thread_sleep(5 * NX_IP_PERIODIC_RATE); +#endif + + /* Set the HTTP stack and IPerf stack. */ + http_stack = pointer; + pointer += HTTP_STACK_SIZE; + iperf_stack = pointer; + pointer += IPERF_STACK_SIZE; + + /* Call entry function to start iperf test. */ + nx_iperf_entry(&pool_0, &ip_0, http_stack, HTTP_STACK_SIZE, iperf_stack, IPERF_STACK_SIZE); +} \ No newline at end of file diff --git a/utility/iperf/nx_iperf.c b/utility/iperf/nx_iperf.c new file mode 100644 index 00000000..907b5ad8 --- /dev/null +++ b/utility/iperf/nx_iperf.c @@ -0,0 +1,2454 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Utility */ +/** */ +/** NetX Duo IPerf Test Program */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#include "tx_api.h" +#include "nx_api.h" +#include "nx_iperf.h" +#ifndef NX_WEB_HTTP_NO_FILEX +#include "fx_api.h" +#else +#include "filex_stub.h" +#endif + +#include "nx_web_http_server.h" + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) +#include "tx_execution_profile.h" +#endif /* TX_EXECUTION_PROFILE_ENABLE */ + +/* Define the counters used in the demo application... */ + +NX_WEB_HTTP_SERVER nx_iperf_web_server; +FX_MEDIA nx_iperf_ram_disk; +NX_IP *nx_iperf_test_ip; +NX_PACKET_POOL *nx_iperf_test_pool; +UCHAR *nx_iperf_stack_area; +ULONG nx_iperf_stack_area_size; +ULONG nx_iperf_test_error_counter; +ctrl_info nx_iperf_ctrl_info; + +static NXD_ADDRESS udp_tx_ip_address; +static NXD_ADDRESS tcp_tx_ip_address; + +static ULONG udp_tx_port = NX_IPERF_DESTINATION_PORT; +static ULONG tcp_tx_port = NX_IPERF_DESTINATION_PORT; + +static UINT udp_tx_packet_size = 1470; +static UINT udp_tx_test_time = 10; +static UINT udp_rx_test_time = 10; +static UINT tcp_tx_test_time = 10; +static UINT tcp_rx_test_time = 10; + +static ULONG error_counter; + +NX_TCP_SOCKET tcp_server_socket; +NX_TCP_SOCKET tcp_client_socket; +NX_UDP_SOCKET udp_server_socket; +NX_UDP_SOCKET udp_client_socket; +ULONG thread_tcp_rx_counter; +ULONG thread_tcp_tx_counter; +ULONG thread_udp_rx_counter; +ULONG thread_udp_tx_counter; +static TX_THREAD thread_tcp_rx_iperf; +static TX_THREAD thread_tcp_tx_iperf; +static TX_THREAD thread_udp_rx_iperf; +static TX_THREAD thread_udp_tx_iperf; + +extern ULONG _tx_timer_system_clock; +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) +EXECUTION_TIME thread_time = 0; +EXECUTION_TIME isr_time = 0; +EXECUTION_TIME idle_time = 0; +extern TX_THREAD *_tx_thread_created_ptr; +#endif + + +static void nx_iperf_send_image(NX_WEB_HTTP_SERVER *server_ptr, UCHAR *img, UINT imgsize); +static void nx_iperf_print_tcp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address); +static void nx_iperf_print_tcp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address); +static void nx_iperf_print_udp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address); +static void nx_iperf_print_udp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address); + +void nx_iperf_tcp_rx_test(UCHAR *, ULONG); +void nx_iperf_tcp_tx_test(UCHAR *, ULONG); +void nx_iperf_udp_rx_test(UCHAR *, ULONG); +void nx_iperf_udp_tx_test(UCHAR *, ULONG); + +void nx_iperf_tcp_rx_cleanup(void); +void nx_iperf_tcp_tx_cleanup(void); +void nx_iperf_udp_rx_cleanup(void); +void nx_iperf_udp_tx_cleanup(void); + +char *nx_iperf_get_ip_addr_string(NXD_ADDRESS *ip_address, UINT *string_length); +void nx_iperf_test_info_parse(ctrl_info *iperf_ctrlInfo_ptr); +void nx_iperf_tcp_rx_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port); +void nx_iperf_tcp_rx_disconnect_received(NX_TCP_SOCKET *socket_ptr); +UINT nx_iperf_authentication_check(struct NX_WEB_HTTP_SERVER_STRUCT *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm); +UINT nx_iperf_get_notify(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr); +void nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR *http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size); + +void nx_iperf_thread_tcp_rx_entry(ULONG thread_input); +void nx_iperf_thread_tcp_tx_entry(ULONG thread_input); +void nx_iperf_thread_udp_tx_entry(ULONG thread_input); +void nx_iperf_thread_udp_rx_entry(ULONG thread_input); + +void nx_iperf_entry(NX_PACKET_POOL *pool_ptr, NX_IP *ip_ptr, UCHAR *http_stack, ULONG http_stack_size, UCHAR *iperf_stack, ULONG iperf_stack_size) +{ +UINT status; + + /* Create a TCP server socket. */ + status = nx_tcp_socket_create(nx_iperf_test_ip, &tcp_server_socket, "TCP Server Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 32 * 1024, + NX_NULL, nx_iperf_tcp_rx_disconnect_received); + + /* Check for error. */ + if (status) + { + nx_iperf_test_error_counter++; + return; + } + + /* Create a TCP client socket. */ + status = nx_tcp_socket_create(nx_iperf_test_ip, &tcp_client_socket, "TCP Client Socket", + NX_IP_NORMAL, NX_FRAGMENT_OKAY, NX_IP_TIME_TO_LIVE, 32 * 1024, + NX_NULL, NX_NULL); + + /* Check for error. */ + if (status) + { + nx_iperf_test_error_counter++; + return; + } + + /* Create a UDP server socket. */ + status = nx_udp_socket_create(nx_iperf_test_ip, &udp_server_socket, "UDP Server Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + + /* Check status. */ + if (status) + { + nx_iperf_test_error_counter++; + return; + } + + /* Create a UDP client socket. */ + status = nx_udp_socket_create(nx_iperf_test_ip, &udp_client_socket, "UDP Client Socket", NX_IP_NORMAL, NX_FRAGMENT_OKAY, 0x80, 5); + + /* Check status. */ + if (status) + { + nx_iperf_test_error_counter++; + return; + } + + /* Create the HTTP Server. */ + status = nx_web_http_server_create(&nx_iperf_web_server, "My HTTP Server", ip_ptr, NX_WEB_HTTP_SERVER_PORT, &nx_iperf_ram_disk, http_stack, http_stack_size, pool_ptr, nx_iperf_authentication_check, nx_iperf_get_notify); + + /* Check the status. */ + if (status) + { + + /* Update the error counter and return. */ + nx_iperf_test_error_counter++; + return; + } + + /* Set the iPerf Stack and Size. */ + nx_iperf_stack_area = iperf_stack; + nx_iperf_stack_area_size = iperf_stack_size; + + /* Set the IP instance and Packet Pool. */ + nx_iperf_test_ip = ip_ptr; + nx_iperf_test_pool = pool_ptr; + + /* Start the HTTP Server. */ + status = nx_web_http_server_start(&nx_iperf_web_server); + + /* Check the status. */ + if (status) + { + + /* Update the error counter and return. */ + nx_iperf_test_error_counter++; + return; + } +} + +UINT nx_iperf_authentication_check(struct NX_WEB_HTTP_SERVER_STRUCT *server_ptr, UINT request_type, CHAR *resource, CHAR **name, CHAR **password, CHAR **realm) +{ + + +#ifdef NX_IPERF_AUTH_ENABLE + + NX_PARAMETER_NOT_USED(server_ptr); + NX_PARAMETER_NOT_USED(request_type); + NX_PARAMETER_NOT_USED(resource); + *name = "PlaceholderName"; + *password = "PlaceholderPassword"; + *realm = "test.htm"; + + return(NX_WEB_HTTP_BASIC_AUTHENTICATE); +#else + NX_PARAMETER_NOT_USED(server_ptr); + NX_PARAMETER_NOT_USED(request_type); + NX_PARAMETER_NOT_USED(resource); + NX_PARAMETER_NOT_USED(name); + NX_PARAMETER_NOT_USED(password); + NX_PARAMETER_NOT_USED(realm); + + return(NX_SUCCESS); +#endif +} + +static CHAR device_ip_addr_string[40]; +char *nx_iperf_get_ip_addr_string(NXD_ADDRESS *ip_address, UINT *string_length) +{ +UINT length = 0; +#ifdef FEATURE_NX_IPV6 +UINT i; +#endif + + memset(device_ip_addr_string, 0, sizeof(device_ip_addr_string)); + +#ifdef FEATURE_NX_IPV6 + if (ip_address -> nxd_ip_version == NX_IP_VERSION_V6) + { + for (i = 0; i < 4; i ++) + { + length += _nx_utility_uint_to_string((UINT)ip_address -> nxd_ip_address.v6[i] >> 16, 16, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length); + device_ip_addr_string[length++] = ':'; + length += _nx_utility_uint_to_string((UINT)ip_address -> nxd_ip_address.v6[i] & 0xFFFF, 16, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length); + if (i != 3) + { + device_ip_addr_string[length++] = ':'; + } + } + } + else +#endif + { +#ifndef NX_DISABLE_IPV4 + length = _nx_utility_uint_to_string(ip_address -> nxd_ip_address.v4 >> 24, 10, device_ip_addr_string, sizeof(device_ip_addr_string) - length); + device_ip_addr_string[length++] = '.'; + length += _nx_utility_uint_to_string(((ip_address -> nxd_ip_address.v4 >> 16) & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length); + device_ip_addr_string[length++] = '.'; + length += _nx_utility_uint_to_string(((ip_address -> nxd_ip_address.v4 >> 8) & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length); + device_ip_addr_string[length++] = '.'; + length += _nx_utility_uint_to_string((ip_address -> nxd_ip_address.v4 & 0xFF), 10, &device_ip_addr_string[length], sizeof(device_ip_addr_string) - length); +#endif + } + + *string_length = length; + return device_ip_addr_string; +} + +/* This function takes the token/value pair, and stores the information in the ctrl_info_ptr. */ +/* For example, a token/value pair can be: "TestType"="TC_Rx", and the ctrl_info_ptr stores the information. */ +static void nx_iperf_check_token_value(char *token, char *value_ptr, ctrl_info *ctrl_info_ptr) +{ +UINT val; +UINT i; +UINT token_length = 0; +UINT value_length = 0; +UINT status; + + /* Check string length of token. */ + status = _nx_utility_string_length_check(token, &token_length, NX_MAX_STRING_LENGTH); + if (status) + { + return; + } + + /* Check string length of value. */ + if (value_ptr) + { + status = _nx_utility_string_length_check(value_ptr, &value_length, NX_MAX_STRING_LENGTH); + if (status) + { + return; + } + } + + /* Check for name. */ + if ((token_length == sizeof("TestType") - 1 ) && + (memcmp(token, "TestType", token_length) == 0)) + { + /* Check for value. */ + ctrl_info_ptr -> ctrl_sign = UNKNOWN_TEST; + if (value_ptr) + { + if ((value_length == sizeof(TCP_Rx) - 1 ) && + (memcmp(value_ptr, TCP_Rx, value_length) == 0)) + { + ctrl_info_ptr -> ctrl_sign = TCP_RX_START; + } + else if ((value_length == sizeof(TCP_Tx) - 1 ) && + (memcmp(value_ptr, TCP_Tx, value_length) == 0)) + { + ctrl_info_ptr -> ctrl_sign = TCP_TX_START; + } + else if ((value_length == sizeof(UDP_Rx) - 1 ) && + (memcmp(value_ptr, UDP_Rx, value_length) == 0)) + { + ctrl_info_ptr -> ctrl_sign = UDP_RX_START; + } + else if ((value_length == sizeof(UDP_Tx) - 1 ) && + (memcmp(value_ptr, UDP_Tx, value_length) == 0)) + { + ctrl_info_ptr -> ctrl_sign = UDP_TX_START; + } + } + } + else if ((token_length == (sizeof("ip") - 1)) && + (memcmp(token, "ip", token_length) == 0)) + { + char *ptr = value_ptr; + int colon_sum, colon_count; + ctrl_info_ptr -> ip = 0; + val = 0; + colon_sum = 0; + colon_count = 0; + if (value_ptr == 0) + { + ctrl_info_ptr -> version = NX_IP_VERSION_V4; + } + while (ptr && (*ptr != 0)) + { + if (*ptr == '.') + { + ctrl_info_ptr -> version = NX_IP_VERSION_V4; + while (value_ptr && (*value_ptr != 0)) + { + if (*value_ptr == '.') + { + ctrl_info_ptr -> ip = (ctrl_info_ptr -> ip << 8) + val; + val = 0; + } + else + { + val = val * 10 + ((UINT)(*value_ptr - '0')); + } + value_ptr++; + } + ctrl_info_ptr -> ip = (ctrl_info_ptr -> ip << 8) + val; + break; + } + else if (*ptr == '%') + { + if ((*(++ptr) == '3') && (*(++ptr) == 'A')) + { + ctrl_info_ptr -> version = NX_IP_VERSION_V6; + colon_sum++; + } + } + ptr++; + } + while (value_ptr && (*value_ptr != 0) && (colon_sum != 0)) + { + if (*value_ptr == '%') + { + if ((*(++value_ptr) == '3') && (*(++value_ptr) == 'A')) + { + ctrl_info_ptr -> ipv6[colon_count / 2] = (ctrl_info_ptr -> ipv6[colon_count / 2] << 16) + val; + colon_count++; + + if (*(value_ptr + 1) == '%') + { + value_ptr++; + if ((*(++value_ptr) == '3') && (*(++value_ptr) == 'A')) + { + for (i = 0; i <= (UINT)(7 - colon_sum); i++) + { + ctrl_info_ptr -> ipv6[colon_count / 2] = ctrl_info_ptr -> ipv6[colon_count / 2] << 16; + colon_count++; + } + } + } + val = 0; + } + } + else + { + if (*value_ptr >= '0' && *value_ptr <= '9') + { + val = val * 16 + ((UINT)(*value_ptr - '0')); + } + else if (*value_ptr >= 'a' && *value_ptr <= 'f') + { + val = val * 16 + ((UINT)(*value_ptr - 'a')) + 10; + } + else if (*value_ptr >= 'A' && *value_ptr <= 'F') + { + val = val * 16 + ((UINT)(*value_ptr - 'A')) + 10; + } + } + value_ptr++; + } + if (ctrl_info_ptr -> version == NX_IP_VERSION_V6) + { + ctrl_info_ptr -> ipv6[3] = (ctrl_info_ptr -> ipv6[3] << 16) + val; + } + } + else if ((token_length == (sizeof("test_time") - 1)) && + (memcmp(token, "test_time", token_length) == 0)) + { + ctrl_info_ptr -> TestTime = 0; + while (value_ptr && (*value_ptr != 0)) + { + ctrl_info_ptr -> TestTime = ctrl_info_ptr -> TestTime * 10 + ((UINT)(*value_ptr - '0')); + value_ptr++; + } + ctrl_info_ptr -> TestTime = ctrl_info_ptr -> TestTime * NX_IP_PERIODIC_RATE; + } + else if ((token_length == (sizeof("rate") - 1)) && + (memcmp(token, "rate", token_length) == 0)) + { + ctrl_info_ptr -> Rate = 0; + while (value_ptr && (*value_ptr != 0)) + { + ctrl_info_ptr -> Rate = ctrl_info_ptr -> Rate * 10 + ((UINT)(*value_ptr - '0')); + value_ptr++; + } + } + else if ((token_length == (sizeof("size") - 1)) && + (memcmp(token, "size", token_length) == 0)) + { + ctrl_info_ptr -> PacketSize = 0; + while (value_ptr && (*value_ptr != 0)) + { + ctrl_info_ptr -> PacketSize = ctrl_info_ptr -> PacketSize * 10 + ((UINT)(*value_ptr - '0')); + value_ptr++; + } + } + else if ((token_length == (sizeof("port") - 1)) && + (memcmp(token, "port", token_length) == 0)) + { + ctrl_info_ptr -> port = 0; + while (value_ptr && (*value_ptr != 0)) + { + ctrl_info_ptr -> port = ctrl_info_ptr -> port * 10 + ((UINT)(*value_ptr - '0')); + value_ptr++; + } + } +} + +/* This function parses the incoming HTTP command line. For each token/value pair, it + invokes the nx_iperf_check_token_value routine to parse the values. */ +static void nx_iperf_parse_command(NX_PACKET *packet_ptr, ctrl_info *ctrl_info_ptr) +{ +UCHAR *cmd_string = packet_ptr -> nx_packet_prepend_ptr; +UCHAR *token = NX_NULL; +UCHAR *end_cmd; +UCHAR *next_token; +UCHAR *value_ptr; + + /* At this point, cmd_string points to the beginning of the HTTP request, + which takes the form of: + "GET /test.htm?TestType=xxxxx&ip=....&rxed_pkts=xxxx&test_time=xxxx&tputs=xxxx" */ + + /* First skip the "Get /test.html?" string. */ + cmd_string += (sizeof("GET /test.htm?") - 1); + + /* Find the end of the cmd string, */ + end_cmd = cmd_string; + while (end_cmd < packet_ptr -> nx_packet_append_ptr) + { + if (*end_cmd == ' ') + { + break; + } + end_cmd++; + } + *end_cmd = 0; + + /* The first token starts from cmd_string. */ + token = cmd_string; + next_token = cmd_string; + while (next_token < end_cmd) + { + /* Find the next token .*/ + while (next_token < end_cmd) + { + if (*next_token == '=') + { + break; + } + next_token++; + } + + if (*next_token == '=') + { + /* Find a name=value pair. Now we need to find the "=" sign. */ + *next_token = 0; + value_ptr = next_token + 1; + next_token++; + + while (next_token < end_cmd) + { + if (*next_token == '&') + { + *next_token = 0; + + break; + } + next_token++; + } + + if (value_ptr == next_token) + { + /* There is no value string. */ + value_ptr = NX_NULL; + } + + /* Move next_token beyond the NULL terminator. */ + next_token++; + + + nx_iperf_check_token_value((char *)token, (char *)value_ptr, ctrl_info_ptr); + } + token = next_token; + } + + /* Finished parsing the whole command. */ +} + +static CHAR mytempstring[30]; +static VOID nx_iperf_print_main_test_window(NX_WEB_HTTP_SERVER *server_ptr) +{ +NX_PACKET *resp_packet_ptr; +UINT status; +NXD_ADDRESS server_ip; +UINT length = 0; +CHAR *ip_addr_string; + +#ifdef FEATURE_NX_IPV6 +UINT address_index; +ULONG prefix_length; +UINT interface_index; +#endif + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + + /* write HTML code into the packet */ + /* htmlwrite(p,s,l) (nx_packet_data_append(p,s,l, server_ptr-> nx_web_http_server_packet_pool_ptr,NX_WAIT_FOREVER)) */ + + status += htmlwrite(resp_packet_ptr, outtermosttable, sizeof(outtermosttable) - 1); + status += htmlwrite(resp_packet_ptr, maintabletag, sizeof(maintabletag) - 1); + + /* print the IP address line. */ + status += htmlwrite(resp_packet_ptr, h1line1, sizeof(h1line1) - 1); + +#ifndef NX_DISABLE_IPV4 + server_ip.nxd_ip_version = NX_IP_VERSION_V4; + server_ip.nxd_ip_address.v4 = nx_iperf_test_ip -> nx_ip_interface[0].nx_interface_ip_address; + ip_addr_string = nx_iperf_get_ip_addr_string(&server_ip, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, "\n", sizeof("\n") - 1); +#endif + +#ifdef FEATURE_NX_IPV6 + address_index = 0; + + /* Loop to output the IPv6 address. */ + while (1) + { + + /* Get the IPv6 address. */ + if (nxd_ipv6_address_get(nx_iperf_test_ip, address_index, &server_ip, &prefix_length, &interface_index) == NX_SUCCESS) + { + ip_addr_string = nx_iperf_get_ip_addr_string(&server_ip, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, "\n", sizeof("\n") - 1); + address_index++; + } + else + { + break; + } + } +#endif + + status += htmlwrite(resp_packet_ptr, h1line2, sizeof(h1line2) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, udptxsubmittag1, sizeof(udptxsubmittag1) - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(&udp_tx_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, udptxsubmittag2, sizeof(udptxsubmittag2) - 1); + length = _nx_utility_uint_to_string(udp_tx_port, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, udptxsubmittag3, sizeof(udptxsubmittag3) - 1); + length = _nx_utility_uint_to_string(udp_tx_test_time, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, udptxsubmittag4, sizeof(udptxsubmittag4) - 1); + length = _nx_utility_uint_to_string(udp_tx_packet_size, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, udptxsubmittag5, sizeof(udptxsubmittag5) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, udprxsubmittag1, sizeof(udprxsubmittag1) - 1); + length = _nx_utility_uint_to_string(udp_rx_test_time, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, udprxsubmittag2, sizeof(udprxsubmittag2) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, tcptxsubmittag1, sizeof(tcptxsubmittag1) - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(&tcp_tx_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, tcptxsubmittag2, sizeof(tcptxsubmittag2) - 1); + length = _nx_utility_uint_to_string(tcp_tx_port, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, tcptxsubmittag3, sizeof(tcptxsubmittag3) - 1); + length = _nx_utility_uint_to_string(tcp_tx_test_time, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, tcptxsubmittag4, sizeof(tcptxsubmittag4) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, tcprxsubmittag1, sizeof(tcprxsubmittag1) - 1); + length = _nx_utility_uint_to_string(tcp_rx_test_time, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, tcprxsubmittag2, sizeof(tcprxsubmittag2) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } +} + +static void nx_iperf_print_end_of_page(NX_WEB_HTTP_SERVER *server_ptr) +{ +UINT status; +NX_PACKET *resp_packet_ptr; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + + /* End of the page. */ + status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); /* outtermost table. */ + status += htmlwrite(resp_packet_ptr, doublebr, sizeof(doublebr) - 1); + status += htmlwrite(resp_packet_ptr, centerendtag, sizeof(centerendtag) - 1); + status += htmlwrite(resp_packet_ptr, bodyendtag, sizeof(bodyendtag) - 1); + status += htmlwrite(resp_packet_ptr, htmlendtag, sizeof(htmlendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } +} + +static void nx_iperf_print_header(NX_WEB_HTTP_SERVER *server_ptr) +{ +NX_PACKET *resp_packet_ptr; +UINT status; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + + + /* write HTML code into the packet */ + /* htmlwrite(p,s,l) (nx_packet_data_append(p,s,l, server_ptr-> nx_web_http_server_packet_pool_ptr,NX_WAIT_FOREVER)) */ + + status += htmlwrite(resp_packet_ptr, htmlresponse, sizeof(htmlresponse) - 1); + status += htmlwrite(resp_packet_ptr, htmltag, sizeof(htmltag) - 1); + status += htmlwrite(resp_packet_ptr, titleline, sizeof(titleline) - 1); + status += htmlwrite(resp_packet_ptr, bodytag, sizeof(bodytag) - 1); + status += htmlwrite(resp_packet_ptr, logo_area, sizeof(logo_area) - 1); + status += htmlwrite(resp_packet_ptr, hrline, sizeof(hrline) - 1); + status += htmlwrite(resp_packet_ptr, centertag, sizeof(centertag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } +} + + +static void nx_iperf_print_test_inprogress(NX_WEB_HTTP_SERVER *server_ptr, char *msg) +{ +NX_PACKET *resp_packet_ptr; +UINT status; +UINT length = 0; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, tdcentertag, sizeof(tdcentertag) - 1); + status += htmlwrite(resp_packet_ptr, fontcolortag, sizeof(fontcolortag) - 1); + _nx_utility_string_length_check(msg, &length, NX_MAX_STRING_LENGTH); + status += htmlwrite(resp_packet_ptr, msg, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } +} + +static void nx_iperf_print_empty_line(NX_WEB_HTTP_SERVER *server_ptr) +{ +NX_PACKET *resp_packet_ptr; +UINT status = 0; + + status += nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, &resp_packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + status += htmlwrite(resp_packet_ptr, choosetesttag, sizeof(choosetesttag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } +} + +static void nx_iperf_send_test_result_info(NX_WEB_HTTP_SERVER *server_ptr) +{ +char *response_string = NX_NULL; +NXD_ADDRESS peer_ip_address; + + if (nx_iperf_ctrl_info.TestStatus == 0) + { + nx_iperf_print_empty_line(server_ptr); + + /* No test is running. Do nothing. */ + return; + } + else if (nx_iperf_ctrl_info.TestStatus == 1) + { + switch (nx_iperf_ctrl_info.ctrl_sign) + { + case UDP_RX_START: + response_string = "UDP Receive Test started. After the iperf test finishes, click here to get results."; + break; + case TCP_RX_START: + response_string = "TCP Receive Test started. After the iperf test finishes, click here to get results."; + break; + case UDP_TX_START: + response_string = "UDP Transmit Test starts in 2 seconds. After iperf test is done, click here to get results."; + break; + case TCP_TX_START: + response_string = "TCP Transmit test starts in 2 seconds. After iperf test is done, click here to get results."; + break; + } + nx_iperf_print_test_inprogress(server_ptr, response_string); + } + else if (nx_iperf_ctrl_info.TestStatus == 2) + { + + /* Check the ThroughPut value and StartTime, + if the StartTime is zero means no connection. + if throughput value is zero means maybe user interrupt the test. + recalculate the ThroughPut before Interrupt. */ + if ((!nx_iperf_ctrl_info.ThroughPut) && (nx_iperf_ctrl_info.StartTime)) + { + + /* Calculate the run time and Throughput(Mbps). */ + nx_iperf_ctrl_info.RunTime = tx_time_get() - nx_iperf_ctrl_info.StartTime; + + /* Check the run time. */ + if (nx_iperf_ctrl_info.RunTime > nx_iperf_ctrl_info.TestTime) + { + nx_iperf_ctrl_info.RunTime = nx_iperf_ctrl_info.TestTime; + } + + /* Calculate Throughput(Mbps). */ + nx_iperf_ctrl_info.ThroughPut = (nx_iperf_ctrl_info.BytesTxed + nx_iperf_ctrl_info.BytesRxed) / nx_iperf_ctrl_info.RunTime * NX_IP_PERIODIC_RATE / 125000; + } + + peer_ip_address.nxd_ip_version = nx_iperf_ctrl_info.version; + +#ifdef FEATURE_NX_IPV6 + if (peer_ip_address.nxd_ip_version == NX_IP_VERSION_V6) + { + peer_ip_address.nxd_ip_address.v6[0] = nx_iperf_ctrl_info.ipv6[0]; + peer_ip_address.nxd_ip_address.v6[1] = nx_iperf_ctrl_info.ipv6[1]; + peer_ip_address.nxd_ip_address.v6[2] = nx_iperf_ctrl_info.ipv6[2]; + peer_ip_address.nxd_ip_address.v6[3] = nx_iperf_ctrl_info.ipv6[3]; + } + else +#endif + { +#ifndef NX_DISABLE_IPV4 + peer_ip_address.nxd_ip_address.v4 = nx_iperf_ctrl_info.ip; +#endif + } + + switch (nx_iperf_ctrl_info.ctrl_sign) + { + case UDP_RX_START: + nx_iperf_print_udp_rx_results(server_ptr, &peer_ip_address); + break; + case TCP_RX_START: + nx_iperf_print_tcp_rx_results(server_ptr, &peer_ip_address); + break; + case UDP_TX_START: + nx_iperf_print_udp_tx_results(server_ptr, &peer_ip_address); + break; + case TCP_TX_START: + nx_iperf_print_tcp_tx_results(server_ptr, &peer_ip_address); + break; + } + memset(&nx_iperf_ctrl_info, 0, sizeof(nx_iperf_ctrl_info)); + } +} + +UINT nx_iperf_get_notify(NX_WEB_HTTP_SERVER *server_ptr, UINT request_type, CHAR *resource, NX_PACKET *packet_ptr) +{ +ctrl_info new_cmd; +UINT status; +ULONG port; +UINT length; + + NX_PARAMETER_NOT_USED(request_type); + + memset(&new_cmd, 0, sizeof(ctrl_info)); + + /* Get peer IP address. */ + status = nxd_tcp_socket_peer_info_get(&server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket, &udp_tx_ip_address, &port); + if (status) + { + return(status); + } + tcp_tx_ip_address = udp_tx_ip_address; + + /* Disconnect to mark the end of respond. */ +#ifndef NX_WEB_HTTP_KEEPALIVE_DISABLE + server_ptr -> nx_web_http_server_keepalive = NX_FALSE; +#endif + + _nx_utility_string_length_check(resource, &length, NX_WEB_HTTP_MAX_RESOURCE); + if (((length == sizeof("/test.htm") - 1) && (memcmp(resource, "/test.htm", length) == 0)) || + ((length == 1) && *resource == '/')) + { + + /* Printer the header. */ + nx_iperf_print_header(server_ptr); + + /* Parse the command. */ + nx_iperf_parse_command(packet_ptr, &new_cmd); + + /* If the current test is still running, and we have a new command, + we need to clean up the current one. */ + if (new_cmd.ctrl_sign) + { + if ((nx_iperf_ctrl_info.TestStatus != 0) || ((nx_iperf_ctrl_info.ctrl_sign & NX_IPERF_CLEAN_UP_MASK) == 1)) + { + + switch (nx_iperf_ctrl_info.ctrl_sign) + { + case TCP_RX_START: + nx_iperf_tcp_rx_cleanup(); + break; + case TCP_TX_START: + nx_iperf_tcp_tx_cleanup(); + break; + case UDP_RX_START: + nx_iperf_udp_rx_cleanup(); + break; + case UDP_TX_START: + nx_iperf_udp_tx_cleanup(); + break; + default: + break; + } + memset(&nx_iperf_ctrl_info, 0, sizeof(nx_iperf_ctrl_info)); + } + + memcpy(&nx_iperf_ctrl_info, &new_cmd, sizeof(ctrl_info)); /* Use case of memcpy is verified. */ + + /* Create the test thread and run the test. */ + nx_iperf_test_info_parse(&nx_iperf_ctrl_info); + + /* Update the TestStatus. */ + nx_iperf_ctrl_info.TestStatus = 1; + } + + /* Check the status, set the default value. */ + if (nx_iperf_ctrl_info.TestStatus == 0) + { + + /* Check the IP version. */ + if (udp_tx_ip_address.nxd_ip_version == NX_IP_VERSION_V4) + { + udp_tx_packet_size = 1470; + } + else + { + udp_tx_packet_size = 1450; + } + } + + /* Print the main window. */ + nx_iperf_print_main_test_window(server_ptr); + + /* If there is a new command, show the result of launching the command. */ + nx_iperf_send_test_result_info(server_ptr); + + nx_iperf_print_end_of_page(server_ptr); + + /* Update the TestStatus. */ + if (nx_iperf_ctrl_info.TestStatus == 1) + { + nx_iperf_ctrl_info.TestStatus = 2; + } + + return(NX_WEB_HTTP_CALLBACK_COMPLETED); + } + /* send the logo files */ + if ((length == sizeof("/nxlogo.png") - 1) && (memcmp(resource, "/nxlogo.png", length) == 0)) + { + nx_iperf_send_image(server_ptr, (UCHAR *)nxlogo_png, nxlogo_png_size); + return(NX_WEB_HTTP_CALLBACK_COMPLETED); + } + + if ((length == sizeof("/mslogo.jpg") - 1) && (memcmp(resource, "/mslogo.jpg", length) == 0)) + { + nx_iperf_send_image(server_ptr, (UCHAR *)mslogo_jpg, mslogo_jpg_size); + return(NX_WEB_HTTP_CALLBACK_COMPLETED); + } + + return(NX_SUCCESS); +} + +static void nx_iperf_send_image(NX_WEB_HTTP_SERVER *server_ptr, UCHAR *img, UINT imgsize) +{ + +UINT remaining; +UCHAR *position; +UINT max_size; +UINT status; +NX_PACKET *resp_packet_ptr; + + /* Generate HTTP header. */ + status = nx_web_http_server_callback_generate_response_header(server_ptr, + &resp_packet_ptr, NX_WEB_HTTP_STATUS_OK, imgsize, "image/jpeg", NX_NULL); + if (status) + { + return; + } + + status = nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + if (status) + { + nx_packet_release(resp_packet_ptr); + return; + } + + status = nx_tcp_socket_mss_get(&(server_ptr -> nx_web_http_server_current_session_ptr -> nx_tcp_session_socket), (ULONG *)&max_size); + if (status) + { + return; + } + + remaining = imgsize; + position = img; + while (remaining) + { + if (remaining > max_size) + { + nx_web_http_server_callback_data_send(server_ptr, (void *)position, max_size); + position += max_size; + remaining -= max_size; + } + else + { + nx_web_http_server_callback_data_send(server_ptr, (void *)position, remaining); + remaining = 0; + } + } +} + + +void nx_iperf_test_info_parse(ctrl_info *iperf_ctrlInfo_ptr) +{ + + /* Check the sign and set the related parameters. */ + switch ((iperf_ctrlInfo_ptr -> ctrl_sign) & NX_IPERF_CTRL_SIGN_MASK) + { + + case TCP_RX_START: + { + if (iperf_ctrlInfo_ptr -> TestTime == 0) + { + iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE; + } + tcp_rx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE); + + nx_iperf_tcp_rx_test(nx_iperf_stack_area, nx_iperf_stack_area_size); + break; + } + + case TCP_TX_START: + { + + if (iperf_ctrlInfo_ptr -> TestTime == 0) + { + iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE; + } + tcp_tx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE); + + /* Set the transmit ip address. */ + if (iperf_ctrlInfo_ptr -> version == NX_IP_VERSION_V4) + { +#ifndef NX_DISABLE_IPV4 + tcp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V4; + tcp_tx_ip_address.nxd_ip_address.v4 = iperf_ctrlInfo_ptr -> ip; +#else + break; +#endif + } + +#ifdef FEATURE_NX_IPV6 + else + { + tcp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V6; + tcp_tx_ip_address.nxd_ip_address.v6[0] = iperf_ctrlInfo_ptr -> ipv6[0]; + tcp_tx_ip_address.nxd_ip_address.v6[1] = iperf_ctrlInfo_ptr -> ipv6[1]; + tcp_tx_ip_address.nxd_ip_address.v6[2] = iperf_ctrlInfo_ptr -> ipv6[2]; + tcp_tx_ip_address.nxd_ip_address.v6[3] = iperf_ctrlInfo_ptr -> ipv6[3]; + } +#endif + tcp_tx_port = iperf_ctrlInfo_ptr -> port; + + nx_iperf_tcp_tx_test(nx_iperf_stack_area, nx_iperf_stack_area_size); + break; + } + + case UDP_RX_START: + { + if (iperf_ctrlInfo_ptr -> TestTime == 0) + { + iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE; + } + udp_rx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE); + + nx_iperf_udp_rx_test(nx_iperf_stack_area, nx_iperf_stack_area_size); + break; + } + + case UDP_TX_START: + { + if (iperf_ctrlInfo_ptr -> TestTime == 0) + { + iperf_ctrlInfo_ptr -> TestTime = 10 * NX_IP_PERIODIC_RATE; + } + udp_tx_test_time = (UINT)((iperf_ctrlInfo_ptr -> TestTime) / NX_IP_PERIODIC_RATE); + + if ((iperf_ctrlInfo_ptr -> PacketSize == 0) || (iperf_ctrlInfo_ptr -> PacketSize > 1470)) + { + iperf_ctrlInfo_ptr -> PacketSize = 1470; + } + udp_tx_packet_size = (UINT)(iperf_ctrlInfo_ptr -> PacketSize); + udp_tx_port = iperf_ctrlInfo_ptr -> port; + + /* Set the transmit ip address. */ + if (iperf_ctrlInfo_ptr -> version == NX_IP_VERSION_V4) + { +#ifndef NX_DISABLE_IPV4 + udp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V4; + udp_tx_ip_address.nxd_ip_address.v4 = iperf_ctrlInfo_ptr -> ip; +#else + break; +#endif + } + +#ifdef FEATURE_NX_IPV6 + else + { + udp_tx_ip_address.nxd_ip_version = NX_IP_VERSION_V6; + udp_tx_ip_address.nxd_ip_address.v6[0] = iperf_ctrlInfo_ptr -> ipv6[0]; + udp_tx_ip_address.nxd_ip_address.v6[1] = iperf_ctrlInfo_ptr -> ipv6[1]; + udp_tx_ip_address.nxd_ip_address.v6[2] = iperf_ctrlInfo_ptr -> ipv6[2]; + udp_tx_ip_address.nxd_ip_address.v6[3] = iperf_ctrlInfo_ptr -> ipv6[3]; + if (udp_tx_packet_size > 1450) + { + udp_tx_packet_size = 1450; + } + } +#endif + + if (iperf_ctrlInfo_ptr -> Rate == 0) + { + iperf_ctrlInfo_ptr -> Rate = 10; + } + + nx_iperf_udp_tx_test(nx_iperf_stack_area, nx_iperf_stack_area_size); + break; + } + + default: + { + break; + } + } +} + +static void nx_iperf_print_tcp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address) +{ + +UINT status; +NX_PACKET *resp_packet_ptr; +UINT length = 0; +CHAR *ip_addr_string; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + + htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1); + htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1); + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + htmlwrite(resp_packet_ptr, "TCP Receive Test Done:", sizeof("TCP Receive Test Done:") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Source IP Address: ", sizeof("Source IP Address: ") - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(peer_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Packets Received: ", sizeof("Number of Packets Received: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsRxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Bytes Received: ", sizeof("Number of Bytes Received: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesRxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.idleTime, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); +#endif + + htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); + htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + /* Delete the receive thread. */ + nx_iperf_tcp_rx_cleanup(); +} + +static void nx_iperf_print_tcp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address) +{ +UINT status; +NX_PACKET *resp_packet_ptr; +UINT length = 0; +CHAR *ip_addr_string; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + + htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1); + htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1); + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + htmlwrite(resp_packet_ptr, "TCP Transmit Test Done:", sizeof("TCP Transmit Test Done:") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Destination IP Address: ", sizeof("Destination IP Address: ") - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(peer_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Destination Port: ", sizeof("Destination Port: ") - 1); + length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.port, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Packets Transmitted: ", sizeof("Number of Packets Transmitted: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsTxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Bytes Transmitted: ", sizeof("Number of Bytes Transmitted: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesTxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.idleTime, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); +#endif + + status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + /* Delete the receive thread. */ + nx_iperf_tcp_tx_cleanup(); +} + +static void nx_iperf_print_udp_rx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address) +{ +UINT status; +NX_PACKET *resp_packet_ptr; +UINT length = 0; +CHAR *ip_addr_string; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + + /* now send the data back to the client. */ + htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1); + htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1); + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + htmlwrite(resp_packet_ptr, "UDP Receive Test Done:", sizeof("UDP Receive Test Done:") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Source IP Address: ", sizeof("Source IP Address: ") - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(peer_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Packets Received: ", sizeof("Number of Packets Received: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsRxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Bytes Received: ", sizeof("Number of Bytes Received: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesRxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.idleTime), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); +#endif + + status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + nx_iperf_udp_rx_cleanup(); +} + +static void nx_iperf_print_udp_tx_results(NX_WEB_HTTP_SERVER *server_ptr, NXD_ADDRESS *peer_ip_address) +{ +UINT status; +NX_PACKET *resp_packet_ptr; +UINT length = 0; +CHAR *ip_addr_string; + + status = nx_packet_allocate(server_ptr -> nx_web_http_server_packet_pool_ptr, + &resp_packet_ptr, + NX_TCP_PACKET, + NX_WAIT_FOREVER); + + /* now send the data back to the client. */ + htmlwrite(resp_packet_ptr, toptdtag, sizeof(toptdtag) - 1); + htmlwrite(resp_packet_ptr, tabletag, sizeof(tabletag) - 1); + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + htmlwrite(resp_packet_ptr, "UDP Transmit Test Done:", sizeof("UDP Transmit Test Done:") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, rightspanline, sizeof(rightspanline) - 1); + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Destination IP Address: ", sizeof("Destination IP Address: ") - 1); + ip_addr_string = nx_iperf_get_ip_addr_string(peer_ip_address, &length); + status += htmlwrite(resp_packet_ptr, ip_addr_string, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Destination Port: ", sizeof("Destination Port: ") - 1); + length = _nx_utility_uint_to_string(nx_iperf_ctrl_info.port, 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Test Time(milliseconds): ", sizeof("Test Time(milliseconds): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.RunTime * 1000 / NX_IP_PERIODIC_RATE), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Packets Transmitted: ", sizeof("Number of Packets Transmitted: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.PacketsTxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Number of Bytes Transmitted: ", sizeof("Number of Bytes Transmitted: ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.BytesTxed), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + status += htmlwrite(resp_packet_ptr, "Throughput(Mbps): ", sizeof("Throughput(Mbps): ") - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.ThroughPut), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + status += htmlwrite(resp_packet_ptr, trtag, sizeof(trtag) - 1); + status += htmlwrite(resp_packet_ptr, tdtag, sizeof(tdtag) - 1); + status += htmlwrite(resp_packet_ptr, fonttag, sizeof(fonttag) - 1); + length = _nx_utility_uint_to_string((UINT)(nx_iperf_ctrl_info.idleTime), 10, mytempstring, sizeof(mytempstring)); + status += htmlwrite(resp_packet_ptr, "Idle Time: ", sizeof("Idle Time: ") - 1); + status += htmlwrite(resp_packet_ptr, mytempstring, length); + status += htmlwrite(resp_packet_ptr, "%", sizeof("%") - 1); + status += htmlwrite(resp_packet_ptr, fontendtag, sizeof(fontendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + status += htmlwrite(resp_packet_ptr, trendtag, sizeof(trendtag) - 1); +#endif + + status += htmlwrite(resp_packet_ptr, tableendtag, sizeof(tableendtag) - 1); + status += htmlwrite(resp_packet_ptr, tdendtag, sizeof(tdendtag) - 1); + + status += nx_web_http_server_callback_packet_send(server_ptr, resp_packet_ptr); + + if (status) + { + nx_packet_release(resp_packet_ptr); + nx_iperf_test_error_counter++; + } + + nx_iperf_udp_tx_cleanup(); +} + +void nx_iperf_thread_tcp_rx_entry(ULONG thread_input) +{ +UINT status; +NX_PACKET *packet_ptr; +ULONG actual_status; +ULONG expire_time; +ctrl_info *ctrlInfo_ptr; +NXD_ADDRESS ip_address; +ULONG port; + + /* Set the pointer. */ + ctrlInfo_ptr = (ctrl_info *)thread_input; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + /* Update the time. */ + thread_time = 0; + isr_time = 0; + idle_time = 0; +#endif + + /* Update the test result. */ + ctrlInfo_ptr -> PacketsRxed = 0; + ctrlInfo_ptr -> BytesRxed = 0; + ctrlInfo_ptr -> ThroughPut = 0; + ctrlInfo_ptr -> StartTime = 0; + ctrlInfo_ptr -> RunTime = 0; + ctrlInfo_ptr -> ErrorCode = 0; + + /* Ensure the IP instance has been initialized. */ + status = nx_ip_status_check(nx_iperf_test_ip, NX_IP_INITIALIZE_DONE, &actual_status, NX_IP_PERIODIC_RATE); + + /* Check status... */ + if (status != NX_SUCCESS) + { + error_counter++; + return; + } + + /* Setup this thread to listen. */ + status = nx_tcp_server_socket_listen(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT, &tcp_server_socket, 5, nx_iperf_tcp_rx_connect_received); + + /* Check for error. */ + if (status) + { + error_counter++; + return; + } + + /* Increment thread tcp rx's counter. */ + thread_tcp_rx_counter++; + + /* Accept a client socket connection. */ + status = nx_tcp_server_socket_accept(&tcp_server_socket, NX_WAIT_FOREVER); + + /* Check for error. */ + if (status) + { + nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT); + error_counter++; + return; + } + + /*Get source ip address*/ + status = nxd_tcp_socket_peer_info_get(&tcp_server_socket, &ip_address, &port); + if (status) + { + nx_tcp_server_socket_unaccept(&tcp_server_socket); + nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT); + error_counter++; + return; + } + + ctrlInfo_ptr -> version = ip_address.nxd_ip_version; + if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4) + { +#ifndef NX_DISABLE_IPV4 + ctrlInfo_ptr -> ip = ip_address.nxd_ip_address.v4; +#endif + } +#ifdef FEATURE_NX_IPV6 + else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6) + { + memcpy(ctrlInfo_ptr -> ipv6, ip_address.nxd_ip_address.v6, sizeof(ULONG) * 4); /* Use case of memcpy is verified. */ + } +#endif + + /* Set the test start time. */ + ctrlInfo_ptr -> StartTime = tx_time_get(); + expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime) + 20); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_reset(); + _tx_execution_isr_time_reset(); + _tx_execution_idle_time_reset(); +#endif + + while (tx_time_get() < expire_time) + { + /* Receive a TCP message from the socket. */ + status = nx_tcp_socket_receive(&tcp_server_socket, &packet_ptr, NX_WAIT_FOREVER); + + /* Check for error. */ + if (status) + { + error_counter++; + break; + } + + /* Update the counter. */ + ctrlInfo_ptr -> PacketsRxed++; + ctrlInfo_ptr -> BytesRxed += packet_ptr -> nx_packet_length; + + /* Release the packet. */ + nx_packet_release(packet_ptr); + } + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_get(&thread_time); + _tx_execution_isr_time_get(&isr_time); + _tx_execution_idle_time_get(&idle_time); +#endif + + /* Calculate the test time and Throughput(Mbps). */ + ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime; + ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time)); +#endif + + /* Disconnect the server socket. */ + status = nx_tcp_socket_disconnect(&tcp_server_socket, 10); + + /* Check for error. */ + if (status) + { + error_counter++; + } + + /* Unaccept the server socket. */ + status = nx_tcp_server_socket_unaccept(&tcp_server_socket); + status += nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT); + + /* Check for error. */ + if (status) + { + error_counter++; + } + + if (error_counter) + { + ctrlInfo_ptr -> ErrorCode = error_counter; + } +} + +void nx_iperf_tcp_rx_connect_received(NX_TCP_SOCKET *socket_ptr, UINT port) +{ + /* Check for the proper socket and port. */ + if ((socket_ptr != &tcp_server_socket) || (port != NX_IPERF_TCP_RX_PORT)) + { + error_counter++; + } +} + +void nx_iperf_tcp_rx_disconnect_received(NX_TCP_SOCKET *socket) +{ + /* Check for proper disconnected socket. */ + if (socket != &tcp_server_socket) + { + error_counter++; + } +} + +void nx_iperf_tcp_rx_cleanup(void) +{ + nx_tcp_socket_disconnect(&tcp_server_socket, NX_NO_WAIT); + nx_tcp_server_socket_unaccept(&tcp_server_socket); + nx_tcp_server_socket_unlisten(nx_iperf_test_ip, NX_IPERF_TCP_RX_PORT); + + tx_thread_terminate(&thread_tcp_rx_iperf); + tx_thread_delete(&thread_tcp_rx_iperf); +} + +void nx_iperf_tcp_rx_test(UCHAR *stack_space, ULONG stack_size) +{ + +UINT status; + + status = tx_thread_create(&thread_tcp_rx_iperf, "thread tcp rx", + nx_iperf_thread_tcp_rx_entry, + (ULONG)&nx_iperf_ctrl_info, + stack_space, stack_size, NX_IPERF_THREAD_PRIORITY, NX_IPERF_THREAD_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status) + { + nx_iperf_ctrl_info.ErrorCode = 1; + } + return; +} + +void nx_iperf_thread_tcp_tx_entry(ULONG thread_input) +{ +UINT status; +UINT is_first = NX_TRUE; +NX_PACKET *my_packet = NX_NULL; +#ifndef NX_DISABLE_PACKET_CHAIN +NX_PACKET *packet_ptr; +NX_PACKET *last_packet; +ULONG remaining_size; +#endif /* NX_DISABLE_PACKET_CHAIN */ +ULONG expire_time; +ctrl_info *ctrlInfo_ptr; +ULONG packet_size; +NXD_ADDRESS server_ip; + + /* Set the pointer. */ + ctrlInfo_ptr = (ctrl_info *)thread_input; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + thread_time = 0; + isr_time = 0; + idle_time = 0; +#endif + + ctrlInfo_ptr -> PacketsTxed = 0; + ctrlInfo_ptr -> BytesTxed = 0; + ctrlInfo_ptr -> ThroughPut = 0; + ctrlInfo_ptr -> StartTime = 0; + ctrlInfo_ptr -> RunTime = 0; + ctrlInfo_ptr -> ErrorCode = 0; + + server_ip.nxd_ip_version = ctrlInfo_ptr -> version; + +#ifdef FEATURE_NX_IPV6 + if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6) + { + server_ip.nxd_ip_address.v6[0] = ctrlInfo_ptr -> ipv6[0]; + server_ip.nxd_ip_address.v6[1] = ctrlInfo_ptr -> ipv6[1]; + server_ip.nxd_ip_address.v6[2] = ctrlInfo_ptr -> ipv6[2]; + server_ip.nxd_ip_address.v6[3] = ctrlInfo_ptr -> ipv6[3]; + } + else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4) +#endif + { +#ifndef NX_DISABLE_IPV4 + server_ip.nxd_ip_address.v4 = ctrlInfo_ptr -> ip; +#endif + } + + /* TCP Transmit Test Starts in 2 seconds. */ + tx_thread_sleep(200); + + /* Bind the socket. */ + status = nx_tcp_client_socket_bind(&tcp_client_socket, NX_ANY_PORT, NX_WAIT_FOREVER); + + /* Check for error. */ + if (status) + { + error_counter++; + return; + } + + /* Attempt to connect the socket. */ + status = nxd_tcp_client_socket_connect(&tcp_client_socket, &server_ip, ctrlInfo_ptr -> port, NX_WAIT_FOREVER); + + /* Check for error. */ + if (status) + { + nx_tcp_client_socket_unbind(&tcp_client_socket); + error_counter++; + return; + } + + /* Set the test start time. */ + ctrlInfo_ptr -> StartTime = tx_time_get(); + expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime)); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_reset(); + _tx_execution_isr_time_reset(); + _tx_execution_idle_time_reset(); +#endif + + /* Set the packet size. */ + status = nx_tcp_socket_mss_get(&tcp_client_socket, &packet_size); + + /* Check for error. */ + if (status) + { + nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT); + nx_tcp_client_socket_unbind(&tcp_client_socket); + error_counter++; + return; + } + + /* Loop to transmit the packet. */ + while (tx_time_get() < expire_time) + { + + /* Allocate a packet. */ + status = nx_packet_allocate(nx_iperf_test_pool, &my_packet, NX_TCP_PACKET, NX_WAIT_FOREVER); + + /* Check status. */ + if (status != NX_SUCCESS) + { + break; + } + + /* Write ABCs into the packet payload! */ + /* Adjust the write pointer. */ + if (my_packet -> nx_packet_prepend_ptr + packet_size <= my_packet -> nx_packet_data_end) + { + my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + packet_size; +#ifndef NX_DISABLE_PACKET_CHAIN + remaining_size = 0; +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + else + { +#ifdef NX_DISABLE_PACKET_CHAIN + packet_size = (ULONG)(my_packet -> nx_packet_data_end - my_packet -> nx_packet_prepend_ptr); + my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + packet_size; +#else + my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_data_end; + remaining_size = packet_size - (ULONG)(my_packet -> nx_packet_append_ptr - my_packet -> nx_packet_prepend_ptr); + last_packet = my_packet; +#endif /* NX_DISABLE_PACKET_CHAIN */ + } + my_packet -> nx_packet_length = packet_size; + +#ifndef NX_DISABLE_PACKET_CHAIN + while (remaining_size) + { + + /* Allocate a packet. */ + status = nx_packet_allocate(nx_iperf_test_pool, &packet_ptr, NX_TCP_PACKET, NX_WAIT_FOREVER); + + /* Check status. */ + if (status != NX_SUCCESS) + { + break; + } + + last_packet -> nx_packet_next = packet_ptr; + last_packet = packet_ptr; + if (remaining_size < (ULONG)(packet_ptr -> nx_packet_data_end - packet_ptr -> nx_packet_prepend_ptr)) + { + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_prepend_ptr + remaining_size; + } + else + { + packet_ptr -> nx_packet_append_ptr = packet_ptr -> nx_packet_data_end; + } + remaining_size = remaining_size - (ULONG)(packet_ptr -> nx_packet_append_ptr - packet_ptr -> nx_packet_prepend_ptr); + } +#endif /* NX_DISABLE_PACKET_CHAIN */ + + if (is_first) + { + memset(my_packet -> nx_packet_prepend_ptr, 0, (UINT)(my_packet -> nx_packet_data_end - my_packet -> nx_packet_prepend_ptr)); + is_first = NX_FALSE; + } + + /* Send the packet out! */ + status = nx_tcp_socket_send(&tcp_client_socket, my_packet, NX_WAIT_FOREVER); + + /* Determine if the status is valid. */ + if (status) + { + error_counter++; + nx_packet_release(my_packet); + break; + } + else + { + + /* Update the counter. */ + ctrlInfo_ptr -> PacketsTxed++; + ctrlInfo_ptr -> BytesTxed += packet_size; + } + } + + /* Calculate the test time and Throughput(Mbps). */ + ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime; + ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesTxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_get(&thread_time); + _tx_execution_isr_time_get(&isr_time); + _tx_execution_idle_time_get(&idle_time); +#endif + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time)); +#endif + + /* Disconnect this socket. */ + status = nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT); + + /* Determine if the status is valid. */ + if (status) + { + error_counter++; + } + + /* Unbind the socket. */ + status = nx_tcp_client_socket_unbind(&tcp_client_socket); + + /* Check for error. */ + if (status) + { + error_counter++; + } + + if (error_counter) + { + ctrlInfo_ptr -> ErrorCode = error_counter; + } +} + +void nx_iperf_tcp_tx_cleanup(void) +{ + nx_tcp_socket_disconnect(&tcp_client_socket, NX_NO_WAIT); + nx_tcp_client_socket_unbind(&tcp_client_socket); + + tx_thread_terminate(&thread_tcp_tx_iperf); + tx_thread_delete(&thread_tcp_tx_iperf); +} + +void nx_iperf_tcp_tx_test(UCHAR *stack_space, ULONG stack_size) +{ +UINT status; + + status = tx_thread_create(&thread_tcp_tx_iperf, "thread tcp tx", + nx_iperf_thread_tcp_tx_entry, + (ULONG)&nx_iperf_ctrl_info, + stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1, + TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status) + { + nx_iperf_ctrl_info.ErrorCode = 1; + } + return; +} + + +void nx_iperf_thread_udp_rx_entry(ULONG thread_input) +{ +UINT status; +ULONG expire_time; +NX_PACKET *my_packet; +ctrl_info *ctrlInfo_ptr; +int packetID = 0; +UINT sender_port; +ULONG tmp; +NXD_ADDRESS source_ip_address; + + /* Set the pointer. */ + ctrlInfo_ptr = (ctrl_info *)thread_input; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + thread_time = 0; + isr_time = 0; + idle_time = 0; +#endif + + /* Update the test result. */ + ctrlInfo_ptr -> PacketsRxed = 0; + ctrlInfo_ptr -> BytesRxed = 0; + ctrlInfo_ptr -> ThroughPut = 0; + ctrlInfo_ptr -> StartTime = 0; + ctrlInfo_ptr -> RunTime = 0; + ctrlInfo_ptr -> ErrorCode = 0; + + /* Bind the UDP socket to the IP port. */ + status = nx_udp_socket_bind(&udp_server_socket, NX_IPERF_UDP_RX_PORT, TX_WAIT_FOREVER); + + /* Check status. */ + if (status) + { + error_counter++; + return; + } + + /* Disable checksum for UDP. */ + nx_udp_socket_checksum_disable(&udp_server_socket); + + /* Receive a UDP packet. */ + status = nx_udp_socket_receive(&udp_server_socket, &my_packet, TX_WAIT_FOREVER); + + /* Check status. */ + if (status) + { + nx_udp_socket_unbind(&udp_server_socket); + error_counter++; + return; + } + + /* Get source ip address*/ + nxd_udp_source_extract(my_packet, &source_ip_address, &sender_port); + + /* Set the IP address Version. */ + ctrlInfo_ptr -> version = source_ip_address.nxd_ip_version; + +#ifndef NX_DISABLE_IPV4 + if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4) + { + ctrlInfo_ptr -> ip = source_ip_address.nxd_ip_address.v4; + } +#endif +#ifdef FEATURE_NX_IPV6 + if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6) + { + ctrlInfo_ptr -> ipv6[0] = source_ip_address.nxd_ip_address.v6[0]; + ctrlInfo_ptr -> ipv6[1] = source_ip_address.nxd_ip_address.v6[1]; + ctrlInfo_ptr -> ipv6[2] = source_ip_address.nxd_ip_address.v6[2]; + ctrlInfo_ptr -> ipv6[3] = source_ip_address.nxd_ip_address.v6[3]; + } +#endif + + /* Release the packet. */ + nx_packet_release(my_packet); + + /* Set the test start time. */ + ctrlInfo_ptr -> StartTime = tx_time_get(); + expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime) + 5); /* Wait 5 more ticks to synchronize. */ + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_reset(); + _tx_execution_isr_time_reset(); + _tx_execution_idle_time_reset(); +#endif + + while (tx_time_get() < expire_time) + { + + /* Receive a UDP packet. */ + status = nx_udp_socket_receive(&udp_server_socket, &my_packet, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != NX_SUCCESS) + { + error_counter++; + break; + } + + /* Update the counter. */ + ctrlInfo_ptr -> PacketsRxed++; + ctrlInfo_ptr -> BytesRxed += my_packet -> nx_packet_length; + + /* Detect the end of the test signal. */ + packetID = *(int *)(my_packet -> nx_packet_prepend_ptr); + + tmp = (ULONG)packetID; + NX_CHANGE_ULONG_ENDIAN(tmp); + packetID = (int)tmp; + + + /* Check the packet ID. */ + if (packetID < 0) + { + + /* Test has finished. */ +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_get(&thread_time); + _tx_execution_isr_time_get(&isr_time); + _tx_execution_idle_time_get(&idle_time); +#endif + + /* Calculate the test time and Throughput. */ + ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime; + ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000; + + /* received end of the test signal */ + + /* Send the UDP packet. */ + status = nxd_udp_socket_send(&udp_server_socket, my_packet, &source_ip_address, sender_port); + + /* Check the status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(my_packet); + } + else + { + + /* Loop to receive the end of the test signal. */ + while (1) + { + + /* Receive a UDP packet. */ + status = nx_udp_socket_receive(&udp_server_socket, &my_packet, 20); + + /* Check the status. */ + if (status) + { + break; + } + + /* Send the UDP packet. */ + status = nxd_udp_socket_send(&udp_server_socket, my_packet, &source_ip_address, sender_port); + + /* Check the status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(my_packet); + } + } + } + break; + } + else + { + + /* Release the packet. */ + nx_packet_release(my_packet); + } + } + + if (packetID >= 0) + { + + /* Test is not synchronized. */ +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_get(&thread_time); + _tx_execution_isr_time_get(&isr_time); + _tx_execution_idle_time_get(&idle_time); +#endif + + /* Calculate the test time and Throughput. */ + ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime; + ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesRxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000; + } + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time)); +#endif + + /* Unbind the socket. */ + nx_udp_socket_unbind(&udp_server_socket); + + /* Check error counter. */ + if (error_counter) + { + ctrlInfo_ptr -> ErrorCode = error_counter; + } +} + +void nx_iperf_udp_rx_cleanup(void) +{ + nx_udp_socket_unbind(&udp_server_socket); + + tx_thread_terminate(&thread_udp_rx_iperf); + tx_thread_delete(&thread_udp_rx_iperf); +} + +void nx_iperf_udp_rx_test(UCHAR *stack_space, ULONG stack_size) +{ +UINT status; + + status = tx_thread_create(&thread_udp_rx_iperf, "thread udp rx", + nx_iperf_thread_udp_rx_entry, + (ULONG)&nx_iperf_ctrl_info, + stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1, + TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status) + { + nx_iperf_ctrl_info.ErrorCode = 1; + } + return; +} + +static void nx_iperf_send_udp_packet(int udp_id, ctrl_info *ctrlInfo_ptr) +{ + +UINT status; +NX_PACKET *my_packet = NX_NULL; +udp_payload *payload_ptr; +ULONG tmp; + +NXD_ADDRESS server_ip; + + server_ip.nxd_ip_version = ctrlInfo_ptr -> version; + +#ifdef FEATURE_NX_IPV6 + if (ctrlInfo_ptr -> version == NX_IP_VERSION_V6) + { + server_ip.nxd_ip_address.v6[0] = ctrlInfo_ptr -> ipv6[0]; + server_ip.nxd_ip_address.v6[1] = ctrlInfo_ptr -> ipv6[1]; + server_ip.nxd_ip_address.v6[2] = ctrlInfo_ptr -> ipv6[2]; + server_ip.nxd_ip_address.v6[3] = ctrlInfo_ptr -> ipv6[3]; + } + else if (ctrlInfo_ptr -> version == NX_IP_VERSION_V4) +#endif + { +#ifndef NX_DISABLE_IPV4 + server_ip.nxd_ip_address.v4 = ctrlInfo_ptr -> ip; +#endif + } + + /* Send the end of test indicator. */ + nx_packet_allocate(nx_iperf_test_pool, &my_packet, NX_UDP_PACKET, TX_WAIT_FOREVER); + my_packet -> nx_packet_append_ptr = my_packet -> nx_packet_prepend_ptr + ctrlInfo_ptr -> PacketSize; + + payload_ptr = (udp_payload *)my_packet -> nx_packet_prepend_ptr; + payload_ptr -> udp_id = udp_id; + payload_ptr -> tv_sec = _tx_timer_system_clock / NX_IP_PERIODIC_RATE; + payload_ptr -> tv_usec = _tx_timer_system_clock / NX_IP_PERIODIC_RATE * 1000000; + + tmp = (ULONG)payload_ptr -> udp_id; + NX_CHANGE_ULONG_ENDIAN(tmp); + payload_ptr -> udp_id = (int)tmp; + + NX_CHANGE_ULONG_ENDIAN(payload_ptr -> tv_sec); + NX_CHANGE_ULONG_ENDIAN(payload_ptr -> tv_usec); + + /* Adjust the write pointer. */ + my_packet -> nx_packet_length = (UINT)(ctrlInfo_ptr -> PacketSize); + + /* Send the UDP packet. */ + status = nxd_udp_socket_send(&udp_client_socket, my_packet, &server_ip, ctrlInfo_ptr -> port); + + /* Check the status. */ + if (status) + { + + /* Release the packet. */ + nx_packet_release(my_packet); + return; + } +} + +void nx_iperf_thread_udp_tx_entry(ULONG thread_input) +{ +UINT status; +ULONG expire_time; +ctrl_info *ctrlInfo_ptr; +NX_PACKET *my_packet; +int i; +long udp_id; + + /* Initialize the value. */ + udp_id = 0; + ctrlInfo_ptr = (ctrl_info *)thread_input; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + thread_time = 0; + isr_time = 0; + idle_time = 0; +#endif + + ctrlInfo_ptr -> PacketsTxed = 0; + ctrlInfo_ptr -> BytesTxed = 0; + ctrlInfo_ptr -> ThroughPut = 0; + ctrlInfo_ptr -> StartTime = 0; + ctrlInfo_ptr -> RunTime = 0; + ctrlInfo_ptr -> ErrorCode = 0; + + /* UDP Transmit Test Starts in 2 seconds. */ + tx_thread_sleep(200); + + /* Bind the UDP socket to the IP port. */ + status = nx_udp_socket_bind(&udp_client_socket, NX_ANY_PORT, TX_WAIT_FOREVER); + + /* Check status. */ + if (status) + { + error_counter++; + return; + } + + /* Do not calculate checksum for UDP. */ + nx_udp_socket_checksum_disable(&udp_client_socket); + + /* Set the test start time. */ + ctrlInfo_ptr -> StartTime = tx_time_get(); + expire_time = (ULONG)(ctrlInfo_ptr -> StartTime + (ctrlInfo_ptr -> TestTime)); + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_reset(); + _tx_execution_isr_time_reset(); + _tx_execution_idle_time_reset(); +#endif + + while (tx_time_get() < expire_time) + { + + /* Write ABCs into the packet payload! */ + nx_iperf_send_udp_packet(udp_id, ctrlInfo_ptr); + + /* Update the ID. */ + udp_id = (udp_id + 1) & 0x7FFFFFFF; + + /* Update the counter. */ + ctrlInfo_ptr -> PacketsTxed++; + ctrlInfo_ptr -> BytesTxed += ctrlInfo_ptr -> PacketSize; + } + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + _tx_execution_thread_total_time_get(&thread_time); + _tx_execution_isr_time_get(&isr_time); + _tx_execution_idle_time_get(&idle_time); +#endif + + /* Calculate the test time and Throughput. */ + ctrlInfo_ptr -> RunTime = tx_time_get() - ctrlInfo_ptr -> StartTime; + ctrlInfo_ptr -> ThroughPut = ctrlInfo_ptr -> BytesTxed / ctrlInfo_ptr -> RunTime * NX_IP_PERIODIC_RATE / 125000; + +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) + ctrlInfo_ptr -> idleTime = (ULONG)((unsigned long long)idle_time * 100 / ((unsigned long long)thread_time + (unsigned long long)isr_time + (unsigned long long)idle_time)); +#endif + + if (error_counter) + { + ctrlInfo_ptr -> ErrorCode = error_counter; + } + + ctrlInfo_ptr -> PacketSize = 100; + for (i = 0; i < 10; i++) + { + /* Send the end of the test signal*/ + nx_iperf_send_udp_packet((0 - udp_id), ctrlInfo_ptr); + + /* Receive the packet. s*/ + if (nx_udp_socket_receive(&udp_client_socket, &my_packet, 10) == NX_SUCCESS) + { + nx_packet_release(my_packet); + break; + } + } + + /* Unbind the socket. */ + nx_udp_socket_unbind(&udp_client_socket); +} + +void nx_iperf_udp_tx_cleanup(void) +{ + nx_udp_socket_unbind(&udp_client_socket); + tx_thread_terminate(&thread_udp_tx_iperf); + tx_thread_delete(&thread_udp_tx_iperf); +} + +void nx_iperf_udp_tx_test(UCHAR *stack_space, ULONG stack_size) +{ +UINT status; + + status = tx_thread_create(&thread_udp_tx_iperf, "thread udp tx", + nx_iperf_thread_udp_tx_entry, + (ULONG)&nx_iperf_ctrl_info, + stack_space, stack_size, NX_WEB_HTTP_SERVER_PRIORITY + 1, NX_WEB_HTTP_SERVER_PRIORITY + 1, + TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status) + { + nx_iperf_ctrl_info.ErrorCode = 1; + } + return; +} + diff --git a/utility/iperf/nx_iperf.h b/utility/iperf/nx_iperf.h new file mode 100644 index 00000000..fc449dec --- /dev/null +++ b/utility/iperf/nx_iperf.h @@ -0,0 +1,2218 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) Microsoft Corporation. All rights reserved. */ +/* */ +/* This software is licensed under the Microsoft Software License */ +/* Terms for Microsoft Azure RTOS. Full text of the license can be */ +/* found in the LICENSE file at https://aka.ms/AzureRTOS_EULA */ +/* and in the root directory of this software. */ +/* */ +/**************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** NetX Utility */ +/** */ +/** NetX Duo IPerf Test Program */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* Enable authentication. +#define NX_IPERF_AUTH_ENABLE +*/ + +#ifndef NX_IPERF_TCP_RX_PORT +#define NX_IPERF_TCP_RX_PORT 5001 +#endif + +#ifndef NX_IPERF_UDP_RX_PORT +#define NX_IPERF_UDP_RX_PORT 5001 +#endif + +#ifndef NX_IPERF_DESTINATION_PORT +#define NX_IPERF_DESTINATION_PORT 5001 +#endif + +#ifndef NX_IPERF_THREAD_PRIORITY +#define NX_IPERF_THREAD_PRIORITY 1 +#endif + +#ifndef ULONG64_DEFINED +#define ULONG64_DEFINED +#define ULONG64 unsigned long long +#endif + +#define NX_IPERF_CTRL_SIGN_MASK 0x0F +#define NX_IPERF_CLEAN_UP_MASK 0x01 + +typedef struct +{ + ULONG CmdID; + ULONG version; + ULONG ip; + ULONG ipv6[4]; + ULONG port; + UCHAR ctrl_sign; + UINT ErrorCode; + ULONG WperfPort; + ULONG64 PacketsTxed; + ULONG64 PacketsRxed; + ULONG64 BytesTxed; + ULONG64 BytesRxed; + ULONG64 StartTime; + ULONG64 RunTime; + ULONG64 TestTime; + ULONG64 ThroughPut; + ULONG64 PacketSize; + ULONG64 Rate; + UINT TestStatus; /* 0 means no test is running. + 1 means Test Thread is created and is running. + 2 means a test has finished. */ + ULONG64 idleTime; +} ctrl_info; + +/*test list for wperf*/ +typedef struct +{ + ULONG cmdID; + ULONG threadID; +} thread_list; + +/* test type enum */ +enum testTypeList +{ + UNKNOWN_TEST = 0, + TCP_RX_START = 1, + UDP_RX_START = 3, + TCP_TX_START = 5, + UDP_TX_START = 7, + + UDP_RX_STOP, + TCP_RX_STOP, + UDP_TX_STOP, + TCP_TX_STOP +}; + +enum errorCodeList +{ + UDP_RX_STOP_ERROR = 5000, + UDP_RX_CREATE_ERROR, + UDP_TX_STOP_ERROR, + UDP_TX_CREATE_ERROR, + TCP_RX_STOP_ERROR, + TCP_RX_CREATE_ERROR, + TCP_TX_STOP_ERROR, + TCP_TX_CREATE_ERROR +}; + +typedef struct +{ + int udp_id; + ULONG tv_sec; + ULONG tv_usec; +} udp_payload; + +#define htmlwrite(p, s, l) (nx_packet_data_append(p, s, l, server_ptr -> nx_web_http_server_packet_pool_ptr, NX_WAIT_FOREVER)) + +#define htmlresponse "HTTP/1.0 200 \r\nContent-Type: text/html\r\n\r\n" +#define htmltag "" +#define htmlendtag "" +#define titleline "NetX IPerf Demonstration\r\n" + +#define bodytag "\r\n" +#define bodyendtag "\r\n" + +#define logo_area \ + "" \ + "
" \ + "
" + +#define hrline "
" +#define h1line1 "

NetX IP Address: " +#define h1line2 "


\r\n" +#define tabletag "" +#define fonttag "" +#define fontcolortag "" +#define fontendtag "" + +#define centertag "
\r\n" +#define centerendtag "
" +#define outtermosttable "
" +#define trendtag "" +#define tdtag "\r\n" +#define doublebr "

\r\n" +#define spanline "
" +#define rightspanline "" +#define tdcentertag "\r\n" \ + "" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" + +#define UDPRXSTRING "Start UDP Receive Test" +#define UDP_Rx "UDP_Rx" +#define udprxsubmittag1 \ + "
\r\n" \ + "
\r\n" \ + "" \ + "\r\n" \ + "\r\n" \ + "\r\n" + +#define TCP_Tx "TCP_Tx" +#define tcptxsubmittag1 \ + "
\r\n" \ + "
\r\n" \ + "" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" \ + "\r\n" + +#define TCP_Rx "TCP_Rx" +#define tcprxsubmittag1 \ + "
\r\n" \ + "
\r\n" \ + "" \ + "\r\n" \ + "\r\n" \ + "\r\n\r\n" + +#define choosetesttag \ + "\r\n" + +const unsigned char mslogo_jpg[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, + 0x00, 0x00, 0x00, 0x0d, 0x49, 0x48, 0x44, 0x52, + 0x00, 0x00, 0x01, 0xd7, 0x00, 0x00, 0x00, 0x9c, + 0x08, 0x06, 0x00, 0x00, 0x00, 0x2d, 0x6c, 0xe1, + 0xda, 0x00, 0x00, 0x00, 0x01, 0x73, 0x52, 0x47, + 0x42, 0x00, 0xae, 0xce, 0x1c, 0xe9, 0x00, 0x00, + 0x00, 0x04, 0x67, 0x41, 0x4d, 0x41, 0x00, 0x00, + 0xb1, 0x8f, 0x0b, 0xfc, 0x61, 0x05, 0x00, 0x00, + 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, + 0x2e, 0x22, 0x00, 0x00, 0x2e, 0x22, 0x01, 0xaa, + 0xe2, 0xdd, 0x92, 0x00, 0x00, 0x19, 0xc7, 0x49, + 0x44, 0x41, 0x54, 0x78, 0x5e, 0xed, 0xdd, 0x07, + 0xb8, 0x2c, 0x67, 0x5d, 0xc7, 0xf1, 0x7b, 0x91, + 0x2a, 0x10, 0x08, 0x08, 0xa1, 0xb7, 0x18, 0x20, + 0x14, 0xe9, 0x01, 0x44, 0x40, 0x5a, 0x00, 0x43, + 0x53, 0x8c, 0x08, 0x04, 0x43, 0x4d, 0x10, 0x94, + 0x26, 0x20, 0xc2, 0x23, 0x21, 0x54, 0x45, 0x10, + 0x69, 0x81, 0x50, 0x05, 0x42, 0x53, 0xe0, 0x41, + 0x50, 0x90, 0xa0, 0x14, 0x41, 0x41, 0x88, 0x0a, + 0xc6, 0x12, 0x5a, 0x10, 0x41, 0xa2, 0xb4, 0x20, + 0xd2, 0x04, 0x21, 0xfe, 0xbe, 0xb3, 0xb3, 0xcb, + 0xec, 0xbb, 0xef, 0xec, 0xee, 0xec, 0xd9, 0xbd, + 0xf7, 0x9c, 0x73, 0xbf, 0x9f, 0xe7, 0xf9, 0x9f, + 0x99, 0xdd, 0x9d, 0x99, 0xdd, 0xb3, 0x3b, 0x33, + 0xef, 0xbc, 0x75, 0xf6, 0x48, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x3a, 0xa0, 0xec, 0x6d, 0xa7, 0xbb, + 0xc2, 0x37, 0xee, 0x76, 0x15, 0xfe, 0x9f, 0x7f, + 0x4d, 0x5c, 0xa2, 0x79, 0x62, 0x33, 0xce, 0x3a, + 0xe8, 0xad, 0x67, 0x5e, 0x8b, 0x99, 0x13, 0x4e, + 0xdd, 0x73, 0x52, 0x26, 0xf7, 0x60, 0x7e, 0x83, + 0x8e, 0x38, 0xf1, 0xc8, 0x3d, 0x9f, 0x69, 0xe7, + 0x25, 0x49, 0x3b, 0xc0, 0xb9, 0xda, 0xe9, 0x6e, + 0x72, 0xd1, 0xc4, 0xc5, 0x36, 0x18, 0x07, 0x27, + 0xc6, 0x2e, 0x94, 0xa8, 0x2d, 0xb3, 0xce, 0xd8, + 0x8d, 0xbf, 0x91, 0x24, 0xed, 0x6a, 0x9e, 0xb8, + 0x25, 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, + 0xd6, 0xcc, 0xc4, 0x55, 0x92, 0xa4, 0x35, 0x33, + 0x71, 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25, + 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6, + 0xcc, 0xc4, 0x55, 0xd2, 0xda, 0x9c, 0x73, 0xce, + 0x39, 0x17, 0x49, 0x1c, 0x9b, 0x78, 0x45, 0xe2, + 0xbd, 0x89, 0x0f, 0x27, 0xde, 0x9d, 0x38, 0x39, + 0x71, 0x58, 0xbb, 0x98, 0xb4, 0xeb, 0x99, 0xb8, + 0x6a, 0xbf, 0xc9, 0xc9, 0x76, 0x6f, 0xe2, 0xd2, + 0x89, 0xab, 0x25, 0xce, 0xdb, 0x3e, 0xad, 0x1d, + 0xa8, 0xfd, 0x2d, 0x7f, 0x35, 0xb3, 0x9f, 0x4e, + 0xfc, 0x61, 0xe2, 0x7e, 0x89, 0x9f, 0x4d, 0xdc, + 0x38, 0x71, 0xdb, 0xc4, 0x71, 0x89, 0xeb, 0x24, + 0xa4, 0x03, 0xc2, 0x6e, 0x1c, 0xa1, 0xe9, 0xac, + 0xc4, 0x21, 0xcd, 0x13, 0x9b, 0xf1, 0xc5, 0x83, + 0xde, 0x7a, 0xe6, 0x65, 0x99, 0x39, 0xe1, 0xd4, + 0x3d, 0xaf, 0xce, 0xe4, 0x3e, 0xcc, 0x6f, 0xd0, + 0x55, 0x4f, 0x3c, 0x72, 0xcf, 0xa7, 0xda, 0xf9, + 0x41, 0x72, 0xb2, 0x23, 0xa7, 0x30, 0x6f, 0x04, + 0xa9, 0xd3, 0xf6, 0xee, 0xdd, 0xfb, 0xe7, 0xed, + 0xfc, 0xca, 0xf2, 0x3e, 0x0c, 0xa6, 0xf1, 0xf0, + 0x44, 0xdf, 0xfe, 0xf4, 0xfe, 0xbc, 0xcf, 0x07, + 0xda, 0xf9, 0x46, 0xd6, 0x61, 0x80, 0x0c, 0x4e, + 0xc2, 0x47, 0x25, 0xb8, 0xc8, 0xfb, 0x8f, 0xc4, + 0x71, 0x59, 0xee, 0x1d, 0x99, 0x6a, 0x07, 0xc9, + 0x6f, 0xc9, 0xef, 0xf7, 0xc2, 0xc4, 0x83, 0x9b, + 0x27, 0xfa, 0x1d, 0x9d, 0xdf, 0xf7, 0x4d, 0xed, + 0xfc, 0x7e, 0x91, 0xcf, 0xca, 0xe4, 0x81, 0x89, + 0x4b, 0x31, 0x53, 0xf8, 0x40, 0x3e, 0xdf, 0xfb, + 0xdb, 0x79, 0x69, 0x4b, 0x4c, 0x5c, 0x87, 0xdb, + 0x49, 0x89, 0xeb, 0x9d, 0x33, 0x79, 0xdb, 0xe8, + 0x51, 0x15, 0xb9, 0x8c, 0xc3, 0x73, 0x42, 0xf9, + 0xbf, 0xd1, 0xc3, 0xd5, 0xe4, 0x7d, 0x38, 0x59, + 0xbd, 0x74, 0xf4, 0xa8, 0xea, 0x89, 0x79, 0x8f, + 0xa7, 0xb4, 0xf3, 0x8d, 0xac, 0xf3, 0xc7, 0x99, + 0xfc, 0xe2, 0xe8, 0xd1, 0xc4, 0xb7, 0x12, 0xd7, + 0xcc, 0xb2, 0x9f, 0x1b, 0x3d, 0xd4, 0x4e, 0x90, + 0xdf, 0xf2, 0x31, 0x99, 0x3c, 0x73, 0xf4, 0x68, + 0xae, 0xed, 0x90, 0xb8, 0x5e, 0x26, 0x93, 0xcf, + 0x26, 0x6a, 0x25, 0x25, 0x7f, 0x9b, 0xb8, 0x69, + 0x3e, 0x63, 0x93, 0x02, 0x4b, 0x5b, 0x61, 0xb1, + 0xf0, 0x81, 0xed, 0x27, 0x13, 0xb7, 0x18, 0xcd, + 0xae, 0x26, 0x27, 0x2b, 0x2e, 0x68, 0x8e, 0x1f, + 0x3d, 0x5a, 0x4e, 0xd6, 0x39, 0x4f, 0x26, 0x77, + 0x1c, 0x3d, 0x9a, 0x72, 0xc1, 0xc4, 0xed, 0x47, + 0xb3, 0xda, 0x09, 0xf2, 0x5b, 0x72, 0xa1, 0xf9, + 0xc4, 0xd1, 0xa3, 0x19, 0x67, 0x26, 0xde, 0x90, + 0xe0, 0x42, 0x8a, 0xf9, 0xaa, 0x6c, 0xe3, 0x7c, + 0x89, 0xcb, 0xb7, 0x0f, 0x37, 0xed, 0xde, 0x89, + 0xbe, 0x2a, 0x88, 0x1b, 0x25, 0xae, 0x31, 0x9a, + 0x95, 0xb6, 0xc6, 0xc4, 0x55, 0x0f, 0x68, 0xa7, + 0xab, 0xe2, 0x84, 0x74, 0x83, 0xd1, 0xec, 0xd2, + 0xc8, 0x19, 0xf4, 0xe5, 0x96, 0xff, 0xb7, 0x9d, + 0x6a, 0x67, 0x20, 0xb1, 0xa2, 0x5a, 0xa0, 0xf4, + 0x07, 0x89, 0xab, 0x27, 0x17, 0x78, 0xcf, 0xc4, + 0x2f, 0x65, 0xfe, 0x6a, 0x89, 0x49, 0x15, 0x44, + 0x12, 0xd3, 0x8b, 0x26, 0x8e, 0x4e, 0xbc, 0x26, + 0x0f, 0x3f, 0x9f, 0xf8, 0xed, 0xe6, 0x85, 0x0d, + 0xca, 0x7b, 0x71, 0xbe, 0x9b, 0x57, 0xd2, 0xc4, + 0xeb, 0xbf, 0x32, 0x9a, 0x95, 0xb6, 0xc6, 0xc4, + 0x55, 0x77, 0xcd, 0x49, 0xe7, 0xe2, 0xed, 0xfc, + 0x2a, 0xc8, 0xb5, 0x0e, 0xaa, 0x5e, 0xc8, 0xc9, + 0x96, 0x84, 0x95, 0xfa, 0xd6, 0x12, 0x45, 0xfa, + 0x7f, 0x36, 0x9a, 0xd5, 0x0e, 0x71, 0xab, 0x76, + 0xda, 0xc5, 0x5d, 0x9c, 0x1e, 0x9b, 0xdf, 0xf9, + 0xfb, 0xa3, 0x87, 0xa3, 0xdf, 0x3c, 0xf1, 0x4d, + 0xe6, 0xb3, 0xbf, 0x3d, 0x3b, 0x93, 0x2f, 0x26, + 0xfe, 0x28, 0x71, 0x4c, 0x82, 0xbb, 0x58, 0xed, + 0x8b, 0x2a, 0xaa, 0x1b, 0x26, 0x9a, 0x3b, 0x5a, + 0xcd, 0x71, 0xaf, 0x7c, 0x3e, 0x1b, 0xd7, 0x69, + 0xcb, 0x4c, 0x5c, 0x45, 0x51, 0xec, 0x2f, 0x8f, + 0x66, 0x87, 0xc9, 0x49, 0x88, 0x3b, 0x10, 0xad, + 0xb4, 0x6e, 0x3c, 0x36, 0xf1, 0x8c, 0x04, 0x0d, + 0x99, 0xfe, 0x3b, 0xf1, 0xae, 0xc4, 0x6d, 0x72, + 0x02, 0xfe, 0x4a, 0xa6, 0xda, 0x39, 0xae, 0xd2, + 0x4e, 0xbb, 0xde, 0xdd, 0x4d, 0x58, 0x2b, 0xae, + 0x99, 0xb8, 0xc0, 0x68, 0x76, 0x9f, 0x3a, 0x36, + 0xb1, 0x28, 0x11, 0xbf, 0x5c, 0x82, 0xd6, 0xcd, + 0xd2, 0x96, 0x98, 0xb8, 0x0a, 0xf7, 0x4f, 0x42, + 0xd9, 0xce, 0x0e, 0xc2, 0xc9, 0xea, 0xc7, 0x47, + 0xb3, 0xc3, 0xe4, 0xe4, 0xfb, 0xbd, 0xc4, 0xe3, + 0x33, 0x7b, 0x85, 0xc4, 0x4f, 0x24, 0xee, 0x90, + 0xc7, 0xdc, 0x8b, 0x57, 0x3b, 0x0b, 0x17, 0x67, + 0x25, 0x72, 0xa5, 0xdb, 0x4a, 0xf6, 0x6f, 0xf6, + 0x53, 0x8a, 0xa7, 0xbb, 0x7e, 0x98, 0x38, 0x6d, + 0x34, 0x3b, 0xe5, 0xbe, 0xed, 0x54, 0x5a, 0x99, + 0x89, 0xeb, 0x81, 0xe7, 0x0b, 0x09, 0x4e, 0x2a, + 0x5d, 0xd7, 0x4b, 0x0c, 0xaa, 0x37, 0xcd, 0xc9, + 0xea, 0xc7, 0x32, 0x79, 0xd0, 0xe8, 0xd1, 0xc4, + 0x7f, 0x26, 0x06, 0xd5, 0x99, 0x26, 0x41, 0xfd, + 0x61, 0x82, 0x22, 0xc3, 0xf6, 0x19, 0xed, 0x02, + 0x3f, 0x68, 0xa7, 0xdb, 0x09, 0x5d, 0xbe, 0xb8, + 0x88, 0xeb, 0xfa, 0x87, 0xc4, 0x93, 0x47, 0xb3, + 0x53, 0xee, 0x94, 0xfd, 0x9b, 0xa2, 0x6a, 0x69, + 0x65, 0x26, 0xae, 0x07, 0x1e, 0x72, 0x87, 0x1f, + 0x1a, 0xcd, 0x4e, 0x90, 0xb2, 0xd1, 0xe9, 0x7f, + 0x88, 0x9b, 0x27, 0x28, 0xde, 0xeb, 0xa2, 0x1e, + 0x75, 0x9f, 0x9e, 0x58, 0x49, 0xe4, 0x13, 0x17, + 0x4b, 0x1c, 0x9e, 0xb8, 0x41, 0x82, 0x01, 0x29, + 0x2e, 0x9c, 0xd8, 0x52, 0x6a, 0xcd, 0xfa, 0x89, + 0xf3, 0xb4, 0xb1, 0x70, 0x5b, 0x59, 0x86, 0x38, + 0x77, 0xe2, 0x12, 0x89, 0xc3, 0x12, 0x57, 0x4d, + 0x5c, 0x92, 0xe7, 0xda, 0x45, 0x56, 0x96, 0x6d, + 0x9c, 0x2b, 0x71, 0xf1, 0xc4, 0xb5, 0x12, 0xd7, + 0x4f, 0x5c, 0x25, 0x71, 0xfe, 0xc4, 0x4a, 0xff, + 0x23, 0xeb, 0x25, 0x2e, 0x90, 0xb8, 0x6c, 0xe2, + 0xea, 0x09, 0xb6, 0x77, 0x50, 0x62, 0x37, 0x9f, + 0x0f, 0x6a, 0xb9, 0x51, 0x5a, 0x32, 0xbf, 0x3b, + 0xf1, 0xa5, 0xe6, 0xd1, 0x8f, 0x50, 0x64, 0x5d, + 0xe6, 0x72, 0x0f, 0x48, 0xd9, 0x27, 0x86, 0x1e, + 0x07, 0x2c, 0x4f, 0xeb, 0x6f, 0x8e, 0xc9, 0x83, + 0x13, 0xe7, 0xe5, 0xb9, 0xf6, 0xe5, 0x03, 0xca, + 0xae, 0xfa, 0xa7, 0xed, 0xe7, 0x3a, 0x2d, 0x3b, + 0x75, 0xad, 0x9f, 0xeb, 0xa9, 0x89, 0x53, 0x12, + 0x7c, 0xf6, 0xae, 0xb3, 0x13, 0x97, 0x4d, 0x0e, + 0xf2, 0x3b, 0xa3, 0x87, 0xf3, 0x65, 0xdb, 0x9c, + 0x98, 0xba, 0x03, 0x54, 0x90, 0xa8, 0x92, 0xd8, + 0xfe, 0x7d, 0xa2, 0x2c, 0x2a, 0xae, 0xf5, 0x73, + 0xbd, 0x6b, 0x26, 0x65, 0x3f, 0xd7, 0x2f, 0x66, + 0xb9, 0xdf, 0x6c, 0xe7, 0x7b, 0x71, 0xc0, 0x66, + 0xf2, 0x0b, 0x09, 0xd6, 0xff, 0xe9, 0xc4, 0xa5, + 0x13, 0x5d, 0x34, 0x98, 0xfa, 0x44, 0xe2, 0x9d, + 0x89, 0x57, 0x67, 0x9b, 0xa7, 0xf3, 0x24, 0xb2, + 0x2e, 0x8d, 0xb7, 0x68, 0xc9, 0x5a, 0x7a, 0x52, + 0x96, 0xfb, 0x4c, 0x5e, 0xbf, 0x64, 0xe6, 0x1f, + 0x9d, 0xe0, 0xbb, 0xa3, 0x7b, 0x08, 0xe5, 0xe5, + 0xac, 0x7f, 0xcb, 0xbc, 0x3e, 0x53, 0x8f, 0x98, + 0xe5, 0xaf, 0x98, 0x09, 0x8d, 0x72, 0xee, 0x90, + 0xb8, 0x76, 0xe2, 0x22, 0x89, 0xae, 0x6f, 0x24, + 0xc8, 0x21, 0xfd, 0x69, 0xe2, 0x55, 0xd9, 0xc6, + 0x97, 0x79, 0x72, 0x19, 0xd9, 0x36, 0xdb, 0x63, + 0xd4, 0x23, 0xba, 0x2d, 0xf1, 0x3e, 0xdd, 0xe3, + 0xf5, 0x7b, 0x89, 0x4f, 0x26, 0xde, 0x9b, 0x78, + 0x7e, 0xb6, 0x3b, 0x77, 0x1f, 0xc9, 0xb6, 0x58, + 0x97, 0x6e, 0x57, 0xd4, 0x91, 0xdf, 0x32, 0x41, + 0x37, 0x2c, 0xba, 0x44, 0x8d, 0xf1, 0x7f, 0x52, + 0xff, 0xfd, 0x37, 0x09, 0x1a, 0x1a, 0xbd, 0xad, + 0xe7, 0xff, 0xa5, 0xb4, 0xa2, 0xdb, 0x7d, 0x8b, + 0xdf, 0xa1, 0xfc, 0xbd, 0x3f, 0x96, 0xf8, 0xa7, + 0xd1, 0x6c, 0xd5, 0xad, 0x13, 0xf4, 0x37, 0xed, + 0xa2, 0xcf, 0xf5, 0x87, 0x47, 0xb3, 0x13, 0xdf, + 0xca, 0x67, 0x58, 0x34, 0x30, 0xc5, 0x42, 0xf9, + 0xcc, 0xbc, 0xd7, 0xbf, 0x27, 0x28, 0x6d, 0x19, + 0x63, 0x7f, 0xbd, 0x72, 0xb6, 0xff, 0xf9, 0xbc, + 0xfe, 0xe2, 0xcc, 0x97, 0xdd, 0xc9, 0x3e, 0x9a, + 0xd7, 0x8e, 0x68, 0xe7, 0xe7, 0xca, 0xfa, 0x74, + 0xdf, 0xf9, 0xad, 0xd1, 0xa3, 0x2d, 0xe1, 0x3d, + 0x9f, 0xc7, 0x4c, 0xb6, 0xc9, 0x85, 0x6a, 0xf7, + 0xf3, 0xe2, 0x65, 0x79, 0x7d, 0xee, 0x20, 0x17, + 0x59, 0x8f, 0x3a, 0xf0, 0x13, 0x47, 0x8f, 0xa6, + 0x3c, 0x22, 0xeb, 0x7e, 0xb5, 0x9d, 0x67, 0x39, + 0x5a, 0x78, 0xbf, 0x68, 0xf4, 0x68, 0xca, 0x09, + 0x59, 0xee, 0xcc, 0xbc, 0xce, 0x39, 0xf4, 0x37, + 0x12, 0x77, 0x49, 0x50, 0x0f, 0xcd, 0xfe, 0x71, + 0x46, 0x5e, 0xa3, 0x77, 0xc0, 0x8c, 0x2c, 0x7f, + 0xdd, 0x4c, 0xb8, 0x40, 0xa7, 0xbe, 0x9a, 0x7d, + 0x6b, 0xdc, 0x28, 0xec, 0xbb, 0x09, 0x7e, 0xdb, + 0xbf, 0x4c, 0xbc, 0x32, 0xeb, 0x7f, 0x9c, 0x27, + 0x0f, 0x04, 0x26, 0xae, 0xc3, 0xed, 0x86, 0xc4, + 0xf5, 0xe7, 0x13, 0x0c, 0xd4, 0x50, 0x16, 0x93, + 0x1d, 0x93, 0x9d, 0xff, 0xb5, 0xed, 0x7c, 0xaf, + 0x6c, 0x97, 0x93, 0x15, 0x2d, 0x42, 0xcf, 0xdf, + 0x3c, 0x31, 0x42, 0x0e, 0x80, 0x04, 0xe6, 0x7f, + 0x12, 0xcb, 0x24, 0xae, 0x4f, 0xc8, 0xe4, 0xa9, + 0xa3, 0x47, 0x13, 0x9f, 0xc8, 0x72, 0x57, 0x6f, + 0xe7, 0x67, 0x64, 0x1d, 0x7e, 0x5f, 0x4e, 0xe6, + 0xbf, 0x97, 0xb8, 0x32, 0xcf, 0x2d, 0x81, 0xc4, + 0xed, 0x52, 0xd9, 0x6e, 0x73, 0xd1, 0x90, 0x6d, + 0x90, 0x60, 0x72, 0xa2, 0x2d, 0xdd, 0x24, 0x41, + 0xa2, 0x4c, 0x6b, 0xe5, 0x72, 0xff, 0xa1, 0xc1, + 0xd5, 0x21, 0xd9, 0xc6, 0xa4, 0xc8, 0x3b, 0xdb, + 0x61, 0x84, 0xa9, 0xa7, 0x25, 0xee, 0x9f, 0x58, + 0xb6, 0x75, 0x29, 0xad, 0x65, 0x7f, 0x27, 0xf1, + 0xcc, 0x6c, 0xab, 0xb7, 0xc1, 0x4f, 0xb6, 0xcd, + 0xf6, 0x58, 0xee, 0x61, 0x89, 0xf2, 0x04, 0x5b, + 0xc3, 0x89, 0xf3, 0xb9, 0xed, 0xfc, 0x8c, 0x6c, + 0x8f, 0x13, 0xe2, 0xf3, 0x13, 0x0c, 0x45, 0xb8, + 0x2c, 0x2e, 0x4e, 0x1e, 0x9a, 0xed, 0x72, 0x52, + 0x9c, 0xc8, 0xb6, 0x5e, 0x91, 0xc9, 0xd0, 0x52, + 0x8e, 0x55, 0x9d, 0x9d, 0xf7, 0xe7, 0x7b, 0xde, + 0x92, 0x7c, 0x66, 0x2e, 0xd8, 0xf8, 0x3e, 0xbb, + 0xde, 0x97, 0xb8, 0x55, 0xb6, 0xcf, 0xeb, 0x5c, + 0x6c, 0xf0, 0xb8, 0x74, 0xed, 0xbc, 0x3e, 0xef, + 0x22, 0xa1, 0x91, 0xf5, 0xb9, 0x58, 0x98, 0xfa, + 0x9e, 0x56, 0xf4, 0xe6, 0xbc, 0x5f, 0x73, 0xc1, + 0x99, 0x6d, 0xb2, 0x7f, 0x94, 0xa5, 0x1e, 0x0f, + 0xcc, 0xeb, 0x2f, 0x6f, 0xe7, 0xab, 0xb2, 0x1e, + 0x17, 0x04, 0x0c, 0x86, 0x51, 0xba, 0x62, 0xd6, + 0x9d, 0xec, 0xf7, 0x59, 0x8e, 0x8b, 0xcc, 0x5a, + 0xe3, 0x41, 0xf6, 0x11, 0xaa, 0x8d, 0xde, 0x9e, + 0x28, 0x47, 0xb1, 0xfa, 0x4e, 0xb6, 0x31, 0x75, + 0x6c, 0x67, 0x3b, 0x9c, 0x43, 0xd8, 0xf7, 0xee, + 0x99, 0x58, 0x94, 0x9e, 0xb0, 0x5d, 0xce, 0x99, + 0x0f, 0xcf, 0x76, 0x38, 0x2e, 0x77, 0x35, 0x8b, + 0x85, 0x0f, 0x40, 0xd9, 0xb1, 0xbf, 0x9d, 0x49, + 0x99, 0x73, 0xc5, 0xb2, 0x0d, 0x9b, 0x28, 0x62, + 0xeb, 0x26, 0xac, 0x78, 0x59, 0x3b, 0xdd, 0x88, + 0x7c, 0x2e, 0x12, 0x19, 0xba, 0x70, 0x90, 0xab, + 0x5a, 0x36, 0x61, 0xc5, 0xb2, 0x17, 0x90, 0x24, + 0xa8, 0x9c, 0x50, 0x16, 0x5e, 0x98, 0xe5, 0xb3, + 0x90, 0x53, 0xf9, 0x48, 0x82, 0x5c, 0xd5, 0x90, + 0x6e, 0x1b, 0xe4, 0x16, 0xb8, 0xa0, 0x78, 0x7b, + 0xb6, 0x71, 0xe1, 0xe6, 0x99, 0x42, 0x9e, 0x27, + 0x37, 0xf9, 0xc6, 0xc4, 0x23, 0x13, 0xcb, 0x24, + 0xac, 0xbd, 0xf8, 0x2d, 0x13, 0xe4, 0x34, 0x19, + 0x7a, 0x72, 0x48, 0xc2, 0x8a, 0xa6, 0x5f, 0x6a, + 0xd6, 0x7f, 0x18, 0xdb, 0xd9, 0xa9, 0xf2, 0xd9, + 0x39, 0xc7, 0xd5, 0x2e, 0x80, 0x5f, 0x9f, 0xe3, + 0xa0, 0x9d, 0xdd, 0xf3, 0xd7, 0x09, 0xfa, 0xda, + 0x96, 0xf6, 0x75, 0xc3, 0xa6, 0xb2, 0x78, 0x7a, + 0x7f, 0xa0, 0xe4, 0xa6, 0x96, 0xb0, 0xce, 0xc8, + 0x77, 0xcb, 0x3e, 0x42, 0x42, 0x7e, 0xaf, 0xc4, + 0x32, 0xc7, 0x19, 0xbf, 0x05, 0xdf, 0xe9, 0xfb, + 0xb2, 0xee, 0x56, 0xba, 0xff, 0xed, 0x08, 0x26, + 0xae, 0x07, 0x2e, 0x86, 0x2b, 0x2c, 0x1b, 0x36, + 0x8d, 0x8b, 0x0b, 0x7b, 0xe5, 0xa0, 0xe0, 0xe4, + 0x5f, 0x0e, 0x3c, 0x41, 0x43, 0x26, 0x0e, 0xc8, + 0x8d, 0x68, 0x4f, 0xee, 0x0c, 0xaf, 0x47, 0x82, + 0xb3, 0xa9, 0x7d, 0x96, 0x62, 0xbd, 0xb2, 0x78, + 0x79, 0x46, 0x3e, 0xcb, 0x95, 0x32, 0xf9, 0x8b, + 0xc4, 0xa1, 0xcd, 0x13, 0xab, 0x61, 0x14, 0xaa, + 0xd7, 0x65, 0x5b, 0xb5, 0xc4, 0xf3, 0x11, 0x89, + 0xbb, 0x8d, 0x66, 0x67, 0xf0, 0x45, 0x94, 0xbf, + 0xd9, 0x3c, 0xe4, 0xaa, 0x29, 0xf2, 0x3c, 0x5f, + 0xf3, 0x68, 0x38, 0x72, 0x4e, 0xcf, 0x49, 0xec, + 0xe4, 0xd6, 0xb3, 0xe4, 0xda, 0xcb, 0xb6, 0x01, + 0x14, 0xa9, 0xbf, 0x65, 0x34, 0xdb, 0x5c, 0x6c, + 0x52, 0x62, 0xc1, 0x45, 0x5b, 0xe9, 0x9e, 0xf9, + 0x8d, 0x86, 0x5c, 0x3c, 0x6d, 0x05, 0x25, 0x49, + 0x7d, 0x23, 0x5d, 0xed, 0x4b, 0xb4, 0xe0, 0x5f, + 0x26, 0x61, 0xa5, 0xa8, 0x98, 0x52, 0xb0, 0x5a, + 0x57, 0x2c, 0xf0, 0x1d, 0x13, 0x35, 0x34, 0xa0, + 0x3c, 0x25, 0xdb, 0xd8, 0xd5, 0xe9, 0x8f, 0x89, + 0xeb, 0x01, 0x2a, 0x27, 0x94, 0x33, 0x32, 0x29, + 0xeb, 0x6f, 0x38, 0xd9, 0xd3, 0xbd, 0x66, 0x9e, + 0x23, 0x13, 0xe5, 0x01, 0xf5, 0xda, 0x6c, 0x6f, + 0xa9, 0xba, 0xda, 0x15, 0xdd, 0x3d, 0xf1, 0xa8, + 0xd1, 0xec, 0x0c, 0xea, 0x74, 0xc8, 0xe9, 0x3d, + 0x24, 0x41, 0x71, 0xf7, 0xd1, 0x89, 0x13, 0x12, + 0xd4, 0xfd, 0x0e, 0x41, 0xb1, 0xf0, 0x18, 0x27, + 0x5b, 0x8a, 0xe2, 0x19, 0x83, 0x76, 0xd2, 0x40, + 0x2b, 0x27, 0x03, 0x12, 0x9b, 0xd7, 0x27, 0x6a, + 0x89, 0x30, 0x89, 0x1e, 0x27, 0x1b, 0xc6, 0xd9, + 0xa5, 0x0e, 0x96, 0xa2, 0x53, 0x72, 0xda, 0xb5, + 0x1c, 0x11, 0xee, 0x94, 0xf8, 0xb5, 0xd1, 0xec, + 0x48, 0xb6, 0x4f, 0x69, 0x00, 0xf5, 0xbd, 0x25, + 0xba, 0xb6, 0x90, 0x50, 0x92, 0x53, 0x20, 0x71, + 0xbf, 0x69, 0x82, 0x7e, 0xc2, 0xbd, 0xf5, 0x57, + 0xd9, 0x16, 0xf5, 0xb5, 0x2f, 0x48, 0xd4, 0x8e, + 0x71, 0x8a, 0xe4, 0x28, 0x5e, 0x24, 0xe7, 0xcd, + 0x08, 0x4b, 0x0f, 0x4d, 0xf0, 0x7f, 0xf1, 0x5d, + 0x96, 0x58, 0xff, 0x05, 0xd9, 0xde, 0xf8, 0x37, + 0xa7, 0x41, 0x1c, 0xf5, 0xbc, 0xe3, 0xa8, 0xb5, + 0x0e, 0x67, 0xa8, 0xc3, 0xee, 0x32, 0x65, 0x7c, + 0x2d, 0x51, 0xe2, 0x7f, 0x2c, 0x97, 0xfb, 0x60, + 0x62, 0xab, 0x6a, 0x17, 0x06, 0xa7, 0x66, 0x7f, + 0x2d, 0x8b, 0x44, 0x69, 0x43, 0x50, 0xa2, 0xfa, + 0x83, 0xfd, 0x7d, 0x11, 0xaa, 0xa2, 0x28, 0x2e, + 0x5f, 0x26, 0x6a, 0xfb, 0x03, 0xfb, 0xdb, 0xb1, + 0x95, 0xcf, 0xb4, 0x3f, 0xb0, 0x6f, 0x8d, 0x75, + 0x8f, 0x03, 0xe6, 0x1b, 0xd9, 0x17, 0x38, 0x4f, + 0x30, 0xb2, 0x16, 0xdd, 0xe8, 0xba, 0xb8, 0xf8, + 0x63, 0x3f, 0xa2, 0x94, 0x84, 0xe2, 0x7c, 0x8a, + 0x8c, 0x6f, 0x96, 0xa8, 0x8d, 0x6f, 0x4e, 0x15, + 0x12, 0x45, 0xc9, 0xbb, 0xd6, 0xb2, 0x45, 0x66, + 0x3b, 0x42, 0x5b, 0xe7, 0xfa, 0x2f, 0x09, 0x8a, + 0x36, 0x36, 0xe5, 0xac, 0x83, 0xde, 0x7a, 0x66, + 0x33, 0xca, 0xcb, 0x09, 0xa7, 0xee, 0x39, 0x29, + 0x93, 0x79, 0x77, 0x9d, 0x59, 0x87, 0x23, 0x4e, + 0x3c, 0xb2, 0xa9, 0xdf, 0x1c, 0x2c, 0x07, 0x41, + 0xb5, 0xce, 0x35, 0x07, 0x71, 0x33, 0x7e, 0x6f, + 0x5e, 0xa7, 0x45, 0x24, 0x09, 0x53, 0x17, 0xf5, + 0x32, 0x87, 0x65, 0x99, 0xea, 0x55, 0x67, 0xd6, + 0x21, 0x87, 0x4a, 0xc2, 0x30, 0x46, 0xa2, 0xc2, + 0x60, 0xfb, 0x67, 0xe4, 0x35, 0x4e, 0xc4, 0x6b, + 0xad, 0x73, 0xcd, 0x72, 0x14, 0x9f, 0x72, 0x21, + 0x50, 0x36, 0x80, 0x01, 0xf5, 0xbc, 0xe4, 0xa2, + 0x3f, 0x9f, 0xf5, 0x9a, 0x27, 0xc6, 0xb2, 0x1e, + 0x93, 0xdb, 0x24, 0x78, 0x5f, 0x06, 0xa7, 0x58, + 0x54, 0xe7, 0x0a, 0x56, 0x22, 0xa7, 0x47, 0xe2, + 0x3c, 0x6e, 0x78, 0xc4, 0x49, 0x82, 0xdf, 0x98, + 0x62, 0x6f, 0x2e, 0x3c, 0x6a, 0x37, 0x28, 0x20, + 0xe7, 0x4e, 0xa2, 0xfe, 0xc1, 0xca, 0xe7, 0x20, + 0xc1, 0xa4, 0xbe, 0x8f, 0xbb, 0x06, 0x95, 0x68, + 0x44, 0x76, 0x68, 0xd6, 0x61, 0xca, 0xb2, 0x9c, + 0x94, 0xca, 0x46, 0x3d, 0xb8, 0x59, 0x96, 0xa1, + 0xa1, 0xd1, 0x94, 0xf6, 0x7f, 0xa4, 0xb1, 0xd3, + 0xb9, 0xf3, 0xfa, 0xa4, 0xe4, 0x20, 0xcf, 0xf3, + 0x21, 0xf8, 0x6e, 0xf8, 0xff, 0x4b, 0xd4, 0x29, + 0xdf, 0x37, 0xcb, 0x4f, 0x9d, 0xc8, 0xdb, 0x6d, + 0x91, 0x80, 0x92, 0x83, 0xab, 0x75, 0xcb, 0xe2, + 0xa4, 0x79, 0xaf, 0xca, 0xff, 0x47, 0xd7, 0xae, + 0xa6, 0x0d, 0x42, 0xc7, 0x13, 0xb2, 0xdc, 0xd3, + 0xdb, 0xf9, 0x19, 0x59, 0x87, 0x61, 0x10, 0xcb, + 0x31, 0xa4, 0x69, 0xac, 0x53, 0x76, 0xed, 0xda, + 0x92, 0xbc, 0x0f, 0x7d, 0x70, 0xc9, 0x11, 0x96, + 0x45, 0x90, 0xfc, 0x1f, 0xfc, 0x3f, 0x13, 0xed, + 0x77, 0xc6, 0x7e, 0x76, 0xd5, 0xe6, 0x89, 0x1f, + 0x79, 0x4b, 0x96, 0xe5, 0xe2, 0x6e, 0xcb, 0xf2, + 0x1e, 0x24, 0x34, 0x5c, 0x34, 0x74, 0x1b, 0x92, + 0xe1, 0x49, 0x89, 0x13, 0xbb, 0xdf, 0x6d, 0x96, + 0xdd, 0x5f, 0x75, 0xae, 0x60, 0x67, 0x38, 0x39, + 0x41, 0x4e, 0xba, 0x7b, 0x1c, 0xf0, 0xbd, 0x71, + 0xa1, 0xc5, 0x10, 0x91, 0xaf, 0x6a, 0x9e, 0xfd, + 0x11, 0xce, 0x03, 0x34, 0xbe, 0x7b, 0x49, 0xf7, + 0xff, 0x40, 0x96, 0xe7, 0x09, 0x8e, 0x1f, 0x2e, + 0x10, 0xbb, 0xfe, 0x31, 0x71, 0xbd, 0x2c, 0x3f, + 0xa4, 0x34, 0x66, 0xc7, 0xd8, 0x6d, 0x39, 0x57, + 0x76, 0x8a, 0x9f, 0x4a, 0x50, 0xac, 0xb1, 0xa9, + 0xa0, 0x55, 0xdc, 0xd8, 0xaf, 0x27, 0x6a, 0xcb, + 0xac, 0x33, 0x7a, 0x07, 0x3c, 0x5f, 0x03, 0x12, + 0x5e, 0xae, 0xba, 0xbb, 0xb8, 0x1a, 0xad, 0x8e, + 0x50, 0x93, 0x83, 0x84, 0x5c, 0x13, 0x57, 0x9c, + 0x5d, 0xd4, 0xe7, 0xd1, 0xf8, 0x65, 0x53, 0xb8, + 0xe3, 0x4e, 0x2d, 0x61, 0x25, 0x91, 0x38, 0x2a, + 0x07, 0xe6, 0x4c, 0xc2, 0x0a, 0x9e, 0x4b, 0xd0, + 0xc8, 0x84, 0x7b, 0x8a, 0xd6, 0x72, 0x64, 0x35, + 0xe4, 0x34, 0x1f, 0x92, 0xf5, 0xbe, 0xdc, 0xae, + 0x4f, 0x7c, 0x2d, 0x41, 0xab, 0x4a, 0x4e, 0x00, + 0xb4, 0x9e, 0x2c, 0x91, 0x68, 0xdf, 0x31, 0xcb, + 0xcc, 0x24, 0xac, 0xc8, 0x73, 0xbc, 0x37, 0xc5, + 0xd9, 0xb5, 0x3a, 0xee, 0x83, 0x13, 0xdd, 0xab, + 0x77, 0x8a, 0xda, 0x4a, 0xe4, 0x9c, 0xab, 0xdf, + 0x2f, 0xef, 0x97, 0x78, 0x67, 0xa2, 0x2c, 0x92, + 0x67, 0x98, 0xbf, 0xda, 0xb0, 0x84, 0x24, 0xdc, + 0x77, 0xcf, 0xf2, 0x33, 0x27, 0xd5, 0x76, 0x5b, + 0xec, 0x6b, 0x3f, 0x97, 0xa0, 0xd5, 0x70, 0x89, + 0x04, 0x66, 0x61, 0xb1, 0xf9, 0x36, 0xc3, 0x45, + 0x60, 0x99, 0xb0, 0x92, 0x6b, 0x9f, 0x19, 0x62, + 0x33, 0xff, 0x3b, 0xe7, 0x8e, 0xa9, 0x04, 0xb7, + 0x75, 0xc7, 0xec, 0xf7, 0x5b, 0xbe, 0x58, 0x6f, + 0x13, 0x33, 0x72, 0x7b, 0x65, 0xc2, 0x4a, 0xe9, + 0xd1, 0xd3, 0xf8, 0xfe, 0xb7, 0x91, 0xdf, 0x4f, + 0xd4, 0x8e, 0x03, 0x12, 0x56, 0x3e, 0x68, 0xad, + 0x65, 0x34, 0x89, 0xf1, 0x4c, 0xc2, 0x8a, 0x3c, + 0xc7, 0x77, 0x4b, 0x89, 0x4e, 0xd9, 0x88, 0x89, + 0xd2, 0x95, 0xb2, 0xc8, 0x5e, 0xda, 0xfe, 0x72, + 0x20, 0xdc, 0x39, 0x51, 0x62, 0x98, 0xc1, 0x89, + 0x3c, 0x7e, 0xc6, 0xe8, 0xe9, 0x29, 0x6f, 0x6e, + 0x5f, 0x9e, 0x92, 0xe7, 0x9f, 0x3a, 0x7a, 0x79, + 0x0a, 0xc5, 0x8a, 0x8d, 0xcc, 0xd3, 0x1f, 0xf3, + 0x5b, 0xcd, 0xb3, 0xd3, 0x66, 0x06, 0x65, 0xcf, + 0x73, 0x4f, 0x18, 0xbd, 0x34, 0x85, 0x9c, 0xc3, + 0x44, 0x1e, 0xd3, 0x67, 0xee, 0x63, 0xcd, 0x2b, + 0xd3, 0xbe, 0x92, 0x28, 0x5b, 0x3a, 0x2f, 0x25, + 0xeb, 0x5d, 0xbe, 0xd9, 0xc2, 0xac, 0x2f, 0x24, + 0x7a, 0x87, 0xe4, 0xcb, 0x6b, 0x37, 0x6c, 0x96, + 0x9a, 0xf5, 0xac, 0x76, 0x91, 0xb9, 0xb2, 0xdc, + 0xa5, 0x12, 0xdf, 0x6e, 0xd6, 0x98, 0x46, 0x0e, + 0xb3, 0x91, 0xf9, 0xa3, 0x46, 0x4f, 0xcd, 0x18, + 0x34, 0x98, 0x7c, 0x96, 0x7f, 0xf6, 0x68, 0xb5, + 0x29, 0x3f, 0x48, 0x2c, 0xdb, 0xb5, 0xe4, 0xb8, + 0x66, 0x8d, 0x59, 0x33, 0x37, 0x79, 0xc8, 0x73, + 0x7c, 0x6f, 0x25, 0xea, 0xed, 0x7a, 0xe5, 0x75, + 0x1a, 0x4a, 0x95, 0xe6, 0xdd, 0xb2, 0x70, 0x25, + 0xd9, 0x66, 0xed, 0x7d, 0x5e, 0xd7, 0xbe, 0x3c, + 0x23, 0xaf, 0x5d, 0x23, 0xc1, 0xf7, 0x54, 0xe2, + 0x22, 0x7a, 0x65, 0x59, 0x9f, 0xe3, 0xe2, 0x4d, + 0xcd, 0x96, 0xa6, 0xb1, 0x1f, 0xd3, 0xc5, 0x6a, + 0x46, 0x9e, 0xff, 0x7e, 0xb3, 0xc4, 0xb4, 0x85, + 0x37, 0xd9, 0xc8, 0x32, 0x47, 0x8c, 0x16, 0x9d, + 0x31, 0x55, 0x84, 0x9b, 0xc7, 0xf4, 0x9b, 0xae, + 0x59, 0x74, 0x1c, 0xd4, 0xb6, 0xff, 0xdd, 0x44, + 0xed, 0x02, 0x78, 0x4a, 0x96, 0x79, 0x5b, 0xb3, + 0xf4, 0xb4, 0xa9, 0xaa, 0x91, 0xdd, 0x64, 0x5b, + 0x5d, 0x2e, 0x6d, 0xd9, 0x29, 0x67, 0xf3, 0xff, + 0xd0, 0xf0, 0xe5, 0xa0, 0xe6, 0xf1, 0x66, 0x7c, + 0x7d, 0xcf, 0x31, 0x07, 0x37, 0x7d, 0x31, 0x93, + 0x4c, 0x51, 0xaf, 0xd6, 0xad, 0xab, 0xdb, 0x84, + 0x27, 0xee, 0xbd, 0xfd, 0x9e, 0xff, 0x6a, 0xe7, + 0x07, 0xc9, 0x8e, 0x3b, 0xb7, 0x58, 0x18, 0x59, + 0x86, 0x06, 0x4c, 0xd4, 0xa3, 0x75, 0x8b, 0xa0, + 0xc8, 0x6d, 0xd1, 0x07, 0x90, 0xe2, 0xce, 0x46, + 0x96, 0xa3, 0x61, 0xc7, 0xbf, 0x25, 0xba, 0xb9, + 0x17, 0xea, 0xce, 0xe8, 0x1b, 0xdb, 0xe4, 0x0c, + 0xb3, 0xcc, 0x5a, 0x8b, 0x85, 0xb3, 0x0c, 0x39, + 0x65, 0x8a, 0xc4, 0xcb, 0x12, 0x96, 0xa7, 0x67, + 0x39, 0xd6, 0x1f, 0x2c, 0xdb, 0xec, 0x2b, 0x16, + 0x7e, 0x6e, 0xb6, 0x49, 0x63, 0xa2, 0xaa, 0xac, + 0x47, 0x1d, 0xe7, 0xef, 0x8e, 0x1e, 0x4d, 0x70, + 0x45, 0x7e, 0xad, 0xac, 0x47, 0x55, 0xc4, 0x42, + 0xd9, 0x06, 0xbf, 0x05, 0xbf, 0x49, 0x17, 0x45, + 0xc2, 0x74, 0x15, 0xfa, 0x5e, 0x5e, 0xe7, 0xe6, + 0xf6, 0x5c, 0x60, 0x94, 0xff, 0x2f, 0xb9, 0x63, + 0xbe, 0xbf, 0xe7, 0x65, 0x39, 0xee, 0x79, 0x3b, + 0x57, 0xb6, 0xf3, 0x77, 0x99, 0x5c, 0x7f, 0xf4, + 0x68, 0x82, 0xbe, 0xa7, 0xd7, 0xcf, 0xfa, 0x7c, + 0xe6, 0xb9, 0xb2, 0x3e, 0x63, 0x46, 0xd3, 0x72, + 0xb5, 0xcc, 0x65, 0xbd, 0x3c, 0xeb, 0x53, 0x92, + 0x30, 0x91, 0x65, 0xb7, 0x65, 0xb1, 0x70, 0xde, + 0x83, 0xc4, 0x84, 0xfe, 0x95, 0xe5, 0xff, 0x70, + 0xe7, 0xbc, 0x0f, 0x7d, 0x8e, 0x67, 0x64, 0x1d, + 0xce, 0x1f, 0x7c, 0x77, 0x34, 0xb8, 0xe9, 0xe2, + 0xb9, 0x1b, 0x2d, 0xf3, 0xdd, 0xd5, 0x64, 0xbb, + 0xb4, 0x07, 0xe0, 0x66, 0xf2, 0x5d, 0x94, 0x84, + 0x70, 0x7f, 0xdb, 0x49, 0xc3, 0xaa, 0xae, 0xac, + 0xb3, 0xbf, 0x8a, 0x85, 0xe9, 0x33, 0x4d, 0x17, + 0xb0, 0xaa, 0xac, 0x57, 0x3b, 0x6e, 0xb9, 0x40, + 0x3c, 0x32, 0xeb, 0x8d, 0x1e, 0xf5, 0xc8, 0xba, + 0x5c, 0x88, 0x96, 0xa5, 0x3f, 0x27, 0x65, 0x3d, + 0xea, 0xfc, 0x77, 0x9d, 0xdd, 0x98, 0xb8, 0x6e, + 0xbc, 0x9f, 0x6b, 0x12, 0xd7, 0xe6, 0x64, 0x92, + 0xc4, 0x75, 0x9f, 0xf4, 0x73, 0x4d, 0x52, 0xb8, + 0xd6, 0x7e, 0xae, 0xd9, 0x99, 0xa7, 0x4e, 0x6c, + 0x59, 0xee, 0x1d, 0x99, 0x94, 0xf7, 0x57, 0x7d, + 0x4c, 0x96, 0x9b, 0xe4, 0xca, 0xb2, 0x4c, 0xad, + 0x7e, 0x96, 0x93, 0xfd, 0xa4, 0x2e, 0x31, 0xcb, + 0xac, 0x3b, 0x71, 0xa5, 0x4f, 0x6b, 0x2d, 0x17, + 0x7d, 0xe3, 0x2c, 0x47, 0x57, 0x98, 0xc1, 0xb2, + 0xcd, 0xbe, 0xc4, 0x75, 0x6e, 0x1f, 0xdf, 0xac, + 0x47, 0x91, 0x1e, 0x0d, 0x95, 0xba, 0xb8, 0xe8, + 0xb9, 0x4c, 0xd6, 0x5b, 0xaa, 0xce, 0x28, 0xdb, + 0x20, 0x47, 0x47, 0xdf, 0xd8, 0x2e, 0x4e, 0xd8, + 0x57, 0xc8, 0x36, 0xc8, 0x31, 0xb0, 0xff, 0x72, + 0x62, 0xac, 0x76, 0xd4, 0x0f, 0x4e, 0x86, 0xe4, + 0xf0, 0x48, 0x88, 0xaa, 0xd5, 0x05, 0xd9, 0x06, + 0x17, 0x41, 0x5f, 0x4f, 0x94, 0xb9, 0x8f, 0xa9, + 0xdf, 0x6a, 0x91, 0x6c, 0x87, 0xfa, 0x30, 0x8a, + 0xed, 0xba, 0x3e, 0x90, 0x6d, 0x4c, 0xdd, 0xff, + 0x37, 0xcb, 0x6d, 0xd7, 0xc4, 0xf5, 0x71, 0x99, + 0x70, 0x63, 0x88, 0x2e, 0xea, 0x0f, 0xf9, 0xae, + 0x7b, 0xab, 0x09, 0xb2, 0x1e, 0x0d, 0xca, 0xe8, + 0x47, 0xdd, 0xc5, 0xef, 0x7b, 0x83, 0xac, 0xc7, + 0x05, 0xca, 0x20, 0xd9, 0x1e, 0xd5, 0x48, 0xd4, + 0x97, 0x97, 0xbf, 0x07, 0x55, 0x0d, 0x14, 0xbd, + 0x8e, 0x1e, 0x15, 0xb2, 0xde, 0xfe, 0x4a, 0x5c, + 0x17, 0x1d, 0x07, 0xdc, 0xec, 0xbe, 0xac, 0x83, + 0xa6, 0xc1, 0xd3, 0x3f, 0x8f, 0x66, 0xe7, 0xe2, + 0xd8, 0x2e, 0x7b, 0x23, 0xac, 0xad, 0x4e, 0x7b, + 0xbb, 0xd9, 0x6d, 0x75, 0xae, 0x5a, 0xcd, 0x4b, + 0xda, 0x69, 0xd7, 0xfd, 0x72, 0x20, 0x35, 0x47, + 0x7e, 0x3b, 0x2d, 0x47, 0xca, 0xe1, 0x84, 0xb3, + 0xd1, 0xbe, 0xad, 0x51, 0x6b, 0xe6, 0x4f, 0x43, + 0xab, 0x95, 0x2e, 0x36, 0x16, 0x20, 0x91, 0x98, + 0xa7, 0x56, 0x1f, 0xfa, 0xd9, 0x9c, 0x18, 0x96, + 0x4a, 0x58, 0x5b, 0xb5, 0x44, 0x9d, 0xef, 0xb6, + 0xa9, 0x17, 0xcc, 0xb6, 0x48, 0x68, 0xb9, 0xb2, + 0xef, 0x1b, 0x9f, 0x99, 0xa2, 0x70, 0xea, 0xbb, + 0x68, 0x3c, 0xf6, 0x9a, 0x44, 0xad, 0xbf, 0x2f, + 0xdb, 0xaa, 0x75, 0xbd, 0x19, 0x5a, 0x77, 0x4f, + 0x43, 0xa0, 0xd2, 0x8e, 0x18, 0x6f, 0xb7, 0xdd, + 0x5f, 0x6b, 0xad, 0xde, 0xb9, 0xe8, 0x38, 0x21, + 0xaf, 0x53, 0x15, 0x52, 0x8d, 0xbc, 0x5e, 0xab, + 0x03, 0xe4, 0x3c, 0x39, 0xf8, 0x3e, 0xaf, 0xd9, + 0x1e, 0xfd, 0x9a, 0x29, 0x86, 0x2e, 0x13, 0x56, + 0x5a, 0x79, 0x3f, 0x3a, 0xbf, 0xf7, 0xe8, 0xd1, + 0xf6, 0x52, 0xab, 0x6f, 0xef, 0xe2, 0xe2, 0xb4, + 0xc4, 0x7e, 0x48, 0xfd, 0xf6, 0xa2, 0xa8, 0x75, + 0xf3, 0x2b, 0x2f, 0xc4, 0x77, 0x0d, 0x13, 0x57, + 0x81, 0x06, 0x1e, 0x65, 0x17, 0x01, 0x06, 0x4a, + 0x18, 0x37, 0xcb, 0x3f, 0x3c, 0x31, 0x95, 0x63, + 0x09, 0xae, 0x8e, 0x27, 0xc3, 0x0a, 0x6e, 0x08, + 0x0d, 0x7e, 0x4a, 0x24, 0xae, 0xe4, 0x8e, 0xd7, + 0x6d, 0x51, 0xa3, 0xa7, 0xda, 0xa0, 0x0f, 0x43, + 0x3f, 0x47, 0x73, 0x3f, 0xd3, 0x8a, 0x49, 0x62, + 0x98, 0x13, 0x2e, 0x0d, 0xc4, 0x68, 0x9d, 0xcc, + 0xa8, 0x50, 0x7d, 0x28, 0xea, 0x24, 0x17, 0xfd, + 0xf1, 0x9c, 0xc0, 0xef, 0x93, 0x68, 0x9e, 0x6c, + 0xd1, 0x42, 0xb6, 0x76, 0x5c, 0x0f, 0x1d, 0x11, + 0xa7, 0x56, 0xfc, 0x5c, 0x16, 0xb1, 0x6e, 0x57, + 0xec, 0xb7, 0xb5, 0x91, 0xbe, 0x28, 0x76, 0x27, + 0x47, 0x3b, 0x2f, 0xfa, 0xfa, 0xf4, 0x0e, 0xea, + 0xf3, 0x9a, 0x65, 0x49, 0x39, 0x19, 0xca, 0x90, + 0x63, 0xa7, 0x8b, 0x01, 0x5c, 0xc8, 0x1d, 0x32, + 0xdd, 0x8e, 0x16, 0x7d, 0xae, 0xea, 0xe0, 0x27, + 0x9a, 0x65, 0xe2, 0x2a, 0x4e, 0xe8, 0x14, 0x41, + 0xd1, 0x07, 0xaf, 0x34, 0x6e, 0x3a, 0x7f, 0x5c, + 0xa2, 0x1c, 0xf0, 0xe0, 0xa5, 0xfb, 0xe0, 0xca, + 0xbb, 0x76, 0x32, 0x67, 0x9f, 0xdd, 0x1f, 0x27, + 0xf9, 0x5a, 0x0e, 0xb5, 0x2c, 0xb6, 0x5b, 0xa4, + 0xef, 0xe4, 0x3c, 0xd5, 0x47, 0x38, 0xdf, 0xeb, + 0x9f, 0x64, 0x42, 0xbd, 0x1f, 0x45, 0xe2, 0xf3, + 0x72, 0xc6, 0x9c, 0xe8, 0x18, 0x83, 0x76, 0xd2, + 0xa8, 0x2c, 0xfa, 0xea, 0x05, 0x87, 0x0e, 0x24, + 0x51, 0x8e, 0xc0, 0x85, 0x41, 0x77, 0x3c, 0xda, + 0x8f, 0x16, 0xf5, 0xd5, 0x5e, 0x05, 0x2d, 0xf7, + 0xcb, 0xaa, 0x93, 0x79, 0xf8, 0x4d, 0x6a, 0x09, + 0xf5, 0xa3, 0xf2, 0xfb, 0x2e, 0x1c, 0x52, 0x71, + 0x1b, 0x1b, 0x52, 0x52, 0x73, 0x40, 0x33, 0x71, + 0xd5, 0x18, 0x75, 0x39, 0x93, 0x8e, 0xe2, 0xad, + 0xa3, 0x73, 0x05, 0x4e, 0x2b, 0xc0, 0xb2, 0xae, + 0x91, 0x46, 0x38, 0xd5, 0x16, 0xc5, 0x6b, 0x56, + 0xcb, 0x6d, 0x71, 0xd2, 0xdf, 0x1f, 0xc5, 0x93, + 0x14, 0x29, 0x96, 0x86, 0x76, 0x4d, 0xe9, 0x1b, + 0x7c, 0xa2, 0xd6, 0x35, 0x86, 0x22, 0x67, 0xc6, + 0x99, 0xa5, 0xce, 0x8e, 0x6e, 0x0e, 0x7d, 0xb9, + 0x5e, 0x8e, 0xe1, 0xe7, 0xe5, 0x77, 0x1a, 0x8f, + 0xc1, 0x4b, 0x6e, 0xba, 0x76, 0x67, 0xa2, 0xa1, + 0xed, 0x10, 0x48, 0x4c, 0x4a, 0x2b, 0x35, 0xac, + 0xdb, 0x97, 0xf2, 0x3d, 0x90, 0x73, 0xa7, 0xcf, + 0xf1, 0x26, 0x1c, 0x9b, 0xed, 0xb7, 0xb3, 0xfd, + 0xb2, 0x0c, 0x7d, 0x65, 0x19, 0xc0, 0xa3, 0xbc, + 0xfa, 0xa4, 0xbe, 0xb2, 0x56, 0x05, 0xb3, 0x4e, + 0x9b, 0x3e, 0xa7, 0xd7, 0x8e, 0x49, 0x72, 0xe8, + 0xb4, 0x13, 0x58, 0x25, 0x7a, 0x1b, 0x4f, 0xed, + 0x74, 0x26, 0xae, 0x6a, 0xe4, 0x44, 0x4e, 0xb1, + 0x70, 0xd9, 0xff, 0x8f, 0x56, 0xd7, 0xd4, 0x19, + 0x35, 0x75, 0x82, 0x1d, 0x6f, 0xc8, 0xf2, 0x43, + 0x8b, 0x19, 0x57, 0x41, 0x43, 0x89, 0x12, 0xfb, + 0x2c, 0x77, 0xc2, 0xd9, 0xd7, 0x6a, 0x75, 0x96, + 0x57, 0xce, 0x89, 0xb4, 0x56, 0x74, 0xdd, 0xe7, + 0x3a, 0xed, 0xb4, 0x8b, 0x3b, 0x95, 0xf4, 0xde, + 0x29, 0x27, 0xdf, 0xf3, 0xe9, 0x09, 0xea, 0xbb, + 0xa9, 0x7f, 0xa6, 0xff, 0x21, 0xa5, 0x0c, 0x25, + 0x12, 0x56, 0x46, 0xa7, 0x02, 0x09, 0x75, 0xad, + 0xb8, 0xba, 0x6c, 0x3d, 0xdc, 0x2b, 0xff, 0x13, + 0x25, 0x03, 0x54, 0x0b, 0x94, 0xa6, 0xba, 0x4a, + 0x6d, 0x53, 0xdc, 0x6d, 0x69, 0xc8, 0x6f, 0x32, + 0x04, 0x7d, 0x80, 0xe7, 0xf6, 0x79, 0xcd, 0x77, + 0xc7, 0xc5, 0x1f, 0xc7, 0x4c, 0x79, 0x77, 0x24, + 0xf6, 0xe5, 0xe3, 0xf3, 0x5b, 0x2e, 0x4e, 0x9d, + 0xfb, 0x2d, 0x53, 0x24, 0xbb, 0xc9, 0x01, 0x74, + 0x50, 0xab, 0x8b, 0xbf, 0x50, 0xfe, 0xaf, 0xd3, + 0x56, 0x8c, 0x4d, 0xb4, 0x9f, 0xd8, 0x16, 0x4c, + 0x5c, 0xd5, 0x45, 0x0e, 0xa9, 0xc4, 0x78, 0xc3, + 0x5d, 0x9c, 0x1c, 0xe6, 0xb6, 0x58, 0x5c, 0x23, + 0x5a, 0x04, 0xd7, 0x8a, 0xa1, 0x1e, 0xb0, 0x4c, + 0x0e, 0x62, 0xcd, 0x3e, 0xda, 0x4e, 0xbb, 0x28, + 0x6a, 0x2d, 0xbb, 0xd6, 0x54, 0xe5, 0xf3, 0xb2, + 0x6c, 0x39, 0x00, 0x07, 0x3e, 0x94, 0x13, 0x4c, + 0x59, 0x62, 0x30, 0x23, 0xcb, 0xd0, 0xa1, 0x9f, + 0xc6, 0x4e, 0x0c, 0x3a, 0x51, 0xfb, 0x4e, 0x9a, + 0xee, 0x23, 0x59, 0x86, 0xd7, 0xe8, 0x3a, 0x52, + 0xba, 0x55, 0x3e, 0x43, 0x79, 0x91, 0xd4, 0x87, + 0xbb, 0xbc, 0xd4, 0x4e, 0xe4, 0xd4, 0x07, 0x6f, + 0xca, 0x96, 0x6e, 0x52, 0x80, 0x76, 0x9f, 0xa8, + 0x15, 0xc5, 0x92, 0xeb, 0xa7, 0x45, 0x33, 0xff, + 0xff, 0xb2, 0x41, 0xfd, 0x6b, 0x89, 0xdf, 0xb0, + 0x77, 0xc8, 0xbe, 0xf6, 0xfd, 0x19, 0x8d, 0xab, + 0x1c, 0xe1, 0x8a, 0x76, 0x02, 0x0c, 0x6f, 0x58, + 0x1b, 0xf6, 0xb1, 0x4f, 0xed, 0x02, 0xa9, 0x1c, + 0x3d, 0xaa, 0x66, 0xe8, 0x0d, 0x1a, 0x86, 0xaa, + 0xb5, 0x98, 0xbe, 0x5d, 0xfe, 0xf7, 0x9d, 0x52, + 0x1f, 0xbf, 0xcf, 0x98, 0xb8, 0xaa, 0x8b, 0xfe, + 0x6a, 0x8b, 0x5a, 0x95, 0x9e, 0x96, 0x18, 0x3a, + 0x6e, 0xef, 0xaa, 0xe8, 0xe3, 0x5a, 0xab, 0x9f, + 0x62, 0x58, 0xbf, 0x7b, 0xb7, 0x27, 0xb3, 0xb9, + 0xb2, 0x0c, 0x03, 0x51, 0xb4, 0x8f, 0xb6, 0x84, + 0x71, 0x83, 0x6b, 0xb9, 0x46, 0x06, 0xc3, 0xa0, + 0x28, 0xb2, 0x57, 0xfb, 0xfe, 0x74, 0x33, 0xa9, + 0x15, 0x0b, 0x4f, 0x8a, 0xd7, 0xb3, 0x1c, 0x83, + 0x0d, 0xb4, 0x8f, 0x7a, 0xb1, 0x7c, 0xad, 0xdb, + 0x43, 0xb7, 0x6f, 0x77, 0xad, 0x1f, 0x27, 0x89, + 0xe5, 0xe3, 0x16, 0x6d, 0x3f, 0xaf, 0x93, 0xc8, + 0xd5, 0x46, 0xe0, 0xa1, 0x81, 0x13, 0x5d, 0x68, + 0xd6, 0xa1, 0xf6, 0x21, 0x16, 0x0e, 0x42, 0xb0, + 0x04, 0x06, 0x64, 0x60, 0x44, 0xae, 0xd2, 0x3b, + 0x92, 0xb0, 0x71, 0xaf, 0x60, 0x46, 0x19, 0x5a, + 0x2a, 0xb2, 0x0e, 0xdd, 0xec, 0x6a, 0xc5, 0xeb, + 0x14, 0x0d, 0xf7, 0x35, 0x36, 0xe0, 0xde, 0xa7, + 0xb5, 0x62, 0xce, 0xa7, 0x66, 0x9b, 0x43, 0x2f, + 0x4c, 0x6a, 0xad, 0xd7, 0xef, 0x90, 0xf7, 0xee, + 0x4d, 0xc4, 0xf2, 0x1a, 0xfb, 0xe1, 0xe0, 0x56, + 0xcd, 0x03, 0x71, 0xd3, 0x8a, 0x12, 0x2d, 0x88, + 0xb9, 0x33, 0xce, 0xd2, 0xd8, 0x0f, 0x89, 0xdd, + 0xcc, 0xc4, 0x55, 0x13, 0x39, 0x01, 0x90, 0x83, + 0x5a, 0x94, 0x2b, 0x7d, 0x45, 0x96, 0xdb, 0x27, + 0x47, 0x45, 0xde, 0x87, 0x5c, 0x58, 0xd9, 0xf9, + 0x1e, 0x9c, 0xdc, 0xe8, 0x06, 0x44, 0x4b, 0xd9, + 0xde, 0x56, 0x55, 0x79, 0x8d, 0xa2, 0x4d, 0x12, + 0xa3, 0xde, 0x11, 0x67, 0x96, 0x95, 0xcf, 0x42, + 0xb1, 0x39, 0xfd, 0x81, 0x4b, 0xe4, 0x26, 0xb8, + 0xc3, 0x0d, 0xdd, 0x2e, 0xfa, 0x70, 0x31, 0x50, + 0x0e, 0x40, 0x01, 0x4e, 0xa0, 0xd4, 0xc3, 0x8d, + 0x51, 0xb4, 0xfb, 0xdc, 0x6c, 0x6b, 0x5e, 0xd1, + 0x1e, 0xff, 0x6f, 0xad, 0x21, 0xd5, 0x64, 0xc0, + 0x8f, 0xa0, 0x58, 0xb2, 0x96, 0xf3, 0xe1, 0xe6, + 0x07, 0x0f, 0xee, 0x3b, 0xa9, 0xe5, 0x79, 0x12, + 0x56, 0xfa, 0x78, 0x96, 0xa5, 0x15, 0xe0, 0x46, + 0xef, 0xcd, 0x18, 0xc8, 0x6b, 0x50, 0xdb, 0xce, + 0x4d, 0xf3, 0xfe, 0xe4, 0x18, 0xb7, 0x82, 0xb6, + 0x01, 0xb5, 0xc4, 0xa7, 0x36, 0xac, 0xe1, 0x22, + 0xf4, 0x97, 0x7f, 0xcf, 0x68, 0x76, 0x0a, 0x75, + 0xe0, 0xdd, 0x21, 0x50, 0x1b, 0xf9, 0xec, 0x24, + 0x30, 0xec, 0x93, 0xe5, 0xfe, 0xc8, 0x58, 0xc2, + 0xbd, 0x7d, 0x7e, 0xe7, 0xe0, 0x06, 0xfb, 0x25, + 0xba, 0xbc, 0x54, 0x07, 0x5c, 0xc8, 0xfb, 0x73, + 0x2e, 0xa7, 0xee, 0xb3, 0xd6, 0x65, 0x6c, 0x9d, + 0x28, 0x15, 0xa1, 0x0f, 0x74, 0xe9, 0x39, 0xf9, + 0x0c, 0xdd, 0x41, 0xff, 0x7b, 0x65, 0x39, 0x2e, + 0xa4, 0xc8, 0xe1, 0xef, 0xea, 0xf4, 0xc7, 0xc4, + 0x55, 0x25, 0x5a, 0x9f, 0xf6, 0x75, 0x4b, 0xe1, + 0x84, 0xbd, 0xca, 0x89, 0x6a, 0x2b, 0xf8, 0x3c, + 0xb5, 0x13, 0x0d, 0x75, 0x5b, 0x0c, 0x1e, 0xfe, + 0x9e, 0x1c, 0xac, 0xe4, 0x26, 0x0e, 0x4f, 0x1c, + 0x92, 0xa0, 0x1e, 0xf4, 0x1e, 0x09, 0x46, 0xbe, + 0xe1, 0x24, 0x50, 0x1d, 0x27, 0x79, 0x45, 0x0c, + 0x64, 0x5e, 0x6b, 0x31, 0x4b, 0x8e, 0xe5, 0xf4, + 0xbc, 0xe7, 0x23, 0x13, 0xd7, 0x49, 0xf0, 0x39, + 0x2e, 0x97, 0xb8, 0x6d, 0x82, 0x8b, 0x15, 0x72, + 0x7c, 0xb5, 0xfe, 0x7c, 0x8f, 0x4f, 0x82, 0xd5, + 0xed, 0xfa, 0x40, 0xa2, 0x49, 0xce, 0xe7, 0xd3, + 0x59, 0xef, 0xe4, 0xc4, 0x6d, 0x12, 0x4d, 0x8e, + 0x34, 0x53, 0x82, 0x44, 0xf7, 0xc9, 0x89, 0x5a, + 0x37, 0x93, 0x49, 0xce, 0x28, 0xdb, 0x64, 0x74, + 0x25, 0xc6, 0x49, 0x2e, 0x71, 0xbc, 0x33, 0x78, + 0x01, 0xc3, 0x02, 0xd2, 0x58, 0xed, 0x50, 0xb6, + 0x99, 0x38, 0x2c, 0x41, 0xc2, 0xc4, 0x5d, 0x68, + 0x18, 0x07, 0xb9, 0x44, 0xbd, 0xf0, 0xd4, 0x20, + 0x20, 0x5b, 0x54, 0xab, 0x67, 0xe3, 0xff, 0x64, + 0x78, 0xbc, 0x5b, 0x24, 0x18, 0x2a, 0xf2, 0x46, + 0x09, 0x46, 0x5b, 0x5b, 0x4a, 0x96, 0xe5, 0xc2, + 0xa0, 0x36, 0xa0, 0x0b, 0x09, 0x39, 0xa5, 0x0e, + 0x83, 0xe4, 0x3b, 0x64, 0x72, 0x4a, 0xf3, 0x60, + 0x1a, 0x2f, 0x4c, 0xe5, 0x0e, 0xf3, 0xde, 0x24, + 0xe8, 0x0c, 0x32, 0x52, 0x36, 0xb4, 0xe3, 0x2a, + 0x86, 0x2e, 0x6b, 0xc7, 0x67, 0x99, 0x87, 0x2c, + 0x11, 0xdd, 0x2a, 0x86, 0xda, 0x85, 0x1c, 0x9e, + 0x95, 0xe5, 0x9e, 0x99, 0xe0, 0xb7, 0x3b, 0x5f, + 0xe2, 0x82, 0x09, 0x6e, 0x08, 0x40, 0x7b, 0x89, + 0x72, 0x60, 0xfc, 0xb5, 0x6b, 0xbf, 0x17, 0x06, + 0x7f, 0x29, 0xaf, 0xd0, 0xa8, 0xe7, 0x7e, 0x6f, + 0x3e, 0x0b, 0x8d, 0xeb, 0xae, 0x9d, 0x98, 0x2a, + 0xe6, 0xcf, 0xe3, 0x0b, 0x25, 0xc6, 0xc7, 0x03, + 0xbf, 0x7f, 0xb7, 0x85, 0xfb, 0xae, 0x54, 0x5e, + 0x65, 0xed, 0x6c, 0x8e, 0xd0, 0x34, 0x25, 0x3b, + 0xf2, 0x52, 0x23, 0x34, 0x95, 0xb2, 0x1e, 0x77, + 0x46, 0xa9, 0xb5, 0xb8, 0x24, 0xd7, 0xda, 0x3b, + 0xbe, 0x69, 0xd6, 0xe3, 0xe4, 0x4d, 0x02, 0xbc, + 0xb6, 0xbb, 0xe2, 0x20, 0xcb, 0x92, 0x03, 0xe5, + 0x86, 0xd6, 0x0c, 0xcb, 0x37, 0x0f, 0xc5, 0x78, + 0x7c, 0x86, 0xee, 0x7e, 0xcd, 0xe7, 0x39, 0x24, + 0xdb, 0x5d, 0x74, 0x57, 0x9c, 0x9b, 0x64, 0x99, + 0xda, 0xc8, 0x36, 0x13, 0x59, 0x97, 0x09, 0xb9, + 0xbf, 0x5a, 0xc2, 0xd5, 0xc5, 0xe7, 0xe0, 0x33, + 0xcc, 0xbb, 0x78, 0x65, 0xdf, 0xe1, 0xee, 0x34, + 0x93, 0x93, 0x54, 0xb6, 0x4f, 0xff, 0xd6, 0xf2, + 0xd6, 0x67, 0x5c, 0xe8, 0xd0, 0x52, 0x99, 0x93, + 0x15, 0xff, 0x7f, 0x2d, 0x67, 0x46, 0x43, 0xa3, + 0xeb, 0x66, 0x5b, 0x93, 0x84, 0x3f, 0xdb, 0xa2, + 0x7e, 0x90, 0x62, 0xfe, 0x9b, 0x37, 0x4f, 0xd4, + 0xf1, 0xde, 0x7c, 0xd6, 0x79, 0x5d, 0x8a, 0x28, + 0xcd, 0x60, 0xb0, 0xff, 0x72, 0x3f, 0x6a, 0xe4, + 0x7d, 0x56, 0x19, 0xa1, 0x89, 0x3e, 0xd3, 0xe5, + 0xed, 0x0e, 0xbb, 0xf8, 0x4c, 0xfc, 0xbf, 0x67, + 0x67, 0x3b, 0xe3, 0x56, 0xd0, 0x73, 0x65, 0x9b, + 0x3f, 0x93, 0xc9, 0x5f, 0x25, 0xca, 0x73, 0xda, + 0x6b, 0xb2, 0x8d, 0x95, 0x8a, 0x4a, 0xb3, 0x4d, + 0x1a, 0x25, 0xf1, 0xff, 0x95, 0xa5, 0x12, 0xb4, + 0x9a, 0xbe, 0x52, 0xb6, 0x3b, 0x1e, 0xf6, 0xf3, + 0xc4, 0x4c, 0xd6, 0x71, 0x2f, 0xd6, 0x77, 0x65, + 0x9b, 0x4d, 0xbd, 0x7c, 0xb6, 0x49, 0x69, 0x0b, + 0xc3, 0x92, 0x56, 0xc7, 0x1e, 0x0e, 0x4a, 0x75, + 0xb8, 0x30, 0xe3, 0x7b, 0xea, 0x96, 0xcc, 0xf0, + 0x7b, 0xd5, 0x7e, 0xcf, 0x65, 0x47, 0x68, 0x5a, + 0x38, 0xfa, 0x59, 0xd6, 0xe5, 0x3b, 0xa6, 0xc4, + 0x85, 0x11, 0xd4, 0x6a, 0xd8, 0xaf, 0xd8, 0x36, + 0xe7, 0x62, 0xea, 0x9b, 0xd9, 0x6f, 0xd9, 0x47, + 0xba, 0x9f, 0x93, 0xef, 0x95, 0xcf, 0x54, 0x6b, + 0x3f, 0xb0, 0x2b, 0x98, 0x73, 0x55, 0x4d, 0xad, + 0x61, 0x13, 0x07, 0xcc, 0xda, 0x07, 0x57, 0x5f, + 0x46, 0x0e, 0x40, 0xc6, 0xee, 0xe5, 0x42, 0x61, + 0x51, 0x83, 0x10, 0x4e, 0x34, 0xe5, 0xc9, 0x75, + 0x6d, 0xf2, 0x39, 0x98, 0x70, 0xf3, 0x70, 0x46, + 0xf2, 0x99, 0x24, 0x8a, 0x15, 0x7c, 0x8e, 0x79, + 0xc7, 0x16, 0xc3, 0x48, 0x3e, 0x28, 0xdb, 0x9b, + 0xb7, 0x8d, 0x31, 0x72, 0xe8, 0x74, 0x8b, 0x21, + 0x57, 0x54, 0x4b, 0x58, 0xa9, 0x0b, 0xbd, 0x5f, + 0xb6, 0x35, 0x95, 0xa3, 0x6e, 0x1f, 0x73, 0xd3, + 0xf5, 0x79, 0x17, 0x0c, 0xfc, 0x43, 0xf3, 0x12, + 0x56, 0xb6, 0xc1, 0x90, 0x7b, 0xd5, 0x84, 0x75, + 0x0b, 0xb8, 0x50, 0xaa, 0x35, 0xba, 0x1a, 0xe3, + 0xfb, 0x1b, 0x8a, 0xbe, 0xad, 0xb5, 0xdf, 0xbe, + 0x76, 0x9f, 0xd6, 0xa5, 0xe4, 0xff, 0x66, 0x20, + 0x8f, 0xb2, 0x05, 0x3d, 0xb8, 0x78, 0x1f, 0x27, + 0x82, 0x24, 0x52, 0xcd, 0x58, 0xe3, 0xeb, 0x94, + 0xf7, 0xe6, 0x62, 0x90, 0x41, 0xed, 0xfb, 0x1a, + 0xbb, 0xb1, 0x7f, 0x91, 0xe8, 0x77, 0x13, 0x2c, + 0x7e, 0x2f, 0x6e, 0x97, 0xb8, 0x51, 0xf9, 0x6c, + 0xec, 0xb7, 0x8c, 0xab, 0x3e, 0x73, 0x1b, 0xc4, + 0x16, 0xbf, 0x03, 0xfb, 0x2b, 0x77, 0x28, 0xe3, + 0x0e, 0x4d, 0x8c, 0xcc, 0xb4, 0xe5, 0xaa, 0x99, + 0x9d, 0xc6, 0xc4, 0x55, 0x35, 0xef, 0x4b, 0x94, + 0xdd, 0x2e, 0x68, 0x58, 0x34, 0x37, 0x67, 0xb7, + 0x49, 0x39, 0xa0, 0x29, 0xb2, 0xe4, 0x26, 0x09, + 0x43, 0x6f, 0xa0, 0xbd, 0xd6, 0x2b, 0x63, 0x4e, + 0x2c, 0x09, 0xc6, 0x08, 0xa6, 0x01, 0x07, 0xc5, + 0xaf, 0x43, 0x90, 0x8b, 0xa6, 0xc5, 0x2f, 0xf7, + 0xc5, 0xac, 0xde, 0x2f, 0x77, 0x20, 0xba, 0x45, + 0xdc, 0x2e, 0xdb, 0xaa, 0xdd, 0x03, 0x96, 0xcf, + 0xca, 0xc5, 0x08, 0x2d, 0x7f, 0xa9, 0xb7, 0x5e, + 0xd8, 0x22, 0xb9, 0xc0, 0x05, 0xcd, 0xad, 0xb3, + 0x8d, 0xf2, 0xbe, 0x9d, 0x5b, 0x96, 0x6d, 0x92, + 0x33, 0xe5, 0xe4, 0x3c, 0xa4, 0xf5, 0x6c, 0xaf, + 0x24, 0x70, 0x24, 0x32, 0xb5, 0x92, 0x16, 0xba, + 0x38, 0xd5, 0xea, 0x4d, 0x87, 0xe8, 0x1b, 0x67, + 0x77, 0xdc, 0x2a, 0x99, 0x0b, 0x9e, 0x79, 0x17, + 0x28, 0x2b, 0xcb, 0xf7, 0x44, 0xc3, 0x34, 0x4a, + 0xc6, 0x6a, 0xf5, 0xe7, 0x25, 0x86, 0x2d, 0x64, + 0x90, 0x8b, 0x5a, 0x83, 0xa3, 0xb5, 0xcb, 0x67, + 0xa3, 0x2b, 0x1e, 0x37, 0x92, 0xa7, 0xdf, 0xee, + 0x2a, 0xc7, 0x18, 0xad, 0xef, 0x97, 0xb9, 0xb8, + 0xdc, 0xb1, 0x36, 0x76, 0x95, 0xbf, 0x5f, 0x58, + 0x2c, 0x3c, 0x25, 0x27, 0x1d, 0x8a, 0x04, 0xcb, + 0x22, 0xcc, 0x0f, 0xe7, 0xc0, 0x58, 0xd8, 0x71, + 0x3b, 0xeb, 0x72, 0xf7, 0x13, 0x46, 0x66, 0x1a, + 0x7b, 0xe1, 0xa2, 0x13, 0x6d, 0xd6, 0xe1, 0x62, + 0x8d, 0x84, 0xb9, 0x1c, 0xdd, 0xe7, 0xe4, 0xac, + 0x3b, 0xd5, 0x50, 0x2a, 0xcb, 0x52, 0x3f, 0x54, + 0x8e, 0x57, 0xfc, 0xb9, 0x2c, 0x37, 0x77, 0x00, + 0x80, 0xf6, 0x3d, 0x18, 0xa7, 0xf4, 0xf8, 0x04, + 0x2d, 0x43, 0x6b, 0x75, 0x99, 0x1c, 0xb4, 0x24, + 0x3c, 0x9c, 0x9c, 0x48, 0x58, 0xce, 0xc8, 0x76, + 0x33, 0x69, 0xd6, 0x67, 0xdf, 0x28, 0xef, 0x7f, + 0x0a, 0x72, 0x7f, 0xcb, 0x0c, 0x3e, 0x3e, 0x91, + 0x6d, 0x51, 0x4f, 0xc8, 0xf7, 0x44, 0x42, 0x4b, + 0x1f, 0xd6, 0xda, 0x49, 0x96, 0x84, 0x84, 0x0b, + 0x15, 0x8a, 0xda, 0x5f, 0x9c, 0xf7, 0xe8, 0x4d, + 0x90, 0xb3, 0x3d, 0xc6, 0x0e, 0xa6, 0x55, 0x31, + 0xff, 0x1f, 0x5d, 0x6b, 0x6a, 0x57, 0xfb, 0x6c, + 0x8f, 0xcf, 0xc9, 0xbe, 0xc7, 0xf7, 0xda, 0x37, + 0xb8, 0xc4, 0x44, 0xb6, 0xcb, 0x84, 0x61, 0xf8, + 0x68, 0x0c, 0x43, 0xfd, 0x70, 0x6d, 0x7c, 0x58, + 0x50, 0xcc, 0x48, 0xae, 0x92, 0xdf, 0xf9, 0x8d, + 0xd9, 0xf6, 0xc2, 0x04, 0x39, 0xdb, 0xe6, 0x3b, + 0x2e, 0x1b, 0x60, 0xbd, 0x28, 0xeb, 0xbe, 0xb2, + 0x9d, 0xef, 0x95, 0x75, 0xe9, 0xbb, 0xcb, 0xcd, + 0x21, 0x8e, 0x4a, 0x94, 0xa3, 0x57, 0xf1, 0xde, + 0xef, 0xcf, 0x76, 0x16, 0xd6, 0x99, 0x67, 0x3b, + 0xdc, 0xbb, 0xb6, 0xd6, 0x60, 0x8c, 0x7b, 0xdd, + 0x6e, 0x29, 0x27, 0x97, 0x6d, 0xb3, 0x2f, 0x53, + 0xff, 0x59, 0x16, 0x0d, 0x93, 0x4b, 0x24, 0x31, + 0xa3, 0xf8, 0x9d, 0xef, 0x60, 0x95, 0xdc, 0x76, + 0x89, 0x6e, 0x59, 0x33, 0x37, 0x57, 0xc8, 0x67, + 0xa0, 0x91, 0x12, 0xb7, 0xbd, 0xa3, 0xf4, 0xe6, + 0xd0, 0xc4, 0xf8, 0xbb, 0x22, 0x77, 0xcb, 0x45, + 0x2f, 0xed, 0x20, 0x18, 0x31, 0xed, 0x9b, 0x59, + 0x96, 0xb1, 0x91, 0x6b, 0xdf, 0xfd, 0x5d, 0xf2, + 0x7a, 0xf7, 0x2e, 0x57, 0x14, 0x79, 0x4f, 0x6e, + 0x77, 0xd8, 0x31, 0xe8, 0x38, 0xc8, 0x76, 0x98, + 0xd0, 0xf5, 0x88, 0xcf, 0x47, 0x3f, 0xe0, 0xbe, + 0x01, 0x5e, 0xf8, 0x3d, 0xb9, 0x2f, 0x31, 0x89, + 0x3f, 0x17, 0x2c, 0x1f, 0xcd, 0xfb, 0x64, 0xb2, + 0x7b, 0x99, 0xb8, 0x0e, 0xb7, 0x63, 0x12, 0xd7, + 0xdd, 0x2e, 0x07, 0x36, 0x5d, 0x0f, 0xa8, 0xa3, + 0xe5, 0xe4, 0xc3, 0xc9, 0x8f, 0xdc, 0x20, 0xb9, + 0x15, 0x6e, 0x35, 0x76, 0x56, 0x0e, 0x5e, 0x12, + 0xa2, 0x8d, 0xcb, 0xe7, 0x60, 0xbf, 0xa3, 0x6e, + 0x90, 0x96, 0xc3, 0x74, 0xb7, 0x21, 0x51, 0xa4, + 0x3e, 0x8e, 0xba, 0xb9, 0x4f, 0x26, 0xe8, 0xa3, + 0xba, 0xf4, 0x55, 0x7a, 0x7b, 0xc2, 0xe2, 0x7f, + 0xe3, 0x44, 0xca, 0xad, 0xd3, 0x48, 0xc4, 0xe9, + 0x06, 0xc4, 0xf6, 0x38, 0x41, 0x7d, 0x69, 0xc8, + 0xf6, 0xba, 0xb2, 0x6d, 0x12, 0x01, 0x12, 0x57, + 0x8a, 0xea, 0x28, 0xd2, 0xe4, 0x82, 0x80, 0xe2, + 0x4f, 0xea, 0xc0, 0x3e, 0x95, 0xed, 0x2e, 0xbc, + 0xa5, 0xdd, 0x3a, 0xb5, 0xff, 0x2b, 0x9f, 0x83, + 0x22, 0x44, 0x8e, 0x5b, 0x9e, 0xe0, 0x18, 0x26, + 0xe7, 0xfc, 0xd5, 0x55, 0xff, 0xcf, 0xdd, 0xa8, + 0xdd, 0xcf, 0xb8, 0x98, 0xa4, 0x5b, 0x15, 0xdf, + 0x0b, 0xb9, 0xc7, 0xef, 0xe4, 0x3b, 0xca, 0x64, + 0xff, 0xcb, 0xe7, 0x23, 0xd1, 0xa7, 0x45, 0x33, + 0x31, 0x1e, 0xc8, 0x83, 0xcf, 0x48, 0xa2, 0x4e, + 0x17, 0xbf, 0xaf, 0x1f, 0x48, 0xbf, 0xa7, 0x89, + 0xeb, 0x70, 0x26, 0xae, 0x92, 0xa4, 0xb9, 0xac, + 0x73, 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25, + 0x49, 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6, + 0xcc, 0xc4, 0x55, 0x92, 0xa4, 0x35, 0x33, 0x71, + 0x95, 0x24, 0x69, 0xcd, 0x4c, 0x5c, 0x25, 0x49, + 0x5a, 0x33, 0x13, 0x57, 0x49, 0x92, 0xd6, 0xcc, + 0xc4, 0x55, 0x92, 0xa4, 0x35, 0xdb, 0x6d, 0x83, + 0x48, 0xf0, 0x97, 0x7b, 0x0a, 0x96, 0x43, 0xa9, + 0xad, 0xd3, 0x77, 0xf7, 0x1c, 0x73, 0x70, 0x33, + 0xc6, 0xee, 0x39, 0xef, 0x6a, 0x46, 0x07, 0xda, + 0xe4, 0x80, 0x15, 0xf8, 0xc8, 0xde, 0xdb, 0x37, + 0xc3, 0x9c, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, + 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, + 0x24, 0x49, 0x92, 0x24, 0x49, 0x92, 0x24, 0x49, + 0x5b, 0xb7, 0x67, 0xcf, 0xff, 0x03, 0x27, 0xa6, + 0xaa, 0x9c, 0x80, 0xec, 0x5b, 0x07, 0x00, 0x00, + 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, + 0x60, 0x82, +}; + +unsigned int mslogo_jpg_size = sizeof(mslogo_jpg); + +const unsigned char nxlogo_png[] = { + 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, + 0x0d, 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x01, 0x34, 0x00, 0x00, + 0x00, 0x55, 0x08, 0x06, 0x00, 0x00, 0x00, 0xc7, 0x5e, 0x18, 0xd4, + 0x00, 0x00, 0x00, 0x09, 0x70, 0x48, 0x59, 0x73, 0x00, 0x00, 0x2e, + 0x23, 0x00, 0x00, 0x2e, 0x23, 0x01, 0x78, 0xa5, 0x3f, 0x76, 0x00, + 0x00, 0x0a, 0x4f, 0x69, 0x43, 0x43, 0x50, 0x50, 0x68, 0x6f, 0x74, + 0x6f, 0x73, 0x68, 0x6f, 0x70, 0x20, 0x49, 0x43, 0x43, 0x20, 0x70, + 0x72, 0x6f, 0x66, 0x69, 0x6c, 0x65, 0x00, 0x00, 0x78, 0xda, 0x9d, + 0x53, 0x67, 0x54, 0x53, 0xe9, 0x16, 0x3d, 0xf7, 0xde, 0xf4, 0x42, + 0x4b, 0x88, 0x80, 0x94, 0x4b, 0x6f, 0x52, 0x15, 0x08, 0x20, 0x52, + 0x42, 0x8b, 0x80, 0x14, 0x91, 0x26, 0x2a, 0x21, 0x09, 0x10, 0x4a, + 0x88, 0x21, 0xa1, 0xd9, 0x15, 0x51, 0xc1, 0x11, 0x45, 0x45, 0x04, + 0x1b, 0xc8, 0xa0, 0x88, 0x03, 0x8e, 0x8e, 0x80, 0x8c, 0x15, 0x51, + 0x2c, 0x0c, 0x8a, 0x0a, 0xd8, 0x07, 0xe4, 0x21, 0xa2, 0x8e, 0x83, + 0xa3, 0x88, 0x8a, 0xca, 0xfb, 0xe1, 0x7b, 0xa3, 0x6b, 0xd6, 0xbc, + 0xf7, 0xe6, 0xcd, 0xfe, 0xb5, 0xd7, 0x3e, 0xe7, 0xac, 0xf3, 0x9d, + 0xb3, 0xcf, 0x07, 0xc0, 0x08, 0x0c, 0x96, 0x48, 0x33, 0x51, 0x35, + 0x80, 0x0c, 0xa9, 0x42, 0x1e, 0x11, 0xe0, 0x83, 0xc7, 0xc4, 0xc6, + 0xe1, 0xe4, 0x2e, 0x40, 0x81, 0x0a, 0x24, 0x70, 0x00, 0x10, 0x08, + 0xb3, 0x64, 0x21, 0x73, 0xfd, 0x23, 0x01, 0x00, 0xf8, 0x7e, 0x3c, + 0x3c, 0x2b, 0x22, 0xc0, 0x07, 0xbe, 0x00, 0x01, 0x78, 0xd3, 0x0b, + 0x08, 0x00, 0xc0, 0x4d, 0x9b, 0xc0, 0x30, 0x1c, 0x87, 0xff, 0x0f, + 0xea, 0x42, 0x99, 0x5c, 0x01, 0x80, 0x84, 0x01, 0xc0, 0x74, 0x91, + 0x38, 0x4b, 0x08, 0x80, 0x14, 0x00, 0x40, 0x7a, 0x8e, 0x42, 0xa6, + 0x00, 0x40, 0x46, 0x01, 0x80, 0x9d, 0x98, 0x26, 0x53, 0x00, 0xa0, + 0x04, 0x00, 0x60, 0xcb, 0x63, 0x62, 0xe3, 0x00, 0x50, 0x2d, 0x00, + 0x60, 0x27, 0x7f, 0xe6, 0xd3, 0x00, 0x80, 0x9d, 0xf8, 0x99, 0x7b, + 0x01, 0x00, 0x5b, 0x94, 0x21, 0x15, 0x01, 0xa0, 0x91, 0x00, 0x20, + 0x13, 0x65, 0x88, 0x44, 0x00, 0x68, 0x3b, 0x00, 0xac, 0xcf, 0x56, + 0x8a, 0x45, 0x00, 0x58, 0x30, 0x00, 0x14, 0x66, 0x4b, 0xc4, 0x39, + 0x00, 0xd8, 0x2d, 0x00, 0x30, 0x49, 0x57, 0x66, 0x48, 0x00, 0xb0, + 0xb7, 0x00, 0xc0, 0xce, 0x10, 0x0b, 0xb2, 0x00, 0x08, 0x0c, 0x00, + 0x30, 0x51, 0x88, 0x85, 0x29, 0x00, 0x04, 0x7b, 0x00, 0x60, 0xc8, + 0x23, 0x23, 0x78, 0x00, 0x84, 0x99, 0x00, 0x14, 0x46, 0xf2, 0x57, + 0x3c, 0xf1, 0x2b, 0xae, 0x10, 0xe7, 0x2a, 0x00, 0x00, 0x78, 0x99, + 0xb2, 0x3c, 0xb9, 0x24, 0x39, 0x45, 0x81, 0x5b, 0x08, 0x2d, 0x71, + 0x07, 0x57, 0x57, 0x2e, 0x1e, 0x28, 0xce, 0x49, 0x17, 0x2b, 0x14, + 0x36, 0x61, 0x02, 0x61, 0x9a, 0x40, 0x2e, 0xc2, 0x79, 0x99, 0x19, + 0x32, 0x81, 0x34, 0x0f, 0xe0, 0xf3, 0xcc, 0x00, 0x00, 0xa0, 0x91, + 0x15, 0x11, 0xe0, 0x83, 0xf3, 0xfd, 0x78, 0xce, 0x0e, 0xae, 0xce, + 0xce, 0x36, 0x8e, 0xb6, 0x0e, 0x5f, 0x2d, 0xea, 0xbf, 0x06, 0xff, + 0x22, 0x62, 0x62, 0xe3, 0xfe, 0xe5, 0xcf, 0xab, 0x70, 0x40, 0x00, + 0x00, 0xe1, 0x74, 0x7e, 0xd1, 0xfe, 0x2c, 0x2f, 0xb3, 0x1a, 0x80, + 0x3b, 0x06, 0x80, 0x6d, 0xfe, 0xa2, 0x25, 0xee, 0x04, 0x68, 0x5e, + 0x0b, 0xa0, 0x75, 0xf7, 0x8b, 0x66, 0xb2, 0x0f, 0x40, 0xb5, 0x00, + 0xa0, 0xe9, 0xda, 0x57, 0xf3, 0x70, 0xf8, 0x7e, 0x3c, 0x3c, 0x45, + 0xa1, 0x90, 0xb9, 0xd9, 0xd9, 0xe5, 0xe4, 0xe4, 0xd8, 0x4a, 0xc4, + 0x42, 0x5b, 0x61, 0xca, 0x57, 0x7d, 0xfe, 0x67, 0xc2, 0x5f, 0xc0, + 0x57, 0xfd, 0x6c, 0xf9, 0x7e, 0x3c, 0xfc, 0xf7, 0xf5, 0xe0, 0xbe, + 0xe2, 0x24, 0x81, 0x32, 0x5d, 0x81, 0x47, 0x04, 0xf8, 0xe0, 0xc2, + 0xcc, 0xf4, 0x4c, 0xa5, 0x1c, 0xcf, 0x92, 0x09, 0x84, 0x62, 0xdc, + 0xe6, 0x8f, 0x47, 0xfc, 0xb7, 0x0b, 0xff, 0xfc, 0x1d, 0xd3, 0x22, + 0xc4, 0x49, 0x62, 0xb9, 0x58, 0x2a, 0x14, 0xe3, 0x51, 0x12, 0x71, + 0x8e, 0x44, 0x9a, 0x8c, 0xf3, 0x32, 0xa5, 0x22, 0x89, 0x42, 0x92, + 0x29, 0xc5, 0x25, 0xd2, 0xff, 0x64, 0xe2, 0xdf, 0x2c, 0xfb, 0x03, + 0x3e, 0xdf, 0x35, 0x00, 0xb0, 0x6a, 0x3e, 0x01, 0x7b, 0x91, 0x2d, + 0xa8, 0x5d, 0x63, 0x03, 0xf6, 0x4b, 0x27, 0x10, 0x58, 0x74, 0xc0, + 0xe2, 0xf7, 0x00, 0x00, 0xf2, 0xbb, 0x6f, 0xc1, 0xd4, 0x28, 0x08, + 0x03, 0x80, 0x68, 0x83, 0xe1, 0xcf, 0x77, 0xff, 0xef, 0x3f, 0xfd, + 0x47, 0xa0, 0x25, 0x00, 0x80, 0x66, 0x49, 0x92, 0x71, 0x00, 0x00, + 0x5e, 0x44, 0x24, 0x2e, 0x54, 0xca, 0xb3, 0x3f, 0xc7, 0x08, 0x00, + 0x00, 0x44, 0xa0, 0x81, 0x2a, 0xb0, 0x41, 0x1b, 0xf4, 0xc1, 0x18, + 0x2c, 0xc0, 0x06, 0x1c, 0xc1, 0x05, 0xdc, 0xc1, 0x0b, 0xfc, 0x60, + 0x36, 0x84, 0x42, 0x24, 0xc4, 0xc2, 0x42, 0x10, 0x42, 0x0a, 0x64, + 0x80, 0x1c, 0x72, 0x60, 0x29, 0xac, 0x82, 0x42, 0x28, 0x86, 0xcd, + 0xb0, 0x1d, 0x2a, 0x60, 0x2f, 0xd4, 0x40, 0x1d, 0x34, 0xc0, 0x51, + 0x68, 0x86, 0x93, 0x70, 0x0e, 0x2e, 0xc2, 0x55, 0xb8, 0x0e, 0x3d, + 0x70, 0x0f, 0xfa, 0x61, 0x08, 0x9e, 0xc1, 0x28, 0xbc, 0x81, 0x09, + 0x04, 0x41, 0xc8, 0x08, 0x13, 0x61, 0x21, 0xda, 0x88, 0x01, 0x62, + 0x8a, 0x58, 0x23, 0x8e, 0x08, 0x17, 0x99, 0x85, 0xf8, 0x21, 0xc1, + 0x48, 0x04, 0x12, 0x8b, 0x24, 0x20, 0xc9, 0x88, 0x14, 0x51, 0x22, + 0x4b, 0x91, 0x35, 0x48, 0x31, 0x52, 0x8a, 0x54, 0x20, 0x55, 0x48, + 0x1d, 0xf2, 0x3d, 0x72, 0x02, 0x39, 0x87, 0x5c, 0x46, 0xba, 0x91, + 0x3b, 0xc8, 0x00, 0x32, 0x82, 0xfc, 0x86, 0xbc, 0x47, 0x31, 0x94, + 0x81, 0xb2, 0x51, 0x3d, 0xd4, 0x0c, 0xb5, 0x43, 0xb9, 0xa8, 0x37, + 0x1a, 0x84, 0x46, 0xa2, 0x0b, 0xd0, 0x64, 0x74, 0x31, 0x9a, 0x8f, + 0x16, 0xa0, 0x9b, 0xd0, 0x72, 0xb4, 0x1a, 0x3d, 0x8c, 0x36, 0xa1, + 0xe7, 0xd0, 0xab, 0x68, 0x0f, 0xda, 0x8f, 0x3e, 0x43, 0xc7, 0x30, + 0xc0, 0xe8, 0x18, 0x07, 0x33, 0xc4, 0x6c, 0x30, 0x2e, 0xc6, 0xc3, + 0x42, 0xb1, 0x38, 0x2c, 0x09, 0x93, 0x63, 0xcb, 0xb1, 0x22, 0xac, + 0x0c, 0xab, 0xc6, 0x1a, 0xb0, 0x56, 0xac, 0x03, 0xbb, 0x89, 0xf5, + 0x63, 0xcf, 0xb1, 0x77, 0x04, 0x12, 0x81, 0x45, 0xc0, 0x09, 0x36, + 0x04, 0x77, 0x42, 0x20, 0x61, 0x1e, 0x41, 0x48, 0x58, 0x4c, 0x58, + 0x4e, 0xd8, 0x48, 0xa8, 0x20, 0x1c, 0x24, 0x34, 0x11, 0xda, 0x09, + 0x37, 0x09, 0x03, 0x84, 0x51, 0xc2, 0x27, 0x22, 0x93, 0xa8, 0x4b, + 0xb4, 0x26, 0xba, 0x11, 0xf9, 0xc4, 0x18, 0x62, 0x32, 0x31, 0x87, + 0x58, 0x48, 0x2c, 0x23, 0xd6, 0x12, 0x8f, 0x13, 0x2f, 0x10, 0x7b, + 0x88, 0x43, 0xc4, 0x37, 0x24, 0x12, 0x89, 0x43, 0x32, 0x27, 0xb9, + 0x90, 0x02, 0x49, 0xb1, 0xa4, 0x54, 0xd2, 0x12, 0xd2, 0x46, 0xd2, + 0x6e, 0x52, 0x23, 0xe9, 0x2c, 0xa9, 0x9b, 0x34, 0x48, 0x1a, 0x23, + 0x93, 0xc9, 0xda, 0x64, 0x6b, 0xb2, 0x07, 0x39, 0x94, 0x2c, 0x20, + 0x2b, 0xc8, 0x85, 0xe4, 0x9d, 0xe4, 0xc3, 0xe4, 0x33, 0xe4, 0x1b, + 0xe4, 0x21, 0xf2, 0x5b, 0x0a, 0x9d, 0x62, 0x40, 0x71, 0xa4, 0xf8, + 0x53, 0xe2, 0x28, 0x52, 0xca, 0x6a, 0x4a, 0x19, 0xe5, 0x10, 0xe5, + 0x34, 0xe5, 0x06, 0x65, 0x98, 0x32, 0x41, 0x55, 0xa3, 0x9a, 0x52, + 0xdd, 0xa8, 0xa1, 0x54, 0x11, 0x35, 0x8f, 0x5a, 0x42, 0xad, 0xa1, + 0xb6, 0x52, 0xaf, 0x51, 0x87, 0xa8, 0x13, 0x34, 0x75, 0x9a, 0x39, + 0xcd, 0x83, 0x16, 0x49, 0x4b, 0xa5, 0xad, 0xa2, 0x95, 0xd3, 0x1a, + 0x68, 0x17, 0x68, 0xf7, 0x69, 0xaf, 0xe8, 0x74, 0xba, 0x11, 0xdd, + 0x95, 0x1e, 0x4e, 0x97, 0xd0, 0x57, 0xd2, 0xcb, 0xe9, 0x47, 0xe8, + 0x97, 0xe8, 0x03, 0xf4, 0x77, 0x0c, 0x0d, 0x86, 0x15, 0x83, 0xc7, + 0x88, 0x67, 0x28, 0x19, 0x9b, 0x18, 0x07, 0x18, 0x67, 0x19, 0x77, + 0x18, 0xaf, 0x98, 0x4c, 0xa6, 0x19, 0xd3, 0x8b, 0x19, 0xc7, 0x54, + 0x30, 0x37, 0x31, 0xeb, 0x98, 0xe7, 0x99, 0x0f, 0x99, 0x6f, 0x55, + 0x58, 0x2a, 0xb6, 0x2a, 0x7c, 0x15, 0x91, 0xca, 0x0a, 0x95, 0x4a, + 0x95, 0x26, 0x95, 0x1b, 0x2a, 0x2f, 0x54, 0xa9, 0xaa, 0xa6, 0xaa, + 0xde, 0xaa, 0x0b, 0x55, 0xf3, 0x55, 0xcb, 0x54, 0x8f, 0xa9, 0x5e, + 0x53, 0x7d, 0xae, 0x46, 0x55, 0x33, 0x53, 0xe3, 0xa9, 0x09, 0xd4, + 0x96, 0xab, 0x55, 0xaa, 0x9d, 0x50, 0xeb, 0x53, 0x1b, 0x53, 0x67, + 0xa9, 0x3b, 0xa8, 0x87, 0xaa, 0x67, 0xa8, 0x6f, 0x54, 0x3f, 0xa4, + 0x7e, 0x59, 0xfd, 0x89, 0x06, 0x59, 0xc3, 0x4c, 0xc3, 0x4f, 0x43, + 0xa4, 0x51, 0xa0, 0xb1, 0x5f, 0xe3, 0xbc, 0xc6, 0x20, 0x0b, 0x63, + 0x19, 0xb3, 0x78, 0x2c, 0x21, 0x6b, 0x0d, 0xab, 0x86, 0x75, 0x81, + 0x35, 0xc4, 0x26, 0xb1, 0xcd, 0xd9, 0x7c, 0x76, 0x2a, 0xbb, 0x98, + 0xfd, 0x1d, 0xbb, 0x8b, 0x3d, 0xaa, 0xa9, 0xa1, 0x39, 0x43, 0x33, + 0x4a, 0x33, 0x57, 0xb3, 0x52, 0xf3, 0x94, 0x66, 0x3f, 0x07, 0xe3, + 0x98, 0x71, 0xf8, 0x9c, 0x74, 0x4e, 0x09, 0xe7, 0x28, 0xa7, 0x97, + 0xf3, 0x7e, 0x8a, 0xde, 0x14, 0xef, 0x29, 0xe2, 0x29, 0x1b, 0xa6, + 0x34, 0x4c, 0xb9, 0x31, 0x65, 0x5c, 0x6b, 0xaa, 0x96, 0x97, 0x96, + 0x58, 0xab, 0x48, 0xab, 0x51, 0xab, 0x47, 0xeb, 0xbd, 0x36, 0xae, + 0xed, 0xa7, 0x9d, 0xa6, 0xbd, 0x45, 0xbb, 0x59, 0xfb, 0x81, 0x0e, + 0x41, 0xc7, 0x4a, 0x27, 0x5c, 0x27, 0x47, 0x67, 0x8f, 0xce, 0x05, + 0x9d, 0xe7, 0x53, 0xd9, 0x53, 0xdd, 0xa7, 0x0a, 0xa7, 0x16, 0x4d, + 0x3d, 0x3a, 0xf5, 0xae, 0x2e, 0xaa, 0x6b, 0xa5, 0x1b, 0xa1, 0xbb, + 0x44, 0x77, 0xbf, 0x6e, 0xa7, 0xee, 0x98, 0x9e, 0xbe, 0x5e, 0x80, + 0x9e, 0x4c, 0x6f, 0xa7, 0xde, 0x79, 0xbd, 0xe7, 0xfa, 0x1c, 0x7d, + 0x2f, 0xfd, 0x54, 0xfd, 0x6d, 0xfa, 0xa7, 0xf5, 0x47, 0x0c, 0x58, + 0x06, 0xb3, 0x0c, 0x24, 0x06, 0xdb, 0x0c, 0xce, 0x18, 0x3c, 0xc5, + 0x35, 0x71, 0x6f, 0x3c, 0x1d, 0x2f, 0xc7, 0xdb, 0xf1, 0x51, 0x43, + 0x5d, 0xc3, 0x40, 0x43, 0xa5, 0x61, 0x95, 0x61, 0x97, 0xe1, 0x84, + 0x91, 0xb9, 0xd1, 0x3c, 0xa3, 0xd5, 0x46, 0x8d, 0x46, 0x0f, 0x8c, + 0x69, 0xc6, 0x5c, 0xe3, 0x24, 0xe3, 0x6d, 0xc6, 0x6d, 0xc6, 0xa3, + 0x26, 0x06, 0x26, 0x21, 0x26, 0x4b, 0x4d, 0xea, 0x4d, 0xee, 0x9a, + 0x52, 0x4d, 0xb9, 0xa6, 0x29, 0xa6, 0x3b, 0x4c, 0x3b, 0x4c, 0xc7, + 0xcd, 0xcc, 0xcd, 0xa2, 0xcd, 0xd6, 0x99, 0x35, 0x9b, 0x3d, 0x31, + 0xd7, 0x32, 0xe7, 0x9b, 0xe7, 0x9b, 0xd7, 0x9b, 0xdf, 0xb7, 0x60, + 0x5a, 0x78, 0x5a, 0x2c, 0xb6, 0xa8, 0xb6, 0xb8, 0x65, 0x49, 0xb2, + 0xe4, 0x5a, 0xa6, 0x59, 0xee, 0xb6, 0xbc, 0x6e, 0x85, 0x5a, 0x39, + 0x59, 0xa5, 0x58, 0x55, 0x5a, 0x5d, 0xb3, 0x46, 0xad, 0x9d, 0xad, + 0x25, 0xd6, 0xbb, 0xad, 0xbb, 0xa7, 0x11, 0xa7, 0xb9, 0x4e, 0x93, + 0x4e, 0xab, 0x9e, 0xd6, 0x67, 0xc3, 0xb0, 0xf1, 0xb6, 0xc9, 0xb6, + 0xa9, 0xb7, 0x19, 0xb0, 0xe5, 0xd8, 0x06, 0xdb, 0xae, 0xb6, 0x6d, + 0xb6, 0x7d, 0x61, 0x67, 0x62, 0x17, 0x67, 0xb7, 0xc5, 0xae, 0xc3, + 0xee, 0x93, 0xbd, 0x93, 0x7d, 0xba, 0x7d, 0x8d, 0xfd, 0x3d, 0x07, + 0x0d, 0x87, 0xd9, 0x0e, 0xab, 0x1d, 0x5a, 0x1d, 0x7e, 0x73, 0xb4, + 0x72, 0x14, 0x3a, 0x56, 0x3a, 0xde, 0x9a, 0xce, 0x9c, 0xee, 0x3f, + 0x7d, 0xc5, 0xf4, 0x96, 0xe9, 0x2f, 0x67, 0x58, 0xcf, 0x10, 0xcf, + 0xd8, 0x33, 0xe3, 0xb6, 0x13, 0xcb, 0x29, 0xc4, 0x69, 0x9d, 0x53, + 0x9b, 0xd3, 0x47, 0x67, 0x17, 0x67, 0xb9, 0x73, 0x83, 0xf3, 0x88, + 0x8b, 0x89, 0x4b, 0x82, 0xcb, 0x2e, 0x97, 0x3e, 0x2e, 0x9b, 0x1b, + 0xc6, 0xdd, 0xc8, 0xbd, 0xe4, 0x4a, 0x74, 0xf5, 0x71, 0x5d, 0xe1, + 0x7a, 0xd2, 0xf5, 0x9d, 0x9b, 0xb3, 0x9b, 0xc2, 0xed, 0xa8, 0xdb, + 0xaf, 0xee, 0x36, 0xee, 0x69, 0xee, 0x87, 0xdc, 0x9f, 0xcc, 0x34, + 0x9f, 0x29, 0x9e, 0x59, 0x33, 0x73, 0xd0, 0xc3, 0xc8, 0x43, 0xe0, + 0x51, 0xe5, 0xd1, 0x3f, 0x0b, 0x9f, 0x95, 0x30, 0x6b, 0xdf, 0xac, + 0x7e, 0x4f, 0x43, 0x4f, 0x81, 0x67, 0xb5, 0xe7, 0x23, 0x2f, 0x63, + 0x2f, 0x91, 0x57, 0xad, 0xd7, 0xb0, 0xb7, 0xa5, 0x77, 0xaa, 0xf7, + 0x61, 0xef, 0x17, 0x3e, 0xf6, 0x3e, 0x72, 0x9f, 0xe3, 0x3e, 0xe3, + 0x3c, 0x37, 0xde, 0x32, 0xde, 0x59, 0x5f, 0xcc, 0x37, 0xc0, 0xb7, + 0xc8, 0xb7, 0xcb, 0x4f, 0xc3, 0x6f, 0x9e, 0x5f, 0x85, 0xdf, 0x43, + 0x7f, 0x23, 0xff, 0x64, 0xff, 0x7a, 0xff, 0xd1, 0x00, 0xa7, 0x80, + 0x25, 0x01, 0x67, 0x03, 0x89, 0x81, 0x41, 0x81, 0x5b, 0x02, 0xfb, + 0xf8, 0x7a, 0x7c, 0x21, 0xbf, 0x8e, 0x3f, 0x3a, 0xdb, 0x65, 0xf6, + 0xb2, 0xd9, 0xed, 0x41, 0x8c, 0xa0, 0xb9, 0x41, 0x15, 0x41, 0x8f, + 0x82, 0xad, 0x82, 0xe5, 0xc1, 0xad, 0x21, 0x68, 0xc8, 0xec, 0x90, + 0xad, 0x21, 0xf7, 0xe7, 0x98, 0xce, 0x91, 0xce, 0x69, 0x0e, 0x85, + 0x50, 0x7e, 0xe8, 0xd6, 0xd0, 0x07, 0x61, 0xe6, 0x61, 0x8b, 0xc3, + 0x7e, 0x0c, 0x27, 0x85, 0x87, 0x85, 0x57, 0x86, 0x3f, 0x8e, 0x70, + 0x88, 0x58, 0x1a, 0xd1, 0x31, 0x97, 0x35, 0x77, 0xd1, 0xdc, 0x43, + 0x73, 0xdf, 0x44, 0xfa, 0x44, 0x96, 0x44, 0xde, 0x9b, 0x67, 0x31, + 0x4f, 0x39, 0xaf, 0x2d, 0x4a, 0x35, 0x2a, 0x3e, 0xaa, 0x2e, 0x6a, + 0x3c, 0xda, 0x37, 0xba, 0x34, 0xba, 0x3f, 0xc6, 0x2e, 0x66, 0x59, + 0xcc, 0xd5, 0x58, 0x9d, 0x58, 0x49, 0x6c, 0x4b, 0x1c, 0x39, 0x2e, + 0x2a, 0xae, 0x36, 0x6e, 0x6c, 0xbe, 0xdf, 0xfc, 0xed, 0xf3, 0x87, + 0xe2, 0x9d, 0xe2, 0x0b, 0xe3, 0x7b, 0x17, 0x98, 0x2f, 0xc8, 0x5d, + 0x70, 0x79, 0xa1, 0xce, 0xc2, 0xf4, 0x85, 0xa7, 0x16, 0xa9, 0x2e, + 0x12, 0x2c, 0x3a, 0x96, 0x40, 0x4c, 0x88, 0x4e, 0x38, 0x94, 0xf0, + 0x41, 0x10, 0x2a, 0xa8, 0x16, 0x8c, 0x25, 0xf2, 0x13, 0x77, 0x25, + 0x8e, 0x0a, 0x79, 0xc2, 0x1d, 0xc2, 0x67, 0x22, 0x2f, 0xd1, 0x36, + 0xd1, 0x88, 0xd8, 0x43, 0x5c, 0x2a, 0x1e, 0x4e, 0xf2, 0x48, 0x2a, + 0x4d, 0x7a, 0x92, 0xec, 0x91, 0xbc, 0x35, 0x79, 0x24, 0xc5, 0x33, + 0xa5, 0x2c, 0xe5, 0xb9, 0x84, 0x27, 0xa9, 0x90, 0xbc, 0x4c, 0x0d, + 0x4c, 0xdd, 0x9b, 0x3a, 0x9e, 0x16, 0x9a, 0x76, 0x20, 0x6d, 0x32, + 0x3d, 0x3a, 0xbd, 0x31, 0x83, 0x92, 0x91, 0x90, 0x71, 0x42, 0xaa, + 0x21, 0x4d, 0x93, 0xb6, 0x67, 0xea, 0x67, 0xe6, 0x66, 0x76, 0xcb, + 0xac, 0x65, 0x85, 0xb2, 0xfe, 0xc5, 0x6e, 0x8b, 0xb7, 0x2f, 0x1e, + 0x95, 0x07, 0xc9, 0x6b, 0xb3, 0x90, 0xac, 0x05, 0x59, 0x2d, 0x0a, + 0xb6, 0x42, 0xa6, 0xe8, 0x54, 0x5a, 0x28, 0xd7, 0x2a, 0x07, 0xb2, + 0x67, 0x65, 0x57, 0x66, 0xbf, 0xcd, 0x89, 0xca, 0x39, 0x96, 0xab, + 0x9e, 0x2b, 0xcd, 0xed, 0xcc, 0xb3, 0xca, 0xdb, 0x90, 0x37, 0x9c, + 0xef, 0x9f, 0xff, 0xed, 0x12, 0xc2, 0x12, 0xe1, 0x92, 0xb6, 0xa5, + 0x86, 0x4b, 0x57, 0x2d, 0x1d, 0x58, 0xe6, 0xbd, 0xac, 0x6a, 0x39, + 0xb2, 0x3c, 0x71, 0x79, 0xdb, 0x0a, 0xe3, 0x15, 0x05, 0x2b, 0x86, + 0x56, 0x06, 0xac, 0x3c, 0xb8, 0x8a, 0xb6, 0x2a, 0x6d, 0xd5, 0x4f, + 0xab, 0xed, 0x57, 0x97, 0xae, 0x7e, 0xbd, 0x26, 0x7a, 0x4d, 0x6b, + 0x81, 0x5e, 0xc1, 0xca, 0x82, 0xc1, 0xb5, 0x01, 0x6b, 0xeb, 0x0b, + 0x55, 0x0a, 0xe5, 0x85, 0x7d, 0xeb, 0xdc, 0xd7, 0xed, 0x5d, 0x4f, + 0x58, 0x2f, 0x59, 0xdf, 0xb5, 0x61, 0xfa, 0x86, 0x9d, 0x1b, 0x3e, + 0x15, 0x89, 0x8a, 0xae, 0x14, 0xdb, 0x17, 0x97, 0x15, 0x7f, 0xd8, + 0x28, 0xdc, 0x78, 0xe5, 0x1b, 0x87, 0x6f, 0xca, 0xbf, 0x99, 0xdc, + 0x94, 0xb4, 0xa9, 0xab, 0xc4, 0xb9, 0x64, 0xcf, 0x66, 0xd2, 0x66, + 0xe9, 0xe6, 0xde, 0x2d, 0x9e, 0x5b, 0x0e, 0x96, 0xaa, 0x97, 0xe6, + 0x97, 0x0e, 0x6e, 0x0d, 0xd9, 0xda, 0xb4, 0x0d, 0xdf, 0x56, 0xb4, + 0xed, 0xf5, 0xf6, 0x45, 0xdb, 0x2f, 0x97, 0xcd, 0x28, 0xdb, 0xbb, + 0x83, 0xb6, 0x43, 0xb9, 0xa3, 0xbf, 0x3c, 0xb8, 0xbc, 0x65, 0xa7, + 0xc9, 0xce, 0xcd, 0x3b, 0x3f, 0x54, 0xa4, 0x54, 0xf4, 0x54, 0xfa, + 0x54, 0x36, 0xee, 0xd2, 0xdd, 0xb5, 0x61, 0xd7, 0xf8, 0x6e, 0xd1, + 0xee, 0x1b, 0x7b, 0xbc, 0xf6, 0x34, 0xec, 0xd5, 0xdb, 0x5b, 0xbc, + 0xf7, 0xfd, 0x3e, 0xc9, 0xbe, 0xdb, 0x55, 0x01, 0x55, 0x4d, 0xd5, + 0x66, 0xd5, 0x65, 0xfb, 0x49, 0xfb, 0xb3, 0xf7, 0x3f, 0xae, 0x89, + 0xaa, 0xe9, 0xf8, 0x96, 0xfb, 0x6d, 0x5d, 0xad, 0x4e, 0x6d, 0x71, + 0xed, 0xc7, 0x03, 0xd2, 0x03, 0xfd, 0x07, 0x23, 0x0e, 0xb6, 0xd7, + 0xb9, 0xd4, 0xd5, 0x1d, 0xd2, 0x3d, 0x54, 0x52, 0x8f, 0xd6, 0x2b, + 0xeb, 0x47, 0x0e, 0xc7, 0x1f, 0xbe, 0xfe, 0x9d, 0xef, 0x77, 0x2d, + 0x0d, 0x36, 0x0d, 0x55, 0x8d, 0x9c, 0xc6, 0xe2, 0x23, 0x70, 0x44, + 0x79, 0xe4, 0xe9, 0xf7, 0x09, 0xdf, 0xf7, 0x1e, 0x0d, 0x3a, 0xda, + 0x76, 0x8c, 0x7b, 0xac, 0xe1, 0x07, 0xd3, 0x1f, 0x76, 0x1d, 0x67, + 0x1d, 0x2f, 0x6a, 0x42, 0x9a, 0xf2, 0x9a, 0x46, 0x9b, 0x53, 0x9a, + 0xfb, 0x5b, 0x62, 0x5b, 0xba, 0x4f, 0xcc, 0x3e, 0xd1, 0xd6, 0xea, + 0xde, 0x7a, 0xfc, 0x47, 0xdb, 0x1f, 0x0f, 0x9c, 0x34, 0x3c, 0x59, + 0x79, 0x4a, 0xf3, 0x54, 0xc9, 0x69, 0xda, 0xe9, 0x82, 0xd3, 0x93, + 0x67, 0xf2, 0xcf, 0x8c, 0x9d, 0x95, 0x9d, 0x7d, 0x7e, 0x2e, 0xf9, + 0xdc, 0x60, 0xdb, 0xa2, 0xb6, 0x7b, 0xe7, 0x63, 0xce, 0xdf, 0x6a, + 0x0f, 0x6f, 0xef, 0xba, 0x10, 0x74, 0xe1, 0xd2, 0x45, 0xff, 0x8b, + 0xe7, 0x3b, 0xbc, 0x3b, 0xce, 0x5c, 0xf2, 0xb8, 0x74, 0xf2, 0xb2, + 0xdb, 0xe5, 0x13, 0x57, 0xb8, 0x57, 0x9a, 0xaf, 0x3a, 0x5f, 0x6d, + 0xea, 0x74, 0xea, 0x3c, 0xfe, 0x93, 0xd3, 0x4f, 0xc7, 0xbb, 0x9c, + 0xbb, 0x9a, 0xae, 0xb9, 0x5c, 0x6b, 0xb9, 0xee, 0x7a, 0xbd, 0xb5, + 0x7b, 0x66, 0xf7, 0xe9, 0x1b, 0x9e, 0x37, 0xce, 0xdd, 0xf4, 0xbd, + 0x79, 0xf1, 0x16, 0xff, 0xd6, 0xd5, 0x9e, 0x39, 0x3d, 0xdd, 0xbd, + 0xf3, 0x7a, 0x6f, 0xf7, 0xc5, 0xf7, 0xf5, 0xdf, 0x16, 0xdd, 0x7e, + 0x72, 0x27, 0xfd, 0xce, 0xcb, 0xbb, 0xd9, 0x77, 0x27, 0xee, 0xad, + 0xbc, 0x4f, 0xbc, 0x5f, 0xf4, 0x40, 0xed, 0x41, 0xd9, 0x43, 0xdd, + 0x87, 0xd5, 0x3f, 0x5b, 0xfe, 0xdc, 0xd8, 0xef, 0xdc, 0x7f, 0x6a, + 0xc0, 0x77, 0xa0, 0xf3, 0xd1, 0xdc, 0x47, 0xf7, 0x06, 0x85, 0x83, + 0xcf, 0xfe, 0x91, 0xf5, 0x8f, 0x0f, 0x43, 0x05, 0x8f, 0x99, 0x8f, + 0xcb, 0x86, 0x0d, 0x86, 0xeb, 0x9e, 0x38, 0x3e, 0x39, 0x39, 0xe2, + 0x3f, 0x72, 0xfd, 0xe9, 0xfc, 0xa7, 0x43, 0xcf, 0x64, 0xcf, 0x26, + 0x9e, 0x17, 0xfe, 0xa2, 0xfe, 0xcb, 0xae, 0x17, 0x16, 0x2f, 0x7e, + 0xf8, 0xd5, 0xeb, 0xd7, 0xce, 0xd1, 0x98, 0xd1, 0xa1, 0x97, 0xf2, + 0x97, 0x93, 0xbf, 0x6d, 0x7c, 0xa5, 0xfd, 0xea, 0xc0, 0xeb, 0x19, + 0xaf, 0xdb, 0xc6, 0xc2, 0xc6, 0x1e, 0xbe, 0xc9, 0x78, 0x33, 0x31, + 0x5e, 0xf4, 0x56, 0xfb, 0xed, 0xc1, 0x77, 0xdc, 0x77, 0x1d, 0xef, + 0xa3, 0xdf, 0x0f, 0x4f, 0xe4, 0x7c, 0x20, 0x7f, 0x28, 0xff, 0x68, + 0xf9, 0xb1, 0xf5, 0x53, 0xd0, 0xa7, 0xfb, 0x93, 0x19, 0x93, 0x93, + 0xff, 0x04, 0x03, 0x98, 0xf3, 0xfc, 0x63, 0x33, 0x2d, 0xdb, 0x00, + 0x00, 0x00, 0x20, 0x63, 0x48, 0x52, 0x4d, 0x00, 0x00, 0x7a, 0x25, + 0x00, 0x00, 0x80, 0x83, 0x00, 0x00, 0xf9, 0xff, 0x00, 0x00, 0x80, + 0xe9, 0x00, 0x00, 0x75, 0x30, 0x00, 0x00, 0xea, 0x60, 0x00, 0x00, + 0x3a, 0x98, 0x00, 0x00, 0x17, 0x6f, 0x92, 0x5f, 0xc5, 0x46, 0x00, + 0x00, 0x25, 0xa0, 0x49, 0x44, 0x41, 0x54, 0x78, 0xda, 0xec, 0x9d, + 0x79, 0x94, 0x25, 0x55, 0x9d, 0xe7, 0xbf, 0xbf, 0x1b, 0xf1, 0xf6, + 0xf7, 0x72, 0xad, 0x5c, 0xaa, 0xa8, 0x3d, 0x6b, 0x2f, 0x76, 0x41, + 0x60, 0x4a, 0xb4, 0xb1, 0x65, 0x5c, 0xda, 0xb6, 0x15, 0x6c, 0x04, + 0xec, 0xd1, 0x43, 0xab, 0xad, 0x07, 0x41, 0x1a, 0xa4, 0x6d, 0x9d, + 0x46, 0xa4, 0x68, 0xa8, 0xee, 0x39, 0x72, 0xa6, 0xad, 0xee, 0x71, + 0x10, 0x97, 0x71, 0x03, 0xb4, 0x61, 0x46, 0x4b, 0xc7, 0x6d, 0xc0, + 0x06, 0x51, 0xb1, 0x9a, 0x62, 0x69, 0x4a, 0xaa, 0x84, 0xda, 0xf7, + 0x25, 0x2b, 0xf7, 0xcc, 0x97, 0x6f, 0x8d, 0xb8, 0x77, 0xfe, 0x78, + 0x2f, 0x5f, 0x46, 0xc6, 0x8b, 0xe5, 0xde, 0xb7, 0x64, 0x15, 0x95, + 0xf1, 0xcb, 0x13, 0xe7, 0x45, 0xdc, 0xb8, 0xb1, 0x64, 0x44, 0xdc, + 0x4f, 0x7c, 0x7f, 0xbf, 0x7b, 0xe3, 0x5e, 0x12, 0x42, 0x20, 0xb0, + 0xc0, 0x02, 0x0b, 0xec, 0x6c, 0x30, 0xbd, 0x32, 0xf7, 0x4a, 0x28, + 0xb8, 0x1a, 0x73, 0xdb, 0xe8, 0x2c, 0xfb, 0x7f, 0x82, 0x37, 0xf5, + 0x9c, 0x06, 0x5a, 0x60, 0x73, 0x11, 0x4a, 0xf4, 0x3a, 0xfa, 0xbf, + 0x44, 0x8d, 0xff, 0x5b, 0x3d, 0x60, 0x0b, 0xa0, 0x18, 0x00, 0x2d, + 0xb0, 0x26, 0x00, 0x85, 0x9a, 0xb0, 0xcf, 0x66, 0xc0, 0x8d, 0x6c, + 0x30, 0x20, 0x17, 0x40, 0xf8, 0x1d, 0x4b, 0x34, 0x00, 0x68, 0x6e, + 0xe7, 0xa0, 0x02, 0x32, 0xd5, 0xf3, 0x0c, 0xc0, 0x18, 0x00, 0x6d, + 0x4e, 0x82, 0xaa, 0x11, 0x20, 0xa3, 0x1a, 0xd3, 0x65, 0x0b, 0xf9, + 0xeb, 0xd1, 0x05, 0x15, 0x75, 0xae, 0xf7, 0xcb, 0x27, 0x6a, 0x54, + 0x81, 0xd4, 0xa0, 0xe3, 0x07, 0x16, 0x00, 0xed, 0x8c, 0x51, 0x54, + 0xb2, 0x70, 0xaa, 0x15, 0x54, 0x8d, 0x06, 0x2a, 0x35, 0xf1, 0xfa, + 0x34, 0xa3, 0x40, 0x37, 0x1a, 0x56, 0x32, 0xfb, 0x15, 0x8a, 0x69, + 0xd4, 0x60, 0x70, 0x05, 0xe0, 0x0b, 0x80, 0x36, 0x6b, 0xa0, 0x22, + 0xc5, 0xe5, 0x46, 0xe4, 0x21, 0x0f, 0x05, 0x56, 0x0f, 0xe4, 0xfc, + 0xd6, 0x89, 0x3a, 0xae, 0x6d, 0xb3, 0x63, 0x5c, 0x42, 0x61, 0x3b, + 0xe1, 0xf2, 0xff, 0xd4, 0xbb, 0x2c, 0x9b, 0x26, 0x0b, 0x3e, 0x31, + 0x0b, 0xd7, 0x36, 0x00, 0xda, 0xeb, 0x14, 0x5e, 0x24, 0xe1, 0x86, + 0x91, 0x02, 0x50, 0x6a, 0x9d, 0xf7, 0x5a, 0xb6, 0x9e, 0x1f, 0x29, + 0x9c, 0x5b, 0xbd, 0x10, 0x6e, 0x94, 0x02, 0xa3, 0x1a, 0x0b, 0x9c, + 0x4a, 0xec, 0xac, 0x56, 0xa8, 0xd8, 0xd3, 0x6b, 0x81, 0x91, 0xdf, + 0xb1, 0xb9, 0x87, 0xdb, 0xe9, 0xb4, 0x1f, 0xbf, 0x3c, 0xf5, 0x54, + 0x78, 0x38, 0xc1, 0xf0, 0xac, 0x01, 0xdf, 0xd9, 0x08, 0x34, 0x55, + 0xa5, 0x41, 0x92, 0xb0, 0x80, 0x4b, 0x3e, 0xf2, 0x59, 0x2f, 0xb3, + 0x9d, 0xca, 0xbe, 0x6b, 0x85, 0x62, 0xbd, 0x8a, 0xd2, 0x0d, 0xb0, + 0xb3, 0x61, 0xa2, 0xce, 0x3c, 0x2a, 0x8a, 0xaa, 0x96, 0x75, 0x7e, + 0x79, 0x34, 0x8f, 0x3c, 0x2a, 0x40, 0x13, 0x8a, 0xe7, 0xe5, 0xf4, + 0x42, 0x70, 0x4b, 0xf3, 0x52, 0xa8, 0x01, 0xd0, 0xce, 0x40, 0x17, + 0xb1, 0x1e, 0x65, 0x45, 0x35, 0x02, 0x8d, 0x1a, 0xb8, 0x4f, 0x55, + 0x78, 0xd6, 0x0b, 0xbe, 0x7a, 0x94, 0xdc, 0x6c, 0x83, 0x4d, 0x36, + 0x5d, 0x45, 0x55, 0x89, 0x1a, 0xe0, 0xd3, 0x88, 0x34, 0xfb, 0x7a, + 0xd9, 0xe3, 0xab, 0x9c, 0xa7, 0x9b, 0x5b, 0x4d, 0x75, 0x2a, 0xea, + 0x00, 0x68, 0x0a, 0x50, 0x12, 0x35, 0xa8, 0x0b, 0xbf, 0x02, 0xed, + 0x07, 0x1c, 0xaa, 0x03, 0x54, 0xcc, 0x03, 0x2c, 0x2a, 0x80, 0x53, + 0x01, 0x9a, 0xaa, 0x02, 0x54, 0x51, 0x70, 0xf5, 0xac, 0x6b, 0x86, + 0x22, 0x53, 0x8d, 0x4b, 0xc9, 0xaa, 0x23, 0x15, 0xd7, 0x4f, 0x16, + 0x32, 0x42, 0x72, 0x1b, 0x51, 0xc3, 0x7e, 0x54, 0x20, 0x57, 0x8b, + 0xbb, 0xeb, 0xe4, 0xa6, 0x8a, 0x1a, 0x42, 0x02, 0x73, 0x1a, 0x68, + 0x7e, 0x6a, 0xa1, 0x96, 0xc2, 0x2e, 0x03, 0x18, 0xaa, 0x01, 0x68, + 0xaa, 0xeb, 0x64, 0xd2, 0x1a, 0x01, 0xba, 0x7a, 0x21, 0x56, 0x4f, + 0xcd, 0xab, 0x4a, 0x9e, 0x46, 0x34, 0x65, 0x10, 0x75, 0x02, 0x4d, + 0x46, 0x9d, 0x71, 0x87, 0x02, 0x2c, 0x24, 0xe0, 0x21, 0x0b, 0x23, + 0x2e, 0x01, 0x39, 0x21, 0x09, 0x41, 0xaf, 0x63, 0x92, 0xe5, 0x58, + 0x4e, 0xe7, 0xac, 0x0a, 0xa9, 0x46, 0xd7, 0xdc, 0x9e, 0x15, 0x40, + 0x93, 0xa9, 0x9d, 0x53, 0x71, 0xf3, 0xfc, 0xd2, 0x54, 0xd6, 0xcb, + 0x6c, 0xe7, 0xb6, 0xec, 0x96, 0xa7, 0x51, 0xc0, 0x54, 0x01, 0x7d, + 0xbd, 0x95, 0x09, 0xcd, 0xaa, 0x48, 0x68, 0x26, 0xd0, 0xbc, 0xd4, + 0x46, 0xa3, 0xd5, 0x96, 0x97, 0x6a, 0x72, 0xcb, 0xa3, 0x9a, 0xae, + 0x9a, 0xc7, 0x29, 0xff, 0xd4, 0xcb, 0x5d, 0xe5, 0x3c, 0x49, 0xe1, + 0x85, 0x41, 0xa7, 0x53, 0xc1, 0xe9, 0xa7, 0x11, 0x60, 0x2a, 0xe0, + 0x52, 0x2d, 0xf8, 0xa4, 0xb8, 0xae, 0x96, 0x3c, 0xaa, 0xfb, 0xf3, + 0xdb, 0x4e, 0x15, 0x7e, 0x32, 0xea, 0x4e, 0x45, 0xd9, 0x9d, 0x89, + 0x71, 0x35, 0x51, 0x47, 0x5a, 0x2d, 0x6e, 0x96, 0x1f, 0xe4, 0xb8, + 0xc7, 0xbe, 0x65, 0x41, 0x63, 0xcf, 0xeb, 0x97, 0x66, 0xdf, 0x07, + 0x57, 0x84, 0x98, 0xa8, 0x21, 0xbf, 0xd7, 0xf9, 0x93, 0xc3, 0xb2, + 0xd7, 0x3d, 0x98, 0xd5, 0xda, 0x54, 0xfd, 0x34, 0x43, 0x4c, 0x36, + 0xae, 0x54, 0x0b, 0xb4, 0x98, 0x0b, 0x64, 0xbc, 0x00, 0x44, 0x3e, + 0xdb, 0xc8, 0x82, 0x4c, 0x45, 0xf1, 0x35, 0x5a, 0xdd, 0xb9, 0xb9, + 0xd7, 0x24, 0x79, 0xcd, 0x9d, 0xe2, 0x96, 0xcd, 0x6a, 0xbc, 0xab, + 0xaa, 0xd6, 0x54, 0x9a, 0x66, 0xa8, 0xa8, 0xad, 0x46, 0x2a, 0x30, + 0x19, 0xd5, 0xa5, 0x02, 0x34, 0xbf, 0x6d, 0x55, 0xd6, 0x73, 0x17, + 0x40, 0x3a, 0xad, 0x93, 0x85, 0x20, 0x24, 0x5c, 0xd5, 0x59, 0x6b, + 0x2a, 0xa2, 0x9f, 0x06, 0x80, 0xc9, 0x2a, 0x30, 0x2f, 0xf5, 0x62, + 0x2f, 0xe8, 0x4e, 0xf0, 0x62, 0x12, 0x70, 0x52, 0x99, 0x9c, 0xf6, + 0x55, 0x0b, 0x34, 0x6b, 0x49, 0x53, 0x75, 0x9f, 0xa1, 0xb0, 0x5e, + 0xc6, 0x05, 0x55, 0x6d, 0xd2, 0x51, 0x0f, 0xd0, 0xfc, 0xdc, 0x94, + 0x7a, 0x63, 0x64, 0x8d, 0x70, 0x25, 0x9d, 0x00, 0x81, 0x1a, 0x81, + 0x04, 0x05, 0x28, 0x35, 0x62, 0x72, 0x3b, 0x86, 0x17, 0xd8, 0x84, + 0x24, 0x70, 0xdd, 0xd2, 0xc8, 0xe1, 0xda, 0x35, 0x25, 0xf6, 0xa6, + 0x9f, 0x81, 0x10, 0xb3, 0x17, 0x42, 0xbb, 0xda, 0x60, 0x92, 0x00, + 0x62, 0x0a, 0xdb, 0xb0, 0x06, 0x82, 0x4f, 0x55, 0x11, 0xaa, 0xa8, + 0x36, 0x15, 0xc0, 0xc1, 0x27, 0x7d, 0x36, 0x9a, 0x77, 0x34, 0x22, + 0x86, 0xa6, 0xda, 0x18, 0xb6, 0xd6, 0x66, 0x16, 0xaa, 0x2a, 0xab, + 0x16, 0x80, 0x41, 0x41, 0x3d, 0xc9, 0x4c, 0xbc, 0x46, 0xa8, 0xf1, + 0x06, 0xec, 0x4b, 0xe6, 0x9c, 0xfd, 0x62, 0x6c, 0x4e, 0x80, 0x13, + 0x67, 0x0a, 0xd0, 0x64, 0xe2, 0x62, 0xb2, 0xae, 0x17, 0x73, 0x98, + 0x67, 0x92, 0x10, 0x62, 0x1e, 0xdb, 0x31, 0x8f, 0xed, 0xdd, 0xf2, + 0x63, 0x16, 0xa0, 0x67, 0x3d, 0x2e, 0x6a, 0x80, 0x9c, 0x9f, 0xcb, + 0x5a, 0x6b, 0xe5, 0x01, 0x29, 0x42, 0xac, 0xd9, 0xdf, 0x72, 0xaa, + 0x36, 0xc1, 0x90, 0x49, 0x53, 0x8d, 0x79, 0xf9, 0xc5, 0xc2, 0xb8, + 0xa4, 0x22, 0xe3, 0x0a, 0xca, 0x8c, 0x37, 0x00, 0x52, 0xdc, 0x76, + 0x7e, 0xc2, 0x63, 0xde, 0x2d, 0xcd, 0xbe, 0xcc, 0x6a, 0x50, 0x85, + 0x7e, 0xf7, 0xb5, 0x2e, 0xb7, 0x54, 0x6f, 0x22, 0xc4, 0x64, 0x00, + 0xa6, 0xaa, 0x9a, 0x98, 0x07, 0x98, 0xfc, 0xd2, 0x9c, 0xd2, 0xfd, + 0x00, 0x47, 0x35, 0xa6, 0x91, 0xe2, 0xff, 0xd9, 0x58, 0xd7, 0x94, + 0x2c, 0xf7, 0xa0, 0x1a, 0x69, 0x24, 0xa1, 0xff, 0x08, 0x64, 0x79, + 0x73, 0x7a, 0x37, 0xb7, 0x24, 0x4b, 0xa8, 0x9c, 0x2c, 0x8f, 0x20, + 0xd9, 0x1e, 0x59, 0x72, 0xd8, 0xb2, 0x1a, 0x38, 0x54, 0x4e, 0x17, + 0xe5, 0x73, 0x20, 0x97, 0x87, 0x7a, 0xba, 0x78, 0x88, 0xca, 0x16, + 0x53, 0xc7, 0x99, 0x9a, 0xf3, 0xd6, 0x5f, 0xc2, 0x56, 0xc4, 0x84, + 0x65, 0x7f, 0xb2, 0xc1, 0x7c, 0xa1, 0x00, 0x37, 0x37, 0xd0, 0x71, + 0x1b, 0xe4, 0xa0, 0x00, 0x1c, 0xbf, 0x3c, 0xdc, 0x07, 0x56, 0x7e, + 0x70, 0xe3, 0x12, 0xfb, 0xf2, 0x02, 0xa1, 0x4c, 0x8c, 0x4e, 0x06, + 0x6e, 0x62, 0x36, 0x80, 0xa6, 0xda, 0x8c, 0x82, 0x24, 0xd4, 0x8e, + 0x1b, 0x68, 0x64, 0x97, 0x99, 0x47, 0x9a, 0xdb, 0x7a, 0x37, 0x55, + 0xe7, 0x04, 0x38, 0xbb, 0x62, 0xf3, 0x53, 0x8f, 0xf0, 0xf9, 0x5f, + 0xdd, 0x01, 0x4f, 0x16, 0x38, 0x4d, 0xef, 0xa9, 0x34, 0xa7, 0x01, + 0x60, 0x65, 0x44, 0xd0, 0x0c, 0xec, 0x94, 0x96, 0x8a, 0xd0, 0x60, + 0x82, 0x81, 0x43, 0x33, 0x0b, 0xd0, 0x8a, 0x26, 0x34, 0xd3, 0x84, + 0x56, 0x28, 0x42, 0x2b, 0x1a, 0x60, 0x86, 0x09, 0x8d, 0x73, 0x68, + 0x99, 0x9c, 0xd0, 0xf3, 0x05, 0x68, 0x86, 0x01, 0xdd, 0xe0, 0xd0, + 0x0a, 0x05, 0x68, 0xb9, 0x02, 0xb4, 0xa2, 0x01, 0xcd, 0x30, 0xc1, + 0x4c, 0x0e, 0x56, 0x28, 0x40, 0x1f, 0x1a, 0x15, 0xe1, 0x4c, 0x0e, + 0xa1, 0x6c, 0x0e, 0x7a, 0xae, 0x80, 0x90, 0x61, 0x42, 0x2b, 0x16, + 0x11, 0x32, 0x38, 0x34, 0xce, 0x41, 0x99, 0x1c, 0x34, 0x02, 0xc0, + 0x05, 0xa8, 0x50, 0x84, 0x66, 0x7f, 0x50, 0x0c, 0x43, 0x30, 0x2e, + 0x66, 0x84, 0x0e, 0x00, 0x00, 0x21, 0x9d, 0x4c, 0xb2, 0x00, 0x4b, + 0x08, 0x40, 0xd7, 0xc1, 0x43, 0x1a, 0xb8, 0x00, 0x28, 0xa4, 0x83, + 0x47, 0xc2, 0x30, 0x09, 0x40, 0x24, 0x8c, 0x3c, 0x63, 0x10, 0xb1, + 0x08, 0xf2, 0x21, 0x1d, 0x66, 0x32, 0x8e, 0x42, 0x5b, 0x0a, 0xc5, + 0x64, 0x82, 0x8a, 0x1a, 0x81, 0x6b, 0x1a, 0xb8, 0xae, 0xc3, 0x8c, + 0x84, 0x60, 0xc6, 0x22, 0x30, 0x35, 0x0d, 0xa6, 0xae, 0xc1, 0x08, + 0x87, 0x60, 0xc6, 0xa2, 0x64, 0x84, 0x42, 0x30, 0x35, 0x02, 0x0f, + 0xe9, 0x30, 0x23, 0x61, 0x98, 0x1a, 0x2b, 0xe5, 0x09, 0x87, 0x61, + 0x42, 0x07, 0x07, 0x83, 0x09, 0x1d, 0x26, 0x58, 0xb9, 0xb0, 0x89, + 0x19, 0xa8, 0x2b, 0x15, 0x47, 0xb3, 0x0c, 0x4b, 0x6b, 0x0e, 0x2b, + 0x36, 0x85, 0x2f, 0xe4, 0xb8, 0x43, 0x21, 0x97, 0x55, 0x45, 0x70, + 0x80, 0x90, 0x90, 0x54, 0x5c, 0x6e, 0x80, 0xe2, 0x0e, 0xeb, 0xb9, + 0x07, 0xf0, 0x64, 0xf7, 0xc9, 0x2c, 0xff, 0x23, 0xd9, 0x62, 0xa3, + 0xf6, 0x89, 0xe0, 0x5f, 0x1b, 0x2d, 0xad, 0xda, 0xf4, 0x06, 0x83, + 0xcc, 0xad, 0x86, 0xce, 0x4b, 0xd5, 0x30, 0x05, 0x30, 0xd9, 0xe7, + 0xfd, 0x96, 0xc9, 0x63, 0x9f, 0x4c, 0x42, 0xb9, 0x31, 0x45, 0xc5, + 0xe7, 0xfe, 0xbf, 0x52, 0x05, 0x39, 0xd3, 0xbf, 0xd5, 0x67, 0x59, + 0xd2, 0x24, 0x26, 0x34, 0x70, 0x30, 0x70, 0x30, 0x18, 0xd0, 0x72, + 0x39, 0x84, 0x0a, 0x05, 0xe8, 0xd9, 0x02, 0x42, 0x85, 0x02, 0x42, + 0x27, 0x07, 0x45, 0x6c, 0x60, 0x14, 0xc9, 0xf1, 0x34, 0x62, 0x63, + 0x69, 0x11, 0xc9, 0xe5, 0x11, 0x1e, 0x4f, 0x23, 0x9c, 0xce, 0x22, + 0x92, 0xc9, 0x22, 0x7c, 0xfc, 0x94, 0x88, 0x0f, 0x8e, 0x21, 0x91, + 0xc9, 0x22, 0x9a, 0xc9, 0x41, 0x2f, 0x14, 0xa1, 0x1b, 0x86, 0xd0, + 0x72, 0x05, 0x68, 0x65, 0x80, 0x69, 0x06, 0x87, 0x66, 0x18, 0x20, + 0x93, 0x83, 0x38, 0xaf, 0x86, 0xcd, 0xec, 0x58, 0x73, 0x6b, 0xf1, + 0x89, 0x20, 0x34, 0x06, 0xa1, 0x6b, 0x65, 0xe0, 0x95, 0x01, 0x16, + 0x0b, 0xc3, 0xd4, 0x75, 0x98, 0x21, 0x9d, 0xcc, 0x58, 0x14, 0x46, + 0x3c, 0x86, 0x7c, 0x5b, 0x12, 0x93, 0xf3, 0xe7, 0x51, 0xb6, 0xb5, + 0x05, 0xb9, 0x78, 0x04, 0x85, 0xd6, 0x24, 0x0a, 0xb1, 0x18, 0x0a, + 0xa9, 0x38, 0xf2, 0x6d, 0x29, 0xca, 0xb5, 0x26, 0x31, 0x79, 0x4e, + 0x37, 0x26, 0x13, 0x71, 0xca, 0x47, 0x42, 0x30, 0x23, 0x11, 0x14, + 0xa3, 0x61, 0x14, 0xb5, 0x30, 0x8c, 0xd2, 0xab, 0xa3, 0xfc, 0x0a, + 0x61, 0xe0, 0x15, 0xb4, 0xcd, 0x2c, 0xf2, 0xc2, 0x52, 0xf4, 0xed, + 0xf0, 0x53, 0x71, 0x1b, 0xfd, 0x54, 0x96, 0x53, 0x7e, 0xd3, 0x05, + 0x44, 0x32, 0x40, 0xe3, 0x35, 0x6c, 0x23, 0x3c, 0x7e, 0x9d, 0x20, + 0x4d, 0x0e, 0x80, 0x23, 0xc8, 0x7f, 0xb6, 0x55, 0x13, 0xd0, 0x64, + 0xaa, 0xfd, 0xdd, 0x9a, 0x4f, 0xc8, 0x42, 0x8c, 0xf9, 0xa4, 0xb9, + 0x4d, 0x24, 0xb1, 0xad, 0x0c, 0xf8, 0x54, 0x80, 0xc6, 0x2c, 0x6a, + 0x8a, 0xcd, 0x98, 0xd3, 0x20, 0xa0, 0xcd, 0xd0, 0x5a, 0x84, 0x02, + 0x74, 0xe4, 0x11, 0xce, 0xe4, 0x10, 0xce, 0xe4, 0x10, 0xca, 0x64, + 0x11, 0x19, 0x4d, 0x8b, 0x68, 0x09, 0x4a, 0x88, 0xf4, 0x0f, 0x89, + 0xc4, 0xde, 0x23, 0x68, 0x1f, 0x1c, 0x46, 0xcb, 0x58, 0x5a, 0x44, + 0xc6, 0xd3, 0x88, 0x8e, 0xa6, 0x11, 0xc9, 0x64, 0x11, 0x99, 0xcc, + 0x22, 0x94, 0xcb, 0x8b, 0xd0, 0x64, 0x16, 0xa1, 0x7c, 0x11, 0x7a, + 0x36, 0x07, 0x1d, 0x67, 0xdf, 0x18, 0x00, 0x8d, 0xc7, 0xa5, 0x00, + 0x19, 0x26, 0xc8, 0x30, 0xdd, 0x80, 0x2d, 0x94, 0x00, 0x1b, 0xd2, + 0x61, 0x46, 0x23, 0x30, 0xe2, 0x51, 0x14, 0x63, 0x51, 0x14, 0xe3, + 0x11, 0x2a, 0x26, 0xe2, 0x28, 0x24, 0x63, 0xc8, 0xb7, 0xb5, 0x20, + 0x9f, 0x8a, 0x23, 0xd7, 0xd9, 0x46, 0x99, 0x85, 0x3d, 0x18, 0x59, + 0xbe, 0x90, 0xc6, 0x5a, 0x92, 0xc8, 0xb5, 0x24, 0x91, 0x6b, 0x4d, + 0x52, 0x2e, 0x19, 0x47, 0x3e, 0x11, 0x43, 0x21, 0x16, 0x41, 0x21, + 0x14, 0x45, 0x11, 0x11, 0x14, 0x2a, 0xf0, 0x43, 0x19, 0x39, 0x46, + 0xd9, 0x75, 0xe6, 0x16, 0x87, 0x58, 0xf8, 0xaa, 0x2d, 0x2f, 0xc0, + 0x08, 0x0f, 0x28, 0xb9, 0x81, 0xc8, 0x94, 0x48, 0xf3, 0x9a, 0xdc, + 0x8e, 0x61, 0xdd, 0x0f, 0xb3, 0xe4, 0x23, 0x17, 0x77, 0xdd, 0xab, + 0xe6, 0xdb, 0xd5, 0x15, 0xa5, 0xca, 0xa8, 0x4f, 0xde, 0x83, 0xa4, + 0xf8, 0xa9, 0x32, 0x7b, 0xf3, 0x09, 0x37, 0x77, 0x4d, 0x15, 0x54, + 0xf6, 0x49, 0xab, 0x63, 0x5b, 0x52, 0x4c, 0x9b, 0x5e, 0x37, 0x05, + 0x25, 0xcd, 0x72, 0x06, 0x5a, 0x19, 0x56, 0x26, 0x74, 0x18, 0xd0, + 0x50, 0x40, 0x28, 0x9d, 0x41, 0x38, 0x9d, 0x43, 0xe4, 0xe4, 0x80, + 0x48, 0xee, 0x3b, 0x82, 0xce, 0xfe, 0x21, 0x91, 0x1c, 0x1c, 0x45, + 0x62, 0x70, 0x04, 0xc9, 0x5d, 0x87, 0x44, 0xfb, 0x89, 0x53, 0x68, + 0x9b, 0xc8, 0x88, 0x48, 0x7a, 0x12, 0xe1, 0xc9, 0x2c, 0x22, 0xb9, + 0x02, 0x34, 0x21, 0x02, 0x30, 0x9d, 0xed, 0x16, 0xd2, 0x61, 0xc6, + 0xa2, 0x28, 0xb6, 0x24, 0x90, 0x4f, 0xc4, 0xa9, 0xd0, 0xd1, 0x82, + 0xc9, 0x95, 0x4b, 0x30, 0x34, 0xbf, 0x9b, 0x26, 0x7a, 0xda, 0x30, + 0xd9, 0xd5, 0x89, 0xc9, 0x45, 0xbd, 0x34, 0xbc, 0xfc, 0x1c, 0x1a, + 0x4b, 0xc6, 0x91, 0x4f, 0xc6, 0x91, 0x0b, 0x45, 0x51, 0x84, 0x0e, + 0x03, 0x7a, 0x19, 0x73, 0x1c, 0x02, 0x66, 0x19, 0x01, 0x46, 0xa5, + 0xe8, 0xbb, 0xc1, 0x4c, 0x46, 0x71, 0xc9, 0xac, 0xe3, 0x15, 0x67, + 0x7b, 0x26, 0xdc, 0xb8, 0xe4, 0x64, 0x4a, 0x9c, 0x8f, 0x9b, 0xf2, + 0x74, 0x8b, 0xb7, 0x79, 0xbe, 0x85, 0x64, 0x80, 0x26, 0xf3, 0x01, + 0x37, 0xb9, 0x00, 0xcc, 0x0e, 0x07, 0xcd, 0x07, 0x52, 0x9a, 0x0f, + 0xc0, 0x54, 0xf2, 0xaa, 0xc1, 0x6e, 0x4a, 0x65, 0x31, 0x10, 0x74, + 0x00, 0x7a, 0x25, 0x2c, 0xcd, 0x60, 0x40, 0x47, 0x01, 0xa1, 0x53, + 0x83, 0x48, 0xf5, 0x0f, 0x89, 0xd4, 0xa9, 0x51, 0x24, 0x0f, 0x1f, + 0x13, 0xad, 0xaf, 0xec, 0x41, 0xef, 0xf1, 0x01, 0xd1, 0xda, 0x3f, + 0x8c, 0xc4, 0xd0, 0x28, 0x12, 0x63, 0x13, 0x22, 0x3a, 0x96, 0x46, + 0x64, 0x7c, 0x02, 0x51, 0x11, 0x28, 0xa8, 0xc0, 0x14, 0x2d, 0x16, + 0x45, 0xb1, 0xb5, 0xac, 0xe8, 0xda, 0x5b, 0x91, 0xed, 0xe9, 0x40, + 0xba, 0xab, 0x83, 0x26, 0x57, 0x2f, 0x45, 0xff, 0x9a, 0xe5, 0x34, + 0xd4, 0xdd, 0x8e, 0x74, 0x57, 0x3b, 0xa5, 0x17, 0x74, 0x63, 0x3c, + 0x92, 0x44, 0x0e, 0x3a, 0x0c, 0x30, 0x98, 0x65, 0x55, 0x27, 0x60, + 0x80, 0xca, 0x08, 0x71, 0x72, 0x7a, 0xeb, 0x81, 0x96, 0xe9, 0x91, + 0x5f, 0x65, 0x9d, 0x69, 0x3b, 0x27, 0x53, 0xc2, 0x3d, 0xf5, 0xaa, + 0xa4, 0xa9, 0x82, 0x9a, 0x17, 0xd0, 0x54, 0x02, 0xfd, 0x5e, 0x71, + 0x2a, 0x3f, 0x20, 0x59, 0x7f, 0x9d, 0xe6, 0xdd, 0x96, 0xfd, 0x00, + 0xe7, 0x9c, 0x46, 0x60, 0x65, 0x68, 0x09, 0x68, 0xe5, 0x38, 0x16, + 0x81, 0x50, 0x40, 0xb8, 0x50, 0x72, 0xf3, 0xe2, 0x07, 0x8f, 0x89, + 0xb6, 0x3f, 0xec, 0x17, 0xbd, 0x47, 0x4e, 0xa2, 0xf5, 0xd8, 0x29, + 0xb4, 0x1e, 0xeb, 0x17, 0xa9, 0x13, 0x03, 0x48, 0x1d, 0x38, 0x26, + 0xda, 0x47, 0x26, 0x10, 0x17, 0x3c, 0x80, 0x55, 0x60, 0xa7, 0xc7, + 0xa2, 0x61, 0x14, 0x17, 0xf6, 0xd2, 0xd8, 0x92, 0x05, 0x18, 0x9b, + 0xdf, 0x85, 0xf1, 0x73, 0xba, 0x69, 0x7c, 0x51, 0x0f, 0xc6, 0x96, + 0x2d, 0xa4, 0xc1, 0xf5, 0x7d, 0x34, 0xd0, 0xd9, 0x86, 0xc9, 0x64, + 0x12, 0x59, 0xc4, 0x90, 0x07, 0x81, 0x97, 0x95, 0x9d, 0x80, 0x09, + 0x82, 0x31, 0x03, 0x74, 0x66, 0x1d, 0xf0, 0xaa, 0xe7, 0xd7, 0x4f, + 0xe1, 0x09, 0x97, 0xca, 0x0f, 0x3f, 0xb0, 0x89, 0x5a, 0x81, 0xe6, + 0x57, 0x3b, 0xe9, 0xa5, 0x9e, 0x34, 0x0f, 0x70, 0xe9, 0x0e, 0xeb, + 0x75, 0x1f, 0x80, 0x79, 0x83, 0x8e, 0x55, 0xdc, 0x44, 0x2a, 0xbb, + 0x88, 0x0c, 0x45, 0x84, 0x26, 0xc7, 0x10, 0x3f, 0x78, 0x4c, 0x74, + 0x1e, 0x3d, 0x85, 0xd6, 0x43, 0xc7, 0x45, 0xdb, 0xc1, 0xe3, 0xe8, + 0x78, 0xf9, 0x35, 0xd1, 0xbb, 0xf7, 0x30, 0xe6, 0x0d, 0x8e, 0x8a, + 0xf8, 0xc8, 0x18, 0xe2, 0x41, 0xd1, 0x09, 0xec, 0xf5, 0x66, 0xf1, + 0x28, 0x0a, 0xf3, 0xda, 0x91, 0x99, 0xdf, 0x45, 0x63, 0x17, 0xaf, + 0xc5, 0x89, 0xbe, 0xc5, 0x34, 0xb4, 0x74, 0x3e, 0x8d, 0x2e, 0xea, + 0xc5, 0xc8, 0xe2, 0xf9, 0x34, 0xda, 0xdb, 0x83, 0x31, 0x84, 0x51, + 0x80, 0x06, 0xa3, 0x1c, 0xb3, 0x03, 0xcc, 0xb2, 0xba, 0x13, 0x8e, + 0x10, 0x73, 0x52, 0x5a, 0xa6, 0x0b, 0xa0, 0x0c, 0x5b, 0x9a, 0xe9, + 0x92, 0xd7, 0x94, 0x50, 0x70, 0x6e, 0x8a, 0x0d, 0xf0, 0x6e, 0xb8, + 0x2b, 0xdc, 0x80, 0x26, 0x0b, 0x33, 0xe6, 0x01, 0x33, 0x27, 0x88, + 0x59, 0x27, 0xdd, 0x65, 0x99, 0xd9, 0xd2, 0xbc, 0xf6, 0x31, 0x7d, + 0x1c, 0x02, 0x83, 0x06, 0x42, 0xa8, 0xbc, 0x15, 0x87, 0x66, 0x8c, + 0x23, 0x3e, 0x38, 0x82, 0xd4, 0x91, 0x53, 0xa2, 0x75, 0xef, 0x61, + 0x74, 0xfe, 0xf6, 0x25, 0xb1, 0x64, 0xf7, 0x61, 0xd1, 0xb5, 0xe7, + 0xa0, 0xe8, 0x3c, 0x72, 0x12, 0xed, 0x3c, 0x50, 0x5a, 0x81, 0xcd, + 0x11, 0x6b, 0x6f, 0x41, 0x66, 0xcd, 0x32, 0x1a, 0x58, 0xb6, 0x10, + 0x23, 0x17, 0xaf, 0xa5, 0xa3, 0x17, 0xae, 0xa5, 0x13, 0x4b, 0xe6, + 0xd3, 0x68, 0x6f, 0x27, 0xc6, 0x93, 0x6d, 0x48, 0x23, 0x8c, 0x02, + 0x38, 0x80, 0x02, 0xc8, 0xe2, 0xc4, 0x72, 0x17, 0x20, 0xf1, 0x4a, + 0x35, 0x86, 0x33, 0xac, 0x0c, 0xc9, 0x34, 0xa7, 0x7d, 0x0b, 0x07, + 0xf7, 0xd7, 0x2b, 0xbe, 0x66, 0x85, 0x9a, 0x23, 0xd0, 0x54, 0x61, + 0xe6, 0xe4, 0xe6, 0xb9, 0xc1, 0x4b, 0xb7, 0xa5, 0x79, 0x2d, 0x3b, + 0x41, 0x6f, 0x5a, 0x6f, 0x4d, 0xc5, 0xba, 0x42, 0xe5, 0x38, 0x57, + 0x0e, 0xd1, 0xe1, 0x51, 0x24, 0x5f, 0xdd, 0x27, 0xba, 0xb7, 0xed, + 0x14, 0x8b, 0x5e, 0x7e, 0x55, 0xf4, 0x6e, 0xdb, 0x81, 0xc5, 0x27, + 0x06, 0x44, 0xcb, 0xd8, 0x04, 0xa2, 0xc1, 0x23, 0x1d, 0x58, 0x60, + 0x33, 0x2d, 0x1c, 0x86, 0xd1, 0xdb, 0x89, 0xf4, 0x9a, 0xe5, 0xd4, + 0x7f, 0xf9, 0x05, 0x74, 0xe4, 0xdc, 0x15, 0x74, 0xf2, 0xb2, 0x73, + 0xe9, 0xe8, 0xfc, 0x2e, 0x8c, 0x85, 0x12, 0xc8, 0x42, 0x47, 0x11, + 0x26, 0x84, 0x45, 0xc9, 0xb9, 0x29, 0x30, 0x27, 0x68, 0x19, 0x96, + 0x65, 0xb7, 0x5f, 0xfb, 0x76, 0x4e, 0x6e, 0xa9, 0xa9, 0xa0, 0xd6, + 0xe0, 0x05, 0x34, 0xa7, 0x56, 0xe8, 0x5e, 0x31, 0x32, 0x37, 0x10, + 0xe9, 0x36, 0xa0, 0x39, 0x4d, 0x1a, 0x50, 0xd1, 0x56, 0xce, 0x00, + 0x64, 0x60, 0x08, 0x97, 0x73, 0x15, 0x11, 0x1a, 0x1b, 0x42, 0xcb, + 0xc1, 0xe3, 0xa2, 0x73, 0xfb, 0x2e, 0xcc, 0xff, 0xb7, 0xad, 0x7c, + 0xc5, 0xab, 0x07, 0xd1, 0x7d, 0xe8, 0xb8, 0x68, 0x3b, 0x35, 0x84, + 0x54, 0xf0, 0xa8, 0x06, 0x16, 0x58, 0x6d, 0x96, 0x8c, 0xa3, 0x70, + 0x4e, 0x0f, 0x8d, 0xad, 0x58, 0x8c, 0xc1, 0xcb, 0xcf, 0xa7, 0x43, + 0x57, 0x5e, 0x42, 0x07, 0x57, 0x2c, 0xa4, 0xa1, 0x05, 0xdd, 0x18, + 0xa5, 0x24, 0x32, 0x30, 0x21, 0x50, 0x28, 0x03, 0x4e, 0x54, 0x41, + 0xc9, 0xb0, 0xcd, 0x3b, 0x2d, 0x1b, 0x2e, 0xeb, 0x9d, 0xe0, 0xe8, + 0x04, 0x35, 0xaf, 0xd8, 0x9a, 0x2f, 0xd0, 0x54, 0x5d, 0x4c, 0x2f, + 0x50, 0x59, 0xa7, 0x90, 0x6d, 0xbe, 0x3a, 0x1f, 0x41, 0x43, 0x08, + 0x84, 0x30, 0x04, 0x4c, 0x84, 0xb2, 0xe3, 0x25, 0xf5, 0xf5, 0xd4, + 0xf3, 0x62, 0xc5, 0x6f, 0x5e, 0x10, 0xcb, 0x5e, 0xd8, 0x29, 0x16, + 0x9e, 0x18, 0x40, 0x4b, 0xd0, 0xec, 0x21, 0xb0, 0xc0, 0x9a, 0x6b, + 0x2d, 0x49, 0xe4, 0x56, 0x2e, 0xa1, 0x81, 0xb7, 0x5d, 0x46, 0xfb, + 0xae, 0xb8, 0x88, 0x0e, 0x6d, 0xb8, 0x90, 0x0e, 0xce, 0xeb, 0xc4, + 0x38, 0xa2, 0xc8, 0x96, 0x01, 0x47, 0x30, 0x7d, 0xc1, 0x55, 0xf4, + 0x59, 0x76, 0x02, 0xa0, 0x5b, 0x25, 0x85, 0x6b, 0x4d, 0xa8, 0x0a, + 0xd0, 0xbc, 0x5c, 0x4c, 0x27, 0x05, 0x16, 0xb2, 0xfc, 0x7a, 0xcd, + 0x4f, 0x2f, 0x97, 0x54, 0x18, 0x21, 0x04, 0x42, 0x1e, 0xd1, 0x3d, + 0xfb, 0x45, 0xef, 0xd3, 0xcf, 0xa1, 0xef, 0xa7, 0xbf, 0xe6, 0x6b, + 0x77, 0xec, 0x45, 0xef, 0x81, 0xa3, 0xa2, 0x23, 0x00, 0x58, 0x60, + 0x5e, 0xa6, 0x31, 0xc0, 0xe4, 0xcd, 0x3d, 0x06, 0x51, 0xe9, 0x33, + 0xad, 0xb9, 0x6a, 0x5d, 0xed, 0x48, 0xaf, 0x5a, 0x4a, 0x83, 0x57, + 0xbe, 0x81, 0xf6, 0xff, 0xc9, 0x9b, 0xe9, 0xb5, 0x4b, 0xd6, 0xd1, + 0x91, 0x68, 0x07, 0xc6, 0x21, 0x60, 0x22, 0x0f, 0xc0, 0xa8, 0x54, + 0x12, 0x58, 0xc1, 0x55, 0xb0, 0xcc, 0x5b, 0x7f, 0xed, 0xf3, 0x76, + 0xb5, 0x67, 0x3a, 0xb8, 0xa1, 0x6e, 0x1f, 0xde, 0x57, 0x01, 0x4d, + 0x36, 0x66, 0xe6, 0x14, 0xbc, 0xd7, 0x5d, 0x60, 0x65, 0x9f, 0xc2, + 0x33, 0x96, 0x19, 0x74, 0x44, 0x40, 0xd0, 0x41, 0xc5, 0x71, 0xa4, + 0x5e, 0xd8, 0x21, 0x96, 0xfc, 0xe4, 0x19, 0xb1, 0xee, 0x77, 0x2f, + 0x8b, 0xa5, 0xcf, 0x6d, 0x17, 0x8b, 0xb3, 0x79, 0x84, 0x82, 0x62, + 0x1a, 0x98, 0xac, 0xad, 0x5c, 0x4c, 0xf8, 0xf2, 0xdd, 0x0c, 0xcc, + 0xda, 0x73, 0x3e, 0xa6, 0x03, 0x26, 0x79, 0x03, 0xf8, 0xe4, 0x46, + 0x8e, 0x83, 0xc7, 0x9d, 0x89, 0xc4, 0x08, 0x78, 0xe8, 0x6e, 0x0d, + 0xcb, 0x96, 0x95, 0x8b, 0xd7, 0x0c, 0x92, 0x01, 0xa1, 0x30, 0x70, + 0xf3, 0xbd, 0x1c, 0x3b, 0xf7, 0x06, 0x83, 0x96, 0x4f, 0xd9, 0xaa, + 0xa5, 0x34, 0xb0, 0xe1, 0x22, 0x3a, 0xf0, 0xd6, 0xcb, 0x68, 0xef, + 0x3b, 0xdf, 0x44, 0xaf, 0x75, 0xf6, 0x62, 0x08, 0x0c, 0x05, 0xe4, + 0x40, 0x96, 0xfa, 0xd4, 0x82, 0x05, 0x5a, 0xd6, 0xf9, 0xa9, 0x65, + 0xc3, 0xf2, 0x6b, 0x38, 0x40, 0xcd, 0x80, 0x7b, 0x33, 0x8f, 0xca, + 0x24, 0x0b, 0x34, 0xb7, 0x78, 0x99, 0x55, 0x99, 0xb9, 0x81, 0x2b, + 0xec, 0x38, 0x1f, 0x02, 0x43, 0x04, 0x84, 0x0c, 0x92, 0x5b, 0xb7, + 0x8b, 0x65, 0x4f, 0x3c, 0x2b, 0xd6, 0x3c, 0xfe, 0xa4, 0xb8, 0x60, + 0xe7, 0x1e, 0x31, 0x3f, 0x78, 0x44, 0x02, 0xab, 0x47, 0x3d, 0x3d, + 0x74, 0xb7, 0x86, 0x8f, 0x7d, 0x92, 0x80, 0x31, 0x87, 0x0c, 0x09, + 0xe0, 0x5f, 0xbf, 0x2b, 0x70, 0xfd, 0xdf, 0x9a, 0x8e, 0xdb, 0xbf, + 0xf7, 0x2a, 0xc2, 0x0f, 0xbf, 0xa9, 0x4d, 0xeb, 0x01, 0xab, 0xa5, + 0x80, 0x1f, 0x7d, 0x5f, 0xe0, 0xba, 0xbf, 0x31, 0x51, 0x28, 0x06, + 0xd7, 0xda, 0xc9, 0xba, 0x3b, 0x90, 0x7e, 0xfb, 0x9b, 0xd8, 0xab, + 0x7f, 0x7a, 0x15, 0xed, 0xbc, 0xea, 0x52, 0xda, 0x3d, 0xef, 0x1c, + 0x0c, 0xa0, 0x08, 0x8e, 0x3c, 0x04, 0x44, 0x05, 0x5e, 0x05, 0x0b, + 0xc8, 0x0a, 0x2e, 0x90, 0x2b, 0xba, 0xc4, 0xd9, 0x3c, 0xdd, 0x4f, + 0x19, 0xa0, 0x4d, 0xc5, 0xcc, 0x9c, 0x9a, 0x61, 0xd8, 0x5d, 0xcc, + 0xb0, 0xcb, 0x14, 0x01, 0xca, 0x11, 0xb1, 0x08, 0x18, 0x34, 0x68, + 0x47, 0x0f, 0x63, 0xfe, 0x4f, 0x9e, 0xe6, 0xe7, 0x7f, 0xe7, 0xc7, + 0xe2, 0x8d, 0x5b, 0x5f, 0x16, 0xcb, 0x82, 0x47, 0x21, 0xb0, 0x46, + 0x59, 0x6b, 0x12, 0xd8, 0xf6, 0x7d, 0x0d, 0xab, 0x56, 0x11, 0x90, + 0xab, 0x56, 0x69, 0x82, 0x01, 0x1b, 0x6e, 0x30, 0xb1, 0x75, 0xfb, + 0x4c, 0x95, 0x95, 0x88, 0x03, 0x2f, 0x7e, 0x5f, 0xc3, 0xea, 0x35, + 0x0e, 0xdb, 0x45, 0x80, 0x63, 0x47, 0x81, 0xf3, 0xde, 0x67, 0x60, + 0x64, 0x3c, 0xb8, 0xc6, 0x32, 0xb6, 0xa0, 0x1b, 0xa3, 0xd7, 0x5c, + 0xcd, 0xb6, 0x7f, 0xe8, 0x3d, 0xb4, 0xed, 0xd2, 0x73, 0xe9, 0x00, + 0x62, 0x48, 0x23, 0x03, 0x02, 0x9f, 0x01, 0xb3, 0x7c, 0x19, 0x5e, + 0x79, 0x17, 0xb8, 0x39, 0xa9, 0x35, 0x57, 0xa8, 0x79, 0x01, 0xcd, + 0xad, 0x46, 0x53, 0x77, 0x71, 0x33, 0xad, 0x4a, 0x2c, 0x62, 0x99, + 0xc2, 0x20, 0x84, 0x11, 0x05, 0x03, 0x10, 0xfe, 0xfd, 0x0e, 0xb1, + 0xfc, 0x5f, 0x1e, 0x11, 0x57, 0x3d, 0xfe, 0xff, 0xf8, 0x1b, 0xc6, + 0x26, 0x82, 0x06, 0xac, 0x81, 0x35, 0xc7, 0x36, 0x5c, 0x48, 0xf8, + 0xcd, 0xf7, 0x34, 0x90, 0x93, 0xd2, 0x8a, 0x03, 0xcf, 0x6f, 0x13, + 0xd8, 0xf0, 0x21, 0x13, 0x45, 0x63, 0x3a, 0xf9, 0xb6, 0x0f, 0x32, + 0x7c, 0xe9, 0x7e, 0x06, 0x8c, 0x57, 0x43, 0x10, 0x61, 0xe0, 0xbd, + 0x1f, 0x37, 0xf1, 0xa3, 0xa7, 0x03, 0x57, 0xb3, 0x16, 0x7b, 0xf3, + 0x1b, 0x68, 0xf7, 0x2d, 0x7f, 0xc1, 0x7e, 0xf5, 0x67, 0x6f, 0xa5, + 0x97, 0xc2, 0x29, 0x8c, 0x21, 0x0b, 0xc0, 0x84, 0x61, 0x01, 0x59, + 0xde, 0x32, 0x5f, 0x70, 0x50, 0x6a, 0x45, 0x97, 0x78, 0x1a, 0x77, + 0x53, 0x68, 0xf6, 0xf6, 0x67, 0x4e, 0xdf, 0x60, 0x3a, 0xc5, 0xcc, + 0x42, 0x0e, 0xea, 0x2c, 0x5a, 0x01, 0x5a, 0x04, 0x0c, 0x84, 0xf0, + 0x73, 0x2f, 0x8a, 0xb5, 0xff, 0xf8, 0x75, 0xfe, 0x27, 0x3f, 0xff, + 0xb5, 0x38, 0x2f, 0x5f, 0x9c, 0x5b, 0x71, 0xb1, 0x68, 0x34, 0x0a, + 0xc6, 0x18, 0x4c, 0xd3, 0x44, 0x3e, 0x9f, 0x97, 0xce, 0x2f, 0x84, + 0x40, 0x36, 0x9b, 0x6d, 0xca, 0x39, 0xc5, 0xe3, 0x71, 0x44, 0xa3, + 0x51, 0x14, 0x8b, 0x45, 0x18, 0x86, 0x01, 0xd3, 0x2c, 0xb9, 0x60, + 0x9a, 0x56, 0xea, 0xce, 0x4c, 0xd7, 0x75, 0x70, 0xce, 0x31, 0x39, + 0x39, 0xd9, 0x90, 0xe3, 0xa5, 0x52, 0x29, 0x68, 0x9a, 0x36, 0xe3, + 0x58, 0xa6, 0x69, 0x82, 0x73, 0x0e, 0x4d, 0xd3, 0xc0, 0x18, 0xab, + 0x1c, 0x57, 0xd7, 0x75, 0x64, 0x32, 0x19, 0xa9, 0x6b, 0xe5, 0x65, + 0x5f, 0xbc, 0x83, 0xe1, 0xce, 0x5b, 0x19, 0x30, 0xe1, 0xb0, 0x32, + 0x09, 0xdc, 0x74, 0x3b, 0xc7, 0xb7, 0x7e, 0x54, 0xa2, 0xdd, 0xc2, + 0x1e, 0xe0, 0xc5, 0xc7, 0x75, 0x74, 0x77, 0x39, 0xc4, 0xce, 0x5a, + 0x80, 0x6f, 0x7c, 0x8b, 0xe3, 0xa3, 0xf7, 0xf0, 0x80, 0x4c, 0x75, + 0xda, 0xb9, 0x2b, 0xe9, 0xd8, 0x2d, 0x37, 0xb2, 0x7f, 0xfb, 0x8b, + 0xf7, 0xd0, 0x6f, 0x13, 0xed, 0x18, 0xc6, 0x24, 0x50, 0x6e, 0x08, + 0x92, 0x47, 0x49, 0x17, 0xdb, 0x95, 0x9b, 0x75, 0x32, 0x3d, 0x94, + 0x9a, 0x2b, 0xd0, 0xbc, 0x2a, 0x02, 0xa6, 0x26, 0x7b, 0xf0, 0x3f, + 0x5c, 0x51, 0x63, 0xa5, 0xdf, 0x28, 0x08, 0x11, 0x24, 0xc1, 0xf7, + 0xef, 0xc1, 0xd2, 0xbb, 0x37, 0xf3, 0x0f, 0x3c, 0xfa, 0x33, 0xfe, + 0x9f, 0xe6, 0x6a, 0x0d, 0xe5, 0x6d, 0xb7, 0xdd, 0x86, 0xdb, 0x6f, + 0xbf, 0x1d, 0xe9, 0x74, 0x1a, 0xd7, 0x5f, 0x7f, 0x3d, 0x76, 0xec, + 0xd8, 0xe1, 0x99, 0xff, 0xa6, 0x9b, 0x6e, 0xc2, 0x17, 0xbe, 0xf0, + 0x05, 0xfc, 0xe0, 0x07, 0x3f, 0xc0, 0x1d, 0x77, 0xdc, 0xd1, 0x94, + 0x73, 0xfa, 0xf8, 0xc7, 0x3f, 0x8e, 0x8d, 0x1b, 0x37, 0xa2, 0x50, + 0x28, 0xc0, 0x34, 0x4d, 0x68, 0x9a, 0x56, 0x01, 0x8b, 0x69, 0x9a, + 0x60, 0x8c, 0x61, 0xcb, 0x96, 0x2d, 0xb8, 0xf9, 0xe6, 0x9b, 0x1b, + 0x72, 0xbc, 0x07, 0x1f, 0x7c, 0x10, 0xd7, 0x5e, 0x7b, 0x2d, 0x84, + 0x10, 0xe0, 0x9c, 0x83, 0x73, 0x8e, 0x6c, 0x36, 0x0b, 0xd3, 0x34, + 0xa1, 0xeb, 0x3a, 0xe2, 0xf1, 0x92, 0x58, 0x67, 0x8c, 0x81, 0x88, + 0x70, 0xfd, 0xf5, 0xd7, 0xe3, 0xa9, 0xa7, 0x9e, 0xaa, 0xeb, 0x98, + 0xe1, 0x10, 0xf0, 0xfc, 0xf7, 0x35, 0x9c, 0x7f, 0x01, 0x01, 0x19, + 0xfb, 0x4a, 0xe0, 0xe4, 0x49, 0xe0, 0x82, 0x6b, 0x0c, 0x9c, 0x1a, + 0x06, 0x1e, 0xbc, 0x4b, 0xc3, 0x27, 0x3e, 0x4a, 0xd5, 0xea, 0x2c, + 0x0a, 0xec, 0xde, 0x0d, 0xbc, 0xf1, 0x06, 0x03, 0x63, 0x13, 0x01, + 0x90, 0x1a, 0x65, 0x6b, 0x97, 0xd3, 0xd1, 0xfb, 0xff, 0x9a, 0x3d, + 0xf6, 0xbe, 0x77, 0xd0, 0xef, 0xc0, 0x51, 0x44, 0x1e, 0x26, 0x08, + 0x39, 0x8b, 0x52, 0xcb, 0x7b, 0xb8, 0x9f, 0xf6, 0x2f, 0x0b, 0x2a, + 0x50, 0x93, 0xed, 0xd8, 0x4f, 0xa6, 0x82, 0x60, 0x5a, 0xb9, 0xe9, + 0x60, 0x88, 0xc3, 0xfc, 0xf2, 0x37, 0xf8, 0xbb, 0x2f, 0xbb, 0xce, + 0xfc, 0xfb, 0x47, 0x7e, 0xca, 0x37, 0xcc, 0xe5, 0xe6, 0x16, 0xd1, + 0x68, 0x14, 0x4b, 0x96, 0x2c, 0xc1, 0xfa, 0xf5, 0xeb, 0xf1, 0xc3, + 0x1f, 0xfe, 0x10, 0x8b, 0x16, 0x2d, 0xf2, 0xcc, 0x6f, 0x9a, 0x26, + 0x96, 0x2c, 0x59, 0x82, 0x48, 0x24, 0xd2, 0xb4, 0x73, 0xca, 0xe5, + 0x72, 0xe8, 0xe9, 0xe9, 0xc1, 0xa2, 0x45, 0x8b, 0xb0, 0x74, 0xe9, + 0x52, 0x68, 0x9a, 0x86, 0xf1, 0xf1, 0x71, 0xe4, 0xf3, 0x79, 0xc4, + 0xe3, 0x71, 0xf4, 0xf6, 0xf6, 0xa2, 0xb3, 0xb3, 0xb3, 0x61, 0xc7, + 0x6b, 0x6b, 0x6b, 0x43, 0x2a, 0x95, 0x42, 0x3e, 0x9f, 0xc7, 0xc8, + 0xc8, 0x08, 0x88, 0x08, 0x7d, 0x7d, 0x7d, 0x58, 0xb5, 0x6a, 0x15, + 0x96, 0x2f, 0x5f, 0x8e, 0x89, 0x89, 0x09, 0x8c, 0x8f, 0x8f, 0xc3, + 0x34, 0x4d, 0xcc, 0x9b, 0x37, 0x0f, 0xd1, 0x68, 0xfd, 0x1f, 0x77, + 0x14, 0x8a, 0xc0, 0x27, 0x36, 0x72, 0x14, 0x26, 0xcb, 0x4f, 0xe7, + 0x8c, 0x95, 0x40, 0xef, 0x32, 0xe0, 0x96, 0x1b, 0x18, 0x56, 0x2d, + 0x25, 0xdc, 0xf4, 0x7e, 0x02, 0x26, 0x1d, 0x5c, 0x4d, 0x0e, 0xdc, + 0x72, 0xbf, 0x19, 0xc0, 0xac, 0xc1, 0xf6, 0xea, 0x7e, 0xb1, 0xf0, + 0x9a, 0x4f, 0x99, 0x77, 0x7c, 0xe0, 0x53, 0xe6, 0xed, 0x03, 0xc3, + 0x68, 0x47, 0x12, 0x26, 0xaa, 0x1b, 0xd7, 0xdb, 0xbf, 0xdf, 0x76, + 0xea, 0x93, 0xd0, 0xca, 0x28, 0xcf, 0x9e, 0x4a, 0x65, 0xfa, 0xc2, + 0xaf, 0xfe, 0xd4, 0x29, 0x04, 0xe4, 0x0b, 0x08, 0xff, 0xe5, 0xa7, + 0xf9, 0xa7, 0x6e, 0xb9, 0x8f, 0xff, 0xd5, 0xe0, 0xa8, 0x68, 0x9d, + 0xeb, 0x37, 0xcf, 0xea, 0x36, 0xae, 0x58, 0xb1, 0x02, 0x5b, 0xb6, + 0x6c, 0x41, 0x5b, 0x5b, 0x9b, 0x6b, 0xfe, 0xb1, 0xb1, 0xb1, 0x19, + 0xbf, 0xcd, 0xb0, 0xe1, 0xe1, 0xe1, 0x2a, 0xc5, 0xb6, 0x76, 0xed, + 0x5a, 0xf4, 0xf5, 0xf5, 0x61, 0xf9, 0xf2, 0xe5, 0x58, 0xb1, 0x62, + 0x05, 0xee, 0xbc, 0xf3, 0xce, 0x86, 0x1d, 0xef, 0xb3, 0x9f, 0xfd, + 0x2c, 0x56, 0xac, 0x58, 0x81, 0xbe, 0xbe, 0x3e, 0xac, 0x5b, 0xb7, + 0x0e, 0x9f, 0xf9, 0xcc, 0x67, 0x66, 0xc0, 0xf5, 0x1d, 0xef, 0x78, + 0x07, 0x56, 0xaf, 0x5e, 0x8d, 0xbe, 0xbe, 0x3e, 0xac, 0x5c, 0xb9, + 0x12, 0x5b, 0xb7, 0x6e, 0x6d, 0xc8, 0x71, 0xb7, 0xfe, 0x5e, 0xe0, + 0x8b, 0x5f, 0xe3, 0x40, 0xd2, 0x61, 0x65, 0x1a, 0xb8, 0xf5, 0x46, + 0x86, 0x1f, 0xfc, 0x93, 0x86, 0x48, 0xb4, 0xfc, 0xbe, 0xb7, 0xb9, + 0xa5, 0xff, 0xfd, 0xeb, 0x1c, 0x4f, 0x6e, 0x0d, 0xe2, 0x66, 0xcd, + 0xb2, 0xc7, 0x7e, 0x21, 0x36, 0xbc, 0xe5, 0x83, 0xc6, 0xbd, 0xcf, + 0x3d, 0x2f, 0xd6, 0x21, 0x85, 0x02, 0xaa, 0x3f, 0x81, 0x74, 0xeb, + 0x65, 0xda, 0xb1, 0x8f, 0x46, 0xd5, 0xae, 0x97, 0xbd, 0x7b, 0xd9, + 0xd0, 0x40, 0x06, 0x87, 0xf6, 0xc1, 0x3b, 0xcd, 0x3b, 0xbe, 0xb9, + 0x85, 0x5f, 0x1d, 0xdc, 0xae, 0x92, 0xd9, 0x63, 0x41, 0x17, 0x5f, + 0x7c, 0x31, 0x1e, 0x7b, 0xec, 0x31, 0xc4, 0x62, 0x31, 0x69, 0x10, + 0x36, 0xda, 0xd2, 0xe9, 0xf4, 0x8c, 0xe5, 0x4c, 0x26, 0x53, 0x51, + 0x87, 0xa3, 0xa3, 0xa3, 0xd8, 0xbf, 0x7f, 0x3f, 0x8e, 0x1c, 0x39, + 0xd2, 0xb0, 0xe3, 0x1d, 0x3a, 0x74, 0x08, 0xc7, 0x8e, 0x1d, 0x43, + 0xb1, 0x58, 0x0a, 0x50, 0x15, 0x0a, 0x85, 0xca, 0x3a, 0xce, 0x79, + 0x25, 0xae, 0x96, 0xcd, 0x66, 0xb1, 0x6f, 0xdf, 0x3e, 0x8c, 0x8c, + 0x8c, 0x34, 0xec, 0xd8, 0xf7, 0x7f, 0x9d, 0x63, 0xdb, 0xb3, 0x40, + 0x55, 0x15, 0x94, 0x09, 0xb4, 0xb5, 0x01, 0xeb, 0xd7, 0x96, 0x1d, + 0x1c, 0x9b, 0xab, 0xb9, 0x6b, 0x07, 0xb0, 0xf1, 0x2b, 0x41, 0xdc, + 0xac, 0xe9, 0x6a, 0xed, 0x00, 0x16, 0xbf, 0xfb, 0x13, 0xe6, 0x5d, + 0x5b, 0xb7, 0x8a, 0xf3, 0x10, 0x47, 0x11, 0xee, 0x1d, 0xb4, 0x7a, + 0x8d, 0x9a, 0xe6, 0x09, 0x34, 0x99, 0xb1, 0x01, 0xaa, 0xfb, 0x19, + 0x8b, 0xc0, 0xf8, 0xbb, 0x2f, 0xf2, 0x0f, 0xff, 0x9f, 0x5f, 0x8a, + 0x2b, 0x83, 0xdb, 0xe4, 0x6d, 0x57, 0x5f, 0x7d, 0x35, 0xbe, 0xf1, + 0x8d, 0x6f, 0x40, 0xd7, 0xab, 0x7b, 0x41, 0x9f, 0x82, 0x4b, 0x2e, + 0x97, 0x6b, 0xaa, 0xcb, 0x69, 0x77, 0x73, 0x67, 0xd3, 0x84, 0xad, + 0xa9, 0xfd, 0x54, 0xa5, 0x40, 0x53, 0x14, 0x72, 0x0e, 0xb8, 0x75, + 0x93, 0x89, 0x42, 0xd6, 0xc1, 0xf5, 0x34, 0xcb, 0x51, 0x1a, 0xdb, + 0xb8, 0xf3, 0x42, 0x00, 0x7f, 0xfd, 0x0f, 0x26, 0xc6, 0xd3, 0xc1, + 0xb3, 0x3a, 0x1b, 0x36, 0x38, 0x8a, 0xf6, 0x1b, 0xef, 0xe4, 0x7f, + 0x3b, 0xd4, 0x8f, 0x0e, 0x84, 0x2a, 0xdd, 0x74, 0xfb, 0x8d, 0xcc, + 0x56, 0xc5, 0x2a, 0xbf, 0xa7, 0xc8, 0x0b, 0x6c, 0x33, 0xd3, 0xc3, + 0x30, 0x5e, 0xdb, 0x29, 0xfa, 0x1e, 0xf8, 0x0e, 0xbf, 0x2e, 0xb8, + 0x3d, 0xb6, 0x8b, 0x48, 0xa5, 0xcb, 0xb5, 0x69, 0xd3, 0x26, 0xf4, + 0xf7, 0xf7, 0x57, 0xd2, 0x6f, 0xb8, 0xe1, 0x06, 0x6c, 0xde, 0xbc, + 0xb9, 0x3a, 0xf6, 0x53, 0x56, 0x2f, 0xcd, 0x04, 0xda, 0xd4, 0x39, + 0xcd, 0x86, 0x1a, 0x3c, 0x13, 0x6c, 0xdb, 0x0e, 0x81, 0x7f, 0xfa, + 0xba, 0x8b, 0xeb, 0x89, 0x6a, 0x57, 0x73, 0xf3, 0xd7, 0x39, 0x7e, + 0xf1, 0x6c, 0xe0, 0x6a, 0xce, 0xa6, 0x1d, 0x3c, 0x2e, 0xe6, 0xdf, + 0xf3, 0x3f, 0xf8, 0x07, 0x11, 0x82, 0x01, 0xe7, 0x91, 0xd1, 0x7c, + 0xcd, 0x2f, 0x86, 0x26, 0xef, 0x7e, 0x86, 0x60, 0x3c, 0xfc, 0x53, + 0xf1, 0x16, 0xce, 0xab, 0x87, 0x31, 0x0b, 0x80, 0x56, 0xba, 0x94, + 0x5b, 0xb6, 0x6c, 0xc1, 0xb5, 0xd7, 0x5e, 0x3b, 0xc3, 0xdd, 0xbb, + 0xf9, 0xe6, 0x9b, 0xb1, 0x69, 0xd3, 0x26, 0xc7, 0xfc, 0xf5, 0x36, + 0x5b, 0x50, 0xb1, 0xbe, 0xbe, 0x3e, 0xac, 0x59, 0xb3, 0x06, 0xe7, + 0x9f, 0x7f, 0x3e, 0x2e, 0xbd, 0xf4, 0x52, 0xbc, 0xf9, 0xcd, 0x6f, + 0xc6, 0xea, 0xd5, 0xab, 0xcf, 0xaa, 0xfb, 0x70, 0xef, 0x43, 0x1c, + 0xcf, 0x3d, 0x2b, 0xe0, 0xd9, 0x99, 0x54, 0x04, 0x78, 0xed, 0xf7, + 0x02, 0xf7, 0x3c, 0x18, 0xb8, 0x9a, 0xa7, 0xc3, 0x1e, 0x7f, 0x82, + 0xbf, 0x65, 0x62, 0x10, 0x1d, 0xd0, 0x2b, 0x83, 0xa3, 0x78, 0x29, + 0xb2, 0x2a, 0x5e, 0x79, 0x01, 0xcd, 0x3a, 0xac, 0x94, 0xd7, 0x70, + 0x75, 0xe5, 0x40, 0x08, 0x68, 0xcf, 0x21, 0xb1, 0x38, 0xb8, 0x25, + 0xd5, 0x16, 0x0e, 0x87, 0x01, 0x00, 0x2d, 0x2d, 0x2d, 0x78, 0xf6, + 0xd9, 0x67, 0x71, 0xdd, 0x75, 0xd7, 0xc1, 0x30, 0xa6, 0x5b, 0x74, + 0x7e, 0xee, 0x73, 0x9f, 0xc3, 0x2d, 0xb7, 0xdc, 0x52, 0xb5, 0x9d, + 0x35, 0x4f, 0xb3, 0xed, 0xd1, 0x47, 0x1f, 0xc5, 0xab, 0xaf, 0xbe, + 0x8a, 0xed, 0xdb, 0xb7, 0x63, 0xdb, 0xb6, 0x6d, 0x78, 0xe6, 0x99, + 0x67, 0xf0, 0x91, 0x8f, 0x7c, 0xe4, 0xac, 0xba, 0x0f, 0x99, 0x1c, + 0xf0, 0xa9, 0x4d, 0x1c, 0xbc, 0xe8, 0x52, 0x2c, 0x18, 0x50, 0x2c, + 0x02, 0x7f, 0xf9, 0x79, 0x8e, 0xb1, 0xc0, 0xd5, 0x3c, 0x2d, 0x96, + 0xce, 0x22, 0x39, 0x99, 0x45, 0x0c, 0xb0, 0x0c, 0x74, 0x5d, 0xcd, + 0x25, 0x57, 0xb1, 0xe5, 0x37, 0x8c, 0x9d, 0xd3, 0x20, 0xa0, 0xce, + 0xa3, 0x1e, 0x33, 0x88, 0x05, 0xdd, 0x34, 0xd0, 0xec, 0xb1, 0x16, + 0x5f, 0x8f, 0x66, 0x8f, 0x93, 0xfd, 0xfc, 0xe7, 0x3f, 0xc7, 0x87, + 0x3f, 0xfc, 0x61, 0x3c, 0xf2, 0xc8, 0x23, 0x95, 0xb4, 0xcd, 0x9b, + 0x37, 0x63, 0x62, 0x62, 0x02, 0xdf, 0xfe, 0xf6, 0xb7, 0xab, 0x5c, + 0xcf, 0x59, 0x79, 0x33, 0x3e, 0xfe, 0x38, 0x8e, 0x1e, 0x3d, 0x8a, + 0x44, 0x22, 0x81, 0x78, 0x3c, 0x8e, 0x54, 0x2a, 0x85, 0xdd, 0xbb, + 0x77, 0x9f, 0x75, 0xf7, 0x62, 0xc3, 0x45, 0x04, 0x0a, 0xa1, 0xfa, + 0xd3, 0xa6, 0xf2, 0x93, 0xad, 0x85, 0x81, 0xab, 0xaf, 0xa0, 0xaa, + 0xcf, 0xa2, 0x02, 0x9b, 0x1d, 0x8b, 0x86, 0x91, 0x8b, 0x85, 0x91, + 0xaf, 0xd5, 0x73, 0x54, 0x1d, 0x68, 0xd8, 0x09, 0x6c, 0xa5, 0xc9, + 0x84, 0x76, 0xfd, 0xdb, 0xe9, 0xd7, 0x5f, 0xfa, 0x2e, 0x3e, 0x10, + 0xdc, 0x16, 0x9b, 0x17, 0xe3, 0xd0, 0x9e, 0xec, 0xd1, 0x47, 0x1f, + 0x45, 0x57, 0x57, 0x17, 0xbe, 0xf4, 0xa5, 0x2f, 0x95, 0xde, 0x07, + 0x8c, 0xe1, 0xc1, 0x07, 0x1f, 0xc4, 0x89, 0x13, 0x27, 0x66, 0xc4, + 0xd9, 0x66, 0xcb, 0x36, 0x6d, 0xda, 0x84, 0x97, 0x5f, 0x7e, 0xf9, + 0xac, 0xbe, 0x0f, 0x97, 0xac, 0x27, 0xdc, 0xf7, 0x69, 0x06, 0x2a, + 0xba, 0x3f, 0xdd, 0xcc, 0x00, 0xee, 0xbe, 0x95, 0xe1, 0x89, 0x67, + 0x05, 0xfe, 0xfd, 0x95, 0x00, 0x6a, 0xb3, 0x6d, 0x57, 0x5f, 0x41, + 0xcf, 0xb7, 0x76, 0x61, 0x18, 0xf9, 0xca, 0xd8, 0x9d, 0x5e, 0x83, + 0xa4, 0xc0, 0x96, 0xee, 0xdb, 0x6c, 0xc3, 0x6d, 0xc3, 0x6a, 0xb0, + 0xe5, 0x10, 0x7a, 0xe3, 0x25, 0xf4, 0x87, 0xeb, 0xfe, 0x33, 0x3d, + 0x1d, 0xdc, 0x16, 0xdb, 0x5b, 0xc7, 0xa5, 0x91, 0xe8, 0xe6, 0xcd, + 0x9b, 0x71, 0xff, 0xfd, 0xf7, 0x57, 0x96, 0x63, 0xb1, 0x18, 0x1e, + 0x7e, 0xf8, 0x61, 0xbc, 0xfb, 0xdd, 0xef, 0x06, 0x30, 0xbb, 0x31, + 0xb4, 0x64, 0x32, 0x39, 0xab, 0xd7, 0x24, 0x14, 0x9a, 0xdd, 0xaf, + 0xdf, 0x22, 0x61, 0xe0, 0x5f, 0x3e, 0xc7, 0x10, 0x4f, 0xa1, 0xba, + 0xbd, 0x99, 0xd5, 0xcc, 0x92, 0x4a, 0x7b, 0xe8, 0x1e, 0x86, 0x54, + 0x22, 0x78, 0x76, 0x67, 0xd3, 0xda, 0x52, 0x98, 0xb8, 0xf7, 0x16, + 0xed, 0xe1, 0xca, 0x10, 0xcb, 0x70, 0x9c, 0x9c, 0xd8, 0x64, 0x8d, + 0x1a, 0xf8, 0x82, 0xac, 0x8a, 0x82, 0x96, 0xf9, 0xe9, 0x6f, 0xa9, + 0x04, 0x04, 0x09, 0xe0, 0xab, 0xf7, 0x69, 0xff, 0x7c, 0xe9, 0x7a, + 0xda, 0x15, 0xdc, 0x1e, 0x7f, 0xa0, 0x01, 0xc0, 0x5d, 0x77, 0xdd, + 0x85, 0xaf, 0x7e, 0xf5, 0xab, 0x95, 0xe5, 0xae, 0xae, 0x2e, 0xdc, + 0x77, 0xdf, 0x7d, 0x00, 0x4a, 0xed, 0xb3, 0x9a, 0x65, 0xe2, 0x34, + 0xf7, 0x50, 0x68, 0x6d, 0xa6, 0xa1, 0x69, 0x9a, 0x63, 0xf3, 0x95, + 0x46, 0xda, 0xad, 0x37, 0x30, 0x5c, 0xbe, 0xc1, 0xe1, 0x6b, 0x00, + 0xa7, 0x88, 0x70, 0x16, 0x38, 0xff, 0x12, 0xc2, 0xe7, 0x3e, 0xc2, + 0x82, 0x87, 0x77, 0xb6, 0x5e, 0x70, 0x3a, 0x8a, 0x0f, 0xdd, 0xa3, + 0x6d, 0x5e, 0xb9, 0x16, 0x07, 0x90, 0x2f, 0x0f, 0x73, 0xe4, 0xdc, + 0xdd, 0xb6, 0x80, 0x7b, 0x5c, 0x4b, 0xea, 0xd3, 0x27, 0xe1, 0xf0, + 0xeb, 0xd4, 0x75, 0x87, 0x89, 0x22, 0xa8, 0xb5, 0x0d, 0x13, 0x3f, + 0x79, 0x48, 0xbb, 0x77, 0xc3, 0x85, 0xb4, 0x33, 0xb8, 0x4d, 0xd3, + 0xca, 0xcb, 0xcb, 0x3e, 0xf9, 0xc9, 0x4f, 0xe2, 0x89, 0x27, 0x9e, + 0x98, 0xd5, 0x73, 0x9a, 0xfa, 0x08, 0xfd, 0x4c, 0x30, 0x22, 0xaa, + 0x6a, 0x46, 0xd2, 0x48, 0xbb, 0x68, 0x2d, 0xe1, 0xde, 0xdb, 0x59, + 0xf5, 0xf7, 0x9c, 0x5e, 0xf5, 0x66, 0x69, 0xe0, 0x6f, 0x3e, 0xc6, + 0x70, 0xe9, 0xfa, 0xa0, 0x83, 0xe4, 0x66, 0x5b, 0x4b, 0x02, 0x93, + 0xdf, 0x7f, 0x40, 0xfb, 0xe2, 0x75, 0xd7, 0xd0, 0xd3, 0x48, 0x23, + 0x0a, 0xff, 0x8e, 0x1c, 0xe1, 0xe2, 0x2d, 0x92, 0x4c, 0x2d, 0xa7, + 0x7d, 0x08, 0x29, 0xfb, 0x60, 0xa0, 0x33, 0x07, 0x36, 0xc8, 0x82, + 0x75, 0x77, 0x61, 0xf8, 0x97, 0xdf, 0xd2, 0x36, 0x7e, 0xfa, 0x26, + 0xf6, 0xa3, 0x90, 0x0e, 0x63, 0xae, 0xdf, 0xb0, 0x44, 0x22, 0xe1, + 0xe9, 0x66, 0x19, 0x86, 0x81, 0x1b, 0x6f, 0xbc, 0x11, 0x2f, 0xbc, + 0xf0, 0xc2, 0xec, 0x3d, 0x44, 0x2d, 0x2d, 0x33, 0x96, 0xed, 0x6d, + 0xde, 0x18, 0x63, 0x0d, 0xf9, 0x9e, 0xd2, 0xd5, 0x05, 0xb4, 0xc4, + 0x15, 0x19, 0x63, 0x4d, 0x53, 0x68, 0x91, 0x30, 0xf0, 0x3f, 0xff, + 0x8e, 0x21, 0xe6, 0xe4, 0x6a, 0x26, 0x80, 0x7f, 0xf8, 0x1a, 0xc7, + 0x33, 0xdb, 0x04, 0x10, 0xab, 0x76, 0x3d, 0xf5, 0x68, 0xc9, 0xf5, + 0x4c, 0x04, 0x9d, 0x5c, 0x35, 0xcd, 0xae, 0xb8, 0x80, 0x76, 0x3d, + 0xf3, 0x5d, 0xed, 0xf3, 0xd7, 0xbc, 0x87, 0x7e, 0x8d, 0x09, 0x84, + 0xe1, 0xdd, 0xf7, 0x99, 0x5d, 0x4c, 0x55, 0xb1, 0x8a, 0xf9, 0xb8, + 0x9b, 0xc2, 0x05, 0x6e, 0xf6, 0xfe, 0xbc, 0xa7, 0xa1, 0x46, 0x30, + 0x90, 0x07, 0x45, 0xc3, 0xc8, 0x3f, 0xf0, 0x79, 0xf6, 0xbf, 0x9e, + 0xfe, 0xb6, 0xf6, 0xf7, 0x6f, 0xba, 0x98, 0x5e, 0x9b, 0xd3, 0x6f, + 0xa0, 0x32, 0x3c, 0xbc, 0xe2, 0x46, 0x43, 0x43, 0x43, 0x78, 0xff, + 0xfb, 0xdf, 0x8f, 0xc3, 0x87, 0x0f, 0xcf, 0x50, 0x2e, 0xcd, 0xb2, + 0xd6, 0xd6, 0x99, 0x9f, 0xd8, 0x6e, 0xdc, 0xb8, 0x11, 0xdf, 0xfc, + 0xe6, 0x37, 0xf1, 0xe8, 0xa3, 0x8f, 0xe2, 0x67, 0x3f, 0xfb, 0x19, + 0x76, 0xee, 0xdc, 0x89, 0x07, 0x1e, 0x78, 0x60, 0x56, 0x54, 0xab, + 0xae, 0xeb, 0x95, 0xa6, 0x2d, 0x8d, 0xb6, 0xbb, 0x3f, 0xce, 0x70, + 0xf9, 0x9b, 0x1c, 0x5c, 0xcd, 0x30, 0x70, 0x64, 0x5f, 0xa9, 0x6d, + 0xda, 0xe7, 0xbf, 0xcc, 0x21, 0x0c, 0x67, 0xd7, 0xf3, 0xa2, 0x37, + 0x12, 0xee, 0xfa, 0x58, 0xe0, 0x7a, 0x36, 0xda, 0x3a, 0x5a, 0x90, + 0xfe, 0xe2, 0x9d, 0xec, 0x91, 0x5f, 0x3f, 0xac, 0x6d, 0xbc, 0xf0, + 0x3c, 0xda, 0x8b, 0x34, 0x42, 0x1e, 0x30, 0x73, 0x1a, 0xf1, 0x09, + 0x4e, 0xae, 0xa7, 0xee, 0xa1, 0xce, 0xc8, 0x47, 0xa9, 0x99, 0x98, + 0xf9, 0xf9, 0x93, 0x01, 0xeb, 0x97, 0xf1, 0x06, 0x18, 0xd2, 0x88, + 0x6c, 0xb8, 0x8c, 0x76, 0xfc, 0xea, 0x3b, 0xda, 0x3f, 0xfe, 0xf0, + 0x97, 0xe2, 0x92, 0xfb, 0x1e, 0xe4, 0xef, 0xd9, 0xbe, 0x6b, 0xee, + 0xb5, 0x55, 0x8b, 0xc7, 0xe3, 0xe0, 0x9c, 0xfb, 0x2a, 0x9e, 0x43, + 0x87, 0x0e, 0xe1, 0x9a, 0x6b, 0xae, 0xc1, 0x93, 0x4f, 0x3e, 0x89, + 0xb6, 0xb6, 0xb6, 0xa6, 0xc6, 0xb9, 0xba, 0xba, 0xba, 0x00, 0x94, + 0xe2, 0x74, 0x42, 0x08, 0xbc, 0xeb, 0x5d, 0xef, 0xaa, 0xca, 0xf3, + 0xca, 0x2b, 0xaf, 0x34, 0xf5, 0x9a, 0x4c, 0x75, 0x25, 0xa4, 0x69, + 0x5a, 0xa5, 0xfb, 0xa0, 0x46, 0xda, 0x65, 0xe7, 0x11, 0xee, 0xfc, + 0x18, 0xab, 0x86, 0x59, 0x19, 0x68, 0x7f, 0xb7, 0x99, 0x23, 0x97, + 0x07, 0x7e, 0xf3, 0xa2, 0xc0, 0x63, 0x3f, 0x16, 0xf8, 0xc0, 0x75, + 0x54, 0xdd, 0x77, 0x5a, 0x1a, 0xb8, 0xf3, 0xaf, 0x18, 0x9e, 0xdc, + 0x2a, 0xf0, 0xd4, 0xb6, 0xa0, 0xd6, 0xb3, 0xee, 0x17, 0x69, 0x12, + 0x99, 0x8f, 0xfe, 0x39, 0x7b, 0xe6, 0xb6, 0x0f, 0xb1, 0x27, 0x16, + 0x2d, 0xc1, 0x51, 0x64, 0x21, 0x90, 0x05, 0xa1, 0xba, 0x9b, 0x20, + 0xa7, 0x01, 0x52, 0x5c, 0x87, 0xaf, 0xab, 0x88, 0x00, 0x89, 0x0e, + 0x1e, 0xed, 0x9d, 0x3c, 0x3a, 0xf5, 0x58, 0xeb, 0xd4, 0xfd, 0xf6, + 0x74, 0x8f, 0xb5, 0x0c, 0x61, 0xc4, 0x21, 0xb2, 0xa3, 0x68, 0xff, + 0xbf, 0xbf, 0x12, 0x17, 0x7d, 0xed, 0x71, 0x7e, 0xe5, 0x2f, 0xb7, + 0x8a, 0xb5, 0x73, 0xe5, 0x26, 0xf6, 0xf5, 0xf5, 0x21, 0x1a, 0x8d, + 0xe2, 0xe4, 0xc9, 0x93, 0x18, 0x1a, 0x1a, 0xf2, 0xcd, 0xbf, 0x6c, + 0xd9, 0x32, 0x24, 0x12, 0x09, 0x1c, 0x3b, 0x76, 0xac, 0xa1, 0x1f, + 0x69, 0x5b, 0x6d, 0xc1, 0x82, 0x05, 0xe8, 0xe9, 0xe9, 0x41, 0x2e, + 0x97, 0x83, 0x10, 0xa2, 0xa2, 0x06, 0x85, 0x10, 0xd0, 0x34, 0x0d, + 0xd1, 0x68, 0x14, 0x63, 0x63, 0x63, 0xd8, 0xbb, 0x77, 0x6f, 0xd3, + 0x8e, 0xdf, 0xd9, 0xd9, 0x89, 0x42, 0xa1, 0x80, 0x68, 0x34, 0x8a, + 0x03, 0x07, 0x0e, 0x60, 0x7c, 0xbc, 0x71, 0x7d, 0x5b, 0xc7, 0x22, + 0xc0, 0xb6, 0xef, 0x69, 0x38, 0xf7, 0x3c, 0x02, 0xec, 0x5f, 0x75, + 0xc5, 0x81, 0x17, 0x9f, 0x17, 0xd8, 0xf0, 0x61, 0x13, 0xf9, 0x72, + 0x53, 0xbf, 0xd5, 0x4b, 0x09, 0xcf, 0x3f, 0xae, 0x95, 0x6a, 0x36, + 0x8d, 0xea, 0xfc, 0x3b, 0x77, 0x00, 0x97, 0xdd, 0x60, 0x60, 0x32, + 0x1b, 0x40, 0xa9, 0x16, 0x5b, 0x7a, 0x0e, 0x06, 0x3f, 0xfa, 0x7e, + 0xf6, 0xec, 0x07, 0xde, 0x49, 0xdb, 0x56, 0xac, 0xa6, 0x03, 0xc8, + 0x43, 0x94, 0xc7, 0x6a, 0x9f, 0xea, 0xd4, 0x31, 0x6f, 0xfb, 0xad, + 0xa5, 0x1b, 0x6e, 0xe9, 0x31, 0x05, 0xdc, 0x46, 0x45, 0x77, 0xea, + 0xb9, 0x36, 0x84, 0xe9, 0xce, 0x1e, 0x67, 0x02, 0x4e, 0x43, 0x08, + 0x31, 0x08, 0x14, 0x10, 0x7f, 0xe6, 0x39, 0xb1, 0xe6, 0x5f, 0x7f, + 0x21, 0x2e, 0xf9, 0xe9, 0xaf, 0xf8, 0xfa, 0xc3, 0x27, 0xd0, 0x11, + 0xdc, 0xf2, 0xc0, 0x1a, 0x69, 0xf7, 0xdf, 0xca, 0xf0, 0x5f, 0xef, + 0x70, 0xe8, 0xad, 0x96, 0x01, 0x5c, 0x03, 0xde, 0xf6, 0x21, 0x13, + 0x4f, 0x3f, 0x3f, 0x53, 0x71, 0x7d, 0xe1, 0x13, 0x0c, 0xf7, 0x7c, + 0xd6, 0xa1, 0x0b, 0x6e, 0x00, 0x48, 0x01, 0xff, 0xfc, 0x15, 0x8e, + 0xdb, 0xfe, 0x5b, 0xf0, 0x49, 0x94, 0xac, 0x85, 0x74, 0x18, 0x7f, + 0x7c, 0x39, 0xed, 0x7e, 0xdf, 0xdb, 0x68, 0xfb, 0xf5, 0xef, 0x64, + 0xcf, 0xb7, 0x74, 0x63, 0xa8, 0x0c, 0x32, 0xd3, 0x02, 0xad, 0x82, + 0x03, 0xc8, 0xec, 0xa3, 0x40, 0x39, 0x0d, 0x46, 0xec, 0x54, 0x61, + 0xc0, 0x55, 0x06, 0x49, 0x71, 0x1a, 0x57, 0xc0, 0x3e, 0x50, 0x4a, + 0x18, 0xd5, 0xe3, 0x0b, 0x84, 0xab, 0x96, 0x09, 0x21, 0x44, 0x41, + 0xd0, 0xc1, 0x46, 0x4e, 0x62, 0xde, 0x2f, 0x7e, 0x2b, 0xd6, 0x7d, + 0xf7, 0xc7, 0xfc, 0xd2, 0xe7, 0x77, 0x88, 0x45, 0x83, 0x23, 0x48, + 0x06, 0x8f, 0x42, 0x60, 0xf5, 0xd8, 0x95, 0x6f, 0x20, 0x3c, 0xf3, + 0xb0, 0x06, 0x9a, 0x0a, 0x8c, 0x58, 0x2d, 0x09, 0xfc, 0xe4, 0x27, + 0x02, 0x7f, 0xfa, 0xa9, 0xea, 0xc6, 0x68, 0x1d, 0xad, 0xc0, 0xcb, + 0xff, 0x5b, 0xc7, 0xa2, 0xc5, 0xa8, 0xee, 0x4e, 0x48, 0x03, 0x04, + 0x01, 0x6f, 0xf9, 0x2f, 0x26, 0x7e, 0xf3, 0x62, 0xe0, 0x7a, 0x7a, + 0x40, 0xcc, 0x3c, 0x6f, 0x15, 0x9d, 0x78, 0xd7, 0x95, 0xf4, 0x87, + 0xeb, 0xde, 0x45, 0x2f, 0x9d, 0xb7, 0x86, 0x0e, 0x23, 0x84, 0x5c, + 0x79, 0x0c, 0x01, 0x13, 0x33, 0x7b, 0xa2, 0x75, 0x1a, 0xfd, 0xc9, + 0x3a, 0xac, 0x9d, 0xdd, 0xfd, 0xf4, 0x1d, 0xca, 0xae, 0x11, 0xe3, + 0x72, 0x3a, 0x8d, 0x8a, 0xee, 0x34, 0xa4, 0x9d, 0x8e, 0x99, 0x63, + 0x72, 0x96, 0xe6, 0x75, 0x68, 0x88, 0x00, 0x30, 0x11, 0x3e, 0x75, + 0x12, 0x9d, 0xbf, 0x78, 0x96, 0xaf, 0xf9, 0xd1, 0x53, 0x62, 0xfd, + 0x6f, 0x5e, 0x14, 0xcb, 0x07, 0x86, 0x03, 0xb8, 0x05, 0xa6, 0x66, + 0xdd, 0x1d, 0xc0, 0xbf, 0x7f, 0x4f, 0xc7, 0xb2, 0xf5, 0xa8, 0x76, + 0x35, 0x75, 0x20, 0x3b, 0x0a, 0x5c, 0xf4, 0x3e, 0x13, 0xbb, 0x0e, + 0x3a, 0x43, 0xe9, 0xfa, 0x77, 0x30, 0x7c, 0xef, 0x2b, 0xac, 0x54, + 0x74, 0xec, 0x59, 0xa2, 0xc0, 0xc9, 0xbd, 0xc0, 0x45, 0x7f, 0x6e, + 0xe0, 0xe4, 0x60, 0x70, 0xad, 0x2b, 0x97, 0x25, 0x8c, 0xe2, 0xfa, + 0x95, 0x74, 0xf2, 0xcf, 0xae, 0xa2, 0x9d, 0xef, 0xb9, 0x8a, 0x76, + 0x5e, 0xb0, 0x86, 0x8e, 0x21, 0x86, 0x49, 0x14, 0xcb, 0x6e, 0xa5, + 0xa8, 0xc0, 0xc9, 0x6b, 0x6c, 0x4e, 0xaf, 0x21, 0xec, 0x7c, 0x07, + 0x47, 0x91, 0x01, 0x9a, 0x97, 0xeb, 0xe9, 0x35, 0x3e, 0xa7, 0xcc, + 0xc8, 0xe9, 0xd5, 0x69, 0x04, 0x1d, 0x1a, 0x18, 0xa2, 0x00, 0x0c, + 0x84, 0x07, 0xfb, 0xd1, 0xbe, 0x73, 0x9f, 0x98, 0xbf, 0xe5, 0x29, + 0xb1, 0xee, 0x77, 0xff, 0x21, 0x96, 0xed, 0x3e, 0x28, 0xe6, 0x8d, + 0x4e, 0x20, 0x16, 0x3c, 0x3e, 0x81, 0x79, 0xd9, 0xc2, 0x1e, 0xe0, + 0x8a, 0x0b, 0x09, 0xf9, 0x3c, 0xaa, 0x6a, 0x2d, 0x49, 0x03, 0x4e, + 0x9d, 0x2a, 0xf5, 0x62, 0xeb, 0x66, 0x8c, 0x01, 0x6f, 0xbf, 0x82, + 0x10, 0x8e, 0x38, 0x8c, 0x8e, 0x2e, 0x80, 0x48, 0x04, 0xf8, 0xed, + 0x4b, 0x02, 0x27, 0x06, 0xe6, 0xee, 0x35, 0x66, 0x0c, 0x7c, 0xc5, + 0x62, 0x1a, 0x3a, 0x6f, 0x25, 0x4e, 0xbc, 0xf7, 0x8f, 0xd9, 0xce, + 0xcb, 0xcf, 0xa7, 0xc3, 0x7d, 0x0b, 0x31, 0x40, 0x29, 0xa4, 0xcb, + 0x5a, 0x4b, 0x40, 0xc0, 0x84, 0xf3, 0xc8, 0xe8, 0x5e, 0xcb, 0x06, + 0xdc, 0x07, 0x1a, 0xe6, 0xa8, 0xae, 0xf9, 0x94, 0x1e, 0x39, 0xdd, + 0x4b, 0xa5, 0x11, 0xdc, 0x47, 0x50, 0x77, 0x52, 0x6c, 0x4e, 0x80, + 0xd3, 0x1d, 0xe6, 0xa7, 0xa7, 0x29, 0xb8, 0x85, 0x40, 0xd0, 0x40, + 0xc8, 0x22, 0x76, 0xbc, 0x1f, 0x6d, 0xcf, 0xbc, 0x28, 0x96, 0xff, + 0xee, 0x3f, 0xc4, 0xd2, 0xa7, 0x9e, 0x13, 0xcb, 0x0f, 0x1e, 0x17, + 0x1d, 0x99, 0x2c, 0xc2, 0x41, 0x11, 0x0e, 0x2c, 0xb0, 0xe6, 0x1a, + 0x11, 0xc4, 0xfc, 0x2e, 0x8c, 0xbf, 0x61, 0x1d, 0x1d, 0xfb, 0xa3, + 0xcb, 0x68, 0xdf, 0x5b, 0x2f, 0xa5, 0x7d, 0x6b, 0xfb, 0xa8, 0x3f, + 0x92, 0x42, 0x1a, 0x04, 0xa3, 0x8c, 0x22, 0x01, 0x5e, 0x71, 0x0b, + 0xad, 0xae, 0xa2, 0x15, 0x54, 0x5e, 0xf3, 0x26, 0x66, 0x0e, 0x55, + 0x67, 0xb8, 0x80, 0xcc, 0xeb, 0x0b, 0x02, 0xd8, 0x81, 0x26, 0x03, + 0x35, 0xaf, 0x81, 0x52, 0x18, 0xaa, 0xfb, 0x04, 0x77, 0x82, 0x9b, + 0x66, 0x03, 0x9a, 0xe6, 0xb2, 0xbe, 0x34, 0x4f, 0x60, 0xd0, 0x41, + 0x08, 0x43, 0x80, 0xa0, 0x19, 0x63, 0x48, 0x1e, 0x3d, 0x85, 0xb6, + 0x5d, 0x07, 0x44, 0xf7, 0x2f, 0x9f, 0x13, 0xcb, 0x5f, 0xfa, 0x83, + 0x58, 0xb8, 0x7d, 0x97, 0x98, 0x3f, 0x34, 0x8a, 0xe0, 0xeb, 0xbb, + 0xc0, 0x02, 0x6b, 0x40, 0x1c, 0x6c, 0x5d, 0x1f, 0xf5, 0x9f, 0xbb, + 0x0a, 0x27, 0xdf, 0x76, 0x19, 0xed, 0xbd, 0x68, 0x1d, 0x1d, 0x5f, + 0x3a, 0x9f, 0x86, 0x5b, 0x3b, 0x31, 0x8e, 0x10, 0x0a, 0x15, 0x67, + 0x91, 0x57, 0x60, 0x63, 0x8f, 0x73, 0x59, 0x87, 0x9c, 0xf3, 0x9a, + 0x4c, 0x38, 0x8f, 0x8e, 0xee, 0x15, 0xfc, 0xb7, 0x36, 0xaa, 0x95, + 0x02, 0x9a, 0x9f, 0xeb, 0xe9, 0x56, 0x51, 0xe0, 0xa4, 0xd6, 0x9c, + 0x5c, 0x52, 0xcd, 0x03, 0x60, 0x4e, 0x79, 0xaa, 0xf7, 0xc7, 0xca, + 0x80, 0xd3, 0x21, 0xc0, 0xa0, 0xa1, 0x80, 0x50, 0xff, 0x49, 0xb4, + 0xed, 0x3e, 0x24, 0xba, 0x77, 0x1f, 0x12, 0x5d, 0x3b, 0xf6, 0xa0, + 0xe7, 0xb7, 0x2f, 0x89, 0x25, 0x87, 0x4e, 0x88, 0xf6, 0x20, 0x0e, + 0x17, 0x58, 0x60, 0xee, 0x96, 0x88, 0xa1, 0xb0, 0xa0, 0x9b, 0xc6, + 0x2f, 0x5a, 0x8b, 0xa3, 0x97, 0x9c, 0x4b, 0xc7, 0xd6, 0x2d, 0xa3, + 0xc1, 0xe5, 0x8b, 0x30, 0xb0, 0x7a, 0x29, 0x0d, 0xb0, 0x04, 0xb2, + 0x20, 0x98, 0x16, 0x05, 0xc6, 0x21, 0xaa, 0xbe, 0x0e, 0x72, 0x02, + 0x9a, 0xe9, 0x02, 0x2b, 0x37, 0x70, 0x39, 0xd5, 0x60, 0xba, 0xc1, + 0x4c, 0xb8, 0x00, 0x0d, 0x32, 0x40, 0xb3, 0xc2, 0x0c, 0x2e, 0x50, + 0xb3, 0xb6, 0x53, 0x23, 0x1b, 0x7c, 0xdc, 0x00, 0xe7, 0x04, 0x2b, + 0xdd, 0x25, 0x8f, 0x93, 0x02, 0x9c, 0xd9, 0x2e, 0x8e, 0xc0, 0x2a, + 0xa3, 0x85, 0x6a, 0x20, 0x10, 0x18, 0xd2, 0x88, 0x0e, 0x8d, 0x21, + 0xf9, 0xda, 0x7e, 0xd1, 0xbd, 0x7d, 0x97, 0x58, 0xb0, 0xe7, 0x30, + 0x3a, 0xf7, 0x1d, 0x15, 0x1d, 0xbb, 0x0e, 0x60, 0xde, 0xfe, 0xa3, + 0xa2, 0xd3, 0x30, 0x82, 0x9e, 0x75, 0x03, 0x9b, 0x5b, 0xd6, 0xd3, + 0x89, 0xf1, 0xb5, 0xcb, 0x69, 0x70, 0xe9, 0x39, 0x18, 0xe9, 0x5b, + 0x4c, 0x83, 0x6b, 0x97, 0xd1, 0xa9, 0x4b, 0xd6, 0xe3, 0xd8, 0xfc, + 0x79, 0x34, 0x1e, 0x6e, 0xc1, 0x24, 0x34, 0x98, 0x30, 0xcb, 0x8e, + 0x63, 0x11, 0x54, 0x9e, 0xe3, 0x36, 0xc8, 0x58, 0xa1, 0xe3, 0xa4, + 0xa8, 0x64, 0x61, 0xe7, 0x04, 0x30, 0x2b, 0xc4, 0x4c, 0x9b, 0x1a, + 0xf3, 0x85, 0x99, 0x17, 0xd0, 0xbc, 0x54, 0x1a, 0x3c, 0xa0, 0xe6, + 0x56, 0x71, 0xc0, 0x24, 0x21, 0xa7, 0x79, 0xc0, 0x4b, 0x43, 0x75, + 0x03, 0x5f, 0xa7, 0x63, 0x4c, 0x0f, 0xda, 0xa2, 0x81, 0xca, 0x90, + 0x03, 0x08, 0x0c, 0x06, 0xf4, 0xfc, 0x04, 0x62, 0x07, 0x8f, 0x89, + 0x8e, 0x63, 0xa7, 0xd0, 0xb6, 0x7d, 0x97, 0xe8, 0x79, 0x79, 0x97, + 0x38, 0xe7, 0xf0, 0x71, 0xb4, 0x9d, 0x18, 0x40, 0x6a, 0x60, 0x44, + 0x24, 0x86, 0xc7, 0x10, 0x7c, 0xb9, 0x17, 0xd8, 0xeb, 0x5a, 0x71, + 0xcd, 0x6b, 0xc7, 0x64, 0x77, 0x07, 0xa5, 0x17, 0xf5, 0x62, 0x6c, + 0xe5, 0x62, 0x1a, 0xbc, 0xec, 0x7c, 0x3a, 0xb2, 0x64, 0x01, 0x46, + 0x97, 0x2e, 0xa0, 0xa1, 0x8e, 0x79, 0x98, 0x40, 0x08, 0x45, 0x30, + 0x98, 0xe0, 0x10, 0x28, 0x80, 0xca, 0xe8, 0x10, 0x1e, 0x50, 0xb1, + 0xa7, 0x99, 0x2e, 0x90, 0xf3, 0x83, 0x95, 0x9b, 0x3b, 0xe9, 0x14, + 0x23, 0x93, 0xf9, 0xe4, 0xa9, 0xea, 0x63, 0x75, 0x19, 0xa0, 0xc9, + 0xb8, 0xa0, 0x32, 0xae, 0xa8, 0x17, 0xe0, 0x9c, 0x94, 0x97, 0xe6, + 0x01, 0x33, 0xcd, 0x65, 0xff, 0x4e, 0xc7, 0xa2, 0x19, 0xe9, 0x0c, + 0x34, 0x43, 0x0b, 0x0a, 0x68, 0x28, 0x22, 0x54, 0xcc, 0x20, 0x32, + 0x9a, 0x46, 0x7c, 0xff, 0x51, 0xd1, 0xf6, 0xda, 0x01, 0xd1, 0x73, + 0xa4, 0x1f, 0xad, 0x7b, 0x0e, 0xa2, 0x73, 0xc7, 0x1e, 0xd1, 0x3b, + 0x30, 0x22, 0x12, 0x23, 0xe3, 0x88, 0x4d, 0x66, 0x11, 0x9e, 0xcb, + 0x03, 0x26, 0x07, 0x76, 0x66, 0x58, 0x38, 0x04, 0xb3, 0xad, 0x05, + 0xd9, 0x8e, 0x56, 0xca, 0x2c, 0x3f, 0x07, 0x43, 0xe7, 0xad, 0xa2, + 0x53, 0x8b, 0x7a, 0x30, 0xd6, 0xb7, 0x90, 0x86, 0xd6, 0xad, 0xa0, + 0xfe, 0xce, 0x36, 0x4c, 0x26, 0x12, 0xc8, 0x21, 0x8c, 0x22, 0x74, + 0x18, 0xe0, 0xe5, 0x3a, 0xc7, 0x29, 0x7d, 0x24, 0x66, 0x40, 0xc3, + 0x0d, 0x26, 0x5e, 0x30, 0x73, 0x5b, 0x36, 0x5c, 0xb6, 0x35, 0x5d, + 0xd2, 0x38, 0xbc, 0xdb, 0x95, 0xf9, 0x7d, 0xee, 0x54, 0xf5, 0xdd, + 0xb9, 0x17, 0xd0, 0x64, 0xa0, 0x26, 0x1b, 0x5f, 0x73, 0xab, 0x1d, + 0x65, 0x92, 0x80, 0x92, 0xcd, 0xef, 0xb4, 0x6c, 0x3f, 0x7e, 0xf5, + 0xe0, 0xa5, 0x54, 0x76, 0x53, 0xa7, 0xab, 0x34, 0x04, 0x08, 0x0c, + 0x1c, 0x0c, 0x59, 0x44, 0x26, 0xd2, 0x88, 0x8d, 0xa7, 0x11, 0x1d, + 0x1c, 0x11, 0xc9, 0x53, 0xa3, 0x48, 0xec, 0x3d, 0x2c, 0xda, 0x77, + 0xec, 0xc1, 0xfc, 0xfe, 0x21, 0x91, 0xea, 0x1f, 0x42, 0x72, 0x78, + 0x0c, 0xf1, 0xd1, 0x09, 0x11, 0x1d, 0x9b, 0x40, 0x74, 0x32, 0xa8, + 0x79, 0x0d, 0xac, 0x0e, 0x0b, 0xe9, 0x30, 0x5b, 0x52, 0xc8, 0xb5, + 0xa7, 0x90, 0x6b, 0x6b, 0xa1, 0x6c, 0x77, 0x3b, 0x26, 0xbb, 0x3b, + 0x29, 0xbd, 0x7c, 0x21, 0x06, 0xcf, 0x5f, 0x49, 0xa7, 0xba, 0x3b, + 0x91, 0xee, 0x6a, 0xa7, 0x74, 0x47, 0x2b, 0x32, 0x2d, 0x09, 0xe4, + 0xf4, 0x04, 0xb2, 0x08, 0xc1, 0x80, 0x28, 0x63, 0xaa, 0x08, 0x4b, + 0x0f, 0x85, 0x55, 0xbd, 0x53, 0xcc, 0xec, 0xee, 0x0b, 0x15, 0x55, + 0xc6, 0x7d, 0xa0, 0xe6, 0x94, 0xdf, 0xf4, 0xc9, 0xcb, 0x15, 0x00, + 0xe6, 0x07, 0x31, 0xaf, 0x1e, 0x6b, 0x21, 0x13, 0x43, 0x73, 0x83, + 0x9a, 0x9f, 0x2b, 0xca, 0x7c, 0xe2, 0x6c, 0xcc, 0xa2, 0x98, 0xec, + 0xdf, 0x88, 0x92, 0x0f, 0xa0, 0xc8, 0x03, 0x56, 0x32, 0x13, 0xc1, + 0x79, 0x24, 0x66, 0xe6, 0x70, 0x7e, 0x33, 0x61, 0x37, 0xed, 0xc4, + 0x4e, 0x9f, 0x01, 0xc0, 0x60, 0x42, 0x83, 0x01, 0xcd, 0xcc, 0x23, + 0x9c, 0xce, 0x20, 0x92, 0xce, 0x20, 0xb2, 0xff, 0xa8, 0x68, 0x3b, + 0x72, 0x12, 0x1d, 0x03, 0xc3, 0x22, 0xd1, 0x3f, 0x82, 0xc4, 0xe1, + 0xe3, 0x68, 0xdd, 0x7f, 0x54, 0x74, 0x0e, 0x8f, 0x23, 0x3e, 0x31, + 0x29, 0x22, 0x13, 0x93, 0x88, 0xe4, 0xf2, 0xd0, 0x8b, 0x41, 0x0c, + 0x6f, 0x4e, 0x19, 0x63, 0x10, 0x91, 0x30, 0x8c, 0x44, 0x0c, 0xf9, + 0x96, 0x04, 0x0a, 0x2d, 0x09, 0xca, 0xcf, 0xef, 0xc6, 0xe8, 0xea, + 0xa5, 0x34, 0xdc, 0x53, 0x86, 0x54, 0x6f, 0x27, 0x26, 0x56, 0x2e, + 0xc6, 0x50, 0x47, 0x3b, 0x65, 0x92, 0x31, 0xe4, 0xa3, 0x31, 0xe4, + 0x11, 0x82, 0x01, 0x0d, 0x26, 0x58, 0x39, 0x24, 0x6f, 0x5a, 0x80, + 0x55, 0x2a, 0xfa, 0x4e, 0xe0, 0x72, 0xeb, 0xea, 0xcb, 0x9a, 0x66, + 0xba, 0xac, 0x93, 0x99, 0x64, 0x20, 0xe8, 0x04, 0x4e, 0xe1, 0x11, + 0xe8, 0xf7, 0x82, 0x99, 0x9b, 0x2a, 0x83, 0x4a, 0x0c, 0x4d, 0x05, + 0x6c, 0x4e, 0x90, 0x73, 0x82, 0x9b, 0x5b, 0xcc, 0x8d, 0x5c, 0xe0, + 0xc3, 0x7c, 0xe2, 0x73, 0xcc, 0x67, 0x3f, 0x4c, 0x11, 0x60, 0x4e, + 0xf3, 0x4e, 0xbf, 0xd3, 0xf3, 0xd3, 0x7f, 0x28, 0xbb, 0xb3, 0x62, + 0xc6, 0x1a, 0x13, 0x0c, 0x05, 0x84, 0x8a, 0x39, 0x84, 0x33, 0xe5, + 0x69, 0x3c, 0x2d, 0x22, 0xe3, 0x69, 0xc4, 0x46, 0xd3, 0x88, 0x0e, + 0x8e, 0x20, 0xbe, 0xe7, 0xb0, 0x68, 0xeb, 0x1f, 0x44, 0xdb, 0xc8, + 0x04, 0x62, 0xe3, 0x69, 0x11, 0x19, 0x4d, 0x23, 0x3a, 0x32, 0x8a, + 0x58, 0xff, 0xb0, 0x48, 0x4c, 0x66, 0x11, 0x2d, 0x14, 0xa1, 0x71, + 0x1e, 0xb8, 0xba, 0x67, 0xa2, 0x9a, 0x8a, 0x46, 0x50, 0xec, 0x68, + 0xc5, 0x64, 0x6f, 0x27, 0x65, 0x92, 0x09, 0xe4, 0x3a, 0x52, 0xc8, + 0xa7, 0x92, 0x94, 0xed, 0x6a, 0xc7, 0xe4, 0xd2, 0x73, 0x30, 0xbc, + 0xa8, 0x97, 0x26, 0x5a, 0x93, 0xc8, 0xb7, 0x24, 0x91, 0x6d, 0x4f, + 0x51, 0x36, 0x1e, 0x45, 0x21, 0x1e, 0x43, 0x31, 0x16, 0x45, 0x1e, + 0x11, 0x14, 0xcb, 0x63, 0x50, 0x8a, 0x8a, 0xc2, 0x32, 0x40, 0x15, + 0x50, 0xf1, 0x72, 0x30, 0x5c, 0xb8, 0x16, 0x78, 0x2f, 0x80, 0xc9, + 0x40, 0xce, 0x4d, 0xa1, 0x09, 0x9f, 0x65, 0x3f, 0xa5, 0xc5, 0xe1, + 0x5d, 0x43, 0x29, 0x5c, 0x80, 0x56, 0x33, 0xc8, 0x6a, 0x01, 0x9a, + 0x8c, 0x1b, 0x6a, 0x77, 0x41, 0x9d, 0x54, 0x9b, 0xdb, 0x68, 0xc8, + 0xf6, 0x5f, 0xcd, 0x53, 0x39, 0x79, 0x2f, 0x93, 0x4f, 0x1e, 0x92, + 0x04, 0x98, 0x1f, 0xd4, 0xbc, 0x46, 0x76, 0x9e, 0x9e, 0xb7, 0x02, + 0x6f, 0x7a, 0x2d, 0xcd, 0xd8, 0xa3, 0x00, 0x81, 0x43, 0x03, 0x2f, + 0xb9, 0xba, 0x66, 0x16, 0xa1, 0x91, 0x09, 0xc4, 0x26, 0x33, 0x88, + 0x8c, 0x4d, 0x8a, 0x48, 0x36, 0x87, 0xf0, 0x78, 0x49, 0xdd, 0x85, + 0xc7, 0x26, 0x10, 0x99, 0xc8, 0x88, 0xc8, 0x64, 0x16, 0x91, 0xb1, + 0x09, 0x84, 0x73, 0x05, 0x44, 0x4e, 0x0e, 0x88, 0xd8, 0x89, 0x21, + 0x24, 0x26, 0x26, 0x91, 0xc8, 0x64, 0xa1, 0xe7, 0x8b, 0xd0, 0x0d, + 0x03, 0x7a, 0x26, 0x27, 0xb4, 0x7c, 0x11, 0x9a, 0x61, 0x40, 0xcf, + 0x17, 0xa0, 0xcd, 0x75, 0x65, 0x48, 0x04, 0x1e, 0x8b, 0xc0, 0xd4, + 0x75, 0x98, 0x61, 0x1d, 0x66, 0x2c, 0x4a, 0x46, 0x38, 0x04, 0x33, + 0x1c, 0x82, 0x11, 0x8b, 0xc0, 0x48, 0xc4, 0x91, 0xeb, 0x6c, 0x45, + 0x7a, 0x61, 0x0f, 0x65, 0x92, 0x09, 0xe4, 0x53, 0x31, 0xe4, 0x5b, + 0x52, 0x28, 0xc4, 0x23, 0x94, 0x6f, 0x4b, 0x21, 0x1f, 0x8b, 0x21, + 0x9f, 0x8a, 0xa1, 0x90, 0x88, 0xa3, 0x90, 0x8c, 0x21, 0x9f, 0x4a, + 0x50, 0x3e, 0x95, 0x40, 0x36, 0x91, 0x42, 0xbe, 0x7c, 0xf7, 0xcc, + 0x72, 0xb0, 0x82, 0x5b, 0x8a, 0xab, 0x70, 0x68, 0x0e, 0x2a, 0x2c, + 0xea, 0x4a, 0x78, 0xa8, 0x14, 0xee, 0x31, 0xef, 0xb4, 0xce, 0x0d, + 0x6a, 0x7e, 0xeb, 0x4c, 0x87, 0x7d, 0xfb, 0xa9, 0x3d, 0xbf, 0xbc, + 0x6e, 0xc7, 0x84, 0xa2, 0x1a, 0x93, 0x82, 0x59, 0xad, 0x40, 0x73, + 0x52, 0x6b, 0x7e, 0xb1, 0x35, 0xaf, 0x8a, 0x04, 0x15, 0x90, 0xf8, + 0x29, 0x27, 0x59, 0x70, 0x11, 0x54, 0x54, 0x98, 0xf7, 0x70, 0xf4, + 0x5e, 0x69, 0xb0, 0x1c, 0xd7, 0xef, 0x1a, 0x4c, 0xc3, 0x0f, 0x15, + 0x00, 0xda, 0x8f, 0x3c, 0x55, 0x25, 0x31, 0x95, 0x0f, 0x95, 0x5f, + 0xb3, 0xec, 0x02, 0x9b, 0xd0, 0x78, 0x09, 0x5c, 0xba, 0x69, 0x82, + 0xe5, 0x8b, 0xe5, 0x79, 0x0e, 0x36, 0x9e, 0x16, 0xe1, 0xe1, 0x31, + 0x44, 0xd2, 0x19, 0x44, 0xf3, 0x05, 0x84, 0x27, 0xb3, 0x08, 0x65, + 0x72, 0x08, 0x15, 0x0d, 0xa1, 0x15, 0xcb, 0xc0, 0xcb, 0xe4, 0xa0, + 0x17, 0x8a, 0xd3, 0xdb, 0x9b, 0x1c, 0x5a, 0x26, 0x07, 0xcd, 0x30, + 0xc1, 0x8a, 0x45, 0x30, 0xd3, 0x84, 0x66, 0x72, 0x41, 0x9c, 0x43, + 0xe3, 0x02, 0xc4, 0x39, 0x28, 0x93, 0xab, 0x40, 0x92, 0x0a, 0x45, + 0x30, 0x93, 0x83, 0x91, 0xf5, 0xa1, 0x23, 0xc0, 0x30, 0xca, 0x2a, + 0x93, 0xa6, 0xd5, 0x0d, 0xd9, 0x1e, 0x4c, 0x51, 0x0a, 0x78, 0x73, + 0x8d, 0x81, 0x0b, 0x01, 0x8a, 0x84, 0x61, 0x86, 0x43, 0xa5, 0x07, + 0x5f, 0xd7, 0xc0, 0x89, 0x20, 0x74, 0x8d, 0x4c, 0x4d, 0x83, 0x28, + 0xab, 0x23, 0x33, 0xa4, 0x83, 0xeb, 0x1a, 0x4c, 0x5d, 0x83, 0x19, + 0xd2, 0x61, 0xc4, 0xa2, 0x30, 0xe3, 0x51, 0x18, 0xa5, 0x65, 0x32, + 0xca, 0x6e, 0x9e, 0x11, 0x8b, 0xa2, 0x10, 0x8b, 0x20, 0xd7, 0x96, + 0x42, 0x7e, 0x5e, 0x1b, 0xe5, 0x74, 0x1d, 0xa6, 0xa6, 0x81, 0x47, + 0x42, 0x30, 0x43, 0x3a, 0x4c, 0x5d, 0x87, 0xa1, 0x87, 0x60, 0x42, + 0x2f, 0x5f, 0xc9, 0x50, 0xe5, 0xb3, 0x76, 0x61, 0x29, 0x56, 0xc2, + 0x02, 0x23, 0xaa, 0x68, 0x27, 0x5e, 0x56, 0x55, 0x70, 0x04, 0x94, + 0xb5, 0xf0, 0xc2, 0x47, 0x91, 0x78, 0xb9, 0x5e, 0x6e, 0xa0, 0x93, + 0x81, 0x9c, 0x4c, 0x7e, 0xd3, 0x07, 0x42, 0xdc, 0x63, 0x5b, 0x2e, + 0x09, 0x60, 0xeb, 0x35, 0x00, 0xe4, 0x47, 0x74, 0x92, 0x82, 0x59, + 0x3d, 0x40, 0xf3, 0x73, 0x43, 0xfd, 0x62, 0x6d, 0x7e, 0x60, 0x93, + 0x55, 0x3f, 0xf5, 0xa4, 0xc9, 0xaa, 0x2e, 0xb7, 0xed, 0xa0, 0x00, + 0xb7, 0x5a, 0x26, 0x48, 0xa4, 0xc1, 0x06, 0x43, 0xd8, 0x70, 0x87, + 0xaa, 0x34, 0x0d, 0x02, 0x04, 0x61, 0x5b, 0x4f, 0x96, 0xbb, 0x46, + 0x0e, 0x8f, 0x10, 0xb3, 0x3c, 0x72, 0xa5, 0x63, 0x09, 0xcb, 0x76, + 0xbc, 0x72, 0x0e, 0x02, 0xc2, 0xf1, 0x99, 0x10, 0x96, 0x6d, 0xac, + 0xc7, 0x15, 0x2e, 0x4f, 0xd4, 0xd4, 0xde, 0xad, 0xe7, 0x69, 0x3d, + 0x03, 0xeb, 0x59, 0x54, 0xbf, 0xbd, 0x85, 0xc3, 0xbc, 0xa8, 0xa8, + 0xe0, 0xea, 0xe2, 0x64, 0x45, 0xd1, 0xcc, 0x2d, 0xdd, 0x7a, 0x6c, + 0x86, 0xcf, 0xb2, 0x9b, 0xf2, 0xe0, 0x1e, 0xcb, 0x32, 0x70, 0xf3, + 0x52, 0x37, 0xdc, 0x07, 0x86, 0xb2, 0x40, 0x14, 0x35, 0x82, 0x4a, + 0x48, 0xfe, 0x3f, 0x6e, 0x00, 0x13, 0xb5, 0x42, 0xcc, 0x6a, 0xf5, + 0x76, 0xe4, 0x2e, 0x1c, 0x1e, 0x5c, 0xaf, 0xbc, 0x34, 0xe3, 0x01, + 0xaf, 0x2e, 0x98, 0x5c, 0x01, 0x76, 0x5e, 0x40, 0xf2, 0x03, 0x24, + 0x53, 0x38, 0x06, 0x49, 0x6e, 0x03, 0x49, 0x98, 0xc1, 0x01, 0x8a, + 0xa8, 0x01, 0x68, 0xd5, 0xf3, 0xa2, 0x82, 0x03, 0xaf, 0xd1, 0xee, + 0xdd, 0xd2, 0xdd, 0x42, 0x08, 0xfe, 0x2f, 0x2f, 0x92, 0x56, 0xf1, + 0x2a, 0xcf, 0x93, 0x3d, 0x45, 0xf8, 0x6c, 0xe3, 0xf6, 0x66, 0xf7, + 0x6a, 0xbb, 0xe4, 0x35, 0xe0, 0x86, 0x2c, 0xd0, 0x20, 0x51, 0x60, + 0x1b, 0x35, 0xf9, 0xb9, 0x6b, 0x2a, 0xca, 0xce, 0x6f, 0x9d, 0x90, + 0x3c, 0x0e, 0x57, 0x84, 0x3a, 0xe0, 0xd3, 0xeb, 0x6c, 0x2d, 0x20, + 0x6b, 0x14, 0xd0, 0x9c, 0x0e, 0x4e, 0x0e, 0x0f, 0x10, 0x39, 0xcc, + 0xab, 0x28, 0x37, 0x2a, 0x4b, 0x62, 0x27, 0x80, 0xa0, 0x06, 0x40, + 0xd9, 0x21, 0xa2, 0xba, 0x3d, 0x24, 0xd7, 0xc9, 0xb9, 0x99, 0xb5, + 0xc0, 0xcb, 0xbf, 0x52, 0xc6, 0xed, 0x1a, 0x7b, 0x81, 0x8b, 0x3c, + 0x94, 0xb6, 0x3b, 0xa8, 0x9a, 0xd7, 0x36, 0x4f, 0xd4, 0x90, 0x26, + 0x24, 0xa1, 0x06, 0x05, 0xc0, 0xf9, 0x15, 0x4a, 0x59, 0xd5, 0xd6, + 0x0c, 0xc8, 0x09, 0x49, 0x08, 0xd5, 0x02, 0x3f, 0x95, 0xc9, 0xcf, + 0x95, 0x94, 0x89, 0x8d, 0xd5, 0x04, 0xb1, 0x66, 0x01, 0x0d, 0x0e, + 0xd0, 0xf2, 0x7b, 0x08, 0xad, 0xaa, 0x8e, 0xd9, 0xa0, 0xe8, 0x54, + 0x50, 0x99, 0xe5, 0xa2, 0xa9, 0xaa, 0x20, 0xbf, 0xfc, 0x4c, 0x01, + 0x40, 0xf5, 0xb8, 0x8d, 0xb2, 0x31, 0xc6, 0x7a, 0x20, 0x26, 0xdb, + 0x7e, 0x50, 0x16, 0x70, 0xb2, 0xaa, 0x0d, 0x67, 0x08, 0xd8, 0xbc, + 0xd4, 0x9a, 0x0c, 0xe8, 0xbc, 0x54, 0x18, 0x5c, 0x0a, 0xb0, 0x5f, + 0x41, 0x56, 0x85, 0x9b, 0x1b, 0x20, 0x4e, 0xd7, 0x04, 0x0f, 0x35, + 0x26, 0xe3, 0x3e, 0x0a, 0x09, 0x60, 0xd5, 0xdd, 0x73, 0xa6, 0x3e, + 0x4b, 0x0f, 0x20, 0x49, 0x9c, 0x34, 0x97, 0x28, 0x84, 0x5c, 0x52, + 0xd1, 0x01, 0xf5, 0xa9, 0x22, 0x26, 0xb1, 0x7f, 0x26, 0x09, 0x2c, + 0x28, 0xc2, 0x0c, 0xa8, 0x4f, 0x89, 0xd5, 0x03, 0x31, 0x3f, 0x35, + 0x46, 0x0a, 0x95, 0x44, 0xcd, 0x02, 0x99, 0x4c, 0xad, 0x97, 0xac, + 0xfb, 0xa9, 0x0a, 0x39, 0x15, 0xe0, 0xd5, 0xa2, 0xda, 0x20, 0x09, + 0x34, 0x48, 0xba, 0x7a, 0xb0, 0xb9, 0xa9, 0xa8, 0x11, 0xac, 0x7e, + 0x0a, 0x0c, 0xf0, 0x6e, 0xf8, 0xda, 0x14, 0x35, 0x36, 0x9b, 0x40, + 0x93, 0x05, 0x9c, 0x70, 0x51, 0x76, 0x76, 0xf5, 0xe6, 0x57, 0xa8, + 0x65, 0xd6, 0xcb, 0x42, 0x05, 0x0a, 0x10, 0x83, 0xc7, 0x7a, 0x2f, + 0x60, 0xfa, 0x41, 0xcc, 0x69, 0xbd, 0xdf, 0x75, 0x68, 0x96, 0x1a, + 0x23, 0xc7, 0x00, 0x7f, 0x73, 0xa0, 0x26, 0x7c, 0x62, 0xb1, 0x4e, + 0xeb, 0x55, 0x6a, 0xc5, 0x64, 0x5c, 0x1f, 0x59, 0xf7, 0xb3, 0x56, + 0xe8, 0x01, 0xf2, 0xf1, 0x38, 0x59, 0x00, 0xd5, 0x53, 0x71, 0xa1, + 0x72, 0x8e, 0xb5, 0x5c, 0xbb, 0xa6, 0x43, 0xec, 0x74, 0x00, 0xcd, + 0xaf, 0x32, 0x01, 0x0a, 0x80, 0x53, 0xa9, 0x49, 0xad, 0x25, 0x4d, + 0x56, 0x61, 0xa9, 0xc6, 0xb8, 0x64, 0xcf, 0xa1, 0x96, 0x3c, 0x50, + 0x58, 0x27, 0x0b, 0xb5, 0x5a, 0xdc, 0x4c, 0x6a, 0xf0, 0xb3, 0x51, + 0xab, 0x6a, 0x93, 0x55, 0x70, 0x2a, 0x40, 0x83, 0x42, 0x01, 0xf7, + 0xfd, 0x88, 0x5a, 0x41, 0xdd, 0xa9, 0xe6, 0x57, 0x55, 0x92, 0x2a, + 0xe7, 0xec, 0x05, 0x2d, 0x71, 0x3a, 0x00, 0x76, 0xa6, 0x00, 0xcd, + 0xef, 0x1f, 0x26, 0x8f, 0x87, 0x4a, 0xb6, 0x90, 0xd6, 0xd2, 0x84, + 0x64, 0xb6, 0x40, 0xe9, 0x74, 0x7e, 0x8d, 0x70, 0x23, 0x6b, 0x55, + 0x65, 0x2a, 0xae, 0xe4, 0x99, 0x08, 0x34, 0x51, 0x07, 0xe0, 0xbc, + 0x0a, 0x68, 0x3d, 0xea, 0x4e, 0xa5, 0x22, 0xa2, 0x56, 0xb7, 0xb6, + 0x5e, 0xc8, 0xca, 0xfe, 0x3f, 0x2a, 0x0a, 0x6c, 0xd6, 0x21, 0x76, + 0xa6, 0x01, 0xad, 0x51, 0x90, 0x73, 0x72, 0x47, 0x48, 0xa1, 0xa0, + 0xab, 0xb8, 0x6e, 0x8d, 0xac, 0x61, 0xac, 0x57, 0x71, 0xa9, 0xb4, + 0x05, 0x54, 0x75, 0x31, 0x67, 0x13, 0x64, 0x8d, 0x80, 0x9b, 0x0a, + 0xd8, 0x54, 0x0b, 0xae, 0x6a, 0x4d, 0xaa, 0xac, 0xda, 0x51, 0x01, + 0x4d, 0x23, 0x9a, 0xa3, 0xf8, 0x01, 0x5b, 0x15, 0x5e, 0xa7, 0x15, + 0x60, 0xaf, 0x17, 0xa0, 0xa9, 0xb8, 0xa9, 0x4e, 0x17, 0x9f, 0x5c, + 0x80, 0xa7, 0x12, 0x2b, 0x52, 0x85, 0x4c, 0xad, 0x79, 0x20, 0x19, + 0x17, 0x53, 0xd9, 0x0f, 0x14, 0xf3, 0x9d, 0x2e, 0x35, 0xd6, 0x48, + 0xc0, 0xc9, 0x28, 0x37, 0x55, 0xa0, 0xa9, 0xce, 0xd7, 0x0a, 0x42, + 0x15, 0x08, 0xaa, 0xba, 0xcc, 0xb2, 0xff, 0xdb, 0x19, 0xad, 0xbc, + 0xce, 0x46, 0xa0, 0xd5, 0x73, 0x61, 0x9d, 0xc0, 0xa6, 0x52, 0xc8, + 0xeb, 0x89, 0x45, 0xd5, 0x52, 0xc3, 0x28, 0x0b, 0x3e, 0x48, 0xba, + 0x90, 0xe4, 0xa2, 0x74, 0xfd, 0x3e, 0x61, 0xf3, 0x7b, 0x21, 0x34, + 0x0b, 0x72, 0xc2, 0x63, 0xff, 0x4e, 0x71, 0x56, 0x21, 0xb1, 0xad, + 0xf0, 0x51, 0xf9, 0xb5, 0xc6, 0xe1, 0xea, 0x55, 0x74, 0xaa, 0xdb, + 0xa9, 0xee, 0xaf, 0x16, 0x25, 0xfb, 0xba, 0x35, 0x1d, 0x67, 0xa7, + 0x09, 0xc5, 0x7c, 0xe4, 0xa2, 0x02, 0x65, 0xe1, 0xa7, 0x0a, 0x34, + 0x81, 0xe9, 0x1a, 0xd1, 0x7a, 0xd5, 0x94, 0x5a, 0xab, 0xfe, 0xfa, + 0xd2, 0x55, 0xd4, 0x9b, 0x6a, 0x01, 0x91, 0xdd, 0x46, 0xf8, 0xe4, + 0x57, 0x09, 0x4e, 0xab, 0xaa, 0x3a, 0x55, 0xd7, 0xcc, 0x2f, 0x2e, + 0xd7, 0x08, 0xb7, 0xb8, 0x51, 0x69, 0x67, 0x85, 0x9d, 0xad, 0x40, + 0x6b, 0x84, 0xb2, 0x13, 0x0d, 0x72, 0xd1, 0xdc, 0xd2, 0xb8, 0x02, + 0x50, 0x54, 0xa0, 0xe5, 0xd5, 0xb4, 0xc2, 0x0d, 0x88, 0x02, 0xcd, + 0x6b, 0x63, 0x46, 0x0d, 0xbc, 0x27, 0x2a, 0xdb, 0x0b, 0x45, 0xe8, + 0xd9, 0x41, 0x59, 0x0b, 0xec, 0x6a, 0x05, 0x22, 0x35, 0x70, 0xbb, + 0xd7, 0xa5, 0xab, 0x18, 0x00, 0xed, 0xf4, 0xba, 0xb0, 0x6e, 0x0f, + 0x94, 0x4a, 0x1c, 0xaa, 0x19, 0x79, 0x9b, 0x11, 0xd0, 0xa7, 0xd7, + 0xf9, 0x7d, 0x13, 0x0d, 0x5c, 0x57, 0x6b, 0x43, 0x5f, 0x55, 0xe5, + 0xa8, 0x0a, 0x65, 0x3f, 0xd5, 0x3a, 0x67, 0x2c, 0x00, 0x5a, 0x7d, + 0x85, 0x47, 0xc0, 0xff, 0x2b, 0x08, 0x99, 0x36, 0x77, 0x2a, 0x0f, + 0x63, 0x33, 0x82, 0xf7, 0xaa, 0xd0, 0xa2, 0x33, 0xec, 0x3e, 0x9c, + 0x0e, 0xe0, 0xd5, 0x0a, 0x29, 0xd5, 0xff, 0x81, 0x2b, 0xec, 0x47, + 0xcc, 0xf5, 0x42, 0x1a, 0x00, 0xed, 0xf4, 0x14, 0x30, 0x92, 0xdc, + 0x0f, 0x29, 0x1e, 0x4f, 0x05, 0x34, 0xcd, 0x00, 0xdd, 0x99, 0x7e, + 0x0f, 0x1a, 0x99, 0xcf, 0xad, 0x92, 0x21, 0x70, 0xfd, 0x02, 0xa0, + 0x05, 0x10, 0x54, 0xc8, 0x47, 0x0d, 0x2a, 0x30, 0x14, 0x5c, 0xf7, + 0xba, 0xf7, 0x11, 0x00, 0xea, 0x0c, 0xb3, 0xff, 0x3f, 0x00, 0x33, + 0x7e, 0xb5, 0x01, 0x3c, 0x57, 0x93, 0xe4, 0x00, 0x00, 0x00, 0x00, + 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82 +}; + +unsigned int nxlogo_png_size = sizeof(nxlogo_png); +
\r\n" +#define maintabletag "
\r\n" +#define tableendtag "
" +#define trtag "
" +#define toptdtag "" +#define tdcolspan4tag "" +#define tdcolspan3tag "" +#define tdcolspan2tag "" +#define tdendtag "




" + + +#define formtag "
" +#define formendtag "
" + +#define UDPTXSTRING "Start UDP Transmit Test" +#define UDP_Tx "UDP_Tx" +#define udptxsubmittag1 \ + "
\r\n" \ + "
"fonttag "Destination IP Address:
"fonttag "Destination Port:
"fonttag "Test Time(Seconds):
"fonttag "Packet size:


"fonttag "Test Time(Seconds):


"fonttag "Destination IP Address:
"fonttag "Destination Port:
"fonttag "Test Time(Seconds):


"fonttag "Test Time(Seconds):


Choose a test from the left.