summaryrefslogtreecommitdiffstats
path: root/tests/keyring-compat-test
blob: ea88c21011aea82637fc53739e618f55cdcb05f4 (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
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#!/bin/bash

CIPHER_XTS_PLAIN="aes-xts-plain64"
CIPHER_CBC_ESSIV="aes-cbc-essiv:sha256"
CIPHER_CBC_TCW="serpent-cbc-tcw"
# TODO: mode with LMK

TEST_KEYRING_NAME="keyringtest_keyring"

LOGON_KEY_16_OK="dmtst:lkey_16"
LOGON_KEY_32_OK="dmtst:lkey_32"
LOGON_KEY_64_OK="dmtst:lkey_64"

HEXKEY_16="be21aa8c733229347bd4e681891e213d";
HEXKEY_32="bb21158c733229347bd4e681891e213d94c685be6a5b84818afe7a78a6de7a1a";
HEXKEY_64="34f95b96abff946b64f1339ff8653cc77c38697c93b797a496f3786e86eed7781850d5112bbae17d209b8310a8f3a034f1cd297667bc0cd1438fad28d87ef6a1"

DEVSIZEMB=16
DEVSECTORS=$((DEVSIZEMB*1024*1024/512))
NAME=testcryptdev
CHKS_DMCRYPT=vk_in_dmcrypt.chk
CHKS_KEYRING=vk_in_keyring.chk

PWD="aaablabl"

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

CRYPTSETUP_VALGRIND=../.libs/cryptsetup
CRYPTSETUP_LIB_VALGRIND=../.libs

FIPS_MODE=$(cat /proc/sys/crypto/fips_enabled 2>/dev/null)

function remove_mapping()
{
	[ -b /dev/mapper/$NAME ] && dmsetup remove --retry $NAME

	# unlink whole test keyring
	[ -n "$TEST_KEYRING" ] && keyctl unlink $TEST_KEYRING "@u" >/dev/null

	rmmod scsi_debug >/dev/null 2>&1

	rm -f $CHKS_DMCRYPT $CHKS_KEYRING
}

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

function valgrind_setup()
{
	command -v valgrind >/dev/null || fail "Cannot find valgrind."
	[ ! -f $CRYPTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
	export LD_LIBRARY_PATH="$CRYPTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
}

function valgrind_run()
{
	INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${CRYPTSETUP_VALGRIND} "$@"
}

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

# $1 hexbyte key
# $2 type
# $3 description
# $4 keyring
function load_key()
{
	local tmp="$1"
	shift
	echo -n "$tmp" | xxd -r -p | keyctl padd $@ >/dev/null
}

function dm_crypt_keyring_support()
{
	VER_STR=$(dmsetup targets | grep crypt | cut -f2 -dv)
	[ -z "$VER_STR" ] && fail "Failed to parse dm-crypt version."

	VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
	VER_MIN=$(echo $VER_STR | cut -f 2 -d.)

	# run the test with dm-crypt v1.15.0+ on purpose
	# the fix is in dm-crypt v1.18.1+
	[ $VER_MAJ -gt 1 ] && return 0
	[ $VER_MAJ -lt 1 ] && return 1
	[ $VER_MIN -ge 15 ]
}

function test_and_prepare_keyring() {
	keyctl list "@s" > /dev/null || skip "Current session keyring is unreachable, test skipped"
	TEST_KEYRING=$(keyctl newring $TEST_KEYRING_NAME "@u" 2> /dev/null)
	test -n "$TEST_KEYRING" || skip "Failed to create keyring in user keyring"
	keyctl search "@s" keyring "$TEST_KEYRING" > /dev/null 2>&1 || keyctl link "@u" "@s" > /dev/null 2>&1
	load_key "$HEXKEY_16" user test_key "$TEST_KEYRING" || skip "Kernel keyring service is useless on this system, test skipped."
}

function fips_mode()
{
	[ -n "$FIPS_MODE" ] && [ "$FIPS_MODE" -gt 0 ]
}

add_device() {
	rmmod scsi_debug >/dev/null 2>&1
	if [ -d /sys/module/scsi_debug ] ; then
		echo "Cannot use scsi_debug module (in use or compiled-in), test skipped."
		exit 77
	fi

	modprobe scsi_debug $@ delay=0 >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
		echo "This kernel seems to not support proper scsi_debug module, test skipped."
		exit 77
	fi

	sleep 2
	DEV=$(grep -l -e scsi_debug /sys/block/*/device/model | cut -f4 -d /)

	DEV="/dev/$DEV"
	[ -b $DEV ] || fail "Cannot find $DEV."
}

[ ! -x "$CRYPTSETUP" ] && skip "Cannot find $CRYPTSETUP, test skipped."
[ -n "$VALG" ] && valgrind_setup && CRYPTSETUP=valgrind_run
[ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
command -v dmsetup >/dev/null || skip "Cannot find dmsetup, test skipped"
command -v keyctl >/dev/null || skip "Cannot find keyctl, test skipped"
command -v xxd >/dev/null || skip "Cannot find xxd, test skipped"
command -v sha256sum >/dev/null || skip "Cannot find sha256sum, test skipped"
modprobe dm-crypt >/dev/null 2>&1 || fail "dm-crypt failed to load"
dm_crypt_keyring_support || skip "dm-crypt doesn't support kernel keyring, test skipped."

test_and_prepare_keyring

add_device dev_size_mb=$DEVSIZEMB

dd if=/dev/urandom of=$DEV bs=1M count=$DEVSIZEMB oflag=direct > /dev/null 2>&1 || fail

#test aes cipher with xts mode, plain IV
echo -n "Testing $CIPHER_XTS_PLAIN..."
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
load_key "$HEXKEY_32" logon  $LOGON_KEY_32_OK "$TEST_KEYRING" || fail "Cannot load 32 byte logon key type"
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN :32:logon:$LOGON_KEY_32_OK 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
# same test using message
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_XTS_PLAIN $HEXKEY_32 0 $DEV 0" || fail
dmsetup suspend $NAME || fail
dmsetup message $NAME 0 key wipe || fail
dmsetup message $NAME 0 "key set :32:logon:$LOGON_KEY_32_OK" || fail
dmsetup resume $NAME || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
echo "OK"

#test aes cipher, xts mode, essiv IV
echo -n "Testing $CIPHER_CBC_ESSIV..."
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
load_key "$HEXKEY_16" logon  $LOGON_KEY_16_OK "$TEST_KEYRING" || fail "Cannot load 16 byte logon key type"
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV :16:logon:$LOGON_KEY_16_OK 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
# same test using message
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_ESSIV $HEXKEY_16 0 $DEV 0" || fail
dmsetup suspend $NAME || fail
dmsetup message $NAME 0 key wipe || fail
dmsetup message $NAME 0 "key set :16:logon:$LOGON_KEY_16_OK" || fail
dmsetup resume $NAME || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
echo "OK"

#test serpent cipher, cbc mode, tcw IV
fips_mode || {
echo -n "Testing $CIPHER_CBC_TCW..."
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
load_key "$HEXKEY_64" logon  $LOGON_KEY_64_OK "$TEST_KEYRING" || fail "Cannot load 16 byte logon key type"
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW :64:logon:$LOGON_KEY_64_OK 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksum mismatch (corruption)"
# same test using message
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
sha256sum /dev/mapper/$NAME > $CHKS_DMCRYPT || fail
dmsetup remove --retry $NAME || fail
dmsetup create $NAME --table "0 $DEVSECTORS crypt $CIPHER_CBC_TCW $HEXKEY_64 0 $DEV 0" || fail
dmsetup suspend $NAME || fail
dmsetup message $NAME 0 key wipe || fail
dmsetup message $NAME 0 "key set :64:logon:$LOGON_KEY_64_OK" || fail
dmsetup resume $NAME || fail
sha256sum /dev/mapper/$NAME > $CHKS_KEYRING || fail
dmsetup remove --retry $NAME || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksums mismatch (corruption)"
echo "OK"
}

echo -n "Test LUKS2 key refresh..."
echo $PWD | $CRYPTSETUP luksFormat --type luks2 --luks2-metadata-size 16k --luks2-keyslots-size 4064k --pbkdf pbkdf2 --pbkdf-force-iterations 1000 --force-password $DEV || fail
echo $PWD | $CRYPTSETUP open $DEV $NAME || fail
$CRYPTSETUP status $NAME | grep -q -i "location:.*keyring" || skip "LUKS2 can't use keyring. Test skipped."
dd if=/dev/mapper/$NAME bs=1M iflag=direct status=none | sha256sum > $CHKS_KEYRING || fail
echo $PWD | $CRYPTSETUP refresh $NAME --disable-keyring || fail
$CRYPTSETUP status $NAME | grep -q -i "location:.*keyring" && fail "Key is still in keyring"
dd if=/dev/mapper/$NAME bs=1M iflag=direct status=none | sha256sum > $CHKS_DMCRYPT || fail
diff $CHKS_DMCRYPT $CHKS_KEYRING || fail "Plaintext checksum mismatch (corruption)"
echo "OK"

remove_mapping