1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
|
#!/bin/bash
CC="cc"
PASSWD="tpm2_test"
PASSWD2="tpm2_test2"
FAST_PBKDF_OPT="--pbkdf pbkdf2 --pbkdf-force-iterations 1000"
IMG=systemd_token_test.img
MAP="systemd_tpm2_test"
function bin_check()
{
command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
}
function cleanup() {
[ -S $SWTPM_STATE_DIR/ctrl.sock ] && {
# shutdown TPM via control socket
swtpm_ioctl -s --unix $SWTPM_STATE_DIR/ctrl.sock
sleep 1
}
# if graceful shutdown was successful, pidfile should be deleted
# if it is still present, we forcefully kill the process
[ -f "$SWTPM_PIDFILE" ] && {
kill -9 $(cat $SWTPM_PIDFILE) >/dev/null 2>&1
}
[ -b /dev/mapper/$MAP ] && dmsetup remove --retry $MAP
rm -f $SWTPM_PIDFILE >/dev/null 2>&1
rm -rf $SWTPM_STATE_DIR >/dev/null 2>&1
rm -f $IMG >/dev/null 2>&1
}
function fail()
{
echo "[FAILED]"
[ -n "$1" ] && echo "$1"
echo "FAILED backtrace:"
while caller $frame; do ((frame++)); done
cleanup
exit 2
}
function skip()
{
[ -n "$1" ] && echo "$1"
cleanup
exit 77
}
# Prevent downloading and compiling systemd by default
[ -z "$RUN_SYSTEMD_PLUGIN_TEST" ] && skip "WARNING: Variable RUN_SYSTEMD_PLUGIN_TEST must be defined, test skipped."
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
bin_check swtpm
bin_check swtpm_ioctl
CRYPTENROLL_LD_PRELOAD=""
# if CRYPTSETUP_PATH is defined, we run against installed binaries,
# otherwise we compile systemd tokens from source
[ ! -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ] && {
bin_check git
bin_check meson
bin_check ninja
bin_check pkgconf
INSTALL_PATH=$CRYPTSETUP_PATH/../external-tokens/install
mkdir -p $INSTALL_PATH
DESTDIR=$INSTALL_PATH meson install -C ..
PC_FILE="$(find $INSTALL_PATH -name 'libcryptsetup.pc')"
echo "INSTALL_PATH $INSTALL_PATH"
echo "PC_FILE $PC_FILE"
sed -i "s/^prefix=/prefix=${INSTALL_PATH//\//\\\/}/g" "$PC_FILE"
export PKG_CONFIG_PATH=$(dirname $PC_FILE)
# systemd build system misses libcryptsetup.h if it is installed in non-default path
export CFLAGS="${CFLAGS:-} $(pkgconf --cflags libcryptsetup)"
SYSTEMD_PATH=$CRYPTSETUP_PATH/../external-tokens/systemd
SYSTEMD_CRYPTENROLL=$SYSTEMD_PATH/build/systemd-cryptenroll
mkdir -p $SYSTEMD_PATH
[ -d $SYSTEMD_PATH/.git ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH
cd $SYSTEMD_PATH
meson setup build/ -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true || skip "Failed to configure systemd via meson, some dependencies are probably missing."
ninja -C build/ systemd-cryptenroll libcryptsetup-token-systemd-tpm2.so || skip "Failed to build systemd."
CRYPTSETUP_TOKENS_PATH=$CRYPTSETUP_PATH/../tokens/ssh
cd $CRYPTSETUP_PATH/../tests
cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so $CRYPTSETUP_TOKENS_PATH
cp $SYSTEMD_PATH/build/src/shared/*.so $CRYPTSETUP_TOKENS_PATH
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$CRYPTSETUP_PATH/../tests"
CRYPTENROLL_LD_PRELOAD="$CRYPTSETUP_PATH/../lib/libcryptsetup.so"
echo "CRYPTENROLL_LD_PRELOAD $CRYPTENROLL_LD_PRELOAD"
}
[ -z "$CRYPTSETUP_PATH" ] && {
bin_check git
bin_check meson
bin_check ninja
bin_check pkgconf
INSTALL_PATH=$(pwd)/external-tokens/install
make -C .. install DESTDIR=$INSTALL_PATH
PC_FILE="$(find $INSTALL_PATH -name 'libcryptsetup.pc')"
sed -i "s/^prefix=/prefix=${INSTALL_PATH//\//\\\/}/g" "$PC_FILE"
export PKG_CONFIG_PATH=$(dirname $PC_FILE)
# systemd build system misses libcryptsetup.h if it is installed in non-default path
export CFLAGS="${CFLAGS:-} $(pkgconf --cflags libcryptsetup)"
SYSTEMD_PATH=$(pwd)/external-tokens/systemd
CRYPTSETUP_PATH=$(pwd)/..
SYSTEMD_CRYPTENROLL=$SYSTEMD_PATH/build/systemd-cryptenroll
mkdir -p $SYSTEMD_PATH
[ -d $SYSTEMD_PATH/.git ] || git clone --depth=1 https://github.com/systemd/systemd.git $SYSTEMD_PATH
cd $SYSTEMD_PATH
meson setup build/ -D tpm2=true -D libcryptsetup=true -D libcryptsetup-plugins=true || skip "Failed to configure systemd via meson, some dependencies are probably missing."
ninja -C build/ systemd-cryptenroll libcryptsetup-token-systemd-tpm2.so || skip "Failed to build systemd."
CRYPTSETUP_TOKENS_PATH=$CRYPTSETUP_PATH/.libs
cd $CRYPTSETUP_PATH/tests
cp $SYSTEMD_PATH/build/libcryptsetup-token-*.so $CRYPTSETUP_TOKENS_PATH
cp $SYSTEMD_PATH/build/src/shared/*.so $CRYPTSETUP_TOKENS_PATH
CRYPTENROLL_LD_PRELOAD="$CRYPTSETUP_PATH/.libs/libcryptsetup.so"
}
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup
[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
[ -z "$SYSTEMD_CRYPTENROLL" ] && {
bin_check systemd-cryptenroll
SYSTEMD_CRYPTENROLL="systemd-cryptenroll"
}
[ -z "$TPM_PATH" ] && {
echo "Setting up virtual TPM using swtpm..."
SWTPM_PIDFILE=$(mktemp /tmp/systemd_swtpm_pid.XXXXXX)
SWTPM_STATE_DIR=$(mktemp -d /tmp/systemd_swtpm_state.XXXXXX)
modprobe tpm_vtpm_proxy || skip "Failed to load tpm_vtpm_proxy kernel module, required for emulated TPM."
SWTPM_LOG=$(swtpm chardev --vtpm-proxy --tpm2 --tpmstate dir=$SWTPM_STATE_DIR -d --pid file=$SWTPM_PIDFILE --ctrl type=unixio,path=$SWTPM_STATE_DIR/ctrl.sock)
TPM_PATH=$(echo $SWTPM_LOG | grep -Eo '/dev/tpm([0-9])+' | sed 's/tpm/tpmrm/')
[ -z "$TPM_PATH" ] && skip "No TPM_PATH set and swtpm failed, test skipped."
sleep 1
echo "Virtual TPM set up at $TPM_PATH"
}
if [ -n "$SSH_BUILD_DIR" ]; then
CUSTOM_TOKENS_PATH="--external-tokens-path $SSH_BUILD_DIR"
fi
FAKE_TPM_PATH="$(pwd)/fake_systemd_tpm_path.so"
[ ! -z "$CRYPTSETUP_TESTS_RUN_IN_MESON" ] && FAKE_TPM_PATH="$CRYPTSETUP_PATH/../tests/fake_systemd_tpm_path.so"
[ -f $FAKE_TPM_PATH ] || skip "Please compile $FAKE_TPM_PATH."
export LD_PRELOAD="$LD_PRELOAD:$FAKE_TPM_PATH"
export TPM_PATH=$TPM_PATH
echo "TPM path is $TPM_PATH"
dd if=/dev/zero of=$IMG bs=1M count=32 >/dev/null 2>&1
echo $PASSWD | $CRYPTSETUP luksFormat --type luks2 $FAST_PBKDF_OPT $IMG --force-password -q
echo "Enrolling the device to TPM 2 using systemd-cryptenroll.."
LD_PRELOAD="$LD_PRELOAD:$CRYPTENROLL_LD_PRELOAD" PASSWORD="$PASSWD" $SYSTEMD_CRYPTENROLL $IMG --tpm2-device=$TPM_PATH >/dev/null 2>&1
$CRYPTSETUP luksDump --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG | grep -q "tpm2-blob" || fail "Failed to dump $IMG using systemd_tpm2 token (no tpm2-blob in output)."
echo "Activating the device via TPM2 external token.."
$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH --token-only $IMG $MAP >/dev/null 2>&1 || fail "Failed to open $IMG using systemd_tpm2 token."
$CRYPTSETUP close $MAP >/dev/null 2>&1 || fail "Failed to close $MAP."
echo "Adding passphrase via TPM2 token.."
echo $PASSWD2 | $CRYPTSETUP luksAddKey --external-tokens-path $CRYPTSETUP_TOKENS_PATH $FAST_PBKDF_OPT $IMG --force-password -q --token-only >/dev/null 2>&1 || fail "Failed to add passphrase by tpm2 token."
echo $PASSWD2 | $CRYPTSETUP open $IMG --test-passphrase --disable-external-tokens >/dev/null 2>&1 || fail "Failed to test passphrase added by tpm2 token."
echo "Exporting and removing TPM2 token.."
EXPORTED_TOKEN=$($CRYPTSETUP token export $IMG --token-id 0)
$CRYPTSETUP token remove $IMG --token-id 0
$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG --test-passphrase --token-only >/dev/null 2>&1 && fail "Activating without passphrase should fail after TPM2 token removal."
echo "Re-importing TPM2 token.."
echo $EXPORTED_TOKEN | $CRYPTSETUP token import $IMG --token-id 0 || fail "Failed to re-import deleted token."
$CRYPTSETUP open --external-tokens-path $CRYPTSETUP_TOKENS_PATH $IMG --test-passphrase --token-only >/dev/null 2>&1 || fail "Failed to activate after re-importing deleted token."
cleanup
exit 0
|