iPXE
entropy.c File Reference

Entropy source. More...

#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <errno.h>
#include <ipxe/crypto.h>
#include <ipxe/hash_df.h>
#include <ipxe/entropy.h>

Go to the source code of this file.

Macros

#define EPIPE_REPETITION_COUNT_TEST    __einfo_error ( EINFO_EPIPE_REPETITION_COUNT_TEST )
#define EINFO_EPIPE_REPETITION_COUNT_TEST    __einfo_uniqify ( EINFO_EPIPE, 0x01, "Repetition count test failed" )
#define EPIPE_ADAPTIVE_PROPORTION_TEST    __einfo_error ( EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST )
#define EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST    __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" )

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 FILE_SECBOOT (PERMITTED)
static void repetition_count_test_init (struct entropy_source *source)
 Initialise repetition count test.
static int repetition_count_test (struct entropy_source *source, noise_sample_t sample)
 Perform repetition count test.
static void adaptive_proportion_test_init (struct entropy_source *source)
 Initialise adaptive proportion test.
static int adaptive_proportion_test (struct entropy_source *source, noise_sample_t sample)
 Perform adaptive proportion test.
static int get_entropy (struct entropy_source *source, entropy_sample_t *entropy)
 Get entropy sample.
static void startup_test_init (struct entropy_source *source)
 Initialise startup test.
static int startup_test (struct entropy_source *source)
 Perform startup test.
int entropy_enable (struct entropy_source *source)
 Enable entropy gathering.
static int entropy_enable_and_test (struct entropy_source *source)
 Enable and test entropy source.
static int entropy_enable_working (struct entropy_source **source)
 Enable first working entropy source.
void entropy_disable (struct entropy_source *source)
 Disable entropy gathering.
static uint32_t make_next_nonce (void)
 Create next nonce value.
int get_entropy_input_tmp (min_entropy_t min_entropy, uint8_t *tmp, size_t tmp_len)
 Obtain entropy input temporary buffer.
 REQUIRING_SYMBOL (entropy_enable)
 REQUIRE_OBJECT (config_entropy)

Detailed Description

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.

Definition in file entropy.c.

Macro Definition Documentation

◆ EPIPE_REPETITION_COUNT_TEST

#define EPIPE_REPETITION_COUNT_TEST    __einfo_error ( EINFO_EPIPE_REPETITION_COUNT_TEST )

Definition at line 45 of file entropy.c.

45#define EPIPE_REPETITION_COUNT_TEST \
46 __einfo_error ( EINFO_EPIPE_REPETITION_COUNT_TEST )

Referenced by repetition_count_test().

◆ EINFO_EPIPE_REPETITION_COUNT_TEST

#define EINFO_EPIPE_REPETITION_COUNT_TEST    __einfo_uniqify ( EINFO_EPIPE, 0x01, "Repetition count test failed" )

Definition at line 47 of file entropy.c.

47#define EINFO_EPIPE_REPETITION_COUNT_TEST \
48 __einfo_uniqify ( EINFO_EPIPE, 0x01, "Repetition count test failed" )

◆ EPIPE_ADAPTIVE_PROPORTION_TEST

#define EPIPE_ADAPTIVE_PROPORTION_TEST    __einfo_error ( EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST )

Definition at line 49 of file entropy.c.

49#define EPIPE_ADAPTIVE_PROPORTION_TEST \
50 __einfo_error ( EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST )

Referenced by adaptive_proportion_test().

◆ EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST

#define EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST    __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" )

Definition at line 51 of file entropy.c.

51#define EINFO_EPIPE_ADAPTIVE_PROPORTION_TEST \
52 __einfo_uniqify ( EINFO_EPIPE, 0x02, "Adaptive proportion test failed" )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL )

◆ FILE_SECBOOT()

FILE_SECBOOT ( PERMITTED )

◆ repetition_count_test_init()

void repetition_count_test_init ( struct entropy_source * source)
static

Initialise repetition count test.

Parameters
sourceEntropy source

Definition at line 59 of file entropy.c.

59 {
61 &source->repetition_count_test;
62
63 /* Sanity checks */
64 assert ( test->repetition_count == 0 );
65 assert ( test->cutoff > 0 );
66}
#define assert(condition)
Assert a condition at run-time.
Definition assert.h:50
static int test
Definition epic100.c:73
Repetition count test state.
Definition entropy.h:52
struct entropy_repetition_count_test repetition_count_test
Repetition count test state.
Definition entropy.h:134

References assert, entropy_source::repetition_count_test, and test.

Referenced by entropy_enable().

◆ repetition_count_test()

int repetition_count_test ( struct entropy_source * source,
noise_sample_t sample )
static

Perform repetition count test.

Parameters
sourceEntropy source
sampleNoise sample
Return values
rcReturn status code

This is the Repetition Count Test defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.2.

Definition at line 78 of file entropy.c.

79 {
81 &source->repetition_count_test;
82
83 /* A = the most recently seen sample value
84 * B = the number of times that value A has been seen in a row
85 * C = the cutoff value above which the repetition test should fail
86 */
87
88 /* 1. For each new sample processed:
89 *
90 * (Note that the test for "repetition_count > 0" ensures that
91 * the initial value of most_recent_sample is treated as being
92 * undefined.)
93 */
94 if ( ( sample == test->most_recent_sample ) &&
95 ( test->repetition_count > 0 ) ) {
96
97 /* a) If the new sample = A, then B is incremented by one. */
98 test->repetition_count++;
99
100 /* i. If B >= C, then an error condition is raised
101 * due to a failure of the test
102 */
103 if ( test->repetition_count >= test->cutoff ) {
104 DBGC ( source, "ENTROPY %s excessively repeated "
105 "value %d (%d/%d)\n", source->name, sample,
106 test->repetition_count, test->cutoff );
108 }
109
110 } else {
111
112 /* b) Else:
113 * i. A = new sample
114 */
115 test->most_recent_sample = sample;
116
117 /* ii. B = 1 */
118 test->repetition_count = 1;
119 }
120
121 return 0;
122}
#define EPIPE_REPETITION_COUNT_TEST
Definition entropy.c:45
#define DBGC(...)
Definition compiler.h:505
const char * name
Name.
Definition entropy.h:119

References DBGC, EPIPE_REPETITION_COUNT_TEST, entropy_source::name, entropy_source::repetition_count_test, and test.

Referenced by get_entropy().

◆ adaptive_proportion_test_init()

void adaptive_proportion_test_init ( struct entropy_source * source)
static

Initialise adaptive proportion test.

Parameters
sourceEntropy source

Definition at line 129 of file entropy.c.

129 {
132
133 /* Sanity checks */
134 assert ( test->sample_count == 0 );
135 assert ( test->repetition_count == 0 );
136 assert ( test->cutoff > 0 );
137
138 /* Ensure that a new test run starts immediately */
140}
#define ADAPTIVE_PROPORTION_WINDOW_SIZE
Window size for the adaptive proportion test.
Definition entropy.h:354
Adaptive proportion test state.
Definition entropy.h:76
struct entropy_adaptive_proportion_test adaptive_proportion_test
Adaptive proportion test state.
Definition entropy.h:136

References entropy_source::adaptive_proportion_test, ADAPTIVE_PROPORTION_WINDOW_SIZE, assert, and test.

Referenced by entropy_enable().

◆ adaptive_proportion_test()

int adaptive_proportion_test ( struct entropy_source * source,
noise_sample_t sample )
static

Perform adaptive proportion test.

Parameters
sourceEntropy source
sampleNoise sample
Return values
rcReturn status code

This is the Adaptive Proportion Test for the Most Common Value defined in ANS X9.82 Part 2 (October 2011 Draft) Section 8.5.2.1.3.

Definition at line 152 of file entropy.c.

153 {
156
157 /* A = the sample value currently being counted
158 * S = the number of samples examined in this run of the test so far
159 * N = the total number of samples that must be observed in
160 * one run of the test, also known as the "window size" of
161 * the test
162 * B = the current number of times that S (sic) has been seen
163 * in the W (sic) samples examined so far
164 * C = the cutoff value above which the repetition test should fail
165 * W = the probability of a false positive: 2^-30
166 */
167
168 /* 1. The entropy source draws the current sample from the
169 * noise source.
170 *
171 * (Nothing to do; we already have the current sample.)
172 */
173
174 /* 2. If S = N, then a new run of the test begins: */
175 if ( test->sample_count == ADAPTIVE_PROPORTION_WINDOW_SIZE ) {
176
177 /* a. A = the current sample */
178 test->current_counted_sample = sample;
179
180 /* b. S = 0 */
181 test->sample_count = 0;
182
183 /* c. B = 0 */
184 test->repetition_count = 0;
185
186 } else {
187
188 /* Else: (the test is already running)
189 * a. S = S + 1
190 */
191 test->sample_count++;
192
193 /* b. If A = the current sample, then: */
194 if ( sample == test->current_counted_sample ) {
195
196 /* i. B = B + 1 */
197 test->repetition_count++;
198
199 /* ii. If S (sic) > C then raise an error
200 * condition, because the test has
201 * detected a failure
202 */
203 if ( test->repetition_count > test->cutoff ) {
204 DBGC ( source, "ENTROPY %s excessively "
205 "repeated value %d (%d/%d)\n",
206 source->name, sample,
207 test->repetition_count, test->cutoff );
209 }
210 }
211 }
212
213 return 0;
214}
#define EPIPE_ADAPTIVE_PROPORTION_TEST
Definition entropy.c:49

References entropy_source::adaptive_proportion_test, ADAPTIVE_PROPORTION_WINDOW_SIZE, DBGC, EPIPE_ADAPTIVE_PROPORTION_TEST, entropy_source::name, and test.

Referenced by get_entropy().

◆ get_entropy()

int get_entropy ( struct entropy_source * source,
entropy_sample_t * entropy )
static

Get entropy sample.

Parameters
sourceEntropy source
Return values
entropyEntropy sample
rcReturn status code

This is the GetEntropy function defined in ANS X9.82 Part 2 (October 2011 Draft) Section 6.5.1.

Definition at line 226 of file entropy.c.

227 {
228 noise_sample_t noise;
229 int rc;
230
231 /* Any failure is permanent */
232 if ( ( rc = source->rc ) != 0 )
233 goto err_broken;
234
235 /* Get noise sample */
236 if ( ( rc = get_noise ( source, &noise ) ) != 0 )
237 goto err_get_noise;
238
239 /* Perform Repetition Count Test and Adaptive Proportion Test
240 * as mandated by ANS X9.82 Part 2 (October 2011 Draft)
241 * Section 8.5.2.1.1.
242 */
243 if ( ( rc = repetition_count_test ( source, noise ) ) != 0 )
244 goto err_repetition_count_test;
245 if ( ( rc = adaptive_proportion_test ( source, noise ) ) != 0 )
246 goto err_adaptive_proportion_test;
247
248 /* We do not use any optional conditioning component */
249 *entropy = noise;
250
251 return 0;
252
253 err_adaptive_proportion_test:
254 err_repetition_count_test:
255 err_get_noise:
256 source->rc = rc;
257 err_broken:
258 return rc;
259}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
static int repetition_count_test(struct entropy_source *source, noise_sample_t sample)
Perform repetition count test.
Definition entropy.c:78
static int adaptive_proportion_test(struct entropy_source *source, noise_sample_t sample)
Perform adaptive proportion test.
Definition entropy.c:152
uint8_t noise_sample_t
A noise sample.
Definition entropy.h:22
static int get_noise(struct entropy_source *source, noise_sample_t *noise)
Get noise sample.
Definition entropy.h:209
int rc
Failure status (if any)
Definition entropy.h:144

References adaptive_proportion_test(), get_noise(), entropy_source::rc, rc, and repetition_count_test().

Referenced by get_entropy_input_tmp(), and startup_test().

◆ startup_test_init()

void startup_test_init ( struct entropy_source * source)
static

Initialise startup test.

Parameters
sourceEntropy source

Definition at line 266 of file entropy.c.

266 {
267 struct entropy_startup_test *test = &source->startup_test;
268
269 /* Sanity check */
270 assert ( test->tested == 0 );
271 assert ( test->count > 0 );
272}
struct entropy_startup_test startup_test
Startup test state.
Definition entropy.h:138
Startup test state.
Definition entropy.h:105

References assert, entropy_source::startup_test, and test.

Referenced by entropy_enable().

◆ startup_test()

int startup_test ( struct entropy_source * source)
static

Perform startup test.

Parameters
sourceEntropy source
Return values
rcReturn status code

Definition at line 280 of file entropy.c.

280 {
281 struct entropy_startup_test *test = &source->startup_test;
282 entropy_sample_t sample;
283 int rc;
284
285 /* Perform mandatory number of startup tests */
286 for ( ; test->tested < test->count ; test->tested++ ) {
287 if ( ( rc = get_entropy ( source, &sample ) ) != 0 ) {
288 DBGC ( source, "ENTROPY %s failed: %s\n",
289 source->name, strerror ( rc ) );
290 return rc;
291 }
292 }
293
294 return 0;
295}
static int get_entropy(struct entropy_source *source, entropy_sample_t *entropy)
Get entropy sample.
Definition entropy.c:226
uint8_t entropy_sample_t
An entropy sample.
Definition entropy.h:25
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79

References DBGC, get_entropy(), entropy_source::name, rc, entropy_source::startup_test, strerror(), and test.

Referenced by entropy_enable_and_test().

◆ entropy_enable()

int entropy_enable ( struct entropy_source * source)

Enable entropy gathering.

Parameters
sourceEntropy source
Return values
rcReturn status code

Definition at line 303 of file entropy.c.

303 {
304 int rc;
305
306 /* Refuse to enable a previously failed source */
307 if ( ( rc = source->rc ) != 0 )
308 return rc;
309
310 /* Enable entropy source */
311 if ( ( rc = source->enable() ) != 0 ) {
312 DBGC ( source, "ENTROPY %s could not enable: %s\n",
313 source->name, strerror ( rc ) );
314 source->rc = rc;
315 return rc;
316 }
317
318 /* Sanity check */
319 assert ( source->min_entropy_per_sample > 0 );
320
321 /* Initialise test state if this source has not previously been used */
322 if ( source->startup_test.tested == 0 ) {
325 startup_test_init ( source );
326 }
327
328 DBGC ( source, "ENTROPY %s enabled\n", source->name );
329 return 0;
330}
static void startup_test_init(struct entropy_source *source)
Initialise startup test.
Definition entropy.c:266
static void repetition_count_test_init(struct entropy_source *source)
Initialise repetition count test.
Definition entropy.c:59
static void adaptive_proportion_test_init(struct entropy_source *source)
Initialise adaptive proportion test.
Definition entropy.c:129
min_entropy_t min_entropy_per_sample
min-entropy per sample
Definition entropy.h:132
int(* enable)(void)
Enable entropy gathering.
Definition entropy.h:151
unsigned int tested
Number of startup tests performed.
Definition entropy.h:107

References adaptive_proportion_test_init(), assert, DBGC, entropy_source::enable, entropy_source::min_entropy_per_sample, entropy_source::name, entropy_source::rc, rc, repetition_count_test_init(), entropy_source::startup_test, startup_test_init(), strerror(), and entropy_startup_test::tested.

Referenced by entropy_enable_and_test(), entropy_sample(), and REQUIRING_SYMBOL().

◆ entropy_enable_and_test()

int entropy_enable_and_test ( struct entropy_source * source)
static

Enable and test entropy source.

Parameters
sourceEntropy source
Return values
rcReturn status code

Definition at line 338 of file entropy.c.

338 {
339 int rc;
340
341 /* Enable source */
342 if ( ( rc = entropy_enable ( source ) ) != 0 )
343 goto err_enable;
344
345 /* Test source */
346 if ( ( rc = startup_test ( source ) ) != 0 )
347 goto err_test;
348
349 DBGC ( source, "ENTROPY %s passed %d startup tests\n",
350 source->name, source->startup_test.count );
351 return 0;
352
353 err_test:
354 entropy_disable ( source );
355 err_enable:
356 assert ( source->rc == rc );
357 return rc;
358}
void entropy_disable(struct entropy_source *source)
Disable entropy gathering.
Definition entropy.c:386
int entropy_enable(struct entropy_source *source)
Enable entropy gathering.
Definition entropy.c:303
static int startup_test(struct entropy_source *source)
Perform startup test.
Definition entropy.c:280
unsigned int count
Number of startup tests required for one full cycle.
Definition entropy.h:113

References assert, entropy_startup_test::count, DBGC, entropy_disable(), entropy_enable(), entropy_source::name, entropy_source::rc, rc, entropy_source::startup_test, and startup_test().

Referenced by entropy_enable_working().

◆ entropy_enable_working()

int entropy_enable_working ( struct entropy_source ** source)
static

Enable first working entropy source.

Parameters
sourceEntropy source to fill in
Return values
rcReturn status code

Definition at line 366 of file entropy.c.

366 {
367 int rc;
368
369 /* Find the first working source */
370 rc = -ENOENT;
372 if ( ( rc = entropy_enable_and_test ( *source ) ) == 0 )
373 return 0;
374 }
375
376 DBGC ( *source, "ENTROPY has no working sources: %s\n",
377 strerror ( rc ) );
378 return rc;
379}
static int entropy_enable_and_test(struct entropy_source *source)
Enable and test entropy source.
Definition entropy.c:338
#define ENOENT
No such file or directory.
Definition errno.h:515
#define ENTROPY_SOURCES
Entropy source table.
Definition entropy.h:170
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References DBGC, ENOENT, entropy_enable_and_test(), ENTROPY_SOURCES, for_each_table_entry, rc, and strerror().

Referenced by get_entropy_input_tmp().

◆ entropy_disable()

void entropy_disable ( struct entropy_source * source)

Disable entropy gathering.

Parameters
sourceEntropy source

Definition at line 386 of file entropy.c.

386 {
387
388 /* Disable entropy gathering, if applicable */
389 if ( source->disable )
390 source->disable();
391
392 DBGC ( source, "ENTROPY %s disabled\n", source->name );
393}
void(* disable)(void)
Disable entropy gathering.
Definition entropy.h:156

References DBGC, entropy_source::disable, and entropy_source::name.

Referenced by entropy_enable_and_test(), entropy_sample(), and get_entropy_input_tmp().

◆ make_next_nonce()

uint32_t make_next_nonce ( void )
static

Create next nonce value.

Return values
nonceNonce

This is the MakeNextNonce function defined in ANS X9.82 Part 4 (April 2011 Draft) Section 13.3.4.2.

Definition at line 403 of file entropy.c.

403 {
404 static uint32_t nonce;
405
406 /* The simplest implementation of a nonce uses a large counter */
407 nonce++;
408
409 return nonce;
410}
unsigned int uint32_t
Definition stdint.h:12
u8 nonce[32]
Nonce value.
Definition wpa.h:25

References nonce.

Referenced by get_entropy_input_tmp().

◆ get_entropy_input_tmp()

int get_entropy_input_tmp ( min_entropy_t min_entropy,
uint8_t * tmp,
size_t tmp_len )

Obtain entropy input temporary buffer.

Parameters
min_entropyMin-entropy required
tmpTemporary buffer
tmp_lenLength of temporary buffer
Return values
rcReturn 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.

Definition at line 426 of file entropy.c.

427 {
428 struct entropy_source *source;
429 struct {
431 entropy_sample_t sample;
432 } __attribute__ (( packed )) data;;
433 uint8_t df_buf[tmp_len];
434 min_entropy_t entropy_total;
435 unsigned int num_samples;
436 unsigned int i;
437 int rc;
438
439 /* Enable entropy gathering */
440 if ( ( rc = entropy_enable_working ( &source ) ) != 0 )
441 goto err_enable_working;
442
443 /* Sanity checks */
444 assert ( source->startup_test.count > 0 );
445 assert ( source->startup_test.tested >= source->startup_test.count );
446
447 /* 3. entropy_total = 0 */
448 entropy_total = MIN_ENTROPY ( 0 );
449
450 /* 4. tmp = a fixed n-bit value, such as 0^n */
451 memset ( tmp, 0, tmp_len );
452
453 /* 5. While ( entropy_total < min_entropy ) */
454 for ( num_samples = 0 ; entropy_total < min_entropy ; num_samples++ ) {
455 /* 5.1. ( status, entropy_bitstring, assessed_entropy )
456 * = GetEntropy()
457 * 5.2. If status indicates an error, return ( status, Null )
458 */
459 if ( ( rc = get_entropy ( source, &data.sample ) ) != 0 )
460 goto err_get_entropy;
461
462 /* 5.3. nonce = MakeNextNonce() */
463 data.nonce = make_next_nonce();
464
465 /* 5.4. tmp = tmp XOR
466 * df ( ( nonce || entropy_bitstring ), n )
467 */
469 df_buf, sizeof ( df_buf ) );
470 for ( i = 0 ; i < tmp_len ; i++ )
471 tmp[i] ^= df_buf[i];
472
473 /* 5.5. entropy_total = entropy_total + assessed_entropy */
474 entropy_total += source->min_entropy_per_sample;
475 }
476
477 /* Disable entropy gathering */
478 entropy_disable ( source );
479
480 DBGC ( source, "ENTROPY %s gathered %d bits in %d samples\n",
481 source->name, ( min_entropy / MIN_ENTROPY_SCALE ), num_samples );
482 return 0;
483
484 err_get_entropy:
485 entropy_disable ( source );
486 assert ( source->rc == rc );
487 err_enable_working:
488 return rc;
489}
unsigned char uint8_t
Definition stdint.h:10
uint8_t data[48]
Additional event data.
Definition ena.h:11
static int entropy_enable_working(struct entropy_source **source)
Enable first working entropy source.
Definition entropy.c:366
static uint32_t make_next_nonce(void)
Create next nonce value.
Definition entropy.c:403
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
#define __attribute__(x)
Definition compiler.h:10
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition entropy.h:43
#define MIN_ENTROPY_SCALE
Fixed-point scale for min-entropy amounts.
Definition entropy.h:35
#define entropy_hash_df_algorithm
Use SHA-256 as the underlying hash algorithm for Hash_df.
Definition entropy.h:193
unsigned int min_entropy_t
An amount of min-entropy.
Definition entropy.h:32
void * memset(void *dest, int character, size_t len) __nonnull
unsigned long tmp
Definition linux_pci.h:65
An entropy source.
Definition entropy.h:117

References __attribute__, assert, entropy_startup_test::count, data, DBGC, entropy_disable(), entropy_enable_working(), entropy_hash_df_algorithm, get_entropy(), hash_df(), make_next_nonce(), memset(), MIN_ENTROPY, entropy_source::min_entropy_per_sample, MIN_ENTROPY_SCALE, entropy_source::name, nonce, entropy_source::rc, rc, entropy_source::startup_test, entropy_startup_test::tested, and tmp.

Referenced by get_entropy_input().

◆ REQUIRING_SYMBOL()

REQUIRING_SYMBOL ( entropy_enable )

References entropy_enable().

◆ REQUIRE_OBJECT()

REQUIRE_OBJECT ( config_entropy )