DTLS PSK Handshake Failure on nRF9151 DK

7762.wireshark_trace_clienthello_only_scsv.pcapng

Summary

We are trying to perform a DTLS 1.2 handshake using PSK (Pre-Shared Key)
from an **nRF9151 module running NCS v3.0.2, using modem-offloaded DTLS (IPPROTO_DTLS_1_2).

  • LTE connects successfully
  • PSK Identity + Key are provisioned to security tag 42
  • The socket is configured with `TLS_SEC_TAG_LIST` and `TLS_PEER_VERIFY_NONE`
  • DTLS handshake always fails with `errno = 111` (`ECONNREFUSED`)
  • Wireshark trace shows the modem sends a DTLS ClientHello containing only: that means no usable cipher suites get advertised.

Expected Behavior

The client should send a DTLS ClientHello advertising PSK cipher suites such as:

  • - `TLS_PSK_WITH_AES_128_CCM_8`
  • - `TLS_PSK_WITH_AES_128_CCM`

And the server should reply with ServerHello → PSK Key Exchange.

This works correctly using:
Heavy check mark OpenSSL-based client  
Heavy check mark Go client (Pion/dtls)  
Heavy multiplication x Fails only with the nRF91 modem-based DTLS client

Actual Behavior

  • Although PSK identity and key are provisioned correctly inside the modem, the ClientHello sent by the nRF9151 does not include any PSK cipher suite (e.g., TLS_PSK_WITH_AES_128_CCM_8). Instead, it offers only ECDHE-based certificate cipher suites followed by TLS_EMPTY_RENEGOTIATION_INFO_SCSV (0x00FF). As a result, the DTLS handshake fails with no shared cipher suite.
  • Server (Go or OpenSSL) rejects handshake
  • Client receives errno=111.


Files Included

| File | Description |
|------|-------------|
| `main.c` | Full C source used on nRF9151 |
| `prj.conf` | Project configuration |
| `wireshark_trace_clienthello_only_scsv.pcapng` | Modem trace export |
| `server_log.txt` | Output from Go/openssl servers (no shared cipher) |


Test with OpenSSL

> openssl s_server -dtls -accept 5684 -nocert -psk 73757065727365637265746b6579313233 -psk_identity device001 -cipher "PSK-AES128-CCM8:PSK-AES128-CCM:PSK-AES128-CBC-HA"
Returns:

Using default temp DH parameters
ACCEPT
ERROR
4057EA2E827B0000:error:0A0000C1:SSL routines:tls_post_process_client_hello:no shared cipher:../ssl/statem/statem_srvr.c:2220:
shutting down SSL
CONNECTION CLOSED

PSK Used

Identity: device001
Key: supersecretkey123
Confirmed stored under SEC_TAG=42.

Questions to Nordic

Why does modem DTLS not include PSK ciphers in ClientHello?

Is IPPROTO_DTLS_1_2 + TLS_SEC_TAG_LIST enough to enable PSK?

Do we need to explicitly set TLS_DTLS_VERSION, TLS_CIPHERSUITE_LIST, or something undocumented?

Is this a known issue in nRF9151 modem firmware v1.x?

Can you help me to get the DTLS handshake complete with success?

In the final product, the DTLS stuff must coexist with the LwM2M (which I already successfully tested 0m nRF9161 platform using Eclipse Leshan together with lwm2m client sample) one on nRF9151.

Thank you in advance for your support!

  • Cannot connect to LwM2M server with X509 DTLS. Wireshark shows empty client certificate.

    That's the vice versa. It doesn't work, if certificate and PSK credentials are mixed into one sec_tag.

    You may check, if that applies with

    AT%CMNG=1,42

    If that show's more than your PSK credentials, remove the others.

  • Hello,  AT%%CMNG=1,42 returned:

    42,3,"A4E05CEFA49CFFE2BB25E5E0793625C1199CB4ED83FF1B155BD6591EB043E9F1"

    42,4,"54CCD4B043ECEC38BFB890596F7BD99FC8E6058517882A75F3BF37B9475972A1"

    Which are the result of:

        modem_key_mgmt_write(SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_IDENTITY,
                             PSK_ID, strlen(PSK_ID));
        modem_key_mgmt_write(SEC_TAG, MODEM_KEY_MGMT_CRED_TYPE_PSK,
                             PSK_KEY, strlen(PSK_KEY));

    So no other credentials than PSK ID and KEY. To be 100% sure the right stuff is injected into the modem now always delete all credentials for tag 42 and then re-enter them using modem_key_mgmt_write.

    *** Booting nRF Connect SDK v3.0.2-89ba1294ac9b ***
    *** Using Zephyr OS v4.0.99-f791c49f492c ***
    [00:00:00.388,000] <inf> main: === LTE + DTLS Handshake Test ===
    [00:00:00.388,000] <inf> main: Client PSK Key (ASCII) hex:
    73 75 70 65 72 73 65 63 72 65 74 6B 65 79 31 32 33 
    [00:00:00.388,336] <inf> main: Initializing modem...
    [00:00:00.646,270] <inf> nrf_modem_lib_trace: Trace thread ready
    [00:00:00.648,071] <inf> nrf_modem_lib_trace: Trace level override: 2
    [00:00:00.792,694] <inf> main: Set CFUN to 0 to reset the SIM: OK

    [00:00:03.031,860] <inf> main: Cleared credentials type 3 fotr Tag 42
    [00:00:03.136,932] <inf> main: Cleared credentials type 4 fotr Tag 42
    [00:00:03.260,986] <inf> main: Credentials of Tag 42 are wiped
    [00:00:03.261,016] <inf> main: Provisioning  Tag 42 with new credentials
    [00:00:03.474,914] <inf> main: New credentials for Tag 42 -> ID:1 PSK:1
    [00:00:06.546,813] <inf> main: Connecting LTE...
    +CEREG: 1,"057D","01017406",7,,,"00001111","00101101"
    [00:00:07.181,976] main: White check mark LTE connected!
    [00:00:07.375,427] <inf> main: Connecting to GIMSServer.mooo.com (84.55.253.71):5684
    [00:00:07.375,732] <inf> main: Performing DTLS handshake with GIMSServer.mooo.com:5684...
    [00:00:07.527,954] main: X DTLS handshake failed, errno=111

    Nothing changed I still get errno=111.

  • cellfund_less5_exer2_solution.zip

    I've tested DTLS PSK with the coap client of "cellfund_less5_exer2_solution" (slightly adapted for NCS 3.1.0).

    Works on my machine.

    I don't know, what happens in your case. If you enable the modem trace (-DSNIPPET="nrf91-modem-trace-uart" when no McuBoot is used and -D<yourdir>_SNIPPET="nrf91-modem-trace-uart" if used) you will get a capture and the Client Hello will be the interesting message (or you capture it on the server side.)

  • I downloaded your cellfund_less5_exer2_solution and switched to SDK 3.1.0 (to completely align with you).

    I noticed that this sample makes use of posix socket API, which is different from what I was doing.

    Anyway, I slight l modified the code since I'm not interested in COAP for the time being.

    As you can see in main.c, I simply replaced server url, PSK ID and KEY and I added the required PIN code.

    On the server side I replaced the COAP server with OpenSSL.

    Since COAP stuff comes after the DTLS PSK, the code should be able to successfully complete the DTSL PSK handshake.

    Here the outcomes:

    *** Booting nRF Connect SDK v3.1.0-6c6e5b32496e ***
    *** Using Zephyr OS v4.1.99-1612683d4010 ***
    [00:00:00.390,502] <inf> Lesson5_Exercise2: Initializing modem library
    [00:00:00.648,742] <inf> nrf_modem_lib_trace: Trace thread ready
    [00:00:00.650,146] <inf> nrf_modem_lib_trace: Trace level override: 2
    [00:00:02.360,687] <inf> Lesson5_Exercise2: Connecting to LTE network
    [00:00:06.162,292] <inf> Lesson5_Exercise2: Network registration status: Connected - home network
    [00:00:06.162,414] <inf> Lesson5_Exercise2: Connected to LTE network
    [00:00:06.377,288] <inf> Lesson5_Exercise2: IPv4 Address found 84.55.253.71
    
    [00:00:06.631,561] <err> Lesson5_Exercise2: Connect failed : 111
    
    [00:00:06.631,591] <inf> Lesson5_Exercise2: Failed to initialize client
    [00:00:08.796,966] <inf> Lesson5_Exercise2: RRC mode: Idle

    As before on the terminal I get error 111.

    On the server side I run:

    > openssl s_server -dtls1_2 -accept 5684 -psk_identity device001 -psk\ 73757065727365637265746b6579313233  -nocert  -state  -debug -msg.

    cellfund_less5_exer2_solution_newresults.zip

    In the zip:

    • main.c: the modified main
    • prj.conf and nrf9151dk_nrf9151_ns.overlay required to enable modem trace
    • OpenSSL_ DTLS_ log.txt: openssl debug dump
    • wireshark.txt: Wireshark output summary and ClientHello dettail

    I'm using VC nrfConnect plugin for building and programming the target (nrfjprog has been obsoleted and is not anymore available for download).

    Do you see any useful information in the results ? Can you try to replicate the same on your side (using OpenSSL)?

    Thanks in advance for any help.

    Regards, Joel

    p.s. I'm assuming NRF uses DTLS 1_2. Is this correct ?

  • I noticed that this sample makes use of posix socket API, which is different from what I was doing.

    AFAIK, that's getting required in NCS 3.1.0

    Anyway, I slight l modified the code since I'm not interested in COAP for the time being.

    I'm an other user, no Nordic engineer. I just toke an common example to verify DTLS. Though the "Client_Hello" seems to be the issue, it also doesn't depend on the used server (at least I'm not aware of). With that I would recommend, that you simply use the unmodified example (maybe you need to remove other credentials on sec_tag 12, I haven't added a modem_key_mgmt_clear) and see, if that succeeds or fails as well.

    Only if it succeeds, you may apply your changes step by step and see, when it breaks.

    If the unmodified example fails also, I don't know why. Then you may need to wait for an Nordic engineer.

Related