Accepting non-self-signed server certificates for unknown CAs
I have run into a practical problem with mbedTLS and I would appreciate any input on that.
Let us say that the user wants to access a SSL/TLS protected service whose server certificate is not signed by a known CA. In such case, it is customary to show a warning dialog with an option to add a security exception. This is done by Mozilla, for example.
Let us say that the user accepts the security exception and thus indicates that the next handshakes using this server certificate should be considered OK.
As long as the server certificate is self-signed, I can do this in mbedTLS. I simply store the certificate to the disk and, when running the next connection attempt, I will parse the certificate file and add the certificate to the list of trusted CAs using the method mbedtls_ssl_conf_ca_chain.
This does not work for non-self-signed certificates, though. And thus the handshake will abort, unless I specify MBEDTLS_SSL_VERIFY_NONE or MBEDTLS_SSL_VERIFY_OPTIONAL in mbedtls_ssl_conf_authmode, which I do not want to do.
How to solve this situation?
Well, entering the certificate you want to trust in the CA list does not work as it's not the signer of the certificate.
The alternative that is used, is to add a verify callback with
mbedtls_ssl_conf_verify() and check the certificate fingerprint / hash there and then allow it.
Thank you for your tip. Is the optional verification function only invoked if verification of the entire chain with the known CA certificates fails?
Or is it so that when I register a custom verification function, that it supersedes the built-in verification and everything must be done within that function?
No, it is always invoked as a 'final' check on each certificate where you can modify the current flags for a certificate in the chain. So you can change the flags to 'trusted' for certificates with fingerprints you recognize.
Thank you. I am now experimenting with your suggestion.
I would like to ask about the meaning of individual parameters of the int(*)(void *, mbedtls_x509_crt *, int, uint32_t *) function.
void* is verification parameter, mbedtls_x509_crt * is the certificate being tested, int is what? Index within the certificate chain? uint32_t * are the flags which I can modify?
If there is a longer chain of certificates, will the method be invoked sequentially on all the certificates of the chain?
Also, if my custom verification fails, what should I return? MBEDTLS_ERR_X509_CERT_VERIFY_FAILED?
Please check out the mbedtls_x509_crt_verify() documentation