Skip to content

Commit ccd6200

Browse files
committed
[crypto] Start up RBG on demand if needed
The ANS X9.82 specification implicitly assumes that the RBG_Startup function will be called before it is needed, and includes checks to make sure that Generate_function fails if this has not happened. However, there is no well-defined point at which the RBG_Startup function is to be called: it's just assumed that this happens as part of system startup. We currently call RBG_Startup to instantiate the DRBG as an iPXE startup function, with the corresponding shutdown function uninstantiating the DRBG. This works for most use cases, and avoids an otherwise unexpected user-visible delay when a caller first attempts to use the DRBG (e.g. by attempting an HTTPS download). The download of autoexec.ipxe for UEFI is triggered by the EFI root bus probe in efi_probe(). Both the root bus probe and the RBG startup function run at STARTUP_NORMAL, so there is no defined ordering between them. If the base URI for autoexec.ipxe uses HTTPS, then this may cause random bits to be requested before the RBG has been started. Extend the logic in rbg_generate() to automatically start up the RBG if startup has not already been attempted. If startup fails (e.g. because the entropy source is broken), then do not automatically retry since this could result in extremely long delays waiting for entropy that will never arrive. Reported-by: Michael Niehaus <[email protected]> Signed-off-by: Michael Brown <[email protected]>
1 parent b35300f commit ccd6200

File tree

2 files changed

+43
-23
lines changed

2 files changed

+43
-23
lines changed

src/crypto/rbg.c

+39-4
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ static int rbg_startup ( void ) {
7575
int len;
7676
int rc;
7777

78+
/* Record that startup has been attempted (even if unsuccessful) */
79+
rbg.started = 1;
80+
7881
/* Try to obtain system UUID for use as personalisation
7982
* string, in accordance with ANS X9.82 Part 3-2007 Section
8083
* 8.5.2. If no UUID is available, proceed without a
@@ -97,6 +100,33 @@ static int rbg_startup ( void ) {
97100
return 0;
98101
}
99102

103+
/**
104+
* Generate bits using RBG
105+
*
106+
* @v additional Additional input
107+
* @v additional_len Length of additional input
108+
* @v prediction_resist Prediction resistance is required
109+
* @v data Output buffer
110+
* @v len Length of output buffer
111+
* @ret rc Return status code
112+
*
113+
* This is the RBG_Generate function defined in ANS X9.82 Part 4
114+
* (April 2011 Draft) Section 9.1.2.2.
115+
*/
116+
int rbg_generate ( const void *additional, size_t additional_len,
117+
int prediction_resist, void *data, size_t len ) {
118+
119+
/* Attempt startup, if not already attempted */
120+
if ( ! rbg.started )
121+
rbg_startup();
122+
123+
/* Generate bits. The DRBG will itself return an error if it
124+
* is not valid (e.g. due to an instantiation failure).
125+
*/
126+
return drbg_generate ( &rbg.state, additional, additional_len,
127+
prediction_resist, data, len );
128+
}
129+
100130
/**
101131
* Shut down RBG
102132
*
@@ -105,16 +135,21 @@ static void rbg_shutdown ( void ) {
105135

106136
/* Uninstantiate DRBG */
107137
drbg_uninstantiate ( &rbg.state );
138+
139+
/* Clear startup attempted flag */
140+
rbg.started = 0;
108141
}
109142

110143
/** RBG startup function */
111144
static void rbg_startup_fn ( void ) {
112145

113-
/* Start up RBG. There is no way to report an error at this
114-
* stage, but a failed startup will result in an invalid DRBG
115-
* that refuses to generate bits.
146+
/* Start up RBG (if not already started on demand). There is
147+
* no way to report an error at this stage, but a failed
148+
* startup will result in an invalid DRBG that refuses to
149+
* generate bits.
116150
*/
117-
rbg_startup();
151+
if ( ! rbg.started )
152+
rbg_startup();
118153
}
119154

120155
/** RBG shutdown function */

src/include/ipxe/rbg.h

+4-19
Original file line numberDiff line numberDiff line change
@@ -16,28 +16,13 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
1616
struct random_bit_generator {
1717
/** DRBG state */
1818
struct drbg_state state;
19+
/** Startup has been attempted */
20+
int started;
1921
};
2022

2123
extern struct random_bit_generator rbg;
2224

23-
/**
24-
* Generate bits using RBG
25-
*
26-
* @v additional Additional input
27-
* @v additional_len Length of additional input
28-
* @v prediction_resist Prediction resistance is required
29-
* @v data Output buffer
30-
* @v len Length of output buffer
31-
* @ret rc Return status code
32-
*
33-
* This is the RBG_Generate function defined in ANS X9.82 Part 4
34-
* (April 2011 Draft) Section 9.1.2.2.
35-
*/
36-
static inline int rbg_generate ( const void *additional, size_t additional_len,
37-
int prediction_resist, void *data,
38-
size_t len ) {
39-
return drbg_generate ( &rbg.state, additional, additional_len,
40-
prediction_resist, data, len );
41-
}
25+
extern int rbg_generate ( const void *additional, size_t additional_len,
26+
int prediction_resist, void *data, size_t len );
4227

4328
#endif /* _IPXE_RBG_H */

0 commit comments

Comments
 (0)