mirror of https://github.com/ipxe/ipxe.git
[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 <mcb30@ipxe.org>pull/71/head
parent
d5d4bf8870
commit
0d35411f88
|
@ -22,7 +22,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
*
|
*
|
||||||
* @ret min_entropy min-entropy of each sample
|
* @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 ) {
|
ENTROPY_INLINE ( rtc, min_entropy_per_sample ) ( void ) {
|
||||||
|
|
||||||
/* The min-entropy has been measured on several platforms
|
/* 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
|
* safety margin to allow for some potential non-independence
|
||||||
* of samples.
|
* of samples.
|
||||||
*/
|
*/
|
||||||
return 1.3;
|
return MIN_ENTROPY ( 1.3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
extern uint8_t rtc_sample ( void );
|
extern uint8_t rtc_sample ( void );
|
||||||
|
|
|
@ -70,7 +70,8 @@ repetition_count_cutoff ( void ) {
|
||||||
* where W is set at 2^(-30) (in ANS X9.82 Part 2 (October
|
* where W is set at 2^(-30) (in ANS X9.82 Part 2 (October
|
||||||
* 2011 Draft) Section 8.5.2.1.3.1).
|
* 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
|
/* Round up to a whole number of repetitions. We don't have
|
||||||
* the ceil() function available, so do the rounding by hand.
|
* 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 */
|
/* Look up cutoff value in cutoff table */
|
||||||
n = ADAPTIVE_PROPORTION_WINDOW_SIZE;
|
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 );
|
cutoff = adaptive_proportion_cutoff_lookup ( n, h );
|
||||||
|
|
||||||
/* Fail unless cutoff value is a build-time constant */
|
/* Fail unless cutoff value is a build-time constant */
|
||||||
|
|
|
@ -22,14 +22,14 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
*
|
*
|
||||||
* @ret min_entropy min-entropy of each sample
|
* @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 ) {
|
ENTROPY_INLINE ( efi, min_entropy_per_sample ) ( void ) {
|
||||||
|
|
||||||
/* We use essentially the same mechanism as for the BIOS
|
/* We use essentially the same mechanism as for the BIOS
|
||||||
* RTC-based entropy source, and so assume the same
|
* RTC-based entropy source, and so assume the same
|
||||||
* min-entropy per sample.
|
* min-entropy per sample.
|
||||||
*/
|
*/
|
||||||
return 1.3;
|
return MIN_ENTROPY ( 1.3 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _IPXE_EFI_ENTROPY_H */
|
#endif /* _IPXE_EFI_ENTROPY_H */
|
||||||
|
|
|
@ -52,6 +52,25 @@ typedef uint8_t noise_sample_t;
|
||||||
/** An entropy sample */
|
/** An entropy sample */
|
||||||
typedef uint8_t entropy_sample_t;
|
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 all architecture-independent entropy API headers */
|
||||||
#include <ipxe/null_entropy.h>
|
#include <ipxe/null_entropy.h>
|
||||||
#include <ipxe/efi/efi_entropy.h>
|
#include <ipxe/efi/efi_entropy.h>
|
||||||
|
@ -87,7 +106,7 @@ void entropy_disable ( void );
|
||||||
*
|
*
|
||||||
* This must be a compile-time constant.
|
* This must be a compile-time constant.
|
||||||
*/
|
*/
|
||||||
double min_entropy_per_sample ( void );
|
min_entropy_t min_entropy_per_sample ( void );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get noise sample
|
* Get noise sample
|
||||||
|
@ -142,7 +161,7 @@ get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len,
|
||||||
|
|
||||||
/* Sanity checks */
|
/* Sanity checks */
|
||||||
linker_assert ( ( min_entropy_per_sample() <=
|
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 );
|
min_entropy_per_sample_is_impossibly_high );
|
||||||
linker_assert ( ( min_entropy_bits <= ( 8 * max_len ) ),
|
linker_assert ( ( min_entropy_bits <= ( 8 * max_len ) ),
|
||||||
entropy_buffer_too_small );
|
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 );
|
min_entropy_bits = ( ( min_entropy_bits + 7 ) & ~7 );
|
||||||
|
|
||||||
/* Calculate number of samples required to contain sufficient entropy */
|
/* 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
|
/* Round up to a whole number of samples. We don't have the
|
||||||
* ceil() function available, so do the rounding by hand.
|
* ceil() function available, so do the rounding by hand.
|
||||||
|
|
|
@ -20,7 +20,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
|
||||||
*
|
*
|
||||||
* @ret min_entropy min-entropy of each sample
|
* @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 ) {
|
ENTROPY_INLINE ( linux, min_entropy_per_sample ) ( void ) {
|
||||||
|
|
||||||
/* linux_get_noise() reads a single byte from /dev/random,
|
/* 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
|
* entropy is available. We therefore assume that each sample
|
||||||
* contains exactly 8 bits of entropy.
|
* contains exactly 8 bits of entropy.
|
||||||
*/
|
*/
|
||||||
return 8.0;
|
return MIN_ENTROPY ( 8.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* _IPXE_LINUX_ENTROPY_H */
|
#endif /* _IPXE_LINUX_ENTROPY_H */
|
||||||
|
|
|
@ -30,14 +30,14 @@ ENTROPY_INLINE ( null, entropy_disable ) ( void ) {
|
||||||
/* Do nothing */
|
/* Do nothing */
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __always_inline double
|
static inline __always_inline min_entropy_t
|
||||||
ENTROPY_INLINE ( null, min_entropy_per_sample ) ( void ) {
|
ENTROPY_INLINE ( null, min_entropy_per_sample ) ( void ) {
|
||||||
/* Actual amount of min-entropy is zero. To avoid
|
/* Actual amount of min-entropy is zero. To avoid
|
||||||
* division-by-zero errors and to allow compilation of
|
* division-by-zero errors and to allow compilation of
|
||||||
* entropy-consuming code, pretend to have 1 bit of entropy in
|
* entropy-consuming code, pretend to have 1 bit of entropy in
|
||||||
* each sample.
|
* each sample.
|
||||||
*/
|
*/
|
||||||
return 1.0;
|
return MIN_ENTROPY ( 1.0 );
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline __always_inline int
|
static inline __always_inline int
|
||||||
|
|
Loading…
Reference in New Issue