Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-9]: src Pull up following revision(s) (requested by riastradh in ...



details:   https://anonhg.NetBSD.org/src/rev/b61360bac972
branches:  netbsd-9
changeset: 368779:b61360bac972
user:      martin <martin%NetBSD.org@localhost>
date:      Wed Aug 03 16:00:47 2022 +0000

description:
Pull up following revision(s) (requested by riastradh in ticket #1495):

        share/man/man4/tpm.4: revision 1.7
        sys/dev/ic/tpm.c: revision 1.17
        sys/dev/ic/tpmvar.h: revision 1.10
        sys/dev/ic/tpm.c: revision 1.18
        sys/dev/ic/tpm.c: revision 1.19
        sys/dev/acpi/tpm_acpi.c: revision 1.14
        sys/dev/ic/tpmreg.h: revision 1.10
        sys/dev/ic/tpmreg.h: revision 1.11
        sys/dev/ic/tpm.c: revision 1.21
        sys/dev/ic/tpm.c: revision 1.22
        sys/dev/ic/tpm.c: revision 1.23
        sys/dev/ic/tpm.c: revision 1.24
        sys/dev/ic/tpm.c: revision 1.25
        sys/dev/ic/tpmreg.h: revision 1.7
        sys/dev/ic/tpmreg.h: revision 1.8
        sys/dev/ic/tpmreg.h: revision 1.9
        sys/dev/ic/tpmvar.h: revision 1.8
        sys/dev/ic/tpmvar.h: revision 1.9

dev/ic/tpm: Tidy up headers.
- Add include guards.
- Add necessary includes.
- Sort includes.
- Use _BYTE_ORDER, not BYTE_ORDER, for public header.

dev/ic/tpm: Add missing line break in attach output.

dev/ic/tpm: Take advantage of entropy source if available.

If the tpm is deactivated, though, detach the entropy source so we
don't continue to try polling it -- it can't be activated without a
reboot anyway.

Add note about enabling TPM and rnd(4) source.

tpm(4): Handle TPM 2.0 random source too, and loop on short reads.
Tested on ThinkPad T480.

tpm(4): Preserve error if any on ending commands.
This way we don't spuriously suppress an error, such as
TPM_DEACTIVATED, in a loop where we rely on it.

tpm@acpi: Require only one locality's worth of register space.
We don't actually use the registers for the other localities, and
some older TPMs only have the first locality exposed via ACPI.


tpm(4): Fix disabling of rnd source if tpm is deactivated.

Nothing prevents a second worker from being queued when the first one
is about to do rnd_detach_source.  Instead, just set a flag so future
requests don't bother running a new thread; if there's a concurrent
one that's already been scheduled on another CPU, well, too bad, we
get a couple extra log messages but that's fine.

A better way to do this would probably be to detect whether the tpm
is deactivated at attach time, but that requires reading more of the
tpm spec than I care to do when there are alternative ways to
procrastinate like scrubbing the toilet.


tpm(4): Fix suspend and rework I/O transaction lock.

Use sc->sc_lock over individual I/O transactions, not open/close of
the whole device.  This way there is a bounded time before the tpm is
unbusied even if userland is getting at it, so userland can't hold up
suspend indefinitely.  Of course, the tpm might be suspended and
resumed in the middle of the user's session this way -- tough.

This limits the response buffer to 1024 bytes -- which is already a
bit hefty to have on the stack (but it's probably not very deep on
the stack from userland so maybe not a big deal).  If it turns out we
need more, we can use kmem to allocate a buffer on the heap, with the
caveat that it might fail.  This is necessary so that suspend doesn't
block indefinitely on uiomove in tpmread.


tpm(4): Nix TPM_BE16/TPM_BE32.  Just use sys/endian.h.

diffstat:

 share/man/man4/tpm.4    |   14 +-
 sys/dev/acpi/tpm_acpi.c |    8 +-
 sys/dev/ic/tpm.c        |  615 ++++++++++++++++++++++++++++++++++++++++++++---
 sys/dev/ic/tpmreg.h     |   77 +++++-
 sys/dev/ic/tpmvar.h     |   21 +-
 5 files changed, 674 insertions(+), 61 deletions(-)

diffs (truncated from 940 to 300 lines):

diff -r 06fb74f1cf88 -r b61360bac972 share/man/man4/tpm.4
--- a/share/man/man4/tpm.4      Wed Aug 03 15:54:23 2022 +0000
+++ b/share/man/man4/tpm.4      Wed Aug 03 16:00:47 2022 +0000
@@ -1,4 +1,4 @@
-.\"    $NetBSD: tpm.4,v 1.4.6.1 2019/10/16 09:52:38 martin Exp $
+.\"    $NetBSD: tpm.4,v 1.4.6.2 2022/08/03 16:00:47 martin Exp $
 .\"
 .\" Copyright (c) 2019 The NetBSD Foundation, Inc.
 .\" All rights reserved.
@@ -51,9 +51,19 @@
 .El
 .Pp
 Note that the supported interface version is TIS1.2 in each case.
+.Pp
+The TPM may need to be enabled in the system's firmware or BIOS, which
+requires a reboot to take effect.
+This is generally beyond the control of
+.Nx .
+Enabling a TPM does not require using trusted boot \(em it can be
+enabled, for example, only for the
+.Xr rnd 4
+entropy source.
 .Sh SEE ALSO
 .Xr config 1 ,
-.Xr intro 4
+.Xr intro 4 ,
+.Xr rnd 4
 .Sh AUTHORS
 .An -nosplit
 The
diff -r 06fb74f1cf88 -r b61360bac972 sys/dev/acpi/tpm_acpi.c
--- a/sys/dev/acpi/tpm_acpi.c   Wed Aug 03 15:54:23 2022 +0000
+++ b/sys/dev/acpi/tpm_acpi.c   Wed Aug 03 16:00:47 2022 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: tpm_acpi.c,v 1.8.2.1 2019/10/16 09:52:38 martin Exp $ */
+/* $NetBSD: tpm_acpi.c,v 1.8.2.2 2022/08/03 16:00:47 martin Exp $ */
 
 /*
  * Copyright (c) 2012, 2019 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8.2.1 2019/10/16 09:52:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm_acpi.c,v 1.8.2.2 2022/08/03 16:00:47 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -113,8 +113,8 @@
                aprint_error_dev(self, "cannot find mem\n");
                goto out;
        }
-       if (mem->ar_length != TPM_SPACE_SIZE) {
-               aprint_error_dev(self, "wrong size mem %"PRIu64" != %u\n",
+       if (mem->ar_length < TPM_SPACE_SIZE) {
+               aprint_error_dev(self, "wrong size mem %"PRIu64" < %u\n",
                    (uint64_t)mem->ar_length, TPM_SPACE_SIZE);
                goto out;
        }
diff -r 06fb74f1cf88 -r b61360bac972 sys/dev/ic/tpm.c
--- a/sys/dev/ic/tpm.c  Wed Aug 03 15:54:23 2022 +0000
+++ b/sys/dev/ic/tpm.c  Wed Aug 03 16:00:47 2022 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: tpm.c,v 1.13.2.1 2019/10/16 09:52:38 martin Exp $      */
+/*     $NetBSD: tpm.c,v 1.13.2.2 2022/08/03 16:00:47 martin Exp $      */
 
 /*
  * Copyright (c) 2019 The NetBSD Foundation, Inc.
@@ -48,17 +48,21 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13.2.1 2019/10/16 09:52:38 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tpm.c,v 1.13.2.2 2022/08/03 16:00:47 martin Exp $");
 
 #include <sys/param.h>
-#include <sys/systm.h>
+#include <sys/types.h>
+
+#include <sys/atomic.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/device.h>
 #include <sys/kernel.h>
 #include <sys/malloc.h>
+#include <sys/pmf.h>
 #include <sys/proc.h>
-#include <sys/device.h>
-#include <sys/conf.h>
-#include <sys/bus.h>
-#include <sys/pmf.h>
+#include <sys/systm.h>
+#include <sys/workqueue.h>
 
 #include <dev/ic/tpmreg.h>
 #include <dev/ic/tpmvar.h>
@@ -137,14 +141,91 @@
                0x00, 0x00, 0x00, 0x98  /* TPM_ORD_SaveState */
        };
        struct tpm_header response;
+       size_t nread;
+       bool endwrite = false, endread = false;
+       int error;
 
-       if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
+       /*
+        * Write the command.
+        */
+       error = (*sc->sc_intf->start)(sc, UIO_WRITE);
+       if (error) {
+               device_printf(sc->sc_dev, "start write failed: %d", error);
+               goto out;
+       }
+
+       endwrite = true;
+
+       error = (*sc->sc_intf->write)(sc, &command, sizeof(command));
+       if (error) {
+               device_printf(sc->sc_dev, "write TPM_ORD_SaveState failed: %d",
+                   error);
+               goto out;
+       }
+
+       endwrite = false;
+
+       error = (*sc->sc_intf->end)(sc, UIO_WRITE, 0);
+       if (error) {
+               device_printf(sc->sc_dev, "end write failed: %d", error);
+               goto out;
+       }
+
+       /*
+        * Read the response -- just the header; we don't expect a
+        * payload.
+        */
+       error = (*sc->sc_intf->start)(sc, UIO_READ);
+       if (error) {
+               device_printf(sc->sc_dev, "start read failed: %d", error);
+               goto out;
+       }
+
+       endread = true;
+
+       error = (*sc->sc_intf->read)(sc, &response, sizeof(response), &nread,
+           0);
+       if (error) {
+               device_printf(sc->sc_dev, "read failed: %d", error);
+               goto out;
+       }
+       if (nread != sizeof(response)) {
+               device_printf(sc->sc_dev, "short header read: %zu", nread);
+               goto out;
+       }
+
+       endread = false;
+
+       error = (*sc->sc_intf->end)(sc, UIO_READ, 0);
+       if (error) {
+               device_printf(sc->sc_dev, "end read failed: %d", error);
+               goto out;
+       }
+
+       /*
+        * Verify the response looks reasonable.
+        */
+       if (be16toh(response.tag) != TPM_TAG_RSP_COMMAND ||
+           be32toh(response.length) != sizeof(response) ||
+           be32toh(response.code) != 0) {
+               device_printf(sc->sc_dev,
+                   "TPM_ORD_SaveState failed: tag=0x%x length=0x%x code=0x%x",
+                   be16toh(response.tag),
+                   be32toh(response.length),
+                   be32toh(response.code));
+               error = EIO;
+               goto out;
+       }
+
+       /* Success!  */
+       error = 0;
+
+out:   if (endwrite)
+               error = (*sc->sc_intf->end)(sc, UIO_WRITE, error);
+       if (endread)
+               error = (*sc->sc_intf->end)(sc, UIO_READ, error);
+       if (error)
                return false;
-       if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
-               return false;
-       if (TPM_BE32(response.code) != 0)
-               return false;
-
        return true;
 }
 
@@ -158,14 +239,91 @@
                0x00, 0x01              /* TPM_SU_STATE */
        };
        struct tpm_header response;
+       size_t nread;
+       bool endwrite = false, endread = false;
+       int error;
 
-       if ((*sc->sc_intf->write)(sc, &command, sizeof(command)) != 0)
+       /*
+        * Write the command.
+        */
+       error = (*sc->sc_intf->start)(sc, UIO_WRITE);
+       if (error) {
+               device_printf(sc->sc_dev, "start write failed: %d", error);
+               goto out;
+       }
+
+       endwrite = true;
+
+       error = (*sc->sc_intf->write)(sc, &command, sizeof(command));
+       if (error) {
+               device_printf(sc->sc_dev, "write TPM_ORD_SaveState failed: %d",
+                   error);
+               goto out;
+       }
+
+       endwrite = false;
+
+       error = (*sc->sc_intf->end)(sc, UIO_WRITE, 0);
+       if (error) {
+               device_printf(sc->sc_dev, "end write failed: %d", error);
+               goto out;
+       }
+
+       /*
+        * Read the response -- just the header; we don't expect a
+        * payload.
+        */
+       error = (*sc->sc_intf->start)(sc, UIO_READ);
+       if (error) {
+               device_printf(sc->sc_dev, "start read failed: %d", error);
+               goto out;
+       }
+
+       endread = true;
+
+       error = (*sc->sc_intf->read)(sc, &response, sizeof(response), &nread,
+           0);
+       if (error) {
+               device_printf(sc->sc_dev, "read failed: %d", error);
+               goto out;
+       }
+       if (nread != sizeof(response)) {
+               device_printf(sc->sc_dev, "short header read: %zu", nread);
+               goto out;
+       }
+
+       endread = false;
+
+       error = (*sc->sc_intf->end)(sc, UIO_READ, 0);
+       if (error) {
+               device_printf(sc->sc_dev, "end read failed: %d", error);
+               goto out;
+       }
+
+       /*
+        * Verify the response looks reasonable.
+        */
+       if (be16toh(response.tag) != TPM2_ST_NO_SESSIONS ||
+           be32toh(response.length) != sizeof(response) ||
+           be32toh(response.code) != TPM2_RC_SUCCESS) {
+               device_printf(sc->sc_dev,
+                   "TPM_CC_Shutdown failed: tag=0x%x length=0x%x code=0x%x",
+                   be16toh(response.tag),
+                   be32toh(response.length),
+                   be32toh(response.code));
+               error = EIO;
+               goto out;
+       }
+
+       /* Success!  */
+       error = 0;
+
+out:   if (endwrite)
+               error = (*sc->sc_intf->end)(sc, UIO_WRITE, error);
+       if (endread)
+               error = (*sc->sc_intf->end)(sc, UIO_READ, error);
+       if (error)
                return false;
-       if ((*sc->sc_intf->read)(sc, &response, sizeof(response), NULL, 0) != 0)
-               return false;
-       if (TPM_BE32(response.code) != 0)
-               return false;
-
        return true;
 }
 
@@ -324,10 +482,348 @@
 }
 
 static int
+tpm12_rng(struct tpm_softc *sc, unsigned *entropybitsp)
+{
+       /*
+        * TPM Specification Version 1.2, Main Part 3: Commands,



Home | Main Index | Thread Index | Old Index