8 ms·
Common LibreSSL porting mistakes
- joosters 13y agoI thought /dev/urandom was meant to be just fine to use? http://www.2uo.de/myths-about-urandom/ http://www.2uo.de/myths-about-urandom/
- AaronFriel 13y agoProbably? It's fine to use /dev/urandom as a seed for random number generators, and for most applications it is safe. But I think within SSL/TLS implementations, there could be reasons to use their own cryptographic PRNG. For one thing, it's easier to reason about in a platform independent way. On modern Linux kernels, /dev/urandom is Probably Safe(tm). But what about everything else? That's where it gets murkier.
- paddyoloughlin 13y agoYour point seems valid, but from my reading the article appears to be explicitly describing Linux's /dev/urandom as a poor source of entropy. And it seems to be implying that while use of the arc4random_buf function is platform-independent, its implementation is permitted to be platform-specific.
- dlitz 13y ago> On modern Linux kernels, /dev/urandom is Probably Safe(tm). But what about everything else? That's where it gets murkier. No. That argument is exactly why I didn't just use /dev/urandom in PyCrypto's userspace RNG when I wrote it in 2008. The result was 5 years of a catastrophic failure in certain cases where fork() is used, even though I specifically designed it to cope with fork(). If someone hadn't made that argument, PyCrypto wouldn't have had a catastrophic failure mode that went undetected for 5 years until I stumbled across it: CVE-2013-1445 http://www.openwall.com/lists/oss-security/2013/10/17/3 http://www.openwall.com/lists/oss-security/2013/10/17/3 It is surprisingly difficult to implement a fast, reliable CSPRNG in a crypto library. There are innumerable things that can leak or corrupt your state, which compromises everything. You can leak state as a result of multithreading, fork(), signal-handling, etc., and libraries generally can't cope with that without having complicated APIs that application developers WILL misuse, causing silent security failures for end-users that go unnoticed for years. Plus, since you're still relying on /dev/urandom anyway, it really only gives you another way to fail. Arguably, there are so few people who understand this stuff that---at least in the FOSS world---we should kill off all but one implementation, so that the few of us who collectively understand how this stuff really works can focus on that one implementation.
- brigade 13y agoThey're probably referring to the bug/"feature" in Linux's implementation, which will happily return data before the system has enough entropy, instead of the sane behavior of blocking on only the first calls to it. Fortunately major distros work around this bug, so it's only an issue in unusual cases, like cloud VMs. See also http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/ http://sockpuppet.org/blog/2014/02/25/safely-generate-random...
- bostik 13y agoThat link lines out the single most important technical detail: > FreeBSD’s kernel crypto RNG doesn’t block regardless of whether you use /dev/random or urandom. Unless it hasn’t been seeded, in which case both block. This behavior, unlike Linux’s, makes sense. Linux should adopt it. It boils down to a tricky and potentially misleading interface. Abstractions are leaky beasts, and if there are many ways to get apparently identical results, we will use the one that most closely aligns with our usual way of thinking. Security is hard to get right. Cryptographic security depends on entropy, so getting sufficient entropy should be hard too. Right? Maybe the default answer should be "yeah, right" instead.
- sitkack 13y agoYour random number generator shouldn't block.
- pixl97 13y agoYour random number generator should give random numbers.
- mey 13y agoIt depends what type of random number you need. Having one interface isn't sufficient to describe the types of random applications need. A load balancing system probably doesn't have the same requirements as the RSA private key generation algorithm.
- derefr 13y agoWould it help to think of it as a (kernel) RNG daemon that you're trying to connect to, that doesn't finish starting up until it's seeded? That's basically what the blocking means, in the OpenBSD case.
- ndeine 13y ago/dev/urandom is a perfectly fine source of machine-generated randomness. In order to break /dev/urandom (but not /dev/random), you need to find a corner-case where you can break the cryptographically secure random number generator (CSPRNG) only when you can make certain guesses about its seed values. Since making those guesses about its seed values in the first place from the CSPRNG's output is a hard problem, and making an accurate guess about what eventually happened to the CSPRNG's output is a hard problem, this is pretty unlikely. But let's quote the kernel source on the matter[1], just to be clear: > The two other interfaces are two character devices /dev/random and /dev/urandom. /dev/random is suitable for use when very high quality randomness is desired (for example, for key generation or one-time pads), as it will only return a maximum of the number of bits of randomness (as estimated by the random number generator) contained in the entropy pool. > The /dev/urandom device does not have this limit, and will return as many bytes as are requested. As more and more random bytes are requested without giving time for the entropy pool to recharge, this will result in random numbers that are merely cryptographically strong. For many applications, however, this is acceptable. The real point to be made here is that, yes, /dev/random is theoretically better - but for many applications, letting /dev/random hang to wait for entropy is worse than having /dev/urandom use a CSPRNG in a way that is generally recognized to be secure. [1]: http://repo.or.cz/w/davej-history.git/blob/d0562c8dc:/drivers/char/random.c#l107 http://repo.or.cz/w/davej-history.git/blob/d0562c8dc:/driver... Edit: I would like to add that the original article is talking about using /dev/urandom to generate long-lived keys, not session keys or similar. In this case, the blocking is sometimes acceptable to generate appropriate entropy, since the fact that the key is long-lived implies that you don't do this very often. The argument for /dev/urandom only holds clout when you are making a tradeoff for non-blocking behavior (which is 99% of the time). As such, there is nothing wrong with being slightly paranoid and using /dev/random if you can afford the time spent collecting entropy.
- azinman2 13y agoThat's the best explanation of urandom vs random I've seen. Thanks!
- dspillett 13y agoMy understanding is that /dev/urandom is perfectly fine for almost all cases, including session keys and such but (if only for the sake of paranoia) for long lived keys it is worth the potential extra time waiting for /dev/random to serve what you need. The key to remember is that when the pool has sufficient entropy there is no difference between /dev/random and /dev/urandom, and if the pool is low then there is practically no difference between /dev/random and /dev/urandom - the quality of the PRNG means it is practically impossible to tell the difference between the two outputs (take a few thousand bits from each at a time and see if any statistical analysis can reliably tell the difference). It is increasingly common for CPUs and/or related chipsets to have a built in TRNG so keeping the entropy pool "topped up" is getting easier by feeding the pool from those using rng-tools. The SoC RPi's are based around has an RNG that pushes out more then 500kbit/s for instance.
- stouset 13y agoYour understanding is common, is stated explicitly in the manpage, and is unfortunately incorrect. /dev/random and /dev/urandom both even use the same CSPRNG behind the scenes. The former tries to maintain a count of the estimated entropy, but this is a meaningless distinction. CSPRNGs can't run out of entropy (for instance, a stream cipher is essentially a non-reseeded CSPRNG that works by generating an arbitrarily long sequence of computationally random bits that can be XORed against a plaintext). There might be a meaningful distinction if /dev/random provided "true" randomness (and could therefore be used for something like an OTP). But it doesn't. Both use the same CSPRNG algorithm.
- edwintorok 13y agoAssuming it has been seeded with enough entropy, if you just booted and haven't gathered/seeded with entropy yet, then /dev/urandom can potentially give you predictable values, whereas /dev/random would be safer as you'd wait until it has enough entropy. Too bad there isn't a way to tell whether the CSPRNG has been seeded or not.
- sitkack 13y ago
- callesgg 13y agoTo me it seams way to early to switch. Wait until libreSSL is battle tested, and we know if it is actually better or worse than the original.
- scrollaway 13y agoHow exactly do you think LibreSSL will be battle tested?
- callesgg 13y agoBy OpenBSD From http://www.libressl.org/ http://www.libressl.org/ "LibreSSL is primarily developed by the OpenBSD Project, and its first inclusion into an operating system will be in OpenBSD 5.6. "
- icebraining 13y agoOpenBSD will tests its implementation; it probably won't test ports to other OSs. So unless you use OpenBSD yourself, it won't be of much help.
- ForHackernews 13y agoMaybe that's an argument for more people running OpenBSD.
- i386 13y agoWill they? Point me to their CI server
- estebank 13y agoI can point you to their test rack: http://www.openbsd.org/images/rack2009.jpg http://www.openbsd.org/images/rack2009.jpg They run every version of OpenBSD in every machine they support, including 32bit SPARC, HP 300 and SGI. By running in all those machines they uncover subtle bugs that are made evident by architecture differences. Also, please see http://anoncvs.estpak.ee/cgi-bin/cgit/openbsd-src/tree/regress http://anoncvs.estpak.ee/cgi-bin/cgit/openbsd-src/tree/regre...
- bananas 13y agoI think some of this rant is invalid. If you look at the portable versions of their products they tend to ship a chunk of the OpenBSD library implementation with them to give consistency guarantees. Perhaps we need a consistent OpenBSD platform abstraction layer that gives solid guarantees?
- lplplplplp 13y agoMost is invalid in principle, perhaps not in practice (stupid as that is): 1. Ye shall use C11 memset_s(). 2. Ye shall (as you note) use a reallocarray() with OpenBSD-like (ANSI C) wrap checking. 3. Ye shall use /dev/urandom on Linux (I know you guys love him, see https://news.ycombinator.com/item?id=7361868 https://news.ycombinator.com/item?id=7361868 by tptacek) 4. Also, timingsafe_bcmp() is 3 lines of ANSI C99 code (minus variable and function declarations), include it with the code (as you note).
- clarry 13y agoHow many systems today get calloc() wrong? I checked the implementation of quite a few open source implementations a year or two back, and I don't recall seeing one get it wrong.
- jbert 13y agoWould it be possible to add system tests for some/all of these problems? e.g. a test which calls explicit_bzero() in a way which would have it optimised out in a platform with a low-quality port. A reasonably descriptive comment in the header (or failure text) of the test should guide a porter onto the path of wisdom. (If there is a problem in that the test would need to inspect the output of explicit_bzero(), hence negating the optimisation, it can be implemented as multiple processes).
- clarry 13y agoHow does the other process inspect the memory at the right time? How do you know all the scenarios where some compiler would optimize things out? It doesn't sound like it'd be easy to do a portable & reliable test. Testing that your entropy source is good sounds harder still. reallocarray() should be pretty easy to test though. But how many potential issues will your tests miss? If we had perfect test coverage for everything (and the tests were perfect, or we had test for them...), all software would be 100% bug-free. Tests might not hurt, but I am not sure trying to cater for braindead porters is a good idea. They might get the idea they're doing it right once they get the tests to pass one way or another... Reasonably descriptive commentary on the mentioned functions is there in the man pages. That is where porters should look.
- jbert 13y ago> How does the other process inspect the memory at the right time? There must be some side effect of the optimisation, otherwise there wouldn't be a problem. Detect that side effect (e.g. write a buffer of memory to disk, check timing of some code, ptrace-attach to the other process and inspect it, trigger a core dump and pick over the bones, code up an exploit which would work if the explicit_bzero() wasn't present) > How do you know all the scenarios where some compiler would optimize things out? You only really need to know one case where the compiler will, if the prevent-optimisation compiler magic isn't sprinkled on it. > Tests might not hurt, but I am not sure trying to cater for braindead porters is a good idea. They might get the idea they're doing it right once they get the tests to pass one way or another... At least they'd get an idea that something was up. I guess you might get away with: #ifndef OPENBSD #error "You can't just call bcopy() for explicit_bcopy() - see http://good-description-here why not" #endif
- frik 13y agoIs someone working on a Win32/64 port?
- valarauca1 13y agoThe problem with porting POSIX code to Win32/64 is other then windows not being POSIX which causes a lot of problems to start with. Windows lacks a lot of fundamental equals to Unix-Like system calls. I.E.: Windows has no equal to Fork, instead you need to use something like spawn(), and do some tricky memory cloning to get the same effect. In fact one could say there is no port of OpenSSL for windows. It hasn't been updated since 2004, and lacks 64bit support.
- cypher543 13y agoWhat are you talking about? OpenSSL doesn't need the fork system call and it already builds just fine on Win32 and Win64. You can even get pre-built binaries of the latest release: http://slproweb.com/products/Win32OpenSSL.html http://slproweb.com/products/Win32OpenSSL.html
- frik 13y agoHave you noticed the annoying "blink" (and the Comics Sans) on http://www.libressl.org http://www.libressl.org ? <blink>Coming Soon Please Be Patient</blink> As modern browser don't show the "blink" tag, I looked deeper in the source (CSS): blink { animation:blink 1s; animation-iteration-count: infinite; -webkit-animation:blink 1s; -webkit-animation-iteration-count: infinite; } @keyframes blink { 0%{opacity:0.0;} 50%{opacity:0.0;} 50.01%{opacity:1.0;} 100%{opacity:1.0;} } @-webkit-keyframes blink { 0%{opacity:0.0;} 50%{opacity:0.0;} 50.01%{opacity:1.0;} 100%{opacity:1.0;} } Well, later I saw their footer message.
- sanderjd 13y agoReminds me of the geocities bootstrap theme[0]. I'm surprised they don't have a scrolling marquee! [0]: http://code.divshot.com/geo-bootstrap/ http://code.divshot.com/geo-bootstrap/
- Cyph0n 13y agoThat's actually quite smart :)
- drdaeman 13y agoThat piece of CSS appeared relatively recently. Guess, it's a weird side effect - that page was supposed to annoy web hipsters, not challenge them to restore vintage tag behavior.
- Intermernet 13y agoThey need to add one of these: http://www.geocities.ws/disseminator1/under_construction_gifs/Webpage_construction.gif http://www.geocities.ws/disseminator1/under_construction_gif...
- malkia 13y agoNot sure whether it helps, but here is way to force a "C" function to never be inlined (by asking for it's address, and then calling it): http://www.flipcode.com/archives/Forcing_Functions_To_Be_Called_Non-inlined.shtml http://www.flipcode.com/archives/Forcing_Functions_To_Be_Cal...
- silvestrov 13y agoBoth of the methods on the page are easy to optimize out. GCC does optimize the first version out. These methods are not safe and they do not ensure that the compiler doesn't optimize out a call to bzero.
- malkia 13y agoI guess you are right. 10+ years ago that made the trick :) Probably there is some declspec/attribute for it.
- mzs 13y agoA bit off-topic (sorry) but the recent decision to allow ANSSI FRP256v1 in libressl worries me: http://opensslrampage.org/post/84442190366/add-support-for-the-french-anssi-frp256v1-elliptic http://opensslrampage.org/post/84442190366/add-support-for-t... I get that logic in the post, but there are concerns that FRP256v1 was weakened in the standard similarly to the FIPS curves. So I'm not sure that is good reasoning. Also I am unsure if the libressl/openssl implementation has good small subgroup attack defenses even.
- X-Istence 13y agoAre you suggesting they remove all curves that may be tainted and ship without them? Thereby forcing application developers that do want to use them to implement each and every single one themselves?
- mzs 13y agoI suppose so, but I'd rather people not use anything other than Goldilocks or 41417. I'm hoping that for those applications if they are forced so use something like p=192 they ignore the ECC option entirely, don't code it, and fallback to some interoperable DSA or RSA scheme instead in whatever protocol it may be. Maybe there is some case where that is not possible?
- derefr 13y agoHow about seeming to ship them, but when you try to compile with them, getting an error containing a link to a page that explains why you shouldn't be using them?
- loftsy 13y agoI've had a quick browse through the LibreSSL commits. There is some comedy gold in there. Check out: http://freshbsd.org/commit/openbsd/e5136d69ece4682e6167c8f4a8122270236898bf http://freshbsd.org/commit/openbsd/e5136d69ece4682e6167c8f4a... http://freshbsd.org/commit/openbsd/c862290df5533966091ded3906da184f1cac8675 http://freshbsd.org/commit/openbsd/c862290df5533966091ded390... http://freshbsd.org/commit/openbsd/a35e815be16befe27ee3f7623adfd5fc5e6693f4 http://freshbsd.org/commit/openbsd/a35e815be16befe27ee3f7623...
- micv 13y agoStuff like this is why you need fresh, objective eyes to review critical code. It's too easy to miss things when you're deep in the weeds.
- raverbashing 13y agoThe big-endian x86 is probably the worse one, but they're all gold
- Intermernet 13y agoThat big-endian bug is a perfect example of OCD in coding. "I can't ever reach that code path so I'll remove it". I have caught myself doing this in some cases. I once removed a test to see if the CSPRNG was actually working because the test coverage showed that I could never reach that code-path. I then realised that this needed to be there, because otherwise, if the CSPRNG ever stopped working, the code wouldn't know about it, and (maybe) start using streams of zeroes as it's entropy. Sometimes you need to remember that hardware can fail, or be compromised, even though in most cases it will just cause the program to crash.