This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF9160 Using MQTT with TLS

Hi everyone,

I am looking at using MQTT v3.1.1 with TLS 1.2, to send data to Azure IoT Hub.

I tested the MQTT Simple sample and it worked perfeclty. So I am modifying this project to enable TLS. To do so I followed those threads:

https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/enabling-and-testing-tls-in-mqtt_5f00_simple

https://github.com/joakimtoe/fw-nrfconnect-nrf/commit/36532a8ca60bf7139a988b5cbb4e6cb47948a9fa#diff-607096fd76f1fd14e4c9453aa1dc8fd3

https://devzone.nordicsemi.com/f/nordic-q-a/44921/nrf9160-tls-and-mqtt

https://devzone.nordicsemi.com/f/nordic-q-a/49339/implementing-tls-with-mqtt-in-nrf9160

Right now I am able to create the TLS socket but I am stucked at the next step which is the connection step. 

When defining  tls_config->peer_verify = 2; I got back ERROR: mqtt_connect -45.

And when I define it to 0 or 1 there is no response, as if the nRF9160 is stucked somewhere.

My log is the following for peer_verify=2. It is the same for 0/1, but without the error code.

00> ***** Booting Zephyr OS build v2.0.99-ncs1 *****
00> 
00> The MQTT simple sample started
00> 
00> Deleting certs sec_tag: 2
00> 
00> nrf_inbuilt_key_delete(2, 0) => result=0
00> 
00> Deleting certs sec_tag: 2
00> 
00> nrf_inbuilt_key_delete(2, 1) => result=0
00> 
00> Deleting certs sec_tag: 2
00> 
00> nrf_inbuilt_key_delete(2, 2) => result=0
00> 
00> Deleting certs sec_tag: 2
00> 
00> nrf_inbuilt_key_delete(2, 3) => result=2
00> 
00> Deleting certs sec_tag: 2
00> 
00> nrf_inbuilt_key_delete(2, 4) => result=2
00> 
00> Write ca certs sec_tag: 2
00> 
00> Write private cert sec_tag: 2
00> 
00> Write public cert sec_tag: 2
00> 
00> err_provision = 0
00> 
00> LTE Link Connecting ...
00> 
00> LTE Link Connected!
00> 
00> IPv4 Address found 13.95.15.251
00> 
00> ERROR: mqtt_connect -45

It has to be noted that the certificates I used are working in an application on my computer. They are placed here in certificates.h and are using the right formatting.

In my project folder, my prof.conf file is the following:

#
# Copyright (c) 2019 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#
# General config
CONFIG_PRINTK=y
CONFIG_CONSOLE=y
CONFIG_LOG=y
CONFIG_SERIAL=y
CONFIG_STDOUT_CONSOLE=y

CONFIG_UART_CONSOLE=n
CONFIG_RTT_CONSOLE=y
CONFIG_HAS_SEGGER_RTT=y
CONFIG_USE_SEGGER_RTT=y

# Random Generator
CONFIG_TEST_RANDOM_GENERATOR=y

# Networking
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_SOCKETS_OFFLOAD=y
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y

# nRF Cloud
CONFIG_NRF_CLOUD_PROVISION_CERTIFICATES=y
#CONFIG_NRF_CLOUD=y

# Modem info
#CONFIG_MODEM_INFO=y

#TLS
CONFIG_SEC_TAG=2
CONFIG_PEER_VERIFY=2

# LTE link control
#CONFIG_POWER_OPTIMIZATION_ENABLE=n
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n

# BSD library
CONFIG_BSD_LIBRARY=y

# AT Host
CONFIG_UART_INTERRUPT_DRIVEN=y
CONFIG_AT_HOST_LIBRARY=y

# MQTT
CONFIG_MQTT_LIB=y
#CONFIG_MQTT_SOCKET_LIB=y
CONFIG_MQTT_LIB_TLS=y
#CONFIG_MQTT_MAX_PACKET_LENGTH=2048

# Application
#CONFIG_MQTT_PUB_TOPIC="/my/publish/topic"
#CONFIG_MQTT_SUB_TOPIC="/my/subscribe/topic"
CONFIG_MQTT_CLIENT_ID="mqtt_test"
CONFIG_MQTT_BROKER_HOSTNAME="test-aptus.azure-devices.net"
CONFIG_MQTT_BROKER_PORT=8883

CONFIG_PROVISION_CERTIFICATES=y
CONFIG_CERTIFICATES_FILE="certificates.h"

# Main thread
CONFIG_MAIN_THREAD_PRIORITY=7
CONFIG_MAIN_STACK_SIZE=4096

CONFIG_HEAP_MEM_POOL_SIZE=2048

The Kconfig file there is the following:

#
# Copyright (c) 2018 Nordic Semiconductor ASA
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#

menu "MQTT simple sample"

config PROVISION_CERTIFICATES
	bool "Provision of certificate"
	help
		Enable run-time provisioning of certificates from the
		certificates header file selected by using CERTIFICATES_FILE

config CERTIFICATES_FILE
	string "Certificates to use"
	depends on PROVISION_CERTIFICATES
	default "certificates.h"

config SEC_TAG
	int "Security tag to use for the connection"
	default 1

config PEER_VERIFY
    int "Peer verify parameter for mqtt_client"
    default 1
    help
        Set to 0 for VERIFY_NONE, 1 for VERIFY_OPTIONAL, and 2 for VERIFY_REQUIRED.

config MQTT_PUB_TOPIC
	string "MQTT publish topic"
	default "my/publish/topic"

config MQTT_SUB_TOPIC
	string "MQTT subscribe topic"
	default "my/subscribe/topic"

config MQTT_CLIENT_ID
	string "MQTT Client ID"
	default "my-client-id"

config MQTT_BROKER_HOSTNAME
	string "MQTT broker hostname"
	default "mqtt.eclipse.org"

config MQTT_BROKER_PORT
	int "MQTT broker port"
	default 1883

config MQTT_MESSAGE_BUFFER_SIZE
	int "MQTT message buffer size"
	default 128

config MQTT_PAYLOAD_BUFFER_SIZE
	int "MQTT payload buffer size"
	default 128

endmenu

menu "Zephyr Kernel"
source "$ZEPHYR_BASE/Kconfig.zephyr"
endmenu

And the main.c is :

/*
 * Copyright (c) 2018 Nordic Semiconductor ASA
 *
 * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
 */

#include <zephyr.h>
#include <stdio.h>
#include <uart.h>
#include <string.h>

#include <net/mqtt.h>
#include <net/socket.h>
#include <lte_lc.h>
#include <certificates.h>


#if defined(CONFIG_BSD_LIBRARY)
#include "nrf_inbuilt_key.h"
#endif

#include CONFIG_CERTIFICATES_FILE

#if defined(CONFIG_LWM2M_CARRIER)
#include <lwm2m_carrier.h>
#endif



//#define CONFIG_NRF_CLOUD_SEC_TAG 1
#define NRF_CLOUD_HOSTNAME CONFIG_MQTT_BROKER_HOSTNAME
//#define NRF_CLOUD_SEC_TAG  CONFIG_NRF_CLOUD_SEC_TAG

static sec_tag_t sec_tag_list[] = {CONFIG_SEC_TAG};

/* Buffers for MQTT client. */
static u8_t rx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE];
static u8_t tx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE];
static u8_t payload_buf[CONFIG_MQTT_PAYLOAD_BUFFER_SIZE];

/* The mqtt client struct */
static struct mqtt_client client;

/* MQTT Broker details. */
static struct sockaddr_storage broker;

/* Connected flag */
static bool connected;

/* File descriptor */
static struct pollfd fds;

#if defined(CONFIG_BSD_LIBRARY)

/**@brief Recoverable BSD library error. */
void bsd_recoverable_error_handler(uint32_t err)
{
	printk("bsdlib recoverable error: %u\n", (unsigned int)err);
}

/**@brief Irrecoverable BSD library error. */
void bsd_irrecoverable_error_handler(uint32_t err)
{
	printk("bsdlib irrecoverable error: %u\n", err);

	__ASSERT_NO_MSG(false);
}

#endif /* defined(CONFIG_BSD_LIBRARY) */



/**@brief Function to print strings without null-termination
 */
static void data_print(u8_t *prefix, u8_t *data, size_t len)
{
	char buf[len + 1];
	memcpy(buf, data, len);
	buf[len] = 0;
	printk("%s%s\n", prefix, buf);
}

/**@brief Function to publish data on the configured topic
 */
static int data_publish(struct mqtt_client *c, enum mqtt_qos qos,
	u8_t *data, size_t len)
{
	struct mqtt_publish_param param;

	param.message.topic.qos = qos;
	param.message.topic.topic.utf8 = CONFIG_MQTT_PUB_TOPIC;
	param.message.topic.topic.size = strlen(CONFIG_MQTT_PUB_TOPIC);
	param.message.payload.data = data;
	param.message.payload.len = len;
	param.message_id = sys_rand32_get();
	param.dup_flag = 0;
	param.retain_flag = 0;

	data_print("Publishing: ", data, len);
	printk("to topic: %s len: %u\n",
		CONFIG_MQTT_PUB_TOPIC,
		(unsigned int)strlen(CONFIG_MQTT_PUB_TOPIC));

	return mqtt_publish(c, &param);
}

/**@brief Function to subscribe to the configured topic
 */
static int subscribe(void)
{
	struct mqtt_topic subscribe_topic = {
		.topic = {
			.utf8 = CONFIG_MQTT_SUB_TOPIC,
			.size = strlen(CONFIG_MQTT_SUB_TOPIC)
		},
		.qos = MQTT_QOS_1_AT_LEAST_ONCE
	};

	const struct mqtt_subscription_list subscription_list = {
		.list = &subscribe_topic,
		.list_count = 1,
		.message_id = 1234
	};

	printk("Subscribing to: %s len %u\n", CONFIG_MQTT_SUB_TOPIC,
		(unsigned int)strlen(CONFIG_MQTT_SUB_TOPIC));

	return mqtt_subscribe(&client, &subscription_list);
}

/**@brief Function to read the published payload.
 */
static int publish_get_payload(struct mqtt_client *c, size_t length)
{
	u8_t *buf = payload_buf;
	u8_t *end = buf + length;

	if (length > sizeof(payload_buf)) {
		return -EMSGSIZE;
	}

	while (buf < end) {
		int ret = mqtt_read_publish_payload(c, buf, end - buf);

		if (ret < 0) {
			int err;

			if (ret != -EAGAIN) {
				return ret;
			}

			printk("mqtt_read_publish_payload: EAGAIN\n");

			err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE));
			if (err > 0 && (fds.revents & POLLIN) == POLLIN) {
				continue;
			} else {
				return -EIO;
			}
		}
		if (ret == 0) {
			return -EIO;
		}

		buf += ret;
	}

	return 0;
}

/**@brief MQTT client event handler
 */
void mqtt_evt_handler(struct mqtt_client *const c,
		      const struct mqtt_evt *evt)
{
	int err;

	switch (evt->type) {
	case MQTT_EVT_CONNACK:
		if (evt->result != 0) {
			printk("MQTT connect failed %d\n", evt->result);
			break;
		}

		connected = true;
		printk("[%s:%d] MQTT client connected!\n", __func__, __LINE__);
		subscribe();
		break;

	case MQTT_EVT_DISCONNECT:
		printk("[%s:%d] MQTT client disconnected %d\n", __func__,
		       __LINE__, evt->result);

		connected = false;
		break;

	case MQTT_EVT_PUBLISH: {
		const struct mqtt_publish_param *p = &evt->param.publish;

		printk("[%s:%d] MQTT PUBLISH result=%d len=%d\n", __func__,
		       __LINE__, evt->result, p->message.payload.len);
		err = publish_get_payload(c, p->message.payload.len);
		if (err >= 0) {
			data_print("Received: ", payload_buf,
				p->message.payload.len);
			/* Echo back received data */
			data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE,
				payload_buf, p->message.payload.len);
		} else {
			printk("mqtt_read_publish_payload: Failed! %d\n", err);
			printk("Disconnecting MQTT client...\n");

			err = mqtt_disconnect(c);
			if (err) {
				printk("Could not disconnect: %d\n", err);
			}
		}
	} break;

	case MQTT_EVT_PUBACK:
		if (evt->result != 0) {
			printk("MQTT PUBACK error %d\n", evt->result);
			break;
		}

		printk("[%s:%d] PUBACK packet id: %u\n", __func__, __LINE__,
				evt->param.puback.message_id);
		break;

	case MQTT_EVT_SUBACK:
		if (evt->result != 0) {
			printk("MQTT SUBACK error %d\n", evt->result);
			break;
		}

		printk("[%s:%d] SUBACK packet id: %u\n", __func__, __LINE__,
				evt->param.suback.message_id);
		break;

	default:
		printk("[%s:%d] default: %d\n", __func__, __LINE__,
				evt->type);
		break;
	}
}

/**@brief Resolves the configured hostname and
 * initializes the MQTT broker structure
 */
static void broker_init(void)
{
	int err;
	struct addrinfo *result;
	struct addrinfo *addr;
	struct addrinfo hints = {
		.ai_family = AF_INET,
		.ai_socktype = SOCK_STREAM
	};

	err = getaddrinfo(CONFIG_MQTT_BROKER_HOSTNAME, NULL, &hints, &result);
	if (err) {
		printk("ERROR: getaddrinfo failed %d\n", err);

		return;
	}

	addr = result;
	err = -ENOENT;

	/* Look for address of the broker. */
	while (addr != NULL) {
		/* IPv4 Address. */
		if (addr->ai_addrlen == sizeof(struct sockaddr_in)) {
			struct sockaddr_in *broker4 =
				((struct sockaddr_in *)&broker);
			char ipv4_addr[NET_IPV4_ADDR_LEN];

			broker4->sin_addr.s_addr =
				((struct sockaddr_in *)addr->ai_addr)
				->sin_addr.s_addr;
			broker4->sin_family = AF_INET;
			broker4->sin_port = htons(CONFIG_MQTT_BROKER_PORT);

			inet_ntop(AF_INET, &broker4->sin_addr.s_addr,
				  ipv4_addr, sizeof(ipv4_addr));
			printk("IPv4 Address found %s\n", ipv4_addr);

			break;
		} else {
			printk("ai_addrlen = %u should be %u or %u\n",
				(unsigned int)addr->ai_addrlen,
				(unsigned int)sizeof(struct sockaddr_in),
				(unsigned int)sizeof(struct sockaddr_in6));
		}

		addr = addr->ai_next;
		break;
	}

	/* Free the address. */
	freeaddrinfo(result);
}

/**@brief Initialize the MQTT client structure
 */
static void client_init(struct mqtt_client *client)
{
	mqtt_client_init(client);

	broker_init();

	/* MQTT client configuration */
	client->broker = &broker;
	client->evt_cb = mqtt_evt_handler;
	client->client_id.utf8 = (u8_t *)CONFIG_MQTT_CLIENT_ID;
	client->client_id.size = strlen(CONFIG_MQTT_CLIENT_ID);
        printk("clientId %s \n", CONFIG_MQTT_CLIENT_ID);
	client->password = NULL;
	client->user_name = NULL;
	client->protocol_version = MQTT_VERSION_3_1_1;

	/* MQTT buffers configuration */
	client->rx_buf = rx_buffer;
	client->rx_buf_size = sizeof(rx_buffer);
	client->tx_buf = tx_buffer;
	client->tx_buf_size = sizeof(tx_buffer);

	/* MQTT transport configuration */
        #if defined(CONFIG_MQTT_LIB_TLS)
          struct mqtt_sec_config *tls_config = &client->transport.tls.config;
    
          client->transport.type = MQTT_TRANSPORT_SECURE;
    
          tls_config->peer_verify = 2;
          tls_config->cipher_count = 0;
          tls_config->cipher_list = NULL;
          tls_config->sec_tag_count = ARRAY_SIZE(sec_tag_list);
          tls_config->sec_tag_list = sec_tag_list;
          tls_config->hostname = CONFIG_MQTT_BROKER_HOSTNAME;
          #else /* MQTT transport configuration */
          client->transport.type = MQTT_TRANSPORT_NON_SECURE;
          #endif /* defined(CONFIG_MQTT_LIB_TLS) */
}

/**@brief Initialize the file descriptor structure used by poll.
 */
static int fds_init(struct mqtt_client *c)
{
	if (c->transport.type == MQTT_TRANSPORT_NON_SECURE) {
		fds.fd = c->transport.tcp.sock;
	} else {
#if defined(CONFIG_MQTT_LIB_TLS)
		fds.fd = c->transport.tls.sock;
#else
		return -ENOTSUP;
#endif
	}

	fds.events = POLLIN;

	return 0;
}

/**@brief Configures modem to provide LTE link. Blocks until link is
 * successfully established.
 */
static void modem_configure(void)
{
#if defined(CONFIG_LTE_LINK_CONTROL)
	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
		/* Do nothing, modem is already turned on
		 * and connected.
		 */
	} else {
#if defined(CONFIG_LWM2M_CARRIER)
		/* Wait for the LWM2M_CARRIER to configure the modem and
		 * start the connection.
		 */
		printk("Waitng for carrier registration...\n");
		k_sem_take(&carrier_registered, K_FOREVER);
		printk("Registered!\n");
#else /* defined(CONFIG_LWM2M_CARRIER) */
		int err;
		printk("LTE Link Connecting ...\n");
		err = lte_lc_init_and_connect();
		__ASSERT(err == 0, "LTE link could not be established.");
		printk("LTE Link Connected!\n");
#endif /* defined(CONFIG_LWM2M_CARRIER) */
	}
#endif /* defined(CONFIG_LTE_LINK_CONTROL) */
}

/* Provisions root CA certificate using nrf_inbuilt_key API */
static int provision_certificate(void)
{
#if defined(CONFIG_PROVISION_CERTIFICATES)
#if defined(CONFIG_BSD_LIBRARY)
	{
		int err;

		/* Delete certificates */
		nrf_sec_tag_t sec_tag = (nrf_sec_tag_t) sec_tag_list[0];

		for (nrf_key_mgnt_cred_type_t type = 0; type < 5; type++) {
			printk("Deleting certs sec_tag: %d\n", sec_tag);
			err = nrf_inbuilt_key_delete(sec_tag, type);
			printk("nrf_inbuilt_key_delete(%u, %d) => result=%d\n",
				sec_tag, type, err);
		}

#if defined(CA_CERTIFICATE)
		/* Provision CA Certificate. */
		printk("Write ca certs sec_tag: %d\n", sec_tag);
		err = nrf_inbuilt_key_write(sec_tag,
			NRF_KEY_MGMT_CRED_TYPE_CA_CHAIN,
			CA_CERTIFICATE,
			strlen(CA_CERTIFICATE));
		if (err) {
			printk("CA_CERTIFICATE err: %d\n", err);
			return err;
		}
#endif
#if defined (CLIENT_PRIVATE_KEY)
		/* Provision Private Certificate. */
		printk("Write private cert sec_tag: %d\n", sec_tag);
		err = nrf_inbuilt_key_write(
			sec_tag,
			NRF_KEY_MGMT_CRED_TYPE_PRIVATE_CERT,
			CLIENT_PRIVATE_KEY,
			strlen(CLIENT_PRIVATE_KEY));
		if (err) {
			printk("CLIENT_PRIVATE_KEY err: %d\n", err);
			return err;
		}
#endif
#if defined(CLIENT_PUBLIC_CERTIFICATE)
		/* Provision Public Certificate. */
		printk("Write public cert sec_tag: %d\n", sec_tag);
		err = nrf_inbuilt_key_write(
			sec_tag,
			NRF_KEY_MGMT_CRED_TYPE_PUBLIC_CERT,
			CLIENT_PUBLIC_CERTIFICATE,
			strlen(CLIENT_PUBLIC_CERTIFICATE));
		if (err) {
			printk("CLIENT_PUBLIC_CERTIFICATE err: %d\n",err);
			return err;
		}
	}
#endif
#else
	{
		int err;
		err = tls_credential_add(CONFIG_SEC_TAG,
			TLS_CREDENTIAL_CA_CERTIFICATE,
			NRF_CLOUD_CA_CERTIFICATE,
			sizeof(NRF_CLOUD_CA_CERTIFICATE));
		if (err < 0) {
			printk("Failed to register ca certificate: %d\n",err);
			return err;
		}
		err = tls_credential_add(CONFIG_SEC_TAG,
			TLS_CREDENTIAL_PRIVATE_KEY,
			NRF_CLOUD_CLIENT_PRIVATE_KEY,
			sizeof(NRF_CLOUD_CLIENT_PRIVATE_KEY));
		if (err < 0) {
			printk("Failed to register private key: %d\n",err);
			return err;
		}
		err = tls_credential_add(CONFIG_SEC_TAG,
			TLS_CREDENTIAL_SERVER_CERTIFICATE,
			NRF_CLOUD_CLIENT_PUBLIC_CERTIFICATE,
			sizeof(NRF_CLOUD_CLIENT_PUBLIC_CERTIFICATE));
		if (err < 0) {
			printk("Failed to register public certificate: %d\n",err);
			return err;
		}

	}
#endif /* defined(CONFIG_BSD_LIBRARY) */
#endif /* defined(CONFIG_PROVISION_CERTIFICATES) */

	return 0;
}

void main(void)
{
	int err;

	printk("The MQTT simple sample started\n");

        int err_provision = provision_certificate();
        if (err_provision != 0) {
          printk("ERROR: nct_provision failure %d\n", err_provision);
          return;
        }
        printk("err_provision = %d\n", err_provision);

	modem_configure();

	client_init(&client);

	err = mqtt_connect(&client);
	if (err != 0) {
		printk("ERROR: mqtt_connect %d\n", err);
		return;
	}
        printk("\n CONNECTED\n");

	err = fds_init(&client);
	if (err != 0) {
		printk("ERROR: fds_init %d\n", err);
		return;
	}
        printk("FDS init done \n");
	while (1) {
		err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE));
		if (err < 0) {
			printk("ERROR: poll %d\n", errno);
			break;
		}

		err = mqtt_live(&client);
		if (err != 0) {
			printk("ERROR: mqtt_live %d\n", err);
			break;
		}

		if ((fds.revents & POLLIN) == POLLIN) {
			err = mqtt_input(&client);
			if (err != 0) {
				printk("ERROR: mqtt_input %d\n", err);
				break;
			}
		}

		if ((fds.revents & POLLERR) == POLLERR) {
			printk("POLLERR\n");
			break;
		}

		if ((fds.revents & POLLNVAL) == POLLNVAL) {
			printk("POLLNVAL\n");
			break;
		}
	}

	printk("Disconnecting MQTT client...\n");

	err = mqtt_disconnect(&client);
	if (err) {
		printk("Could not disconnect MQTT client. Error: %d\n", err);
	}
}

Looking at errno.h, I understand the error -45 as "Operation not supported on socket".

But which operation is not supported ?

How can I fix this ? And why is it hanging out when I use peer-verify=0 or 1 ?

Thank you in advance

Parents
  • Hi,

     

    Q1: How large are your certificates?

    They are casted from const to non-const, meaning that they'll be stacked. Increasing the main stack size might be beneficial (double the heap as well, testing purposes):

    CONFIG_MAIN_STACK_SIZE=8192
    CONFIG_HEAP_MEM_POOL_SIZE=4096

     

    Q2: Do you chain your CA root? Ie: having one root auth. certificate and a second one? The .peer_verify value of 2 indicates that you shall verify the hostname, while 1 states optional, and 0 is do not verify.

    If your broker requires key-pair + CA, you need to provide a CA to the host you're connecting to + a root CA (ie: a chained CA certificate)

    In C format, it'll look like this: https://devzone.nordicsemi.com/f/nordic-q-a/55393/nrf9160-adding-intermediate-certificates-to-the-tls-engine/225697#225697

     

    Q3: When you're setting .peer_verify=1, does it hang forever? Does it print anything? Have you checked if the firmware is stuck somewhere?

     

    Q4: Have you checked if TLS section is working, by for instance connecting to mosquitto? You can connect to mosquitto, https://test.mosquitto.org/, on port 8883 without any certificates to see if your TLS setup itself is working. In this case, you can set peer_verify=1, and tls_config->sec_tag_count = 0 , tls_config->sec_tag_list = NULL

     

    Kind regards,

    HĂĄkon

  • Hi Håkon,

    Q1 : I have change the main stack size and memory pool size as you showed. And the issue is stil there

    Q2: I have the Root CA, the Client CA and the Client Key in a header file certificates.h. It looks like this :

    #define CLIENT_PRIVATE_KEY \
    "-----BEGIN RSA PRIVATE KEY-----\n" \
    "MIIEowIBAAKCAQEAmHoUn2xBQf9+9QQYyxZZtsmJYw/N5z1cO4yt6S2bpIeynfU8\n" \
    ...
    "dP7W0GsXt3aYNSdfTjcp7cw62gEvJ64BI+FKxzpbocnetWCeyUaB\n" \
    "-----END RSA PRIVATE KEY-----\n"
    
    
    
    #define CLIENT_PUBLIC_CERTIFICATE \
    "-----BEGIN CERTIFICATE-----\n" \
    "MIICvDCCAaSgAwIBAgIEAQhZ6DANBgkqhkiG9w0BAQsFADAQMQ4wDAYDVQQDDAVU\n" \
    ...
    "o5ym/Cy1VLs28we6Uk3FgbSQy8aBHV8JplbapPaLYQ8=\n" \
    "-----END CERTIFICATE-----\n"
    
    
    
    #define CA_CERTIFICATE \
    "-----BEGIN CERTIFICATE-----\n" \
    "MIICtjCCAZ6gAwIBAgIJAIjqRXrEC+UGMA0GCSqGSIb3DQEBCwUAMBAxDjAMBgNV\n" \
    ...
    "xCYJngfVEThKYGTCyCC09GsG6uWcRDfnrwo=\n" \
    "-----END CERTIFICATE-----\n"
    

    I now answer first Q4 as I did it before Q3 and it showed me interesting things 

    Q4: Yes I can connect to mosquitto and wait for the event with the modification you showed. The first time I got the mqtt event handler being triggered with :

     

    [mqtt_evt_handler:169] MQTT client connected!
    [mqtt_evt_handler:219] SUBACK packet id: 1234

    But not the other times. I changed the clien Id and restarted the the DK but nothing appears. So I added a printk call after the poll function and I got :

     The MQTT simple sample started
    
    err_provision = 0
    
    LTE Link Connecting ...
    
    LTE Link Connected!
     
    IPv4 Address found 5.196.95.208
     
    After Poll

    I print "After Poll" just after the poll function

    Q3 : Now I am back with my DNS, and the certificates. I am testing with peer-verify =1and I am looking at were it is hanging out.

    I have left the "After Poll" printk call, and I have added a "CONNECTED" printk call after the mqtt_connect function and a "FDS init done" after the fds_init function like here :

    err = mqtt_connect(&client);
    	if (err != 0) {
    		printk("ERROR: mqtt_connect %d\n", err);
    		return;
    	}
            printk("\n CONNECTED\n");
    
    	err = fds_init(&client);
    	if (err != 0) {
    		printk("ERROR: fds_init %d\n", err);
    		return;
    	}
            printk("FDS init done \n");
    	while (1) {
    		err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE));
    		if (err < 0) {
    			printk("ERROR: poll %d\n", errno);
    			break;
    		}
                    printk("After Poll");

    And I got this : 

    ***** Booting Zephyr OS build v2.0.99-ncs1 *****
    The MQTT simple sample started
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 0) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 1) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 2) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 3) => result=2
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 4) => result=2
    Write ca certs sec_tag: 2
    Write private cert sec_tag: 2
    Write public cert sec_tag: 2
    err_provision = 0
    LTE Link Connecting ...
    LTE Link Connected!
    IPv4 Address found 13.95.15.251
    clientId mqtt_test 
    
     CONNECTED
    FDS init done 
    After poll
    

    So it seems the connection is successfull but that I got no response from server like with the test on mosquitto

  • Hi,

     

    The mqtt_simple sample will just connect, and subscribe to a given topic. Not much more will happen there, unless you publish to the specific topic that the nrf is subscribed to.

    Poll will stand there for CONFIG_MQTT_KEEPALIVE seconds before sending a keep-alive, so it might not do much unless you wait 60 seconds (default value), where then should print "after poll" again.

    I did this exact setup with mqtt_simple (.peer_verify = 1 for testing purposes), connecting to mqtt.eclipse.org port 8883, and I'm not seeing the same failure as you.

    Note that I am not testing with test.mosquitto.org. It seems to be down? I get a timed out request back when I try to connect to port 8883, which I also get if I use mosquitto_sub on my PC.

     

    Have you removed the prints in the mqtt_evt_handler() ? You do not seem to get any mqtt-related prints from that one.

    PS: I see that you're using ncs v1.1.0. We have released v1.2.0, but this sample should work on both.

     

    Kind regards,

    HĂĄkon

Reply
  • Hi,

     

    The mqtt_simple sample will just connect, and subscribe to a given topic. Not much more will happen there, unless you publish to the specific topic that the nrf is subscribed to.

    Poll will stand there for CONFIG_MQTT_KEEPALIVE seconds before sending a keep-alive, so it might not do much unless you wait 60 seconds (default value), where then should print "after poll" again.

    I did this exact setup with mqtt_simple (.peer_verify = 1 for testing purposes), connecting to mqtt.eclipse.org port 8883, and I'm not seeing the same failure as you.

    Note that I am not testing with test.mosquitto.org. It seems to be down? I get a timed out request back when I try to connect to port 8883, which I also get if I use mosquitto_sub on my PC.

     

    Have you removed the prints in the mqtt_evt_handler() ? You do not seem to get any mqtt-related prints from that one.

    PS: I see that you're using ncs v1.1.0. We have released v1.2.0, but this sample should work on both.

     

    Kind regards,

    HĂĄkon

Children
  • Hi Håkon,

    I also got the time out if I try with test.mosquito.org. Yes it seems to be down

    I did not remove the printk calls from the mqtt_evt_handler. I also tried with mqtt.eclipse.org and I have the same thing : the mqtt_event handler is never called

  • I tested with both v1.1.0 and v1.2.0, and get this behavior:

    ***** Booting Zephyr OS build v2.0.99-ncs1 *****
    The MQTT simple sample started
    LTE Link Connecting ...
    +CEREG: 2,"76C1","014ACE00",7,0,0,"11100000","11100000"
    +CEREG: 1,"76C1","014ACE00",7,,,"11100000","00001111"
    LTE Link Connected!
    IPv4 Address found 137.135.83.217
    [mqtt_evt_handler:190] MQTT client connected!
    Subscribing to: my/subscribe/topic len 18
    After Poll
    [mqtt_evt_handler:240] SUBACK packet id: 1234
    After Poll

    Here's my source for reference: mqtt_simple.zip

    Please note that the .peer_verify shall be '2' in an actual product, as we are currently not performing hostname verification.

     

    Could you test this and see if you still do not get connected and suback callback?

     

    Kind regards,

    HĂĄkon

  • Hi Håkon,,

    I have totally removed and reinstalled the ncs/nrf repo.

    With your code and with my code with TLS (no certificates) and with hostname : test.mosquitto.org, I got the same log as you, with the mqtt_event_handler working.

    Now with my certificates for Azure IoT Hub :

    - If peer_verify=2 : I got ERROR: mqtt_connect -45 when I try to connect (both with J-Link RTT Viewer and the debug terminal)

    - If peer_verify= 1 : In my J-Link RTT Viewer, I have nothing after the "IPv4 Address found 13.95.15.251" statement. But when I use the debug terminal from Segger Embedded Studio, I got :

    IPv4 Address found 13.95.15.251
    After Poll
    mqtt event handler called 
    MQTT connect failed 3
    After Poll
    mqtt event handler called 
    MQTT connect failed -61
    ERROR: mqtt_input -57
    Disconnecting MQTT client...
    Could not disconnect MQTT client. Error: -57

    The only differences between my Azure Mqtt code and the test on mosquitto is that in prj.conf I added :

    CONFIG_MQTT_CLIENT_ID="mqtt_test"
    CONFIG_MQTT_BROKER_HOSTNAME="test-aptus.azure-devices.net"
    
    CONFIG_PROVISION_CERTIFICATES=y
    CONFIG_CERTIFICATES_FILE="certificates.h"

    And in my main.c, I changed the configuration to :

              tls_config->peer_verify = 2; // or 1
              tls_config->cipher_count = 0;
              tls_config->cipher_list = NULL;
              tls_config->sec_tag_count = ARRAY_SIZE(sec_tag_list); //0;
              tls_config->sec_tag_list = sec_tag_list; //NULL;
              tls_config->hostname = CONFIG_MQTT_BROKER_HOSTNAME;

  • Hi,

      

    thomallain said:
    If peer_verify=2 : I got ERROR: mqtt_connect -45 when I try to connect (both with J-Link RTT Viewer and the debug terminal)

     This makes sense if you do not have a root CA to verify the hostname against.

     

    thomallain said:
    If peer_verify= 1 : In my J-Link RTT Viewer, I have nothing after the "IPv4 Address found 13.95.15.251" statement. But when I use the debug terminal from Segger Embedded Studio, I got :

    -57 -> errno.h::ENOTCONN

    -61 -> errno.h::ECONNREFUSED.

     

    Have you tried to connect using your generated certificates on a PC, using mosquitto_sub / mosquitto_pub, to see if you connect successfully ?

    There's a guide on using certificates here and on stack overflow:

    http://www.steves-internet-guide.com/mosquitto_pub-sub-clients/

    https://stackoverflow.com/questions/34491799/secured-ssl-connection-with-mosquitto-broker

     

    Kind regards,

    HĂĄkon

  • Hi Håkon,

    I have followed what you said, and I have been able to connect to Azure IoT Hub both with my computer and the nRF9160.

    First I look at using paho_mqtt to connect to Azure IoT Hub. I found out that I had to use a username looking like this : hostname/deviceId/API_version. I also found out that as my certificates were self-signed I could not use the certificates verification, so I had to remove it (for the nRF9160 it means peer_verify=0)

    Here is my python code:

    from paho.mqtt import client as mqtt
    import ssl
    import os
    import time
    
    path_to_root_cert = "test2_cert.pem"
    cert_file = "mqttTest_cert.pem"
    key_file = "mqttTest_key.pem"
    
    device_id = "mqtt_test"
    iot_hub_name = "test-aptus"
    
    def on_connect(client, userdata, flags, rc):
        print("Device connected with result code: " + str(rc))
    
    def on_disconnect(client, userdata, rc):
        print("Device disconnected with result code: " + str(rc))
    
    def on_publish(client, userdata, mid):
        print("Device sent message")
    
    client = mqtt.Client(client_id=device_id, protocol=mqtt.MQTTv311)
    
    client.on_connect = on_connect
    client.on_disconnect = on_disconnect
    client.on_publish = on_publish
    
    # Set the username but not the password on your client
    client.username_pw_set(username=iot_hub_name+".azure-devices.net/" +
                           device_id + "/?api-version=2018-06-30", password=None)
    
    # Set the certificate and key paths on your client
    
    client.tls_set(ca_certs=path_to_root_cert, certfile=cert_file, keyfile=key_file,
                   cert_reqs=ssl.CERT_NONE, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None)
    # Connect as before
    client.connect(iot_hub_name+".azure-devices.net", port=8883)
    
    client.loop_start()
    client.publish("devices/" + device_id + "/messages/events/", "{id=123}", qos=1)
    time.sleep(10) # wait
    client.loop_stop() #stop the loop

    I then added those changes to my nRF9160 project, and I added a publish call to sent a message to Azure.

    Here is my main :

    /*
     * Copyright (c) 2018 Nordic Semiconductor ASA
     *
     * SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
     */
    
    #include <zephyr.h>
    #include <stdio.h>
    #include <uart.h>
    #include <string.h>
    
    #include <net/mqtt.h>
    #include <net/socket.h>
    #include <lte_lc.h>
    #include <certificates.h>
    
    #if defined(CONFIG_BSD_LIBRARY)
    #include "nrf_inbuilt_key.h"
    #endif
    
    //#include CONFIG_CERTIFICATES_FILE
    
    #if defined(CONFIG_LWM2M_CARRIER)
    #include <lwm2m_carrier.h>
    #endif
    
    #define MQTT_USERNAME "test-aptus.azure-devices.net/mqtt_test/?api-version=2018-06-30"
    struct mqtt_utf8 name;
    
    //#define CONFIG_NRF_CLOUD_SEC_TAG 1
    #define NRF_CLOUD_HOSTNAME CONFIG_MQTT_BROKER_HOSTNAME
    //#define NRF_CLOUD_SEC_TAG  CONFIG_NRF_CLOUD_SEC_TAG
    
    static sec_tag_t sec_tag_list[] = {CONFIG_SEC_TAG};
    
    /* Buffers for MQTT client. */
    static u8_t rx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE];
    static u8_t tx_buffer[CONFIG_MQTT_MESSAGE_BUFFER_SIZE];
    static u8_t payload_buf[CONFIG_MQTT_PAYLOAD_BUFFER_SIZE];
    
    /* The mqtt client struct */
    static struct mqtt_client client;
    
    /* MQTT Broker details. */
    static struct sockaddr_storage broker;
    
    /* Connected flag */
    static bool connected;
    
    /* File descriptor */
    static struct pollfd fds;
    
    #if defined(CONFIG_BSD_LIBRARY)
    
    /**@brief Recoverable BSD library error. */
    void bsd_recoverable_error_handler(uint32_t err)
    {
    	printk("bsdlib recoverable error: %u\n", (unsigned int)err);
    }
    
    /**@brief Irrecoverable BSD library error. */
    void bsd_irrecoverable_error_handler(uint32_t err)
    {
    	printk("bsdlib irrecoverable error: %u\n", err);
    
    	__ASSERT_NO_MSG(false);
    }
    
    #endif /* defined(CONFIG_BSD_LIBRARY) */
    
    
    
    /**@brief Function to print strings without null-termination
     */
    static void data_print(u8_t *prefix, u8_t *data, size_t len)
    {
    	char buf[len + 1];
    	memcpy(buf, data, len);
    	buf[len] = 0;
    	printk("%s%s\n", prefix, buf);
    }
    
    /**@brief Function to publish data on the configured topic
     */
    static int data_publish(struct mqtt_client *c, enum mqtt_qos qos,
    	u8_t *data, size_t len)
    {
    	struct mqtt_publish_param param;
    
    	param.message.topic.qos = qos;
    	param.message.topic.topic.utf8 = CONFIG_MQTT_PUB_TOPIC;
    	param.message.topic.topic.size = strlen(CONFIG_MQTT_PUB_TOPIC);
    	param.message.payload.data = data;
    	param.message.payload.len = len;
    	param.message_id = sys_rand32_get();
    	param.dup_flag = 0;
    	param.retain_flag = 0;
    
    	data_print("Publishing: ", data, len);
    	printk("to topic: %s len: %u\n",
    		CONFIG_MQTT_PUB_TOPIC,
    		(unsigned int)strlen(CONFIG_MQTT_PUB_TOPIC));
    
    	return mqtt_publish(c, &param);
    }
    
    /**@brief Function to subscribe to the configured topic
     */
    static int subscribe(void)
    {
    	struct mqtt_topic subscribe_topic = {
    		.topic = {
    			.utf8 = CONFIG_MQTT_SUB_TOPIC,
    			.size = strlen(CONFIG_MQTT_SUB_TOPIC)
    		},
    		.qos = MQTT_QOS_1_AT_LEAST_ONCE
    	};
    
    	const struct mqtt_subscription_list subscription_list = {
    		.list = &subscribe_topic,
    		.list_count = 1,
    		.message_id = 1234
    	};
    
    	printk("Subscribing to: %s len %u\n", CONFIG_MQTT_SUB_TOPIC,
    		(unsigned int)strlen(CONFIG_MQTT_SUB_TOPIC));
    
    	return mqtt_subscribe(&client, &subscription_list);
    }
    
    /**@brief Function to read the published payload.
     */
    static int publish_get_payload(struct mqtt_client *c, size_t length)
    {
    	u8_t *buf = payload_buf;
    	u8_t *end = buf + length;
    
    	if (length > sizeof(payload_buf)) {
    		return -EMSGSIZE;
    	}
    
    	while (buf < end) {
    		int ret = mqtt_read_publish_payload(c, buf, end - buf);
    
    		if (ret < 0) {
    			int err;
    
    			if (ret != -EAGAIN) {
    				return ret;
    			}
    
    			printk("mqtt_read_publish_payload: EAGAIN\n");
    
    			err = poll(&fds, 1, K_SECONDS(CONFIG_MQTT_KEEPALIVE));
    			if (err > 0 && (fds.revents & POLLIN) == POLLIN) {
    				continue;
    			} else {
    				return -EIO;
    			}
    		}
    		if (ret == 0) {
    			return -EIO;
    		}
    
    		buf += ret;
    	}
    
    	return 0;
    }
    
    /**@brief MQTT client event handler
     */
    void mqtt_evt_handler(struct mqtt_client *const c,
    		      const struct mqtt_evt *evt)
    {
    	int err;
    	printk("mqtt event handler called \n");
    	switch (evt->type) {
    	case MQTT_EVT_CONNACK:
    		if (evt->result != 0) {
    			printk("MQTT connect failed %d\n", evt->result);
    			break;
    		}
    
    		connected = true;
    		printk("[%s:%d] MQTT client connected!\n", __func__, __LINE__);
    		subscribe();
    		break;
    
    	case MQTT_EVT_DISCONNECT:
    		printk("[%s:%d] MQTT client disconnected %d\n", __func__,
    		       __LINE__, evt->result);
    
    		connected = false;
    		break;
    
    	case MQTT_EVT_PUBLISH: {
    		const struct mqtt_publish_param *p = &evt->param.publish;
    
    		printk("[%s:%d] MQTT PUBLISH result=%d len=%d\n", __func__,
    		       __LINE__, evt->result, p->message.payload.len);
    		err = publish_get_payload(c, p->message.payload.len);
    		if (err >= 0) {
    			data_print("Received: ", payload_buf,
    				p->message.payload.len);
    			/* Echo back received data */
    			data_publish(&client, MQTT_QOS_1_AT_LEAST_ONCE,
    				payload_buf, p->message.payload.len);
    		} else {
    			printk("mqtt_read_publish_payload: Failed! %d\n", err);
    			printk("Disconnecting MQTT client...\n");
    
    			err = mqtt_disconnect(c);
    			if (err) {
    				printk("Could not disconnect: %d\n", err);
    			}
    		}
    	} break;
    
    	case MQTT_EVT_PUBACK:
    		if (evt->result != 0) {
    			printk("MQTT PUBACK error %d\n", evt->result);
    			break;
    		}
    
    		printk("[%s:%d] PUBACK packet id: %u\n", __func__, __LINE__,
    				evt->param.puback.message_id);
    		break;
    
    	case MQTT_EVT_SUBACK:
    		if (evt->result != 0) {
    			printk("MQTT SUBACK error %d\n", evt->result);
    			break;
    		}
    
    		printk("[%s:%d] SUBACK packet id: %u\n", __func__, __LINE__,
    				evt->param.suback.message_id);
    		break;
    
    	default:
    		printk("[%s:%d] default: %d\n", __func__, __LINE__,
    				evt->type);
    		break;
    	}
    }
    
    /**@brief Resolves the configured hostname and
     * initializes the MQTT broker structure
     */
    static void broker_init(void)
    {
    	int err;
    	struct addrinfo *result;
    	struct addrinfo *addr;
    	struct addrinfo hints = {
    		.ai_family = AF_INET,
    		.ai_socktype = SOCK_STREAM
    	};
    
    	err = getaddrinfo(CONFIG_MQTT_BROKER_HOSTNAME, NULL, &hints, &result);
    	if (err) {
    		printk("ERROR: getaddrinfo failed %d\n", err);
    
    		return;
    	}
    
    	addr = result;
    	err = -ENOENT;
    
    	/* Look for address of the broker. */
    	while (addr != NULL) {
    		/* IPv4 Address. */
    		if (addr->ai_addrlen == sizeof(struct sockaddr_in)) {
    			struct sockaddr_in *broker4 =
    				((struct sockaddr_in *)&broker);
    			char ipv4_addr[NET_IPV4_ADDR_LEN];
    
    			broker4->sin_addr.s_addr =
    				((struct sockaddr_in *)addr->ai_addr)
    				->sin_addr.s_addr;
    			broker4->sin_family = AF_INET;
    			broker4->sin_port = htons(CONFIG_MQTT_BROKER_PORT);
    
    			inet_ntop(AF_INET, &broker4->sin_addr.s_addr,
    				  ipv4_addr, sizeof(ipv4_addr));
    			printk("IPv4 Address found %s\n", ipv4_addr);
    
    			break;
    		} else {
    			printk("ai_addrlen = %u should be %u or %u\n",
    				(unsigned int)addr->ai_addrlen,
    				(unsigned int)sizeof(struct sockaddr_in),
    				(unsigned int)sizeof(struct sockaddr_in6));
    		}
    
    		addr = addr->ai_next;
    		break;
    	}
    
    	/* Free the address. */
    	freeaddrinfo(result);
    }
    
    /**@brief Initialize the MQTT client structure
     */
    static void client_init(struct mqtt_client *client)
    {
    	mqtt_client_init(client);
    
    	broker_init();
    
    	/* MQTT client configuration */
    	client->broker = &broker;
    	client->evt_cb = mqtt_evt_handler;
    	client->client_id.utf8 = (u8_t *)CONFIG_MQTT_CLIENT_ID;
    	client->client_id.size = strlen(CONFIG_MQTT_CLIENT_ID);
            //printk("clientId %s \n", CONFIG_MQTT_CLIENT_ID);
    	client->password = NULL;
            name.size = strlen(MQTT_USERNAME);
            name.utf8 = (u8_t *)MQTT_USERNAME;
    	client->user_name= &name;
    	client->protocol_version = MQTT_VERSION_3_1_1;
    
    	/* MQTT buffers configuration */
    	client->rx_buf = rx_buffer;
    	client->rx_buf_size = sizeof(rx_buffer);
    	client->tx_buf = tx_buffer;
    	client->tx_buf_size = sizeof(tx_buffer);
    
    	/* MQTT transport configuration */
            #if defined(CONFIG_MQTT_LIB_TLS)
              struct mqtt_sec_config *tls_config = &client->transport.tls.config;
        
              client->transport.type = MQTT_TRANSPORT_SECURE;
        
              tls_config->peer_verify = 0;
              tls_config->cipher_count = 0;
              tls_config->cipher_list = NULL;
              tls_config->sec_tag_count = ARRAY_SIZE(sec_tag_list); //0;//
              tls_config->sec_tag_list = sec_tag_list; //NULL;//
              tls_config->hostname = CONFIG_MQTT_BROKER_HOSTNAME;
              #else /* MQTT transport configuration */
              client->transport.type = MQTT_TRANSPORT_NON_SECURE;
              #endif /* defined(CONFIG_MQTT_LIB_TLS) */
              
    }
    
    /**@brief Initialize the file descriptor structure used by poll.
     */
    static int fds_init(struct mqtt_client *c)
    {
    	if (c->transport.type == MQTT_TRANSPORT_NON_SECURE) {
    		fds.fd = c->transport.tcp.sock;
    	} else {
    #if defined(CONFIG_MQTT_LIB_TLS)
    		fds.fd = c->transport.tls.sock;
    #else
    		return -ENOTSUP;
    #endif
    	}
    
    	fds.events = POLLIN;
    
    	return 0;
    }
    
    /**@brief Configures modem to provide LTE link. Blocks until link is
     * successfully established.
     */
    static void modem_configure(void)
    {
    #if defined(CONFIG_LTE_LINK_CONTROL)
    	if (IS_ENABLED(CONFIG_LTE_AUTO_INIT_AND_CONNECT)) {
    		/* Do nothing, modem is already turned on
    		 * and connected.
    		 */
    	} else {
    #if defined(CONFIG_LWM2M_CARRIER)
    		/* Wait for the LWM2M_CARRIER to configure the modem and
    		 * start the connection.
    		 */
    		printk("Waitng for carrier registration...\n");
    		k_sem_take(&carrier_registered, K_FOREVER);
    		printk("Registered!\n");
    #else /* defined(CONFIG_LWM2M_CARRIER) */
    		int err;
    		printk("LTE Link Connecting ...\n");
    		err = lte_lc_init_and_connect();
    		__ASSERT(err == 0, "LTE link could not be established.");
    		printk("LTE Link Connected!\n");
    #endif /* defined(CONFIG_LWM2M_CARRIER) */
    	}
    #endif /* defined(CONFIG_LTE_LINK_CONTROL) */
    }
    
    /* Provisions root CA certificate using nrf_inbuilt_key API */
    static int provision_certificate(void)
    {
    #if defined(CONFIG_PROVISION_CERTIFICATES)
    #if defined(CONFIG_BSD_LIBRARY)
    	{
    		int err;
    
    		/* Delete certificates */
    		nrf_sec_tag_t sec_tag = (nrf_sec_tag_t) sec_tag_list[0];
    
    		for (nrf_key_mgnt_cred_type_t type = 0; type < 5; type++) {
    			printk("Deleting certs sec_tag: %d\n", sec_tag);
    			err = nrf_inbuilt_key_delete(sec_tag, type);
    			printk("nrf_inbuilt_key_delete(%u, %d) => result=%d\n",
    				sec_tag, type, err);
    		}
    
    #if defined(CA_CERTIFICATE)
    		/* Provision CA Certificate. */
    		printk("Write ca certs sec_tag: %d\n", sec_tag);
    		err = nrf_inbuilt_key_write(sec_tag,
    			NRF_KEY_MGMT_CRED_TYPE_CA_CHAIN,
    			CA_CERTIFICATE,
    			strlen(CA_CERTIFICATE));
    		if (err) {
    			printk("CA_CERTIFICATE err: %d\n", err);
    			return err;
    		}
    #endif
    #if defined (CLIENT_PRIVATE_KEY)
    		/* Provision Private Certificate. */
    		printk("Write private cert sec_tag: %d\n", sec_tag);
    		err = nrf_inbuilt_key_write(
    			sec_tag,
    			NRF_KEY_MGMT_CRED_TYPE_PRIVATE_CERT,
    			CLIENT_PRIVATE_KEY,
    			strlen(CLIENT_PRIVATE_KEY));
    		if (err) {
    			printk("CLIENT_PRIVATE_KEY err: %d\n", err);
    			return err;
    		}
    #endif
    #if defined(CLIENT_PUBLIC_CERTIFICATE)
    		/* Provision Public Certificate. */
    		printk("Write public cert sec_tag: %d\n", sec_tag);
    		err = nrf_inbuilt_key_write(
    			sec_tag,
    			NRF_KEY_MGMT_CRED_TYPE_PUBLIC_CERT,
    			CLIENT_PUBLIC_CERTIFICATE,
    			strlen(CLIENT_PUBLIC_CERTIFICATE));
    		if (err) {
    			printk("CLIENT_PUBLIC_CERTIFICATE err: %d\n",err);
    			return err;
    		}
    	}
    #endif
    #else
    	{
    		int err;
    		err = tls_credential_add(CONFIG_SEC_TAG,
    			TLS_CREDENTIAL_CA_CERTIFICATE,
    			NRF_CLOUD_CA_CERTIFICATE,
    			sizeof(NRF_CLOUD_CA_CERTIFICATE));
    		if (err < 0) {
    			printk("Failed to register ca certificate: %d\n",err);
    			return err;
    		}
    		err = tls_credential_add(CONFIG_SEC_TAG,
    			TLS_CREDENTIAL_PRIVATE_KEY,
    			NRF_CLOUD_CLIENT_PRIVATE_KEY,
    			sizeof(NRF_CLOUD_CLIENT_PRIVATE_KEY));
    		if (err < 0) {
    			printk("Failed to register private key: %d\n",err);
    			return err;
    		}
    		err = tls_credential_add(CONFIG_SEC_TAG,
    			TLS_CREDENTIAL_SERVER_CERTIFICATE,
    			NRF_CLOUD_CLIENT_PUBLIC_CERTIFICATE,
    			sizeof(NRF_CLOUD_CLIENT_PUBLIC_CERTIFICATE));
    		if (err < 0) {
    			printk("Failed to register public certificate: %d\n",err);
    			return err;
    		}
    
    	}
    #endif /* defined(CONFIG_BSD_LIBRARY) */
    #endif /* defined(CONFIG_PROVISION_CERTIFICATES) */
    
    	return 0;
    }
    
    void main(void)
    {
    	int err;
            uint8_t pub[4] = {0x01, 0x02, 0x03, 0x04};
    
    	printk("The MQTT simple sample started\n");
    
            int err_provision = provision_certificate();
            if (err_provision != 0) {
              printk("ERROR: nct_provision failure %d\n", err_provision);
              return;
            }
            printk("err_provision = %d\n", err_provision);
    
    	modem_configure();
    
    	client_init(&client);
    
    	err = mqtt_connect(&client);
    	if (err != 0) {
    		printk("ERROR: mqtt_connect %d\n", err);
    		return;
    	}
    
    	err = fds_init(&client);
    	if (err != 0) {
    		printk("ERROR: fds_init %d\n", err);
    		return;
    	}
    
            
    	while (1) {
                    data_publish(&client,1,pub,4);
    
    		err = poll(&fds, 1, K_SECONDS(10));
    		if (err < 0) {
    			printk("ERROR: poll %d\n", errno);
    			break;
    		}
                    printk("After Poll\n");
    		err = mqtt_live(&client);
    		if (err != 0) {
    			printk("ERROR: mqtt_live %d\n", err);
    			break;
    		}
                    
    
    		if ((fds.revents & POLLIN) == POLLIN) {
    			err = mqtt_input(&client);
    			if (err != 0) {
    				printk("ERROR: mqtt_input %d\n", err);
    				break;
    			}
    		}
    
    		if ((fds.revents & POLLERR) == POLLERR) {
    			printk("POLLERR\n");
    			break;
    		}
    
    		if ((fds.revents & POLLNVAL) == POLLNVAL) {
    			printk("POLLNVAL\n");
    			break;
    		}
    	}
    	printk("Disconnecting MQTT client...\n");
    
    	err = mqtt_disconnect(&client);
    	if (err) {
    		printk("Could not disconnect MQTT client. Error: %d\n", err);
    	}
    }
    
    

    Here is my log :

    ***** Booting Zephyr OS build v2.0.99-ncs1 *****
    The MQTT simple sample started
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 0) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 1) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 2) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 3) => result=2
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 4) => result=2
    Write ca certs sec_tag: 2
    Write private cert sec_tag: 2
    Write public cert sec_tag: 2
    err_provision = 0
    LTE Link Connecting ...
    LTE Link Connected!
    IPv4 Address found 13.95.15.251
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:187] MQTT client connected!
    Subscribing to: /my/subscribe/topic len 19
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:237] SUBACK packet id: 1234
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 16457
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 18574
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 22424
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 24013
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 27520
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 30390
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34

    It is not perfect yet as it sent a lot of message before disconnect but I have at least communication working.

    Thank you very much for you help

    EDIT :

    To decrease the number of message I sent I have added a IF statement on the polling, within which I call the publish function. 

    while (1) {
    		err = poll(&fds, 1, K_SECONDS(10));
    		if (err < 0) {
    			printk("ERROR: poll %d\n", errno);
    			break;
    		}
                    if (err==0){
                      data_publish(&client,1,pub,4);
                    }
                    printk("After Poll\n");

    ***** Booting Zephyr OS build v2.0.99-ncs1 *****
    The MQTT simple sample started
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 0) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 1) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 2) => result=0
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 3) => result=2
    Deleting certs sec_tag: 2
    nrf_inbuilt_key_delete(2, 4) => result=2
    Write ca certs sec_tag: 2
    Write private cert sec_tag: 2
    Write public cert sec_tag: 2
    err_provision = 0
    LTE Link Connecting ...
    LTE Link Connected!
    IPv4 Address found 13.95.15.251
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:187] MQTT client connected!
    Subscribing to: /my/subscribe/topic len 19
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:237] SUBACK packet id: 1234
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 55663
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 6776
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 30147
    Publishing: 
    to topic: devices/mqtt_test/messages/events/ len: 34
    After Poll
    After Poll
    mqtt event handler called 
    [mqtt_evt_handler:227] PUBACK packet id: 55055

Related