[PATCH] ARM: implement support for SMCCC TRNG entropy source

Ard Biesheuvel ardb at kernel.org
Tue Oct 6 06:40:24 EDT 2020


Implement arch_get_random_seed_*() for ARM based on the firmware
or hypervisor provided entropy source described in ARM DEN0098.

This will make the kernel's random number generator consume entropy
provided by this interface, at early boot, and periodically at
runtime when reseeding.

Cc: Andre Przywara <andre.przywara at arm.com>
Cc: Linus Walleij <linus.walleij at linaro.org>
Cc: Russell King <linux at armlinux.org.uk>
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
Note that this depends on changes to include/linux/arm-smccc.h that
are still under review.

 arch/arm/Kconfig                  |  4 ++
 arch/arm/include/asm/archrandom.h | 55 ++++++++++++++++++++
 arch/arm/kernel/Makefile          |  1 +
 arch/arm/kernel/random.c          | 28 ++++++++++
 arch/arm/kernel/setup.c           |  3 ++
 5 files changed, 91 insertions(+)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index e00d94b16658..dd67500ca8c9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1682,6 +1682,10 @@ config STACKPROTECTOR_PER_TASK
 	  Enable this option to switch to a different method that uses a
 	  different canary value for each task.
 
+config ARCH_RANDOM
+	def_bool y
+	depends on HAVE_ARM_SMCCC
+
 endmenu
 
 menu "Boot options"
diff --git a/arch/arm/include/asm/archrandom.h b/arch/arm/include/asm/archrandom.h
new file mode 100644
index 000000000000..0fd6de1179f4
--- /dev/null
+++ b/arch/arm/include/asm/archrandom.h
@@ -0,0 +1,55 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARCHRANDOM_H
+#define _ASM_ARCHRANDOM_H
+
+#ifdef CONFIG_ARCH_RANDOM
+
+#include <linux/arm-smccc.h>
+#include <linux/kernel.h>
+
+extern bool have_arch_random;
+
+static inline bool __must_check arch_get_random_long(unsigned long *v)
+{
+	return false;
+}
+
+static inline bool __must_check arch_get_random_int(unsigned int *v)
+{
+	return false;
+}
+
+static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
+{
+	struct arm_smccc_res res;
+
+	if (!have_arch_random)
+		return false;
+
+	arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_RND32, 8 * sizeof(*v), &res);
+
+	if (res.a0 != 0)
+		return false;
+
+	*v = res.a3;
+	return true;
+}
+
+static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
+{
+	return arch_get_random_seed_long((unsigned long *)v);
+}
+
+void init_arch_random(void);
+
+#else
+
+static inline bool have_arch_random(void)
+{
+	return false;
+}
+
+static inline void init_arch_random(void) { }
+
+#endif /* CONFIG_ARCH_RANDOM */
+#endif /* _ASM_ARCHRANDOM_H */
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 89e5d864e923..11b13f0e7627 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -105,5 +105,6 @@ obj-$(CONFIG_SMP)		+= psci_smp.o
 endif
 
 obj-$(CONFIG_HAVE_ARM_SMCCC)	+= smccc-call.o
+obj-$(CONFIG_ARCH_RANDOM)	+= random.o
 
 extra-y := $(head-y) vmlinux.lds
diff --git a/arch/arm/kernel/random.c b/arch/arm/kernel/random.c
new file mode 100644
index 000000000000..6f1e6eb57ae6
--- /dev/null
+++ b/arch/arm/kernel/random.c
@@ -0,0 +1,28 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/arm-smccc.h>
+#include <linux/kernel.h>
+#include <asm/archrandom.h>
+
+#define ARM_SMCCC_TRNG_MIN_VERSION	0x10000UL
+
+bool __ro_after_init have_arch_random;
+
+void __init init_arch_random(void)
+{
+	struct arm_smccc_res res;
+
+	arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_VERSION, &res);
+
+	if ((s32)res.a0 >= ARM_SMCCC_TRNG_MIN_VERSION) {
+		/* double check that the 32-bit flavor is available */
+		arm_smccc_1_1_invoke(ARM_SMCCC_TRNG_FEATURES,
+				     ARM_SMCCC_TRNG_RND32,
+				     &res);
+		if ((s32)res.a0 >= 0)
+			have_arch_random = true;
+	}
+
+	pr_info("SMCCC TRNG entropy source %sdetected\n",
+		have_arch_random ? "" : "not ");
+}
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index bdba280a569d..c08574cad748 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -31,6 +31,7 @@
 #include <linux/psci.h>
 
 #include <asm/unified.h>
+#include <asm/archrandom.h>
 #include <asm/cp15.h>
 #include <asm/cpu.h>
 #include <asm/cputype.h>
@@ -1148,6 +1149,8 @@ void __init setup_arch(char **cmdline_p)
 
 	arm_dt_init_cpu_maps();
 	psci_dt_init();
+	init_arch_random();
+
 #ifdef CONFIG_SMP
 	if (is_smp()) {
 		if (!mdesc->smp_init || !mdesc->smp_init()) {
-- 
2.17.1




More information about the linux-arm-kernel mailing list