]>
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 | ||
0fe24669 SB |
37 | = fw_cfg interface = |
38 | ||
39 | The bios/firmware may read the "etc/tpm/config" fw_cfg entry for | |
40 | configuring the guest appropriately. | |
41 | ||
42 | The entry of 6 bytes has the following content, in little-endian: | |
43 | ||
44 | #define TPM_VERSION_UNSPEC 0 | |
45 | #define TPM_VERSION_1_2 1 | |
46 | #define TPM_VERSION_2_0 2 | |
47 | ||
48 | #define TPM_PPI_VERSION_NONE 0 | |
49 | #define TPM_PPI_VERSION_1_30 1 | |
50 | ||
51 | struct FwCfgTPMConfig { | |
52 | uint32_t tpmppi_address; /* PPI memory location */ | |
53 | uint8_t tpm_version; /* TPM version */ | |
54 | uint8_t tpmppi_version; /* PPI version */ | |
55 | }; | |
7931cf31 | 56 | |
8dc67017 SB |
57 | = ACPI Interface = |
58 | ||
59 | The TPM device is defined with ACPI ID "PNP0C31". QEMU builds a SSDT and passes | |
60 | it into the guest through the fw_cfg device. The device description contains | |
61 | the base address of the TIS interface 0xfed40000 and the size of the MMIO area | |
62 | (0x5000). In case a TPM2 is used by QEMU, a TPM2 ACPI table is also provided. | |
63 | The device is described to be used in polling mode rather than interrupt mode | |
64 | primarily because no unused IRQ could be found. | |
65 | ||
66 | To support measurement logs to be written by the firmware, e.g. SeaBIOS, a TCPA | |
67 | table is implemented. This table provides a 64kb buffer where the firmware can | |
68 | write its log into. For TPM 2 only a more recent version of the TPM2 table | |
69 | provides support for measurements logs and a TCPA table does not need to be | |
70 | created. | |
71 | ||
72 | The TCPA and TPM2 ACPI tables follow the Trusted Computing Group specification | |
73 | "TCG ACPI Specification" Family "1.2" and "2.0", Level 00 Revision 00.37. This | |
74 | specification, or a later version of it, can be accessed from the following | |
75 | URL: | |
76 | ||
77 | https://trustedcomputinggroup.org/tcg-acpi-specification/ | |
78 | ||
ac6dd31e SB |
79 | == ACPI PPI Interface == |
80 | ||
81 | QEMU supports the Physical Presence Interface (PPI) for TPM 1.2 and TPM 2. This | |
82 | interface requires ACPI and firmware support. The specification can be found at | |
83 | the following URL: | |
84 | ||
85 | https://trustedcomputinggroup.org/resource/tcg-physical-presence-interface-specification/ | |
86 | ||
87 | PPI enables a system administrator (root) to request a modification to the | |
88 | TPM upon reboot. The PPI specification defines the operation requests and the | |
89 | actions the firmware has to take. The system administrator passes the operation | |
90 | request number to the firmware through an ACPI interface which writes this | |
91 | number to a memory location that the firmware knows. Upon reboot, the firmware | |
92 | finds the number and sends commands to the the TPM. The firmware writes the TPM | |
93 | result code and the operation request number to a memory location that ACPI can | |
94 | read from and pass the result on to the administrator. | |
95 | ||
96 | The PPI specification defines a set of mandatory and optional operations for | |
97 | the firmware to implement. The ACPI interface also allows an administrator to | |
98 | list the supported operations. In QEMU the ACPI code is generated by QEMU, yet | |
99 | the firmware needs to implement support on a per-operations basis, and | |
100 | different firmwares may support a different subset. Therefore, QEMU introduces | |
101 | the virtual memory device for PPI where the firmware can indicate which | |
102 | operations it supports and ACPI can enable the ones that are supported and | |
103 | disable all others. This interface lies in main memory and has the following | |
104 | layout: | |
105 | ||
106 | +----------+--------+--------+-------------------------------------------+ | |
107 | | Field | Length | Offset | Description | | |
108 | +----------+--------+--------+-------------------------------------------+ | |
109 | | func | 0x100 | 0x000 | Firmware sets values for each supported | | |
110 | | | | | operation. See defined values below. | | |
111 | +----------+--------+--------+-------------------------------------------+ | |
112 | | ppin | 0x1 | 0x100 | SMI interrupt to use. Set by firmware. | | |
113 | | | | | Not supported. | | |
114 | +----------+--------+--------+-------------------------------------------+ | |
115 | | ppip | 0x4 | 0x101 | ACPI function index to pass to SMM code. | | |
116 | | | | | Set by ACPI. Not supported. | | |
117 | +----------+--------+--------+-------------------------------------------+ | |
118 | | pprp | 0x4 | 0x105 | Result of last executed operation. Set by | | |
119 | | | | | firmware. See function index 5 for values.| | |
120 | +----------+--------+--------+-------------------------------------------+ | |
121 | | pprq | 0x4 | 0x109 | Operation request number to execute. See | | |
122 | | | | | 'Physical Presence Interface Operation | | |
123 | | | | | Summary' tables in specs. Set by ACPI. | | |
124 | +----------+--------+--------+-------------------------------------------+ | |
125 | | pprm | 0x4 | 0x10d | Operation request optional parameter. | | |
126 | | | | | Values depend on operation. Set by ACPI. | | |
127 | +----------+--------+--------+-------------------------------------------+ | |
128 | | lppr | 0x4 | 0x111 | Last executed operation request number. | | |
129 | | | | | Copied from pprq field by firmware. | | |
130 | +----------+--------+--------+-------------------------------------------+ | |
131 | | fret | 0x4 | 0x115 | Result code from SMM function. | | |
132 | | | | | Not supported. | | |
133 | +----------+--------+--------+-------------------------------------------+ | |
134 | | res1 | 0x40 | 0x119 | Reserved for future use | | |
135 | +----------+--------+--------+-------------------------------------------+ | |
136 | | next_step| 0x1 | 0x159 | Operation to execute after reboot by | | |
137 | | | | | firmware. Used by firmware. | | |
ec86c0f6 MAL |
138 | +----------+--------+--------+-------------------------------------------+ |
139 | | movv | 0x1 | 0x15a | Memory overwrite variable | | |
ac6dd31e SB |
140 | +----------+--------+--------+-------------------------------------------+ |
141 | ||
142 | The following values are supported for the 'func' field. They correspond | |
143 | to the values used by ACPI function index 8. | |
144 | ||
145 | +----------+-------------------------------------------------------------+ | |
146 | | value | Description | | |
147 | +----------+-------------------------------------------------------------+ | |
148 | | 0 | Operation is not implemented. | | |
149 | +----------+-------------------------------------------------------------+ | |
150 | | 1 | Operation is only accessible through firmware. | | |
151 | +----------+-------------------------------------------------------------+ | |
152 | | 2 | Operation is blocked for OS by firmware configuration. | | |
153 | +----------+-------------------------------------------------------------+ | |
154 | | 3 | Operation is allowed and physically present user required. | | |
155 | +----------+-------------------------------------------------------------+ | |
156 | | 4 | Operation is allowed and physically present user is not | | |
157 | | | required. | | |
158 | +----------+-------------------------------------------------------------+ | |
159 | ||
160 | The location of the table is given by the fw_cfg tpmppi_address field. | |
161 | The PPI memory region size is 0x400 (TPM_PPI_ADDR_SIZE) to leave | |
162 | enough room for future updates. | |
163 | ||
8dc67017 SB |
164 | |
165 | QEMU files related to TPM ACPI tables: | |
166 | - hw/i386/acpi-build.c | |
167 | - include/hw/acpi/tpm.h | |
168 | ||
169 | ||
170 | = TPM backend devices = | |
171 | ||
172 | The TPM implementation is split into two parts, frontend and backend. The | |
173 | frontend part is the hardware interface, such as the TPM TIS interface | |
174 | described earlier, and the other part is the TPM backend interface. The backend | |
175 | interfaces implement the interaction with a TPM device, which may be a physical | |
176 | or an emulated device. The split between the front- and backend devices allows | |
177 | a frontend to be connected with any available backend. This enables the TIS | |
178 | interface to be used with the passthrough backend or the (future) swtpm backend. | |
179 | ||
180 | ||
181 | QEMU files related to TPM backends: | |
182 | - backends/tpm.c | |
183 | - include/sysemu/tpm_backend.h | |
184 | - include/sysemu/tpm_backend_int.h | |
185 | ||
186 | ||
187 | == The QEMU TPM passthrough device == | |
188 | ||
189 | In case QEMU is run on Linux as the host operating system it is possible to | |
190 | make the hardware TPM device available to a single QEMU guest. In this case the | |
191 | user must make sure that no other program is using the device, e.g., /dev/tpm0, | |
192 | before trying to start QEMU with it. | |
193 | ||
194 | The passthrough driver uses the host's TPM device for sending TPM commands | |
195 | and receiving responses from. Besides that it accesses the TPM device's sysfs | |
196 | entry for support of command cancellation. Since none of the state of a | |
197 | hardware TPM can be migrated between hosts, virtual machine migration is | |
198 | disabled when the TPM passthrough driver is used. | |
199 | ||
200 | Since the host's TPM device will already be initialized by the host's firmware, | |
201 | certain commands, e.g. TPM_Startup(), sent by the virtual firmware for device | |
202 | initialization, will fail. In this case the firmware should not use the TPM. | |
203 | ||
204 | Sharing the device with the host is generally not a recommended usage scenario | |
205 | for a TPM device. The primary reason for this is that two operating systems can | |
206 | then access the device's single set of resources, such as platform configuration | |
207 | registers (PCRs). Applications or kernel security subsystems, such as the | |
208 | Linux Integrity Measurement Architecture (IMA), are not expecting to share PCRs. | |
209 | ||
210 | ||
211 | QEMU files related to the TPM passthrough device: | |
212 | - hw/tpm/tpm_passthrough.c | |
213 | - hw/tpm/tpm_util.c | |
214 | - hw/tpm/tpm_util.h | |
215 | ||
216 | ||
217 | Command line to start QEMU with the TPM passthrough device using the host's | |
218 | hardware TPM /dev/tpm0: | |
219 | ||
a1d30f28 | 220 | qemu-system-x86_64 -display sdl -accel kvm \ |
8dc67017 SB |
221 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
222 | -tpmdev passthrough,id=tpm0,path=/dev/tpm0 \ | |
223 | -device tpm-tis,tpmdev=tpm0 test.img | |
224 | ||
225 | The following commands should result in similar output inside the VM with a | |
226 | Linux kernel that either has the TPM TIS driver built-in or available as a | |
227 | module: | |
228 | ||
229 | #> dmesg | grep -i tpm | |
230 | [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) | |
231 | ||
232 | #> dmesg | grep TCPA | |
233 | [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ | |
234 | BXPCTCPA 0000001 BXPC 00000001) | |
235 | ||
236 | #> ls -l /dev/tpm* | |
237 | crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 | |
238 | ||
239 | #> find /sys/devices/ | grep pcrs$ | xargs cat | |
240 | PCR-00: 35 4E 3B CE 23 9F 38 59 ... | |
241 | ... | |
242 | PCR-23: 00 00 00 00 00 00 00 00 ... | |
83e83c34 SB |
243 | |
244 | ||
245 | == The QEMU TPM emulator device == | |
246 | ||
247 | The TPM emulator device uses an external TPM emulator called 'swtpm' for | |
248 | sending TPM commands to and receiving responses from. The swtpm program | |
249 | must have been started before trying to access it through the TPM emulator | |
250 | with QEMU. | |
251 | ||
252 | The TPM emulator implements a command channel for transferring TPM commands | |
253 | and responses as well as a control channel over which control commands can | |
254 | be sent. The specification for the control channel can be found here: | |
255 | ||
256 | https://github.com/stefanberger/swtpm/blob/master/man/man3/swtpm_ioctls.pod | |
257 | ||
258 | ||
259 | The control channel serves the purpose of resetting, initializing, and | |
260 | migrating the TPM state, among other things. | |
261 | ||
262 | The swtpm program behaves like a hardware TPM and therefore needs to be | |
263 | initialized by the firmware running inside the QEMU virtual machine. | |
264 | One necessary step for initializing the device is to send the TPM_Startup | |
265 | command to it. SeaBIOS, for example, has been instrumented to initialize | |
266 | a TPM 1.2 or TPM 2 device using this command. | |
267 | ||
268 | ||
269 | QEMU files related to the TPM emulator device: | |
270 | - hw/tpm/tpm_emulator.c | |
271 | - hw/tpm/tpm_util.c | |
272 | - hw/tpm/tpm_util.h | |
273 | ||
274 | ||
275 | The following commands start the swtpm with a UnixIO control channel over | |
276 | a socket interface. They do not need to be run as root. | |
277 | ||
278 | mkdir /tmp/mytpm1 | |
279 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
280 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
281 | --log level=20 | |
282 | ||
283 | Command line to start QEMU with the TPM emulator device communicating with | |
284 | the swtpm: | |
285 | ||
a1d30f28 | 286 | qemu-system-x86_64 -display sdl -accel kvm \ |
83e83c34 SB |
287 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
288 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
289 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
290 | -device tpm-tis,tpmdev=tpm0 test.img | |
291 | ||
292 | ||
293 | In case SeaBIOS is used as firmware, it should show the TPM menu item | |
294 | after entering the menu with 'ESC'. | |
295 | ||
296 | Select boot device: | |
297 | 1. DVD/CD [ata1-0: QEMU DVD-ROM ATAPI-4 DVD/CD] | |
298 | [...] | |
299 | 5. Legacy option rom | |
300 | ||
301 | t. TPM Configuration | |
302 | ||
303 | ||
304 | The following commands should result in similar output inside the VM with a | |
305 | Linux kernel that either has the TPM TIS driver built-in or available as a | |
306 | module: | |
307 | ||
308 | #> dmesg | grep -i tpm | |
309 | [ 0.711310] tpm_tis 00:06: 1.2 TPM (device=id 0x1, rev-id 1) | |
310 | ||
311 | #> dmesg | grep TCPA | |
312 | [ 0.000000] ACPI: TCPA 0x0000000003FFD191C 000032 (v02 BOCHS \ | |
313 | BXPCTCPA 0000001 BXPC 00000001) | |
314 | ||
315 | #> ls -l /dev/tpm* | |
316 | crw-------. 1 root root 10, 224 Jul 11 10:11 /dev/tpm0 | |
317 | ||
318 | #> find /sys/devices/ | grep pcrs$ | xargs cat | |
319 | PCR-00: 35 4E 3B CE 23 9F 38 59 ... | |
320 | ... | |
321 | PCR-23: 00 00 00 00 00 00 00 00 ... | |
9d1f0985 SB |
322 | |
323 | ||
324 | === Migration with the TPM emulator === | |
325 | ||
326 | The TPM emulator supports the following types of virtual machine migration: | |
327 | ||
328 | - VM save / restore (migration into a file) | |
329 | - Network migration | |
330 | - Snapshotting (migration into storage like QoW2 or QED) | |
331 | ||
332 | The following command sequences can be used to test VM save / restore. | |
333 | ||
334 | ||
335 | In a 1st terminal start an instance of a swtpm using the following command: | |
336 | ||
337 | mkdir /tmp/mytpm1 | |
338 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
339 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
340 | --log level=20 --tpm2 | |
341 | ||
342 | In a 2nd terminal start the VM: | |
343 | ||
a1d30f28 | 344 | qemu-system-x86_64 -display sdl -accel kvm \ |
9d1f0985 SB |
345 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
346 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
347 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
348 | -device tpm-tis,tpmdev=tpm0 \ | |
349 | -monitor stdio \ | |
350 | test.img | |
351 | ||
352 | Verify that the attached TPM is working as expected using applications inside | |
353 | the VM. | |
354 | ||
355 | To store the state of the VM use the following command in the QEMU monitor in | |
356 | the 2nd terminal: | |
357 | ||
358 | (qemu) migrate "exec:cat > testvm.bin" | |
359 | (qemu) quit | |
360 | ||
361 | At this point a file called 'testvm.bin' should exists and the swtpm and QEMU | |
362 | processes should have ended. | |
363 | ||
364 | To test 'VM restore' you have to start the swtpm with the same parameters | |
365 | as before. If previously a TPM 2 [--tpm2] was saved, --tpm2 must now be | |
366 | passed again on the command line. | |
367 | ||
368 | In the 1st terminal restart the swtpm with the same command line as before: | |
369 | ||
370 | swtpm socket --tpmstate dir=/tmp/mytpm1 \ | |
371 | --ctrl type=unixio,path=/tmp/mytpm1/swtpm-sock \ | |
372 | --log level=20 --tpm2 | |
373 | ||
9277d81f | 374 | In the 2nd terminal restore the state of the VM using the additional |
9d1f0985 SB |
375 | '-incoming' option. |
376 | ||
a1d30f28 | 377 | qemu-system-x86_64 -display sdl -accel kvm \ |
9d1f0985 SB |
378 | -m 1024 -boot d -bios bios-256k.bin -boot menu=on \ |
379 | -chardev socket,id=chrtpm,path=/tmp/mytpm1/swtpm-sock \ | |
380 | -tpmdev emulator,id=tpm0,chardev=chrtpm \ | |
381 | -device tpm-tis,tpmdev=tpm0 \ | |
382 | -incoming "exec:cat < testvm.bin" \ | |
383 | test.img | |
384 | ||
385 | ||
386 | Troubleshooting migration: | |
387 | ||
388 | There are several reasons why migration may fail. In case of problems, | |
389 | please ensure that the command lines adhere to the following rules and, | |
390 | if possible, that identical versions of QEMU and swtpm are used at all | |
391 | times. | |
392 | ||
393 | VM save and restore: | |
394 | - QEMU command line parameters should be identical apart from the | |
395 | '-incoming' option on VM restore | |
396 | - swtpm command line parameters should be identical | |
397 | ||
398 | VM migration to 'localhost': | |
399 | - QEMU command line parameters should be identical apart from the | |
400 | '-incoming' option on the destination side | |
401 | - swtpm command line parameters should point to two different | |
402 | directories on the source and destination swtpm (--tpmstate dir=...) | |
403 | (especially if different versions of libtpms were to be used on the | |
404 | same machine). | |
405 | ||
406 | VM migration across the network: | |
407 | - QEMU command line parameters should be identical apart from the | |
408 | '-incoming' option on the destination side | |
409 | - swtpm command line parameters should be identical | |
410 | ||
411 | VM Snapshotting: | |
412 | - QEMU command line parameters should be identical | |
413 | - swtpm command line parameters should be identical | |
414 | ||
415 | ||
416 | Besides that, migration failure reasons on the swtpm level may include | |
417 | the following: | |
418 | ||
419 | - the versions of the swtpm on the source and destination sides are | |
420 | incompatible | |
421 | - downgrading of TPM state may not be supported | |
422 | - the source and destination libtpms were compiled with different | |
423 | compile-time options and the destination side refuses to accept the | |
424 | state | |
425 | - different migration keys are used on the source and destination side | |
426 | and the destination side cannot decrypt the migrated state | |
427 | (swtpm ... --migration-key ... ) |