I want to implement a server on IoT devices, and secure remote access. (I am using C++ on an esp32, and already have a lot of code, I have mbedtls available in the build platform, I want to provide connection security now).
I can use ACME to get the server a certificate from letsencrypt.org, and could do the same for client.
But how should my server code check whether the client is one of the trusted ones ? Should I have a list of authorized client certificates in the server (I see a renewal problem with that) ? Or is there a way to create client certificates that are somehow linked to the server ?
In order for your server to authenticate clietn certificates, you will need to set the list of trusted CAs root certificates. You can either do it at build time, or at runtime.
You should set it using the
mbedtls_ssl_conf_ca_chain function at buid time, or setting a verify function at runtime using the
Mbed TLS Support
That would be step 1, I’ll try that out now.
Step 2, in my mind, would be to whitelist the specific certificates that I want to authorize. Do I really have to keep a whitelist in my server, or is there a way to embed that information in the client certificates themselves ?
E.g. if I were to check the email addresses in the client certificates and have my server only authorize access if they match a criterium ?
You don’t whitelist the certificates, but the trusted root certificates. This should be only the CA root certificates which you want to authorize and support.
You may consider using the
MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE extension in your client certificate.
Also, you may supply your own verification callback, in addition to the default one, that will do your desired functionality. This callback will be called, after all the chain verification.
Thanks again, Ron.
I’ll try to hit the same nail again with other words, I’m sure I’ll end up understanding.
You describe the calls I should use, and ultimately I can indeed write my verification callback.
This will only be called if the client certificate is valid, so I should implement only business logic from that point on.
My business logic is to verify that the client is one of a set of clients that I trust. I called that a whitelist earlier. This is the easy way to think about it : e.g. only allow (a specific app on) my own smartphone to access the server. Given that ACME certificates need to be renewed periodically, this introduces a maintenance problem with that list.
So is there another way for me to screen the client certificate ? See my remark about the embedded email address.
Or is that a very bad design idea ?
You can put your business logic in the verification callback I referenced in previous post.
However, the documentation states:
* If set, the provided verify callback is called for each
* certificate in the peer's CRT chain, including the trusted
* root. For more information, please see the documentation of
* \c mbedtls_x509_crt_verify().
So you will probably need to check also whether it is root\intermediate or not.
Please also read documentation to understand how to implement this callback.