mirror of
https://github.com/stefanberger/swtpm.git
synced 2025-12-26 05:16:01 +00:00
swtpm: Implement CMD_GETINFO to retrieve TPM specification info
We quetry the swtpm for TPM specification info that goes into the certificate for the EK. Update the test cases that now see more capabilties being returned by the swtpm. Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
parent
d40700020b
commit
2b8a668dbb
@ -191,6 +191,30 @@ struct ptm_setbuffersize {
|
||||
} 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;
|
||||
@ -202,6 +226,7 @@ typedef struct ptm_getstate ptm_getstate;
|
||||
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)
|
||||
@ -218,6 +243,7 @@ typedef struct ptm_setbuffersize ptm_setbuffersize;
|
||||
#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),
|
||||
@ -237,6 +263,7 @@ enum {
|
||||
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),
|
||||
};
|
||||
|
||||
/*
|
||||
@ -267,6 +294,7 @@ enum {
|
||||
CMD_GET_CONFIG, /* 0x0f */
|
||||
CMD_SET_DATAFD, /* 0x10 */
|
||||
CMD_SET_BUFFERSIZE, /* 0x11 */
|
||||
CMD_GET_INFO, /* 0x12 */
|
||||
};
|
||||
|
||||
#endif /* _TPM_IOCTL_H */
|
||||
|
||||
@ -475,11 +475,16 @@ int ctrlchannel_process_fd(int fd,
|
||||
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;
|
||||
@ -515,7 +520,8 @@ int ctrlchannel_process_fd(int fd,
|
||||
#ifndef __CYGWIN__
|
||||
PTM_CAP_SET_DATAFD |
|
||||
#endif
|
||||
PTM_CAP_SET_BUFFERSIZE
|
||||
PTM_CAP_SET_BUFFERSIZE |
|
||||
PTM_CAP_GET_INFO
|
||||
);
|
||||
|
||||
out_len = sizeof(*ptm_caps);
|
||||
@ -795,6 +801,37 @@ int ctrlchannel_process_fd(int fd,
|
||||
|
||||
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));
|
||||
@ -840,6 +877,12 @@ err_io:
|
||||
|
||||
goto send_resp;
|
||||
|
||||
err_memory:
|
||||
*res_p = htobe32(TPM_SIZE);
|
||||
out_len = sizeof(ptm_res);
|
||||
|
||||
goto send_resp;
|
||||
|
||||
err_socket:
|
||||
close(fd);
|
||||
|
||||
|
||||
@ -1209,6 +1209,39 @@ static void ptm_ioctl(fuse_req_t req, int cmd, void *arg,
|
||||
}
|
||||
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);
|
||||
}
|
||||
@ -1225,11 +1258,23 @@ cleanup:
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@ -64,7 +64,7 @@ def test_get_caps():
|
||||
# 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)
|
||||
|
||||
@ -58,9 +58,9 @@ PID="$(cat $PID_FILE)"
|
||||
# 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:"
|
||||
@ -173,9 +173,9 @@ swtpm_open_cmddev ${SWTPM_INTERFACE} 100
|
||||
# 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:"
|
||||
|
||||
@ -45,7 +45,7 @@ PID="$(cat $PID_FILE)"
|
||||
|
||||
# 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"
|
||||
|
||||
Loading…
Reference in New Issue
Block a user