tpm: tpm_emulator: get and set buffer size of device

Convert the tpm_emulator backend to get the current buffer size
of the external device and set it to the buffer size that the
frontend (TIS) requests.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
This commit is contained in:
Stefan Berger 2017-11-04 19:57:15 -04:00
parent abc5cda097
commit 9375c44fdf
5 changed files with 111 additions and 12 deletions

View file

@ -68,7 +68,7 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp)
return 0;
}
int tpm_backend_startup_tpm(TPMBackend *s)
int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize)
{
int res = 0;
TPMBackendClass *k = TPM_BACKEND_GET_CLASS(s);
@ -79,7 +79,7 @@ int tpm_backend_startup_tpm(TPMBackend *s)
s->thread_pool = g_thread_pool_new(tpm_backend_worker_thread, s, 1, TRUE,
NULL);
res = k->startup_tpm ? k->startup_tpm(s) : 0;
res = k->startup_tpm ? k->startup_tpm(s, buffersize) : 0;
s->had_startup_error = (res != 0);

View file

@ -232,13 +232,14 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
switch (tpm_emu->tpm_version) {
case TPM_VERSION_1_2:
caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD;
PTM_CAP_SET_LOCALITY | PTM_CAP_SET_DATAFD | PTM_CAP_STOP |
PTM_CAP_SET_BUFFERSIZE;
tpm = "1.2";
break;
case TPM_VERSION_2_0:
caps = PTM_CAP_INIT | PTM_CAP_SHUTDOWN | PTM_CAP_GET_TPMESTABLISHED |
PTM_CAP_SET_LOCALITY | PTM_CAP_RESET_TPMESTABLISHED |
PTM_CAP_SET_DATAFD;
PTM_CAP_SET_DATAFD | PTM_CAP_STOP | PTM_CAP_SET_BUFFERSIZE;
tpm = "2";
break;
case TPM_VERSION_UNSPEC:
@ -255,12 +256,76 @@ static int tpm_emulator_check_caps(TPMEmulator *tpm_emu)
return 0;
}
static int tpm_emulator_startup_tpm(TPMBackend *tb)
static int tpm_emulator_stop_tpm(TPMBackend *tb)
{
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
ptm_res res;
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_STOP, &res, 0, sizeof(res)) < 0) {
error_report("tpm-emulator: Could not stop TPM: %s",
strerror(errno));
return -1;
}
res = be32_to_cpu(res);
if (res) {
error_report("tpm-emulator: TPM result for CMD_STOP: 0x%x", res);
return -1;
}
return 0;
}
static int tpm_emulator_set_buffer_size(TPMBackend *tb,
size_t wanted_size,
size_t *actual_size)
{
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
ptm_setbuffersize psbs;
if (tpm_emulator_stop_tpm(tb) < 0) {
return -1;
}
psbs.u.req.buffersize = cpu_to_be32(wanted_size);
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_SET_BUFFERSIZE, &psbs,
sizeof(psbs.u.req), sizeof(psbs.u.resp)) < 0) {
error_report("tpm-emulator: Could not set buffer size: %s",
strerror(errno));
return -1;
}
psbs.u.resp.tpm_result = be32_to_cpu(psbs.u.resp.tpm_result);
if (psbs.u.resp.tpm_result != 0) {
error_report("tpm-emulator: TPM result for set buffer size : 0x%x",
psbs.u.resp.tpm_result);
return -1;
}
if (actual_size) {
*actual_size = be32_to_cpu(psbs.u.resp.buffersize);
}
DPRINTF("buffer size: %u, min: %u, max: %u\n",
be32_to_cpu(psbs.u.resp.buffersize),
be32_to_cpu(psbs.u.resp.minsize),
be32_to_cpu(psbs.u.resp.maxsize));
return 0;
}
static int tpm_emulator_startup_tpm(TPMBackend *tb, size_t buffersize)
{
TPMEmulator *tpm_emu = TPM_EMULATOR(tb);
ptm_init init;
ptm_res res;
if (buffersize != 0 &&
tpm_emulator_set_buffer_size(tb, buffersize, NULL) < 0) {
goto err_exit;
}
DPRINTF("%s", __func__);
if (tpm_emulator_ctrlcmd(tpm_emu, CMD_INIT, &init, sizeof(init),
sizeof(init)) < 0) {
@ -358,7 +423,13 @@ static TPMVersion tpm_emulator_get_tpm_version(TPMBackend *tb)
static size_t tpm_emulator_get_buffer_size(TPMBackend *tb)
{
return 4096;
size_t actual_size;
if (tpm_emulator_set_buffer_size(tb, 0, &actual_size) < 0) {
return 4096;
}
return actual_size;
}
static int tpm_emulator_block_migration(TPMEmulator *tpm_emu)

View file

@ -169,6 +169,28 @@ struct ptm_getconfig {
#define PTM_CONFIG_FLAG_FILE_KEY 0x1
#define PTM_CONFIG_FLAG_MIGRATION_KEY 0x2
/*
* PTM_SET_BUFFERSIZE: Set the buffer size to be used by the TPM.
* A 0 on input queries for the current buffer size. Any other
* number will try to set the buffer size. The returned number is
* the buffer size that will be used, which can be larger than the
* requested one, if it was below the minimum, or smaller than the
* requested one, if it was above the maximum.
*/
struct ptm_setbuffersize {
union {
struct {
uint32_t buffersize; /* 0 to query for current buffer size */
} req; /* request */
struct {
ptm_res tpm_result;
uint32_t buffersize; /* buffer size in use */
uint32_t minsize; /* min. supported buffer size */
uint32_t maxsize; /* max. supported buffer size */
} resp; /* response */
} u;
};
typedef uint64_t ptm_cap;
typedef struct ptm_est ptm_est;
@ -179,6 +201,7 @@ typedef struct ptm_init ptm_init;
typedef struct ptm_getstate ptm_getstate;
typedef struct ptm_setstate ptm_setstate;
typedef struct ptm_getconfig ptm_getconfig;
typedef struct ptm_setbuffersize ptm_setbuffersize;
/* capability flags returned by PTM_GET_CAPABILITY */
#define PTM_CAP_INIT (1)
@ -194,6 +217,7 @@ typedef struct ptm_getconfig ptm_getconfig;
#define PTM_CAP_STOP (1 << 10)
#define PTM_CAP_GET_CONFIG (1 << 11)
#define PTM_CAP_SET_DATAFD (1 << 12)
#define PTM_CAP_SET_BUFFERSIZE (1 << 13)
enum {
PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
@ -212,6 +236,7 @@ enum {
PTM_STOP = _IOR('P', 13, ptm_res),
PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
PTM_SET_DATAFD = _IOR('P', 15, ptm_res),
PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize),
};
/*
@ -240,7 +265,8 @@ enum {
CMD_SET_STATEBLOB,
CMD_STOP,
CMD_GET_CONFIG,
CMD_SET_DATAFD
CMD_SET_DATAFD,
CMD_SET_BUFFERSIZE,
};
#endif /* _TPM_IOCTL_H */

View file

@ -974,9 +974,9 @@ static const MemoryRegionOps tpm_tis_memory_ops = {
},
};
static int tpm_tis_do_startup_tpm(TPMState *s)
static int tpm_tis_do_startup_tpm(TPMState *s, uint32_t buffersize)
{
return tpm_backend_startup_tpm(s->be_driver);
return tpm_backend_startup_tpm(s->be_driver, buffersize);
}
static void tpm_tis_realloc_buffer(TPMSizedBuffer *sb,
@ -1044,7 +1044,7 @@ static void tpm_tis_reset(DeviceState *dev)
tpm_tis_realloc_buffer(&s->loc[c].r_buffer, s->be_buffer_size);
}
tpm_tis_do_startup_tpm(s);
tpm_tis_do_startup_tpm(s, 0);
}
static const VMStateDescription vmstate_tpm_tis = {

View file

@ -66,7 +66,7 @@ struct TPMBackendClass {
TPMBackend *(*create)(QemuOpts *opts);
/* start up the TPM on the backend - optional */
int (*startup_tpm)(TPMBackend *t);
int (*startup_tpm)(TPMBackend *t, size_t buffersize);
/* optional */
void (*reset)(TPMBackend *t);
@ -112,10 +112,12 @@ int tpm_backend_init(TPMBackend *s, TPMIf *tpmif, Error **errp);
/**
* tpm_backend_startup_tpm:
* @s: the backend whose TPM support is to be started
* @buffersize: the buffer size the TPM is supposed to use,
* 0 to leave it as-is
*
* Returns 0 on success.
*/
int tpm_backend_startup_tpm(TPMBackend *s);
int tpm_backend_startup_tpm(TPMBackend *s, size_t buffersize);
/**
* tpm_backend_had_startup_error: