Daniel Shahaf wrote: > On Thursday, November 03, 2011 12:44 AM, "Jonathan Nieder" > <jrnie...@gmail.com> wrote:
>> Another possibility would be to enhance >> apr's random number source API to allow requesting random bytes >> without so much entropy (erandom/frandom) or without blocking on lack >> of entropy (urandom). > > Fixing this by extending APR's API sounds good. Would the change be > backportable to APR 1.4.x too? I think a proper fix is possible without changing APR's API. The calling sequence is something like this: state = apr_random_standard_new(pool); for (;;) { while (apr_random_secure_ready(state) == APR_ENOTENOUGHENTROPY) { apr_generate_random_bytes(buf, sizeof(buf)); apr_random_add_entropy(state, buf, sizeof(buf)); } apr_random_secure_bytes(state, ret, n); yield; } Justification: that is how /dev/random seems to be meant to be used (as source for a random seed, with userspace taking over after that). Actually, using apr_random_insecure_bytes without seeding the generator would be about as good, as far as I can tell. What is important is that a given <nonce, timestamp> pair is not likely to be repeated. Complications: - This involves application-local state. Making the PRNG state per-thread would be fussy. And on the other hand if it's global, synchronizing between threads could hurt performance. - Could be controversial on platforms "where the built-in strong random number generator works just fine without blocking applications all the time" (but aren't good random numbers a scarce resource almost everywhere?). [...] > Something tells me that when a cryptographic protocol calls for random > numbers then a quasiconstant or known value wouldn't do instead. Right. It's not as bad as it sounds because abusing this requires (1) intercepting and replaying challenge responses in real time (2) getting your <nonce, timestamp, hostname> tuple to match the one from the challenge you intercepted. On affected installations, both the nonce and timestamp are timestamps with 1-microsecond resolution. but it certainly looks like a problem to me. So how about this to start, to avoid providing people on platforms with !APR_HAS_RANDOM with a false sense of security? [[[ * subversion/libsvn_ra_svn/cram.c (make_nonce): Refuse to build if APR_HAS_RANDOM is unset, instead of falling back to using a timestamp as nonce. ]]] Index: subversion/libsvn_ra_svn/cram.c =================================================================== --- subversion/libsvn_ra_svn/cram.c (revision 1197294) +++ subversion/libsvn_ra_svn/cram.c (working copy) @@ -117,18 +117,10 @@ return svn_ra_svn_flush(conn, pool); } -/* If we can, make the nonce with random bytes. If we can't... well, - * it just has to be different each time. The current time isn't - * absolutely guaranteed to be different for each connection, but it - * should prevent replay attacks in practice. */ +/* Make the nonce with random bytes. */ static apr_status_t make_nonce(apr_uint64_t *nonce) { -#if APR_HAS_RANDOM return apr_generate_random_bytes((unsigned char *) nonce, sizeof(*nonce)); -#else - *nonce = apr_time_now(); - return APR_SUCCESS; -#endif } svn_error_t *svn_ra_svn_cram_server(svn_ra_svn_conn_t *conn, apr_pool_t *pool,