
Qualys Security Advisory – LibreSSL - dfc
http://seclists.org/oss-sec/2015/q4/87
======
IgorPartola
Here we go. Another round of "damn it, it's written in C. that's the root of
all evil". I think by this point a Markov chain can easily generate responses
to the OpenSSL/LibreSSL vulnerability announcements so we don't have to. Yes,
C sucks because buffer overflows are still possible. That's by design. At the
same time, it goes something like this:

1\. OpenSSL (or this time LibreSSL) has a vulnerability discovered.

2\. Everyone gets in an uproar about how we need a clean implementation in a
language that prevents stupid errors.

3\. Someone suggests unit testing. tptacek tells them to go away.

4\. Someone actually points out a Haskell project
([https://news.ycombinator.com/item?id=7557089](https://news.ycombinator.com/item?id=7557089)).

5\. People poo poo any alternative to OpenSSL because it's not 100% feature
complete and besides the best crypto people are already working on OpenSSL so
what do these schmucks know?

6\. Someone points out that in higher level languages it's hard to write code
that is resistant against timing attacks. The discussion dies.

I see only two alternatives. Either as a community we actually stop bike
shedding and throw our weight behind a project that might actually become a
good alternative to OpenSSL, or we accept that the canonical TLS library will
be written in C and have bugs that are periodically discovered and quickly
patched.

~~~
briansmith
> 6\. Someone points out that in higher level languages it's hard to write
> code that is resistant against timing attacks. The discussion dies.

This doesn't matter, because the code that should be resistant to timing
attacks should be written in assembly language or a language specially
designed for that purpose (that doesn't exist yet) anyway. High-level
languages have ways of accessing code written in assembly language.

Anyway, my point is that all these things are solvable.

~~~
msbarnett
> This doesn't matter, because the code that should be resistant to timing
> attacks should be written in assembly language

This would put you right back into buffer overflow territory...

~~~
dbaupp
It's unfortunate, but the approach would hopefully be to write the smallest
possible primitives in assembly and then use a safer language for the rest of
the code that either doesn't need constant time guarantees, or gets those
guarantees by building on the primitives. This means that verification against
these sort of basic attacks can be focused on a much smaller amount of code,
rather than every single location in the whole code-base that manipulates
memory (as in C). (And, one can go a step further: extract assembly from some
higher-level language/DSL designed to create constant time code.)

In any case, the code in question for this post doesn't seem to be written to
be timing sensitive.

------
snksnk
> We would like to thank the LibreSSL team for their great work and their
> incredibly quick response, and Red Hat Product Security for promptly
> assigning CVE-IDs to these issues.

> Patch:
> [http://ftp.openbsd.org/pub/OpenBSD/patches/5.8/common/007_ob...](http://ftp.openbsd.org/pub/OpenBSD/patches/5.8/common/007_obj2txt.patch.sig)

> Releases:
> [http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/](http://ftp.openbsd.org/pub/OpenBSD/LibreSSL/)

I am glad that bugs are found. It shows that the audit is thorough, since bugs
can still be expected in LibreSSL (still quite new) and OpenSMTPD (audit was
explicitly requested).

------
kevan
> These vulnerabilities affect all LibreSSL versions, including LibreSSL 2.0.0
> (the first public release) and LibreSSL 2.3.0 (the latest release at the
> time of writing). OpenSSL is not affected.

~~~
Johnny_Brahms
I blame C. People that are much smarter than me fail at writing C. I am not
even trolling. It is a thought that has been gnawing away at me for some time.
I no longer think it's a question of being "good enough" to write good C code.

The only one I know of that has written almost bug-free C code is djb, and
that code is a fucking pain to look at regardless of what Aaron Schwartz said.
It is good, but it is not how anyone in their right mind writes C. If that is
what is required to write safe C then I'm all for using another language.

Edit: I do like how Zed Shaw writes C, but I have no idea if the software he
wrote is safe...

~~~
0x01
If we accept that C is here to stay for the time being, but is difficult to
manage memory, then why don't we use a mid-way solution?

Lua is built on c, and is much more (than C) memory safe. It retains all the
advantages of C (ie, can go anywhere), and we limit the C to 17.3k (as of
5.2.3) lines of c, which is relatively static (won't change, won't bloat in
the same way maintaining/building on current C SSL implementations), and could
allow us to handle memory safely.

I'm curious why this approach is not used. Portability? Proficiency? Lua is
quite possibly the most beautiful language to read. I can't see any downsides,
but I'll gladly be enlightened!

~~~
masklinn
Well for a start lua not having integers would be an issue when implementing
cryptographic primitives. The second issue is while lua is relatively
lightweight, carrying a full lua runtime for each of the libraries you're
using would still get unwieldy and costly, adding ~400K to each embedder
according to the About page ("Under 64-bit Linux, […] the Lua library takes
414K")

~~~
0x01
Apologies. I should have referenced Lua 5.3 instead as it has both integer and
bitwise operator support. This should satisfy the concerns regarding crypto
implementation.

As for the space considerations, I have two ways to reason this:

* Wouldn't it only take up 1x414K? If you create luaSSL as a drop in replacement to OpenSSL, you'd only need one copy in your filesystem, just as you only have one OpenSSL.

* Even _if_ you bloat your binary sizes by 414K per executable, isn't it worth it to go from "yes, it could be unsafe, we'll never know... let's wait for the next CVE" to 100% guaranteed no memory faults EVER? Nothing is free, and this could be a cheap price to pay for the guarantee of memory safety, and the implications that come with it.

Edit: wording

~~~
acveilleux
For crypto-primitives, you usually want them to be constant-time. This is
basically impossible to do in an interpreter or a JIT, indeed optimizing
compilers can and will optimize contant-time operations out so inline assembly
is commonly used.

~~~
0x01
Thank you for the info!

------
Confusion
So you'd think that if anything, these kinds of 'trivial' bugs, memory leaks
and buffer overflows, would not be present in LibreSSL. Especially not in the
same function. I wonder what went wrong and how it can be prevented.

~~~
byuu
I know this opinion won't be popular, and I know encryption is a very complex
topic, but ... TLS is simply _vastly_ too complicated. How many of us here
could write a TLS library even if we wanted to? So you end up with code so
complex that even the smartest people can barely understand it, let alone
debug it, and you get terrifyingly long CVE lists like for OpenSSL as a
result.

Compare that to a basic unencrypted HTTP server, which you can write in ~10KiB
of code. Complexity breeds these kinds of problems as a natural consequence.

I do know that verifiability is significantly easier than all of this
(signatures; hashing), but it's quite possible there is no simpler solution
for the secrecy aspect of TLS. I certainly wish there was more support for
HTTP+integrity, for those who didn't need the secrecy component. These
constant CVEs in every TLS library put our servers at risk in cases where
secrecy simply isn't necessary.

~~~
quonn
> Complexity breeds these kinds of problems as a natural consequence.

But the bugs described are not complex - they are local problems that can be
understood by just reading one function. The problem here is not complexity,
but size (not enough people spend enough time to review all of the code) and
the fact that the library is written in a language with manual memory
management and unsafe memory access.

> I do know that verifiability is significantly easier than all of this
> (signatures; hashing), but it's quite possible there is no simpler solution
> for the secrecy aspect of TLS.

In this case, the affected component was related to the identity part
(certificates), which are needed for verifiability. It was not directly
related to secrecy.

~~~
byuu
> the library is written in a language with manual memory management and
> unsafe memory access.

C's simplicity is certainly a blessing and a curse. Right now, I'm of the
opinion that C++ is the best we've got, even if not perfectly ideal. RAII,
shared pointers and smart containers with bounds checking allows you to keep
_nearly_ all of the performance without the drastic downsides of tracing
garbage collectors (obscene amounts of memory usage, nasty stalls, etc.)

And when you get into the really high-level languages (Python, Ruby), they
simply don't scale.

Everyone's darling right now is Rust. I still think it's too early in its life
to know how it'll play out (hot new languages follow a predictable path of
gaining negative baggage and shortcomings as they increase in real-world
usage), but I guess we'll see. Maybe it will indeed be a great panacea to
these issues.

> In this case, the affected component was related to the identity part
> (certificates), which are needed for verifiability. It was not directly
> related to secrecy.

Sure, but I'm generalizing here.

I can (and did) write a SHA256 hashing algorithm in 3KiB of code. Combined
with a package gist updater (these use signing with local keys for updates),
that's enough to secure binary package downloads on the BSDs over plain-text
HTTP.

Surely we can come up with a less complex system for verification alone.
Something akin to signify, perhaps. I know that doesn't solve how to
universally handle anonymously verifying public key authenticity, but surely
we can make something less complex than the clusterfuck that is TLS and the
CAs. Yet it doesn't seem there's much, if any, interest in even trying.
Everyone has hitched their wagons to HTTP/2 and mandatory TLS; which to me
feels like a huge step backward by means of making tech _vastly_ more complex.

~~~
riffraff
> And when you get into the really high-level languages (Python, Ruby), they
> simply don't scale.

I think you need to qualify what "scale" means in this context. Otherwise java
is, for all its warts, more or less as high level as ruby and python, and it's
probably been proven to scale up (to big machines, or many developers)
reasonably well.

~~~
taspeotis
[http://martinfowler.com/articles/lmax.html](http://martinfowler.com/articles/lmax.html)

> The system is built on the JVM platform ... in fact they ended up by doing
> all the business logic for their platform: all trades, from all customers,
> in all markets - on a single thread. A thread that will process 6 million
> orders per second using commodity hardware

~~~
royjacobs
To be fair, one of the ways they achieved this is by using off-heap memory
which needs to be handled in a way similar to how a C allocator would handle
it.

------
TwoBit
Why isn't static analysis or "sanitizers" finding this?

~~~
viraptor
Good question. I'd expect static analysis to find the leak automatically -
it's pretty obvious. The off by one however is behind many branches and only
detectable if you know the buffer size at the call site... I'd be surprised if
it triggered any scanning tool.

As a general answer though: static analysis will give you better answers if
you write your code in a clean and well structured way. If you goto from a
branch from a branch from a (potentially infinite) for-loop from a (not
counting) while-loop - good luck :) OpenSSL's OBJ_/BN_/... functions seem to
strive for complexity.

------
therealmarv
OS X 10.11 El Capitan is using LibreSSL: `ssh -V` How I patch this? ;) If
anybody has infos when Apple is releasing a fix please tell me.

~~~
netheril96
Install your own LibreSSL with Homebrew or wait for a fix from Apple.

I think Apple never discloses information about security vulnerabilities until
a fix is out.

------
jmnicolas
I have no knowledge of C, but reading their code I was surprised to see some
gotos ... is this OK in C to use goto ?

~~~
xorcist
Most languages use unconditional jumps to break flow when necessary, it might
be called "exception" instead of "goto" but it's conceptually the same thing.

~~~
AUmrysh
In many high level languages a break, continue, pass, that sort of thing
(where you want to skip or escape a loop iteration) is usually implemented
with a goto as well.

Also, a common use of goto in C is when you're doing something in nested for
loops and want to break out of all of them. A goto is actually much cleaner
here than using sentinel values or boolean flags, or naughty things like
setting your loop variables to be outside of the conditional bounds.

~~~
masklinn
Well if you go that way, fundamentally all structured programming techniques
are implemented with a goto, that's what jumps are.

------
richardwhiuk
So much for LibreSSL being a better choice than OpenSSL.

~~~
glass-
LibreSSL has had roughly half (22 to 43) as many vulnerabilities as OpenSSL
since the fork and, before this, 0 sev:high, compared to OpenSSL's 5 sev:high.

Would you really disregard all that because of a 1-byte buffer overflow and a
memory leak?

~~~
richardwhiuk
False:

CVE-2015-0204 affected LibreSSL, but they thought it was a low priority
vulnerability, when it actually is a high priority. They fixed it, didn't
notify upstream afaict and just issued a new release.

LibreSSL isn't a panacea, and based on that, they can't even classify
vulnerabilities correctly.

Most of the vulnerabilities in OpenSSL are in parts (e.g. DTLS) which are
disabled in lots of builds.

