diff options
author | Michael Brown <mcb30@ipxe.org> | 2024-10-28 00:10:18 +0000 |
---|---|---|
committer | Michael Brown <mcb30@ipxe.org> | 2024-10-28 15:55:24 +0000 |
commit | be0c9788a13423b851af4d38be149af17f7b8494 (patch) | |
tree | 539b0105300cec6d854b83694ddea91b5e4abb1b | |
parent | cd54e7c844e2148b46c960d72ed853f8f75bf400 (diff) | |
download | ipxe-be0c9788a13423b851af4d38be149af17f7b8494.tar.gz |
[riscv] Add support for the seed CSR as an entropy source
The Zkr entropy source extension defines a potentially unprivileged
seed CSR that can be read to obtain 16 bits of entropy input, with a
mandated requirement that 256 entropy input bits read from the seed
CSR will contain at least 128 bits of min-entropy.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r-- | src/arch/riscv/core/zkr.c | 110 | ||||
-rw-r--r-- | src/arch/riscv/include/bits/errfile.h | 1 | ||||
-rw-r--r-- | src/config/config_entropy.c | 3 |
3 files changed, 114 insertions, 0 deletions
diff --git a/src/arch/riscv/core/zkr.c b/src/arch/riscv/core/zkr.c new file mode 100644 index 000000000..5cb44c2d0 --- /dev/null +++ b/src/arch/riscv/core/zkr.c @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2024 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 + * + * Entropy source extension (Zkr) + * + */ + +#include <errno.h> +#include <ipxe/hart.h> +#include <ipxe/entropy.h> +#include <ipxe/drbg.h> + +struct entropy_source zkr_entropy __entropy_source ( ENTROPY_PREFERRED ); + +/** Seed CSR operational state */ +#define ZKR_SEED_OPST_MASK 0xc0000000UL +#define ZKR_SEED_OPST_ES16 0x80000000UL /**< 16 bits of entropy available */ + +/** Number of times to retry reading from seed CSR */ +#define ZKR_SEED_MAX_RETRY 1024 + +/** Colour for debug messages */ +#define colour &zkr_entropy + +/** + * Enable entropy gathering + * + * @ret rc Return status code + */ +static int zkr_entropy_enable ( void ) { + int rc; + + /* Check if Zkr extension is supported */ + if ( ( rc = hart_supported ( "_zkr" ) ) != 0 ) { + DBGC ( colour, "ZKR not supported: %s\n", strerror ( rc ) ); + return rc; + } + + /* RISC-V ISA mandates that 128 bits of full entropy shall be + * obtained from 256 entropy bits read from the seed CSR. + * + * Each 16-bit sample therefore contains 8 bits of + * min-entropy. + */ + entropy_init ( &zkr_entropy, MIN_ENTROPY ( 8.0 ) ); + + return 0; +} + +/** + * Get noise sample + * + * @ret noise Noise sample + * @ret rc Return status code + */ +static int zkr_get_noise ( noise_sample_t *noise ) { + unsigned long seed; + unsigned int i; + + /* Read entropy from seed CSR */ + for ( i = 0 ; i < ZKR_SEED_MAX_RETRY ; i++ ) { + + /* Read seed CSR */ + __asm__ ( "csrrw %0, seed, zero" : "=r" ( seed ) ); + + /* Check operationsl state */ + if ( ( seed & ZKR_SEED_OPST_MASK ) == ZKR_SEED_OPST_ES16 ) { + + /* Return entropy from both halves of the + * 16-bit entropy source value. + */ + *noise = ( seed ^ ( seed >> 8 ) ); + return 0; + } + } + + DBGC ( colour, "ZKR could not source entropy (seed %#08lx)\n", seed ); + return -EBUSY; +} + +/** Hardware entropy source */ +struct entropy_source zkr_entropy __entropy_source ( ENTROPY_PREFERRED ) = { + .name = "zkr", + .enable = zkr_entropy_enable, + .get_noise = zkr_get_noise, +}; diff --git a/src/arch/riscv/include/bits/errfile.h b/src/arch/riscv/include/bits/errfile.h index 62288ad9c..bdd2927a4 100644 --- a/src/arch/riscv/include/bits/errfile.h +++ b/src/arch/riscv/include/bits/errfile.h @@ -17,6 +17,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #define ERRFILE_sbi_reboot ( ERRFILE_ARCH | ERRFILE_CORE | 0x00000000 ) #define ERRFILE_hart ( ERRFILE_ARCH | ERRFILE_CORE | 0x00010000 ) #define ERRFILE_zicntr ( ERRFILE_ARCH | ERRFILE_CORE | 0x00020000 ) +#define ERRFILE_zkr ( ERRFILE_ARCH | ERRFILE_CORE | 0x00030000 ) /** @} */ diff --git a/src/config/config_entropy.c b/src/config/config_entropy.c index 9f12f1fa3..92aa97884 100644 --- a/src/config/config_entropy.c +++ b/src/config/config_entropy.c @@ -49,3 +49,6 @@ REQUIRE_OBJECT ( linux_entropy ); #ifdef ENTROPY_RDRAND REQUIRE_OBJECT ( rdrand ); #endif +#ifdef ENTROPY_ZKR +REQUIRE_OBJECT ( zkr ); +#endif |