espressif / esp-mqtt

ESP32 mqtt component
Apache License 2.0
603 stars 255 forks source link

Use CA store for client side certificates (IDFGH-1624) #125

Closed enricop closed 5 years ago

enricop commented 5 years ago

Our ESP32 project we require TLS mutual authentication with the MQTT broker. We are using client side certificates which are signed by a custom Certification Authority. To make it work, as @david-cermak suggested in the post below, we added
esp_tls_set_global_ca_store(pems_buffer, len); to our application code, passing a buffer with two pems (the CA chain to validate client certificates).

What I'm suggesting above is not 100% correct either, as the esp-tls client needs to know only the trusted root certificates (the same way openssl has ca-file or ca-path), so the correct way is setup esp_tls_set_global_ca_store with trusted root certificates. Also in mqtt-ssl example, it should be just enough to store let's encrypt root self signed cert only, like: Originally posted by @david-cermak in https://github.com/espressif/esp-mqtt/issues/84#issuecomment-433416057

However it was also required to manually add a call in the component mqtt_client.c file: esp_transport_ssl_enable_global_ca_store(ssl); at line 397. which sets the use_global_ca_store flag in the esp_transport_handle_t ssl struct.

After this we were able to authenticate successfully with the broker.

Would it possible to expose in the esp_mqtt_client_config_t struct a flag to enable the global_ca_store when using TLS certicates?

(Our project uses esp-idf master branch, so we are already using latest esp-mqtt commits)

Thank you for your support and for this great mqtt component,

Enrico

david-cermak commented 5 years ago

Hi @enricop

Thanks for this suggestion, it really makes sense (and is supported in esp-http-client as well) to add a config option to enable global CA store. A new client config field use_global_ca_store will be added.

enricop commented 5 years ago

Thank you @david-cermak !

bbinet commented 4 years ago

@enricop We are in the same situation with client side certificates which are signed by a custom Certification Authority.

I've tried the following mqtt config:

    ESP_ERROR_CHECK(esp_tls_init_global_ca_store());
    ESP_ERROR_CHECK(esp_tls_set_global_ca_store(
                (const unsigned char *) ca_cert_pem_start,
                ca_cert_pem_end - ca_cert_pem_start));

    const esp_mqtt_client_config_t mqtt_cfg = {
        .uri = "mqtts://XXX:8883",
        .event_handle = mqtt_event_handler,
        .use_global_ca_store = true,
        //.cert_pem = (const char *)ca_cert_pem_start,
        //.cert_len = ca_cert_pem_end - ca_cert_pem_start,
        .client_cert_pem = (const char *)client_cert_pem_start,
        .client_cert_len = client_cert_pem_end - client_cert_pem_start,
        .client_key_pem = (const char *)client_key_pem_start,
        .client_key_len = client_key_pem_end - client_key_pem_start,
        .username = "XXX",
        .password = "XXX",
    };

In our case, ca_cert_pem_start is a buffer with only one pem (the CA certificate used to validate both server and client certificates).

But I still get error mbedtls_ssl_handshake returned -0x50:

E (770404) esp-tls-mbedtls: mbedtls_ssl_handshake returned -0x50
I (770404) esp-tls-mbedtls: Certificate verified.
E (770404) esp-tls: Failed to open new connection
E (770414) TRANS_SSL: Failed to open a new connection
E (770424) MQTT_CLIENT: Error transport connect
I (770424) MQTTS: MQTT_EVENT_ERROR
I (770434) MQTTS: MQTT_EVENT_DISCONNECTED
I (785434) MQTTS: Other event id:7

Any idea what's wrong with my mqtt config?

bbinet commented 4 years ago

This is now working: the "issue" seems to occur only when the client key is 4096-bit. I've generated a new client key (2048-bit) and everything works fine!

SERIDJ commented 4 years ago

@bbinet hi , please wen we use use_global_ca_store true ? i think for secure connexion ssl esp32 a client not need ca.crt i use mosquitto broker in raspberry with this configuration :

#port 8883
port 8884

cafile   /etc/mosquitto/ca_certificates/ca.crt
keyfile  /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt

protocol mqtt
tls_version tlsv1.2
require_certificate true

it work with mqtt_client if i use only (mqtt_cfg.client_cert_pem and mqtt_cfg.client_key_pem ) and when i enable use_global_ca_store ant i set cert_pem to ca.crt that that not work , i dont know if i need to add it to have a good secure or its not important

all file CA, Cient for esp32 and server for raspberry are generated by self signed certificate openssl 2048 bit

bbinet commented 4 years ago

@SERIDJ Sorry, I'm not using self signed certificate... But actually CA certificate does not makes sense for self signed certificates.

SERIDJ commented 4 years ago

@bbinet what is different between signed certificates and custom Certification Authority in library ? and in my case i didn't use internet , i have local communication between device esp32 using raspberry broker ? i cant find relations among CA,server,client, key file and certifications...

if i follow tthis from : https://ficus.myvnc.com/en/blog/Mosquitto%20Broker%20Connection%20With%20TLS%20_b74

Certification files and Key filed for TLS/SSL are made by OpenSSL.

The Private key and the Public key in the key file(xxxx.key) related with each other mathematically. The Certification file(xxxx.crt) is created based on this key file.

The unique Key file is made and kept on both sides of CA and Server separately.

CA Key file is used for issuance of its certification and for signing and issuance of Server Public Key.

The Server Key is used for the request of its Public Key Certification by CA. 

The Server Certification file for its Public Key is created by the above request, and it will be distributed to the Client.

The Client verifies the CA Certification and the Server Certification and draws the Public Key of the Server for the encryption of the data.

The Server decrypts the data through its Private Key 

i take here only client need ca.crt and server dont use it but in mosquitto website https://test.mosquitto.org/ its mentioned :

For ports 8883 and 8884 you should use the certificate authority file (mosquitto.org.crt (PEM format), or mosquitto.org.der (DER format)) to verify the server connection

but if i comment ca.crt in broker #cafile /etc/mosquitto/ca_certificates/ca.crt i can publish and subscribe without certificat

bbinet commented 4 years ago

https://en.wikipedia.org/wiki/Certificate_authority Any site using self-signed certificates acts as its own CA.

SERIDJ commented 4 years ago

yes but what i dont understand why i can connect to my broker rasbperrry and send data without ca.crt in client (esp32 or python code) so how client can verifies server certificat in this case ?