Author Archives: Simon Waters

OpenSSL vs LibreSSL before the 2nd critical is revealed

No doubt the latest critical vulnerability on OpenSSL will reopen old debates. Should we use open source software? David Wheeler suggests closed source code is about as bad on average but you can’t test it as easily and it often uses open source code anyway (sometimes outside of permitted license arrangements). Should we write application code, especially network or cryptographic code in C? Cryptographic code has its own challenges in optimisation and avoiding timing attacks where not being too far from the metal has some advantages. I doubt C is still the best language for all aspects of OpenSSL but despite being experienced in lots of IT and IT Security I will leave that debate to cryptographers and specialists. I have views, they are probably wrong.

One person on Twitter suggested OpenSSL and other TLS libraries implemented in C are much of a muchness. Presumably OpenSSL and LibreSSL. Now this is something I think I can make a stab at assessing. LibreSSL is a fork from 2014, a fair amount has changed in TLS since then so these tools are not identical, but any C programmer tasked with implementing TLS in an application likely has this choice available.

OpenSSLLibreSSL
Version3.0.53.5.3
Download integrity availableSHA256, PGP sigSHA256, PGP sig
Size15MB3.9MB
CVE (2015-2022 OpenSSL)1166 (+one in 2014)
Avg CVSS Score5.95
Configure and build time16m34s9m17s
Test time17m2s2m32s
Tests3299102
libcrypto.so size (*inc debug)5MB9.4MB*
SHA256 benchmark 8192 bytes (bigger is better)12126886906
Ciphers146121
libssl/libtls lines of code (*.c)5525445269
Flawfinder findings per 1000 linesssl 7.25
(no tls)
crypto 7.74
ssl 5.10
tls 9.35
crypto 7.64
Comparison of OpenSSL and LibreSSL

First thing to note on unpacking is the size difference, and whilst much of LibreSSL is smaller than the corresponding OpenSSL equivalent the bulk of that difference is that the OpenSSL tarball ships a lot of test data, including scripts to fuzz a lot of the implementation. OpenSSL also ship manual pages for all the various C calls in the tarball. So the difference is not bloat but purpose.

CVE counting is notoriously tricky as it reflects both attention to, processes, and vulnerability of the product. Both products clearly having CVE reported, no high scoring issues in LibreSSL yet. OpenSSL loses out on history, since version 3 is a major piece of work it might arguably be fairer to compare since September 2021, and bugs only in 3, when it still does badly in the comparison. Clearly OpenSSL is more widely used than LibreSSL, although with Apple and OpenBSD (and thus OpenSSH) LibreSSL is used in plenty of high profile situations.

LibreSSL builds faster, ships and runs with fewer tests, includes debugging information by default. I noted a small number of warnings compiling LibreSSL (none for OpenSSL), some from DJB’s ChaCha20 code which has a slightly different coding convention utilising GCC attributes.

Diving into ChaCha20 is instructive, LibreSSL has taken the author’s C code and stuck it in “chacha-merged.c” largely unchanged. OpenSSL has a re-implementation in “chacha_enc.c”, plus a sub-folder with various (presumably) hand coded or hand optimised assembler versions and bench-marking tools to show on which CPUs they outperform the C version compiled with GCC 4.8 dated 2015. So here we have a real difference between the two libraries, a trade-off between greater complexity and maintenance versus performance. Quick web search shows only a handful of complaints where some had noticed that LibreSSL migration had slowed down VPNs or digital checksums.

Ciphers were crudely counted from the command line list, OpenSSL offers ARIA and SEED, both South Korean originated ciphers. A figment of old export controls on stronger cryptography, but this might sway the opinion of people choosing a library if South Korean interoperability is key.

Flawfinder was just the first C static analysis tool to hand that didn’t require setup. Flawfinder results are quoted as raw numbers. David Wheeler says “an idiot with a tool is still an idiot”. So I tried to look closer and not be too big an idiot.

A lot of these flawfinder results are clearly false positives where the tool has misunderstood the code. This is of course what you would expect if both teams are using any sort of static source code analysis tools (including GCC warnings). All the high level issues in LibreSSL tls were immediately recognisable as false positives, so the high score for “libtls” isn’t meaningful in my view. The high risk issues in OpenSSL libraries included a bunch of C string functions which are subject of much secure coding debate. So this approach does reveal some of the secure coding practices that OpenBSD have applied to harden the code base.

At this point I was minded that LibreSSL is smaller and simpler, and has had some C safe coding practices applied, but slower and less featured. In my own C code not following these safe coding practices has generated security issues so I see the value. But it still isn’t quite clear to me why it has so many fewer CVEs. So I figured visit bugs which were found to be present at the fork (1.0.1g) and in v3 of OpenSSL and see why they aren’t a problem in LibreSSL. This seemed a simple idea but for the recent CVE the OpenSSL report doesn’t analyse if it was present before 1.0.2. So I assumed any present at 1.0.2 may be present in 1.0.1.g unless there is a specific statement to the contrary.

Selected commentary

CVE-2022-2068
OpenSSL Commit ce60b13707add7e6b54c5817376234c4043506ed
File not present in LibreSSL

CVE-2022-1292
OpenSSL commit 7c33270707b568c524a8ef125fe611a8872cb5e8
File not present in LibreSSL

CVE-2022-0778
OpenSSL commit 9eafb53614bf65797db25f467946e735e1b43dc9
The vulnerable code appears to be present in LibreSSL unaltered.

CVE-2021-23841
OpenSSL commit 122a19ab48091c657f7cb1fb3af9fc07bd557bbf
The added check is missing in LibreSSL
The notes say it isn’t called directly, so it affected 3rd party apps calling relevant function.
The CVE report documents another OpenSSL commit, not found in logs.

CVE-2021-23840
OpenSSL commit c9fb704cf3af5524eb8e79961e31b60eee8c3c47
Code is too diverse to immediately see if the issue was present.

CVE-2020-1971
OpenSSL commit b33c48b75aaf33c93aeda42d7138616b9e6a64cb
File not present in LibreSSL

CVE-2020-1968
Raccoon Attack a protocol bug, fixed by disabling the method used.
I believe these methods weren’t implemented in LibreSSL

Of the most recent CVEs ~75% appear in code that was added to OpenSSL or removed from LibreSSL since the fork. Of the remaining issues several were unfixed in LibreSSL although they were relatively minor issues or in code that isn’t called directly by LibreSSL. This suggests that counting CVEs may be giving a slightly rosy view of LibreSSL but not so rosy it isn’t clearly better from a security perspective. Some caution is required as recent CVEs will by the nature of forks have fewer issues in common than earlier ones (someone else can look at the 2015-2018 CVEs).

Conclusions

Some were critiquing the code because it is C, my brief inspection suggests that OpenBSD security folk know how to audit and fix C code, and they have addressed many of the obvious C related risk areas. Likely some of those changes weren’t strictly needed but it is easier to change than to rely on code staying safe in future. I’m not getting further into should we write network apps in C debate here.

LibreSSL clearly shuns performance and features for security and maintainability.

Compared to many large C code projects both appear to be developed with disciplined processes, but OpenSSL is consistently adding security vulnerabilities in a manner that LibreSSL isn’t. I note in passing that OpenBSD are not secretive about what they do to audit C code, or precious about people taking their improvements into their own code, and the licensing doesn’t forbid that either.

If you are grabbing libcrypto for cryptography in C, then OpenSSL may occasionally be preferable as the differences between them in the security arena are less stark and the performance edge or features may matter. However that presumes a cryptography use case where security aspects aren’t as crucial as performance, those exist, such as some types of storage encryption or ransomware.

If you after implementing TLS in C, or binding to a C library for TLS, than LibreSSL is likely to be slower but more secure, and for most network bound TLS that is probably fine, especially in client applications. Also the security benefits of LibreSSL may justify cross-porting any missing features you need.

It looks like at least one known cryptographic issue with the forked code base remains unfixed in LibreSSL, and likely more. A keen contributor could review all the OpenSSL CVEs that might apply and address them. But these are large libraries and there will always be issues, pragmatically you can limit exposure further by limiting the optional features at configuration and runtime to reduce further the amount of exposed code. For example a VPN product might only need to permit a small choice, or no runtime choice of ciphers and protocols.

Given the rapid progress in CPU technology, and the limited complaints about LibreSSL performance, one has to wonder for how many people is it worth trading security for performance.