svn commit: r346725 - in stable/11/sys: conf dev/random dev/tpm sys
Marcin Wojtas
mw at FreeBSD.org
Fri Apr 26 01:58:39 UTC 2019
Author: mw
Date: Fri Apr 26 01:58:36 2019
New Revision: 346725
URL: https://svnweb.freebsd.org/changeset/base/346725
Log:
MFC r345438,r345842,r346259,r346261: TPM as possible entropy source
r345438:
Allow using TPM as entropy source
TPM has a built-in RNG, with its own entropy source.
The driver was extended to harvest 16 random bytes from TPM every 10 seconds.
A new build option "TPM_HARVEST" was introduced - for now, however, it
is not enabled by default in the GENERIC config.
Reviewed by: markm, delphij
Approved by: secteam
r345842:
Add a cv_wait to the TPM2.0 harvesting function
r346259:
tpm: Prevent session hijack
r346261:
Improve tpm20 style
Submitted by: Kornel Duleba <mindal at semihalf.com>
Obtained from: Semihalf
Sponsored by: Stormshield
Modified:
stable/11/sys/conf/options
stable/11/sys/dev/random/random_harvestq.c
stable/11/sys/dev/tpm/tpm20.c
stable/11/sys/dev/tpm/tpm20.h
stable/11/sys/dev/tpm/tpm_crb.c
stable/11/sys/dev/tpm/tpm_tis.c
stable/11/sys/sys/random.h
Modified: stable/11/sys/conf/options
==============================================================================
--- stable/11/sys/conf/options Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/conf/options Fri Apr 26 01:58:36 2019 (r346725)
@@ -986,6 +986,9 @@ RANDOM_ENABLE_UMA opt_global.h
# Intel em(4) driver
EM_MULTIQUEUE opt_em.h
+# This options turns TPM into entropy source.
+TPM_HARVEST opt_tpm.h
+
# BHND(4) driver
BHND_LOGLEVEL opt_global.h
Modified: stable/11/sys/dev/random/random_harvestq.c
==============================================================================
--- stable/11/sys/dev/random/random_harvestq.c Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/dev/random/random_harvestq.c Fri Apr 26 01:58:36 2019 (r346725)
@@ -288,6 +288,7 @@ static const char *(random_source_descr[]) = {
"PURE_RDRAND",
"PURE_NEHEMIAH",
"PURE_RNDTEST",
+ [RANDOM_PURE_TPM] = "PURE_TPM",
/* "ENTROPYSOURCE" */
};
Modified: stable/11/sys/dev/tpm/tpm20.c
==============================================================================
--- stable/11/sys/dev/tpm/tpm20.c Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/dev/tpm/tpm20.c Fri Apr 26 01:58:36 2019 (r346725)
@@ -28,13 +28,27 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/random.h>
+
#include "tpm20.h"
+#define TPM_HARVEST_SIZE 16
+/*
+ * Perform a harvest every 10 seconds.
+ * Since discrete TPMs are painfully slow
+ * we don't want to execute this too often
+ * as the chip is likely to be used by others too.
+ */
+#define TPM_HARVEST_INTERVAL 10000000
+
MALLOC_DECLARE(M_TPM20);
MALLOC_DEFINE(M_TPM20, "tpm_buffer", "buffer for tpm 2.0 driver");
static void tpm20_discard_buffer(void *arg);
-static int tpm20_save_state(device_t dev, bool suspend);
+#ifdef TPM_HARVEST
+static void tpm20_harvest(void *arg);
+#endif
+static int tpm20_save_state(device_t dev, bool suspend);
static d_open_t tpm20_open;
static d_close_t tpm20_close;
@@ -63,6 +77,10 @@ tpm20_read(struct cdev *dev, struct uio *uio, int flag
callout_stop(&sc->discard_buffer_callout);
sx_xlock(&sc->dev_lock);
+ if (sc->owner_tid != uio->uio_td->td_tid) {
+ sx_xunlock(&sc->dev_lock);
+ return (EPERM);
+ }
bytes_to_transfer = MIN(sc->pending_data_length, uio->uio_resid);
if (bytes_to_transfer > 0) {
@@ -114,15 +132,18 @@ tpm20_write(struct cdev *dev, struct uio *uio, int fla
result = sc->transmit(sc, byte_count);
- if (result == 0)
+ if (result == 0) {
callout_reset(&sc->discard_buffer_callout,
TPM_READ_TIMEOUT / tick, tpm20_discard_buffer, sc);
+ sc->owner_tid = uio->uio_td->td_tid;
+ }
sx_xunlock(&sc->dev_lock);
return (result);
}
-static void tpm20_discard_buffer(void *arg)
+static void
+tpm20_discard_buffer(void *arg)
{
struct tpm_sc *sc;
@@ -175,6 +196,11 @@ tpm20_init(struct tpm_sc *sc)
sx_init(&sc->dev_lock, "TPM driver lock");
cv_init(&sc->buf_cv, "TPM buffer cv");
callout_init(&sc->discard_buffer_callout, 1);
+#ifdef TPM_HARVEST
+ sc->harvest_ticks = TPM_HARVEST_INTERVAL / tick;
+ callout_init(&sc->harvest_callout, 1);
+ callout_reset(&sc->harvest_callout, 0, tpm20_harvest, sc);
+#endif
sc->pending_data_length = 0;
make_dev_args_init(&args);
@@ -195,6 +221,10 @@ void
tpm20_release(struct tpm_sc *sc)
{
+#ifdef TPM_HARVEST
+ callout_drain(&sc->harvest_callout);
+#endif
+
if (sc->buf != NULL)
free(sc->buf, M_TPM20);
@@ -217,14 +247,69 @@ tpm20_shutdown(device_t dev)
return (tpm20_save_state(dev, false));
}
+#ifdef TPM_HARVEST
+
+/*
+ * Get TPM_HARVEST_SIZE random bytes and add them
+ * into system entropy pool.
+ */
+static void
+tpm20_harvest(void *arg)
+{
+ struct tpm_sc *sc;
+ unsigned char entropy[TPM_HARVEST_SIZE];
+ uint16_t entropy_size;
+ int result;
+ uint8_t cmd[] = {
+ 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/
+ 0x00, 0x00, 0x00, 0x0c, /* cmd length */
+ 0x00, 0x00, 0x01, 0x7b, /* cmd TPM_CC_GetRandom */
+ 0x00, TPM_HARVEST_SIZE /* number of bytes requested */
+ };
+
+
+ sc = arg;
+ sx_xlock(&sc->dev_lock);
+ while (sc->pending_data_length != 0)
+ cv_wait(&sc->buf_cv, &sc->dev_lock);
+
+ memcpy(sc->buf, cmd, sizeof(cmd));
+ result = sc->transmit(sc, sizeof(cmd));
+ if (result != 0) {
+ sx_xunlock(&sc->dev_lock);
+ return;
+ }
+
+ /* Ignore response size */
+ sc->pending_data_length = 0;
+
+ /* The number of random bytes we got is placed right after the header */
+ entropy_size = (uint16_t) sc->buf[TPM_HEADER_SIZE + 1];
+ if (entropy_size > 0) {
+ entropy_size = MIN(entropy_size, TPM_HARVEST_SIZE);
+ memcpy(entropy,
+ sc->buf + TPM_HEADER_SIZE + sizeof(uint16_t),
+ entropy_size);
+ }
+
+ sx_xunlock(&sc->dev_lock);
+ if (entropy_size > 0)
+ random_harvest_queue(entropy, entropy_size,
+ entropy_size * NBBY / 2, RANDOM_PURE_TPM);
+
+ callout_reset(&sc->harvest_callout, sc->harvest_ticks, tpm20_harvest, sc);
+}
+#endif /* TPM_HARVEST */
+
static int
tpm20_save_state(device_t dev, bool suspend)
{
struct tpm_sc *sc;
uint8_t save_cmd[] = {
- 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/
+ 0x80, 0x01, /* TPM_ST_NO_SESSIONS tag*/
0x00, 0x00, 0x00, 0x0C, /* cmd length */
- 0x00, 0x00, 0x01, 0x45, 0x00, 0x00 /* cmd TPM_CC_Shutdown */
+ 0x00, 0x00, 0x01, 0x45, /* cmd TPM_CC_Shutdown */
+ 0x00, 0x00 /* TPM_SU_STATE */
};
sc = device_get_softc(dev);
@@ -233,7 +318,7 @@ tpm20_save_state(device_t dev, bool suspend)
* Inform the TPM whether we are going to suspend or reboot/shutdown.
*/
if (suspend)
- save_cmd[11] = 1; /* TPM_SU_STATE */
+ save_cmd[11] = 1; /* TPM_SU_STATE */
if (sc == NULL || sc->buf == NULL)
return (0);
Modified: stable/11/sys/dev/tpm/tpm20.h
==============================================================================
--- stable/11/sys/dev/tpm/tpm20.h Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/dev/tpm/tpm20.h Fri Apr 26 01:58:36 2019 (r346725)
@@ -26,7 +26,7 @@
*/
#ifndef _TPM20_H_
-#define _TPM20_H_
+#define _TPM20_H_
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@@ -55,49 +55,51 @@ __FBSDID("$FreeBSD$");
#include <dev/acpica/acpivar.h>
#include "opt_acpi.h"
+#include "opt_tpm.h"
+
#define BIT(x) (1 << (x))
/* Timeouts in us */
-#define TPM_TIMEOUT_A 750000
-#define TPM_TIMEOUT_B 2000000
-#define TPM_TIMEOUT_C 200000
-#define TPM_TIMEOUT_D 30000
+#define TPM_TIMEOUT_A 750000
+#define TPM_TIMEOUT_B 2000000
+#define TPM_TIMEOUT_C 200000
+#define TPM_TIMEOUT_D 30000
/*
* Generating RSA key pair takes ~(10-20s), which is significantly longer than
* any timeout defined in spec. Because of that we need a new one.
*/
-#define TPM_TIMEOUT_LONG 40000000
+#define TPM_TIMEOUT_LONG 40000000
/* List of commands that require TPM_TIMEOUT_LONG time to complete */
-#define TPM_CC_CreatePrimary 0x00000131
+#define TPM_CC_CreatePrimary 0x00000131
#define TPM_CC_Create 0x00000153
#define TPM_CC_CreateLoaded 0x00000191
/* List of commands that require only TPM_TIMEOUT_C time to complete */
-#define TPM_CC_SequenceComplete 0x0000013e
-#define TPM_CC_Startup 0x00000144
-#define TPM_CC_SequenceUpdate 0x0000015c
-#define TPM_CC_GetCapability 0x0000017a
-#define TPM_CC_PCR_Extend 0x00000182
-#define TPM_CC_EventSequenceComplete 0x00000185
-#define TPM_CC_HashSequenceStart 0x00000186
+#define TPM_CC_SequenceComplete 0x0000013e
+#define TPM_CC_Startup 0x00000144
+#define TPM_CC_SequenceUpdate 0x0000015c
+#define TPM_CC_GetCapability 0x0000017a
+#define TPM_CC_PCR_Extend 0x00000182
+#define TPM_CC_EventSequenceComplete 0x00000185
+#define TPM_CC_HashSequenceStart 0x00000186
/* Timeout before data in read buffer is discarded */
-#define TPM_READ_TIMEOUT 500000
+#define TPM_READ_TIMEOUT 500000
-#define TPM_BUFSIZE 0x1000
+#define TPM_BUFSIZE 0x1000
-#define TPM_HEADER_SIZE 10
+#define TPM_HEADER_SIZE 10
-#define TPM_CDEV_NAME "tpm0"
-#define TPM_CDEV_PERM_FLAG 0600
+#define TPM_CDEV_NAME "tpm0"
+#define TPM_CDEV_PERM_FLAG 0600
-#define TPM2_START_METHOD_ACPI 2
-#define TPM2_START_METHOD_TIS 6
-#define TPM2_START_METHOD_CRB 7
-#define TPM2_START_METHOD_CRB_ACPI 8
+#define TPM2_START_METHOD_ACPI 2
+#define TPM2_START_METHOD_TIS 6
+#define TPM2_START_METHOD_CRB 7
+#define TPM2_START_METHOD_CRB_ACPI 8
struct tpm_sc {
device_t dev;
@@ -118,8 +120,13 @@ struct tpm_sc {
uint8_t *buf;
size_t pending_data_length;
+ lwpid_t owner_tid;
struct callout discard_buffer_callout;
+#ifdef TPM_HARVEST
+ struct callout harvest_callout;
+ int harvest_ticks;
+#endif
int (*transmit)(struct tpm_sc *, size_t);
};
Modified: stable/11/sys/dev/tpm/tpm_crb.c
==============================================================================
--- stable/11/sys/dev/tpm/tpm_crb.c Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/dev/tpm/tpm_crb.c Fri Apr 26 01:58:36 2019 (r346725)
@@ -34,47 +34,47 @@ __FBSDID("$FreeBSD$");
* CRB register space as defined in
* TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22
*/
-#define TPM_LOC_STATE 0x0
-#define TPM_LOC_CTRL 0x8
-#define TPM_LOC_STS 0xC
-#define TPM_CRB_INTF_ID 0x30
-#define TPM_CRB_CTRL_EXT 0x38
-#define TPM_CRB_CTRL_REQ 0x40
-#define TPM_CRB_CTRL_STS 0x44
-#define TPM_CRB_CTRL_CANCEL 0x48
-#define TPM_CRB_CTRL_START 0x4C
-#define TPM_CRB_INT_ENABLE 0x50
-#define TPM_CRB_INT_STS 0x54
-#define TPM_CRB_CTRL_CMD_SIZE 0x58
-#define TPM_CRB_CTRL_CMD_LADDR 0x5C
-#define TPM_CRB_CTRL_CMD_HADDR 0x60
-#define TPM_CRB_CTRL_RSP_SIZE 0x64
-#define TPM_CRB_CTRL_RSP_ADDR 0x68
-#define TPM_CRB_CTRL_RSP_HADDR 0x6c
-#define TPM_CRB_DATA_BUFFER 0x80
+#define TPM_LOC_STATE 0x0
+#define TPM_LOC_CTRL 0x8
+#define TPM_LOC_STS 0xC
+#define TPM_CRB_INTF_ID 0x30
+#define TPM_CRB_CTRL_EXT 0x38
+#define TPM_CRB_CTRL_REQ 0x40
+#define TPM_CRB_CTRL_STS 0x44
+#define TPM_CRB_CTRL_CANCEL 0x48
+#define TPM_CRB_CTRL_START 0x4C
+#define TPM_CRB_INT_ENABLE 0x50
+#define TPM_CRB_INT_STS 0x54
+#define TPM_CRB_CTRL_CMD_SIZE 0x58
+#define TPM_CRB_CTRL_CMD_LADDR 0x5C
+#define TPM_CRB_CTRL_CMD_HADDR 0x60
+#define TPM_CRB_CTRL_RSP_SIZE 0x64
+#define TPM_CRB_CTRL_RSP_ADDR 0x68
+#define TPM_CRB_CTRL_RSP_HADDR 0x6c
+#define TPM_CRB_DATA_BUFFER 0x80
-#define TPM_LOC_STATE_ESTB BIT(0)
-#define TPM_LOC_STATE_ASSIGNED BIT(1)
-#define TPM_LOC_STATE_ACTIVE_MASK 0x9C
-#define TPM_LOC_STATE_VALID BIT(7)
+#define TPM_LOC_STATE_ESTB BIT(0)
+#define TPM_LOC_STATE_ASSIGNED BIT(1)
+#define TPM_LOC_STATE_ACTIVE_MASK 0x9C
+#define TPM_LOC_STATE_VALID BIT(7)
-#define TPM_CRB_INTF_ID_TYPE_CRB 0x1
-#define TPM_CRB_INTF_ID_TYPE 0x7
+#define TPM_CRB_INTF_ID_TYPE_CRB 0x1
+#define TPM_CRB_INTF_ID_TYPE 0x7
-#define TPM_LOC_CTRL_REQUEST BIT(0)
-#define TPM_LOC_CTRL_RELINQUISH BIT(1)
+#define TPM_LOC_CTRL_REQUEST BIT(0)
+#define TPM_LOC_CTRL_RELINQUISH BIT(1)
-#define TPM_CRB_CTRL_REQ_GO_READY BIT(0)
-#define TPM_CRB_CTRL_REQ_GO_IDLE BIT(1)
+#define TPM_CRB_CTRL_REQ_GO_READY BIT(0)
+#define TPM_CRB_CTRL_REQ_GO_IDLE BIT(1)
-#define TPM_CRB_CTRL_STS_ERR_BIT BIT(0)
-#define TPM_CRB_CTRL_STS_IDLE_BIT BIT(1)
+#define TPM_CRB_CTRL_STS_ERR_BIT BIT(0)
+#define TPM_CRB_CTRL_STS_IDLE_BIT BIT(1)
-#define TPM_CRB_CTRL_CANCEL_CMD BIT(0)
+#define TPM_CRB_CTRL_CANCEL_CMD BIT(0)
-#define TPM_CRB_CTRL_START_CMD BIT(0)
+#define TPM_CRB_CTRL_START_CMD BIT(0)
-#define TPM_CRB_INT_ENABLE_BIT BIT(31)
+#define TPM_CRB_INT_ENABLE_BIT BIT(31)
struct tpmcrb_sc {
struct tpm_sc base;
@@ -166,7 +166,8 @@ tpmcrb_attach(device_t dev)
return (ENXIO);
if(!tpmcrb_request_locality(sc, 0)) {
- tpmcrb_detach(dev);
+ bus_release_resource(dev, SYS_RES_MEMORY,
+ sc->mem_rid, sc->mem_res);
return (ENXIO);
}
@@ -232,12 +233,12 @@ tpmcrb_detach(device_t dev)
struct tpm_sc *sc;
sc = device_get_softc(dev);
+ tpm20_release(sc);
if (sc->mem_res != NULL)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->mem_rid, sc->mem_res);
- tpm20_release(sc);
return (0);
}
Modified: stable/11/sys/dev/tpm/tpm_tis.c
==============================================================================
--- stable/11/sys/dev/tpm/tpm_tis.c Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/dev/tpm/tpm_tis.c Fri Apr 26 01:58:36 2019 (r346725)
@@ -34,45 +34,45 @@ __FBSDID("$FreeBSD$");
* TIS register space as defined in
* TCG_PC_Client_Platform_TPM_Profile_PTP_2.0_r1.03_v22
*/
-#define TPM_ACCESS 0x0
-#define TPM_INT_ENABLE 0x8
-#define TPM_INT_VECTOR 0xc
-#define TPM_INT_STS 0x10
-#define TPM_INTF_CAPS 0x14
-#define TPM_STS 0x18
-#define TPM_DATA_FIFO 0x24
-#define TPM_INTF_ID 0x30
-#define TPM_XDATA_FIFO 0x80
-#define TPM_DID_VID 0xF00
-#define TPM_RID 0xF04
+#define TPM_ACCESS 0x0
+#define TPM_INT_ENABLE 0x8
+#define TPM_INT_VECTOR 0xc
+#define TPM_INT_STS 0x10
+#define TPM_INTF_CAPS 0x14
+#define TPM_STS 0x18
+#define TPM_DATA_FIFO 0x24
+#define TPM_INTF_ID 0x30
+#define TPM_XDATA_FIFO 0x80
+#define TPM_DID_VID 0xF00
+#define TPM_RID 0xF04
-#define TPM_ACCESS_LOC_REQ BIT(1)
-#define TPM_ACCESS_LOC_Seize BIT(3)
-#define TPM_ACCESS_LOC_ACTIVE BIT(5)
-#define TPM_ACCESS_LOC_RELINQUISH BIT(5)
-#define TPM_ACCESS_VALID BIT(7)
+#define TPM_ACCESS_LOC_REQ BIT(1)
+#define TPM_ACCESS_LOC_Seize BIT(3)
+#define TPM_ACCESS_LOC_ACTIVE BIT(5)
+#define TPM_ACCESS_LOC_RELINQUISH BIT(5)
+#define TPM_ACCESS_VALID BIT(7)
-#define TPM_INT_ENABLE_GLOBAL_ENABLE BIT(31)
-#define TPM_INT_ENABLE_CMD_RDY BIT(7)
-#define TPM_INT_ENABLE_LOC_CHANGE BIT(2)
-#define TPM_INT_ENABLE_STS_VALID BIT(1)
-#define TPM_INT_ENABLE_DATA_AVAIL BIT(0)
+#define TPM_INT_ENABLE_GLOBAL_ENABLE BIT(31)
+#define TPM_INT_ENABLE_CMD_RDY BIT(7)
+#define TPM_INT_ENABLE_LOC_CHANGE BIT(2)
+#define TPM_INT_ENABLE_STS_VALID BIT(1)
+#define TPM_INT_ENABLE_DATA_AVAIL BIT(0)
-#define TPM_INT_STS_CMD_RDY BIT(7)
-#define TPM_INT_STS_LOC_CHANGE BIT(2)
-#define TPM_INT_STS_VALID BIT(1)
-#define TPM_INT_STS_DATA_AVAIL BIT(0)
+#define TPM_INT_STS_CMD_RDY BIT(7)
+#define TPM_INT_STS_LOC_CHANGE BIT(2)
+#define TPM_INT_STS_VALID BIT(1)
+#define TPM_INT_STS_DATA_AVAIL BIT(0)
-#define TPM_INTF_CAPS_VERSION 0x70000000
-#define TPM_INTF_CAPS_TPM20 0x30000000
+#define TPM_INTF_CAPS_VERSION 0x70000000
+#define TPM_INTF_CAPS_TPM20 0x30000000
-#define TPM_STS_VALID BIT(7)
-#define TPM_STS_CMD_RDY BIT(6)
-#define TPM_STS_CMD_START BIT(5)
-#define TPM_STS_DATA_AVAIL BIT(4)
-#define TPM_STS_DATA_EXPECTED BIT(3)
-#define TPM_STS_BURST_MASK 0xFFFF00
-#define TPM_STS_BURST_OFFSET 0x8
+#define TPM_STS_VALID BIT(7)
+#define TPM_STS_CMD_RDY BIT(6)
+#define TPM_STS_CMD_START BIT(5)
+#define TPM_STS_DATA_AVAIL BIT(4)
+#define TPM_STS_DATA_EXPECTED BIT(3)
+#define TPM_STS_BURST_MASK 0xFFFF00
+#define TPM_STS_BURST_OFFSET 0x8
static int tpmtis_transmit(struct tpm_sc *sc, size_t length);
@@ -93,6 +93,7 @@ static bool tpmtis_go_ready(struct tpm_sc *sc);
static bool tpm_wait_for_u32(struct tpm_sc *sc, bus_size_t off,
uint32_t mask, uint32_t val, int32_t timeout);
+
static uint16_t tpmtis_wait_for_burst(struct tpm_sc *sc);
char *tpmtis_ids[] = {"MSFT0101", NULL};
@@ -162,6 +163,7 @@ tpmtis_detach(device_t dev)
struct tpm_sc *sc;
sc = device_get_softc(dev);
+ tpm20_release(sc);
if (sc->intr_cookie != NULL)
bus_teardown_intr(dev, sc->irq_res, sc->intr_cookie);
@@ -174,7 +176,6 @@ tpmtis_detach(device_t dev)
bus_release_resource(dev, SYS_RES_MEMORY,
sc->mem_rid, sc->mem_res);
- tpm20_release(sc);
return (0);
}
Modified: stable/11/sys/sys/random.h
==============================================================================
--- stable/11/sys/sys/random.h Fri Apr 26 01:41:55 2019 (r346724)
+++ stable/11/sys/sys/random.h Fri Apr 26 01:58:36 2019 (r346725)
@@ -91,6 +91,7 @@ enum random_entropy_source {
RANDOM_PURE_RNDTEST,
RANDOM_PURE_VIRTIO,
RANDOM_PURE_BROADCOM,
+ RANDOM_PURE_TPM,
ENTROPYSOURCE
};
More information about the svn-src-stable-11
mailing list