From 0d35411f88dd37dda755d52b4549337f8299c698 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 20 Mar 2018 20:42:39 +0200 Subject: [rng] Use fixed-point calculations for min-entropy quantities We currently perform various min-entropy calculations using build-time floating-point arithmetic. No floating-point code ends up in the final binary, since the results are eventually converted to integers and asserted to be compile-time constants. Though this mechanism is undoubtedly cute, it inhibits us from using "-mno-sse" to prevent the use of SSE registers by the compiler. Fix by using fixed-point arithmetic instead. Signed-off-by: Michael Brown --- src/arch/x86/include/ipxe/rtc_entropy.h | 4 ++-- src/crypto/entropy.c | 5 +++-- src/include/ipxe/efi/efi_entropy.h | 4 ++-- src/include/ipxe/entropy.h | 26 +++++++++++++++++++++++--- src/include/ipxe/linux/linux_entropy.h | 4 ++-- src/include/ipxe/null_entropy.h | 4 ++-- 6 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/arch/x86/include/ipxe/rtc_entropy.h b/src/arch/x86/include/ipxe/rtc_entropy.h index e214745d..581abcd3 100644 --- a/src/arch/x86/include/ipxe/rtc_entropy.h +++ b/src/arch/x86/include/ipxe/rtc_entropy.h @@ -22,7 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * * @ret min_entropy min-entropy of each sample */ -static inline __always_inline double +static inline __always_inline min_entropy_t ENTROPY_INLINE ( rtc, min_entropy_per_sample ) ( void ) { /* The min-entropy has been measured on several platforms @@ -38,7 +38,7 @@ ENTROPY_INLINE ( rtc, min_entropy_per_sample ) ( void ) { * safety margin to allow for some potential non-independence * of samples. */ - return 1.3; + return MIN_ENTROPY ( 1.3 ); } extern uint8_t rtc_sample ( void ); diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c index 5acbc025..ced6fd92 100644 --- a/src/crypto/entropy.c +++ b/src/crypto/entropy.c @@ -70,7 +70,8 @@ repetition_count_cutoff ( void ) { * where W is set at 2^(-30) (in ANS X9.82 Part 2 (October * 2011 Draft) Section 8.5.2.1.3.1). */ - max_repetitions = ( 1 + ( 30 / min_entropy_per_sample() ) ); + max_repetitions = ( 1 + ( MIN_ENTROPY ( 30 ) / + min_entropy_per_sample() ) ); /* Round up to a whole number of repetitions. We don't have * the ceil() function available, so do the rounding by hand. @@ -237,7 +238,7 @@ adaptive_proportion_cutoff ( void ) { /* Look up cutoff value in cutoff table */ n = ADAPTIVE_PROPORTION_WINDOW_SIZE; - h = min_entropy_per_sample(); + h = ( min_entropy_per_sample() / MIN_ENTROPY_SCALE ); cutoff = adaptive_proportion_cutoff_lookup ( n, h ); /* Fail unless cutoff value is a build-time constant */ diff --git a/src/include/ipxe/efi/efi_entropy.h b/src/include/ipxe/efi/efi_entropy.h index 39a66735..5b16fd7f 100644 --- a/src/include/ipxe/efi/efi_entropy.h +++ b/src/include/ipxe/efi/efi_entropy.h @@ -22,14 +22,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * * @ret min_entropy min-entropy of each sample */ -static inline __always_inline double +static inline __always_inline min_entropy_t ENTROPY_INLINE ( efi, min_entropy_per_sample ) ( void ) { /* We use essentially the same mechanism as for the BIOS * RTC-based entropy source, and so assume the same * min-entropy per sample. */ - return 1.3; + return MIN_ENTROPY ( 1.3 ); } #endif /* _IPXE_EFI_ENTROPY_H */ diff --git a/src/include/ipxe/entropy.h b/src/include/ipxe/entropy.h index beeb3abf..d2e3ce50 100644 --- a/src/include/ipxe/entropy.h +++ b/src/include/ipxe/entropy.h @@ -52,6 +52,25 @@ typedef uint8_t noise_sample_t; /** An entropy sample */ typedef uint8_t entropy_sample_t; +/** An amount of min-entropy + * + * Expressed as a fixed-point quantity in order to avoid floating + * point calculations. + */ +typedef unsigned int min_entropy_t; + +/** Fixed-point scale for min-entropy amounts */ +#define MIN_ENTROPY_SCALE ( 1 << 16 ) + +/** + * Construct a min-entropy fixed-point value + * + * @v bits min-entropy in bits + * @ret min_entropy min-entropy as a fixed-point value + */ +#define MIN_ENTROPY( bits ) \ + ( ( min_entropy_t ) ( (bits) * MIN_ENTROPY_SCALE ) ) + /* Include all architecture-independent entropy API headers */ #include #include @@ -87,7 +106,7 @@ void entropy_disable ( void ); * * This must be a compile-time constant. */ -double min_entropy_per_sample ( void ); +min_entropy_t min_entropy_per_sample ( void ); /** * Get noise sample @@ -142,7 +161,7 @@ get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len, /* Sanity checks */ linker_assert ( ( min_entropy_per_sample() <= - ( 8 * sizeof ( noise_sample_t ) ) ), + MIN_ENTROPY ( 8 * sizeof ( noise_sample_t ) ) ), min_entropy_per_sample_is_impossibly_high ); linker_assert ( ( min_entropy_bits <= ( 8 * max_len ) ), entropy_buffer_too_small ); @@ -151,7 +170,8 @@ get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len, min_entropy_bits = ( ( min_entropy_bits + 7 ) & ~7 ); /* Calculate number of samples required to contain sufficient entropy */ - min_samples = ( ( min_entropy_bits * 1.0 ) / min_entropy_per_sample() ); + min_samples = ( MIN_ENTROPY ( min_entropy_bits ) / + min_entropy_per_sample() ); /* Round up to a whole number of samples. We don't have the * ceil() function available, so do the rounding by hand. diff --git a/src/include/ipxe/linux/linux_entropy.h b/src/include/ipxe/linux/linux_entropy.h index afef6fe1..ea8c1f16 100644 --- a/src/include/ipxe/linux/linux_entropy.h +++ b/src/include/ipxe/linux/linux_entropy.h @@ -20,7 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); * * @ret min_entropy min-entropy of each sample */ -static inline __always_inline double +static inline __always_inline min_entropy_t ENTROPY_INLINE ( linux, min_entropy_per_sample ) ( void ) { /* linux_get_noise() reads a single byte from /dev/random, @@ -28,7 +28,7 @@ ENTROPY_INLINE ( linux, min_entropy_per_sample ) ( void ) { * entropy is available. We therefore assume that each sample * contains exactly 8 bits of entropy. */ - return 8.0; + return MIN_ENTROPY ( 8.0 ); } #endif /* _IPXE_LINUX_ENTROPY_H */ diff --git a/src/include/ipxe/null_entropy.h b/src/include/ipxe/null_entropy.h index 91adefa6..5a6bb621 100644 --- a/src/include/ipxe/null_entropy.h +++ b/src/include/ipxe/null_entropy.h @@ -30,14 +30,14 @@ ENTROPY_INLINE ( null, entropy_disable ) ( void ) { /* Do nothing */ } -static inline __always_inline double +static inline __always_inline min_entropy_t ENTROPY_INLINE ( null, min_entropy_per_sample ) ( void ) { /* Actual amount of min-entropy is zero. To avoid * division-by-zero errors and to allow compilation of * entropy-consuming code, pretend to have 1 bit of entropy in * each sample. */ - return 1.0; + return MIN_ENTROPY ( 1.0 ); } static inline __always_inline int -- cgit v1.2.3-55-g7522