eclipse-californium / californium

CoAP/DTLS Java Implementation
https://www.eclipse.org/californium/
Other
729 stars 367 forks source link

CoAP with DTLS using Quectel BG96 client #2103

Closed fprokopovich closed 1 year ago

fprokopovich commented 1 year ago

Hello! I want to connect to CoAP californium server using cf-plugtest-server/cf-extplugtest-server demo and DTLS. I am using a BG96 Quectel modem as a client.

Can you provide me instructions on how to use the PSK key? Where can I get it to set up configuration on my modem. Now when I try to connect, I see such logs: Californium coap UDP Message has invalid version: 0; 16FEFD0000000000 UDP Ban Wireshark Constrained Application Protocol, Non-Confirmable, Unknown 254, MID:64768

boaks commented 1 year ago

I'm not sure, what you exactly do.

First, the Californium Sandbox offer both coap without encryption and coaps with encryption using DTLS 1.2. It supports also encryption with OSCORE. See Sandbox. The variant without encryption uses port 5683, with DTLS 1.2 it's 5684. I guess, you send coaps with encryption to the wrong port 5683 instead of 5684.

In general, the most issues using PSK is caused by different encoding, frequently unaware. One peer uses "plain ASCII", the other "hexadecimal" as input. And from the very past, some are supporting only "fixed sized" secrets (e.g. 16 bytes. That was always not required and always a wrong interpretation of PSK!).

I don't know, what Quectel BG96 is currently offering for configuring PSK for DTLS. Maybe you can provide a link? Or a snippet of the AT cmd documentation?

fprokopovich commented 1 year ago

Quectel provide CoAP Application instruction. You can downloaded it - Quectel_BG96_CoAP_Application_Note_V1.0

I'm running cf-plugtest-server demo. Next I set up the BG96 using the instructions below and try to connect to 192.168.0.10:5684. To connect, I need to provide a PSK key. There are also settings for providing PKI certificates to the modem.

image image

boaks commented 1 year ago

I can't see the documentation for "864508030012428&313233343446473839". I guess (maybe wrong), it's:

PSK identity: "864508030012428" PSK secet (hex):"313233343446473839" => PSK secet (plain):"12344FG89"

The cf-plugtest-server demo use "compiled in" credentials, the "cf-cloud-demo-server" (still under development) uses a file based PSK store.

There are two ways to go:

adjust the PSK credentials of the modem, e.g. using the openssl default credentials:

"Client_identity&73656372657450534B"

or add your device credentials to the PSK store of the cf-plugtest-server. For that copy a PSK credentials pair in AbstractTestServer

    // easier testing with openssl clients
    public static final String OPENSSL_PSK_IDENTITY = "Client_identity";
    public static final SecretKey OPENSSL_PSK_SECRET = SecretUtil.create("secretPSK".getBytes(), "PSK");

to new names, e.g.

    // modem client
    public static final String MODEM_PSK_IDENTITY = "864508030012428";
    public static final SecretKey MODEM_PSK_SECRET = SecretUtil.create("12344FG89".getBytes(), "PSK");
        // or
    public static final SecretKey MODEM_PSK_SECRET = SecretUtil.create(StringUtil.hex2ByteArray("313233343446473839"), "PSK");

and add these copies to the store below

        public PlugPskStore() {
            addKey(ETSI_PSK_IDENTITY, ETSI_PSK_SECRET);
            addKey(OPENSSL_PSK_IDENTITY, OPENSSL_PSK_SECRET);
            addKey(MODEM_PSK_IDENTITY, MODEM_PSK_SECRET);
        }
boaks commented 1 year ago

Californium coap UDP Message has invalid version: 0; 16FEFD0000000000 UDP Ban

try to connect to 192.168.0.10:5684.

"16FEFD0000000000" that's the header of a DTLS handshake message. But "UDP" indicates, it's send to 5683.

fprokopovich commented 1 year ago

Thanks! I will try.

Can you provide instructions please to me how can I choose a security mode (PSK or RawPublic key or X509) for Californium Server demos?

boaks commented 1 year ago

The server supports the mode you provide the credentials for.

DTLS uses an so called "handshake" to negotiate the security parameters. A client therefore sends the list of supported cipher suites (PSK or ECDSA) and the server selects the cipher suite based on the provided credentials.

e.g.: If you only add a PSK store, only PSK is supported. If you additionally add a CertificateProvider and a NewAdvancedCertificateVerifier x509 and RPK are also supported.

See also the Scandium README for more details.

fprokopovich commented 1 year ago

Hi! I tried to connect to the СoAP server (demo cf-extplugtest-server) with DTLS from BG96 using only a PSK key you provided above (Client_identity&73656372657450534B). The handshake fails with a "Bad Certificate" error. Attached the log, for convenience, you can sort by ip.addr==192.168.0.10. I used 5684 port coap-wireshark-log.zip

boaks commented 1 year ago

The BG96 sends a very long list of supported cipher suites, even including ones, it has no credentials for. the server chose TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 (0xc02b) and sends it's server certificate. The server then request a client certificate indicating, that the server accepts only certificates signed by the "californium demo certificates". The modem has no and sends a empty one.

The very fastest and easiest way out for an first approach, edit "CaliforniumPlugtest3.properties"

# DTLS client authentication mode for certificate based cipher suites.
# [NONE, WANTED, NEEDED].
# Default: NEEDED
DTLS.CLIENT_AUTHENTICATION_MODE=NEEDED

to

DTLS.CLIENT_AUTHENTICATION_MODE=WANTED

with that, the server accepts the empty certificate, but then the modem client is not authenticated at all.

Is you want PSK, you need to configure the modem, to propose only PSK cipher suites and no Certificate ones. Or at least to put the PSK ones at the begin of the proposed cipher suites, e.g.:

"TLS_PSK_WITH_AES_128_CCM, TLS_PSK_WITH_AES_128_CCM_8, TLS_PSK_WITH_AES_128_GCM_SHA256".

(you need to ask the modem manufacturer about that. Using the client cipher suites order to select the best common fit is the most common approach, but the client must follow that.)

Alternatively, remove the certificate support from the server by removing

X509KeyManager keyManager = SslContextUtil.getX509KeyManager(serverCredentials);
AsyncKeyManagerCertificateProvider certificateProvider = new AsyncKeyManagerCertificateProvider(
                            keyManager, CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);
certificateProvider.setDelay(handshakeResultDelayMillis);
dtlsConfigBuilder.setCertificateIdentityProvider(certificateProvider);
AsyncNewAdvancedCertificateVerifier.Builder verifierBuilder = AsyncNewAdvancedCertificateVerifier
                            .builder();
if (cliConfig.trustall) {
    verifierBuilder.setTrustAllCertificates();
} else {
    verifierBuilder.setTrustedCertificates(trustedCertificates);
}
verifierBuilder.setTrustAllRPKs();
AsyncNewAdvancedCertificateVerifier verifier = verifierBuilder.build();
verifier.setDelay(handshakeResultDelayMillis);
dtlsConfigBuilder.setAdvancedCertificateVerifier(verifier);

or "comment it out".

Hope, that helps for a next try.

fprokopovich commented 1 year ago

Thanks a lot! I will try

boaks commented 1 year ago

Just to say:

It's not too easy to predict, what needs to be done, if I don't have enough details.

It may be sufficient, to remove the x509 support only from the certificateProvider:

AsyncKeyManagerCertificateProvider certificateProvider = new AsyncKeyManagerCertificateProvider(
                            keyManager, CertificateType.RAW_PUBLIC_KEY, CertificateType.X_509);

to

AsyncKeyManagerCertificateProvider certificateProvider = new AsyncKeyManagerCertificateProvider(
                            keyManager, CertificateType.RAW_PUBLIC_KEY);

the modem seems not to support RPK (I guess it's mbedtls), and so only PSK cipher suites will be common.

Anyway, as I wrote before: try to find out, how the cipher suites, proposed by the client (modem), can be configured. That's the most common approach.

fprokopovich commented 1 year ago

I'm looking at the BG96 SSL configuration and I don't see the cipher suits for TLSPSK there. Here is a list of available cipher suits options, what can we choose from this to set up DTLS connection with Californium server demo?

image

if I choose the first option 0x0035 TLSRSA and upload to modem cacert - caRsaTrustStore.pem, clientcert - clientRsa.pem, clientkey - clientRsaPrivateKey.pem in the californium\californium-tests\californium-interoperability-tests folder should this work?

boaks commented 1 year ago

I guess, there is a difference of support cipher suites for TLS and DTLS.

The capture you provided previously contains a list of 138 cipher suites, and PSK ones are included. It containes also TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, which the server already choose.

if I choose the first option 0x0035 TLSRSA

This cipher suite is not supported by Californium, see #2101 . But TLS_ECDHE_RSA may. Using RSA isn't really the best choice, so I would go for a ECDSA client certificate (client.pem, cientPrivateKey.pem) and trust that signer (caTrustStore.pem).

Just to mention, if the configuration of the device is uncontrolled or unknown, you can't achieve security, I'm not sure, if you asked the modem manufacturer, about configuring the use cipher suite list for DTLS, but from my side, that's the way to got. You may also check, if my last proposal, removing x509 works and uses the PSK.

boaks commented 1 year ago

Quectel_BG96_SSL_Application_Note_V1.1

The list there contains these cipher suites for TLS 1.0, but TLS 1.0 is going to be disabled for the most cloud servers.

On page 26 it describes the setup for DTLS 1.0 PSK, DTLS 1.0 is also out dated. I guess, if you try to use that setup for DTLS 1.2 PSK, you have an chance, if not, only QuecTel will be able to help you.

fprokopovich commented 1 year ago

When I using the AT+QSSLCFG="ciphersuite",0,0XFFFF option, which enables support for all available ciphersuites, I actually see a long list (~138 available ciphersuites) in the wireshark logs during the client hello stage. and there really are PSK ciphersuites, but when I try to specify them in AT+QSSLCFG="ciphersuite", the modem gives an error (which is expected, because they are not in the list of supported ones for setting up the Quectel modem - datasheet and the response of the AT+QSSLCFG=? command on the modem say us about it.

Then I tried to specify the TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 and next TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 option in the AT+QSSLCFG="ciphersuite" modem configuration, as you advised above, and provided the modem with client.pem, cientPrivateKey.pem and caTrustStore.pem certificates and got server Bad Certificate error response.

After that I commented out the certificate support from the server in AbstractTestServer.java and rebuilt the cf-plugtest-server demo. The logs show that the server selects the PSK Cipher Suite: TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 (0xc037) and starts responding to handshake. At this time, for some reason, the client - modem returns an error: DTLS handshaking failure.

For each point, I attached the logs in the archive: wireshark_logs.zip

boaks commented 1 year ago

The two cases with certificates: The modem still sends the empty certificate. You may ask the modem manufacturer about the reason, I can't see that in the capture.

The PSK case: The modem doesn't answer to the server flight after the ServerHelloDone. That may be caused by your network or the modem. If it's not the network, you may ask the modem manufacturer about the reason, I can't see that in the capture.

Just to mention: You may test with libcoap and the mbedtls binding. You will see, once you are able to configure the client's cipher suites, the handshake works.

fprokopovich commented 1 year ago

About two cases with certificates - where do you see that modem sends the empty certificate? Can you show me this place

boaks commented 1 year ago

coap-tls-ecdhe-rsa-log.pcapng, frame 85, first handshake message "Certificate":

empty-client-certificate

The handshake message has 15 bytes, the certificates length is 0 => empty client certificate.

coap-tls-ecdhe-ecdsa-log.pcapng, frame 15, first handshake message "Certificate", same lengths.

If the client certificate is empty, you may try if

The very fastest and easiest way out for an first approach, edit "CaliforniumPlugtest3.properties"

# DTLS client authentication mode for certificate based cipher suites.
# [NONE, WANTED, NEEDED].
# Default: NEEDED
DTLS.CLIENT_AUTHENTICATION_MODE=NEEDED
DTLS.CLIENT_AUTHENTICATION_MODE=WANTED

Does it for very first tests.

fprokopovich commented 1 year ago

Hi! AT+QSSLCFG="ciphersuite",0,0XC0A8 // TLS_PSK_WITH_AES_128_CCM_8 or AT+QSSLCFG="ciphersuite",0,0X00AE // TLS_PSK_WITH_AES_128_CBC_SHA256

-config options is available for Quectel BG95 modem and for Californium CoAP server. And they work for PSK (Pre-Shared Key) mode of DTLS. We found the documentation for this particular modem and confirmed the information experimentally with this model. Everything works perfectly!

X.509 certificate mode doesn't work on Quectel modem using AT commands.

Thanks for your help!

boaks commented 1 year ago

Everything works perfectly!

Great! Thanks to let us know.

X.509 certificate mode doesn't work on Quectel modem using AT commands.

Depends on your time, you may find out, how the modem configures:

If you know the first three, you may check, if the device connects with the sandbox at californium.eclipseprojects.io . If that is successful, but fails to connect your server with an different destination, you need to create a server certificate for that destination. That's, how x509 authentication works :-).