iPXE
Macros | Functions | Variables
efi_entropy.c File Reference

EFI entropy source. More...

#include <errno.h>
#include <ipxe/entropy.h>
#include <ipxe/crc32.h>
#include <ipxe/profile.h>
#include <ipxe/efi/efi.h>
#include <ipxe/efi/Protocol/Rng.h>

Go to the source code of this file.

Macros

#define EFI_ENTROPY_RNG_LEN   32
 Minimum number of bytes to request from RNG. More...
 
#define EFI_ENTROPY_TRIGGER_TIME   10
 Time (in 100ns units) to delay waiting for timer tick. More...
 

Functions

 FILE_LICENCE (GPL2_OR_LATER_OR_UBDL)
 
 EFI_REQUEST_PROTOCOL (EFI_RNG_PROTOCOL, &efirng)
 
static int efi_entropy_enable (void)
 Enable entropy gathering. More...
 
static void efi_entropy_disable (void)
 Disable entropy gathering. More...
 
static int efi_entropy_tick (void)
 Wait for a timer tick. More...
 
static int efi_get_noise_ticks (noise_sample_t *noise)
 Get noise sample from timer ticks. More...
 
static int efi_get_noise_rng (noise_sample_t *noise)
 Get noise sample from RNG protocol. More...
 
static int efi_get_noise (noise_sample_t *noise)
 Get noise sample. More...
 
 PROVIDE_ENTROPY_INLINE (efi, min_entropy_per_sample)
 
 PROVIDE_ENTROPY (efi, entropy_enable, efi_entropy_enable)
 
 PROVIDE_ENTROPY (efi, entropy_disable, efi_entropy_disable)
 
 PROVIDE_ENTROPY (efi, get_noise, efi_get_noise)
 

Variables

static EFI_RNG_PROTOCOLefirng
 Random number generator protocol. More...
 
static EFI_EVENT tick
 Event used to wait for timer tick. More...
 

Detailed Description

EFI entropy source.

Definition in file efi_entropy.c.

Macro Definition Documentation

◆ EFI_ENTROPY_RNG_LEN

#define EFI_ENTROPY_RNG_LEN   32

Minimum number of bytes to request from RNG.

The UEFI spec states (for no apparently good reason) that "When a Deterministic Random Bit Generator (DRBG) is used on the output of a (raw) entropy source, its security level must be at least 256 bits." The EDK2 codebase (mis)interprets this to mean that the call to GetRNG() should fail if given a buffer less than 32 bytes.

Incidentally, nothing in the EFI RNG protocol provides any way to report the actual amount of entropy returned by GetRNG().

Definition at line 54 of file efi_entropy.c.

◆ EFI_ENTROPY_TRIGGER_TIME

#define EFI_ENTROPY_TRIGGER_TIME   10

Time (in 100ns units) to delay waiting for timer tick.

In theory, UEFI allows us to specify a trigger time of zero to simply wait for the next timer tick. In practice, specifying zero seems to often return immediately, which produces almost no entropy. Specify a delay of 1000ns to try to force an existent delay.

Definition at line 64 of file efi_entropy.c.

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL  )

◆ EFI_REQUEST_PROTOCOL()

EFI_REQUEST_PROTOCOL ( EFI_RNG_PROTOCOL  ,
efirng 
)

◆ efi_entropy_enable()

static int efi_entropy_enable ( void  )
static

Enable entropy gathering.

Return values
rcReturn status code

Definition at line 74 of file efi_entropy.c.

74  {
76  EFI_STATUS efirc;
77  int rc;
78 
79  DBGC ( &tick, "ENTROPY %s RNG protocol\n",
80  ( efirng ? "has" : "has no" ) );
81 
82  /* Drop to TPL_APPLICATION to allow timer tick event to take place */
84 
85  /* Create timer tick event */
86  if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
87  &tick ) ) != 0 ) {
88  rc = -EEFI ( efirc );
89  DBGC ( &tick, "ENTROPY could not create event: %s\n",
90  strerror ( rc ) );
91  return rc;
92  }
93 
94  return 0;
95 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
#define TPL_APPLICATION
Definition: UefiSpec.h:590
static EFI_EVENT tick
Event used to wait for timer tick.
Definition: efi_entropy.c:67
static EFI_RNG_PROTOCOL * efirng
Random number generator protocol.
Definition: efi_entropy.c:40
#define DBGC(...)
Definition: compiler.h:505
#define TPL_NOTIFY
Definition: UefiSpec.h:592
EFI_CREATE_EVENT CreateEvent
Definition: UefiSpec.h:1860
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
EFI Boot Services Table.
Definition: UefiSpec.h:1836
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
EFI_SYSTEM_TABLE * efi_systab
EFI_RESTORE_TPL RestoreTPL
Definition: UefiSpec.h:1846
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362
#define EVT_TIMER
Definition: UefiSpec.h:391

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CreateEvent, DBGC, EEFI, efi_systab, efirng, EVT_TIMER, NULL, rc, EFI_BOOT_SERVICES::RestoreTPL, strerror(), tick, TPL_APPLICATION, and TPL_NOTIFY.

◆ efi_entropy_disable()

static void efi_entropy_disable ( void  )
static

Disable entropy gathering.

Definition at line 101 of file efi_entropy.c.

101  {
103 
104  /* Close timer tick event */
105  bs->CloseEvent ( tick );
106 
107  /* Return to TPL_CALLBACK */
108  bs->RaiseTPL ( TPL_CALLBACK );
109 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
EFI_RAISE_TPL RaiseTPL
Definition: UefiSpec.h:1845
static EFI_EVENT tick
Event used to wait for timer tick.
Definition: efi_entropy.c:67
EFI_CLOSE_EVENT CloseEvent
Definition: UefiSpec.h:1864
EFI Boot Services Table.
Definition: UefiSpec.h:1836
#define TPL_CALLBACK
Definition: UefiSpec.h:591
EFI_SYSTEM_TABLE * efi_systab

References EFI_SYSTEM_TABLE::BootServices, EFI_BOOT_SERVICES::CloseEvent, efi_systab, EFI_BOOT_SERVICES::RaiseTPL, tick, and TPL_CALLBACK.

◆ efi_entropy_tick()

static int efi_entropy_tick ( void  )
static

Wait for a timer tick.

Return values
lowCPU profiling low-order bits, or negative error

Definition at line 116 of file efi_entropy.c.

116  {
118  UINTN index;
119  uint16_t low;
120  EFI_STATUS efirc;
121  int rc;
122 
123  /* Wait for next timer tick */
124  if ( ( efirc = bs->SetTimer ( tick, TimerRelative,
125  EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) {
126  rc = -EEFI ( efirc );
127  DBGC ( &tick, "ENTROPY could not set timer: %s\n",
128  strerror ( rc ) );
129  return rc;
130  }
131  if ( ( efirc = bs->WaitForEvent ( 1, &tick, &index ) ) != 0 ) {
132  rc = -EEFI ( efirc );
133  DBGC ( &tick, "ENTROPY could not wait for timer tick: %s\n",
134  strerror ( rc ) );
135  return rc;
136  }
137 
138  /* Get current CPU profiling timestamp low-order bits */
139  low = profile_timestamp();
140 
141  return low;
142 }
EFI_BOOT_SERVICES * BootServices
A pointer to the EFI Boot Services Table.
Definition: UefiSpec.h:2000
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
unsigned short uint16_t
Definition: stdint.h:11
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
An event is to be signaled once at a specified interval from the current time.
Definition: UefiSpec.h:493
static EFI_EVENT tick
Event used to wait for timer tick.
Definition: efi_entropy.c:67
#define DBGC(...)
Definition: compiler.h:505
EFI_SET_TIMER SetTimer
Definition: UefiSpec.h:1861
#define EFI_ENTROPY_TRIGGER_TIME
Time (in 100ns units) to delay waiting for timer tick.
Definition: efi_entropy.c:64
uint32_t low
Low 16 bits of address.
Definition: intel.h:21
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
EFI Boot Services Table.
Definition: UefiSpec.h:1836
UINT64 UINTN
Unsigned value of native width.
Definition: ProcessorBind.h:71
EFI_WAIT_FOR_EVENT WaitForEvent
Definition: UefiSpec.h:1862
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
EFI_SYSTEM_TABLE * efi_systab
uint64_t index
Index of the first segment within the content.
Definition: pccrc.h:21

References EFI_SYSTEM_TABLE::BootServices, DBGC, EEFI, EFI_ENTROPY_TRIGGER_TIME, efi_systab, index, low, rc, EFI_BOOT_SERVICES::SetTimer, strerror(), tick, TimerRelative, and EFI_BOOT_SERVICES::WaitForEvent.

Referenced by efi_get_noise_ticks().

◆ efi_get_noise_ticks()

static int efi_get_noise_ticks ( noise_sample_t noise)
static

Get noise sample from timer ticks.

Return values
noiseNoise sample
rcReturn status code

Definition at line 150 of file efi_entropy.c.

150  {
151  int before;
152  int after;
153  int rc;
154 
155  /* Wait for a timer tick */
156  before = efi_entropy_tick();
157  if ( before < 0 ) {
158  rc = before;
159  return rc;
160  }
161 
162  /* Wait for another timer tick */
163  after = efi_entropy_tick();
164  if ( after < 0 ) {
165  rc = after;
166  return rc;
167  }
168 
169  /* Use TSC delta as noise sample */
170  *noise = ( after - before );
171 
172  return 0;
173 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int efi_entropy_tick(void)
Wait for a timer tick.
Definition: efi_entropy.c:116

References efi_entropy_tick(), and rc.

Referenced by efi_get_noise().

◆ efi_get_noise_rng()

static int efi_get_noise_rng ( noise_sample_t noise)
static

Get noise sample from RNG protocol.

Return values
noiseNoise sample
rcReturn status code

Definition at line 181 of file efi_entropy.c.

181  {
183  EFI_STATUS efirc;
184  int rc;
185 
186  /* Fail if we have no EFI RNG protocol */
187  if ( ! efirng )
188  return -ENOTSUP;
189 
190  /* Get the minimum allowed number of random bytes */
191  if ( ( efirc = efirng->GetRNG ( efirng, NULL, EFI_ENTROPY_RNG_LEN,
192  buf ) ) != 0 ) {
193  rc = -EEFI ( efirc );
194  DBGC ( &tick, "ENTROPY could not read from RNG: %s\n",
195  strerror ( rc ) );
196  return rc;
197  }
198 
199  /* Reduce random bytes to a single noise sample. This seems
200  * like overkill, but we have no way of knowing how much
201  * entropy is actually present in the bytes returned by the
202  * RNG protocol.
203  */
204  *noise = crc32_le ( 0, buf, sizeof ( buf ) );
205 
206  return 0;
207 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition: efi.h:157
static EFI_EVENT tick
Event used to wait for timer tick.
Definition: efi_entropy.c:67
static EFI_RNG_PROTOCOL * efirng
Random number generator protocol.
Definition: efi_entropy.c:40
#define DBGC(...)
Definition: compiler.h:505
#define EFI_ENTROPY_RNG_LEN
Minimum number of bytes to request from RNG.
Definition: efi_entropy.c:54
#define ENOTSUP
Operation not supported.
Definition: errno.h:589
u32 crc32_le(u32 seed, const void *data, size_t len)
Calculate 32-bit little-endian CRC checksum.
Definition: crc32.c:39
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
unsigned char uint8_t
Definition: stdint.h:10
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
Definition: UefiBaseType.h:35
EFI_RNG_GET_RNG GetRNG
Definition: Rng.h:147
#define NULL
NULL pointer (VOID *)
Definition: Base.h:362

References crc32_le(), DBGC, EEFI, EFI_ENTROPY_RNG_LEN, efirng, ENOTSUP, _EFI_RNG_PROTOCOL::GetRNG, NULL, rc, strerror(), and tick.

Referenced by efi_get_noise().

◆ efi_get_noise()

static int efi_get_noise ( noise_sample_t noise)
static

Get noise sample.

Return values
noiseNoise sample
rcReturn status code

Definition at line 215 of file efi_entropy.c.

215  {
216  int rc;
217 
218  /* Try RNG first, falling back to timer ticks */
219  if ( ( ( rc = efi_get_noise_rng ( noise ) ) != 0 ) &&
220  ( ( rc = efi_get_noise_ticks ( noise ) ) != 0 ) )
221  return rc;
222 
223  return 0;
224 }
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
static int efi_get_noise_rng(noise_sample_t *noise)
Get noise sample from RNG protocol.
Definition: efi_entropy.c:181
static int efi_get_noise_ticks(noise_sample_t *noise)
Get noise sample from timer ticks.
Definition: efi_entropy.c:150

References efi_get_noise_rng(), efi_get_noise_ticks(), and rc.

◆ PROVIDE_ENTROPY_INLINE()

PROVIDE_ENTROPY_INLINE ( efi  ,
min_entropy_per_sample   
)

◆ PROVIDE_ENTROPY() [1/3]

PROVIDE_ENTROPY ( efi  ,
entropy_enable  ,
efi_entropy_enable   
)

◆ PROVIDE_ENTROPY() [2/3]

PROVIDE_ENTROPY ( efi  ,
entropy_disable  ,
efi_entropy_disable   
)

◆ PROVIDE_ENTROPY() [3/3]

PROVIDE_ENTROPY ( efi  ,
get_noise  ,
efi_get_noise   
)

Variable Documentation

◆ efirng

EFI_RNG_PROTOCOL* efirng
static

Random number generator protocol.

Definition at line 40 of file efi_entropy.c.

Referenced by efi_entropy_enable(), and efi_get_noise_rng().

◆ tick

EFI_EVENT tick
static

Event used to wait for timer tick.

Definition at line 67 of file efi_entropy.c.

Referenced by efi_entropy_disable(), efi_entropy_enable(), efi_entropy_tick(), efi_get_noise_rng(), and fiber_autoneg().