[PATCH] arm64: random: implement arch_get_random_int/_long based on RNDR
Andre Przywara
andre.przywara at arm.com
Fri Jan 14 07:07:25 PST 2022
On Thu, 13 Jan 2022 14:12:39 +0100
Ard Biesheuvel <ardb at kernel.org> wrote:
Hi,
> When support for RNDR/RNDRRS was introduced, we elected to only
> implement arch_get_random_seed_int/_long(), and back them by RNDR
> instead of RNDRRS. This was needed to prevent potential performance
> and/or starvation issues resulting from the fact that the /dev/random
> driver used to invoke these routines on various hot paths.
>
> These issues have all been addressed now [0] [1], and so we can wire up
> this API more straight-forwardly:
>
> - map arch_get_random_int/_long() onto RNDR, which returns the output of
> a DRBG that is reseeded at an implemented defined rate;
> - map arch_get_random_seed_int/_long() onto the TRNG firmware service,
> which returns true, conditioned entropy, or onto RNDRRS if the TRNG
> service is unavailable, which returns the output of a DRBG that is
> reseeded every time it is used.
>
> [0] 390596c9959c random: avoid arch_get_random_seed_long() when collecting IRQ randomness
> [1] 2ee25b6968b1 random: avoid superfluous call to RDRAND in CRNG extraction
>
> Cc: Andre Przywara <andre.przywara at arm.com>
> Cc: Mark Brown <broonie at kernel.org>
> Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
Looks alright to me, at least from the code point of view: I am not a
"crypto guy".
Reviewed-by: Andre Przywara <andre.przywara at arm.com>
Cheers,
Andre
> ---
> arch/arm64/include/asm/archrandom.h | 45 +++++++++++++++++---
> 1 file changed, 39 insertions(+), 6 deletions(-)
>
> diff --git a/arch/arm64/include/asm/archrandom.h b/arch/arm64/include/asm/archrandom.h
> index 09e43272ccb0..d1bb5e71df25 100644
> --- a/arch/arm64/include/asm/archrandom.h
> +++ b/arch/arm64/include/asm/archrandom.h
> @@ -42,13 +42,47 @@ static inline bool __arm64_rndr(unsigned long *v)
> return ok;
> }
>
> +static inline bool __arm64_rndrrs(unsigned long *v)
> +{
> + bool ok;
> +
> + /*
> + * Reads of RNDRRS set PSTATE.NZCV to 0b0000 on success,
> + * and set PSTATE.NZCV to 0b0100 otherwise.
> + */
> + asm volatile(
> + __mrs_s("%0", SYS_RNDRRS_EL0) "\n"
> + " cset %w1, ne\n"
> + : "=r" (*v), "=r" (ok)
> + :
> + : "cc");
> +
> + return ok;
> +}
> +
> static inline bool __must_check arch_get_random_long(unsigned long *v)
> {
> + /*
> + * Only support the generic interface after we have detected
> + * the system wide capability, avoiding complexity with the
> + * cpufeature code and with potential scheduling between CPUs
> + * with and without the feature.
> + */
> + if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndr(v))
> + return true;
> return false;
> }
>
> static inline bool __must_check arch_get_random_int(unsigned int *v)
> {
> + if (cpus_have_const_cap(ARM64_HAS_RNG)) {
> + unsigned long val;
> +
> + if (__arm64_rndr(&val)) {
> + *v = val;
> + return true;
> + }
> + }
> return false;
> }
>
> @@ -71,12 +105,11 @@ static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
> }
>
> /*
> - * Only support the generic interface after we have detected
> - * the system wide capability, avoiding complexity with the
> - * cpufeature code and with potential scheduling between CPUs
> - * with and without the feature.
> + * RNDRRS is not backed by an entropy source but by a DRBG that is
> + * reseeded after each invocation. This is not a 100% fit but good
> + * enough to implement this API if no other entropy source exists.
> */
> - if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndr(v))
> + if (cpus_have_const_cap(ARM64_HAS_RNG) && __arm64_rndrrs(v))
> return true;
>
> return false;
> @@ -96,7 +129,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
> }
>
> if (cpus_have_const_cap(ARM64_HAS_RNG)) {
> - if (__arm64_rndr(&val)) {
> + if (__arm64_rndrrs(&val)) {
> *v = val;
> return true;
> }
More information about the linux-arm-kernel
mailing list