} u;
};
+#define PTM_GETINFO_SIZE (3 * 1024)
+/*
+ * PTM_GET_INFO: Get info about the TPM implementation (from libtpms)
+ *
+ * This request allows to indirectly call TPMLIB_GetInfo(flags) and
+ * retrieve information from libtpms.
+ * Only one transaction is currently necessary for returning results
+ * to a client. Therefore, totlength and length will be the same if
+ * offset is 0.
+ */
+struct ptm_getinfo {
+ union {
+ struct {
+ uint64_t flags;
+ uint32_t offset; /* offset from where to read */
+ } req; /* request */
+ struct {
+ ptm_res tpm_result;
+ uint32_t totlength;
+ uint32_t length;
+ char buffer[PTM_GETINFO_SIZE];
+ } resp; /* response */
+ } u;
+};
typedef uint64_t ptm_cap;
typedef struct ptm_est ptm_est;
typedef struct ptm_setstate ptm_setstate;
typedef struct ptm_getconfig ptm_getconfig;
typedef struct ptm_setbuffersize ptm_setbuffersize;
+typedef struct ptm_getinfo ptm_getinfo;
/* capability flags returned by PTM_GET_CAPABILITY */
#define PTM_CAP_INIT (1)
#define PTM_CAP_GET_CONFIG (1 << 11)
#define PTM_CAP_SET_DATAFD (1 << 12)
#define PTM_CAP_SET_BUFFERSIZE (1 << 13)
+#define PTM_CAP_GET_INFO (1 << 14)
enum {
PTM_GET_CAPABILITY = _IOR('P', 0, ptm_cap),
PTM_GET_CONFIG = _IOR('P', 14, ptm_getconfig),
PTM_SET_DATAFD = _IOR('P', 15, ptm_res),
PTM_SET_BUFFERSIZE = _IOWR('P', 16, ptm_setbuffersize),
+ PTM_GET_INFO = _IOWR('P', 17, ptm_getinfo),
};
/*
CMD_GET_CONFIG, /* 0x0f */
CMD_SET_DATAFD, /* 0x10 */
CMD_SET_BUFFERSIZE, /* 0x11 */
+ CMD_GET_INFO, /* 0x12 */
};
#endif /* _TPM_IOCTL_H */
ptm_setstate *pss;
ptm_loc *pl;
ptm_setbuffersize *psbs;
+ ptm_getinfo *pgi;
size_t out_len = 0;
TPM_RESULT res;
uint32_t remain;
uint32_t buffersize, maxsize, minsize;
+ uint64_t info_flags;
+ uint32_t offset;
+ char *info_data = NULL;
+ size_t length;
if (fd < 0)
return -1;
#ifndef __CYGWIN__
PTM_CAP_SET_DATAFD |
#endif
- PTM_CAP_SET_BUFFERSIZE
+ PTM_CAP_SET_BUFFERSIZE |
+ PTM_CAP_GET_INFO
);
out_len = sizeof(*ptm_caps);
break;
+ case CMD_GET_INFO:
+ pgi = (ptm_getinfo *)input.body;
+ if (n < (ssize_t)sizeof(pgi->u.req)) /* rw */
+ goto err_bad_input;
+
+ info_flags = be64toh(pgi->u.req.flags);
+
+ info_data = TPMLIB_GetInfo(info_flags);
+ if (!info_data)
+ goto err_memory;
+
+ offset = be32toh(pgi->u.req.offset);
+ if (offset >= strlen(info_data)) {
+ free(info_data);
+ goto err_bad_input;
+ }
+
+ length = min(strlen(info_data) + 1 - offset,
+ sizeof(pgi->u.resp.buffer));
+
+ pgi = (ptm_getinfo *)&output.body;
+ pgi->u.resp.tpm_result = htobe32(0);
+ pgi->u.resp.totlength = htobe32(strlen(info_data) + 1);
+ pgi->u.resp.length = htobe32(length);
+ strncpy(pgi->u.resp.buffer, &info_data[offset], length);
+ free(info_data);
+
+ out_len = offsetof(ptm_getinfo, u.resp.buffer) + length;
+
+ break;
+
default:
logprintf(STDERR_FILENO,
"Error: Unknown command: 0x%08x\n", be32toh(input.cmd));
goto send_resp;
+err_memory:
+ *res_p = htobe32(TPM_SIZE);
+ out_len = sizeof(ptm_res);
+
+ goto send_resp;
+
err_socket:
close(fd);
}
break;
+ case PTM_GET_INFO:
+ if (out_bufsz != sizeof(ptm_getinfo)) {
+ struct iovec iov = { arg, sizeof(uint32_t) };
+ fuse_reply_ioctl_retry(req, &iov, 1, NULL, 0);
+ } else {
+ ptm_getinfo *in_pgi = (ptm_getinfo *)in_buf;
+ ptm_getinfo out_pgi;
+ char *info_data;
+ uint32_t length, offset;
+
+ info_data = TPMLIB_GetInfo(in_pgi->u.req.flags);
+ if (!info_data)
+ goto error_memory;
+
+ offset = in_pgi->u.req.offset;
+ if (offset >= strlen(info_data)) {
+ free(info_data);
+ goto error_bad_input;
+ }
+
+ length = min(strlen(info_data) + 1 - offset,
+ sizeof(out_pgi.u.resp.buffer));
+
+ out_pgi.u.resp.tpm_result = 0;
+ out_pgi.u.resp.totlength = strlen(info_data) + 1;
+ out_pgi.u.resp.length = length;
+ strncpy(out_pgi.u.resp.buffer, &info_data[offset], length);
+ free(info_data);
+
+ fuse_reply_ioctl(req, 0, &out_pgi, sizeof(out_pgi));
+ }
+ break;
+
default:
fuse_reply_err(req, EINVAL);
}
return;
+error_bad_input:
+ res = TPM_BAD_PARAMETER;
+ fuse_reply_ioctl(req, 0, &res, sizeof(res));
+
+ goto cleanup;
+
error_running:
error_not_running:
res = TPM_BAD_ORDINAL;
fuse_reply_ioctl(req, 0, &res, sizeof(res));
+ goto cleanup;
+
+error_memory:
+ res = TPM_SIZE;
+ fuse_reply_ioctl(req, 0, &res, sizeof(res));
+
goto cleanup;
}
# test get capabilities
# CMD_GET_CAPABILITY = 0x00 00 00 01
cmd_get_caps = bytearray([0x00, 0x00, 0x00, 0x01])
- expected_caps = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0xff])
+ expected_caps = bytearray([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xff])
def toString(arr):
return ' '.join('{:02x}'.format(x) for x in arr)
# Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01
res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')"
if [[ "$(uname -s)" =~ (Linux|OpenBSD) ]]; then
- exp=" 00 00 00 00 00 00 3f ff"
+ exp=" 00 00 00 00 00 00 7f ff"
else
- exp=" 00 00 00 00 00 00 2f ff"
+ exp=" 00 00 00 00 00 00 6f ff"
fi
if [ "$res" != "$exp" ]; then
echo "Error: Unexpected response from CMD_GET_CAPABILITY:"
# Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01
res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')"
if [[ "$(uname -s)" =~ (Linux|OpenBSD) ]]; then
- exp=" 00 00 00 00 00 00 3f ff"
+ exp=" 00 00 00 00 00 00 7f ff"
else
- exp=" 00 00 00 00 00 00 2f ff"
+ exp=" 00 00 00 00 00 00 6f ff"
fi
if [ "$res" != "$exp" ]; then
echo "Error: Socket TPM: Unexpected response from CMD_GET_CAPABILITY:"
# Get the capability bits: CMD_GET_CAPABILITY = 0x00 00 00 01
res="$(swtpm_ctrl_tx ${SWTPM_INTERFACE} '\x00\x00\x00\x01')"
-exp=" 00 00 00 00 00 00 3f ff"
+exp=" 00 00 00 00 00 00 7f ff"
if [ "$res" != "$exp" ]; then
echo "Error: Unexpected response from CMD_GET_CAPABILITY:"
echo " actual : $res"