File: keyring-trusted-test

package info (click to toggle)
cryptsetup 2%3A2.8.4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 20,356 kB
  • sloc: ansic: 65,885; sh: 17,691; cpp: 994; xml: 920; makefile: 495; perl: 486
file content (187 lines) | stat: -rwxr-xr-x 6,116 bytes parent folder | download | duplicates (2)
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
#!/bin/bash

# Encrypted and trusted keyring test; trusted keys can be emulated by TPM2.
# DO NOT use this in combination with a real TPM data, it can destroy them.
#
# Note that if trusted or tpm kernel module is built-in, emulated TPM2 cannot
# provide trusted keys (only encrypted keys will be tested then).

[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
CRYPTSETUP=$CRYPTSETUP_PATH/cryptsetup

IMG=keyring_trusted_test.img
MAP="trusted_test"
KEYNAME=testxxx

bin_check()
{
    command -v $1 >/dev/null || skip "WARNING: test require $1 binary, test skipped."
}

cleanup() {
    clear_keys

    [ -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

    [ -n "$SWTPM_PIDFILE" ] && rm -f $SWTPM_PIDFILE >/dev/null 2>&1
    [ -n "$SWTPM_STATE_DIR" ] && rm -rf $SWTPM_STATE_DIR >/dev/null 2>&1
    rm -f $IMG >/dev/null 2>&1

    cleanup_modules
}

cleanup_modules()
{
    [ -n "$SKIP_MODULE_UNLOAD" ] && return

    # This is a hack to avoid linking trusted key to another TPM.
    # Without clean load tests do not work reliably.
    modprobe -r dm-crypt 2>/dev/null
    modprobe -r encrypted-keys 2>/dev/null
    modprobe -r trusted 2>/dev/null
    modprobe -r tpm_vtpm_proxy 2>/dev/null
    modprobe -r tpm 2>/dev/null
}

fail()
{
    echo "[FAILED]"
    [ -n "$1" ] && echo "$1"
    echo "FAILED backtrace:"
    while caller $frame; do ((frame++)); done
    cleanup
    exit 2
}

_sigchld() { local c=$?; [ $c -eq 139 ] && fail "Segfault"; [ $c -eq 134 ] && fail "Aborted"; }
trap _sigchld CHLD

skip()
{
    [ -n "$1" ] && echo "$1"
    cleanup
    exit 77
}

prepare_tpm()
{
    SWTPM_STATE_DIR=$(mktemp -d /tmp/systemd_swtpm_state.XXXXXX)
    SWTPM_SEAL_KEY="$SWTPM_STATE_DIR/sealkey.ctxt"
    SWTPM_PERSISTENT_HANDLE=0x81000001

if [ -z "$TPM_PATH" ]; then
    bin_check swtpm
    bin_check swtpm_ioctl

    SWTPM_PIDFILE=$(mktemp /tmp/systemd_swtpm_pid.XXXXXX)

    cleanup_modules
    modprobe tpm_vtpm_proxy || fail "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" ] && fail "No TPM_PATH set and swtpm failed, test skipped."

    echo "Virtual TPM set up at $TPM_PATH"

    # Trusted module needs to see TPM above.
    sleep 1
    modprobe trusted 2>/dev/null || echo "Failed to load trusted keys kernel module."
else
    SKIP_MODULE_UNLOAD=1
    echo "Preconfigured TPM set up at $TPM_PATH"
fi
    # Create persistent store
    tpm2_createprimary -Q -T device:$TPM_PATH --hierarchy o -G rsa2048 -c $SWTPM_SEAL_KEY || fail
    tpm2_evictcontrol -Q -T device:$TPM_PATH -c $SWTPM_SEAL_KEY $SWTPM_PERSISTENT_HANDLE || fail
}

prepare_vk_keyring()
{
    local s_desc=$(keyctl rdescribe @s | cut -d';' -f5)
    local us_desc=$(keyctl rdescribe @us | cut -d';' -f5)

    if [ "$s_desc" = "$us_desc" -a -n "$s_desc" ]; then
        echo "Session keyring is missing, initializing new one."
        keyctl new_session > /dev/null || fail
    fi
}

clear_keys()
{
    keyctl revoke %encrypted:$KEYNAME 2>/dev/null
    keyctl revoke %user:$KEYNAME 2>/dev/null

    if [ -n "$TRUSTED_SUPPORTED" ]; then
        keyctl revoke %trusted:$KEYNAME 2>/dev/null
        tpm2_evictcontrol -Q -T device:$TPM_PATH -C o -c $SWTPM_PERSISTENT_HANDLE 2>/dev/null
    fi
}

[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
bin_check keyctl

prepare_vk_keyring

# Prevent using TPM by default
if [ -n "$RUN_KEYRING_TRUSTED_TEST" ]; then
    prepare_tpm
    # Trusted keyring key
    keyctl add trusted $KEYNAME "new 32 keyhandle=$SWTPM_PERSISTENT_HANDLE" @s >/dev/null 2>&1 && TRUSTED_SUPPORTED=1
    if [ -n "$TRUSTED_SUPPORTED" ]; then
        keyctl print %trusted:$KEYNAME >/dev/null || fail "Cannot read trusted key blob."
    fi
else
    echo "WARNING: Variable RUN_KEYRING_TRUSTED_TEST must be defined, TPM trusted test skipped."
    TRUSTED_SUPPORTED=
fi

# Prepare encrypted key
modprobe encrypted-keys 2>/dev/null || skip "Failed to load encrypted keys kernel module."

# Encrypted keyring key (encrypted with user key)
# User key needed for encrypted key
keyctl add -x user $KEYNAME bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a @s >/dev/null 2>&1 || skip "User key load failed, test skipped."
keyctl print %user:$KEYNAME >/dev/null || fail "Cannot read user key."

keyctl add encrypted $KEYNAME "new user:$KEYNAME 32" @s >/dev/null || fail "Encrypted keys are not supported."
keyctl print %encrypted:$KEYNAME >/dev/null || fail "Cannot read encrypted key blob."

dd if=/dev/zero of=$IMG bs=1M count=32 >/dev/null 2>&1

echo -n "Plain with trusted volume key "
if [ -n "$TRUSTED_SUPPORTED" ]; then
    $CRYPTSETUP open --type plain $IMG $MAP --key-size=256 --cipher=aes-xts-plain64 --volume-key-keyring=%trusted:$KEYNAME || fail
    dmsetup table --showkeys $MAP | grep -q ":32:trusted:$KEYNAME" || fail
    $CRYPTSETUP status $MAP | grep -q "key location: keyring" || fail
    $CRYPTSETUP close $MAP || fail
    echo "[OK]"
else
    echo "[N/A]"
fi

echo -n "Plain with encrypted volume key "
$CRYPTSETUP open --type plain $IMG $MAP --key-size=256 --cipher=aes-xts-plain64 --volume-key-keyring=%encrypted:$KEYNAME ||fail
dmsetup table --showkeys $MAP | grep -q ":32:encrypted:$KEYNAME" || fail
$CRYPTSETUP status $MAP | grep -q "key location: keyring" || fail
$CRYPTSETUP resize $MAP --size 100 || fail
$CRYPTSETUP status  $MAP | grep "size:" | grep -q "100 \[512-byte units\]" || fail
$CRYPTSETUP resize  $MAP || fail
$CRYPTSETUP close $MAP || fail
echo "[OK]"

cleanup
exit 0