Enable MBEDTLS debugging Nordic provided security backend (for CoAP Secure via OpenThread on nRF5340)

Goal

Hi guys,

is there an option to enable MBEDTLS debugging as with the CONFIG_MBEDTLS_DEBUG_LEVEL=4 for the MBEDTLS_BUILTIN? I am trying to setup a DTLS client based in order to establish a CoAP Secure Session via Openthread to a Borderrouter and I am struggling in the handshake process. It would be greatly helpful to have the Debugging Messages shown up.

As explained in the documentation for CONFIG_MBEDTLS_DEBUG i am calling the mentioned functions in my code:

#include "mbedtls/debug.h"
....
mbedtls_ssl_config _ssl_conf;
    /**
     * Debug callback for mbed TLS
     */
    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;
            }
        }

        LOG_INF("%s:%04d: |%d| %s", basename, line, level, str);
    }
....
....
//enabling logging
    mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL);
    mbedtls_debug_set_threshold(4);

However, when building in this setup I get:

FAILED: zephyr/zephyr_pre0.elf zephyr/zephyr_pre0.map /home/jan-zephyr/echo_client/CoAPS_Client/ec1/build/zephyr/zephyr_pre0.map
: && ccache /home/jan-zephyr/zephyr-sdk-0.13.2/arm-zephyr-eabi/bin/arm-zephyr-eabi-g++   zephyr/CMakeFiles/zephyr_pre0.dir/misc/empty_file.c.obj -o zephyr/zephyr_pre0.elf  zephyr/CMakeFiles/offsets.dir/./arch/arm/core/offsets/offsets.c.obj  -fuse-ld=bfd  -Wl,-T  zephyr/linker_zephyr_pre0.cmd  -Wl,-Map=/home/jan-zephyr/echo_client/CoAPS_Client/ec1/build/zephyr/zephyr_pre0.map  -Wl,--whole-archive  app/libapp.a  zephyr/libzephyr.a  zephyr/arch/common/libarch__common.a  zephyr/arch/arch/arm/core/aarch32/libarch__arm__core__aarch32.a  zephyr/arch/arch/arm/core/aarch32/cortex_m/libarch__arm__core__aarch32__cortex_m.a  zephyr/arch/arch/arm/core/aarch32/cortex_m/cmse/libarch__arm__core__aarch32__cortex_m__cmse.a  zephyr/arch/arch/arm/core/aarch32/mpu/libarch__arm__core__aarch32__mpu.a  zephyr/lib/libc/newlib/liblib__libc__newlib.a  zephyr/lib/posix/liblib__posix.a  zephyr/soc/arm/common/cortex_m/libsoc__arm__common__cortex_m.a  zephyr/boards/arm/nrf5340dk_nrf5340/libboards__arm__nrf5340dk_nrf5340.a  zephyr/subsys/net/libsubsys__net.a  zephyr/subsys/net/l2/openthread/libsubsys__net__ip__l2__openthread.a  zephyr/subsys/net/ip/libsubsys__net__ip.a  zephyr/subsys/net/lib/config/libsubsys__net__lib__config.a  zephyr/subsys/net/lib/conn_mgr/libsubsys__net__lib__conn_mgr.a  zephyr/subsys/net/lib/openthread/platform/libopenthread_platform.a  zephyr/subsys/random/libsubsys__random.a  zephyr/drivers/clock_control/libdrivers__clock_control.a  zephyr/drivers/console/libdrivers__console.a  zephyr/drivers/gpio/libdrivers__gpio.a  zephyr/drivers/ieee802154/libdrivers__ieee802154.a  zephyr/drivers/ipm/libdrivers__ipm.a  zephyr/drivers/flash/libdrivers__flash.a  zephyr/drivers/serial/libdrivers__serial.a  zephyr/drivers/entropy/libdrivers__entropy.a  zephyr/drivers/timer/libdrivers__timer.a  modules/nrf/lib/fatal_error/lib..__nrf__lib__fatal_error.a  modules/nrf/subsys/fw_info/lib..__nrf__subsys__fw_info.a  modules/hal_nordic/nrf_802154/libnrf-802154-platform.a  modules/nrfxlib/nrf_802154/nrf_802154/serialization/libnrf-802154-serialization.a  modules/hal_nordic/nrfx/libmodules__hal_nordic__nrfx.a  modules/libmetal/libmetal/lib/libmetal.a  modules/open-amp/open-amp/lib/libopen_amp.a  modules/nrfxlib/nrfxlib/nrf_security/src/zephyr/libmbedtls_zephyr.a  -Wl,--no-whole-archive  zephyr/kernel/libkernel.a  -L"/home/jan-zephyr/zephyr-sdk-0.13.2/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/thumb/v8-m.main/nofp"  -L/home/jan-zephyr/echo_client/CoAPS_Client/ec1/build/zephyr  -lgcc  zephyr/arch/common/libisr_tables.a  modules/hal_nordic/nrf_802154/libnrf-802154-platform.a  -no-pie  -Wl,--gc-sections  -Wl,--build-id=none  -Wl,--sort-common=descending  -Wl,--sort-section=alignment  -Wl,-u,_OffsetAbsSyms  -Wl,-u,_ConfigAbsSyms  -nostdlib  -static  -Wl,-X  -Wl,-N  -Wl,--orphan-handling=warn  spm/libspmsecureentries.a  -lm  -Wl,-lc  -L"/home/jan-zephyr/zephyr-sdk-0.13.2/arm-zephyr-eabi/arm-zephyr-eabi"/lib/thumb/v8-m.main/nofp  -Wl,-lgcc  -lc  -specs=nano.specs  modules/openthread/build/src/cli/libopenthread-cli-ftd.a  modules/openthread/build/src/core/libopenthread-ftd.a  modules/openthread/build/third_party/tcplp/libtcplp.a  modules/openthread/build/src/core/libopenthread-mtd.a  modules/openthread/build/src/core/libopenthread-ftd.a  modules/openthread/build/third_party/tcplp/libtcplp.a  modules/openthread/build/src/core/libopenthread-mtd.a  modules/nrfxlib/nrfxlib/nrf_security/src/libmbedtls.a  modules/nrfxlib/nrfxlib/nrf_security/src/libmbedx509.a  modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto.a  /home/jan-zephyr/echo_client/CoAPS_Client/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_psa_3.0.10.a  /home/jan-zephyr/echo_client/CoAPS_Client/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_mbedtls_3.0.10.a  modules/nrfxlib/nrfxlib/nrf_security/src/libmbedcrypto_base.a  -mcpu=cortex-m33  -mthumb  -mabi=aapcs  -mfp16-format=ieee  -lc  /home/jan-zephyr/echo_client/CoAPS_Client/nrfxlib/crypto/nrf_oberon/lib/cortex-m33/soft-float/liboberon_3.0.10.a && cd /home/jan-zephyr/echo_client/CoAPS_Client/ec1/build/zephyr && /usr/bin/cmake -E echo
/home/jan-zephyr/zephyr-sdk-0.13.2/arm-zephyr-eabi/bin/../lib/gcc/arm-zephyr-eabi/10.3.0/../../../../arm-zephyr-eabi/bin/ld.bfd: app/libapp.a(echo-client.c.obj): in function `main':
/home/jan-zephyr/echo_client/CoAPS_Client/ec1/src/echo-client.c:349: undefined reference to `mbedtls_debug_set_threshold'

Can someone help me here with this problem? Am I missing a library or having a configuration set wrong?

Every help would be greatly appreciated!

best regards

Jan

Setup

OS: Ubuntu 20.04

Zephyr Version: 2.7.99

nRF Connect SDK: 1.9.0

Board: nRF5340dk

Sample: zephyr/samples/net/sockets/echo_client

Config-Files:

prj.conf:

# Generic networking options
CONFIG_NETWORKING=y
CONFIG_NET_UDP=y
CONFIG_NET_TCP=n
CONFIG_NET_IPV6=y
CONFIG_NET_IPV4=n
CONFIG_NET_SOCKETS=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_SOCKETS_POLL_MAX=4
CONFIG_NET_CONNECTION_MANAGER=y

# Kernel options
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_ENTROPY_GENERATOR=y
#CONFIG_TEST_RANDOM_GENERATOR=y
CONFIG_INIT_STACKS=y

# Logging
CONFIG_NET_LOG=y
CONFIG_LOG=y
CONFIG_NET_STATISTICS=y
CONFIG_PRINTK=y

# Network buffers
CONFIG_NET_PKT_RX_COUNT=16
CONFIG_NET_PKT_TX_COUNT=16
CONFIG_NET_BUF_RX_COUNT=80
CONFIG_NET_BUF_TX_COUNT=80
CONFIG_NET_CONTEXT_NET_PKT_POOL=y

# IP address options
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=3
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=4
CONFIG_NET_MAX_CONTEXTS=10

# Network shell
CONFIG_NET_SHELL=y

# The addresses are selected so that qemu<->qemu connectivity works ok.
# For linux<->qemu connectivity, create a new conf file and swap the
# addresses (so that peer address is ending to 2).
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV6=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR=""
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="fd7b:d5a9:ff20:c73f:0:ff:fe00:7000"
CONFIG_NET_CONFIG_NEED_IPV4=n
#CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.0.2.2"
#CONFIG_NET_CONFIG_PEER_IPV4_ADDR="192.0.2.1"
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048


CONFIG_NET_SAMPLE_SEND_ITERATIONS=10
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y
CONFIG_LOG_STRDUP_MAX_STRING=1000

#CONFIG_LOG_DEFAULT_LEVEL=4
overlay-tls.conf
CONFIG_MAIN_STACK_SIZE=4096
CONFIG_NET_BUF_RX_COUNT=100
CONFIG_NET_BUF_TX_COUNT=100

# TLS configuration
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=n
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=60000
#CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048

CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4
CONFIG_NET_SOCKETS_ENABLE_DTLS=y
CONFIG_POSIX_MAX_FDS=8
CONFIG_MBEDTLS_KEY_EXCHANGE_PSK_ENABLED=y
CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED=y
CONFIG_MBEDTLS_ENTROPY_ENABLED=y
CONFIG_MBEDTLS_TLS_VERSION_1_2=y
CONFIG_MBEDTLS_DTLS=y
#CONFIG_MBEDTLS_PEM_CERTIFICATE_FORMAT=y
#CONFIG_MBEDTLS_AES_ROM_TABLES=y
CONFIG_MBEDTLS_KEY_EXCHANGE_RSA_ENABLED=y
CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y
#CONFIG_MBEDTLS_ECP_NIST_OPTIM=y
#CONFIG_MBEDTLS_CIPHER_AES_ENABLED=y
#CONFIG_MBEDTLS_CIPHER_DES_ENABLED=y
#CONFIG_MBEDTLS_CIPHER_CCM_ENABLED=y
#CONFIG_MBEDTLS_MAC_MD5_ENABLED=y
#CONFIG_MBEDTLS_MAC_SHA1_ENABLED=y
CONFIG_MBEDTLS_MAC_SHA256_ENABLED=y
CONFIG_MBEDTLS_CTR_DRBG_ENABLED=y
CONFIG_MBEDTLS_HMAC_DRBG_ENABLED=y
CONFIG_MBEDTLS_GENPRIME_ENABLED=y

#because of NRF Security
CONFIG_MBEDTLS_DEBUG_C=y
CONFIG_MBEDTLS_SSL_DEBUG_ALL=y
CONFIG_MBEDTLS_RSA_C=y
CONFIG_MBEDTLS_AES_C=y
CONFIG_NET_SOCKETS_LOG_LEVEL_DBG=y

overlay-ot.conf

CONFIG_NEWLIB_LIBC=y

# Disable TCP and IPv4 (TCP disabled to avoid heavy traffic)
CONFIG_NET_TCP=n
CONFIG_NET_IPV4=n

CONFIG_NET_IPV6_NBR_CACHE=n
CONFIG_NET_IPV6_MLD=n
CONFIG_NET_CONFIG_NEED_IPV4=n
#CONFIG_NET_CONFIG_MY_IPV4_ADDR=""
#CONFIG_NET_CONFIG_PEER_IPV4_ADDR=""

CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048

# Enable OpenThread shell
CONFIG_SHELL=y
CONFIG_OPENTHREAD_SHELL=y
CONFIG_SHELL_STACK_SIZE=3072

CONFIG_NET_L2_OPENTHREAD=y

CONFIG_OPENTHREAD_DEBUG=y
CONFIG_OPENTHREAD_L2_DEBUG=y
CONFIG_OPENTHREAD_L2_LOG_LEVEL_INF=y

CONFIG_OPENTHREAD_PANID=56022
CONFIG_OPENTHREAD_CHANNEL=11
CONFIG_OPENTHREAD_NETWORK_NAME="networkname"
CONFIG_OPENTHREAD_XPANID="da:da:da:da:da:da:da:da"
CONFIG_OPENTHREAD_NETWORKKEY="<my-networkkey>"

CONFIG_NET_CONFIG_MY_IPV6_ADDR="fdde:ad00:beef::1"

# mbedTLS tweaks
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=768

# A sample configuration to enable Thread Joiner, uncomment if needed
#CONFIG_OPENTHREAD_JOINER=y
#CONFIG_OPENTHREAD_JOINER_AUTOSTART=y

# Enable diagnostic module, uncomment if needed
#CONFIG_OPENTHREAD_DIAG=y

# Kernel options
CONFIG_INIT_STACKS=y

CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y
CONFIG_OPENTHREAD_DEBUG=y
#for CoAP
CONFIG_COAP=y

Building it with:

west build -b nrf5340dk_nrf5340_cpuapp_ns .  -DCONF_FILE="prj.conf overlay-ot.conf overlay-tls.conf" --pristine

Flashing:

west flash

Further Information

To keep it simple I am using the predefined PSK to establish DTLS. To start openthread I implemented the following code:

    struct openthread_context *otJContext;
    uint8_t ret;
   
    otJContext = openthread_get_default_context();
    if (otJContext  == NULL) {
        LOG_INF("couldn't get context");
    }
ret = openthread_start(otJContext);

In order to send the CoAP request I changed the function send_udp_data a little:

uint8_t payload[] = "";
    struct coap_packet request;
    const char * const *p;
    uint8_t *coap_data;
    int ret;


/*  create CoAP-Pakcage instead of random data

do {
        data->udp.expecting = sys_rand32_get() % ipsum_len;
    } while (data->udp.expecting == 0U ||
         data->udp.expecting > data->udp.mtu
         
    now the CoAP-Package gets created    
         */
    coap_data = (uint8_t *)k_malloc(MAX_COAP_MSG_LEN);
    if (!coap_data) {
        return -ENOMEM;
    }

    ret = coap_packet_init(&request, coap_data, MAX_COAP_MSG_LEN,
                 COAP_VERSION_1, COAP_TYPE_CON,
                 COAP_TOKEN_MAX_LEN, coap_next_token(),
                 COAP_METHOD_GET, coap_next_id());
    if (ret < 0) {
        LOG_ERR("Failed to init CoAP message");
    }

    for (p = test_path; p && *p; p++) {
        ret = coap_packet_append_option(&request, COAP_OPTION_URI_PATH,
                          *p, strlen(*p));
        if (ret < 0) {
            LOG_ERR("Unable add option to request");
        }
    }


    ret = send(data->udp.sock, request.data, request.offset, 0);

Related