[PATCH v3 1/9] stdlib: Add arc4random, arc4random_buf, and arc4random_uniform (BZ #4417)
Adhemerval Zanella
adhemerval.zanella@linaro.org
Wed Apr 20 12:38:13 GMT 2022
On 19/04/2022 18:52, H.J. Lu wrote:
> On Tue, Apr 19, 2022 at 2:29 PM Adhemerval Zanella via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
>>
>>
>> diff --git a/NEWS b/NEWS
>> index 4b6d9de2b5..4d9d95b35b 100644
>> --- a/NEWS
>> +++ b/NEWS
>> @@ -9,7 +9,9 @@ Version 2.36
>>
>> Major new features:
>>
>> - [Add new features here]
>> +* The functions arc4random, arc4random_buf, arc4random_uniform have been
>> + added. The functions use a cryptographic pseudo-random number generator
>> + based on ChaCha20 initilized with entropy from kernel.
> ^^^^^^^^ Typo.
>>
>> Deprecated and removed features, and other changes affecting compatibility:
Ack.
>> +
>> +/* Besides the cipher state 'ctx', it keeps two counters: 'have' is the
>> + current valid bytes not yet consumed in 'buf', while 'count' is the maximum
>> + number of bytes until a reseed.
>> +
>> + Both the initial seed an reseed tries to obtain entropy from the kernel
> ^^^^^^^^^^^^^^^^ Typo?
>> + and abort the process if none could be obtained.
>> +
>> + The state 'buf' improves the usage of the cipher call, allowing to call
>> + optimized implementations (if the archictecture provides it) and optimize
> ^^^^^^^^^^^^ Typo?
Ack.
>> +
>> + /* The general case. This algorithm follows Jérémie Lumbroso,
>> + Optimal Discrete Uniform Generation from Coin Flips, and
>> + Applications (2013), who credits Donald E. Knuth and Andrew
>> + C. Yao, The complexity of nonuniform random number generation
>> + (1976), for solving the general case.
>> +
>> + The implementation below unrolls the initialization stage of the
>> + loop, where v is less than n. */
>> +
>> + /* Use 64-bit variables even though the intermediate results are
>> + never larger that 33 bits. This ensures the code easier to
> than
Ack.
>> + compile on 64-bit architectures. */
>> + uint64_t v;
>> + uint64_t c;
>> +
>> + /* Initialize v and c. v is the smallest power of 2 which is larger
>> + than n.*/
>> + {
>> + uint32_t log2p1 = 32 - __builtin_clz (n);
>> + v = 1ULL << log2p1;
>> + c = bits & (v - 1);
>> + bits >>= log2p1;
>> + bits_length -= log2p1;
>> + }
>> +
>> + /* At the start of the loop, c is uniformly distributed within the
>> + half-open interval [0, v), and v < 2n < 2**33. */
>> + while (true)
>> + {
>> + if (v >= n)
>> + {
>> + /* If the candidate is less than n, accept it. */
>> + if (c < n)
>> + /* c is uniformly distributed on [0, n). */
>> + return c;
>> + else
>> + {
>> + /* c is uniformly distributed on [n, v). */
>> + v -= n;
>> + c -= n;
>> + /* The distribution was shifted, so c is uniformly
>> + distributed on [0, v) again. */
>> + }
>> + }
>> + /* v < n here. */
>> +
>> + /* Replenish the bit source if necessary. */
>> + if (bits_length == 0)
>> + {
>> + /* Overwrite the least significant byte. */
>> + random_bytes (&bits, 1);
>> + bits_length = CHAR_BIT;
>> + }
>> +
>> + /* Double the range. No overflow because v < n < 2**32. */
>> + v *= 2;
>> + /* v < 2n here. */
>> +
>> + /* Extract a bit and append it to c. c remains less than v and
>> + thus 2**33. */
>> + c = (c << 1) | (bits & 1);
>> + bits >>= 1;
>> + --bits_length;
>> +
>> + /* At this point, c is uniformly distributed on [0, v) again,
>> + and v < 2n < 2**33. */
>> + }
>> +}
>> +
>> +__libc_lock_define (extern , __arc4random_lock attribute_hidden)
>> +
>> +uint32_t
>> +__arc4random_uniform (uint32_t upper_bound)
>> +{
>> + uint32_t r;
>> + __libc_lock_lock (__arc4random_lock);
>> + r = compute_uniform (upper_bound);
>> + __libc_lock_unlock (__arc4random_lock);
>> + return r;
>> +}
>> +libc_hidden_def (__arc4random_uniform)
>> +weak_alias (__arc4random_uniform, arc4random_uniform)
>> diff --git a/stdlib/chacha20.c b/stdlib/chacha20.c
>> new file mode 100644
>> index 0000000000..af4ffa9860
>> --- /dev/null
>> +++ b/stdlib/chacha20.c
>> @@ -0,0 +1,163 @@
>> +/* Generic ChaCha20 implementation (used on arc4random).
>> + Copyright (C) 2022 Free Software Foundation, Inc.
>> + This file is part of the GNU C Library.
>> +
>> + The GNU C Library is free software; you can redistribute it and/or
>> + modify it under the terms of the GNU Lesser General Public
>> + License as published by the Free Software Foundation; either
>> + version 2.1 of the License, or (at your option) any later version.
>> +
>> + The GNU C Library is distributed in the hope that it will be useful,
>> + but WITHOUT ANY WARRANTY; without even the implied warranty of
>> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
>> + Lesser General Public License for more details.
>> +
>> + You should have received a copy of the GNU Lesser General Public
>> + License along with the GNU C Library; if not, see
>> + <http://www.gnu.org/licenses/>. */
>> +
>> +#include <array_length.h>
>> +#include <endian.h>
>> +#include <stddef.h>
>> +#include <stdint.h>
>> +#include <string.h>
>> +
>> +/* 32-bit stream position, then 96-bit nonce. */
>> +#define CHACHA20_IV_SIZE 16
>> +#define CHACHA20_KEY_SIZE 32
>> +
>> +#define CHACHA20_BLOCK_SIZE 64
>> +#define CHACHA20_BLOCK_WORDS (CHACHA20_BLOCK_SIZE / sizeof (uint32_t))
>> +
>> +#define CHACHA20_STATE_LEN 16
>> +
>> +/* Defining CHACHA20_XOR_FINAL issues the final XOR using the input as defined
>> + Sby RFC8439. Since the input stream will either zero bytes (initial state)
> by
Ack.
More information about the Libc-alpha
mailing list