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
This commit is contained in:
parent
817c58e3ac
commit
4ee7d3b011
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=345438
@ -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
|
||||
|
||||
|
@ -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" */
|
||||
};
|
||||
|
||||
|
@ -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);
|
||||
|
||||
@ -217,6 +240,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)
|
||||
{
|
||||
|
@ -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);
|
||||
};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user