Hi,
We are working on a project in which data must be sent to server using NB-Iot.
We are struggling establishing an HTTPS connection with a server using the NRF9160 development kit.
As a starting point I copied some parts of the https_client sample from the sdk-nrf repo (v3.2.2). Here is the code:
static int Test()
{
int err;
printk("HTTPS client sample started\n\r");
/* Setup handler for Zephyr NET Connection Manager events. */
net_mgmt_init_event_callback(&l4_cb, l4_event_handler, L4_EVENT_MASK);
net_mgmt_add_event_callback(&l4_cb);
/* Setup handler for Zephyr NET Connection Manager Connectivity layer. */
net_mgmt_init_event_callback(&conn_cb, connectivity_event_handler, CONN_LAYER_EVENT_MASK);
net_mgmt_add_event_callback(&conn_cb);
printk("Bringing network interface up\n");
/* Connecting to the configured connectivity layer.
* Wi-Fi or LTE depending on the board that the sample was built for.
*/
err = conn_mgr_all_if_up(true);
if (err) {
printk("conn_mgr_all_if_up, error: %d\n", err);
return err;
}
/* Provision certificates before connecting to the network */
err = cert_provision();
if (err) {
return 0;
}
printk("Connecting to the network\n");
err = conn_mgr_all_if_connect(true);
if (err) {
printk("conn_mgr_all_if_connect, error: %d\n", err);
return 0;
}
/* Resend connection status if the sample is built for NATIVE_SIM.
* This is necessary because the network interface is automatically brought up
* at SYS_INIT() before main() is called.
* This means that NET_EVENT_L4_CONNECTED fires before the
* appropriate handler l4_event_handler() is registered.
*/
if (IS_ENABLED(CONFIG_BOARD_NATIVE_SIM)) {
conn_mgr_mon_resend_status();
}
k_sem_take(&network_connected_sem, K_FOREVER);
send_http_request();
/* A small delay for the TCP connection teardown */
k_sleep(K_SECONDS(1));
/* The HTTP transaction is done, take the network connection down */
err = conn_mgr_all_if_disconnect(true);
if (err) {
printk("conn_mgr_all_if_disconnect, error: %d\n", err);
}
err = conn_mgr_all_if_down(true);
if (err) {
printk("conn_mgr_all_if_down, error: %d\n", err);
}
return 0;
}
int cert_provision(void)
{
int err;
printk("Provisioning certificate\n");
#if CONFIG_MODEM_KEY_MGMT
bool exists;
int mismatch;
/* It may be sufficient for you application to check whether the correct
* certificate is provisioned with a given tag directly using modem_key_mgmt_cmp().
* Here, for the sake of the completeness, we check that a certificate exists
* before comparing it with what we expect it to be.
*/
err = modem_key_mgmt_exists(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, &exists);
if (err) {
printk("Failed to check for certificates err %d\n", err);
return err;
}
if (exists) {
mismatch = modem_key_mgmt_cmp(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert,
sizeof(cert));
if (!mismatch) {
printk("Certificate match\n");
return 0;
}
printk("Certificate mismatch\n");
err = modem_key_mgmt_delete(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN);
if (err) {
printk("Failed to delete existing certificate, err %d\n", err);
}
}
printk("Provisioning certificate to the modem\n");
/* Provision certificate to the modem */
err = modem_key_mgmt_write(TLS_SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_CA_CHAIN, cert,
sizeof(cert));
if (err) {
printk("Failed to provision certificate, err %d\n", err);
return err;
}
#else /* CONFIG_MODEM_KEY_MGMT */
err = tls_credential_add(TLS_SEC_TAG,
TLS_CREDENTIAL_CA_CERTIFICATE,
cert,
sizeof(cert));
if (err == -EEXIST) {
printk("CA certificate already exists, sec tag: %d\n", TLS_SEC_TAG);
} else if (err < 0) {
printk("Failed to register CA certificate: %d\n", err);
return err;
}
#endif /* !CONFIG_MODEM_KEY_MGMT */
return 0;
}
int tls_setup(int fd)
{
int err;
int verify;
/* Security tag that we have provisioned the certificate with */
const sec_tag_t tls_sec_tag[] = {
TLS_SEC_TAG,
};
/* Set up TLS peer verification */
enum {
NONE = 0,
OPTIONAL = 1,
REQUIRED = 2,
};
verify = REQUIRED;
err = setsockopt(fd, SOL_TLS, TLS_PEER_VERIFY, &verify, sizeof(verify));
if (err) {
printk("Failed to setup peer verification, err %d\n", errno);
return err;
}
/* Associate the socket with the security tag
* we have provisioned the certificate with.
*/
err = setsockopt(fd, SOL_TLS, TLS_SEC_TAG_LIST, tls_sec_tag, sizeof(tls_sec_tag));
if (err) {
printk("Failed to setup TLS sec tag, err %d\n", errno);
return err;
}
err = setsockopt(fd, SOL_TLS, TLS_HOSTNAME,
CONFIG_HTTPS_HOSTNAME,
sizeof(CONFIG_HTTPS_HOSTNAME) - 1);
if (err) {
printk("Failed to setup TLS hostname, err %d\n", errno);
return err;
}
return 0;
}
static void on_net_event_l4_disconnected(void)
{
printk("Disconnected from the network\n");
}
static void on_net_event_l4_connected(void)
{
k_sem_give(&network_connected_sem);
}
static void l4_event_handler(struct net_mgmt_event_callback *cb,
uint64_t event,
struct net_if *iface)
{
switch (event) {
case NET_EVENT_L4_CONNECTED:
printk("Network connectivity established and IP address assigned\n");
on_net_event_l4_connected();
break;
case NET_EVENT_L4_DISCONNECTED:
printk("Network connectivity lost\n");
on_net_event_l4_disconnected();
break;
default:
break;
}
}
static void connectivity_event_handler(struct net_mgmt_event_callback *cb,
uint64_t event,
struct net_if *iface)
{
if (event == NET_EVENT_CONN_IF_FATAL_ERROR) {
printk("Fatal error received from the connectivity layer\n");
return;
}
}
I am getting this warning and error :
<wrn> modem_key_mgmt: Failed to retrieve CMEE status, err -1 Failed to check for certificates err -1
HTTPS client sample started Bringing network interface up Provisioning certificate Certificate match Connecting to the network +CEREG: 2,"BD84","09A19608",7 +CSCON: 1 +CGEV: ME PDN ACT 0,0 +CNEC_ESM: 50,0 %MDMEV: SEARCH STATUS 2 +CEREG: 5,"BD84","09A19608",7,,,"11100000","11100000" Network connectivity established and IP address assigned Looking up example.com Resolved 172.66.147.243 (AF_INET) Connecting to example.com:443 connect() failed, err: 111 +CGEV: ME PDN DEACT 0 +CEREG: 0 +CGEV: ME DETACH +CSCON: 0 Network connectivity lost Disconnected from the network
connect() returns 111 (connection refused).
I must admit I am quite lost on which libraries to use (zephyr vs nrf) to setup Nb-IOT vs Lte-M and TLS.
I just want to make a simple HTTPS POST request via NB-IOT.
Any help would be greatly appreciated.
Thank you,
Arthur