Wednesday, May 21, 2014

LibreSSL porting update

Since these articles came out, I've noticed two broken ports I saw prior seem to have vanished. One port has seen significant improvement in response to these articles, although still has significant concerns. And worst of all, more ports are popping up.

The official team has since reiterated some of these concerns, and I also wrote twoarticles regarding some concerns with random data.

Unfortunately, many of these ports are continuing to rely on arc4random() implementations on certain OSs or from certain portability libraries. These OSs or libraries may be copying some or all of the code from OpenBSD, but they are not copying the implementation.

To demonstrate this, let's see how different implementations of arc4random() work across fork() using the following test code:

So in looking at this data, one can see that on OpenBSD the random data is utterly different between the parent and all the various children. However, in all the ports of the function, the parent and children all share the exact same state after the fork() call. This situation is fine for single-process programs, but is a disaster in multi-process ones.

Since LibreSSL is having its random needs all being supplied by arc4random*(), and it can be used by multi-process servers, there is a serious porting problem here.

I covered this problem without elaboration in my previous article. See there for some solutions. The OpenBSD team is saying randomness is the responsibility of the OS, and for many of the issues involved, they are quite right. However, remember your ports cannot necessarily rely on the random functions provided by your OS. Even if the OSs fix them in future versions, one still has to be mindful of porting to older ones, so ensure your port doesn't rely too much on the OS.

For FreeBSD (libbsd via FreeBSD) at least, the problem is that they ARE derived from the OpenBSD implementation. Unfortunately, they haven't pulled upstream changes since the fork fix went into OpenBSD in 2003.

In the case of FreeBSD and NetBSD, this seems to be because of (unfounded) concerns with the performance of getpid() (Someone should probably poke them and get them to update.) In the case of libbsd, this seems to be something the authors don't know about, so I'll try to push it upstream.

Whether FreeBSD is using an implementation that was derived from OpenBSD's implementation or not is NOT the issue. It is whether the implementation they're using mimics the same behavior as the CURRENT implementation within OpenBSD, not an implementation from 11 years ago.