]>
Commit | Line | Data |
---|---|---|
eb26f34a FS |
1 | #!/usr/bin/env bash |
2 | # SPDX-License-Identifier: LGPL-2.1-or-later | |
3 | set -eux | |
4 | set -o pipefail | |
5 | ||
6 | # TODO: | |
7 | # - /proc/cmdline parsing | |
eb26f34a FS |
8 | # - expect + interactive auth? |
9 | ||
10 | # We set up an encrypted /var partition which should get mounted automatically | |
11 | # on boot | |
12 | mountpoint /var | |
13 | ||
14 | systemctl --state=failed --no-legend --no-pager | tee /failed | |
15 | if [[ -s /failed ]]; then | |
16 | echo >&2 "Found units in failed state" | |
17 | exit 1 | |
18 | fi | |
19 | ||
20 | at_exit() { | |
21 | set +e | |
22 | ||
23 | mountpoint -q /proc/cmdline && umount /proc/cmdline | |
24 | rm -f /etc/crypttab | |
25 | [[ -e /tmp/crypttab.bak ]] && cp -fv /tmp/crypttab.bak /etc/crypttab | |
26 | [[ -n "${STORE_LOOP:-}" ]] && losetup -d "$STORE_LOOP" | |
27 | [[ -n "${WORKDIR:-}" ]] && rm -rf "$WORKDIR" | |
28 | ||
29 | systemctl daemon-reload | |
30 | } | |
31 | ||
32 | trap at_exit EXIT | |
33 | ||
34 | cryptsetup_start_and_check() { | |
35 | local expect_fail=0 | |
c9be8e42 | 36 | local umount_header_and_key=0 |
eb26f34a FS |
37 | local ec volume unit |
38 | ||
39 | if [[ "${1:?}" == "-f" ]]; then | |
40 | expect_fail=1 | |
41 | shift | |
42 | fi | |
43 | ||
c9be8e42 LB |
44 | if [[ "${1:?}" == "-u" ]]; then |
45 | umount_header_and_key=1 | |
46 | shift | |
47 | fi | |
48 | ||
eb26f34a FS |
49 | for volume in "$@"; do |
50 | unit="systemd-cryptsetup@$volume.service" | |
51 | ||
52 | # The unit existence check should always pass | |
53 | [[ "$(systemctl show -P LoadState "$unit")" == loaded ]] | |
54 | systemctl list-unit-files "$unit" | |
55 | ||
56 | systemctl start "$unit" && ec=0 || ec=$? | |
57 | if [[ "$expect_fail" -ne 0 ]]; then | |
58 | if [[ "$ec" -eq 0 ]]; then | |
59 | echo >&2 "Unexpected pass when starting $unit" | |
60 | return 1 | |
61 | fi | |
62 | ||
63 | return 0 | |
64 | fi | |
65 | ||
66 | if [[ "$ec" -ne 0 ]]; then | |
67 | echo >&2 "Unexpected fail when starting $unit" | |
68 | return 1 | |
69 | fi | |
70 | ||
c9be8e42 LB |
71 | if [[ "$umount_header_and_key" -ne 0 ]]; then |
72 | umount "$TMPFS_DETACHED_KEYFILE" | |
73 | umount "$TMPFS_DETACHED_HEADER" | |
74 | udevadm settle --timeout=30 | |
75 | fi | |
76 | ||
eb26f34a FS |
77 | systemctl status "$unit" |
78 | test -e "/dev/mapper/$volume" | |
79 | systemctl stop "$unit" | |
80 | test ! -e "/dev/mapper/$volume" | |
81 | done | |
82 | ||
83 | return 0 | |
84 | } | |
85 | ||
86 | # Note: some stuff (especially TPM-related) is already tested by TEST-70-TPM2, | |
87 | # so focus more on other areas instead | |
88 | ||
89 | # Use a common workdir to make the cleanup easier | |
90 | WORKDIR="$(mktemp -d)" | |
91 | ||
92 | # Prepare a couple of LUKS2-encrypted disk images | |
93 | # | |
94 | # 1) Image with an empty password | |
95 | IMAGE_EMPTY="$WORKDIR/empty.img)" | |
96 | IMAGE_EMPTY_KEYFILE="$WORKDIR/empty.keyfile" | |
97 | IMAGE_EMPTY_KEYFILE_ERASE="$WORKDIR/empty-erase.keyfile" | |
98 | IMAGE_EMPTY_KEYFILE_ERASE_FAIL="$WORKDIR/empty-erase-fail.keyfile)" | |
99 | truncate -s 32M "$IMAGE_EMPTY" | |
100 | echo -n passphrase >"$IMAGE_EMPTY_KEYFILE" | |
101 | chmod 0600 "$IMAGE_EMPTY_KEYFILE" | |
102 | cryptsetup luksFormat --batch-mode \ | |
103 | --pbkdf pbkdf2 \ | |
104 | --pbkdf-force-iterations 1000 \ | |
105 | --use-urandom \ | |
106 | "$IMAGE_EMPTY" "$IMAGE_EMPTY_KEYFILE" | |
107 | PASSWORD=passphrase NEWPASSWORD="" systemd-cryptenroll --password "$IMAGE_EMPTY" | |
108 | # Duplicate the key file to test keyfile-erase as well | |
109 | cp -v "$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY_KEYFILE_ERASE" | |
110 | # The key should get erased even on a failed attempt, so test that too | |
111 | cp -v "$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" | |
112 | ||
113 | # 2) Image with a detached header and a key file offset + size | |
114 | IMAGE_DETACHED="$WORKDIR/detached.img" | |
115 | IMAGE_DETACHED_KEYFILE="$WORKDIR/detached.keyfile" | |
116 | IMAGE_DETACHED_KEYFILE2="$WORKDIR/detached.keyfile2" | |
117 | IMAGE_DETACHED_HEADER="$WORKDIR/detached.header" | |
118 | truncate -s 32M "$IMAGE_DETACHED" | |
119 | dd if=/dev/urandom of="$IMAGE_DETACHED_KEYFILE" count=64 bs=1 | |
120 | dd if=/dev/urandom of="$IMAGE_DETACHED_KEYFILE2" count=32 bs=1 | |
121 | chmod 0600 "$IMAGE_DETACHED_KEYFILE" "$IMAGE_DETACHED_KEYFILE2" | |
122 | cryptsetup luksFormat --batch-mode \ | |
123 | --pbkdf pbkdf2 \ | |
124 | --pbkdf-force-iterations 1000 \ | |
125 | --use-urandom \ | |
126 | --header "$IMAGE_DETACHED_HEADER" \ | |
127 | --keyfile-offset 32 \ | |
128 | --keyfile-size 16 \ | |
129 | "$IMAGE_DETACHED" "$IMAGE_DETACHED_KEYFILE" | |
130 | # Also, add a second key file to key slot 8 | |
131 | # Note: --key-slot= behaves as --new-key-slot= when used alone for backwards compatibility | |
132 | cryptsetup luksAddKey --batch-mode \ | |
133 | --header "$IMAGE_DETACHED_HEADER" \ | |
134 | --key-file "$IMAGE_DETACHED_KEYFILE" \ | |
135 | --keyfile-offset 32 \ | |
136 | --keyfile-size 16 \ | |
137 | --key-slot 8 \ | |
138 | "$IMAGE_DETACHED" "$IMAGE_DETACHED_KEYFILE2" | |
139 | ||
140 | # Prepare a couple of dummy devices we'll store a copy of the detached header | |
141 | # and one of the keys on to test if systemd-cryptsetup correctly mounts them | |
142 | # when necessary | |
143 | STORE_IMAGE="$WORKDIR/store.img" | |
144 | truncate -s 64M "$STORE_IMAGE" | |
145 | STORE_LOOP="$(losetup --show --find --partscan "$STORE_IMAGE")" | |
146 | sfdisk "$STORE_LOOP" <<EOF | |
147 | label: gpt | |
148 | type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=header_store size=32M | |
149 | type=0FC63DAF-8483-4772-8E79-3D69D8477DE4 name=keyfile_store | |
150 | EOF | |
151 | udevadm settle --timeout=30 | |
152 | mkdir -p /mnt | |
153 | mkfs.ext4 -L header_store "/dev/disk/by-partlabel/header_store" | |
154 | mount "/dev/disk/by-partlabel/header_store" /mnt | |
155 | cp "$IMAGE_DETACHED_HEADER" /mnt/header | |
156 | umount /mnt | |
157 | mkfs.ext4 -L keyfile_store "/dev/disk/by-partlabel/keyfile_store" | |
158 | mount "/dev/disk/by-partlabel/keyfile_store" /mnt | |
159 | cp "$IMAGE_DETACHED_KEYFILE2" /mnt/keyfile | |
160 | umount /mnt | |
c9be8e42 LB |
161 | |
162 | # Also copy the key and header on a tmpfs that we will umount after unlocking | |
163 | TMPFS_DETACHED_KEYFILE="$(mktemp -d)" | |
164 | TMPFS_DETACHED_HEADER="$(mktemp -d)" | |
165 | mount -t tmpfs -o size=32M tmpfs "$TMPFS_DETACHED_KEYFILE" | |
166 | mount -t tmpfs -o size=32M tmpfs "$TMPFS_DETACHED_HEADER" | |
167 | cp "$IMAGE_DETACHED_KEYFILE" "$TMPFS_DETACHED_KEYFILE/keyfile" | |
168 | cp "$IMAGE_DETACHED_HEADER" "$TMPFS_DETACHED_HEADER/header" | |
169 | ||
eb26f34a FS |
170 | udevadm settle --timeout=30 |
171 | ||
172 | # Prepare our test crypttab | |
173 | [[ -e /etc/crypttab ]] && cp -fv /etc/crypttab /tmp/crypttab.bak | |
174 | cat >/etc/crypttab <<EOF | |
175 | # headless should translate to headless=1 | |
176 | empty_key $IMAGE_EMPTY $IMAGE_EMPTY_KEYFILE headless,x-systemd.device-timeout=1m | |
177 | empty_key_erase $IMAGE_EMPTY $IMAGE_EMPTY_KEYFILE_ERASE headless=1,keyfile-erase=1 | |
178 | empty_key_erase_fail $IMAGE_EMPTY $IMAGE_EMPTY_KEYFILE_ERASE_FAIL headless=1,keyfile-erase=1,keyfile-offset=4 | |
179 | # Empty passphrase without try-empty-password(=yes) shouldn't work | |
180 | empty_fail0 $IMAGE_EMPTY - headless=1 | |
181 | empty_fail1 $IMAGE_EMPTY - headless=1,try-empty-password=0 | |
182 | empty0 $IMAGE_EMPTY - headless=1,try-empty-password | |
183 | empty1 $IMAGE_EMPTY - headless=1,try-empty-password=1 | |
184 | # This one expects the key to be under /{etc,run}/cryptsetup-keys.d/empty_nokey.key | |
185 | empty_nokey $IMAGE_EMPTY - headless=1 | |
a3c1b0d7 | 186 | empty_pkcs11_auto $IMAGE_EMPTY - headless=1,pkcs11-uri=auto |
eb26f34a FS |
187 | |
188 | detached $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=$IMAGE_DETACHED_HEADER,keyfile-offset=32,keyfile-size=16 | |
189 | detached_store0 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=/header:LABEL=header_store,keyfile-offset=32,keyfile-size=16 | |
190 | detached_store1 $IMAGE_DETACHED /keyfile:LABEL=keyfile_store headless=1,header=$IMAGE_DETACHED_HEADER | |
191 | detached_store2 $IMAGE_DETACHED /keyfile:LABEL=keyfile_store headless=1,header=/header:LABEL=header_store | |
192 | detached_fail0 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=$IMAGE_DETACHED_HEADER,keyfile-offset=32 | |
193 | detached_fail1 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=$IMAGE_DETACHED_HEADER | |
194 | detached_fail2 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1 | |
195 | detached_fail3 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=$IMAGE_DETACHED_HEADER,keyfile-offset=16,keyfile-size=16 | |
196 | detached_fail4 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE headless=1,header=$IMAGE_DETACHED_HEADER,keyfile-offset=32,keyfile-size=8 | |
197 | detached_slot0 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER | |
198 | detached_slot1 $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER,key-slot=8 | |
199 | detached_slot_fail $IMAGE_DETACHED $IMAGE_DETACHED_KEYFILE2 headless=1,header=$IMAGE_DETACHED_HEADER,key-slot=0 | |
c9be8e42 | 200 | detached_nofail $IMAGE_DETACHED $TMPFS_DETACHED_KEYFILE/keyfile headless=1,header=$TMPFS_DETACHED_HEADER/header,keyfile-offset=32,keyfile-size=16,nofail |
eb26f34a FS |
201 | EOF |
202 | ||
203 | # Temporarily drop luks.name=/luks.uuid= from the kernel command line, as it makes | |
204 | # systemd-cryptsetup-generator ignore mounts from /etc/crypttab that are not also | |
205 | # specified on the kernel command line | |
206 | sed -r 's/luks.(name|uuid)=[^[:space:]+]//' /proc/cmdline >/tmp/cmdline.tmp | |
207 | mount --bind /tmp/cmdline.tmp /proc/cmdline | |
208 | # Run the systemd-cryptsetup-generator once explicitly, to collect coverage, | |
209 | # as during daemon-reload we run generators in a sandbox | |
210 | mkdir -p /tmp/systemd-cryptsetup-generator.out | |
211 | /usr/lib/systemd/system-generators/systemd-cryptsetup-generator /tmp/systemd-cryptsetup-generator.out/ | |
212 | systemctl daemon-reload | |
213 | systemctl list-unit-files "systemd-cryptsetup@*" | |
214 | ||
215 | cryptsetup_start_and_check empty_key | |
216 | test -e "$IMAGE_EMPTY_KEYFILE_ERASE" | |
217 | cryptsetup_start_and_check empty_key_erase | |
218 | test ! -e "$IMAGE_EMPTY_KEYFILE_ERASE" | |
219 | test -e "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" | |
220 | cryptsetup_start_and_check -f empty_key_erase_fail | |
221 | test ! -e "$IMAGE_EMPTY_KEYFILE_ERASE_FAIL" | |
222 | cryptsetup_start_and_check -f empty_fail{0..1} | |
223 | cryptsetup_start_and_check empty{0..1} | |
224 | # First, check if we correctly fail without any key | |
225 | cryptsetup_start_and_check -f empty_nokey | |
226 | # And now provide the key via /{etc,run}/cryptsetup-keys.d/ | |
227 | mkdir -p /run/cryptsetup-keys.d | |
228 | cp "$IMAGE_EMPTY_KEYFILE" /run/cryptsetup-keys.d/empty_nokey.key | |
229 | cryptsetup_start_and_check empty_nokey | |
230 | ||
a3c1b0d7 VS |
231 | if [[ -r /etc/softhsm2.conf ]]; then |
232 | # Test unlocking with a PKCS#11 token | |
233 | export SOFTHSM2_CONF="/etc/softhsm2.conf" | |
234 | PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=RSATestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY" | |
235 | cryptsetup_start_and_check empty_pkcs11_auto | |
236 | cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2 | |
237 | cryptsetup token remove --token-id 0 "$IMAGE_EMPTY" | |
238 | PIN="1234" systemd-cryptenroll --pkcs11-token-uri="pkcs11:token=TestToken;object=ECTestKey" --unlock-key-file="$IMAGE_EMPTY_KEYFILE" "$IMAGE_EMPTY" | |
239 | cryptsetup_start_and_check empty_pkcs11_auto | |
240 | cryptsetup luksKillSlot -q "$IMAGE_EMPTY" 2 | |
241 | cryptsetup token remove --token-id 0 "$IMAGE_EMPTY" | |
242 | fi | |
243 | ||
eb26f34a FS |
244 | cryptsetup_start_and_check detached |
245 | cryptsetup_start_and_check detached_store{0..2} | |
246 | cryptsetup_start_and_check -f detached_fail{0..4} | |
247 | cryptsetup_start_and_check detached_slot{0..1} | |
248 | cryptsetup_start_and_check -f detached_slot_fail | |
c9be8e42 | 249 | cryptsetup_start_and_check -u detached_nofail |
eb26f34a | 250 | |
07268394 | 251 | touch /testok |