[SOLVED]Question regarding SSL CA certificates and Zerynth


#1

Hi,

I have an ESP32 device that operates in two modes:

  1. Where it operates as an AP on the local network for configuration and deploys its own webserver.
  2. Where it operates on the local network and measures and communicates to an MQTT Broker.

Now I want to secure the connection on the device side by adding SSL CA in it. For mode 1, the device is the server and it needs to have a certificate as such. I read the Secure Socket Layer library and I see that the main point is to use “ssl.create_ssl_context” method. But to get it, I need to pass a reference to “cacert”, which in the example is obtained by calling the “__lookup” macro. This macro, as far as I see, gets the certificate from a CA authority and stores it on the device. Which is crystal clear, if I were to use a CA authority.

My question is: Should, and if yes - how, should I use __lookup if I were to use a locally generated OpenSSL certificate?

If that is not wise or possible to do, and I have to generate a certificate from the CA, I’d use LetsEncrypt. To get the certificate from them, should I use the “SSL_CACERT_DST_ROOT_CA_X3” or “SSL_CACERT_IDENTRUST_COMMERCIAL_ROOT_CA_1”, due to the reasons outlined here in section “Intermediate Certificates”:

I want to secure the local network communication between the Node (ESP32) and the Edge Server (Local Server), which communicate on the local network level only. The device is not reachable directly from the outside.

Thanks in advance!


#2

Hi @tmladenov,

  1. For AP mode, it can be quite difficult to deploy a webserver that handle HTTPS connections. Also, Letsencrypt would not sign you server certificate since the ESP32 is not connected to the Internet (and doesn’t have a static public IP). Apart from that, why would you need to secure the connection between the ESP32 and your client? What is your need? AP mode is typically used as a way to configure the ESP32 for the first time and probably can’t many clients simultaneously.

  2. For connecting using MQTTS you have to pass a SSL context (containing the CA of the server) to the connect method (see https://docs.zerynth.com/latest/official/lib.zerynth.lwmqtt/docs/official_lib.zerynth.lwmqtt_mqtt.html#mqtt.connect)

(Note: I suggest you using LWMQTT module instead of plain MQTT since it appears to be more stable and gives users more control in case of failures)


#3

Thanks for the reply, Antonio!

[Not so Important]
For 1: You’re right. My ‘webserver’ on the ESP32 is close to the one in Zerynth’s example. Basically a listening socket that reads the first few lines of the received packet sent by the client, sees if it’s a GET or POST and takes the appropriate action on what to return to the client.
Correct me if I’m wrong, but I haven’t seen anywhere in Zerynth documentation for an SSL wrapper over Socket to be available, like the "ssl — TLS/SSL wrapper for socket objects" module in Python, which deals with all the certificate verification and packet encryption/decryption for us. As you said, it would be hard to implement this from the ground up.

[Important]
Why I wanted this is: There’s this .1% chance that while the ESP32 is in AP mode, someone can sniff the WiFi packets and conduct a force connent/reconnect between the AP and the client, capture a handshake and then if he’s lucky enough to decrypt the WPA2 encryption of the password from the handshake, could decrypt the packet and see what’s inside, without even connecting to the AP. With simple HTTP traffic, he will see the POST method, where the user will enter his main network SSID and PW for the node to use when operational.
I was looking for a way to secure this with another level of encryption in Zerynth, like SSL/ TLS.

Can you advise me on any possible solution?

[MQTT]
About MQTT. I use the ‘normal’ MQTT, will try the LWMQTT as you advised. I have one simple question about this. I’d like to use a self-signed certificate on the node to authenticate itself with the Broker. How can I build the context with my certificate on the device? Should I upload it as a new resource on it and just call it directly, as the __lookup cannot be used in this case to my understanding (not a certificate provided by CA).

Thanks again for the help!

PS: As why I bother so much about security. It’s about my thesis, this project, and I’m 100% sure they will ask me why I didn’t bother to secure a connection with TLS.


#4

Alright,

I am working on a painless workaround, the setup is to be done over MQTT, and not over Sockets, since MQTT has tls built-in.

I want to authenticate the device before the Broker with self signed certificates, so here’s what the code looks like:

# Hardcoding the local CA cert, device cert, device key

cacert = '-----BEGIN CERTIFICATE-----\MI....'
clicert = '-----BEGIN CERTIFICATE-----\MII...'
clikey = '-----BEGIN RSA PRIVATE KEY-----MII...'

ctx = ssl.create_ssl_context(cacert = cacert, clicert = clicert, pkey = clikey, options = ssl.CERT_REQUIRED|ssl.SERVER_AUTH)

......
client = mqtt.Client("zerynth-mqtt",True)
client.connect("192.168.1.102", 60, 8883, ctx)

The fun ends here. On my test PC, I can connect to the broker with this client certificate and key for the IP of the node. But this doesn’t seem to work right when on the node, I am getting “MQTTConnectionError”…
Any ideas?


#5

Meanwhile, after trying the LWMQTT module on my Huzzah 32, I am getting this in an infinite loop. I am using r.2.3.2.
Normal MQTT works fine for me.

Guru Meditation Error: Core  0 panic'ed (IntegerDivideByZero). Exception was unhandled.
Core 0 register dump:
PC      : 0x400d7f93  PS      : 0x00060330  A0      : 0x800d810c  A1      : 0x3ffd3cd0  
A2      : 0x40172ebc  A3      : 0x000002ca  A4      : 0x00000000  A5      : 0x00000001  
A6      : 0x00000003  A7      : 0x00000000  A8      : 0x800d7f93  A9      : 0x3ffd3cb0  
A10     : 0x00000000  A11     : 0x00000000  A12     : 0x00000000  A13     : 0x00000000  
A14     : 0xffffffff  A15     : 0x00000001  SAR     : 0x00000018  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x4000c46c  LEND    : 0x4000c477  LCOUNT  : 0xffffffff  
Backtrace: 0x400d7f93:0x3ffd3cd0 0x400d8109:0x3ffd3d00 0x400d69b2:0x3ffd3d50 0x400d2edf:0x3ffd3db0 0x400d2efe:0x3ffd3dd0 0x400d1dfa:0x3ffd3df0
Rebooting...
E (10) boot: OTA: -1/-1  -1/-1  -1/-4
E (10) boot: Invalid ota, returning default vm 0
E (10) boot: Starting vm 0

#6

Solved it. The problem was that I was just using backslash at the end of the line, but before that there must be \n at each eol of the string of the certificate. Don’t forget to add the null byte ending for each string.
If you use the ssl.CERT_REQUIRED|ssl.SERVER_AUTH instead of ssl.CERT_NONE|ssl.SERVER_AUTH, you won’t be able to connect.

Python code gist:

Mosquitto MQTT mosquitto.conf: