Connectivity Secure TCP Client problem

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
ToPe_1312931
Level 4
Level 4
10 replies posted 10 questions asked 5 replies posted

I am running this example as well as the Python secure server. The certificates supplied with the example are at the location where I am running the server. The server throws this error.

$ python tcp_secure_server.py

==========================

TCP Secure Server

==========================

Listening on: 192.168.0.39:50007

Traceback (most recent call last):

  File "tcp_secure_server.py", line 104, in <module>

    echo_server(options.hostname, options.port)

  File "tcp_secure_server.py", line 73, in echo_server

    keyfile="server.key")

  File "/usr/lib/python2.7/ssl.py", line 931, in wrap_socket

    ciphers=ciphers)

  File "/usr/lib/python2.7/ssl.py", line 599, in __init__

    self.do_handshake()

  File "/usr/lib/python2.7/ssl.py", line 828, in do_handshake

    self._sslobj.do_handshake()

ssl.SSLError: [SSL: SSLV3_ALERT_BAD_CERTIFICATE] sslv3 alert bad certificate (_ssl.c:727)

When the PSoC hits this call in main.c

    while( ( mbedtls_result = mbedtls_ssl_handshake( &ssl ) ) != 0 )

    {

        if( mbedtls_result != MBEDTLS_ERR_SSL_WANT_READ && mbedtls_result != MBEDTLS_ERR_SSL_WANT_WRITE )

        {

            printf( "Failed! mbedtls_ssl_handshake returned -0x%x\n\n", -mbedtls_result );

        }

    }

0 Likes
1 Solution
lock attach
Attachments are accessible only for community members.

-0x2700 means Certificate verification failed, e.g. CRL, CA or signature check failed as described in /Connectivity_Secure_TCP_Client/libs/mbedtls/include/mbedtls/x509.h

The default example works fine in my setup. Please make sure that you don't change the CA cert present in /Connectivity_Secure_TCP_Client/network_credentials.h; to be on the safer side, you can try replacing the current non-working cert with the one present in github. I am assuming that you have already modified the CE based on your PC's ip address and have launched the server before the client tries to connect.

Attached is my example with the mbedTLS debugging info prints added; which should be able to guide you to find the root cause of the issue; i.e what is the exact reason that the signature check failed or what exact section of the TLS handshake is causing this error.

/******************************************************************************

* File Name:   main.c

*

* Description: This is the source code for TCP Secure Client Example in

* ModusToolbox.

*

* Related Document: See Readme.md

*

*******************************************************************************

* (c) 2019, Cypress Semiconductor Corporation. All rights reserved.

*******************************************************************************

* This software, including source code, documentation and related materials

* ("Software"), is owned by Cypress Semiconductor Corporation or one of its

* subsidiaries ("Cypress") and is protected by and subject to worldwide patent

* protection (United States and foreign), United States copyright laws and

* international treaty provisions. Therefore, you may use this Software only

* as provided in the license agreement accompanying the software package from

* which you obtained this Software ("EULA").

*

* If no EULA applies, Cypress hereby grants you a personal, non-exclusive,

* non-transferable license to copy, modify, and compile the Software source

* code solely for use in connection with Cypress's integrated circuit products.

* Any reproduction, modification, translation, compilation, or representation

* of this Software except as specified above is prohibited without the express

* written permission of Cypress.

*

* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,

* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED

* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress

* reserves the right to make changes to the Software without notice. Cypress

* does not assume any liability arising out of the application or use of the

* Software or any product or circuit described in the Software. Cypress does

* not authorize its products for use in any products where a malfunction or

* failure of the Cypress product may reasonably be expected to result in

* significant property damage, injury or death ("High Risk Product"). By

* including Cypress's product in a High Risk Product, the manufacturer of such

* system or application assumes all risk of such use and in doing so agrees to

* indemnify Cypress against all liability.

*******************************************************************************/

/* Header file includes */

#include "cyhal.h"

#include "cybsp.h"

#include "cybsp_wifi.h"

#include "cy_retarget_io.h"

#include "string.h"

/* FreeRTOS header file */

#include <FreeRTOS.h>

#include <task.h>

#include <queue.h>

/* lwIP header files */

#include <lwip/tcpip.h>

#include <lwip/api.h>

#include <lwipinit.h>

#include <mbedtlsinit.h>

#include "ip4_addr.h"

/* mbedTLS header files */

#include "mbedtls_net_sockets.h"

#include "mbedtls/debug.h"

#include "mbedtls/ssl.h"

#include "mbedtls/entropy.h"

#include "mbedtls/ctr_drbg.h"

#include "mbedtls/error.h"

#include "mbedtls/certs.h"

#include "mbedtls/config.h"

#include "network_credentials.h"

/******************************************************************************

* Macros

******************************************************************************/

#define MAX_CONNECTION_RETRIES            (10u)

/* Change the server IP address to match the TCP Secure Server address

* (IP address of the PC) */

#define TCP_SERVER_IP_ADDR   "192.168.0.103"

#define TCP_SERVER_PORT      "50007"

#define TCP_SERVER_HOSTNAME  "mytcpsecureserver"

/* 32-bit task notification value for the led_task */

#define LED_ON                            (0x00lu)

#define LED_OFF                           (0x01lu)

#define USER_BTN1_INTR_PRIORITY           (5)

#define LED_TASK_STACK_SIZE               (128)

#define TCP_CLIENT_TASK_STACK_SIZE        (1024*5)

#define LED_TASK_PRIORITY                 (1)

#define TCP_CLIENT_TASK_PRIORITY          (1)

#define TCP_CLIENT_TASK_QUEUE_LEN         (10)

#define CLIENT_TASK_Q_TICKS_TO_TIMEOUT    (100)

#define RTOS_TASK_TICKS_TO_WAIT           (100)

#define DEBUG_LEVEL 3

/* Data structure to TCP data and data length */

typedef struct

{

    char text[20];

    uint8_t len;

}tcp_data_packet_t;

/******************************************************************************

* Function Prototypes

******************************************************************************/

void isr_button_press( void *callback_arg, cyhal_gpio_event_t event);

void led_task(void *args);

void tcp_client_task(void *arg);

static void my_debug(void *ctx, int level, const char *file, int line,

                         const char *str);

/******************************************************************************

* Global Variables

******************************************************************************/

/* The primary WIFI driver  */

whd_interface_t iface ;

/* 32-bit task notification value containing the LED state */

uint32_t led_state = LED_OFF;

/* LED task handle */

TaskHandle_t led_task_handle;

/* Handle of the Queue to send TCP data packets */

QueueHandle_t tcpClientQ;

/* This enables RTOS aware debugging */

volatile int uxTopUsedPriority ;

const size_t tcp_server_cert_len = sizeof( tcp_server_cert );

/******************************************************************************

* Function Name: main

******************************************************************************

* Summary:

*  System entrance point. This function sets up user tasks and then starts

*  the RTOS scheduler.

*

* Parameters:

*  void

*

* Return:

*  int

*

******************************************************************************/

int main()

{

    cy_rslt_t result ;

    /* This enables RTOS aware debugging in OpenOCD */

    uxTopUsedPriority = configMAX_PRIORITIES - 1 ;

    /* Initialize the board support package */

    result = cybsp_init() ;

    CY_ASSERT(result == CY_RSLT_SUCCESS) ;

    /* Enable global interrupts */

    __enable_irq();

    /* Initialize retarget-io to use the debug UART port */

    cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX,\

                        CY_RETARGET_IO_BAUDRATE);

    /* \x1b[2J\x1b[;H - ANSI ESC sequence to clear screen */

    printf("\x1b[2J\x1b[;H");

    printf("===============================================================\n");

    printf("CE229252 - ModusToolbox Connectivity Example: Secure TCP Client\n");

    printf("===============================================================\n\n");

    /* Queue to Receive TCP packets */

    tcpClientQ = xQueueCreate(TCP_CLIENT_TASK_QUEUE_LEN, sizeof(tcp_data_packet_t));

    /* Create the tasks */

    xTaskCreate(led_task, "LED task", LED_TASK_STACK_SIZE, NULL,

                LED_TASK_PRIORITY, &led_task_handle) ;

    xTaskCreate(tcp_client_task, "Network task", TCP_CLIENT_TASK_STACK_SIZE,

                NULL, TCP_CLIENT_TASK_PRIORITY, NULL) ;

    /* Start the FreeRTOS scheduler */

    vTaskStartScheduler() ;

    /* Should never get here */

    CY_ASSERT(0) ;

}

/*******************************************************************************

* Function Name: isr_button_press

*******************************************************************************

*

* Summary:

*  GPIO interrupt service routine. This function detects button

*  presses and sends task notifications to the TCP client task.

*

* Parameters:

*  void *callback_arg : pointer to variable passed to the ISR

*  cyhal_gpio_event_t event : GPIO event type

*

* Return:

*  None

*

******************************************************************************/

void isr_button_press( void *callback_arg, cyhal_gpio_event_t event)

{

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if(led_state == LED_ON)

    {

        led_state = LED_OFF;

    }

    else

    {

        led_state = LED_ON;

    }

    /* Notify the led_task about the change in LED state */

    xTaskNotifyFromISR(led_task_handle, led_state, eSetValueWithoutOverwrite,

                       &xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}

/******************************************************************************

* Function Name: led_task

******************************************************************************

* Summary:

*  Task that toggles the LED state on every button (SW2) presses

*

* Parameters:

*  void *args : Task parameter defined during task creation (unused)

*

* Return:

*  void

*

******************************************************************************/

void led_task(void *args)

{

    /* Variable to track LED state */

    uint32_t led_state;

    /* TCP data packet */

    tcp_data_packet_t tcp_pkt_led_state;

    sprintf(tcp_pkt_led_state.text, "LED OFF");

    tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

    /* Initialize User button 1 and register interrupt on falling edge */

    cyhal_gpio_init(CYBSP_USER_BTN1, CYHAL_GPIO_DIR_INPUT,

                    CYHAL_GPIO_DRIVE_PULLUP, 1);

    cyhal_gpio_register_callback(CYBSP_USER_BTN1, isr_button_press, NULL);

    cyhal_gpio_enable_event(CYBSP_USER_BTN1, CYHAL_GPIO_IRQ_FALL,

                            USER_BTN1_INTR_PRIORITY, 1);

    /* Initialize the User LED */

    cyhal_gpio_init((cyhal_gpio_t) CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT,

                    CYHAL_GPIO_DRIVE_PULLUP, CYBSP_LED_STATE_OFF);

    while (true)

    {

        /* Block till USER_BNT1 is pressed */

        xTaskNotifyWait(0, 0, &led_state, portMAX_DELAY);

        /* Update LED state */

        cyhal_gpio_write((cyhal_gpio_t) CYBSP_USER_LED, led_state);

        if(led_state == LED_OFF)

        {

             sprintf(tcp_pkt_led_state.text, "LED OFF");

             tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

        }

        else

        {

            sprintf(tcp_pkt_led_state.text, "LED ON");

            tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

        }

        /* Send TCP data packet to the tcp_client_task */

        xQueueSend(tcpClientQ, &tcp_pkt_led_state, CLIENT_TASK_Q_TICKS_TO_TIMEOUT);

   }

}

/*******************************************************************************

* Function Name: tcp_client_task

*******************************************************************************

* Summary:

*  Task used to establish a connection to a remote TCP server and send

*  LED ON/OFF state to the TCP server

*

* Parameters:

*  void *args : Task parameter defined during task creation (unused)

*

* Return:

*  void

*

*******************************************************************************/

void tcp_client_task(void *arg)

{

    cy_rslt_t result;

    whd_ssid_t ssid_data;

    int mbedtls_result;

    const char *ssid = WIFI_SSID;

    const char *key = WIFI_PASSWORD;

    struct netif *net;

    tcp_data_packet_t tcp_pkt_led_state;

    unsigned char * write_buff;

    size_t  len;

    /* mbed TLS structures

     */

    mbedtls_net_context server_fd;

    mbedtls_entropy_context entropy;

    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_ssl_context ssl;

    mbedtls_ssl_config conf;

    mbedtls_x509_crt cacert;

    /* Variable to track the number of connection retries to the Wi-Fi AP specified

     * by WIFI_SSID macro */

    int conn_retries = 0;

    /* Initialize and start the tcpip_thread */

    tcpip_init(NULL, NULL) ;

    printf("LWiP TCP/IP stack initialized\n") ;

    /* Initialize the Wi-Fi Driver */

    result = cybsp_wifi_init_primary(&iface) ;

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Wi-Fi driver initialized \n") ;

    }

    else

    {

        printf("Wi-Fi Driver initialization failed!\n");

        CY_ASSERT(0);

    }

    /* The  below initializes RTC */

    mbedtls_init();

    /* Join the Wi-Fi AP */

    result = WHD_PENDING;

    ssid_data.length = strlen(ssid) ;

    memcpy(ssid_data.value, ssid, ssid_data.length) ;

    while(result != CY_RSLT_SUCCESS && conn_retries < MAX_CONNECTION_RETRIES)

    {

        result = whd_wifi_join(iface, &ssid_data, WHD_SECURITY_WPA2_AES_PSK,

                               (const uint8_t *)key, strlen(key)) ;

        conn_retries++;

    }

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Successfully joined Wi-Fi network '%s'\n", ssid) ;

    }

    else

    {

        printf("Failed to join Wi-Fi network '%s'\n", ssid);

        CY_ASSERT(0);

    }

    /* Add the Wi-Fi interface to the lwIP stack */

    result = add_interface_to_lwip(iface, NULL) ;

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Wi-Fi interface added to TCP/IP stack\n");

    }

    else

    {

        printf("Failed to add Wi-Fi interface to lwIP stack!\n");

        CY_ASSERT(0);

    }

    /* Fetch the IP address assigned based on the added Wi-Fi interface */

    net = get_lwip_interface() ;

    while (true)

    {

        if (net->ip_addr.u_addr.ip4.addr != 0)

        {

            printf("IP Address %s assigned\n",

                    ip4addr_ntoa(&net->ip_addr.u_addr.ip4));

            break ;

        }

        vTaskDelay(RTOS_TASK_TICKS_TO_WAIT) ;

    }

    /* Initialize mbed TLS structures required to setup a TLS session */

    mbedtls_net_init( &server_fd );

    mbedtls_ssl_init( &ssl );

    mbedtls_ssl_config_init( &conf );

    mbedtls_x509_crt_init( &cacert );

    mbedtls_ctr_drbg_init( &ctr_drbg );

    /* Initialize and seed the entropy source */

    mbedtls_entropy_init( &entropy );

    if( ( mbedtls_result = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,

                               NULL, 0 ) ) != 0 )

    {

        printf( " Failed! mbedtls_ctr_drbg_seed returned %d\n", mbedtls_result );

        CY_ASSERT(0);

    }

    else

    {

        printf( "Success: The random number generator has been seeded\n");

    }

    /* Start the connection */

    printf( "Connecting to TCP Server /%s/%s...\n", TCP_SERVER_IP_ADDR, TCP_SERVER_PORT );

  

    if( ( mbedtls_result = mbedtls_net_connect( &server_fd, TCP_SERVER_IP_ADDR,

                                         TCP_SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )

    {

        printf( "Failed! mbedtls_net_connect returned %d\n", mbedtls_result );

        CY_ASSERT(0);

    }

    else

    {

        printf( "Successfully connected to TCP Server /%s/%s\n", TCP_SERVER_IP_ADDR, TCP_SERVER_PORT );

    }

    /* Configure the TLS layer */

    printf( "Setting up the SSL/TLS Layer...\n" );

    if( ( mbedtls_result = mbedtls_ssl_config_defaults( &conf,

                    MBEDTLS_SSL_IS_CLIENT,

                    MBEDTLS_SSL_TRANSPORT_STREAM,

                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )

    {

        printf( "Failed ! mbedtls_ssl_config_defaults returned %d\n\n", mbedtls_result );

        CY_ASSERT(0);

    }

    /* Set the authentication mode to determine how strict the certificates presented are

     *  checked */

    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );

#if DEBUG_LEVEL > 0

    mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);

    mbedtls_debug_set_threshold(DEBUG_LEVEL);

#endif

    /* Initialize certificates to authenticate the server */

    mbedtls_result = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) tcp_server_cert,

                              tcp_server_cert_len );

    if( mbedtls_result < 0 )

    {

        printf( "Failed!  mbedtls_x509_crt_parse returned -0x%x\n", -mbedtls_result );

        CY_ASSERT(0);

    }

    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );

    /* Set the random engine to be used for random number generation */

    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );

    /* Set up the SSL context for the TLS session */

    if( ( mbedtls_result = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )

    {

        printf( "Failed! mbedtls_ssl_setup returned %d\n", mbedtls_result );

    }

    /* Set the host name to check against the received server certificate */

    if( ( mbedtls_result = mbedtls_ssl_set_hostname( &ssl, TCP_SERVER_HOSTNAME ) ) != 0 )

    {

        printf( "Failed! mbedtls_ssl_set_hostname returned %d\n", mbedtls_result );

    }

   

    /* Set the input and output functions to use for the network traffic */

    mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );

    /* Perform the SSL/TLS Handshake */

    printf( "Performing the SSL/TLS handshake..." );

    while( ( mbedtls_result = mbedtls_ssl_handshake( &ssl ) ) != 0 )

    {

        if( mbedtls_result != MBEDTLS_ERR_SSL_WANT_READ && mbedtls_result != MBEDTLS_ERR_SSL_WANT_WRITE )

        {

            printf( "Failed! mbedtls_ssl_handshake returned -0x%x\n\n", -mbedtls_result );

        }

    }

    printf( " ok\n" );

    /* Verify the server certificate */

    printf( "Verifying peer X.509 certificate..." );

    if( ( mbedtls_result = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )

    {

        char vrfy_buf[512];

        printf( "Failed\n" );

        mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", mbedtls_result );

        printf( "%s\n", vrfy_buf );

        /* Close the connection to the server */

        printf("Closing the connection...\n");

        mbedtls_net_free( &server_fd );

        /* Free up the resources used by the TLS context */

        mbedtls_x509_crt_free( &cacert );

        mbedtls_ssl_free( &ssl );

        mbedtls_ssl_config_free( &conf );

        mbedtls_ctr_drbg_free( &ctr_drbg );

        mbedtls_entropy_free( &entropy );

        /* Calling assert here once server authentication fails.

         * Modify the code to handle the server authentication failure

         * to suit your application. */

        CY_ASSERT(0);

    }

    else

    {

        printf("ok\n\n");

        printf("===============================================================\n");

        printf( "TCP communication layer Secured!!!\n" );

        printf("===============================================================\n");

    }

    for(;;)

    {

        /* Block till TCP packet to be sent to the TCP server

         * is received on the queue */

        xQueueReceive(tcpClientQ, &tcp_pkt_led_state, portMAX_DELAY);

        write_buff = (unsigned char *)tcp_pkt_led_state.text;

        len = tcp_pkt_led_state.len;

        /* Send the LED status to the TCP server */

        do

        {

            mbedtls_result = mbedtls_ssl_write( &ssl, (unsigned char*)write_buff , len );

            if( mbedtls_result == MBEDTLS_ERR_SSL_WANT_READ || mbedtls_result == MBEDTLS_ERR_SSL_WANT_WRITE )

            {

                continue;

            }

            else if( mbedtls_result < 0 )

            {

                printf( "Failed! mbedtls_ssl_write returned %d\n", mbedtls_result );

                CY_ASSERT(0);

            }

            /* Continue the write operation if the data is partially sent.

             * Update the write_buffer and len so as to write the remaining data.

             */

            else if ( mbedtls_result < len )

            {

                write_buff += mbedtls_result;

                len -= mbedtls_result;

                continue;

            }

            else

            {

                /* Break out of the loop once the write operation is successful. */

                break;

            }

        }while(1);

        printf( "%d Bytes written: %s\n", tcp_pkt_led_state.len, tcp_pkt_led_state.text );

    }

}

#if DEBUG_LEVEL > 0

/**

* Debug callback for mbed TLS

* Just prints on the USB serial port

*/

static void my_debug(void *ctx, int level, const char *file, int line,

                     const char *str)

{

    const char *p, *basename;

    (void) ctx;

    /* Extract basename from file */

    for(p = basename = file; *p != '\0'; p++) {

        if(*p == '/' || *p == '\\') {

            basename = p + 1;

        }

    }

    printf("%s:%04d: |%d| %s", basename, line, level, str);

}

#endif

/* [] END OF FILE */

View solution in original post

4 Replies
ToPe_1312931
Level 4
Level 4
10 replies posted 10 questions asked 5 replies posted

Kitprog3 terminal window shows this.

===============================================================

CE229252 - ModusToolbox Connectivity Example: Secure TCP Client

===============================================================

LWiP TCP/IP stack initialized

WLAN MAC Address : 00:9D:6B:98:D0:74

WLAN Firmware    : wl0: Sep  5 2019 23:24:33 version 7.45.98.92 (r722362 CY) FWID 01-f7128517

WLAN CLM         : API: 12.2 Data: 9.10.39 Compiler: 1.29.4 ClmImport: 1.36.3 Creation: 2019-09-05 23:10:00

WHD VERSION      : v1.60.0 : v1.60.0 : GCC 7.2 : 2019-11-13 21:27:38 -0600

Wi-Fi driver initialized

Successfully joined Wi-Fi network 'xyz'

Wi-Fi interface added to TCP/IP stack

IP Address 192.168.0.64 assigned

Success: The random number generator has been seeded

Connecting to TCP Server /192.168.0.39/50007...

Successfully connected to TCP Server /192.168.0.39/50007

Setting up the SSL/TLS Layer...

Performing the SSL/TLS handshake...Failed! mbedtls_ssl_handshake returned -0x2700

Failed! mbedtls_ssl_handshake returned -0x50

Failed! mbedtls_ssl_handshake returned -0x4e

0 Likes
lock attach
Attachments are accessible only for community members.

-0x2700 means Certificate verification failed, e.g. CRL, CA or signature check failed as described in /Connectivity_Secure_TCP_Client/libs/mbedtls/include/mbedtls/x509.h

The default example works fine in my setup. Please make sure that you don't change the CA cert present in /Connectivity_Secure_TCP_Client/network_credentials.h; to be on the safer side, you can try replacing the current non-working cert with the one present in github. I am assuming that you have already modified the CE based on your PC's ip address and have launched the server before the client tries to connect.

Attached is my example with the mbedTLS debugging info prints added; which should be able to guide you to find the root cause of the issue; i.e what is the exact reason that the signature check failed or what exact section of the TLS handshake is causing this error.

/******************************************************************************

* File Name:   main.c

*

* Description: This is the source code for TCP Secure Client Example in

* ModusToolbox.

*

* Related Document: See Readme.md

*

*******************************************************************************

* (c) 2019, Cypress Semiconductor Corporation. All rights reserved.

*******************************************************************************

* This software, including source code, documentation and related materials

* ("Software"), is owned by Cypress Semiconductor Corporation or one of its

* subsidiaries ("Cypress") and is protected by and subject to worldwide patent

* protection (United States and foreign), United States copyright laws and

* international treaty provisions. Therefore, you may use this Software only

* as provided in the license agreement accompanying the software package from

* which you obtained this Software ("EULA").

*

* If no EULA applies, Cypress hereby grants you a personal, non-exclusive,

* non-transferable license to copy, modify, and compile the Software source

* code solely for use in connection with Cypress's integrated circuit products.

* Any reproduction, modification, translation, compilation, or representation

* of this Software except as specified above is prohibited without the express

* written permission of Cypress.

*

* Disclaimer: THIS SOFTWARE IS PROVIDED AS-IS, WITH NO WARRANTY OF ANY KIND,

* EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, NONINFRINGEMENT, IMPLIED

* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Cypress

* reserves the right to make changes to the Software without notice. Cypress

* does not assume any liability arising out of the application or use of the

* Software or any product or circuit described in the Software. Cypress does

* not authorize its products for use in any products where a malfunction or

* failure of the Cypress product may reasonably be expected to result in

* significant property damage, injury or death ("High Risk Product"). By

* including Cypress's product in a High Risk Product, the manufacturer of such

* system or application assumes all risk of such use and in doing so agrees to

* indemnify Cypress against all liability.

*******************************************************************************/

/* Header file includes */

#include "cyhal.h"

#include "cybsp.h"

#include "cybsp_wifi.h"

#include "cy_retarget_io.h"

#include "string.h"

/* FreeRTOS header file */

#include <FreeRTOS.h>

#include <task.h>

#include <queue.h>

/* lwIP header files */

#include <lwip/tcpip.h>

#include <lwip/api.h>

#include <lwipinit.h>

#include <mbedtlsinit.h>

#include "ip4_addr.h"

/* mbedTLS header files */

#include "mbedtls_net_sockets.h"

#include "mbedtls/debug.h"

#include "mbedtls/ssl.h"

#include "mbedtls/entropy.h"

#include "mbedtls/ctr_drbg.h"

#include "mbedtls/error.h"

#include "mbedtls/certs.h"

#include "mbedtls/config.h"

#include "network_credentials.h"

/******************************************************************************

* Macros

******************************************************************************/

#define MAX_CONNECTION_RETRIES            (10u)

/* Change the server IP address to match the TCP Secure Server address

* (IP address of the PC) */

#define TCP_SERVER_IP_ADDR   "192.168.0.103"

#define TCP_SERVER_PORT      "50007"

#define TCP_SERVER_HOSTNAME  "mytcpsecureserver"

/* 32-bit task notification value for the led_task */

#define LED_ON                            (0x00lu)

#define LED_OFF                           (0x01lu)

#define USER_BTN1_INTR_PRIORITY           (5)

#define LED_TASK_STACK_SIZE               (128)

#define TCP_CLIENT_TASK_STACK_SIZE        (1024*5)

#define LED_TASK_PRIORITY                 (1)

#define TCP_CLIENT_TASK_PRIORITY          (1)

#define TCP_CLIENT_TASK_QUEUE_LEN         (10)

#define CLIENT_TASK_Q_TICKS_TO_TIMEOUT    (100)

#define RTOS_TASK_TICKS_TO_WAIT           (100)

#define DEBUG_LEVEL 3

/* Data structure to TCP data and data length */

typedef struct

{

    char text[20];

    uint8_t len;

}tcp_data_packet_t;

/******************************************************************************

* Function Prototypes

******************************************************************************/

void isr_button_press( void *callback_arg, cyhal_gpio_event_t event);

void led_task(void *args);

void tcp_client_task(void *arg);

static void my_debug(void *ctx, int level, const char *file, int line,

                         const char *str);

/******************************************************************************

* Global Variables

******************************************************************************/

/* The primary WIFI driver  */

whd_interface_t iface ;

/* 32-bit task notification value containing the LED state */

uint32_t led_state = LED_OFF;

/* LED task handle */

TaskHandle_t led_task_handle;

/* Handle of the Queue to send TCP data packets */

QueueHandle_t tcpClientQ;

/* This enables RTOS aware debugging */

volatile int uxTopUsedPriority ;

const size_t tcp_server_cert_len = sizeof( tcp_server_cert );

/******************************************************************************

* Function Name: main

******************************************************************************

* Summary:

*  System entrance point. This function sets up user tasks and then starts

*  the RTOS scheduler.

*

* Parameters:

*  void

*

* Return:

*  int

*

******************************************************************************/

int main()

{

    cy_rslt_t result ;

    /* This enables RTOS aware debugging in OpenOCD */

    uxTopUsedPriority = configMAX_PRIORITIES - 1 ;

    /* Initialize the board support package */

    result = cybsp_init() ;

    CY_ASSERT(result == CY_RSLT_SUCCESS) ;

    /* Enable global interrupts */

    __enable_irq();

    /* Initialize retarget-io to use the debug UART port */

    cy_retarget_io_init(CYBSP_DEBUG_UART_TX, CYBSP_DEBUG_UART_RX,\

                        CY_RETARGET_IO_BAUDRATE);

    /* \x1b[2J\x1b[;H - ANSI ESC sequence to clear screen */

    printf("\x1b[2J\x1b[;H");

    printf("===============================================================\n");

    printf("CE229252 - ModusToolbox Connectivity Example: Secure TCP Client\n");

    printf("===============================================================\n\n");

    /* Queue to Receive TCP packets */

    tcpClientQ = xQueueCreate(TCP_CLIENT_TASK_QUEUE_LEN, sizeof(tcp_data_packet_t));

    /* Create the tasks */

    xTaskCreate(led_task, "LED task", LED_TASK_STACK_SIZE, NULL,

                LED_TASK_PRIORITY, &led_task_handle) ;

    xTaskCreate(tcp_client_task, "Network task", TCP_CLIENT_TASK_STACK_SIZE,

                NULL, TCP_CLIENT_TASK_PRIORITY, NULL) ;

    /* Start the FreeRTOS scheduler */

    vTaskStartScheduler() ;

    /* Should never get here */

    CY_ASSERT(0) ;

}

/*******************************************************************************

* Function Name: isr_button_press

*******************************************************************************

*

* Summary:

*  GPIO interrupt service routine. This function detects button

*  presses and sends task notifications to the TCP client task.

*

* Parameters:

*  void *callback_arg : pointer to variable passed to the ISR

*  cyhal_gpio_event_t event : GPIO event type

*

* Return:

*  None

*

******************************************************************************/

void isr_button_press( void *callback_arg, cyhal_gpio_event_t event)

{

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    if(led_state == LED_ON)

    {

        led_state = LED_OFF;

    }

    else

    {

        led_state = LED_ON;

    }

    /* Notify the led_task about the change in LED state */

    xTaskNotifyFromISR(led_task_handle, led_state, eSetValueWithoutOverwrite,

                       &xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

}

/******************************************************************************

* Function Name: led_task

******************************************************************************

* Summary:

*  Task that toggles the LED state on every button (SW2) presses

*

* Parameters:

*  void *args : Task parameter defined during task creation (unused)

*

* Return:

*  void

*

******************************************************************************/

void led_task(void *args)

{

    /* Variable to track LED state */

    uint32_t led_state;

    /* TCP data packet */

    tcp_data_packet_t tcp_pkt_led_state;

    sprintf(tcp_pkt_led_state.text, "LED OFF");

    tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

    /* Initialize User button 1 and register interrupt on falling edge */

    cyhal_gpio_init(CYBSP_USER_BTN1, CYHAL_GPIO_DIR_INPUT,

                    CYHAL_GPIO_DRIVE_PULLUP, 1);

    cyhal_gpio_register_callback(CYBSP_USER_BTN1, isr_button_press, NULL);

    cyhal_gpio_enable_event(CYBSP_USER_BTN1, CYHAL_GPIO_IRQ_FALL,

                            USER_BTN1_INTR_PRIORITY, 1);

    /* Initialize the User LED */

    cyhal_gpio_init((cyhal_gpio_t) CYBSP_USER_LED, CYHAL_GPIO_DIR_OUTPUT,

                    CYHAL_GPIO_DRIVE_PULLUP, CYBSP_LED_STATE_OFF);

    while (true)

    {

        /* Block till USER_BNT1 is pressed */

        xTaskNotifyWait(0, 0, &led_state, portMAX_DELAY);

        /* Update LED state */

        cyhal_gpio_write((cyhal_gpio_t) CYBSP_USER_LED, led_state);

        if(led_state == LED_OFF)

        {

             sprintf(tcp_pkt_led_state.text, "LED OFF");

             tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

        }

        else

        {

            sprintf(tcp_pkt_led_state.text, "LED ON");

            tcp_pkt_led_state.len = strlen(tcp_pkt_led_state.text);

        }

        /* Send TCP data packet to the tcp_client_task */

        xQueueSend(tcpClientQ, &tcp_pkt_led_state, CLIENT_TASK_Q_TICKS_TO_TIMEOUT);

   }

}

/*******************************************************************************

* Function Name: tcp_client_task

*******************************************************************************

* Summary:

*  Task used to establish a connection to a remote TCP server and send

*  LED ON/OFF state to the TCP server

*

* Parameters:

*  void *args : Task parameter defined during task creation (unused)

*

* Return:

*  void

*

*******************************************************************************/

void tcp_client_task(void *arg)

{

    cy_rslt_t result;

    whd_ssid_t ssid_data;

    int mbedtls_result;

    const char *ssid = WIFI_SSID;

    const char *key = WIFI_PASSWORD;

    struct netif *net;

    tcp_data_packet_t tcp_pkt_led_state;

    unsigned char * write_buff;

    size_t  len;

    /* mbed TLS structures

     */

    mbedtls_net_context server_fd;

    mbedtls_entropy_context entropy;

    mbedtls_ctr_drbg_context ctr_drbg;

    mbedtls_ssl_context ssl;

    mbedtls_ssl_config conf;

    mbedtls_x509_crt cacert;

    /* Variable to track the number of connection retries to the Wi-Fi AP specified

     * by WIFI_SSID macro */

    int conn_retries = 0;

    /* Initialize and start the tcpip_thread */

    tcpip_init(NULL, NULL) ;

    printf("LWiP TCP/IP stack initialized\n") ;

    /* Initialize the Wi-Fi Driver */

    result = cybsp_wifi_init_primary(&iface) ;

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Wi-Fi driver initialized \n") ;

    }

    else

    {

        printf("Wi-Fi Driver initialization failed!\n");

        CY_ASSERT(0);

    }

    /* The  below initializes RTC */

    mbedtls_init();

    /* Join the Wi-Fi AP */

    result = WHD_PENDING;

    ssid_data.length = strlen(ssid) ;

    memcpy(ssid_data.value, ssid, ssid_data.length) ;

    while(result != CY_RSLT_SUCCESS && conn_retries < MAX_CONNECTION_RETRIES)

    {

        result = whd_wifi_join(iface, &ssid_data, WHD_SECURITY_WPA2_AES_PSK,

                               (const uint8_t *)key, strlen(key)) ;

        conn_retries++;

    }

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Successfully joined Wi-Fi network '%s'\n", ssid) ;

    }

    else

    {

        printf("Failed to join Wi-Fi network '%s'\n", ssid);

        CY_ASSERT(0);

    }

    /* Add the Wi-Fi interface to the lwIP stack */

    result = add_interface_to_lwip(iface, NULL) ;

    if(result == CY_RSLT_SUCCESS)

    {

        printf("Wi-Fi interface added to TCP/IP stack\n");

    }

    else

    {

        printf("Failed to add Wi-Fi interface to lwIP stack!\n");

        CY_ASSERT(0);

    }

    /* Fetch the IP address assigned based on the added Wi-Fi interface */

    net = get_lwip_interface() ;

    while (true)

    {

        if (net->ip_addr.u_addr.ip4.addr != 0)

        {

            printf("IP Address %s assigned\n",

                    ip4addr_ntoa(&net->ip_addr.u_addr.ip4));

            break ;

        }

        vTaskDelay(RTOS_TASK_TICKS_TO_WAIT) ;

    }

    /* Initialize mbed TLS structures required to setup a TLS session */

    mbedtls_net_init( &server_fd );

    mbedtls_ssl_init( &ssl );

    mbedtls_ssl_config_init( &conf );

    mbedtls_x509_crt_init( &cacert );

    mbedtls_ctr_drbg_init( &ctr_drbg );

    /* Initialize and seed the entropy source */

    mbedtls_entropy_init( &entropy );

    if( ( mbedtls_result = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,

                               NULL, 0 ) ) != 0 )

    {

        printf( " Failed! mbedtls_ctr_drbg_seed returned %d\n", mbedtls_result );

        CY_ASSERT(0);

    }

    else

    {

        printf( "Success: The random number generator has been seeded\n");

    }

    /* Start the connection */

    printf( "Connecting to TCP Server /%s/%s...\n", TCP_SERVER_IP_ADDR, TCP_SERVER_PORT );

  

    if( ( mbedtls_result = mbedtls_net_connect( &server_fd, TCP_SERVER_IP_ADDR,

                                         TCP_SERVER_PORT, MBEDTLS_NET_PROTO_TCP ) ) != 0 )

    {

        printf( "Failed! mbedtls_net_connect returned %d\n", mbedtls_result );

        CY_ASSERT(0);

    }

    else

    {

        printf( "Successfully connected to TCP Server /%s/%s\n", TCP_SERVER_IP_ADDR, TCP_SERVER_PORT );

    }

    /* Configure the TLS layer */

    printf( "Setting up the SSL/TLS Layer...\n" );

    if( ( mbedtls_result = mbedtls_ssl_config_defaults( &conf,

                    MBEDTLS_SSL_IS_CLIENT,

                    MBEDTLS_SSL_TRANSPORT_STREAM,

                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )

    {

        printf( "Failed ! mbedtls_ssl_config_defaults returned %d\n\n", mbedtls_result );

        CY_ASSERT(0);

    }

    /* Set the authentication mode to determine how strict the certificates presented are

     *  checked */

    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );

#if DEBUG_LEVEL > 0

    mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);

    mbedtls_debug_set_threshold(DEBUG_LEVEL);

#endif

    /* Initialize certificates to authenticate the server */

    mbedtls_result = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) tcp_server_cert,

                              tcp_server_cert_len );

    if( mbedtls_result < 0 )

    {

        printf( "Failed!  mbedtls_x509_crt_parse returned -0x%x\n", -mbedtls_result );

        CY_ASSERT(0);

    }

    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );

    /* Set the random engine to be used for random number generation */

    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );

    /* Set up the SSL context for the TLS session */

    if( ( mbedtls_result = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )

    {

        printf( "Failed! mbedtls_ssl_setup returned %d\n", mbedtls_result );

    }

    /* Set the host name to check against the received server certificate */

    if( ( mbedtls_result = mbedtls_ssl_set_hostname( &ssl, TCP_SERVER_HOSTNAME ) ) != 0 )

    {

        printf( "Failed! mbedtls_ssl_set_hostname returned %d\n", mbedtls_result );

    }

   

    /* Set the input and output functions to use for the network traffic */

    mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );

    /* Perform the SSL/TLS Handshake */

    printf( "Performing the SSL/TLS handshake..." );

    while( ( mbedtls_result = mbedtls_ssl_handshake( &ssl ) ) != 0 )

    {

        if( mbedtls_result != MBEDTLS_ERR_SSL_WANT_READ && mbedtls_result != MBEDTLS_ERR_SSL_WANT_WRITE )

        {

            printf( "Failed! mbedtls_ssl_handshake returned -0x%x\n\n", -mbedtls_result );

        }

    }

    printf( " ok\n" );

    /* Verify the server certificate */

    printf( "Verifying peer X.509 certificate..." );

    if( ( mbedtls_result = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )

    {

        char vrfy_buf[512];

        printf( "Failed\n" );

        mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", mbedtls_result );

        printf( "%s\n", vrfy_buf );

        /* Close the connection to the server */

        printf("Closing the connection...\n");

        mbedtls_net_free( &server_fd );

        /* Free up the resources used by the TLS context */

        mbedtls_x509_crt_free( &cacert );

        mbedtls_ssl_free( &ssl );

        mbedtls_ssl_config_free( &conf );

        mbedtls_ctr_drbg_free( &ctr_drbg );

        mbedtls_entropy_free( &entropy );

        /* Calling assert here once server authentication fails.

         * Modify the code to handle the server authentication failure

         * to suit your application. */

        CY_ASSERT(0);

    }

    else

    {

        printf("ok\n\n");

        printf("===============================================================\n");

        printf( "TCP communication layer Secured!!!\n" );

        printf("===============================================================\n");

    }

    for(;;)

    {

        /* Block till TCP packet to be sent to the TCP server

         * is received on the queue */

        xQueueReceive(tcpClientQ, &tcp_pkt_led_state, portMAX_DELAY);

        write_buff = (unsigned char *)tcp_pkt_led_state.text;

        len = tcp_pkt_led_state.len;

        /* Send the LED status to the TCP server */

        do

        {

            mbedtls_result = mbedtls_ssl_write( &ssl, (unsigned char*)write_buff , len );

            if( mbedtls_result == MBEDTLS_ERR_SSL_WANT_READ || mbedtls_result == MBEDTLS_ERR_SSL_WANT_WRITE )

            {

                continue;

            }

            else if( mbedtls_result < 0 )

            {

                printf( "Failed! mbedtls_ssl_write returned %d\n", mbedtls_result );

                CY_ASSERT(0);

            }

            /* Continue the write operation if the data is partially sent.

             * Update the write_buffer and len so as to write the remaining data.

             */

            else if ( mbedtls_result < len )

            {

                write_buff += mbedtls_result;

                len -= mbedtls_result;

                continue;

            }

            else

            {

                /* Break out of the loop once the write operation is successful. */

                break;

            }

        }while(1);

        printf( "%d Bytes written: %s\n", tcp_pkt_led_state.len, tcp_pkt_led_state.text );

    }

}

#if DEBUG_LEVEL > 0

/**

* Debug callback for mbed TLS

* Just prints on the USB serial port

*/

static void my_debug(void *ctx, int level, const char *file, int line,

                     const char *str)

{

    const char *p, *basename;

    (void) ctx;

    /* Extract basename from file */

    for(p = basename = file; *p != '\0'; p++) {

        if(*p == '/' || *p == '\\') {

            basename = p + 1;

        }

    }

    printf("%s:%04d: |%d| %s", basename, line, level, str);

}

#endif

/* [] END OF FILE */

Hi,

Just wanted to update future people with the same issue that swapping main.c to the one above and changing network credentials.h to the one from github fixed my issue.

I am not sure what actually fixed it but I was having the same problem as the user above, bad SSL error (windows 10 x64, DELL XPS15 9560) using the proto 4343 kit.

Thanks for the fix

Sam

0 Likes

Yes. Finally got around to confirm. Lots of more output in the kit3prog terminal, but on the Python side, correct response:

$ python tcp_secure_server.py

==========================

TCP Secure Server

==========================

Listening on: 192.168.0.39:50007

('Incoming connection accepted: ', ('192.168.0.64', 52432))

('Apr 01 19:37:35 ', '192.168.0.64', ':', "'LED ON'")

('Apr 01 19:37:39 ', '192.168.0.64', ':', "'LED OFF'")

('Apr 01 19:37:42 ', '192.168.0.64', ':', "'LED ON'")

('Apr 01 19:37:43 ', '192.168.0.64', ':', "'LED OFF'")

('Apr 01 19:37:44 ', '192.168.0.64', ':', "'LED ON'")

0 Likes