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

nRF9160 TLS_HOSTNAME support

Is TLS_HOSTNAME socket option supported inside the modem firmware or bsdlib?

When I make the function call:

err = setsockopt(client_fd, SOL_TLS, TLS_HOSTNAME, host, sizeof(host));

returns with err==42.

 

I need to set this socket option for my application. I am using AWS API Gateway with a custom domain name and the certificate that gets served by default is the "*.execute-api.us-east-1.amazonaws.com" and not my domain certificate. Then, I believe the TLS peer verification fails due to hostname mismatch.

I am using fairly latest, SW Versions:

fw-nrfconnect-nrf:v1.1.0
fw-nrfconnect-zephyr:v2.0.99-ncs1
nrfxlib:v1.1.0
mfw_nrf9160_1.1.0
  • Yes, it's definitely supported.  It's possible that the SOCKOPT need to be turned on in a certain order.  Take a look at the function mqtt_client_tls_connect over in zephyr/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c.  It walks through opening a new socket and setting up all the TLS settings, and I know that works.

  • One thing i just noticed is that the sample I pointed you to is using strlen() insted of sizeof() for the length.  Is there a chance you're including the NULL character at the end?  Not sure if that would be the issue, but it's something to try.

  • I have tried both strlen() and sizeof(). Both lengths called in setsockopt() return with a value of 42. I have noticed some examples seem to exclude the null terminator for a c string. However, NRF_SO_HOSTNAME (https://github.com/NordicPlayground/nrfxlib/blob/master/bsdlib/include/nrf_socket.h#L133) definition comment states "Host name is provided a null-terminated string."

    Just for reference. strlen() returns the length of string excluding the null terminator, where sizeof() returns the length of the c string including the null terminator. For example:

    char host[] = "api.example.com"
    strlen(host) == 15
    sizeof(host) == 16

  • I have been looking further into this. Inside mqtt_client_tls_connect() the call to setsockopt for TLS_HOSTNAME is failing silently, the return value is only checked to be less than zero (https://github.com/NordicPlayground/fw-nrfconnect-zephyr/blob/master/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c#L76). This would allow a return value of positive 42 to be seen as successful.

    I went a step further and modified, mqtt_transport_socket_tls.c at line 72:

    if (tls_config->hostname) {
    	char hostname[] = "foo.bar.example.com";
    	printk("%s:%d: hostname=%s\n", __FILE__, __LINE__, hostname);
    	ret = setsockopt(client->transport.tls.sock, SOL_TLS,
    			 TLS_HOSTNAME, hostname,
    			 strlen(hostname));
    	printk("%s:%d: ret=%d\n", __FILE__, __LINE__, ret);
    	if (ret < 0) {
    		goto error;
    	}
    }

    With this change, I recompiled the asset_tracker application and tested its connectivity to nrfcloud, this is the log output:

    2019-12-29T17:08:57.171Z DEBUG modem << Connected to LTE network\x0D\x0A
    2019-12-29T17:08:57.244Z DEBUG modem << [00:00:05.331,237] \x1B[0m<dbg> nrf_cloud_transport.nct_connect: IPv4 Address 0x6d6b5d03\x1B[0m\x0D
    2019-12-29T17:08:57.265Z DEBUG modem << ZEPHYR_BASE/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c:74: hostname=foo.bar.example.com\x0D\x0A
    2019-12-29T17:08:57.267Z DEBUG modem << ZEPHYR_BASE/subsys/net/lib/mqtt/mqtt_transport_socket_tls.c:78: ret=42\x0D\x0A
    2019-12-29T17:09:01.610Z DEBUG modem << [00:00:09.695,556] \x1B[0m<inf> aws_jobs: Subscribe: $aws/things/nrf-352656100378911/jobs/notify-next\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.631Z DEBUG modem << [00:00:09.705,718] \x1B[0m<inf> aws_jobs: Subscribe: $aws/things/nrf-352656100378911/jobs/$next/get/#\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.633Z DEBUG modem << [00:00:09.715,545] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_CONNACK\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.637Z DEBUG modem << [00:00:09.723,785] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 2\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.661Z DEBUG modem << [00:00:09.731,567] \x1B[0m<dbg> nrf_cloud.event_handler: NRF_CLOUD_EVT_TRANSPORT_CONNECTED\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.662Z DEBUG modem << CLOUD_EVT_CONNECTED\x0D\x0A
    2019-12-29T17:09:01.663Z DEBUG modem << [00:00:09.741,607] \x1B[0m<dbg> nrf_cloud_transport.nct_cc_connect: nct_cc_connect\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.664Z DEBUG modem << [00:00:09.750,091] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 3\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.755Z DEBUG modem << [00:00:09.842,559] \x1B[0m<inf> aws_fota: subscribed to notify-next topic\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.777Z DEBUG modem << [00:00:09.849,334] \x1B[0m<inf> aws_jobs: Publish topic: $aws/things/nrf-352656100378911/jobs/$next/get\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.778Z DEBUG modem << [00:00:09.858,673] \x1B[0m<inf> aws_jobs: Publish payload {"clientToken": ""}\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.845Z DEBUG modem << [00:00:09.929,260] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_SUBACK: id=2114 result=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.872Z DEBUG modem << [00:00:09.952,545] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_SUBACK: id=1234 result=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.876Z DEBUG modem << [00:00:09.962,249] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 4\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.905Z DEBUG modem << [00:00:09.970,031] \x1B[0m<dbg> nrf_cloud_transport.nct_cc_send: mqtt_publish: id=5678 opcode=0 len=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:01.929Z DEBUG modem << [00:00:09.980,102] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 5\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.000Z DEBUG modem << [00:00:10.083,984] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_PUBACK: id=61137 result=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.048Z DEBUG modem << [00:00:10.131,866] \x1B[0m<inf> aws_fota: Received topic: $aws/things/nrf-352656100378911/jobs/$next/get/accepted\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.069Z DEBUG modem << [00:00:10.142,211] \x1B[0m<inf> aws_fota: Got only one field: {"clientToken":"","timestamp":1577639342}\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.136Z DEBUG modem << [00:00:10.221,008] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_PUBACK: id=5678 result=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.143Z DEBUG modem << [00:00:10.230,712] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 5\x1B[0m\x0D
    2019-12-29T17:09:02.376Z DEBUG modem << [00:00:10.460,205] \x1B[0m<inf> aws_fota: Received topic: nrf-352656100378911/shadow/get/acceptedxt/get/accepted\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.398Z DEBUG modem << [00:00:10.470,336] \x1B[0m<inf> aws_fota: Recived an unhandled MQTT publish event on topic: nrf-352656100378911/shadow/get/acceptedxt/get/accepted\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.400Z DEBUG modem << [00:00:10.483,459] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_PUBLISH: id=15336 len=283 \x1B[0m\x0D\x0A
    2019-12-29T17:09:02.424Z DEBUG modem << [00:00:10.494,598] \x1B[0m<dbg> nrf_cloud_transport.nct_dc_endpoint_set: nct_dc_endpoint_set\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.425Z DEBUG modem << [00:00:10.503,051] \x1B[0m<dbg> nrf_cloud_transport.nct_dc_endpoint_get: nct_dc_endpoint_get\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.426Z DEBUG modem << [00:00:10.511,566] \x1B[0m<dbg> nrf_cloud_transport.nct_dc_endpoint_get: nct_dc_endpoint_get\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.435Z DEBUG modem << [00:00:10.520,629] \x1B[0m<dbg> nrf_cloud_transport.nct_cc_send: mqtt_publish: id=7890 opcode=1 len=329\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.460Z DEBUG modem << [00:00:10.532,165] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 7\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.461Z DEBUG modem << [00:00:10.539,947] \x1B[0m<dbg> nrf_cloud.event_handler: NRF_CLOUD_EVT_USER_ASSOCIATED\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.463Z DEBUG modem << CLOUD_EVT_PAIR_DONE\x0D\x0A
    2019-12-29T17:09:02.715Z DEBUG modem << [00:00:10.800,537] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_PUBACK: id=7890 result=0\x1B[0m\x0D
    2019-12-29T17:09:02.746Z DEBUG modem << [00:00:10.810,241] \x1B[0m<dbg> nrf_cloud_transport.nct_dc_connect: nct_dc_connect\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.748Z DEBUG modem << [00:00:10.818,847] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 13\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.883Z DEBUG modem << [00:00:10.967,803] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_SUBACK: id=8765 result=0\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.913Z DEBUG modem << [00:00:10.977,508] \x1B[0m<dbg> nrf_cloud.nfsm_set_current_state_and_notify: state: 14\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.914Z DEBUG modem << [00:00:10.985,382] \x1B[0m<dbg> nrf_cloud.event_handler: NRF_CLOUD_EVT_READY\x1B[0m\x0D\x0A
    2019-12-29T17:09:02.915Z DEBUG modem << CLOUD_EVT_READY\x0D\x0A
    2019-12-29T17:09:02.916Z DEBUG modem << GPS initialized\x0D\x0A
    2019-12-29T17:09:02.945Z DEBUG modem << [00:00:11.030,609] \x1B[0m<dbg> nrf_cloud_transport.nct_cc_send: mqtt_publish: id=1 opcode=1 len=604\x1B[0m\x0D\x0A
    2019-12-29T17:09:03.345Z DEBUG modem << [00:00:11.430,572] \x1B[0m<dbg> nrf_cloud_transport.nct_mqtt_evt_handler: MQTT_EVT_PUBACK: id=1 result=0\x1B[0m\x0D\x0A

    Even with TLS_HOSTNAME set to "foo.bar.example.com" the device is still able to connect to aws to the nrfcloud. This should clearly result in a hostname mismatch with the server certificate and the TLS connection should be closed. This has some grave security concerns with man-in-the-middle or DNS attack vectors.

  • Hot damn, you're right.  Calls to setsockopt are returning +42 for TLS_HOSTNAME.  I was briefly convinced it must be calling the wrong setsockopt through the offload mechanisms, but I added trace logging down in nrf91_socket_offload_setsockopt and it is getting the +42 back from nrf_setsockopt directly.

    [00:00:14.170,898] <wrn> nrf91_sockets: nrf_setsockopt(3, 282, 4, 0x20032ba0, 4)
    [00:00:14.181,488] <wrn> nrf91_sockets: nrf_setsockopt retval=0
    [00:00:14.190,551] <inf> net_mqtt_sock_tls: setsockopt PEER_VERIFY 0
    [00:00:14.199,768] <wrn> nrf91_sockets: nrf_setsockopt(3, 282, 2, 0x20032fc0, 4)
    [00:00:14.210,327] <wrn> nrf91_sockets: nrf_setsockopt retval=0
    [00:00:14.219,390] <inf> net_mqtt_sock_tls: setsockopt SEC_TAG_LIST 0
    [00:00:14.228,698] <wrn> nrf91_sockets: nrf_setsockopt(3, 282, 5, 0x20032d0a, 27)
    [00:00:14.239,349] <wrn> nrf91_sockets: nrf_setsockopt retval=42
    [00:00:14.248,504] <inf> net_mqtt_sock_tls: setsockopt HOSTNAME 42

    That's completely against the documentation for nrf_setsockopt.

    Hey, can we get someone at Nordic with visibility into the BSDLIB to comment, please?

    In my testing, I was using MFW 1.1.0 and BSDLIB 0.5.1.

Related