I'm currently tinkering on what is effectively a chat server. Since I do not want to expose my users too much, I added TLS encryption to it using LibreSSL's fork of the OpenSSL library. The rest of the code appears to work fine, but I think I am not doing the certificates correctly.
I have a private/public certificate on the server which should be used not only to encrypt the communication, but also to ensure the server is really who the client wanted to talk to. And that's the part I can't figure out:
How do I give the server's public key to the client? It needs it to verify that it's talking to the right server. Or should I be doing something else, maybe involving the root CA's certificate? Is there API to provide that? I can package the public key with the executable as a
.pem
, but I can't find the API to tell OpenSSL about a public server key to use for client requests, or the root CA.How do I get the system's certificate for the client? Right now I just created one in a
.pem
file, but I don't really want to have to build a new download with a unique certificate for every user downloading the client. Surely there's a way to get "the current user's certificate" or auto-generate one for this use via some OpenSSL API?
If anyone could point me at the right API to use, that'd be great! I'd also take clues, links to similar questions on SO, tutorials, pointers at books aimed at OpenSSL-crypto-beginners, answers or sample code.
Currently, I'm using both SSL_CTX_use_certificate_file()
and SSL_CTX_use_PrivateKey_file()
to set certificates in both the client and the server program. You can see the code in the above linked Github chat server repository, in eleven_session.cpp
Thanks to SteffenUllrich and schacker22 for helping me with this issue. Here's the solution I cobbled together with their guidance:
After connecting, the client uses
BIO_new(BIO_s_file())
,BIO_read_filename()
andPEM_read_bio_X509_AUX()
to load the public certificate of the server from a PEM file, then compares it to the certificate returned bySSL_get_peer_certificate()
usingX509_cmp()
. If that doesn't give 0, the client aborts the connection because it is not talking to the correct server.Only the server gets a certificate, which I set using
SSL_CTX_use_certificate_file()
(public) andSSL_CTX_use_PrivateKey_file()
to point to the same PEM file containing both the public and private key.I decided not to use the verify callback, as it would replace the existing certificate verification, so I'd have to do that part as well. The
load_cert()
function in LibreSSL'sapps.c
file was a great help in figuring out how to load the certificate.If you're interested in seeing the final source code, it's publicly available from my Git repository for the eleven chat server and client.
This is my first time working with SSL sockets, so if you spot anything wrong here, please let me know. The whole point of this exercise is to learn how to do it right.