]>
Commit | Line | Data |
---|---|---|
8dc67017 SB |
1 | QEMU TPM Device |
2 | =============== | |
3 | ||
4 | = Guest-side Hardware Interface = | |
5 | ||
6 | The QEMU TPM emulation implements a TPM TIS hardware interface following the | |
7 | Trusted Computing Group's specification "TCG PC Client Specific TPM Interface | |
8 | Specification (TIS)", Specification Version 1.3, 21 March 2013. This | |
9 | specification, or a later version of it, can be accessed from the following | |
10 | URL: | |
11 | ||
12 | https://trustedcomputinggroup.org/pc-client-work-group-pc-client-specific-tpm-interface-specification-tis/ | |
13 | ||
14 | The TIS interface makes a memory mapped IO region in the area 0xfed40000 - | |
15 | 0xfed44fff available to the guest operating system. | |
16 | ||
17 | ||
18 | QEMU files related to TPM TIS interface: | |
19 | - hw/tpm/tpm_tis.c | |
20 | - hw/tpm/tpm_tis.h | |
21 | ||
22 | ||
7931cf31 SB |
23 | QEMU also implements a TPM CRB interface following the Trusted Computing |
24 | Group's specification "TCG PC Client Platform TPM Profile (PTP) | |
25 | Specification", Family "2.0", Level 00 Revision 01.03 v22, May 22, 2017. | |
26 | This specification, or a later version of it, can be accessed from the | |
27 | following URL: | |
28 | ||
29 | https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ | |
30 | ||
31 | The CRB interface makes a memory mapped IO region in the area 0xfed40000 - | |
32 | 0xfed40fff (1 locality) available to the guest operating system. | |
33 | ||
34 | QEMU files related to TPM CRB interface: | |
35 | - hw/tpm/tpm_crb.c | |
36 | ||
37 | ||
8dc67017 SB |
38 | = ACPI Interface = |
39 | ||
40 | The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT and passes | |
41 | it into the guest through the fw_cfg device. The device description contains | |
42 | the base address of the TIS interface 0xfed40000 and the size of the MMIO area | |
43 | (0x5000). In case a TPM2 is used by QEMU, a TPM2 ACPI table is also provided. | |
44 | The device is described to be used in polling mode rather than interrupt mode | |
45 | primarily because no unused IRQ could be found. | |
46 | ||
47 | To support measurement logs to be written by the firmware, e.g. SeaBIOS, a TCPA | |
48 | table is implemented. This table provides a 64kb buffer where the firmware can | |
49 | write its log into. For TPM 2 only a more recent version of the TPM2 table | |
50 | provides support for measurements logs and a TCPA table does not need to be | |
51 | created. | |
52 | ||
53 | The TCPA and TPM2 ACPI tables follow the Trusted Computing Group specification | |
54 | "TCG ACPI Specification" Family "1.2" and "2.0", Level 00 Revision 00.37. This | |
55 | specification, or a later version of it, can be accessed from the following | |
56 | URL: | |
57 | ||
58 | https://trustedcomputinggroup.org/tcg-acpi-specification/ | |
59 | ||
60 | ||
61 | QEMU files related to TPM ACPI tables: | |
62 | - hw/i386/acpi-build.c | |
63 | - include/hw/acpi/tpm.h | |
64 | ||
65 | ||
66 | = TPM backend devices = | |
67 | ||
68 | The TPM implementation is split into two parts, frontend and backend. The | |
69 | frontend part is the hardware interface, such as the TPM TIS interface | |
70 | described earlier, and the other part is the TPM backend interface. The backend | |
71 | interfaces implement the interaction with a TPM device, which may be a physical | |
72 | or an emulated device. The split between the front- and backend devices allows | |
73 | a frontend to be connected with any available backend. This enables the TIS | |
74 | interface to be used with the passthrough backend or the (future) swtpm backend. | |
75 | ||
76 | ||
77 | QEMU files related to TPM backends: | |
78 | - backends/tpm.c | |
79 | - include/sysemu/tpm_backend.h | |
80 | - include/sysemu/tpm_backend_int.h | |
81 | ||
82 | ||
83 | == The QEMU TPM passthrough device == | |
84 | ||
85 | In case QEMU is run on Linux as the host operating system it is possible to | |
86 | make the hardware TPM device available to a single QEMU guest. In this case the | |
87 | user must make sure that no other program is using the device, e.g., /dev/tpm0, | |
88 | before trying to start QEMU with it. | |
89 | ||
90 | The passthrough driver uses the host's TPM device for sending TPM commands | |
91 | and receiving responses from. Besides that it accesses the TPM device's sysfs | |
92 | entry for support of command cancellation. Since none of the state of a | |
93 | hardware TPM can be migrated between hosts, virtual machine migration is | |
94 | disabled when the TPM passthrough driver is used. | |
95 | ||
96 | Since the host's TPM device will already be initialized by the host's firmware, | |
97 | certain commands, e.g. TPM_Startup(), sent by the virtual firmware for device | |
98 | initialization, will fail. In this case the firmware should not use the TPM. | |
99 | ||
100 | Sharing the device with the host is generally not a recommended usage scenario | |
101 | for a TPM device. The primary reason for this is that two operating systems can | |
102 | then access the device's single set of resources, such as platform configuration | |
103 | registers (PCRs). Applications or kernel security subsystems, such as the | |
104 | Linux Integrity Measurement Architecture (IMA), are not expecting to share PCRs. | |
105 | ||
106 | ||
107 | QEMU files related to the TPM passthrough device: | |
108 | - hw/tpm/tpm_passthrough.c | |
109 | - hw/tpm/tpm_util.c | |
110 | - hw/tpm/tpm_util.h | |
111 | ||
112 | ||
113 | Command line to start QEMU with the TPM passthrough device using the host's | |
114 | hardware TPM /dev/tpm0: | |
115 | ||
a1d30f28 | 116 | qemu-system-x86_64 -display sdl -accel kvm \ |
8dc67017 SB |
117 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
118 | -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \ | |
119 | -device tpm-tis,tpmdev=tpm0 test.img | |
120 | ||
121 | The following commands should result in similar output inside the VM with a | |
122 | Linux kernel that either has the TPM TIS driver built-in or available as a | |
123 | module: | |
124 | ||
125 | #> dmesg | grep -i tpm | |
126 | [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) | |
127 | ||
128 | #> dmesg | grep TCPA | |
129 | [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ | |
130 | BXPCTCPA 0000001 BXPC 00000001) | |
131 | ||
132 | #> ls -l /dev/tpm* | |
133 | crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 | |
134 | ||
135 | #> find /sys/devices/ | grep pcrs$ | xargs cat | |
136 | PCR-00: 35 4E 3B CE 23 9F 38 59 ... | |
137 | ... | |
138 | PCR-23: 00 00 00 00 00 00 00 00 ... | |
83e83c34 SB |
139 | |
140 | ||
141 | == The QEMU TPM emulator device == | |
142 | ||
143 | The TPM emulator device uses an external TPM emulator called 'swtpm' for | |
144 | sending TPM commands to and receiving responses from. The swtpm program | |
145 | must have been started before trying to access it through the TPM emulator | |
146 | with QEMU. | |
147 | ||
148 | The TPM emulator implements a command channel for transferring TPM commands | |
149 | and responses as well as a control channel over which control commands can | |
150 | be sent. The specification for the control channel can be found here: | |
151 | ||
152 | https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod | |
153 | ||
154 | ||
155 | The control channel serves the purpose of resetting, initializing, and | |
156 | migrating the TPM state, among other things. | |
157 | ||
158 | The swtpm program behaves like a hardware TPM and therefore needs to be | |
159 | initialized by the firmware running inside the QEMU virtual machine. | |
160 | One necessary step for initializing the device is to send the TPM_Startup | |
161 | command to it. SeaBIOS, for example, has been instrumented to initialize | |
162 | a TPM 1.2 or TPM 2 device using this command. | |
163 | ||
164 | ||
165 | QEMU files related to the TPM emulator device: | |
166 | - hw/tpm/tpm_emulator.c | |
167 | - hw/tpm/tpm_util.c | |
168 | - hw/tpm/tpm_util.h | |
169 | ||
170 | ||
171 | The following commands start the swtpm with a UnixIO control channel over | |
172 | a socket interface. They do not need to be run as root. | |
173 | ||
174 | mkdir /tmp/mytpm1 | |
175 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
176 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
177 | --log level=20 | |
178 | ||
179 | Command line to start QEMU with the TPM emulator device communicating with | |
180 | the swtpm: | |
181 | ||
a1d30f28 | 182 | qemu-system-x86_64 -display sdl -accel kvm \ |
83e83c34 SB |
183 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
184 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
185 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
186 | -device tpm-tis,tpmdev=tpm0 test.img | |
187 | ||
188 | ||
189 | In case SeaBIOS is used as firmware, it should show the TPM menu item | |
190 | after entering the menu with 'ESC'. | |
191 | ||
192 | Select boot device: | |
193 | 1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD] | |
194 | [...] | |
195 | 5. Legacy option rom | |
196 | ||
197 | t. TPM Configuration | |
198 | ||
199 | ||
200 | The following commands should result in similar output inside the VM with a | |
201 | Linux kernel that either has the TPM TIS driver built-in or available as a | |
202 | module: | |
203 | ||
204 | #> dmesg | grep -i tpm | |
205 | [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) | |
206 | ||
207 | #> dmesg | grep TCPA | |
208 | [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ | |
209 | BXPCTCPA 0000001 BXPC 00000001) | |
210 | ||
211 | #> ls -l /dev/tpm* | |
212 | crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 | |
213 | ||
214 | #> find /sys/devices/ | grep pcrs$ | xargs cat | |
215 | PCR-00: 35 4E 3B CE 23 9F 38 59 ... | |
216 | ... | |
217 | PCR-23: 00 00 00 00 00 00 00 00 ... | |
9d1f0985 SB |
218 | |
219 | ||
220 | === Migration with the TPM emulator === | |
221 | ||
222 | The TPM emulator supports the following types of virtual machine migration: | |
223 | ||
224 | - VM save / restore (migration into a file) | |
225 | - Network migration | |
226 | - Snapshotting (migration into storage like QoW2 or QED) | |
227 | ||
228 | The following command sequences can be used to test VM save / restore. | |
229 | ||
230 | ||
231 | In a 1st terminal start an instance of a swtpm using the following command: | |
232 | ||
233 | mkdir /tmp/mytpm1 | |
234 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
235 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
236 | --log level=20 --tpm2 | |
237 | ||
238 | In a 2nd terminal start the VM: | |
239 | ||
a1d30f28 | 240 | qemu-system-x86_64 -display sdl -accel kvm \ |
9d1f0985 SB |
241 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
242 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
243 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
244 | -device tpm-tis,tpmdev=tpm0 \ | |
245 | -monitor stdio \ | |
246 | test.img | |
247 | ||
248 | Verify that the attached TPM is working as expected using applications inside | |
249 | the VM. | |
250 | ||
251 | To store the state of the VM use the following command in the QEMU monitor in | |
252 | the 2nd terminal: | |
253 | ||
254 | (qemu) migrate "exec:cat > testvm.bin" | |
255 | (qemu) quit | |
256 | ||
257 | At this point a file called 'testvm.bin' should exists and the swtpm and QEMU | |
258 | processes should have ended. | |
259 | ||
260 | To test 'VM restore' you have to start the swtpm with the same parameters | |
261 | as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 must now be | |
262 | passed again on the command line. | |
263 | ||
264 | In the 1st terminal restart the swtpm with the same command line as before: | |
265 | ||
266 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
267 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
268 | --log level=20 --tpm2 | |
269 | ||
9277d81f | 270 | In the 2nd terminal restore the state of the VM using the additional |
9d1f0985 SB |
271 | '-incoming' option. |
272 | ||
a1d30f28 | 273 | qemu-system-x86_64 -display sdl -accel kvm \ |
9d1f0985 SB |
274 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
275 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
276 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
277 | -device tpm-tis,tpmdev=tpm0 \ | |
278 | -incoming "exec:cat < testvm.bin" \ | |
279 | test.img | |
280 | ||
281 | ||
282 | Troubleshooting migration: | |
283 | ||
284 | There are several reasons why migration may fail. In case of problems, | |
285 | please ensure that the command lines adhere to the following rules and, | |
286 | if possible, that identical versions of QEMU and swtpm are used at all | |
287 | times. | |
288 | ||
289 | VM save and restore: | |
290 | - QEMU command line parameters should be identical apart from the | |
291 | '-incoming' option on VM restore | |
292 | - swtpm command line parameters should be identical | |
293 | ||
294 | VM migration to 'localhost': | |
295 | - QEMU command line parameters should be identical apart from the | |
296 | '-incoming' option on the destination side | |
297 | - swtpm command line parameters should point to two different | |
298 | directories on the source and destination swtpm (--tpmstate dir=...) | |
299 | (especially if different versions of libtpms were to be used on the | |
300 | same machine). | |
301 | ||
302 | VM migration across the network: | |
303 | - QEMU command line parameters should be identical apart from the | |
304 | '-incoming' option on the destination side | |
305 | - swtpm command line parameters should be identical | |
306 | ||
307 | VM Snapshotting: | |
308 | - QEMU command line parameters should be identical | |
309 | - swtpm command line parameters should be identical | |
310 | ||
311 | ||
312 | Besides that, migration failure reasons on the swtpm level may include | |
313 | the following: | |
314 | ||
315 | - the versions of the swtpm on the source and destination sides are | |
316 | incompatible | |
317 | - downgrading of TPM state may not be supported | |
318 | - the source and destination libtpms were compiled with different | |
319 | compile-time options and the destination side refuses to accept the | |
320 | state | |
321 | - different migration keys are used on the source and destination side | |
322 | and the destination side cannot decrypt the migrated state | |
323 | (swtpm ... --migration-key ... ) |