blob: c53b8e3ae5bb06481570fd14f95cf831cd25d80a [file] [log] [blame]
DIR=$(dirname "$0")
ROOT=${DIR}/..
SWTPM=swtpm
SWTPM_EXE=${SWTPM_EXE:-${ROOT}/src/swtpm/${SWTPM}}
SWTPM_IOCTL=${SWTPM_IOCTL:-${ROOT}/src/swtpm_ioctl/swtpm_ioctl}
SWTPM_BIOS=${SWTPM_BIOS:-${ROOT}/src/swtpm_bios/swtpm_bios}
ECHO=$(type -P echo)
# Note: Do not use file descriptors above 127 due to OpenBSD.
# Wait for a regular file to appear
#
# @1: filename
# @2: timeout in seconds
function wait_for_file()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -f "${filename}" ] && return 1
sleep 0.1
done
return 0
}
# Wait for a regular file to disappear
#
# @1: filename
# @2: timeout in seconds
function wait_file_gone()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -f "${filename}" ] || return 1
sleep 0.1
done
return 0
}
# Wait for a chardev to appear
#
# @1: filename
# @2: timeout in seconds
function wait_for_chardev()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -c "${filename}" ] && return 1
sleep 0.1
done
return 0
}
# Wait for a chardev to disappear
#
# @1: filename
# @2: timeout in seconds
function wait_chardev_gone()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -c "${filename}" ] || return 1
sleep 0.1
done
return 0
}
# Wait for a socket file to appear
#
# @1: filename
# @2: timeout in seconds
function wait_for_socketfile()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -S "${filename}" ] && return 1
sleep 0.1
done
return 0
}
# Wait for a socket file to disappear
#
# @1: filename
# @2: timeout in seconds
function wait_socketfile_gone()
{
local filename="$1"
local timeout="$2"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
[ -S "${filename}" ] || return 1
sleep 0.1
done
return 0
}
# Wait for a server socket to appear
#
# @1: port
# @2: host
# @3: timeout in seconds
function wait_for_serversocket()
{
local port="$1"
local host="$2"
local timeout="$3"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
(exec 127<>/dev/tcp/${host}/${port}) &>/dev/null
[ $? -eq 0 ] && return 1
sleep 0.1
done
return 0
}
# Wait for a server socket to disappear
#
# @1: port
# @2: host
# @3: timeout in seconds
function wait_serversocket_gone()
{
local port="$1"
local host="$2"
local timeout="$3"
local loops=$((timeout * 10)) loop
for ((loop=0; loop<loops; loop++)); do
(exec 127<>/dev/tcp/${host}/${port}) &>/dev/null
[ $? -eq 0 ] || return 1
sleep 0.1
done
return 0
}
# Run the swtpm_ioctl command
#
# @param1: type of interface
function run_swtpm_ioctl()
{
local iface=$1; shift
case "${iface}" in
cuse)
[ -z "${SWTPM_DEV_NAME}" ] && {
echo "SWTPM_DEV_NAME not defined"
exit 1
}
${SWTPM_IOCTL} $@ ${SWTPM_DEV_NAME}
return $?
;;
socket+socket|unix+socket)
[ -z "${SWTPM_SERVER_NAME}" ] && {
echo "SWTPM_SERVER_NAME not defined"
exit 1
}
[ -z "${SWTPM_SERVER_PORT}" ] && {
echo "SWTPM_SERVER_PORT not defined"
exit 1
}
${SWTPM_IOCTL} \
--tcp ${SWTPM_SERVER_NAME}:${SWTPM_CTRL_PORT} \
$@
return $?
;;
socket+unix|unix+unix)
[ -z "${SWTPM_CTRL_UNIX_PATH}" ] && {
echo "SWTPM_CTRL_UNIX_PATH not defined"
exit 1
}
${SWTPM_IOCTL} \
--unix ${SWTPM_CTRL_UNIX_PATH} \
$@
return $?
;;
esac
}
# Start the swtpm in the background
#
# @param1: type of interface
# @param2.. : parameters to pass to 'swtpm'
function run_swtpm()
{
local iface=$1; shift
echo "==== Starting swtpm with interfaces ${iface} ===="
case "${iface}" in
cuse)
[ -z "${SWTPM_DEV_NAME}" ] && {
echo "SWTPM_DEV_NAME not defined"
exit 1
}
if wait_chardev_gone ${SWTPM_DEV_NAME} 2; then
echo "${SWTPM_DEV_NAME} is still there and may be used."
exit 1
fi
${SWTPM_EXE} cuse $@ -n ${SWTPM_DEV_NAME##*/}
rc=$?
if [ $rc -ne 0 ]; then
echo "Could not run ${SWTPM_EXE} using ${iface}"
exit 1
fi
if wait_for_chardev ${SWTPM_DEV_NAME} 2; then
echo "$SWTPM_DEV_NAME did not appear"
exit 1
fi
SWTPM_PID=$(ps aux |
grep "cuse" |
grep -E " ${SWTPM_DEV_NAME##*/}\$" |
grep -v grep |
gawk '{print $2}')
return $?
;;
socket+socket)
[ -z "${SWTPM_SERVER_PORT}" ] && {
echo "SWTPM_SERVER_PORT not defined"
exit 1
}
[ -z "${SWTPM_CTRL_PORT}" ] && {
echo "SWTPM_CTRL_PORT not defined"
exit 1
}
if wait_serversocket_gone "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then
echo "Port ${SWTPM_SERVER_PORT} is still used"
exit 1
fi
if wait_serversocket_gone "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then
echo "Port ${SWTPM_CTRL_PORT} is still used"
exit 1
fi
${SWTPM_EXE} socket $@ \
--server type=tcp,port=${SWTPM_SERVER_PORT},disconnect \
--ctrl type=tcp,port=${SWTPM_CTRL_PORT} &
rc=$?
if [ $rc -ne 0 ]; then
echo "Could not run ${SWTPM_EXE} using ${iface}"
exit 1
fi
SWTPM_PID=$!
if wait_for_serversocket "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then
echo "Server did not open port ${SWTPM_SERVER_PORT}"
kill -9 ${SWTPM_PID}
exit 1
fi
if wait_for_serversocket "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then
echo "Server did not open port ${SWTPM_CTRL_PORT}"
kill -9 ${SWTPM_PID}
exit 1
fi
return 0
;;
socket+unix)
[ -z "${SWTPM_SERVER_PORT}" ] && {
echo "SWTPM_SERVER_PORT not defined"
exit 1
}
[ -z "${SWTPM_CTRL_UNIX_PATH}" ] && {
echo "SWTPM_CTRL_UNIX_PATH not defined"
exit 1
}
if wait_serversocket_gone "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then
echo "Port ${SWTPM_SERVER_PORT} is still used"
exit 1
fi
if wait_socketfile_gone "${SWTPM_CTRL_UNIX_PATH}" 2; then
echo "Unix socket ${SWTPM_CTRL_UNIX_PATH} is still there"
exit 1
fi
${SWTPM_EXE} socket $@ \
--server type=tcp,port=${SWTPM_SERVER_PORT},disconnect \
--ctrl type=unixio,path=${SWTPM_CTRL_UNIX_PATH} &
rc=$?
if [ $rc -ne 0 ]; then
echo "Could not run ${SWTPM_EXE} using ${iface}"
exit 1
fi
[ $rc -ne 0 ] && return $rc
SWTPM_PID=$!
if wait_for_serversocket "${SWTPM_SERVER_PORT}" 127.0.0.1 2; then
echo "Server did not open port ${SWTPM_SERVER_PORT}"
kill -9 ${SWTPM_PID}
exit 1
fi
if wait_for_socketfile ${SWTPM_CTRL_UNIX_PATH} 1; then
echo "Server did not create UnixIO socket ${SWTPM_CTRL_UNIX_PATH}"
kill -9 ${SWTPM_PID}
exit 1
fi
return 0
;;
unix+socket)
[ -z "${SWTPM_CMD_UNIX_PATH}" ] && {
echo "SWTPM_CMD_UNIX_PATH not defined"
exit 1
}
[ -z "${SWTPM_CTRL_PORT}" ] && {
echo "SWTPM_CTRL_PORT not defined"
exit 1
}
if wait_socketfile_gone "${SWTPM_CMD_UNIX_PATH}" 2; then
echo "Unix socket ${SWTPM_CMD_UNIX_PATH} is still there"
exit 1
fi
if wait_serversocket_gone "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then
echo "Port ${SWTPM_CTRL_PORT} is still used"
exit 1
fi
${SWTPM_EXE} socket $@ \
--server type=unixio,path=${SWTPM_CMD_UNIX_PATH} \
--ctrl type=tcp,port=${SWTPM_CTRL_PORT} &
rc=$?
if [ $rc -ne 0 ]; then
echo "Could not run ${SWTPM_EXE} using ${iface}"
exit 1
fi
SWTPM_PID=$!
if wait_for_socketfile ${SWTPM_CMD_UNIX_PATH} 2; then
echo "Server did not create UnixIO socket ${SWTPM_CMD_UNIX_PATH}"
kill -9 ${SWTPM_PID}
exit 1
fi
if wait_for_serversocket "${SWTPM_CTRL_PORT}" 127.0.0.1 1; then
echo "Server did not open port ${SWTPM_CTRL_PORT}"
kill -9 ${SWTPM_PID}
exit 1
fi
return 0
;;
unix+unix)
[ -z "${SWTPM_CMD_UNIX_PATH}" ] && {
echo "SWTPM_CMD_UNIX_PATH not defined"
exit 1
}
[ -z "${SWTPM_CTRL_UNIX_PATH}" ] && {
echo "SWTPM_CTRL_UNIX_PATH not defined"
exit 1
}
if wait_socketfile_gone "${SWTPM_CMD_UNIX_PATH}" 2; then
echo "Unix socket ${SWTPM_CMD_UNIX_PATH} is still there"
exit 1
fi
if wait_socketfile_gone "${SWTPM_CTRL_UNIX_PATH}" 2; then
echo "Unix socket ${SWTPM_CTRL_UNIX_PATH} is still there"
exit 1
fi
${SWTPM_EXE} socket $@ \
--server type=unixio,path=${SWTPM_CMD_UNIX_PATH} \
--ctrl type=unixio,path=${SWTPM_CTRL_UNIX_PATH} &
rc=$?
if [ $rc -ne 0 ]; then
echo "Could not run ${SWTPM_EXE} using ${iface}"
exit 1
fi
SWTPM_PID=$!
if wait_for_socketfile ${SWTPM_CMD_UNIX_PATH} 2; then
echo "Server did not create UnixIO socket ${SWTPM_CMD_UNIX_PATH}"
kill -9 ${SWTPM_PID}
exit 1
fi
if wait_for_socketfile ${SWTPM_CTRL_UNIX_PATH} 1; then
echo "Server did not create UnixIO socket ${SWTPM_CTRL_UNIX_PATH}"
kill -9 ${SWTPM_PID}
exit 1
fi
return 0
;;
esac
}
# Open the command channel/device on fd 100
#
# @param1: type of interface
# @param2: must be '100'
function swtpm_open_cmddev()
{
local iface=$1; shift
[ "$1" != "100" ] && {
echo "swtpm_opendev: Filedescriptor must be 100"
exit 1
}
case "${iface}" in
cuse)
[ -z "${SWTPM_DEV_NAME}" ] && {
echo "SWTPM_DEV_NAME not defined"
exit 1
}
exec 100<>${SWTPM_DEV_NAME}
return $?
;;
socket+socket|socket+unix)
[ -z "${SWTPM_SERVER_NAME}" ] && {
echo "SWTPM_SERVER_NAME not defined"
exit 1
}
[ -z "${SWTPM_SERVER_PORT}" ] && {
echo "SWTPM_SERVER_PORT not defined"
exit 1
}
exec 100<>/dev/tcp/${SWTPM_SERVER_NAME}/${SWTPM_SERVER_PORT}
return $?
;;
unix+socket|unix+unix)
;;
*)
echo "swtpm_opendev: unsupported interface $iface"
exit 1
esac
}
# Transmit a command on fd 100
#
# @param1: type of interface
function swtpm_cmd_tx()
{
local iface=$1
local cmd_path resp_path
cmd_path=$(mktemp)
case "${iface}" in
cuse)
echo -en "$2" > ${cmd_path}
cat ${cmd_path} >&100
dd if=/proc/self/fd/100 2>/dev/null | \
od -t x1 -A n | \
tr -s ' ' | \
tr -d '\n' | \
sed 's/ $//g'
;;
socket+socket|socket+unix)
echo -en "$2" > ${cmd_path}
cat ${cmd_path} >&100
cat <&100 | od -t x1 -A n | \
tr -s ' ' | \
tr -d '\n' | \
sed 's/ $//g'
;;
unix+socket|unix+unix)
echo -en "$2" > ${cmd_path}
socat -x -t50 \
FILE:${cmd_path},rdonly \
UNIX-CLIENT:${SWTPM_CMD_UNIX_PATH} 2>&1 | \
sed -n '/^ /p' | \
tail -n1
;;
*)
echo "swtpm_opendev: unsupported interface $iface"
rm -f ${cmd_path}
exit 1
esac
rm -f ${cmd_path}
}
# Transmit a control command on fd 101
#
# @param1: type of interface
function swtpm_ctrl_tx()
{
local iface=$1
local ctrl_path resp_path
case "${iface}" in
socket+socket|unix+socket)
$ECHO -en "$2" >&101
cat <&101 | od -t x1 -A n -w128
;;
socket+unix|unix+unix)
ctrl_path=$(mktemp)
echo -en "$2" > ${ctrl_path}
socat -x -t50 \
FILE:${ctrl_path},rdonly \
UNIX-CLIENT:${SWTPM_CTRL_UNIX_PATH} 2>&1 | \
sed -n '/^ /p' | \
tail -n1
rm -f ${ctrl_path}
;;
*)
echo "swtpm_opendev: unsupported interface $iface"
exit 1
esac
}
# Run swtpm_bios
#
# @param1: type of interface
# @param2 ...: parameters to pass to swtpm_bios
function run_swtpm_bios()
{
local iface=$1
shift
case "${iface}" in
cuse)
[ -z "${SWTPM_DEV_NAME}" ] && {
echo "SWTPM_DEV_NAME not defined"
exit 1
}
${SWTPM_BIOS} --tpm-device ${SWTPM_DEV_NAME} $@
return $?
;;
unix+unix|unix+socket)
[ -z "${SWTPM_CMD_UNIX_PATH}" ] && {
echo "SWTPM_CMD_UNIX_PATH not defined"
exit 1
}
${SWTPM_BIOS} --unix ${SWTPM_CMD_UNIX_PATH} $@
return $?
;;
socket+unix|socket+socket)
[ -z "${SWTPM_SERVER_PORT}" ] && {
echo "SWTPM_SERVER_PORT not defined"
exit 1
}
${SWTPM_BIOS} --tcp ${SWTPM_SERVER_NAME}:${SWTPM_SERVER_PORT} $@
return $?
;;
*)
echo "run_swtpm_bios: unsupported interface $iface"
exit 1
esac
}
# Get the size of a file in bytes
#
# @1: filename
function get_filesize()
{
if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then
stat -c%s $1
else
# OpenBSD
stat -f%z $1
fi
}
# Get the SHA1 of a file
#
# @1: filename
function get_sha1_file()
{
if [[ "$(uname -s)" =~ (Linux|CYGWIN_NT-) ]]; then
sha1sum $1 | cut -f1 -d" "
else
# OpenBSD
sha1 $1 | cut -d "=" -f2 | tr -d " "
fi
}