Browse Source

[efi] Add EFI entropy source

Originally-implemented-by: Jarrod Johnson <jbjohnso@us.ibm.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 years ago
parent
commit
eb2252fd7a

+ 1
- 0
src/arch/x86/include/bits/errfile.h View File

@@ -50,6 +50,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
50 50
 
51 51
 #define ERRFILE_cpuid_cmd      ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00000000 )
52 52
 #define ERRFILE_cpuid_settings ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00010000 )
53
+#define ERRFILE_efi_entropy    ( ERRFILE_ARCH | ERRFILE_OTHER | 0x00020000 )
53 54
 
54 55
 /** @} */
55 56
 

+ 150
- 0
src/arch/x86/interface/efi/efi_entropy.c View File

@@ -0,0 +1,150 @@
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
+
24
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
+
26
+#include <errno.h>
27
+#include <ipxe/entropy.h>
28
+#include <ipxe/efi/efi.h>
29
+
30
+/** @file
31
+ *
32
+ * EFI entropy source
33
+ *
34
+ */
35
+
36
+/** Time (in 100ns units) to delay waiting for timer tick
37
+ *
38
+ * In theory, UEFI allows us to specify a trigger time of zero to
39
+ * simply wait for the next timer tick.  In practice, specifying zero
40
+ * seems to often return immediately, which produces almost no
41
+ * entropy.  Specify a delay of 1000ns to try to force an existent
42
+ * delay.
43
+ */
44
+#define EFI_ENTROPY_TRIGGER_TIME 10
45
+
46
+/** Event used to wait for timer tick */
47
+static EFI_EVENT tick;
48
+
49
+/**
50
+ * Enable entropy gathering
51
+ *
52
+ * @ret rc		Return status code
53
+ */
54
+static int efi_entropy_enable ( void ) {
55
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
56
+	EFI_STATUS efirc;
57
+	int rc;
58
+
59
+	/* Create timer tick event */
60
+	if ( ( efirc = bs->CreateEvent ( EVT_TIMER, TPL_NOTIFY, NULL, NULL,
61
+					 &tick ) ) != 0 ) {
62
+		rc = -EEFI ( efirc );
63
+		DBGC ( &tick, "ENTROPY could not create event: %s\n",
64
+		       strerror ( rc ) );
65
+		return rc;
66
+	}
67
+
68
+	return 0;
69
+}
70
+
71
+/**
72
+ * Disable entropy gathering
73
+ *
74
+ */
75
+static void efi_entropy_disable ( void ) {
76
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
77
+
78
+	/* Close timer tick event */
79
+	bs->CloseEvent ( tick );
80
+}
81
+
82
+/**
83
+ * Wait for an RTC tick
84
+ *
85
+ * @ret low		TSC low-order bits, or negative error
86
+ */
87
+static int efi_entropy_tick ( void ) {
88
+	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
89
+	UINTN index;
90
+	uint16_t low;
91
+	uint32_t discard_d;
92
+	EFI_STATUS efirc;
93
+	int rc;
94
+
95
+	/* Wait for next timer tick */
96
+	if ( ( efirc = bs->SetTimer ( tick, TimerRelative,
97
+				      EFI_ENTROPY_TRIGGER_TIME ) ) != 0 ) {
98
+		rc = -EEFI ( efirc );
99
+		DBGC ( &tick, "ENTROPY could not set timer: %s\n",
100
+		       strerror ( rc ) );
101
+		return rc;
102
+	}
103
+	if ( ( efirc = bs->WaitForEvent ( 1, &tick, &index ) ) != 0 ) {
104
+		rc = -EEFI ( efirc );
105
+		DBGC ( &tick, "ENTROPY could not wait for timer tick: %s\n",
106
+		       strerror ( rc ) );
107
+		return rc;
108
+	}
109
+
110
+	/* Get current TSC low-order bits */
111
+	__asm__ __volatile__ ( "rdtsc" : "=a" ( low ), "=d" ( discard_d ) );
112
+
113
+	return low;
114
+}
115
+
116
+/**
117
+ * Get noise sample
118
+ *
119
+ * @ret noise		Noise sample
120
+ * @ret rc		Return status code
121
+ */
122
+static int efi_get_noise ( noise_sample_t *noise ) {
123
+	int before;
124
+	int after;
125
+	int rc;
126
+
127
+	/* Wait for a timer tick */
128
+	before = efi_entropy_tick();
129
+	if ( before < 0 ) {
130
+		rc = before;
131
+		return rc;
132
+	}
133
+
134
+	/* Wait for another timer tick */
135
+	after = efi_entropy_tick();
136
+	if ( after < 0 ) {
137
+		rc = after;
138
+		return rc;
139
+	}
140
+
141
+	/* Use TSC delta as noise sample */
142
+	*noise = ( after - before );
143
+
144
+	return 0;
145
+}
146
+
147
+PROVIDE_ENTROPY_INLINE ( efi, min_entropy_per_sample );
148
+PROVIDE_ENTROPY ( efi, entropy_enable, efi_entropy_enable );
149
+PROVIDE_ENTROPY ( efi, entropy_disable, efi_entropy_disable );
150
+PROVIDE_ENTROPY ( efi, get_noise, efi_get_noise );

+ 2
- 2
src/config/defaults/efi.h View File

@@ -7,7 +7,7 @@
7 7
  *
8 8
  */
9 9
 
10
-FILE_LICENCE ( GPL2_OR_LATER );
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11 11
 
12 12
 #define UACCESS_EFI
13 13
 #define IOAPI_X86
@@ -19,7 +19,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
19 19
 #define SMBIOS_EFI
20 20
 #define SANBOOT_NULL
21 21
 #define BOFM_EFI
22
-#define ENTROPY_NULL
22
+#define ENTROPY_EFI
23 23
 #define TIME_NULL
24 24
 #define REBOOT_EFI
25 25
 

+ 35
- 0
src/include/ipxe/efi/efi_entropy.h View File

@@ -0,0 +1,35 @@
1
+#ifndef _IPXE_EFI_ENTROPY_H
2
+#define _IPXE_EFI_ENTROPY_H
3
+
4
+/** @file
5
+ *
6
+ * EFI entropy source
7
+ *
8
+ */
9
+
10
+FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
11
+
12
+#include <stdint.h>
13
+
14
+#ifdef ENTROPY_EFI
15
+#define ENTROPY_PREFIX_efi
16
+#else
17
+#define ENTROPY_PREFIX_efi __efi_
18
+#endif
19
+
20
+/**
21
+ * min-entropy per sample
22
+ *
23
+ * @ret min_entropy	min-entropy of each sample
24
+ */
25
+static inline __always_inline double
26
+ENTROPY_INLINE ( efi, min_entropy_per_sample ) ( void ) {
27
+
28
+	/* We use essentially the same mechanism as for the BIOS
29
+	 * RTC-based entropy source, and so assume the same
30
+	 * min-entropy per sample.
31
+	 */
32
+	return 1.3;
33
+}
34
+
35
+#endif /* _IPXE_EFI_ENTROPY_H */

+ 1
- 0
src/include/ipxe/entropy.h View File

@@ -54,6 +54,7 @@ typedef uint8_t entropy_sample_t;
54 54
 
55 55
 /* Include all architecture-independent entropy API headers */
56 56
 #include <ipxe/null_entropy.h>
57
+#include <ipxe/efi/efi_entropy.h>
57 58
 #include <ipxe/linux/linux_entropy.h>
58 59
 
59 60
 /* Include all architecture-dependent entropy API headers */

Loading…
Cancel
Save