Re: git: 9eecef052155 - main - Add an Armv8 rndr random number provider
Date: Wed, 15 Nov 2023 18:27:57 UTC
On 15 Nov 2023, at 18:12, Andrew Turner <andrew@FreeBSD.org> wrote: > > The branch main has been updated by andrew: > > URL: https://cgit.FreeBSD.org/src/commit/?id=9eecef052155646fbc5f8f533b952b372572d06a > > commit 9eecef052155646fbc5f8f533b952b372572d06a > Author: Andrew Turner <andrew@FreeBSD.org> > AuthorDate: 2023-11-15 17:42:02 +0000 > Commit: Andrew Turner <andrew@FreeBSD.org> > CommitDate: 2023-11-15 18:05:08 +0000 > > Add an Armv8 rndr random number provider > > Armv8.5 adds an optional random number generator. This is implemented > as two special registers one to read a random number, the other to > re-seed the entropy pool before reading a random number. Both registers > will set the condition flags to tell the caller they can't produce a > random number in a reasonable amount of time. > > Without a signal to reseed the entropy pool use the latter register > to provide random numbers to the kernel pool. If at a later time we > had a way to tell the provider if it needs to reseed or not we could > use the former. > > On an Amazon AWS Graviton3 VM this never failed, however this may not > be the case on low end CPUs so retry reading the random number 10 times > before returning an error. > > Reviewed by: imp, delphij (csprng) > Sponsored by: The FreeBSD Foundation > Sponsored by: Arm Ltd > Differential Revision: https://reviews.freebsd.org/D35411 > --- > sys/arm64/conf/std.dev | 1 + > sys/conf/files.arm64 | 2 + > sys/dev/random/armv8rng.c | 135 +++++++++++++++++++++++++++++++++++++++ > sys/dev/random/random_harvestq.c | 1 + > sys/modules/Makefile | 2 + > sys/modules/armv8_rng/Makefile | 11 ++++ > sys/sys/random.h | 1 + > 7 files changed, 153 insertions(+) > > diff --git a/sys/arm64/conf/std.dev b/sys/arm64/conf/std.dev > index 74d2407e0aec..0ebf2e775b11 100644 > --- a/sys/arm64/conf/std.dev > +++ b/sys/arm64/conf/std.dev > @@ -53,6 +53,7 @@ device vt_simplefb > > # Pseudo devices. > device crypto # core crypto support > +device armv8_rng # Armv8.5 rndr RNG > device loop # Network loopback > device ether # Ethernet support > device vlan # 802.1Q VLAN support > diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 > index 38b9e40463eb..9ccead6a98e1 100644 > --- a/sys/conf/files.arm64 > +++ b/sys/conf/files.arm64 > @@ -379,6 +379,8 @@ dev/psci/psci.c standard > dev/psci/smccc_arm64.S standard > dev/psci/smccc.c standard > > +dev/random/armv8rng.c optional armv8_rng !random_loadable > + > dev/safexcel/safexcel.c optional safexcel fdt > > dev/sdhci/sdhci_xenon.c optional sdhci_xenon sdhci > diff --git a/sys/dev/random/armv8rng.c b/sys/dev/random/armv8rng.c > new file mode 100644 > index 000000000000..3cca42a5bbf3 > --- /dev/null > +++ b/sys/dev/random/armv8rng.c > @@ -0,0 +1,135 @@ > +/*- > + * Copyright (c) 2022 The FreeBSD Foundation > + * > + * This software was developed by Andrew Turner under sponsorship from > + * the FreeBSD Foundation. > + * > + * Redistribution and use in source and binary forms, with or without > + * modification, are permitted provided that the following conditions > + * are met: > + * 1. Redistributions of source code must retain the above copyright > + * notice, this list of conditions and the following disclaimer. > + * 2. Redistributions in binary form must reproduce the above copyright > + * notice, this list of conditions and the following disclaimer in the > + * documentation and/or other materials provided with the distribution. > + * > + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND > + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE > + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE > + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE > + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL > + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS > + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) > + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT > + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY > + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF > + * SUCH DAMAGE. > + */ > + > +#include <sys/cdefs.h> > + > +#include <sys/param.h> > +#include <sys/systm.h> > +#include <sys/conf.h> > +#include <sys/kernel.h> > +#include <sys/lock.h> > +#include <sys/malloc.h> > +#include <sys/module.h> > +#include <sys/random.h> > + > +#include <machine/armreg.h> > + > +#include <dev/random/randomdev.h> > + > +static u_int random_rndr_read(void *, u_int); > + > +static bool has_rndr; > +static struct random_source random_armv8_rndr = { > + .rs_ident = "Armv8 rndr RNG", > + .rs_source = RANDOM_PURE_ARMV8, > + .rs_read = random_rndr_read, > +}; > + > +static inline int > +random_rndr_read_one(u_long *buf) > +{ > + u_long val; > + int loop, ret; > + > + loop = 10; > + do { > + __asm __volatile( > + ".arch_extension rng \n" > + "mrs %0, rndrrs \n" /* Read the random number */ > + "cset %w1, ne \n" /* 1 on success, 0 on failure */ > + ".arch_extension norng \n" > + : "=&r" (val), "=&r"(ret) :: "cc"); Early clobber doesn’t make sense with no inputs. Jess > + } while (ret != 0 && --loop > 0); > + > + if (ret != 0) > + *buf = val; > + > + return (ret); > +} > + > +static u_int > +random_rndr_read(void *buf, u_int c) > +{ > + u_long *b; > + u_int count; > + > + b = buf; > + for (count = 0; count < c; count += sizeof(*b)) { > + if (!random_rndr_read_one(b)) > + break; > + > + b++; > + } > + > + return (count); > +} > + > +static int > +rndr_modevent(module_t mod, int type, void *unused) > +{ > + uint64_t reg; > + int error = 0; > + > + switch (type) { > + case MOD_LOAD: > + has_rndr = false; > + if (get_kernel_reg(ID_AA64ISAR0_EL1, ®) && > + ID_AA64ISAR0_RNDR_VAL(reg) != ID_AA64ISAR0_RNDR_NONE) { > + has_rndr = true; > + random_source_register(&random_armv8_rndr); > + printf("random: fast provider: \"%s\"\n", > + random_armv8_rndr.rs_ident); > + } > + break; > + > + case MOD_UNLOAD: > + if (has_rndr) > + random_source_deregister(&random_armv8_rndr); > + break; > + > + case MOD_SHUTDOWN: > + break; > + > + default: > + error = EOPNOTSUPP; > + break; > + > + } > + > + return (error); > +} > + > +static moduledata_t rndr_mod = { > + "rndr", > + rndr_modevent, > + 0 > +}; > + > +DECLARE_MODULE(rndr, rndr_mod, SI_SUB_RANDOM, SI_ORDER_FOURTH); > +MODULE_VERSION(rndr, 1); > +MODULE_DEPEND(rndr, random_harvestq, 1, 1, 1); > diff --git a/sys/dev/random/random_harvestq.c b/sys/dev/random/random_harvestq.c > index 09b81950281b..dce0878513db 100644 > --- a/sys/dev/random/random_harvestq.c > +++ b/sys/dev/random/random_harvestq.c > @@ -385,6 +385,7 @@ static const char *random_source_descr[ENTROPYSOURCE] = { > [RANDOM_PURE_TPM] = "PURE_TPM", > [RANDOM_PURE_VMGENID] = "PURE_VMGENID", > [RANDOM_PURE_QUALCOMM] = "PURE_QUALCOMM", > + [RANDOM_PURE_ARMV8] = "PURE_ARMV8", > /* "ENTROPYSOURCE" */ > }; > > diff --git a/sys/modules/Makefile b/sys/modules/Makefile > index 3eff75312fd3..f9079498dc1f 100644 > --- a/sys/modules/Makefile > +++ b/sys/modules/Makefile > @@ -41,6 +41,7 @@ SUBDIR= \ > ${_arcmsr} \ > ${_allwinner} \ > ${_armv8crypto} \ > + ${_armv8_rng} \ > ${_asmc} \ > ata \ > ath \ > @@ -674,6 +675,7 @@ _cxgb= cxgb > > .if ${MACHINE_CPUARCH} == "aarch64" > _armv8crypto= armv8crypto > +_armv8_rng= armv8_rng > _dpaa2= dpaa2 > _sff= sff > _em= em > diff --git a/sys/modules/armv8_rng/Makefile b/sys/modules/armv8_rng/Makefile > new file mode 100644 > index 000000000000..29d2907aed06 > --- /dev/null > +++ b/sys/modules/armv8_rng/Makefile > @@ -0,0 +1,11 @@ > +# $FreeBSD$ > + > +.PATH: ${SRCTOP}/sys/dev/random > + > +KMOD= armv8_rng > +SRCS= armv8rng.c > +SRCS+= bus_if.h device_if.h > + > +CFLAGS+= -I${SRCTOP}/sys > + > +.include <bsd.kmod.mk> > diff --git a/sys/sys/random.h b/sys/sys/random.h > index 0e6ae02ac078..aa4457fc8c22 100644 > --- a/sys/sys/random.h > +++ b/sys/sys/random.h > @@ -102,6 +102,7 @@ enum random_entropy_source { > RANDOM_PURE_TPM, > RANDOM_PURE_VMGENID, > RANDOM_PURE_QUALCOMM, > + RANDOM_PURE_ARMV8, > ENTROPYSOURCE > }; > _Static_assert(ENTROPYSOURCE <= 32,