On Tue, Dec 21, 2010 at 07:45:09PM +0100, Kurt Knochner wrote: > 2010/12/21 Otto Moerbeek <o...@drijf.net> > > > > So, there is a lot of effort in get_random_bytes() to get "real random" > data > > > for the buffer and then the value of nanotime() is prepended to the > buffer? > > > That does not look right. Please consider: this buffer will be used as > key > > > for rc4_keysetup() and thus it should contain unrelated and > unpredictable > > > data. > > > > I don't know the answer to this question, but my guess is that the > > buffer is filled by nanotime() to cover the case that > > get_random_bytes() does not have enough entropy available, so at least > > some non-constant data is used. > > get_random_bytes() calls extract_entropy() which is a a loop around nbytes, > thus get_random_bytes() will most certainly deliver enough entropy.
extract_entropy() does not guarantee the collected bytes will have enough entropy. Think about situations very early in machine startup, where the state of things could be predictable. During multi-user startup OpenBSD will stir the random pool to ensure this does not happen, but there is a window where rnd(4) might not have collected enough entropy yet. For you remarks below I'll have to check some more things, don't have time for that now. -Otto > > So, why do we need a nanotime value in front of the buffer? I'm just > thinking about those weaknesses of RC4 if the initial key is not good/strong > enough? > > http://www.rsa.com/rsalabs/node.asp?id=2009 > > But then, this is "just" the initialization of the PRNG and not the > encryption itself, so maybe it has no meaning at all. > > > > HOWEVER, right after the call of rc4_crypt(), we call rc4_keysetup() > with > > > the same 'arc4random_state'. This makes the call to rc4_crypt() useless, > as > > > the data structure will be overwritten again with the init data of the > RC4 > > > function. > > > > rc4_crypt() changes both the state and the contents of buf, since buf is > > used both as source and destination. That buf is used by rc4_keysetup() > > to create a new state. So indeed the state is overwritten, but the > > contents of buf produced by rc4_crypt() is used to do that. So both > > calls serve their purpose. > > yes, you are right! I did not see the changes to buf in rc4_crypt(). Sorry > for that! > > But still, why is it done this way? > > I compared the implementation of arc4_stir with the one in libc > (src/lib/libc/crypt/arc4random.c). The implementations are somehow > different. > > The in libc the rc4 state is only initialized once at the first call of > arc4_stir() and then there are consecutive calls to arc4_addrandom() which > is the equivalent of rc4_crypt(). So, there is a difference in the > implementation. May this is just due to different authors. > > First question: Which one is the 'correct' implementation, as proposed in > Applied Cryptography (hint in libc -> arc4random.c)? > Second question: Does it matter if the implementation is different than the > one in Applied Cryptography? > > A last thing: > > From: src/lib/libc/crypt/arc4random.c > > arc4_stir(void) > { > <snip> > > /* > * Discard early keystream, as per recommendations in: > * http://www.wisdom.weizmann.ac.il/~itsik/RC4/Papers/Rc4_ksa.ps > */ > for (i = 0; i < 256; i++) > (void)arc4_getbyte(); > arc4_count = 1600000; > } > > > The first 256 Bytes will be skipped due to the mentioned paper. Similar code > exists in rnd.c. > > /* > * Throw away the first N words of output, as suggested in the > * paper "Weaknesses in the Key Scheduling Algorithm of RC4" > * by Fluher, Mantin, and Shamir. (N = 256 in our case.) > */ > rc4_skip(&arc4random_state, 256 * 4); > mtx_leave(&rndlock); > > However here, 1024 bytes (256 * 4) will be skipped. Maybe that's just a > misinterpretation of what a "word" is (byte or integer). > > Maybe I'm paranoid and see problems where there are none. But then, this is > part of the crypto code and there should be no open questions about the > implementation details. > > Regards > Kurt Knochner > > http://knochner.com/