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

nRF9160 LwM2M with mbedtls

Hello, basically I want my nRF9160 DK to establish a secure connection with DTLS by using mbedtls.

What I'm trying to do

I'm currently working with the LwM2M sample project for the nRF9160. With the CONFIG_LWM2M_DTLS_SUPPORT enabled, I've established a connection to our server with DTLS. As I've already figured out, the network socket is offloaded on to the modem with CONFIG_NET_SOCKETS_OFFLOAD. So UDP and DTLS is both handled by the modem. Therefore, zephyr switches to the sockets defined in ncs/nrf/lib/bsdlib/ (see BSD library of nRF Connect SDK). 

Now, I want to use mbedtls instead of the DTLS within the modem. So, I disabled the CONFIG_NET_SOCKETS_OFFLOAD and tried to enable the MBEDTLS leading to the following prj.conf:

# General config
CONFIG_NEWLIB_LIBC=y
CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_ASSERT=y
CONFIG_REBOOT=y

# Network
CONFIG_NETWORKING=y
CONFIG_NET_NATIVE=n
CONFIG_NET_OFFLOAD=y
CONFIG_NET_IPV6=n
CONFIG_NET_IPV4=y

CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_OFFLOAD=n
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_SOCKETS_POLL_MAX=4
CONFIG_NET_UDP=y

CONFIG_COAP=y
CONFIG_DNS_RESOLVER=y

# MBEDTLS
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_TLS_VERSION_1_2=y
CONFIG_MBEDTLS_DTLS=y
CONFIG_MBEDTLS_BUILTIN=y


# LwM2M
CONFIG_LWM2M=y
CONFIG_LWM2M_DNS_SUPPORT=y
CONFIG_LWM2M_RW_JSON_SUPPORT=n
CONFIG_LWM2M_SERVER_DEFAULT_PMIN=1
CONFIG_LWM2M_SERVER_DEFAULT_PMAX=300
CONFIG_LWM2M_CONN_MON_OBJ_SUPPORT=y
CONFIG_LWM2M_CONN_MON_BEARER_MAX=2
CONFIG_LWM2M_FIRMWARE_UPDATE_OBJ_SUPPORT=y
CONFIG_LWM2M_LOCATION_OBJ_SUPPORT=y
CONFIG_LWM2M_IPSO_SUPPORT=y
CONFIG_LWM2M_IPSO_TEMP_SENSOR=y
CONFIG_LWM2M_IPSO_LIGHT_CONTROL=y
CONFIG_LWM2M_IPSO_BUZZER=y
CONFIG_LWM2M_IPSO_ONOFF_SWITCH=y
CONFIG_LWM2M_IPSO_ONOFF_SWITCH_INSTANCE_COUNT=2
CONFIG_LWM2M_IPSO_PUSH_BUTTON=y
CONFIG_LWM2M_IPSO_PUSH_BUTTON_INSTANCE_COUNT=2
CONFIG_LWM2M_IPSO_ACCELEROMETER=y

# DTLS settings
CONFIG_LWM2M_DTLS_SUPPORT=y
CONFIG_LWM2M_PEER_PORT=5684

# MBEDTLS settings
CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y
# Disable RSA, we don't parse certs: saves flash/memory
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=n
# Enable PSK instead
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4

# Default app to debug logging
CONFIG_LOG=y
CONFIG_APP_LOG_LEVEL_DBG=y

# Expand logging memory to avoid log_strdup() errors
CONFIG_LOG_STRDUP_MAX_STRING=64
CONFIG_LOG_STRDUP_BUF_COUNT=32

# Support HEX style PSK values (double the size + NULL char)
CONFIG_LWM2M_SECURITY_KEY_SIZE=33

# extend CoAP retry timing to 10 seconds for LTE/LTE-M
CONFIG_COAP_INIT_ACK_TIMEOUT_MS=10000

# UI settings
CONFIG_UI_BUTTON=y
CONFIG_UI_BUZZER=y

# FOTA
CONFIG_BOOTLOADER_MCUBOOT=y
CONFIG_IMG_MANAGER=y
CONFIG_MCUBOOT_IMG_MANAGER=y
CONFIG_IMG_ERASE_PROGRESSIVELY=y
CONFIG_FLASH=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y

# Enable temp sensor
CONFIG_SENSOR=y
# TODO: No DIE temp sensor on nRF9150, select a temp sensor?
# CONFIG_TEMP_NRF5=y

# Enable settings storage
CONFIG_SETTINGS=y
CONFIG_FCB=y
CONFIG_SETTINGS_FCB=y

# LTE link control
CONFIG_LTE_LINK_CONTROL=y
CONFIG_LTE_AUTO_INIT_AND_CONNECT=n

# BSD library
CONFIG_BSD_LIBRARY=y

# Modem info
CONFIG_MODEM_INFO=y

# Library for buttons and LEDs
CONFIG_DK_LIBRARY=y
CONFIG_DK_LIBRARY_INVERT_LEDS=n

# Enable shell
CONFIG_NET_SHELL=y

# Heap and stacks
CONFIG_HEAP_MEM_POOL_SIZE=16384
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_GPS_SIM_THREAD_STACK_SIZE=1024
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
#CONFIG_HW_STACK_PROTECTION=y

# Set LwM2M connection information
CONFIG_APP_LWM2M_SERVER="my-server-not-yours"
CONFIG_APP_LWM2M_ENDPOINT="itse-me-mario"

To build successfully, I had to comment the following line in the ncs/nrf/lib/bsdlib/CMakeList.txt:

#
# Copyright (c) 2018 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-BSD-5-Clause-Nordic
#
zephyr_library()
zephyr_library_sources(bsdlib.c)
zephyr_library_sources(bsd_os.c)
#zephyr_library_sources(nrf91_sockets.c)

This way, I get the following error in the terminal after flashing the nRF9160:

<err> at_cmd: Failed to open AT socket (err:-106)

Question

Is it even possible to offload only the network layer (IP) to the modem of the nRF9160 and then use the sockets and TLS from zephyr? If so, how?

Or is there a better approach to use mbedtls?

Development setup

- nRF Connect SDK with tag 1.1.0

- Project is based on this sample: lwm2m_client

- nRF9160 DK 0.8.3

Thanks in advance for any kind of help!

  • Hi.

    While I have to do some more investigation before I can answer your questions, I can comment on the error you are seeing.

    In bsdlib (the socket interface to the modem), we define a couple of extra socket types for GPS and AT commands. When you disable socket offloading, these new socket types no longer "exist".

    You can change this by modifying the at_cmd library to use nrf_sockets instead of "normal" socket. It should not be more than changing all the socket related calls the corresponding nrf_socket call (which should be as simple as adding "nrf_" in front of the call), and including nrf_socket.h instead of net/socket.h.

    I'll come back to you when I know more about how to not offload the sockets.

    Best regards,

    Didrik

  • I am still working on getting you a proper answer.

    However, I am wondering why you do not want to use socket offloading?

  • Hello Didrik

    Thank you for your response. I'm currently having a look at the bsdlib implementation according to your input. 

    In the end, we want to outsource security features such as key storage to a secure element (which offers physically tamper-proof memory).

    We have already done that in other projects by using mbedtls and setting up a bunch of corresponding software hooks. So, make the nRF9160 use the zephyr sockets with mbedtls instead of offloading the sockets seems like the most "straight forward" approach. Of course I'm open for any other reasonable approach.

  • I got an answer from one of our developers to my questions. Note that this is mostly speculation as we have not done much (if any) testing of this:

    None of our current chips has tamper-proof physical memory AFIK meaning our chips can be decapped and read with the right amount of motivation. TLS keys stored in the modem can theoretically be read out this way.

    While we (again, as far as me and the SDK developer that answered knows) do not have tamper-proof physical memory, the keys are stored in the modem, and the application is not allowed to read them back. So unless you are afraid of people physically accessing the flash, it is not possible to access the keys. The relevant AT commands for this are %XPMNG, %CMNG, and %XPRODDONE. In the future, %XSUDO will also be relevant.

    To me, it sounds like what they want is just to use is the RAW socket type which you can build your own TLS instance ontop of with libraries like mbedTLS or your own implementation. Be warned that I have no experience in actually doing this but it's at least what I got from reading the documentation and heard from sprint reviews is that you should be able to put your own TLS ontop of RAW sockets.

Related