Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Mar 2019 05:13:52 +0000 (UTC)
From:      Marcin Wojtas <mw@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r345438 - in head/sys: conf dev/random dev/tpm sys
Message-ID:  <201903230513.x2N5DqoC026727@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: mw
Date: Sat Mar 23 05:13:51 2019
New Revision: 345438
URL: https://svnweb.freebsd.org/changeset/base/345438

Log:
  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.
  
  Submitted by: Kornel Duleba <mindal@semihalf.com>
  Reviewed by: markm, delphij
  Approved by: secteam
  Obtained from: Semihalf
  Sponsored by: Stormshield
  Differential Revision: https://reviews.freebsd.org/D19620

Modified:
  head/sys/conf/options
  head/sys/dev/random/random_harvestq.c
  head/sys/dev/tpm/tpm20.c
  head/sys/dev/tpm/tpm20.h
  head/sys/dev/tpm/tpm_crb.c
  head/sys/dev/tpm/tpm_tis.c
  head/sys/sys/random.h

Modified: head/sys/conf/options
==============================================================================
--- head/sys/conf/options	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/conf/options	Sat Mar 23 05:13:51 2019	(r345438)
@@ -983,6 +983,9 @@ RANDOM_LOADABLE	opt_global.h
 RANDOM_ENABLE_UMA	opt_global.h
 RANDOM_ENABLE_ETHER	opt_global.h
 
+# This options turns TPM into entropy source.
+TPM_HARVEST	opt_tpm.h
+
 # BHND(4) driver
 BHND_LOGLEVEL	opt_global.h
 

Modified: head/sys/dev/random/random_harvestq.c
==============================================================================
--- head/sys/dev/random/random_harvestq.c	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/dev/random/random_harvestq.c	Sat Mar 23 05:13:51 2019	(r345438)
@@ -330,6 +330,7 @@ static const char *random_source_descr[ENTROPYSOURCE] 
 	[RANDOM_PURE_BROADCOM] = "PURE_BROADCOM",
 	[RANDOM_PURE_CCP] = "PURE_CCP",
 	[RANDOM_PURE_DARN] = "PURE_DARN",
+	[RANDOM_PURE_TPM] = "PURE_TPM",
 	/* "ENTROPYSOURCE" */
 };
 

Modified: head/sys/dev/tpm/tpm20.c
==============================================================================
--- head/sys/dev/tpm/tpm20.c	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/dev/tpm/tpm20.c	Sat Mar 23 05:13:51 2019	(r345438)
@@ -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;
@@ -175,6 +189,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 +214,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);
 
@@ -216,6 +239,57 @@ 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);
+
+	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, 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)

Modified: head/sys/dev/tpm/tpm20.h
==============================================================================
--- head/sys/dev/tpm/tpm20.h	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/dev/tpm/tpm20.h	Sat Mar 23 05:13:51 2019	(r345438)
@@ -55,6 +55,8 @@ __FBSDID("$FreeBSD$");
 #include <dev/acpica/acpivar.h>
 #include "opt_acpi.h"
 
+#include "opt_tpm.h"
+
 #define	BIT(x) (1 << (x))
 
 /* Timeouts in us */
@@ -120,6 +122,10 @@ struct tpm_sc {
 	size_t		pending_data_length;
 
 	struct callout 	discard_buffer_callout;
+#ifdef TPM_HARVEST
+	struct callout 	harvest_callout;
+	int		harvest_ticks;
+#endif
 
 	int		(*transmit)(struct tpm_sc *, size_t);
 };

Modified: head/sys/dev/tpm/tpm_crb.c
==============================================================================
--- head/sys/dev/tpm/tpm_crb.c	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/dev/tpm/tpm_crb.c	Sat Mar 23 05:13:51 2019	(r345438)
@@ -165,7 +165,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);
 	}
 
@@ -231,12 +232,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: head/sys/dev/tpm/tpm_tis.c
==============================================================================
--- head/sys/dev/tpm/tpm_tis.c	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/dev/tpm/tpm_tis.c	Sat Mar 23 05:13:51 2019	(r345438)
@@ -162,6 +162,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 +175,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: head/sys/sys/random.h
==============================================================================
--- head/sys/sys/random.h	Sat Mar 23 04:32:10 2019	(r345437)
+++ head/sys/sys/random.h	Sat Mar 23 05:13:51 2019	(r345438)
@@ -87,6 +87,7 @@ enum random_entropy_source {
 	RANDOM_PURE_BROADCOM,
 	RANDOM_PURE_CCP,
 	RANDOM_PURE_DARN,
+	RANDOM_PURE_TPM,
 	ENTROPYSOURCE
 };
 _Static_assert(ENTROPYSOURCE <= 32,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201903230513.x2N5DqoC026727>