|
@@ -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;
|
|
|
+}
|