mirror of
https://github.com/stefanberger/swtpm.git
synced 2026-08-08 10:01:50 +00:00
swtpm_cuse: Support parial reads (issue #376)
This patch adds support for partial reads to the CUSE swtpm. We introduce a ptm_read_offset variable that holds the offset where to read from next. It is reset every time a command has been processed as part of a write() so that subsequent read()s start reading from offset 0. It is advanced by the number of bytes that were read. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
This commit is contained in:
parent
e753128b27
commit
024073c5cc
@ -91,6 +91,9 @@ static unsigned char *ptm_request;
|
||||
/* buffer containing the TPM response */
|
||||
static unsigned char *ptm_response;
|
||||
|
||||
/* offset from where to read from; reset when ptm_response is set */
|
||||
static size_t ptm_read_offset;
|
||||
|
||||
/* the sizes of the data in the buffers */
|
||||
static uint32_t ptm_req_len, ptm_res_len, ptm_res_tot;
|
||||
|
||||
@ -401,6 +404,7 @@ static void worker_thread(gpointer data, gpointer user_data)
|
||||
case MESSAGE_TPM_CMD:
|
||||
TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
|
||||
ptm_request, ptm_req_len);
|
||||
ptm_read_offset = 0;
|
||||
break;
|
||||
case MESSAGE_IOCTL:
|
||||
break;
|
||||
@ -489,6 +493,7 @@ static void ptm_write_fatal_error_response(TPMLIB_TPMVersion l_tpmversion)
|
||||
&ptm_res_len,
|
||||
&ptm_res_tot,
|
||||
l_tpmversion);
|
||||
ptm_read_offset = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -506,9 +511,11 @@ static int ptm_send_startup(uint16_t startupType, TPMLIB_TPMVersion l_tpmversion
|
||||
startupType,
|
||||
tpmversion,
|
||||
command, max_command_length);
|
||||
if (command_length > 0)
|
||||
if (command_length > 0) {
|
||||
rc = TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
|
||||
(unsigned char *)command, command_length);
|
||||
ptm_read_offset = 0;
|
||||
}
|
||||
|
||||
if (rc || command_length == 0) {
|
||||
if (rc) {
|
||||
@ -530,23 +537,22 @@ static int ptm_send_startup(uint16_t startupType, TPMLIB_TPMVersion l_tpmversion
|
||||
*/
|
||||
static void ptm_read_result(fuse_req_t req, size_t size)
|
||||
{
|
||||
int len;
|
||||
size_t len = 0;
|
||||
|
||||
if (tpm_running) {
|
||||
/* wait until results are ready */
|
||||
worker_thread_wait_done();
|
||||
}
|
||||
|
||||
len = ptm_res_len;
|
||||
|
||||
if (ptm_res_len > size) {
|
||||
len = size;
|
||||
ptm_res_len -= size;
|
||||
} else {
|
||||
ptm_res_len = 0;
|
||||
if (ptm_read_offset < ptm_res_len) {
|
||||
len = ptm_res_len - ptm_read_offset;
|
||||
if (size < len)
|
||||
len = size;
|
||||
}
|
||||
|
||||
fuse_reply_buf(req, (const char *)ptm_response, len);
|
||||
fuse_reply_buf(req, (const char *)&ptm_response[ptm_read_offset], len);
|
||||
|
||||
ptm_read_offset += len;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -871,8 +877,10 @@ static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size,
|
||||
tpmlib_process(&ptm_response, &ptm_res_len, &ptm_res_tot,
|
||||
(unsigned char *)buf, ptm_req_len,
|
||||
locality_flags, &locality, tpmversion);
|
||||
if (ptm_res_len)
|
||||
if (ptm_res_len) {
|
||||
ptm_read_offset = 0;
|
||||
goto skip_process;
|
||||
}
|
||||
|
||||
if (tpmlib_is_request_cancelable(l_tpmversion,
|
||||
(const unsigned char*)buf,
|
||||
@ -889,6 +897,7 @@ static void ptm_write_cmd(fuse_req_t req, const char *buf, size_t size,
|
||||
/* direct processing */
|
||||
TPMLIB_Process(&ptm_response, &ptm_res_len, &ptm_res_tot,
|
||||
(unsigned char *)buf, ptm_req_len);
|
||||
ptm_read_offset = 0;
|
||||
}
|
||||
} else {
|
||||
/* TPM not initialized; return error */
|
||||
|
||||
@ -56,6 +56,7 @@ TESTS += \
|
||||
test_tpm2_hashing2 \
|
||||
test_tpm2_hashing3 \
|
||||
test_tpm2_migration_key \
|
||||
test_tpm2_partial_reads \
|
||||
test_tpm2_print_capabilities \
|
||||
test_tpm2_resume_volatile \
|
||||
test_tpm2_savestate \
|
||||
|
||||
151
tests/test_tpm2_partial_reads
Executable file
151
tests/test_tpm2_partial_reads
Executable file
@ -0,0 +1,151 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# For the license, see the LICENSE file in the root directory.
|
||||
# set -x
|
||||
|
||||
cd $(dirname "$0")
|
||||
|
||||
ROOT=${abs_top_builddir:-$(pwd)/..}
|
||||
|
||||
export SWTPM_INTERFACE=cuse
|
||||
|
||||
VTPM_NAME="vtpm-test-tpm2-partial-reads"
|
||||
SWTPM_DEV_NAME="/dev/${VTPM_NAME}"
|
||||
export TPM_PATH=$(mktemp -d)
|
||||
CMD_PATH="${TPM_PATH}/cmd"
|
||||
|
||||
function cleanup()
|
||||
{
|
||||
pid=${SWTPM_PID}
|
||||
if [ -n "$pid" ]; then
|
||||
kill_quiet -9 $pid
|
||||
fi
|
||||
rm -rf $TPM_PATH
|
||||
}
|
||||
|
||||
function swtpm_read_n_bytes_fd100()
|
||||
{
|
||||
dd bs=1 count=$1 if=/proc/self/fd/100 2>/dev/null | \
|
||||
od -t x1 -A n | \
|
||||
tr -s ' ' | \
|
||||
tr -d '\n' | \
|
||||
sed 's/ $//g'
|
||||
}
|
||||
|
||||
trap "cleanup" EXIT
|
||||
|
||||
[ "${SWTPM_INTERFACE}" == "cuse" ] && source test_cuse
|
||||
source common
|
||||
|
||||
run_swtpm ${SWTPM_INTERFACE} --tpm2
|
||||
|
||||
kill_quiet -0 ${SWTPM_PID}
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: ${SWTPM_INTERFACE} TPM did not start."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Init the TPM
|
||||
run_swtpm_ioctl ${SWTPM_INTERFACE} -i
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
kill_quiet -0 ${SWTPM_PID} 2>/dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Prepare the TPM2_Startup
|
||||
echo -en '\x80\x01\x00\x00\x00\x0c\x00\x00\x01\x44\x00\x00' > "${CMD_PATH}"
|
||||
|
||||
swtpm_open_cmddev ${SWTPM_INTERFACE} 100
|
||||
|
||||
# Startup the TPM2
|
||||
cat "${CMD_PATH}" >&100
|
||||
|
||||
# Read 4 and then 6 bytes of the response
|
||||
res1=$(swtpm_read_n_bytes_fd100 4)
|
||||
exp1=' 80 01 00 00'
|
||||
if [ "$res1" != "$exp1" ]; then
|
||||
echo "1st Startup: Unexpected 1st response part"
|
||||
echo "Expected: $exp1"
|
||||
echo "Actual : $res1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
res2=$(swtpm_read_n_bytes_fd100 6)
|
||||
exp2=' 00 0a 00 00 00 00'
|
||||
if [ "$res2" != "$exp2" ]; then
|
||||
echo "1st Startup: Unexpected 2nd response part"
|
||||
echo "Expected: $exp2"
|
||||
echo "Actual : $res2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Startup the TPM2 again (will fail, but that's ok)
|
||||
cat "${CMD_PATH}" >&100
|
||||
|
||||
# Read 4 and then only 4 bytes of the response
|
||||
res1=$(swtpm_read_n_bytes_fd100 4)
|
||||
exp1=' 80 01 00 00'
|
||||
if [ "$res1" != "$exp1" ]; then
|
||||
echo "2nd Startup: Unexpected 1st response part"
|
||||
echo "Expected: $exp1"
|
||||
echo "Actual : $res1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
res2=$(swtpm_read_n_bytes_fd100 4)
|
||||
exp2=' 00 0a 00 00'
|
||||
if [ "$res2" != "$exp2" ]; then
|
||||
echo "2nd Startup: Unexpected 2nd part"
|
||||
echo "Expected: $exp2"
|
||||
echo "Actual : $res2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Startup the TPM2 again (will fail, but that's ok)
|
||||
cat "${CMD_PATH}" >&100
|
||||
|
||||
# Read 4 and then 6 bytes of the response
|
||||
res1=$(swtpm_read_n_bytes_fd100 4)
|
||||
exp1=' 80 01 00 00'
|
||||
if [ "$res1" != "$exp1" ]; then
|
||||
echo "3rd Startup: Unexpected 1st response part"
|
||||
echo "Expected: $exp1"
|
||||
echo "Actual : $res1"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
res2=$(swtpm_read_n_bytes_fd100 6)
|
||||
exp2=' 00 0a 00 00 01 00'
|
||||
if [ "$res2" != "$exp2" ]; then
|
||||
echo "3rd Startup: Unexpected 2nd part"
|
||||
echo "Expected: $exp2"
|
||||
echo "Actual : $res2"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
run_swtpm_ioctl ${SWTPM_INTERFACE} -s
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Error: Could not shut down the ${SWTPM_INTERFACE} TPM."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if wait_process_gone ${SWTPM_PID} 4; then
|
||||
echo "Error: ${SWTPM_INTERFACE} TPM should not be running anymore."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ ! -e $STATE_FILE ]; then
|
||||
echo "Error: TPM state file $STATE_FILE does not exist."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "OK"
|
||||
|
||||
exit 0
|
||||
Loading…
Reference in New Issue
Block a user