summaryrefslogtreecommitdiffstats
path: root/test/units/TEST-50-DISSECT.sh
blob: 0e378a8e5b3718989d583eb81bc9dd99f58bc918 (plain)
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
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
set -eux
set -o pipefail

# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh

# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh

# Setup shared stuff & run all subtests

at_exit() {
    set +e

    if [[ -z "${IMAGE_DIR:-}" ]]; then
        return
    fi

    while read -r dir; do
        if mountpoint -q "$dir"; then
            umount -Rv "$dir"
        fi
    done < <(find "${IMAGE_DIR}" -mindepth 1 -maxdepth 1 -type d)

    rm -rf "$IMAGE_DIR"
}

trap at_exit EXIT

: "Setup base images"

export SYSTEMD_LOG_LEVEL=debug
export ARCHITECTURE
export IMAGE_DIR
export MACHINE
export MINIMAL_IMAGE
export MINIMAL_IMAGE_ROOTHASH
export OPENSSL_CONFIG
export OS_RELEASE
export ROOT_GUID
export SIGNATURE_GUID
export VERITY_GUID

machine="$(uname -m)"
if [[ "$machine" == "x86_64" ]]; then
    ROOT_GUID=4f68bce3-e8cd-4db1-96e7-fbcaf984b709
    VERITY_GUID=2c7357ed-ebd2-46d9-aec1-23d437ec2bf5
    SIGNATURE_GUID=41092b05-9fc8-4523-994f-2def0408b176
    ARCHITECTURE="x86-64"
elif [[ "$machine" =~ ^(i386|i686|x86)$ ]]; then
    ROOT_GUID=44479540-f297-41b2-9af7-d131d5f0458a
    VERITY_GUID=d13c5d3b-b5d1-422a-b29f-9454fdc89d76
    SIGNATURE_GUID=5996fc05-109c-48de-808b-23fa0830b676
    ARCHITECTURE="x86"
elif [[ "$machine" =~ ^(aarch64|aarch64_be|armv8b|armv8l)$ ]]; then
    ROOT_GUID=b921b045-1df0-41c3-af44-4c6f280d3fae
    VERITY_GUID=df3300ce-d69f-4c92-978c-9bfb0f38d820
    SIGNATURE_GUID=6db69de6-29f4-4758-a7a5-962190f00ce3
    ARCHITECTURE="arm64"
elif [[ "$machine" == "arm" ]]; then
    ROOT_GUID=69dad710-2ce4-4e3c-b16c-21a1d49abed3
    VERITY_GUID=7386cdf2-203c-47a9-a498-f2ecce45a2d6
    SIGNATURE_GUID=42b0455f-eb11-491d-98d3-56145ba9d037
    ARCHITECTURE="arm"
elif [[ "$machine" == "ia64" ]]; then
    ROOT_GUID=993d8d3d-f80e-4225-855a-9daf8ed7ea97
    VERITY_GUID=86ed10d5-b607-45bb-8957-d350f23d0571
    SIGNATURE_GUID=e98b36ee-32ba-4882-9b12-0ce14655f46a
    ARCHITECTURE="ia64"
elif [[ "$machine" == "loongarch64" ]]; then
    ROOT_GUID=77055800-792c-4f94-b39a-98c91b762bb6
    VERITY_GUID=f3393b22-e9af-4613-a948-9d3bfbd0c535
    SIGNATURE_GUID=5afb67eb-ecc8-4f85-ae8e-ac1e7c50e7d0
    ARCHITECTURE="loongarch64"
elif [[ "$machine" == "s390x" ]]; then
    ROOT_GUID=5eead9a9-fe09-4a1e-a1d7-520d00531306
    VERITY_GUID=b325bfbe-c7be-4ab8-8357-139e652d2f6b
    SIGNATURE_GUID=c80187a5-73a3-491a-901a-017c3fa953e9
    ARCHITECTURE="s390x"
elif [[ "$machine" == "ppc64le" ]]; then
    ROOT_GUID=c31c45e6-3f39-412e-80fb-4809c4980599
    VERITY_GUID=906bd944-4589-4aae-a4e4-dd983917446a
    SIGNATURE_GUID=d4a236e7-e873-4c07-bf1d-bf6cf7f1c3c6
    ARCHITECTURE="ppc64-le"
elif [[ "$machine" == "riscv64" ]]; then
    ROOT_GUID=72ec70a6-cf74-40e6-bd49-4bda08e8f224
    VERITY_GUID=b6ed5582-440b-4209-b8da-5ff7c419ea3d
    SIGNATURE_GUID=efe0f087-ea8d-4469-821a-4c2a96a8386a
    ARCHITECTURE="riscv64"
elif [[ "$machine" == "riscv32" ]]; then
    ROOT_GUID=60d5a7fe-8e7d-435c-b714-3dd8162144e1
    VERITY_GUID=ae0253be-1167-4007-ac68-43926c14c5de
    SIGNATURE_GUID=3a112a75-8729-4380-b4cf-764d79934448
    ARCHITECTURE="riscv32"
else
    echo "Unexpected uname -m: $machine in TEST-50-DISSECT.sh, please fix me"
    exit 1
fi

udevadm control --log-level=debug

IMAGE_DIR="$(mktemp -d --tmpdir="" TEST-50-IMAGES.XXX)"
cp -v /usr/share/minimal* "$IMAGE_DIR/"
MINIMAL_IMAGE="$IMAGE_DIR/minimal_0"
MINIMAL_IMAGE_ROOTHASH="$(<"$MINIMAL_IMAGE.roothash")"

install_extension_images

OS_RELEASE="$(test -e /etc/os-release && echo /etc/os-release || echo /usr/lib/os-release)"

if systemctl --version | grep -q -- +OPENSSL ; then
    # The openssl binary is installed conditionally. If we have OpenSSL support enabled and openssl is
    # missing, fail early with a proper error message.
    if ! command -v openssl &>/dev/null; then
        echo "openssl binary is missing" >/failed
        exit 1
    fi

    OPENSSL_CONFIG="$(mktemp)"
    # Unfortunately OpenSSL insists on reading some config file, hence provide one with mostly placeholder contents
    cat >"${OPENSSL_CONFIG:?}" <<EOF
[ req ]
prompt = no
distinguished_name = req_distinguished_name

[ req_distinguished_name ]
C = DE
ST = Test State
L = Test Locality
O = Org Name
OU = Org Unit Name
CN = Common Name
emailAddress = test@email.com
EOF
fi

# Make a GPT disk on the fly, with the squashfs as partition 1 and the verity hash tree as partition 2
#
# du rounds up to block size, which is more helpful for partitioning
root_size="$(du --apparent-size -k "$MINIMAL_IMAGE.raw" | cut -f1)"
verity_size="$(du --apparent-size -k "$MINIMAL_IMAGE.verity" | cut -f1)"
signature_size=4
# 4MB seems to be the minimum size blkid will accept, below that probing fails
dd if=/dev/zero of="$MINIMAL_IMAGE.gpt" bs=512 count=$((8192+root_size*2+verity_size*2+signature_size*2))
# sfdisk seems unhappy if the size overflows into the next unit, eg: 1580KiB will be interpreted as 1MiB
# so do some basic rounding up if the minimal image is more than 1 MB
if [[ "$root_size" -ge 1024 ]]; then
    root_size="$((root_size/1024 + 1))MiB"
else
    root_size="${root_size}KiB"
fi
verity_size="$((verity_size * 2))KiB"
signature_size="$((signature_size * 2))KiB"

if [[ -n "${OPENSSL_CONFIG:-}" ]]; then
    # Create key pair
    openssl req -config "$OPENSSL_CONFIG" -new -x509 -newkey rsa:1024 \
                -keyout "$MINIMAL_IMAGE.key" -out "$MINIMAL_IMAGE.crt" -days 365 -nodes
    # Sign Verity root hash with it
    openssl smime -sign -nocerts -noattr -binary \
                  -in "$MINIMAL_IMAGE.roothash" \
                  -inkey "$MINIMAL_IMAGE.key" \
                  -signer "$MINIMAL_IMAGE.crt" \
                  -outform der \
                  -out "$MINIMAL_IMAGE.roothash.p7s"
    # Generate signature partition JSON data
    echo '{"rootHash":"'"$MINIMAL_IMAGE_ROOTHASH"'","signature":"'"$(base64 -w 0 <"$MINIMAL_IMAGE.roothash.p7s")"'"}' >"$MINIMAL_IMAGE.verity-sig"
    # Pad it
    truncate -s "$signature_size" "$MINIMAL_IMAGE.verity-sig"
    # Register certificate in the (userspace) verity key ring
    mkdir -p /run/verity.d
    ln -s "$MINIMAL_IMAGE.crt" /run/verity.d/ok.crt
fi

# Construct a UUID from hash
# input:  11111111222233334444555566667777
# output: 11111111-2222-3333-4444-555566667777
uuid="$(head -c 32 "$MINIMAL_IMAGE.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.+)/\1-\2-\3-\4-\5/')"
echo -e "label: gpt\nsize=$root_size, type=$ROOT_GUID, uuid=$uuid" | sfdisk "$MINIMAL_IMAGE.gpt"
uuid="$(tail -c 32 "$MINIMAL_IMAGE.roothash" | sed -r 's/(.{8})(.{4})(.{4})(.{4})(.+)/\1-\2-\3-\4-\5/')"
echo -e "size=$verity_size, type=$VERITY_GUID, uuid=$uuid" | sfdisk "$MINIMAL_IMAGE.gpt" --append
if [[ -n "${OPENSSL_CONFIG:-}" ]]; then
    echo -e "size=$signature_size, type=$SIGNATURE_GUID" | sfdisk "$MINIMAL_IMAGE.gpt" --append
fi
sfdisk --part-label "$MINIMAL_IMAGE.gpt" 1 "Root Partition"
sfdisk --part-label "$MINIMAL_IMAGE.gpt" 2 "Verity Partition"
if [[ -n "${OPENSSL_CONFIG:-}" ]]; then
    sfdisk --part-label "$MINIMAL_IMAGE.gpt" 3 "Signature Partition"
fi
loop="$(losetup --show -P -f "$MINIMAL_IMAGE.gpt")"
partitions=(
    "${loop:?}p1"
    "${loop:?}p2"
)
if [[ -n "${OPENSSL_CONFIG:-}" ]]; then
    partitions+=("${loop:?}p3")
fi
# The kernel sometimes(?) does not emit "add" uevent for loop block partition devices.
# Let's not expect the devices to be initialized.
udevadm wait --timeout 60 --settle --initialized=no "${partitions[@]}"
udevadm lock --device="${loop}p1" dd if="$MINIMAL_IMAGE.raw" of="${loop}p1"
udevadm lock --device="${loop}p2" dd if="$MINIMAL_IMAGE.verity" of="${loop}p2"
if [[ -n "${OPENSSL_CONFIG:-}" ]]; then
    udevadm lock --device="${loop}p3" dd if="$MINIMAL_IMAGE.verity-sig" of="${loop}p3"
fi
losetup -d "$loop"
udevadm settle --timeout=60

: "Run subtests"

run_subtests

touch /testok