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

Hi,

I am developing a product based on the nRF9160 using the LwM2M client.  I successfully have this working using PSK, but want to use X509.

I am calling lwm2m_security_set_certificate() where I previously called lwm2m_security_set_psk() and have client certificate, client key, and server root CA certificate in PEM form created by following the guidance from dejans and SeppoTakalo in this other post:  LWM2M Client With X.509 Certificate 

The LwM2M library reports the following

[00:01:19.463,531] <err> net_lwm2m_engine: Cannot connect UDP (-111)
[00:01:19.474,121] <err> net_lwm2m_engine: lwm2m_engine_start lwm2m_socket_start() returned -111

...which is 'connection refused'

I have taken a modem lib trace of an attempt to connect to the leshan public server, and looking at this in Wireshark, the client DTLS handshake response to the server's 'Certificate Request' contains a zero length certificate, followed by the server returning a 'Bad Certificate' fatal error (which I'm assuming results in the -111 in the modem DTLS handling).

I have attached the device certificate that I'm using, and the modem lib trace.

I have confirmed with AT%CMNG=1 that the the sha256 checksum of the stored credentials match the sha256 sum of this certificate (the file I've attached).

I'd be grateful for someone to confirm my analysis of what's going on, and suggest why the modem is not including the content of the client certificate in the DTLS handshake.

Thanks

Ian

-----BEGIN CERTIFICATE-----
MIIB1jCCAXwCFE4B5ovn7jwh+YJpWqx6ToAcJu9DMAoGCCqGSM49BAMCMGkxCzAJ
BgNVBAYTAkdCMRIwEAYDVQQIDAlIYW1wc2hpcmUxFDASBgNVBAcMC1NvdXRoYW1w
dG9uMRQwEgYDVQQKDAtVdG9ub215IEx0ZDEaMBgGA1UEAwwRVXRvbm9teSBMdGQg
RUMgQ0EwIBcNMjQxMDI0MDgyMzAxWhgPMjEyNDA5MzAwODIzMDFaMHAxCzAJBgNV
BAYTAkdCMRIwEAYDVQQIDAlIYW1wc2hpcmUxFDASBgNVBAcMC1NvdXRoYW1wdG9u
MRQwEgYDVQQKDAtVdG9ub215IEx0ZDEhMB8GA1UEAwwYdXJuOmltZWk6MzUxOTAx
OTMwNjk5NzkyMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEqej1or6Ukoqjyfj1
3rDTYg9aqyz6qaxTJkI8esY3zXnRDH+xqsn/7j33Y3pNN1QuIPj+3Ni9bpRxji1x
MbkfEjAKBggqhkjOPQQDAgNIADBFAiEA1Gf+wRIXsI2+1+rOHdyHup0OEHPgMUnz
GxBpnS/nNzgCIBlitcVFBkYFB/dLQlMWARJvIT7+CUFNfooTyW9fj6ZA
-----END CERTIFICATE-----
trace-2024-10-24T13-59-55.879Z.mtrace

Parents
  • Such an empty client certificate is commonly used, if the client is not able to use a certificate with private key matching the parameters in the Certificate Request. But from a first check, the certificate should match, so there may be something else prevent the client from using it, maybe an issue with the private key.

    > I am calling lwm2m_security_set_certificate() where I previously called lwm2m_security_set_psk() and have client certificate, client key, and server root CA certificate in PEM form 

    I'm not sure, if the "client key" in PEM is really the intended one for the lwm2m_security_set_certificate. If you follow dejans openssl instructions, the PEM is rather a key pair than a "private key", I get:

    -----BEGIN EC PARAMETERS-----
    BggqhkjOPQMBBw==
    -----END EC PARAMETERS-----
    -----BEGIN EC PRIVATE KEY-----
    MHcCAQEEIBh0Zh5RqJf49jVJhYRL6MJsIb2+RlmGGUSobg1jg2iIoAoGCCqGSM49
    AwEHoUQDQgAEllC1uZ7gFyEYjB/iTN547KsUeqzsSIWLAgCo+2g55PuM0EczbZ8s
    fXcqurjcIAMw3TQlkldktbYzfYKqG+SpQw==
    -----END EC PRIVATE KEY-----

    and if you pass the to ASN.1 decoder you see a a Octet String with 32 bytes (that's the private key), and a BIT String with 520 bit (that's the corresponding public key).

    Dejan refer also to use the Cellular Monitor, maybe that handle this. If lwm2m_security_set_certificate is able to handle this, isn't known by me.

    If you want to check, if that key-pair instead of a pure private key is your issue, you may use


    openssl ec -no_public -in client.key

    to extract the private key only (but still with algorithm identifier). Maybe someone from Nordic points you to the documentation, what's precisely expected there as parameter.

  • Thanks very much for your reply and your suggestion Achim.  As it happens, my certifcate PEM didn't include the EC PARAMS.  However, I've now tried it with the EC PARAMS included and I get the same behaviour.

    Also I note that the message from SeppoTakalo in the post I referenced includes the following code snippet, which doesn't appear to include the EC PARAMS in the key.

    	static const char key[] =
    		"-----BEGIN EC PRIVATE KEY-----\n"
    		"...clip..."
    		"-----END EC PRIVATE KEY-----";
    

    Thanks again for your reply and your suggestion, though.

  • It's not about the "EC PARAMS", it's about the content of "EC PRIVATE KEY". Copy the base 64 part to the ASN.1 decoder (address above) and you will see, if it contains the public key as well. And so you may test, if using only the private key works, using the "openssl ec -no_public -in client.key" to extract that. for my test key-pair the output will be:

    -----BEGIN EC PRIVATE KEY-----
    MDECAQEEIBh0Zh5RqJf49jVJhYRL6MJsIb2+RlmGGUSobg1jg2iIoAoGCCqGSM49
    AwEH
    -----END EC PRIVATE KEY-----

Reply
  • It's not about the "EC PARAMS", it's about the content of "EC PRIVATE KEY". Copy the base 64 part to the ASN.1 decoder (address above) and you will see, if it contains the public key as well. And so you may test, if using only the private key works, using the "openssl ec -no_public -in client.key" to extract that. for my test key-pair the output will be:

    -----BEGIN EC PRIVATE KEY-----
    MDECAQEEIBh0Zh5RqJf49jVJhYRL6MJsIb2+RlmGGUSobg1jg2iIoAoGCCqGSM49
    AwEH
    -----END EC PRIVATE KEY-----

Children
Related