iPXE
entropy.h
Go to the documentation of this file.
1 #ifndef _IPXE_ENTROPY_H
2 #define _IPXE_ENTROPY_H
3 
4 /** @file
5  *
6  * Entropy source
7  *
8  */
9 
10 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 FILE_SECBOOT ( PERMITTED );
12 
13 #include <stdint.h>
14 #include <string.h>
15 #include <assert.h>
16 #include <ipxe/hash_df.h>
17 #include <ipxe/sha256.h>
18 #include <ipxe/tables.h>
19 #include <config/entropy.h>
20 
21 /** A noise sample */
23 
24 /** An entropy sample */
26 
27 /** An amount of min-entropy
28  *
29  * Expressed as a fixed-point quantity in order to avoid floating
30  * point calculations.
31  */
32 typedef unsigned int min_entropy_t;
33 
34 /** Fixed-point scale for min-entropy amounts */
35 #define MIN_ENTROPY_SCALE ( 1 << 16 )
36 
37 /**
38  * Construct a min-entropy fixed-point value
39  *
40  * @v bits min-entropy in bits
41  * @ret min_entropy min-entropy as a fixed-point value
42  */
43 #define MIN_ENTROPY( bits ) \
44  ( ( min_entropy_t ) ( (bits) * MIN_ENTROPY_SCALE ) )
45 
46 /**
47  * Repetition count test state
48  *
49  * This is the state for the repetition Count Test defined in ANS
50  * X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2.
51  */
53  /**
54  * A = the most recently seen sample value
55  */
57  /**
58  * B = the number of times that value A has been seen in a row
59  */
60  unsigned int repetition_count;
61  /**
62  * C = the cutoff value above which the repetition test should fail
63  *
64  * Filled in by entropy_init().
65  */
66  unsigned int cutoff;
67 };
68 
69 /**
70  * Adaptive proportion test state
71  *
72  * This is the state for the Adaptive Proportion Test for the Most
73  * Common Value defined in ANS X9.82 Part 2 (October 2011 Draft)
74  * Section 8.5.2.1.3.
75  */
77  /**
78  * A = the sample value currently being counted
79  */
81  /**
82  * S = the number of samples examined in this run of the test so far
83  */
84  unsigned int sample_count;
85  /**
86  * B = the current number of times that S (sic) has been seen
87  * in the W (sic) samples examined so far
88  */
89  unsigned int repetition_count;
90  /**
91  * C = the cutoff value above which the repetition test should fail
92  *
93  * Filled in by entropy_init().
94  */
95  unsigned int cutoff;
96 };
97 
98 /**
99  * Startup test state
100  *
101  * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires
102  * that at least one full cycle of the continuous tests must be
103  * performed at start-up.
104  */
106  /** Number of startup tests performed */
107  unsigned int tested;
108  /**
109  * Number of startup tests required for one full cycle
110  *
111  * Filled in by entropy_init().
112  */
113  unsigned int count;
114 };
115 
116 /** An entropy source */
118  /** Name */
119  const char *name;
120  /**
121  * min-entropy per sample
122  *
123  * min-entropy is defined in ANS X9.82 Part 1-2006 Section 8.3 and in
124  * NIST SP 800-90 Appendix C.3 as
125  *
126  * H_min = -log2 ( p_max )
127  *
128  * where p_max is the probability of the most likely sample value.
129  *
130  * Filled in by entropy_init().
131  */
133  /** Repetition count test state */
135  /** Adaptive proportion test state */
137  /** Startup test state */
139  /**
140  * Failure status (if any)
141  *
142  * Any failure of an entropy source is regarded as permanent.
143  */
144  int rc;
145 
146  /**
147  * Enable entropy gathering
148  *
149  * @ret rc Return status code
150  */
151  int ( * enable ) ( void );
152  /**
153  * Disable entropy gathering
154  *
155  */
156  void ( * disable ) ( void );
157  /**
158  * Get noise sample
159  *
160  * @ret noise Noise sample
161  * @ret rc Return status code
162  *
163  * This is the GetNoise function defined in ANS X9.82 Part 2
164  * (October 2011 Draft) Section 6.5.2.
165  */
166  int ( * get_noise ) ( noise_sample_t *noise );
167 };
168 
169 /** Entropy source table */
170 #define ENTROPY_SOURCES __table ( struct entropy_source, "entropy_sources" )
171 
172 /** Declare an entropy source */
173 #define __entropy_source( order ) __table_entry ( ENTROPY_SOURCES, order )
174 
175 /** @defgroup entropy_source_order Entropy source order
176  *
177  * @{
178  */
179 
180 #define ENTROPY_PREFERRED 01 /**< Preferred entropy source */
181 #define ENTROPY_NORMAL 02 /**< Normal entropy source */
182 #define ENTROPY_FALLBACK 03 /**< Fallback entropy source */
183 
184 /** @} */
185 
186 extern int get_entropy_input_tmp ( min_entropy_t min_entropy, uint8_t *tmp,
187  size_t tmp_len );
188 
189 /** Use SHA-256 as the underlying hash algorithm for Hash_df
190  *
191  * Hash_df using SHA-256 is an Approved algorithm in ANS X9.82.
192  */
193 #define entropy_hash_df_algorithm sha256_algorithm
194 
195 /** Underlying hash algorithm output length (in bytes) */
196 #define ENTROPY_HASH_DF_OUTLEN_BYTES SHA256_DIGEST_SIZE
197 
198 /**
199  * Get noise sample
200  *
201  * @v source Entropy source
202  * @ret noise Noise sample
203  * @ret rc Return status code
204  *
205  * This is the GetNoise function defined in ANS X9.82 Part 2
206  * (October 2011 Draft) Section 6.5.2.
207  */
208 static inline __attribute__ (( always_inline )) int
209 get_noise ( struct entropy_source *source, noise_sample_t *noise ) {
210 
211  return source->get_noise ( noise );
212 }
213 
214 /**
215  * Obtain entropy input
216  *
217  * @v min_entropy_bits Minimum amount of entropy, in bits
218  * @v data Data buffer
219  * @v min_len Minimum length of entropy input, in bytes
220  * @v max_len Maximum length of entropy input, in bytes
221  * @ret len Length of entropy input, in bytes, or negative error
222  *
223  * This is the implementation of the Get_entropy_input function (using
224  * an entropy source as the source of entropy input and condensing
225  * each entropy source output after each GetEntropy call) as defined
226  * in ANS X9.82 Part 4 (April 2011 Draft) Section 13.3.4.2.
227  *
228  * This function is inlined since the entropy amount and length inputs
229  * are always compile-time constants.
230  */
231 static inline __attribute__ (( always_inline )) int
232 get_entropy_input ( unsigned int min_entropy_bits, void *data, size_t min_len,
233  size_t max_len ) {
234  size_t tmp_len = ( ( ( min_entropy_bits * 2 ) + 7 ) / 8 );
235  uint8_t tmp_buf[ tmp_len ];
236  uint8_t *tmp = ( ( tmp_len > max_len ) ? tmp_buf : data );
237  unsigned int n;
238  int rc;
239 
240  /* Sanity check */
241  build_assert ( min_entropy_bits <= ( 8 * max_len ) );
242 
243  /* Round up minimum entropy to an integral number of bytes */
244  min_entropy_bits = ( ( min_entropy_bits + 7 ) & ~7 );
245 
246  /* (Unnumbered). The output length of the hash function shall
247  * meet or exceed the security strength indicated by the
248  * min_entropy parameter.
249  */
251  min_entropy_bits );
252 
253  /* 1. If ( min_length > max_length ), then return ( FAILURE, Null ) */
254  build_assert ( min_len <= max_len );
255 
256  /* 2. n = 2 * min_entropy */
257  n = ( 2 * min_entropy_bits );
258 
259  /* 3. entropy_total = 0
260  * 4. tmp = a fixed n-bit value, such as 0^n
261  * 5. While ( entropy_total < min_entropy )
262  * 5.1. ( status, entropy_bitstring, assessed_entropy )
263  * = GetEntropy()
264  * 5.2. If status indicates an error, return ( status, Null )
265  * 5.3. nonce = MakeNextNonce()
266  * 5.4. tmp = tmp XOR df ( ( nonce || entropy_bitstring ), n )
267  * 5.5. entropy_total = entropy_total + assessed_entropy
268  *
269  * (The implementation of these steps is inside the function
270  * get_entropy_input_tmp().)
271  */
272  build_assert ( __builtin_constant_p ( tmp_len ) );
273  build_assert ( n == ( 8 * tmp_len ) );
274  if ( ( rc = get_entropy_input_tmp ( MIN_ENTROPY ( min_entropy_bits ),
275  tmp, tmp_len ) ) != 0 ) {
276  return rc;
277  }
278 
279  /* 6. If ( n < min_length ), then tmp = tmp || 0^(min_length-n)
280  * 7. If ( n > max_length ), then tmp = df ( tmp, max_length )
281  * 8. Return ( SUCCESS, tmp )
282  */
283  if ( tmp_len < min_len ) {
284  /* (Data is already in-place.) */
285  build_assert ( data == tmp );
286  memset ( ( data + tmp_len ), 0, ( min_len - tmp_len ) );
287  return min_len;
288  } else if ( tmp_len > max_len ) {
289  build_assert ( tmp == tmp_buf );
291  data, max_len );
292  return max_len;
293  } else {
294  /* (Data is already in-place.) */
295  build_assert ( data == tmp );
296  return tmp_len;
297  }
298 }
299 
300 /**
301  * Calculate cutoff value for the repetition count test
302  *
303  * @v min_entropy_per_sample Min-entropy per sample
304  * @ret cutoff Cutoff value
305  *
306  * This is the cutoff value for the Repetition Count Test defined in
307  * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2.
308  */
309 static inline __attribute__ (( always_inline )) unsigned int
310 entropy_repetition_count_cutoff ( min_entropy_t min_entropy_per_sample ) {
311  double max_repetitions;
312  unsigned int cutoff;
313 
314  /* The cutoff formula for the repetition test is:
315  *
316  * C = ( 1 + ( -log2(W) / H_min ) )
317  *
318  * where W is set at 2^(-30) (in ANS X9.82 Part 2 (October
319  * 2011 Draft) Section 8.5.2.1.3.1).
320  */
321  max_repetitions = ( 1 + ( MIN_ENTROPY ( 30 ) /
322  min_entropy_per_sample ) );
323 
324  /* Round up to a whole number of repetitions. We don't have
325  * the ceil() function available, so do the rounding by hand.
326  */
327  cutoff = max_repetitions;
328  if ( cutoff < max_repetitions )
329  cutoff++;
330  build_assert ( cutoff >= max_repetitions );
331 
332  /* Floating-point operations are not allowed in iPXE since we
333  * never set up a suitable environment. Abort the build
334  * unless the calculated number of repetitions is a
335  * compile-time constant.
336  */
337  build_assert ( __builtin_constant_p ( cutoff ) );
338 
339  return cutoff;
340 }
341 
342 /**
343  * Window size for the adaptive proportion test
344  *
345  * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.1 allows
346  * five possible window sizes: 16, 64, 256, 4096 and 65536.
347  *
348  * We expect to generate relatively few (<256) entropy samples during
349  * a typical iPXE run; the use of a large window size would mean that
350  * the test would never complete a single cycle. We use a window size
351  * of 64, which is the smallest window size that permits values of
352  * H_min down to one bit per sample.
353  */
354 #define ADAPTIVE_PROPORTION_WINDOW_SIZE 64
355 
356 /**
357  * Combine adaptive proportion test window size and min-entropy
358  *
359  * @v n N (window size)
360  * @v h H (min-entropy)
361  * @ret n_h (N,H) combined value
362  */
363 #define APC_N_H( n, h ) ( ( (n) << 8 ) | (h) )
364 
365 /**
366  * Define a row of the adaptive proportion cutoff table
367  *
368  * @v h H (min-entropy)
369  * @v c16 Cutoff for N=16
370  * @v c64 Cutoff for N=64
371  * @v c256 Cutoff for N=256
372  * @v c4096 Cutoff for N=4096
373  * @v c65536 Cutoff for N=65536
374  */
375 #define APC_TABLE_ROW( h, c16, c64, c256, c4096, c65536) \
376  case APC_N_H ( 16, h ) : return c16; \
377  case APC_N_H ( 64, h ) : return c64; \
378  case APC_N_H ( 256, h ) : return c256; \
379  case APC_N_H ( 4096, h ) : return c4096; \
380  case APC_N_H ( 65536, h ) : return c65536;
381 
382 /** Value used to represent "N/A" in adaptive proportion cutoff table */
383 #define APC_NA 0
384 
385 /**
386  * Look up value in adaptive proportion test cutoff table
387  *
388  * @v n N (window size)
389  * @v h H (min-entropy)
390  * @ret cutoff Cutoff
391  *
392  * This is the table of cutoff values defined in ANS X9.82 Part 2
393  * (October 2011 Draft) Section 8.5.2.1.3.1.2.
394  */
395 static inline __attribute__ (( always_inline )) unsigned int
396 entropy_adaptive_proportion_cutoff_lookup ( unsigned int n, unsigned int h ) {
397  switch ( APC_N_H ( n, h ) ) {
398  APC_TABLE_ROW ( 1, APC_NA, 51, 168, 2240, 33537 );
399  APC_TABLE_ROW ( 2, APC_NA, 35, 100, 1193, 17053 );
400  APC_TABLE_ROW ( 3, 10, 24, 61, 643, 8705 );
401  APC_TABLE_ROW ( 4, 8, 16, 38, 354, 4473 );
402  APC_TABLE_ROW ( 5, 6, 12, 25, 200, 2321 );
403  APC_TABLE_ROW ( 6, 5, 9, 17, 117, 1220 );
404  APC_TABLE_ROW ( 7, 4, 7, 15, 71, 653 );
405  APC_TABLE_ROW ( 8, 4, 5, 9, 45, 358 );
406  APC_TABLE_ROW ( 9, 3, 4, 7, 30, 202 );
407  APC_TABLE_ROW ( 10, 3, 4, 5, 21, 118 );
408  APC_TABLE_ROW ( 11, 2, 3, 4, 15, 71 );
409  APC_TABLE_ROW ( 12, 2, 3, 4, 11, 45 );
410  APC_TABLE_ROW ( 13, 2, 2, 3, 9, 30 );
411  APC_TABLE_ROW ( 14, 2, 2, 3, 7, 21 );
412  APC_TABLE_ROW ( 15, 1, 2, 2, 6, 15 );
413  APC_TABLE_ROW ( 16, 1, 2, 2, 5, 11 );
414  APC_TABLE_ROW ( 17, 1, 1, 2, 4, 9 );
415  APC_TABLE_ROW ( 18, 1, 1, 2, 4, 7 );
416  APC_TABLE_ROW ( 19, 1, 1, 1, 3, 6 );
417  APC_TABLE_ROW ( 20, 1, 1, 1, 3, 5 );
418  default:
419  return APC_NA;
420  }
421 }
422 
423 /**
424  * Calculate cutoff value for the adaptive proportion test
425  *
426  * @v min_entropy_per_sample Min-entropy per sample
427  * @ret cutoff Cutoff value
428  *
429  * This is the cutoff value for the Adaptive Proportion Test defined
430  * in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.1.2.
431  */
432 static inline __attribute__ (( always_inline )) unsigned int
434  unsigned int h;
435  unsigned int n;
436  unsigned int cutoff;
437 
438  /* Look up cutoff value in cutoff table */
440  h = ( min_entropy_per_sample / MIN_ENTROPY_SCALE );
442 
443  /* Fail unless cutoff value is a compile-time constant */
444  build_assert ( __builtin_constant_p ( cutoff ) );
445 
446  /* Fail if cutoff value is N/A */
447  build_assert ( cutoff != APC_NA );
448 
449  return cutoff;
450 }
451 
452 /**
453  * Calculate number of samples required for startup tests
454  *
455  * @v repetition_count_cutoff Repetition count test cutoff value
456  * @v adaptive_proportion_cutoff Adaptive proportion test cutoff value
457  * @ret num_samples Number of samples required
458  *
459  * ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.5 requires
460  * that at least one full cycle of the continuous tests must be
461  * performed at start-up.
462  */
463 static inline __attribute__ (( always_inline )) unsigned int
464 entropy_startup_test_count ( unsigned int repetition_count_cutoff,
465  unsigned int adaptive_proportion_cutoff ) {
466  unsigned int num_samples;
467 
468  /* At least max(N,C) samples shall be generated by the noise
469  * source for start-up testing.
470  */
471  num_samples = repetition_count_cutoff;
472  if ( num_samples < adaptive_proportion_cutoff )
473  num_samples = adaptive_proportion_cutoff;
474  build_assert ( __builtin_constant_p ( num_samples ) );
475 
476  return num_samples;
477 }
478 
479 /**
480  * Initialise entropy source
481  *
482  * @v source Entropy source
483  * @v min_entropy_per_sample Min-entropy per sample
484  *
485  * The cutoff value calculations for the repetition count test and the
486  * adaptive proportion test are provided as static inline functions
487  * since the results will always be compile-time constants.
488  */
489 static inline __attribute__ (( always_inline )) void
490 entropy_init ( struct entropy_source *source,
491  min_entropy_t min_entropy_per_sample ) {
492  unsigned int repetition_count_cutoff;
493  unsigned int adaptive_proportion_cutoff;
494  unsigned int startup_test_count;
495 
496  /* Sanity check */
497  build_assert ( min_entropy_per_sample > MIN_ENTROPY ( 0 ) );
498  build_assert ( min_entropy_per_sample <=
499  MIN_ENTROPY ( 8 * sizeof ( noise_sample_t ) ) );
500 
501  /* Calculate test cutoff values */
502  repetition_count_cutoff =
503  entropy_repetition_count_cutoff ( min_entropy_per_sample );
504  adaptive_proportion_cutoff =
505  entropy_adaptive_proportion_cutoff ( min_entropy_per_sample );
506  startup_test_count =
507  entropy_startup_test_count ( repetition_count_cutoff,
508  adaptive_proportion_cutoff );
509 
510  /* Record min-entropy per sample and test cutoff values */
511  source->min_entropy_per_sample = min_entropy_per_sample;
512  source->repetition_count_test.cutoff = repetition_count_cutoff;
513  source->adaptive_proportion_test.cutoff = adaptive_proportion_cutoff;
514  source->startup_test.count = startup_test_count;
515 }
516 
517 extern int entropy_enable ( struct entropy_source *source );
518 extern void entropy_disable ( struct entropy_source *source );
519 extern int get_noise ( struct entropy_source *source, noise_sample_t *noise );
520 
521 #endif /* _IPXE_ENTROPY_H */
#define __attribute__(x)
Definition: compiler.h:10
int rc
Failure status (if any)
Definition: entropy.h:144
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned int tested
Number of startup tests performed.
Definition: entropy.h:107
static int get_entropy_input(unsigned int min_entropy_bits, void *data, size_t min_len, size_t max_len)
Obtain entropy input.
Definition: entropy.h:232
static unsigned int entropy_adaptive_proportion_cutoff(min_entropy_t min_entropy_per_sample)
Calculate cutoff value for the adaptive proportion test.
Definition: entropy.h:433
#define MIN_ENTROPY_SCALE
Fixed-point scale for min-entropy amounts.
Definition: entropy.h:35
void(* disable)(void)
Disable entropy gathering.
Definition: entropy.h:156
int(* enable)(void)
Enable entropy gathering.
Definition: entropy.h:151
static unsigned int entropy_startup_test_count(unsigned int repetition_count_cutoff, unsigned int adaptive_proportion_cutoff)
Calculate number of samples required for startup tests.
Definition: entropy.h:464
min_entropy_t min_entropy_per_sample
min-entropy per sample
Definition: entropy.h:132
Hash-based derivation function (Hash_df)
An entropy source.
Definition: entropy.h:117
const char * name
Name.
Definition: entropy.h:119
unsigned long tmp
Definition: linux_pci.h:65
void entropy_disable(struct entropy_source *source)
Disable entropy gathering.
Definition: entropy.c:386
Repetition count test state.
Definition: entropy.h:52
struct entropy_repetition_count_test repetition_count_test
Repetition count test state.
Definition: entropy.h:134
Entropy API configuration.
Assertions.
struct entropy_startup_test startup_test
Startup test state.
Definition: entropy.h:138
static unsigned int entropy_repetition_count_cutoff(min_entropy_t min_entropy_per_sample)
Calculate cutoff value for the repetition count test.
Definition: entropy.h:310
FILE_SECBOOT(PERMITTED)
#define build_assert(condition)
Assert a condition at build time (after dead code elimination)
Definition: assert.h:77
int get_entropy_input_tmp(min_entropy_t min_entropy, uint8_t *tmp, size_t tmp_len)
Obtain entropy input temporary buffer.
Definition: entropy.c:426
#define APC_N_H(n, h)
Combine adaptive proportion test window size and min-entropy.
Definition: entropy.h:363
uint8_t h
Definition: registers.h:18
noise_sample_t most_recent_sample
A = the most recently seen sample value.
Definition: entropy.h:56
int(* get_noise)(noise_sample_t *noise)
Get noise sample.
Definition: entropy.h:166
static unsigned int entropy_adaptive_proportion_cutoff_lookup(unsigned int n, unsigned int h)
Look up value in adaptive proportion test cutoff table.
Definition: entropy.h:396
unsigned int repetition_count
B = the number of times that value A has been seen in a row.
Definition: entropy.h:60
#define ENTROPY_HASH_DF_OUTLEN_BYTES
Underlying hash algorithm output length (in bytes)
Definition: entropy.h:196
unsigned int sample_count
S = the number of samples examined in this run of the test so far.
Definition: entropy.h:84
int entropy_enable(struct entropy_source *source)
Enable entropy gathering.
Definition: entropy.c:303
unsigned int repetition_count
B = the current number of times that S (sic) has been seen in the W (sic) samples examined so far.
Definition: entropy.h:89
void hash_df(struct digest_algorithm *hash, const void *input, size_t input_len, void *output, size_t output_len)
Distribute entropy throughout a buffer.
Definition: hash_df.c:85
static int get_noise(struct entropy_source *source, noise_sample_t *noise)
Get noise sample.
Definition: entropy.h:209
unsigned char uint8_t
Definition: stdint.h:10
noise_sample_t current_counted_sample
A = the sample value currently being counted.
Definition: entropy.h:80
#define ADAPTIVE_PROPORTION_WINDOW_SIZE
Window size for the adaptive proportion test.
Definition: entropy.h:354
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition: entropy.h:43
unsigned int min_entropy_t
An amount of min-entropy.
Definition: entropy.h:32
uint8_t entropy_sample_t
An entropy sample.
Definition: entropy.h:25
Startup test state.
Definition: entropy.h:105
struct entropy_adaptive_proportion_test adaptive_proportion_test
Adaptive proportion test state.
Definition: entropy.h:136
unsigned int count
Number of startup tests required for one full cycle.
Definition: entropy.h:113
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
#define APC_TABLE_ROW(h, c16, c64, c256, c4096, c65536)
Define a row of the adaptive proportion cutoff table.
Definition: entropy.h:375
uint8_t data[48]
Additional event data.
Definition: ena.h:22
Linker tables.
uint8_t noise_sample_t
A noise sample.
Definition: entropy.h:22
#define entropy_hash_df_algorithm
Use SHA-256 as the underlying hash algorithm for Hash_df.
Definition: entropy.h:193
unsigned int cutoff
C = the cutoff value above which the repetition test should fail.
Definition: entropy.h:66
#define APC_NA
Value used to represent "N/A" in adaptive proportion cutoff table.
Definition: entropy.h:383
static void entropy_init(struct entropy_source *source, min_entropy_t min_entropy_per_sample)
Initialise entropy source.
Definition: entropy.h:490
SHA-256 algorithm.
unsigned int cutoff
C = the cutoff value above which the repetition test should fail.
Definition: entropy.h:95
String functions.
Adaptive proportion test state.
Definition: entropy.h:76
void * memset(void *dest, int character, size_t len) __nonnull