On 8/15/13 11:51 PM, Patrick Pelletier wrote:
On Aug 15, 2013, at 10:38 PM, Nico Williams wrote:

Hmm, I've only read the article linked from there:
http://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html


Yeah, that's the only place I've seen it, and then the Google+ thread I
linked to is essentially the comment area for that post.  We (meaning
those of us commenting in the thread) haven't gotten any official answer
from Google, but Nikolay Elenkov has been very helpful in reconstructing
what seems to be happening.  We've exchanged a few more posts this
evening, and it appears that what's happening is that OpenSSL is
correctly self-seeding when system_server starts, but then system_server
forks (without execing) to start multiple processes, and these processes
are producing the same random sequence.  It's not yet entirely clear
why, since the OpenSSL source code looks like it's trying to be
fork-safe, but it appears that somehow in practice it's not succeeding.

s/system_server/zygote/

So, it appears that the problem is that since OpenSSL merely mixes in the pid to the existing random state, once the pids wrap, you will have had two processes that have generated the exact same random sequence, since they started with the same state (before the fork) and mixed in the same thing (the pid) after the fork, resulting in the same output. (This is in contrast to the approach of comparing the old and new pids, and doing a full reseed from /dev/urandom if they differ, which is what is done by Nick Mathewson's preliminary but already excellent-looking libottery.)

Nikolay Elenkov wrote a proof-of-concept that shows the pid-wrapping bug on Android, and then I took it one step further and wrote a proof-of-concept using OpenSSL in C, demonstrating that this is an underlying OpenSSL bug:

https://gist.github.com/ppelleti/6290984

An easy way to work around this, if you don't mind linking against pthreads, is to do this at the start of your application, after initializing OpenSSL:

typedef void (*voidfunc) (void);

if (ENGINE_get_default_RAND () == NULL)
  pthread_atfork (NULL, (voidfunc) RAND_poll, (voidfunc) RAND_poll);

But, of course, this ought to eventually be fixed in OpenSSL itself. (By using the pid-comparison trick that libottery uses, rather than just mixing in the pid.) I'm happy to submit a patch, if we think there's a good chance it would be considered?

--Patrick

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to