Extend swtpm_bios with --tpm2 to support a TPM 2

Extend the swtpm_bios tool with a --tpm2 command line parameter
to support TPM 2 initialization.

Signed-off-by: Stefan Berger <stefanb@linux.vnet.ibm.com>
This commit is contained in:
Stefan Berger 2016-12-21 17:03:19 -05:00
parent 3008874c91
commit 8fcec541f8
7 changed files with 546 additions and 123 deletions

View File

@ -133,7 +133,7 @@
.\" ========================================================================
.\"
.IX Title "swtpm_bios 8"
.TH swtpm_bios 8 "2016-04-18" "swtpm" ""
.TH swtpm_bios 8 "2016-07-05" "swtpm" ""
.\" For nroff, turn off justification. Always turn off hyphenation; it makes
.\" way too many mistakes in technical documents.
.if n .ad l
@ -197,6 +197,9 @@ if port is not given, the default port 6545 is used.
.IP "\fB\-\-unixio <path>\fR" 4
.IX Item "--unixio <path>"
Connect to the given UnixIO path.
.IP "\fB\-tpm2\fR" 4
.IX Item "-tpm2"
The device is a \s-1TPM 2.\s0
.IP "\fB\-c\fR" 4
.IX Item "-c"
Send TPM_Startup(\s-1ST_CLEAR\s0) (default). This instructs the \s-1TPM\s0 to start
@ -208,7 +211,7 @@ previously saved state.
.IP "\fB\-d\fR" 4
.IX Item "-d"
Send TPM_Startup(\s-1ST_DEACTIVATED\s0). This instructs the \s-1TPM\s0 to start in
deactivated mode.
deactivated mode. This option has no effect on a \s-1TPM 2.\s0
.IP "\fB\-n\fR" 4
.IX Item "-n"
Don't send a TPM_Startup command.
@ -221,10 +224,12 @@ Make sure that the \s-1TPM\s0 is activated; if the \s-1TPM\s0 requires a reset,
will exist and return a return code of 129.
.IP "\fB\-cs\fR" 4
.IX Item "-cs"
Send a TPM_ContinueSelfTest command.
Send a TPM_ContinueSelfTest command to a \s-1TPM 1.2\s0 and a TPM2_IncrementalSelfTest
command to a \s-1TPM 2.\s0
.IP "\fB\-u\fR" 4
.IX Item "-u"
Give up physical presence.
Give up physical presence on a \s-1TPM 1.2.\s0 In case of a \s-1TPM 2\s0 set the platform
hierarchy to a random password.
.IP "\fB\-v\fR" 4
.IX Item "-v"
Display version and exit.

View File

@ -68,6 +68,10 @@ if port is not given, the default port 6545 is used.
Connect to the given UnixIO path.
=item B<-tpm2>
The device is a TPM 2.
=item B<-c>
Send TPM_Startup(ST_CLEAR) (default). This instructs the TPM to start
@ -81,7 +85,7 @@ previously saved state.
=item B<-d>
Send TPM_Startup(ST_DEACTIVATED). This instructs the TPM to start in
deactivated mode.
deactivated mode. This option has no effect on a TPM 2.
=item B<-n>
@ -98,11 +102,13 @@ will exist and return a return code of 129.
=item B<-cs>
Send a TPM_ContinueSelfTest command.
Send a TPM_ContinueSelfTest command to a TPM 1.2 and a TPM2_IncrementalSelfTest
command to a TPM 2.
=item B<-u>
Give up physical presence.
Give up physical presence on a TPM 1.2. In case of a TPM 2 set the platform
hierarchy to a random password.
=item B<-v>

View File

@ -383,130 +383,91 @@ static int TPM_ContinueSelfTest(int *tpm_errcode)
NULL, 0);
}
static void versioninfo(void)
static int TPM2_Startup(unsigned short startup_type, int *tpm_errcode)
{
printf(
"TPM emulator BIOS emulator version %d.%d.%d, Copyright (c) 2015 IBM Corp.\n"
,SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO);
struct tpm2_startup ts = {
.hdr = {
.tag = htobe16(TPM2_ST_NO_SESSIONS),
.length = htobe32(sizeof(ts)),
.ordinal = htobe32(TPM2_CC_Startup),
},
.startup_type = htobe16(startup_type),
};
return talk(&ts, sizeof(ts), tpm_errcode,
TPM_DURATION_SHORT, NULL, 0);
}
static void print_usage(const char *prgname)
static int TPM2_IncrementalSelfTest(int *tpm_errcode)
{
versioninfo();
printf(
"\n"
"%s [options]\n"
"\n"
"Runs TPM_Startup (unless -n), then (unless -o) sets PP, enable, activate \n"
"and finally (using -u) gives up physical presence (PP)\n"
"\n"
"The following options are supported:\n"
"\t--tpm-device <device> use the given device; default is /dev/tpm0\n"
"\t--tcp [<host>]:[<prt>] connect to TPM on given host and port;\n"
"\t default host is 127.0.0.1, default port is %u\n"
"\t--unix <path> connect to TPM using UnixIO socket\n"
"\t-c startup clear (default)\n"
"\t-s startup state\n"
"\t-d startup deactivate\n"
"\t-n no startup\n"
"\t-o startup only\n"
"\t-cs run TPM_ContinueSelfTest\n"
"\t-ea make sure that the TPM is activated; terminate\n"
"\t with exit code 129 if the TPM needs to be reset\n"
"\t-u give up physical presence\n"
"\t-v display version and exit\n"
"\t-h display this help screen and exit\n"
, prgname, DEFAULT_TCP_PORT);
struct tpm2_incremental_selftest ts = {
.hdr = {
.tag = htobe16(TPM2_ST_NO_SESSIONS),
.length = htobe32(sizeof(ts)),
.ordinal = htobe32(TPM2_CC_IncrementalSelfTest),
},
.to_test = {
.num_entries = htobe32(1),
.algids = {
htobe16(TPM2_ALG_SHA1),
},
},
};
return talk(&ts, sizeof(ts), tpm_errcode,
TPM_DURATION_SHORT, NULL, 0);
}
int main(int argc, char *argv[])
static int TPM2_HierarchyChangeAuth(int *tpm_errcode)
{
int ret = 0;
int do_more = 1;
int ensure_activated = 0;
int contselftest = 0;
unsigned char startupparm = TPM_ST_CLEAR; /* parameter for TPM_Startup(); */
int tpm_errcode = 0;
int unassert_pp = 0;
int tpm_error = 0;
struct tpm2_hierarchy_change_auth thca = {
.hdr = {
.tag = htobe16(TPM2_ST_SESSIONS),
.length = htobe32(sizeof(thca)),
.ordinal = htobe32(TPM2_CC_HierarchyChangeAuth),
},
.authhandle = htobe32(TPM2_RH_PLATFORM),
.authblock_size = htobe32(sizeof(thca.authblock)),
.authblock = {
.handle = htobe32(TPM2_RS_PW),
.nonce_size = htobe16(0),
.cont = 1,
.password_size = htobe16(0),
},
.newauth = {
.size = htobe16(sizeof(thca.newauth.buffer)),
},
};
int fd = open("/dev/urandom", O_RDONLY);
if (fd >= 0) {
ssize_t n = read(fd, &thca.newauth.buffer,
sizeof(thca.newauth.buffer));
close(fd);
if (n != sizeof(thca.newauth.buffer)) {
printf("Read of bytes from /dev/urandom failed");
if (n < 0)
printf(": %s", strerror(errno));
printf("\n");
return -1;
}
} else {
printf("Could not open /dev/urandom: %s\n", strerror(errno));
return -1;
}
return talk(&thca, sizeof(thca), tpm_errcode,
TPM_DURATION_SHORT, NULL, 0);
}
static int tpm12_bios(int do_more, int contselftest, unsigned char startupparm,
int unassert_pp, int ensure_activated)
{
int ret = 0;
int tpm_errcode;
int tpm_error = 0;
unsigned short physical_presence;
struct tpm_get_capability_permflags_res perm_flags;
static struct option long_options[] = {
{"tpm-device", required_argument, NULL, 'D'},
{"tcp", required_argument, NULL, 'T'},
{"unix", required_argument, NULL, 'U'},
{"c", no_argument, NULL, 'c'},
{"d", no_argument, NULL, 'd'},
{"h", no_argument, NULL, 'h'},
{"v", no_argument, NULL, 'v'},
{"n", no_argument, NULL, 'n'},
{"s", no_argument, NULL, 's'},
{"o", no_argument, NULL, 'o'},
{"cs", no_argument, NULL, 'C'},
{"ea", no_argument, NULL, 'E'},
{"u", no_argument, NULL, 'u'},
{NULL, 0, NULL, 0},
};
int opt, option_index = 0;
while ((opt = getopt_long_only(argc, argv, "", long_options,
&option_index)) != -1) {
switch (opt) {
case 'D':
tpm_device = strdup(optarg);
if (!tpm_device) {
fprintf(stderr, "Out of memory.");
return EXIT_FAILURE;
}
break;
case 'T':
if (parse_tcp_optarg(optarg, &tcp_hostname, &tcp_port) < 0) {
return EXIT_FAILURE;
}
break;
case 'U':
unix_path = strdup(optarg);
if (!unix_path) {
fprintf(stderr, "Out of memory.\n");
return EXIT_FAILURE;
}
break;
case 'c':
startupparm = TPM_ST_CLEAR;
do_more = 1;
break;
case 'd':
startupparm = TPM_ST_DEACTIVATED;
do_more = 0;
break;
case 'h':
print_usage(argv[0]);
return EXIT_SUCCESS;
case 'n':
startupparm = 0xff;
do_more = 1;
break;
case 's':
startupparm = TPM_ST_STATE;
do_more = 1;
break;
case 'o':
do_more = 0;
break;
case 'C':
contselftest = 1;
break;
case 'E':
ensure_activated = 1;
break;
case 'u':
unassert_pp = 1;
break;
default:
print_usage(argv[0]);
return EXIT_FAILURE;
}
}
if (ret == 0) {
if (0xff != startupparm) {
@ -617,3 +578,191 @@ int main(int argc, char *argv[])
return ret;
}
static int tpm2_bios(int do_more, int contselftest, unsigned char startupparm,
int set_password)
{
int ret = 0;
int tpm_errcode;
int tpm_error = 0;
if (ret == 0) {
if (0xff != startupparm) {
ret = TPM2_Startup(startupparm, &tpm_errcode);
if (tpm_errcode != 0) {
tpm_error = 1;
printf("TPM2_Startup returned error code "
"0x%08x\n", tpm_errcode);
}
}
}
if ((ret == 0) && contselftest) {
ret = TPM2_IncrementalSelfTest(&tpm_errcode);
if (tpm_errcode != 0) {
tpm_error = 1;
printf("TPM2_ImcrementalSelfTest returned error "
"code 0x%08x\n", tpm_errcode);
}
}
if ((ret == 0) && set_password) {
ret = TPM2_HierarchyChangeAuth(&tpm_errcode);
if (tpm_errcode != 0) {
tpm_error = 1;
printf("TPM2_HierarchyChangeAuth returned error "
"code 0x%08x\n", tpm_errcode);
}
}
if (!ret && tpm_error)
ret = 0x80;
return ret;
}
static void versioninfo(void)
{
printf(
"TPM emulator BIOS emulator version %d.%d.%d, Copyright (c) 2015 IBM Corp.\n"
,SWTPM_VER_MAJOR, SWTPM_VER_MINOR, SWTPM_VER_MICRO);
}
static void print_usage(const char *prgname)
{
versioninfo();
printf(
"\n"
"%s [options]\n"
"\n"
"Runs TPM_Startup (unless -n), then (unless -o) sets PP, enable, activate \n"
"and finally (using -u) gives up physical presence (PP)\n"
"\n"
"The following options are supported:\n"
"\t--tpm-device <device> use the given device; default is /dev/tpm0\n"
"\t--tcp [<host>]:[<prt>] connect to TPM on given host and port;\n"
"\t default host is 127.0.0.1, default port is %u\n"
"\t--unix <path> connect to TPM using UnixIO socket\n"
"\t--tpm2 initialize a TPM2\n"
"\t-c startup clear (default)\n"
"\t-s startup state\n"
"\t-d startup deactivate (no effect on TPM2)\n"
"\t-n no startup\n"
"\t-o startup only\n"
"\t-cs run TPM_ContinueSelfTest on TPM1.2\n"
"\t run TPM2_IncrementalSelfTest on TPM2\n"
"\t-ea make sure that the TPM 1.2 is activated;\n"
"\t terminate with exit code 129 if the TPM\n"
"\t needs to be reset\n"
"\t-u give up physical presence\n"
"\t on TPM 2 set the platform hierachy to a\n"
"\t random password\n"
"\t-v display version and exit\n"
"\t-h display this help screen and exit\n"
, prgname, DEFAULT_TCP_PORT);
}
int main(int argc, char *argv[])
{
int ret = 0;
int do_more = 1;
int ensure_activated = 0;
int contselftest = 0;
unsigned char startupparm = 0x1; /* parameter for TPM_Startup(); */
unsigned char startupparm_tpm2 = 0x00;
int unassert_pp = 0;
int tpm2 = 0;
static struct option long_options[] = {
{"tpm-device", required_argument, NULL, 'D'},
{"tcp", required_argument, NULL, 'T'},
{"unix", required_argument, NULL, 'U'},
{"c", no_argument, NULL, 'c'},
{"d", no_argument, NULL, 'd'},
{"h", no_argument, NULL, 'h'},
{"v", no_argument, NULL, 'v'},
{"n", no_argument, NULL, 'n'},
{"s", no_argument, NULL, 's'},
{"o", no_argument, NULL, 'o'},
{"cs", no_argument, NULL, 'C'},
{"ea", no_argument, NULL, 'E'},
{"u", no_argument, NULL, 'u'},
{"tpm2", no_argument, NULL, '2'},
{NULL, 0, NULL, 0},
};
int opt, option_index = 0;
while ((opt = getopt_long_only(argc, argv, "", long_options,
&option_index)) != -1) {
switch (opt) {
case 'D':
tpm_device = strdup(optarg);
if (!tpm_device) {
fprintf(stderr, "Out of memory.");
return EXIT_FAILURE;
}
break;
case 'T':
if (parse_tcp_optarg(optarg, &tcp_hostname, &tcp_port) < 0) {
return EXIT_FAILURE;
}
break;
case 'U':
unix_path = strdup(optarg);
if (!unix_path) {
fprintf(stderr, "Out of memory.\n");
return EXIT_FAILURE;
}
break;
case 'c':
startupparm = TPM_ST_CLEAR;
startupparm_tpm2 = TPM2_SU_CLEAR;
do_more = 1;
break;
case 'd':
startupparm = TPM_ST_DEACTIVATED;
startupparm_tpm2 = 0xff;
do_more = 0;
break;
case 'h':
print_usage(argv[0]);
return EXIT_SUCCESS;
case 'n':
startupparm = 0xff;
startupparm_tpm2 = 0xff;
do_more = 1;
break;
case 's':
startupparm = TPM_ST_STATE;
startupparm_tpm2 = TPM2_SU_STATE;
do_more = 1;
break;
case 'o':
do_more = 0;
break;
case 'C':
contselftest = 1;
break;
case 'E':
ensure_activated = 1;
break;
case 'u':
unassert_pp = 1;
break;
case '2':
tpm2 = 1;
break;
default:
print_usage(argv[0]);
return EXIT_FAILURE;
}
}
if (tpm2) {
ret = tpm2_bios(do_more, contselftest, startupparm_tpm2,
unassert_pp);
} else {
ret = tpm12_bios(do_more, contselftest, startupparm,
unassert_pp, ensure_activated);
}
return ret;
}

View File

@ -117,4 +117,59 @@ struct tpm_get_capability_permflags_res {
uint8_t flags[20];
} __attribute__((packed));
/* constants for TPM 2 */
#define TPM2_ST_NO_SESSIONS 0x8001
#define TPM2_ST_SESSIONS 0x8002
#define TPM2_CC_HierarchyChangeAuth 0x00000129
#define TPM2_CC_IncrementalSelfTest 0x00000142
#define TPM2_CC_Startup 0x00000144
#define TPM2_SU_CLEAR 0x0000
#define TPM2_SU_STATE 0x0001
#define TPM2_ALG_SHA1 0x0004
#define TPM2_RS_PW 0x40000009
#define TPM2_RH_PLATFORM 0x4000000c
/* data structures for TPM 2 */
struct tpm2_startup {
struct tpm_header hdr;
uint16_t startup_type;
} __attribute__((packed));
struct tpm2l_alg_1_entry {
uint32_t num_entries;
uint16_t algids[1];
} __attribute__((packed));
struct tpm2_incremental_selftest {
struct tpm_header hdr;
struct tpm2l_alg_1_entry to_test;
} __attribute__((packed));
struct tpm2_authblock {
uint32_t handle;
uint16_t nonce_size;
uint8_t cont;
uint16_t password_size;
} __attribute__((packed));
struct tpm2b_20 {
uint16_t size;
uint8_t buffer[20];
} __attribute__((packed));
struct tpm2_hierarchy_change_auth {
struct tpm_header hdr;
uint32_t authhandle;
uint32_t authblock_size;
struct tpm2_authblock authblock;
struct tpm2b_20 newauth;
} __attribute__((packed));
#endif /* _SWTPM_BIOS_H */

View File

@ -45,7 +45,9 @@ TESTS += \
test_tpm2_savestate \
test_tpm2_setbuffersize \
test_tpm2_wrongorder \
test_tpm2_probe
test_tpm2_probe \
\
test_tpm2_swtpm_bios
if WITH_SWTPM_SETUP
TESTS += \
@ -108,6 +110,7 @@ EXTRA_DIST=$(TESTS) \
_test_tpm2_probe \
_test_tpm2_savestate \
_test_tpm2_setbuffersize \
_test_tpm2_swtpm_bios \
_test_tpm2_wrongorder \
_test_volatilestate \
_test_wrongorder

168
tests/_test_tpm2_swtpm_bios Executable file
View File

@ -0,0 +1,168 @@
#!/bin/bash
# For the license, see the LICENSE file in the root directory.
#set -x
DIR=$(dirname "$0")
ROOT=${DIR}/..
VTPM_NAME="vtpm-test-tpm2-swtpm-bios"
SWTPM_DEV_NAME="/dev/${VTPM_NAME}"
TPM_PATH=$(mktemp -d)
STATE_FILE=$TPM_PATH/tpm2-00.permall
VOLATILE_STATE_FILE=$TPM_PATH/tpm-00.volatilestate
PID_FILE=$TPM_PATH/${SWTPM}.pid
SWTPM_INTERFACE=${SWTPM_INTERFACE:-cuse}
SWTPM_CMD_UNIX_PATH=${TPM_PATH}/unix-cmd.sock
SWTPM_CTRL_UNIX_PATH=${TPM_PATH}/unix-ctrl.sock
function cleanup()
{
pid=${SWTPM_PID}
if [ -n "$pid" ]; then
kill -9 $pid
fi
rm -rf $TPM_PATH
}
trap "cleanup" EXIT
[ "${SWTPM_INTERFACE}" == "cuse" ] && source ${DIR}/test_cuse
source ${DIR}/common
rm -f $STATE_FILE $VOLATILE_STATE_FILE 2>/dev/null
run_swtpm ${SWTPM_INTERFACE} --tpm2 --tpmstate dir=$TPM_PATH --pid file=$PID_FILE
ps aux | grep $SWTPM | grep -v grep
kill -0 ${SWTPM_PID}
if [ $? -ne 0 ]; then
echo "Error: ${SWTPM_INTERFACE} TPM did not start."
exit 1
fi
if [ ! -r $PID_FILE ]; then
echo "Error: ${SWTPM_INTERFACE} TPM did not write pidfile."
exit 1
fi
PIDF="$(cat $PID_FILE)"
if [ "$PIDF" != "${SWTPM_PID}" ]; then
echo "Error: ${SWTPM_INTERFACE} TPM wrote pid $PIDF, but found ${SWTPM_PID}."
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
sleep 0.5
kill -0 ${SWTPM_PID} 2>/dev/null
if [ $? -ne 0 ]; then
echo "Error: ${SWTPM_INTERFACE} TPM not running anymore after INIT."
exit 1
fi
# must work
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -o 2>&1)
if [ $? -ne 0 ] || [ -n "$res" ]; then
echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM."
exit 1
fi
# must work
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -cs 2>&1)
if [ $? -ne 0 ] || [ -n "$res" ]; then
echo "Error: Could not self-test the ${SWTPM_INTERFACE} TPM."
exit 1
fi
# must work
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1)
if [ $? -ne 0 ] || [ -n "$res" ]; then
echo "Error: Could not give up physical presence on the ${SWTPM_INTERFACE} TPM."
exit 1
fi
# will NOT work -- we get error output in $res
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1)
ret=$?
if [ $ret -eq 0 ] || [ -z "$res" ]; then
echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM."
exit 1
fi
if [ $ret -ne 128 ]; then
echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret."
exit 1
fi
# will NOT work (wrong device) -- we get error output in $res
if [ "${SWTPM_INTERFACE}" == "cuse" ]; then
res=$($SWTPM_BIOS --tpm-device /dev/${VTPM_NAME}123--tpm2 -n -u 2>&1)
ret=$?
if [ $ret -eq 0 ] || [ -z "$res" ]; then
echo "Error: Could give up physical presence on wrong device."
exit 1
fi
if [ $ret -ne 255 ]; then
echo "Error: Wrong return code from swtpm_bios. Should be 255, had $ret."
exit 1
fi
fi
# RESET TPM
run_swtpm_ioctl ${SWTPM_INTERFACE} -i
if [ $? -ne 0 ]; then
echo "Error: Could not initialize the ${SWTPM_INTERFACE} TPM."
exit 1
fi
# must work
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -cs -u 2>&1)
if [ $? -ne 0 ] || [ -n "$res" ]; then
echo "Error: Could not startup the ${SWTPM_INTERFACE} TPM."
exit 1
fi
# will NOT work -- we get error output in $res
res=$(run_swtpm_bios ${SWTPM_INTERFACE} --tpm2 -n -u 2>&1)
ret=$?
if [ $ret -eq 0 ] || [ -z "$res" ]; then
echo "Error: Could give up physical presence on the ${SWTPM_INTERFACE} TPM."
exit 1
fi
if [ $ret -ne 128 ]; then
echo "Error: Wrong return code from swtpm_bios. Should be 128, had $ret."
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
sleep 0.5
kill -0 ${SWTPM_PID} 2>/dev/null
if [ $? -eq 0 ]; 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

37
tests/test_tpm2_swtpm_bios Executable file
View File

@ -0,0 +1,37 @@
#!/bin/bash
cd "$(dirname "$0")"
export SWTPM_IOCTL_BUFFERSIZE=100
export SWTPM_INTERFACE=cuse
bash _test_tpm2_swtpm_bios
ret=$?
[ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret
export SWTPM_IOCTL_BUFFERSIZE=4096
export SWTPM_INTERFACE=cuse
bash _test_tpm2_swtpm_bios
ret=$?
[ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret
export SWTPM_INTERFACE=socket+socket
export SWTPM_SERVER_NAME=localhost
export SWTPM_SERVER_PORT=65520
export SWTPM_CTRL_PORT=65521
bash _test_tpm2_swtpm_bios
ret=$?
[ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret
export SWTPM_INTERFACE=socket+unix
export SWTPM_SERVER_NAME=localhost
export SWTPM_SERVER_PORT=65520
bash _test_tpm2_swtpm_bios
ret=$?
[ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret
export SWTPM_INTERFACE=unix+unix
bash _test_tpm2_swtpm_bios
ret=$?
[ $ret -ne 0 ] && [ $ret -ne 77 ] && exit $ret
exit 0