2

I'm writing code for an embedded linux system, I have some code based on boost beast websockets and it's able to successfully connect to a couple of different TLS encrypted websites. However I've discovered another one, where it's not working, but only on the embedded linux platform.

I'm setting up the context like so;

boost::asio::ssl::context tlsCtx {boost::asio::ssl::context::tlsv12_client};
tlsCtx.set_options(boost::asio::ssl::context::default_workarounds
                 | boost::asio::ssl::context::no_sslv2
                 | boost::asio::ssl::context::no_sslv3
                 | boost::asio::ssl::context::no_tlsv1
                 | boost::asio::ssl::context::no_tlsv1_1
                 | boost::asio::ssl::context::single_dh_use);

tlsCtx.set_default_verify_paths();

and the code also performs

 ws_.next_layer().set_verify_mode(boost::asio::ssl::verify_peer);

This code works connecting to the website on my own laptop running Ubuntu. However on the embedded device, this fails with certificate verify failed. Initially I figured that the root authority certificate didn't exist on the embedded system, but did on mine. However both are using ca-certificates package. I discovered on my laptop that the file /etc/ssl/certs/ca-certificates.crt contains the root authority certificate to validate the certificate on the website.

Changing the code to

boost::asio::ssl::context tlsCtx {boost::asio::ssl::context::tlsv12_client};
tlsCtx.set_options(boost::asio::ssl::context::default_workarounds
                 | boost::asio::ssl::context::no_sslv2
                 | boost::asio::ssl::context::no_sslv3
                 | boost::asio::ssl::context::no_tlsv1
                 | boost::asio::ssl::context::no_tlsv1_1
                 | boost::asio::ssl::context::single_dh_use);

tlsCtx.load_verify_file("/etc/ssl/certs/ca-certificates.crt");

Works on both my laptop and the embedded device. However, I need to support all TLS encrypted websites and not just this one. So I'm using set_default_verify_paths to include the root authority certificates not included in the ca-certificates.crt file.

So updating the code to this;

boost::asio::ssl::context tlsCtx {boost::asio::ssl::context::tlsv12_client};
tlsCtx.set_options(boost::asio::ssl::context::default_workarounds
                 | boost::asio::ssl::context::no_sslv2
                 | boost::asio::ssl::context::no_sslv3
                 | boost::asio::ssl::context::no_tlsv1
                 | boost::asio::ssl::context::no_tlsv1_1
                 | boost::asio::ssl::context::single_dh_use);

tlsCtx.set_default_verify_paths();
tlsCtx.load_verify_file("/etc/ssl/certs/ca-certificates.crt");

I had assumed would support all scenarios, however it works on my development laptop but with the embedded device, I get certificate verify failed.

I know the correct root authority certificate is on the embedded system but it doesn't appear to want to work when I'm including all of the default verifications paths too. Does anyone know why this would be?

Alex
  • 669
  • 15
  • 37
  • Offtopic: adding `using boost::asio::ssl::context;` in scope of function should made this more readable. – Marek R Jun 23 '21 at 17:27

2 Answers2

1

I'd add the missing root certificate on the device. Since strangely /etc/ssl/certs already contains the .crt file for it, perhaps you just need to re-run c_rehash?

Depending on your distribution (which you strangely neglect to mention?) you can also have a utility like update-ca-certificates doing that, and more

sehe
  • 374,641
  • 47
  • 450
  • 633
  • Laptop distro is Ubuntu and embedded device is buildroot. Yes the root authority certificate appears to be already on the device, but ignored when I call 'set_default_verify_paths'. – Alex Jun 24 '21 at 20:03
  • @Alex That's why I suspect the hash index is not up-to-date. It could be a defect in the respective buildroot package (? if that's applicable). – sehe Jun 24 '21 at 22:37
  • 1
    This turned out to work if I then explicitly included `/etc/ssl/certs/ca-certificates.crt` with `tlsCtx.load_verify_file`, the buildroot package appears to be the same as the package used in Ubuntu. I guess something went wrong when I tried it before, but I've left it like this. – Alex Aug 03 '21 at 10:50
0

This is what I use in my development Linux workstation. I can't say anything about an embedded device. I use the update-ca-trust command to update the certificates. I think it is a good practice to create a crontab entry to deal with update-ca-truston a daily basis.

auto const cert_file_name = "ca-bundle.trust.crt"s; // or whatever
const char *dir = getenv(X509_get_default_cert_dir_env());
if (!dir)
    dir = X509_get_default_cert_dir();

auto cert_complete_path = std::string{dir} + "/"s + cert_file_name;
ctx.load_verify_file(cert_complete_path);
Angelo
  • 51
  • 1
  • 5