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/**
54 * Enable entropy gathering
55 *
56 * @ret rc Return status code
57 */
58static int efi_entropy_enable ( void ) {
59 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
60 EFI_STATUS efirc;
61 int rc;
62
63 /* Drop to external TPL to allow timer tick event to take place */
65
66 /* Create timer tick event */
67 if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
68 &tick ) ) != 0 ) {
69 rc = -EEFI ( efirc );
70 DBGC ( &tick, "ENTROPY could not create event: %s\n",
71 strerror ( rc ) );
72 return rc;
73 }
74
75 /* We use essentially the same mechanism as for the BIOS
76 * RTC-based entropy source, and so assume the same
77 * min-entropy per sample.
78 */
79 entropy_init ( &efitick_entropy, MIN_ENTROPY ( 1.3 ) );
80
81 return 0;
82}
83
84/**
85 * Disable entropy gathering
86 *
87 */
88static void efi_entropy_disable ( void ) {
89 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
90
91 /* Close timer tick event */
92 bs->CloseEvent ( tick );
93
94 /* Return to internal TPL */
96}
97
98/**
99 * Wait for a timer tick
100 *
101 * @ret low CPU profiling low-order bits, or negative error
102 */
103static int efi_entropy_tick ( void ) {
104 EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
105 UINTN index;
107 EFI_STATUS efirc;
108 int rc;
109
110 /* Wait for next timer tick */
111 if ( ( efirc = bs->SetTimer ( tick, TimerRelative,
112 EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) {
113 rc = -EEFI ( efirc );
114 DBGC ( &tick, "ENTROPY could not set timer: %s\n",
115 strerror ( rc ) );
116 return rc;
117 }
118 if ( ( efirc = bs->WaitForEvent ( 1, &tick, &index ) ) != 0 ) {
119 rc = -EEFI ( efirc );
120 DBGC ( &tick, "ENTROPY could not wait for timer tick: %s\n",
121 strerror ( rc ) );
122 return rc;
123 }
124
125 /* Get current CPU profiling timestamp low-order bits */
127
128 return low;
129}
130
131/**
132 * Get noise sample from timer ticks
133 *
134 * @ret noise Noise sample
135 * @ret rc Return status code
136 */
137static int efi_get_noise ( noise_sample_t *noise ) {
138 int before;
139 int after;
140 int rc;
141
142 /* Wait for a timer tick */
144 if ( before < 0 ) {
145 rc = before;
146 return rc;
147 }
148
149 /* Wait for another timer tick */
151 if ( after < 0 ) {
152 rc = after;
153 return rc;
154 }
155
156 /* Use TSC delta as noise sample */
157 *noise = ( after - before );
158
159 return 0;
160}
161
162/** EFI entropy source */
163struct entropy_source efitick_entropy __entropy_source ( ENTROPY_FALLBACK ) = {
164 .name = "efitick",
165 .enable = efi_entropy_enable,
166 .disable = efi_entropy_disable,
167 .get_noise = efi_get_noise,
168};
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:58
static EFI_EVENT tick
Event used to wait for timer tick.
Definition efi_entropy.c:51
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:88
#define EFI_ENTROPY_TRIGGER_TIME
Time (in 100ns units) to delay waiting for timer tick.
Definition efi_entropy.c:48
EFI_TPL efi_external_tpl
External task priority level.
Definition efi_init.c:57
EFI_TPL efi_internal_tpl
Internal task priority level.
Definition efi_init.c:54
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:175
#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_RESTORE_TPL RestoreTPL
Definition UefiSpec.h:1941
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_RAISE_TPL RaiseTPL
Definition UefiSpec.h:1940
EFI_WAIT_FOR_EVENT WaitForEvent
Definition UefiSpec.h:1957
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