From fcc35bf48776fff9ebfd8db537679583221a9cd4 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Mon, 23 Jan 2012 15:00:27 +0000 Subject: [PATCH] [rng] Add dummy entropy source Cryptographic random number generation requires an entropy source, which is used as the input to a Deterministic Random Bit Generator (DRBG). iPXE does not currently have a suitable entropy source. Provide a dummy source to allow the DRBG code to be implemented. Signed-off-by: Michael Brown --- src/crypto/entropy.c | 48 ++++++++++++++++++++ src/include/ipxe/entropy.h | 90 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 src/crypto/entropy.c create mode 100644 src/include/ipxe/entropy.h diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c new file mode 100644 index 00000000..86fa8978 --- /dev/null +++ b/src/crypto/entropy.c @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2012 Michael Brown . + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +/** @file + * + * Entropy source + * + */ + +#include +#include + +/** + * Obtain entropy input + * + * @v entropy_bits Minimum amount of entropy, in bits + * @v data Data buffer + * @v min_len Minimum length of entropy input, in bytes + * @v max_len Maximum length of entropy input, in bytes + * @ret len Length of entropy input, in bytes + */ +int get_entropy_input ( unsigned int entropy_bits, void *data, size_t min_len, + size_t max_len ) { + + /* Placeholder to allow remainder of RBG code to be tested */ + ( void ) entropy_bits; + ( void ) min_len; + memset ( data, 0x01, max_len ); + + return max_len; +} diff --git a/src/include/ipxe/entropy.h b/src/include/ipxe/entropy.h new file mode 100644 index 00000000..d9b70848 --- /dev/null +++ b/src/include/ipxe/entropy.h @@ -0,0 +1,90 @@ +#ifndef _IPXE_ENTROPY_H +#define _IPXE_ENTROPY_H + +/** @file + * + * Entropy source + * + */ + +FILE_LICENCE ( GPL2_OR_LATER ); + +#include +#include + +/** min-entropy per entropy sample + * + * min-entropy is defined in ANS X9.82 Part 1-2006 Section 8.3 and in + * NIST SP 800-90 Appendix C.3 as + * + * H_min = -log2 ( p_max ) + * + * where p_max is the probability of the most likely sample value. + */ +#define MIN_ENTROPY_PER_SAMPLE 0.16 + +/** Length of each entropy sample (in bits) */ +#define ENTROPY_SAMPLE_LEN_BITS 12 + +/** + * Calculate entropy buffer size + * + * @v entropy_bits Amount of entropy required, in bits + * @v min_len Minimum buffer size, in bytes + * @v max_len Maximum buffer size, in bytes + * @ret len Buffer size, in bytes + */ +static inline __attribute__ (( const, always_inline )) size_t +entropy_bufsize ( unsigned int entropy_bits, size_t min_len, size_t max_len ) { + unsigned int min_len_bits; + double min_samples; + double samples; + unsigned int samples_int; + unsigned int len_bits; + size_t len; + + /* Sanity check */ + linker_assert ( MIN_ENTROPY_PER_SAMPLE <= ENTROPY_SAMPLE_LEN_BITS, + min_entropy_per_sample_is_impossibly_high ); + + /* Calculate number of samples required to contain sufficient entropy */ + samples = ( ( entropy_bits * 1.0 ) / MIN_ENTROPY_PER_SAMPLE ); + + /* Increase to minimum length if necessary */ + min_len_bits = ( min_len * 8 ); + min_samples = ( ( min_len_bits * 1.0 ) / ENTROPY_SAMPLE_LEN_BITS ); + if ( samples < min_samples ) + samples = min_samples; + + /* Round up to a whole number of samples. We don't have the + * ceil() function available, so do the rounding by hand. + */ + samples_int = samples; + if ( samples_int < samples ) + samples_int++; + assert ( samples_int >= samples ); + + /* Calculate buffer length in bits */ + len_bits = ( samples_int * ENTROPY_SAMPLE_LEN_BITS ); + + /* Calculate buffer length in bytes (rounding up) */ + len = ( ( len_bits + 7 ) / 8 ); + + /* Check that buffer is within allowed lengths */ + linker_assert ( len >= min_len, entropy_bufsize_too_short ); + linker_assert ( len <= max_len, entropy_bufsize_too_long ); + + /* Floating-point operations are not allowed in iPXE since we + * never set up a suitable environment. Abort the build + * unless the calculated length is a compile-time constant. + */ + linker_assert ( __builtin_constant_p ( len ), + entropy_bufsize_not_constant ); + + return len; +} + +extern int get_entropy_input ( unsigned int entropy_bits, void *data, + size_t min_len, size_t max_len ); + +#endif /* _IPXE_ENTROPY_H */