diff options
author | Stefan Berger <stefanb@linux.vnet.ibm.com> | 2017-11-03 22:49:23 -0400 |
---|---|---|
committer | Stefan Berger <stefanb@linux.vnet.ibm.com> | 2017-12-14 23:39:15 -0500 |
commit | abc5cda097f46bdb86833a38ee0961a0e6a47ae1 (patch) | |
tree | d3d32ae6b6d96a7b9cd3a6e6b8cb831384efb57f /hw/tpm/tpm_util.c | |
parent | 56388eee01144d59d5c94a34431a29c75073ba53 (diff) |
tpm: tpm_passthrough: Read the buffer size from the host device
Rather than hard coding the buffer size in the tpm_passthrough
backend read the TPM I/O buffer size from the host device.
Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Diffstat (limited to 'hw/tpm/tpm_util.c')
-rw-r--r-- | hw/tpm/tpm_util.c | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/hw/tpm/tpm_util.c b/hw/tpm/tpm_util.c index b852f53b8d..a317243a7e 100644 --- a/hw/tpm/tpm_util.c +++ b/hw/tpm/tpm_util.c @@ -20,10 +20,19 @@ */ #include "qemu/osdep.h" +#include "qemu/error-report.h" #include "tpm_util.h" #include "tpm_int.h" #include "exec/memory.h" +#define DEBUG_TPM 0 + +#define DPRINTF(fmt, ...) do { \ + if (DEBUG_TPM) { \ + fprintf(stderr, "tpm-util:"fmt"\n", ## __VA_ARGS__); \ + } \ +} while (0) + /* * Write an error message in the given output buffer. */ @@ -173,3 +182,109 @@ int tpm_util_test_tpmdev(int tpm_fd, TPMVersion *tpm_version) return 1; } + +int tpm_util_get_buffer_size(int tpm_fd, TPMVersion tpm_version, + size_t *buffersize) +{ + unsigned char buf[1024]; + int ret; + + switch (tpm_version) { + case TPM_VERSION_1_2: { + const struct tpm_req_get_buffer_size { + struct tpm_req_hdr hdr; + uint32_t capability; + uint32_t len; + uint32_t subcap; + } QEMU_PACKED tpm_get_buffer_size = { + .hdr = { + .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND), + .len = cpu_to_be32(sizeof(tpm_get_buffer_size)), + .ordinal = cpu_to_be32(TPM_ORD_GetCapability), + }, + .capability = cpu_to_be32(TPM_CAP_PROPERTY), + .len = cpu_to_be32(sizeof(uint32_t)), + .subcap = cpu_to_be32(TPM_CAP_PROP_INPUT_BUFFER), + }; + struct tpm_resp_get_buffer_size { + struct tpm_resp_hdr hdr; + uint32_t len; + uint32_t buffersize; + } QEMU_PACKED *tpm_resp = (struct tpm_resp_get_buffer_size *)buf; + + ret = tpm_util_request(tpm_fd, (unsigned char *)&tpm_get_buffer_size, + sizeof(tpm_get_buffer_size), buf, sizeof(buf)); + if (ret < 0) { + return ret; + } + + if (be32_to_cpu(tpm_resp->hdr.len) != sizeof(*tpm_resp) || + be32_to_cpu(tpm_resp->len) != sizeof(uint32_t)) { + DPRINTF("tpm_resp->hdr.len = %u, expected = %zu\n", + be32_to_cpu(tpm_resp->hdr.len), sizeof(*tpm_resp)); + DPRINTF("tpm_resp->len = %u, expected = %zu\n", + be32_to_cpu(tpm_resp->len), sizeof(uint32_t)); + error_report("tpm_util: Got unexpected response to " + "TPM_GetCapability; errcode: 0x%x", + be32_to_cpu(tpm_resp->hdr.errcode)); + return -EFAULT; + } + *buffersize = be32_to_cpu(tpm_resp->buffersize); + break; + } + case TPM_VERSION_2_0: { + const struct tpm2_req_get_buffer_size { + struct tpm_req_hdr hdr; + uint32_t capability; + uint32_t property; + uint32_t count; + } QEMU_PACKED tpm2_get_buffer_size = { + .hdr = { + .tag = cpu_to_be16(TPM2_ST_NO_SESSIONS), + .len = cpu_to_be32(sizeof(tpm2_get_buffer_size)), + .ordinal = cpu_to_be32(TPM2_CC_GetCapability), + }, + .capability = cpu_to_be32(TPM2_CAP_TPM_PROPERTIES), + .property = cpu_to_be32(TPM2_PT_MAX_COMMAND_SIZE), + .count = cpu_to_be32(2), /* also get TPM2_PT_MAX_RESPONSE_SIZE */ + }; + struct tpm2_resp_get_buffer_size { + struct tpm_resp_hdr hdr; + uint8_t more; + uint32_t capability; + uint32_t count; + uint32_t property1; + uint32_t value1; + uint32_t property2; + uint32_t value2; + } QEMU_PACKED *tpm2_resp = (struct tpm2_resp_get_buffer_size *)buf; + + ret = tpm_util_request(tpm_fd, (unsigned char *)&tpm2_get_buffer_size, + sizeof(tpm2_get_buffer_size), buf, sizeof(buf)); + if (ret < 0) { + return ret; + } + + if (be32_to_cpu(tpm2_resp->hdr.len) != sizeof(*tpm2_resp) || + be32_to_cpu(tpm2_resp->count) != 2) { + DPRINTF("tpm2_resp->hdr.len = %u, expected = %zu\n", + be32_to_cpu(tpm2_resp->hdr.len), sizeof(*tpm2_resp)); + DPRINTF("tpm2_resp->len = %u, expected = %u\n", + be32_to_cpu(tpm2_resp->count), 2); + error_report("tpm_util: Got unexpected response to " + "TPM2_GetCapability; errcode: 0x%x", + be32_to_cpu(tpm2_resp->hdr.errcode)); + return -EFAULT; + } + *buffersize = MAX(be32_to_cpu(tpm2_resp->value1), + be32_to_cpu(tpm2_resp->value2)); + break; + } + case TPM_VERSION_UNSPEC: + return -EFAULT; + } + + DPRINTF("buffersize of device: %zu\n", *buffersize); + + return 0; +} |