]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[rng] Add RDRAND as an entropy source
authorMichael Brown <mcb30@ipxe.org>
Wed, 15 Feb 2023 22:43:33 +0000 (22:43 +0000)
committerMichael Brown <mcb30@ipxe.org>
Wed, 15 Feb 2023 22:43:33 +0000 (22:43 +0000)
Signed-off-by: Michael Brown <mcb30@ipxe.org>
src/arch/x86/core/rdrand.c [new file with mode: 0644]
src/arch/x86/include/bits/entropy.h
src/arch/x86/include/bits/errfile.h
src/arch/x86/include/ipxe/cpuid.h
src/arch/x86/include/ipxe/rdrand.h [new file with mode: 0644]

diff --git a/src/arch/x86/core/rdrand.c b/src/arch/x86/core/rdrand.c
new file mode 100644 (file)
index 0000000..29605ab
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2023 Michael Brown <mbrown@fensystems.co.uk>.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ *
+ * You can also choose to distribute this program under the terms of
+ * the Unmodified Binary Distribution Licence (as given in the file
+ * COPYING.UBDL), provided that you have satisfied its requirements.
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+/** @file
+ *
+ * Hardware random number generator
+ *
+ */
+
+#include <errno.h>
+#include <ipxe/cpuid.h>
+#include <ipxe/entropy.h>
+
+/** Number of times to retry RDRAND instruction */
+#define RDRAND_RETRY_COUNT 16
+
+/** Colour for debug messages */
+#define colour CPUID_FEATURES_INTEL_ECX_RDRAND
+
+/**
+ * Enable entropy gathering
+ *
+ * @ret rc             Return status code
+ */
+static int rdrand_entropy_enable ( void ) {
+       struct x86_features features;
+
+       /* Check that RDRAND is supported */
+       x86_features ( &features );
+       if ( ! ( features.intel.ecx & CPUID_FEATURES_INTEL_ECX_RDRAND ) ) {
+               DBGC ( colour, "RDRAND not supported\n" );
+               return -ENOTSUP;
+       }
+
+       return 0;
+}
+
+/**
+ * Disable entropy gathering
+ *
+ */
+static void rdrand_entropy_disable ( void ) {
+
+       /* Nothing to do */
+}
+
+/**
+ * Get noise sample
+ *
+ * @ret noise          Noise sample
+ * @ret rc             Return status code
+ */
+static int rdrand_get_noise ( noise_sample_t *noise ) {
+       unsigned int result;
+       unsigned int discard_c;
+       unsigned int ok;
+
+       /* Issue RDRAND, retrying until CF is set */
+       __asm__ ( "\n1:\n\t"
+                 "rdrand %0\n\t"
+                 "sbb %1, %1\n\t"
+                 "loopz 1b\n\t"
+                 : "=r" ( result ), "=r" ( ok ), "=c" ( discard_c )
+                 : "2" ( RDRAND_RETRY_COUNT ) );
+       if ( ! ok ) {
+               DBGC ( colour, "RDRAND failed to become ready\n" );
+               return -EBUSY;
+       }
+
+       *noise = result;
+       return 0;
+}
+
+PROVIDE_ENTROPY_INLINE ( rdrand, min_entropy_per_sample );
+PROVIDE_ENTROPY ( rdrand, entropy_enable, rdrand_entropy_enable );
+PROVIDE_ENTROPY ( rdrand, entropy_disable, rdrand_entropy_disable );
+PROVIDE_ENTROPY ( rdrand, get_noise, rdrand_get_noise );
index 5ac7fcd2e2a90811b5a7c3c71ee1eedb19fec9a7..7accea33f6e8db797a7abb3c831a98c8db665de2 100644 (file)
@@ -10,5 +10,6 @@
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 
 #include <ipxe/rtc_entropy.h>
+#include <ipxe/rdrand.h>
 
 #endif /* _BITS_ENTROPY_H */
index b0ae1abc2c31f669f99b2c9ced8db6b73c03b26d..b5316a58646791b3476278fe94b57c2dbd4d90f6 100644 (file)
@@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
 #define ERRFILE_cpuid          ( ERRFILE_ARCH | ERRFILE_CORE | 0x00110000 )
 #define ERRFILE_rdtsc_timer    ( ERRFILE_ARCH | ERRFILE_CORE | 0x00120000 )
 #define ERRFILE_acpi_timer     ( ERRFILE_ARCH | ERRFILE_CORE | 0x00130000 )
+#define ERRFILE_rdrand         ( ERRFILE_ARCH | ERRFILE_CORE | 0x00140000 )
 
 #define ERRFILE_bootsector     ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00000000 )
 #define ERRFILE_bzimage               ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00010000 )
index 3983dfb896f3409a4b518d9cb1bb055750dcfa86..90d1bf01dec95162d3a8e7e92f4afd9833a5460f 100644 (file)
@@ -39,6 +39,9 @@ struct x86_features {
 /** Get standard features */
 #define CPUID_FEATURES 0x00000001UL
 
+/** RDRAND instruction is supported */
+#define CPUID_FEATURES_INTEL_ECX_RDRAND 0x40000000UL
+
 /** Hypervisor is present */
 #define CPUID_FEATURES_INTEL_ECX_HYPERVISOR 0x80000000UL
 
diff --git a/src/arch/x86/include/ipxe/rdrand.h b/src/arch/x86/include/ipxe/rdrand.h
new file mode 100644 (file)
index 0000000..c9c170f
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef _IPXE_RDRAND_H
+#define _IPXE_RDRAND_H
+
+/** @file
+ *
+ * Hardware random number generator
+ *
+ */
+
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
+
+#include <stdint.h>
+#include <ipxe/drbg.h>
+
+#ifdef ENTROPY_RDRAND
+#define ENTROPY_PREFIX_rdrand
+#else
+#define ENTROPY_PREFIX_rdrand __rdrand_
+#endif
+
+/**
+ * min-entropy per sample
+ *
+ * @ret min_entropy    min-entropy of each sample
+ */
+static inline __always_inline min_entropy_t
+ENTROPY_INLINE ( rdrand, min_entropy_per_sample ) ( void ) {
+
+       /* Data returned by RDRAND is theoretically full entropy, up
+        * to a security strength of 128 bits.
+        */
+       if ( DRBG_SECURITY_STRENGTH > 128 )
+               return 0;
+       return MIN_ENTROPY ( 8 * sizeof ( noise_sample_t ) );
+}
+
+#endif /* _IPXE_RDRAND_H */