[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