Aaron Conole <[email protected]> writes:

> Ilya Maximets <[email protected]> writes:
>
>> On 10/28/26 8:14 PM, Aaron Conole wrote:
>>> Until now, utilities wishing access to a quality source of
>>> cryptographically secure random numbers would have to either
>>> forego security and just use the xorshift, or use one of a
>>> few very slow entropy options like get_entropy_or_die or
>>> OpenSSL's RAND_bytes() calls.  Both of these are quality
>>> tested mechanisms, but the drawback is a very long time to
>>> execute (measured 10m iterations of rand_bytes taking
>>> roughly 5.14s to complete).
>>> 
>>> This change adds a ChaCha20 based CSPRNG, which is known
>>> to be a high quality CSPRNG.  The benefits are very fast
>>> execution time (the same 10m iterations only take 0.059s
>>> vs. the PRNG taking 0.018s).
>>> 
>>> The following references can help with understanding the
>>> implementation:
>>>  * RFC 8439, "ChaCha20 and Poly1305 for IETF Protocols"
>>>  * libevent/arc4random.c, "Arc4 random number generator for OpenBSD."
>>>  * glibc/stdlib/arc4random.c, "Psuedo random number generator"
>>>  * Ben Tasker, "Writing (and backdooring) a ChaCha20 based CSPRNG"
>>> 
>>> Assisted-by: LLM (claude, opencode, sonnet, opus, qwen3.8)
>>> Signed-off-by: Aaron Conole <[email protected]>
>>> ---
>>> v2->v3:
>>>   * Update the verbiage around the implementations origins
>>>   * Still exists the possiblity to abort on reseed
>>>   * Fixed the CHACHA_K_INPUT comment
>>>   * Fixed the chacha_sigma constant definition + comment
>>>   * Documented maximum length in csprng_random_bytes
>>>   * Introduce ovs_memzero that will clear memory without eliding
>>>     the operations
>>>   * Zero out the chacha20_block
>>
>> [...]
>>
>>> +struct csprng {
>>> +    uint32_t state[16];             /* ChaCha20 state:
>>> +                                     * constant|key|counter|nonce. */
>>> +    uint8_t buf[CSPRNG_BUFSZ];      /* Buffered keystream. */
>>> +    size_t pos;                     /* Next unused byte in 'buf'. */
>>> +    size_t served;                  /* Bytes served since last reseed. */
>>> +    int initialized;
>>> +};
>>> +
>>> +/* ChaCha20 constant: "expand 32-byte k".  Must be at least 16
>>> bytes + NUL. */
>>> +static const uint8_t chacha_sigma[] = "expand 32-byte k";
>>> +
>>> +/* Current random state. */
>>> +DEFINE_STATIC_PER_THREAD_DATA(struct csprng, cs_state, {
>>> .initialized = 0 });
>>
>> LLMs complain that this state is preserved on fork.  It's probably not a big
>> deal since there should be no cases where this code would be used
>> before forking
>> today, but maybe a bit of a trap.  Maybe we should make xfork_at()
>> call a special
>> function that clears the state if it was initialized before?
>
> It's a weird complaint.  Honestly, there isn't much that we can do if
> someone does a fork() unless we explicitly are only calling forks from
> our library.  But a code that can somehow do a fork() from a called
> library will still completely bypass any preventing measures we do here.
>
> The real way to do it safely is to use xmalloc() for the per-thread
> allocation and madvise(region, MADV_WIPEONFORK), I think.  Then even if
> a library we link do does a fork(), the pages are guaranteed to be
> wiped.

Okay - coffee kicked in.  madvise() MADV_WIPEONFORK is only linux from
my little bit of checking.  FreeBSD (and I think NetBSD maybe?) supports
using something like minherit(.., MAP_INHERIT_ZERO) instead.

So we can probably provide something like:

  xmalloc_fork_zero()

which either sets the minherit on the range, or sets madvise() to
wipeonfork and maybe that could be the "more portable" approach.

>> It's not the only place where we can fork, but it may be better to
>> convert other
>> place into xfork if needed in the future.
>>
>> WDYT?

There is also a pthread_atfork() function that takes a callback, and we
could use that to clear the state in the child through the child
function handler (IIUC).  That should run right after the fork()
completes.  We could use that instead.  Do you have a preference?

>> Best regards, Ilya Maximets.
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to