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>