iPXE
efi_entropy.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Michael Brown <mbrown@fensystems.co.uk>.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 * 02110-1301, USA.
18 *
19 * You can also choose to distribute this program under the terms of
20 * the Unmodified Binary Distribution Licence (as given in the file
21 * COPYING.UBDL), provided that you have satisfied its requirements.
22 */
23
24FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25FILE_SECBOOT ( PERMITTED );
26
27#include <errno.h>
28#include <ipxe/entropy.h>
29#include <ipxe/profile.h>
30#include <ipxe/efi/efi.h>
31
32/** @file
33 *
34 * EFI entropy source
35 *
36 */
37
39
40/** Time (in 100ns units) to delay waiting for timer tick
41 *
42 * In theory, UEFI allows us to specify a trigger time of zero to
43 * simply wait for the next timer tick. In practice, specifying zero
44 * seems to often return immediately, which produces almost no
45 * entropy. Specify a delay of 1000ns to try to force an existent
46 * delay.
47 */
48#define EFI_ENTROPY_TRIGGER_TIME 10
49
50/** Event used to wait for timer tick */
52
53/** Dropped TPL */
55
56/**
57 * Enable entropy gathering
58 *
59 * @ret rc Return status code
60 */
61static int efi_entropy_enable ( void ) {
62 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
63 EFI_STATUS efirc;
64 int rc;
65
66 /* Drop to external TPL to allow timer tick event to take place */
68
69 /* Create timer tick event */
70 if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
71 &tick ) ) != 0 ) {
72 rc = -EEFI ( efirc );
73 DBGC ( &tick, "ENTROPY could not create event: %s\n",
74 strerror ( rc ) );
75 return rc;
76 }
77
78 /* We use essentially the same mechanism as for the BIOS
79 * RTC-based entropy source, and so assume the same
80 * min-entropy per sample.
81 */
82 entropy_init ( &efitick_entropy, MIN_ENTROPY ( 1.3 ) );
83
84 return 0;
85}
86
87/**
88 * Disable entropy gathering
89 *
90 */
91static void efi_entropy_disable ( void ) {
92 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
93
94 /* Close timer tick event */
95 bs->CloseEvent ( tick );
96
97 /* Return to internal TPL */
99}
100
101/**
102 * Wait for a timer tick
103 *
104 * @ret low CPU profiling low-order bits, or negative error
105 */
106static int efi_entropy_tick ( void ) {
107 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
108 UINTN index;
110 EFI_STATUS efirc;
111 int rc;
112
113 /* Wait for next timer tick */
114 if ( ( efirc = bs->SetTimer ( tick, TimerRelative,
115 EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) {
116 rc = -EEFI ( efirc );
117 DBGC ( &tick, "ENTROPY could not set timer: %s\n",
118 strerror ( rc ) );
119 return rc;
120 }
121 if ( ( efirc = bs->WaitForEvent ( 1, &tick, &index ) ) != 0 ) {
122 rc = -EEFI ( efirc );
123 DBGC ( &tick, "ENTROPY could not wait for timer tick: %s\n",
124 strerror ( rc ) );
125 return rc;
126 }
127
128 /* Get current CPU profiling timestamp low-order bits */
130
131 return low;
132}
133
134/**
135 * Get noise sample from timer ticks
136 *
137 * @ret noise Noise sample
138 * @ret rc Return status code
139 */
140static int efi_get_noise ( noise_sample_t *noise ) {
141 int before;
142 int after;
143 int rc;
144
145 /* Wait for a timer tick */
147 if ( before < 0 ) {
148 rc = before;
149 return rc;
150 }
151
152 /* Wait for another timer tick */
154 if ( after < 0 ) {
155 rc = after;
156 return rc;
157 }
158
159 /* Use TSC delta as noise sample */
160 *noise = ( after - before );
161
162 return 0;
163}
164
165/** EFI entropy source */
166struct entropy_source efitick_entropy __entropy_source ( ENTROPY_FALLBACK ) = {
167 .name = "efitick",
168 .enable = efi_entropy_enable,
169 .disable = efi_entropy_disable,
170 .get_noise = efi_get_noise,
171};
UINT64 UINTN
Unsigned value of native width.
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
RETURN_STATUS EFI_STATUS
Function return status for EFI API.
@ TimerRelative
An event is to be signaled once at a specified interval from the current time.
Definition UefiSpec.h:552
#define EVT_TIMER
Definition UefiSpec.h:451
#define TPL_NOTIFY
Definition UefiSpec.h:650
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
unsigned short uint16_t
Definition stdint.h:11
long index
Definition bigint.h:65
static int efi_entropy_tick(void)
Wait for a timer tick.
static int efi_entropy_enable(void)
Enable entropy gathering.
Definition efi_entropy.c:61
static EFI_EVENT tick
Event used to wait for timer tick.
Definition efi_entropy.c:51
static struct efi_dropped_tpl efi_entropy_tpl
Dropped TPL.
Definition efi_entropy.c:54
static int efi_get_noise(noise_sample_t *noise)
Get noise sample from timer ticks.
static void efi_entropy_disable(void)
Disable entropy gathering.
Definition efi_entropy.c:91
#define EFI_ENTROPY_TRIGGER_TIME
Time (in 100ns units) to delay waiting for timer tick.
Definition efi_entropy.c:48
void efi_undrop_tpl(struct efi_dropped_tpl *tpl)
Restore dropped task priority level.
Definition efi_init.c:430
void efi_drop_tpl(struct efi_dropped_tpl *tpl)
Drop task priority level temporarily to external level.
Definition efi_init.c:414
Error codes.
#define DBGC(...)
Definition compiler.h:505
#define ENTROPY_FALLBACK
Fallback entropy source.
Definition entropy.h:182
#define FILE_LICENCE(_licence)
Declare a particular licence as applying to a file.
Definition compiler.h:896
#define FILE_SECBOOT(_status)
Declare a file's UEFI Secure Boot permission status.
Definition compiler.h:926
EFI API.
#define EEFI(efirc)
Convert an EFI status code to an iPXE status code.
Definition efi.h:181
#define EFI_EVENT
Definition efi.h:54
EFI_SYSTEM_TABLE * efi_systab
Entropy source.
static void entropy_init(struct entropy_source *source, min_entropy_t min_entropy_per_sample)
Initialise entropy source.
Definition entropy.h:490
#define MIN_ENTROPY(bits)
Construct a min-entropy fixed-point value.
Definition entropy.h:43
uint8_t noise_sample_t
A noise sample.
Definition entropy.h:22
#define __entropy_source(order)
Declare an entropy source.
Definition entropy.h:173
Profiling.
unsigned long profile_timestamp(void)
uint32_t low
Low 16 bits of address.
Definition myson.h:0
char * strerror(int errno)
Retrieve string representation of error number.
Definition strerror.c:79
EFI Boot Services Table.
Definition UefiSpec.h:1931
EFI_SET_TIMER SetTimer
Definition UefiSpec.h:1956
EFI_CREATE_EVENT CreateEvent
Definition UefiSpec.h:1955
EFI_CLOSE_EVENT CloseEvent
Definition UefiSpec.h:1959
EFI_WAIT_FOR_EVENT WaitForEvent
Definition UefiSpec.h:1957
An EFI dropped task priority level.
Definition efi.h:88
An entropy source.
Definition entropy.h:117
int32_t after
Final microcode version.
Definition ucode.h:7
int32_t before
Initial microcode version.
Definition ucode.h:5