summaryrefslogtreecommitdiffstats
path: root/src/crypto/entropy.c
diff options
context:
space:
mode:
authorMichael Brown2012-02-19 23:14:06 +0100
committerMichael Brown2012-02-21 13:42:38 +0100
commit073f41085f0791593d96233ef617fcefe3cdacb9 (patch)
treeba9794f51055b9d1b82f34d1fa204cc9af2b1957 /src/crypto/entropy.c
parent[rng] Record validity within DRBG state (diff)
downloadipxe-073f41085f0791593d96233ef617fcefe3cdacb9.tar.gz
ipxe-073f41085f0791593d96233ef617fcefe3cdacb9.tar.xz
ipxe-073f41085f0791593d96233ef617fcefe3cdacb9.zip
[rng] Add ANS X9.82 Approved Source of Entropy Input
ANS X9.82 specifies several Approved Sources of Entropy Input (SEI). One such SEI uses an entropy source as the Source of Entropy Input, condensing each entropy source output after each GetEntropy call. This can be implemented relatively cheaply in iPXE and avoids the need to allocate potentially very large buffers. (Note that the terms "entropy source" and "Source of Entropy Input" are not synonyms within the context of ANS X9.82.) Use the iPXE API mechanism to allow entropy sources to be selected at compilation time. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/crypto/entropy.c')
-rw-r--r--src/crypto/entropy.c128
1 files changed, 115 insertions, 13 deletions
diff --git a/src/crypto/entropy.c b/src/crypto/entropy.c
index 86fa8978..d5d06e57 100644
--- a/src/crypto/entropy.c
+++ b/src/crypto/entropy.c
@@ -22,27 +22,129 @@ FILE_LICENCE ( GPL2_OR_LATER );
*
* Entropy source
*
+ * This algorithm is designed to comply with ANS X9.82 Part 4 (April
+ * 2011 Draft) Section 13.3. This standard is unfortunately not
+ * freely available.
*/
+#include <stdint.h>
+#include <assert.h>
#include <string.h>
+#include <ipxe/crypto.h>
+#include <ipxe/hash_df.h>
#include <ipxe/entropy.h>
/**
- * Obtain entropy input
+ * Get entropy sample
*
- * @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
+ * @ret entropy Entropy sample
+ * @ret rc Return status code
+ *
+ * This is the GetEntropy function defined in ANS X9.82 Part 2
+ * (October 2011 Draft) Section 6.5.1.
+ */
+static int get_entropy ( entropy_sample_t *entropy ) {
+ noise_sample_t noise;
+ int rc;
+
+ /* Get noise sample */
+ if ( ( rc = get_noise ( &noise ) ) != 0 )
+ return rc;
+
+ /* We do not use any optional conditioning component */
+ *entropy = noise;
+
+ return 0;
+}
+
+/**
+ * Create next nonce value
+ *
+ * @ret nonce Nonce
+ *
+ * This is the MakeNextNonce function defined in ANS X9.82 Part 4
+ * (April 2011 Draft) Section 13.3.4.2.
*/
-int get_entropy_input ( unsigned int entropy_bits, void *data, size_t min_len,
- size_t max_len ) {
+static uint32_t make_next_nonce ( void ) {
+ static uint32_t nonce;
+
+ /* The simplest implementation of a nonce uses a large counter */
+ nonce++;
+
+ return nonce;
+}
+
+/**
+ * Obtain entropy input temporary buffer
+ *
+ * @v num_samples Number of entropy samples
+ * @v tmp Temporary buffer
+ * @v tmp_len Length of temporary buffer
+ * @ret rc Return status code
+ *
+ * This is (part of) the implementation of the Get_entropy_input
+ * function (using an entropy source as the source of entropy input
+ * and condensing each entropy source output after each GetEntropy
+ * call) as defined in ANS X9.82 Part 4 (April 2011 Draft) Section
+ * 13.3.4.2.
+ *
+ * To minimise code size, the number of samples required is calculated
+ * at compilation time.
+ */
+int get_entropy_input_tmp ( unsigned int num_samples, uint8_t *tmp,
+ size_t tmp_len ) {
+ struct {
+ uint32_t nonce;
+ entropy_sample_t sample;
+ } __attribute__ (( packed )) data;;
+ uint8_t df_buf[tmp_len];
+ unsigned int i;
+ int rc;
+
+ /* Enable entropy gathering */
+ entropy_enable();
+
+ /* 3. entropy_total = 0
+ *
+ * (Nothing to do; the number of entropy samples required has
+ * already been precalculated.)
+ */
+
+ /* 4. tmp = a fixed n-bit value, such as 0^n */
+ memset ( tmp, 0, tmp_len );
+
+ /* 5. While ( entropy_total < min_entropy ) */
+ while ( num_samples-- ) {
+ /* 5.1. ( status, entropy_bitstring, assessed_entropy )
+ * = GetEntropy()
+ * 5.2. If status indicates an error, return ( status, Null )
+ */
+ if ( ( rc = get_entropy ( &data.sample ) ) != 0 )
+ goto err_get_entropy;
+
+ /* 5.3. nonce = MakeNextNonce() */
+ data.nonce = make_next_nonce();
+
+ /* 5.4. tmp = tmp XOR
+ * df ( ( nonce || entropy_bitstring ), n )
+ */
+ hash_df ( &data, sizeof ( data ), df_buf, sizeof ( df_buf ) );
+ for ( i = 0 ; i < tmp_len ; i++ )
+ tmp[i] ^= df_buf[i];
+
+ /* 5.5. entropy_total = entropy_total + assessed_entropy
+ *
+ * (Nothing to do; the number of entropy samples
+ * required has already been precalculated.)
+ */
+ }
+
+ /* Disable entropy gathering */
+ entropy_disable();
- /* Placeholder to allow remainder of RBG code to be tested */
- ( void ) entropy_bits;
- ( void ) min_len;
- memset ( data, 0x01, max_len );
+ return 0;
- return max_len;
+ err_get_entropy:
+ entropy_disable();
+ return rc;
}