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. # Kill a process quietly # @1: signal, e.g. -9 # @2: pid function kill_quiet() { local sig="$1" local pid="$2" bash -c "kill $sig $pid &>/dev/null" return $? } # Wait for a regular file to appear; give the process 0.2s to write # into the file # # @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/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/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 } # Must first close on OS/X exec 100>&- 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() { case "$(uname -s)" in Linux|CYGWIN*) sha1sum $1 | cut -f1 -d" " ;; Darwin) shasum $1 | cut -f1 -d" " ;; *) # OpenBSD sha1 $1 | cut -d "=" -f2 | tr -d " " esac } # Display process that have the same name # # @1: process name to match function display_processes_by_name() { local name="$1" if [ 1 -eq 0 ]; then ps aux | grep "${name}" | grep -v grep fi }