summaryrefslogtreecommitdiffstats
path: root/tests/integrity-compat-test
blob: 58b36e963a5191c254c1c416a63a284462421d7e (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
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
#!/bin/bash
#
# Test integritysetup compatibility.
#
INTSETUP=../integritysetup
INTSETUP_VALGRIND=../.libs/integritysetup
INTSETUP_LIB_VALGRIND=../.libs

DEV_NAME=dmc_test
DEV=test123.img
DEV2=test124.img
KEY_FILE=key.img

dmremove() { # device
	udevadm settle >/dev/null 2>&1
	dmsetup remove $1 >/dev/null 2>&1
}

cleanup() {
	[ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
	rm -f $DEV $DEV2 $KEY_FILE >/dev/null 2>&1
}

fail()
{
	echo
	echo "FAILED at line $(caller)"
	cleanup
	exit 100
}

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

function dm_integrity_features()
{
	VER_STR=$(dmsetup targets | grep integrity | cut -f2 -dv)
	[ -z "$VER_STR" ] && skip "Cannot find dm-integrity target, test skipped."

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

	[ $VER_MAJ -lt 1 ] && return
	[ $VER_MIN -gt 1 ] && {
		DM_INTEGRITY_META=1
		DM_INTEGRITY_RECALC=1
	}
}

add_device() {
	cleanup
	dd if=/dev/urandom of=$KEY_FILE bs=1 count=512 >/dev/null 2>&1
	dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
	dd if=/dev/zero of=$DEV2 bs=1M count=32 >/dev/null 2>&1
	sync
}

status_check() # name value
{
	X=$($INTSETUP status $DEV_NAME | grep "$1" | sed 's/.*: //' | sed 's/^[[:space:]]*//')
	if [ "$X" != "$2" ] ; then
		echo "[status FAIL]"
		echo " Expecting $1:$2 got \"$X\"."
		fail
	fi
}

dump_check() # name value
{
	X=$($INTSETUP dump $DEV | grep "$1" | cut -d' '  -f 2)
	if [ "$X" != "$2" ] ; then
		echo "[dump FAIL]"
		echo " Expecting $1:$2 got \"$X\"."
		fail
	fi
}

kernel_param_check() # number value
{
	X=$(dmsetup table $DEV_NAME | cut -d " " -f $1)
	if [ "$X" != $2 ] ; then
		echo "[param_check FAIL]"
		echo "Expecting $2 got \"$X\"."
		fail
	fi
}

function valgrind_setup()
{
    which valgrind >/dev/null 2>&1 || fail "Cannot find valgrind."
    [ ! -f $INTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
    export LD_LIBRARY_PATH="$INTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
}

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

int_check_sum_only() # checksum
{
	VSUM=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
	if [ "$VSUM" = "$1" ] ; then
		echo -n "[CHECKSUM OK]"
	else
		echo "[FAIL]"
		echo " Expecting $1 got $VSUM."
		fail
	fi
}

int_check_sum() # alg checksum [keyfile keysize]
{
	if [ -n "$4" ] ; then
		KEY_PARAMS="--integrity-key-file $3 --integrity-key-size $4"
	else
		KEY_PARAMS=""
	fi

	# Fill device with zeroes and reopen it
	dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M oflag=direct >/dev/null 2>&1
	dmremove $DEV_NAME

	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."

	int_check_sum_only $2
}

intformat() # alg alg_out tagsize sector_size csum [keyfile keysize]
{
	if [ -n "$7" ] ; then
		KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
	else
		KEY_PARAMS=""
	fi

	echo -n "[INTEGRITY:$2:$3:$4]"
	echo -n "[FORMAT]"
	$INTSETUP format -q --integrity $1 --tag-size $3 --sector-size $4 $KEY_PARAMS $DEV || fail "Cannot format device."
	dump_check "tag_size" $3
	dump_check "sector_size" $4
	echo -n "[ACTIVATE]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
	status_check "tag size" $3
	status_check "integrity" $2
	status_check "sector size" "$4 bytes"
	int_check_sum $1 $5 $6 $7
	echo -n "[REMOVE]"
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	echo "[OK]"
}

int_error_detection() # alg tagsize sector_size key_file key_size
{
	if [ -n "$5" ] ; then
		KEY_PARAMS="--integrity-key-file $4 --integrity-key-size $5"
	else
		KEY_PARAMS=""
	fi
	dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1

	echo -n "[INTEGRITY:$1:$2:$3]"
	echo -n "[FORMAT]"
	$INTSETUP format -q --integrity $1 --tag-size $2 --sector-size $3 $KEY_PARAMS $DEV || fail "Cannot format device."
	echo -n "[ACTIVATE]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 --integrity-no-journal $KEY_PARAMS || fail "Cannot activate device."

	if [ -n "$4" -a -n "$5" ]; then
		echo -n "[KEYED HASH]"
		KEY_HEX=$(xxd -c 256 -l $5 -p $4)
		[ -z "$KEY_HEX" ] && fail "Cannot decode key."
		dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
	fi

	echo -n "[WRITE DATA]"
	echo -n "EXAMPLE TEXT" | dd of=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Cannot write to device."
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."

	# find offset of data area
	ARR=($(dd if=$DEV bs=512 2>/dev/null | hexdump -C | grep 'EXAMPLE TEXT'))
	OFF_HEX=${ARR[0]}
	OFF_DEC=$((16#$OFF_HEX))

	echo -n "[CORRUPT DATA:$OFF_DEC]"
	echo -n "Z" | dd of=$DEV bs=1 seek=$OFF_DEC conv=notrunc >/dev/null 2>&1 || fail "Cannot write to device."

	echo -n "[DETECT ERROR]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
	dd if=/dev/mapper/$DEV_NAME  >/dev/null 2>&1 && fail "Error detection failed."

	echo -n "[REMOVE]"
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	echo "[OK]"
}

int_journal() # 1 alg, 2 tagsize, 3 sector_size, 4 watermark, 5 commit_time, 6 journal_integrity, 7 key-file, 8 key-size, 9 journal_integrity_out
{
    echo -n "[INTEGRITY JOURNAL:$6:${4}%:${5}ms]"
    echo -n "[FORMAT]"
    ARGS="--integrity $1 --journal-watermark $4 --journal-commit-time $5 --journal-integrity $6 --journal-integrity-key-file $7 --journal-integrity-key-size $8"
    $INTSETUP format -q --tag-size $2 --sector-size $3 $ARGS $DEV || fail "Cannot format device."

    echo -n "[ACTIVATE]"

    $INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."

    echo -n "[KEYED HASH]"
    KEY_HEX=$(xxd -c 256 -l $8 -p $7)
    [ -z "$KEY_HEX" ] && fail "Cannot decode key."
    dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."

    status_check "journal watermark" "${4}%"
    status_check "journal commit time" "${5} ms"
    status_check "journal integrity MAC" $9

    echo -n "[REMOVE]"
    $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
    echo "[OK]"
}


int_journal_crypt() # crypt_alg crypt_alg_kernel crypt_key crypt_key_size
{
	echo -n "[JOURNAL CRYPT:$1:${4}B]"

	echo -n "[FORMAT]"
	ARGS="--journal-crypt $1 --journal-crypt-key-file $3 --journal-crypt-key-size $4"
	$INTSETUP format -q $ARGS $DEV || fail "Cannot format device."

	echo -n "[ACTIVATE]"
	$INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."

	KEY_HEX=$(xxd -c 256 -l $4 -p $3)
	[ -z "$KEY_HEX" ] && fail "Cannot decode key."
	dmsetup table --showkeys $DEV_NAME | grep -q "journal_crypt:$2:$KEY_HEX" || fail "Key mismatch."

	$INTSETUP close $DEV_NAME
	echo "[OK]"
}

int_mode() # alg tag_size sector_size [keyfile keysize]
{
	if [ -n "$5" ] ; then
		KEY_PARAMS="--integrity-key-file $4 --integrity-key-size $5"
	else
		KEY_PARAMS=""
	fi

	echo -n "[MODE TESTS:$1:$2:$3]"
	ARGS="--tag-size $2 --sector-size $3"

	$INTSETUP format -q $ARGS $KEY_PARAMS $DEV --integrity $1 || fail "Cannot format device."

	echo -n "[JOURNALED WRITES]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device with journal."
	status_check "mode" "read/write"
	kernel_param_check 7 "J"

	$INTSETUP close $DEV_NAME fail "Cannot deactivate device."

	echo -n "[DIRECT WRITES]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-no-journal || fail "Cannot activate device without journal."
	status_check "mode" "read/write"
	status_check "journal" "not active"
	kernel_param_check 7 "D"

	$INTSETUP close $DEV_NAME fail "Cannot deactivate device."

	echo -n "[RECOVERY MODE]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-recovery-mode || fail "Cannot activate device in recovery mode."
	status_check "mode" "read/write recovery"
	kernel_param_check 7 "R"

	$INTSETUP close $DEV_NAME fail "Cannot deactivate device."

	echo "[OK]"
}

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

[ -n "$VALG" ] && valgrind_setup && INTSETUP=valgrind_run
which hexdump >/dev/null 2>&1 || skip "WARNING: hexdump tool required."
modprobe dm-integrity >/dev/null 2>&1
dm_integrity_features

add_device
intformat crc32c      crc32c          4  512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat crc32       crc32           4  512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
intformat sha1        sha1           20  512 6eedd6344dab8875cd185fcd6565dfc869ab36bc57e577f40c685290b1fa7fe7
intformat sha1        sha1           16 4096 e152ec88227b539cd9cafd8bdb587a1072d720cd6bcebe1398d4136c9e7f337b
intformat sha256      sha256         32  512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
intformat hmac-sha256 hmac\(sha256\) 32  512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11 $KEY_FILE 32
intformat sha256      sha256         32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4
intformat hmac-sha256 hmac\(sha256\) 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 32

echo "Error detection tests:"
int_error_detection crc32c      4  512
int_error_detection crc32c      4  4096
int_error_detection crc32       4  512
int_error_detection crc32       4  4096
int_error_detection sha1        20 512
int_error_detection sha1        16 512
int_error_detection sha1        20 4096
int_error_detection sha256      32 512
int_error_detection sha256      32 4096

which xxd >/dev/null 2>&1 || skip "WARNING: xxd tool required."
int_error_detection hmac-sha256 32 512 $KEY_FILE 32
int_error_detection hmac-sha256 32 4096 $KEY_FILE 32

echo "Journal parameters tests:"
# Watermark is calculated in kernel, so it can be rounded down/up
int_journal crc32  4  512  66 1000 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)
int_journal sha256 32 4096 34 5000 hmac-sha1   $KEY_FILE 16 hmac\(sha1\)
int_journal sha1   20 512  75 9999 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)

echo "Journal encryption tests:"
int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 32
int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 16
int_journal_crypt salsa20 salsa20    $KEY_FILE 32
int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 32
int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 16

echo "Mode tests:"
int_mode crc32c      4  512
int_mode crc32       4  512
int_mode sha1        20 512
int_mode sha256      32 512
int_mode hmac-sha256 32 512  $KEY_FILE 32
int_mode hmac-sha256 32 4096 $KEY_FILE 32

echo -n "Recalculate tags in-kernel:"
add_device
if [ -n "$DM_INTEGRITY_RECALC" ] ; then
	$INTSETUP format -q $DEV --no-wipe || fail "Cannot format device."
	$INTSETUP open $DEV $DEV_NAME --integrity-recalculate || fail "Cannot activate device."
	dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot recalculate tags in-kernel"
	int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
	$INTSETUP close $DEV_NAME fail "Cannot deactivate device."
	echo "[OK]"
else
	echo "[N/A]"
fi

echo -n "Separate metadata device:"
if [ -n "$DM_INTEGRITY_META" ] ; then
	add_device
	$INTSETUP format -q $DEV --data-device $DEV2 || fail "Cannot format device."
	$INTSETUP open $DEV --data-device $DEV2 $DEV_NAME || fail "Cannot activate device."
	int_check_sum_only 83ee47245398adee79bd9c0a8bc57b821e92aba10f5f9ade8a5d1fae4d8c4302
	$INTSETUP status $DEV_NAME | grep -q 'metadata device:' || fail
	$INTSETUP close $DEV_NAME fail "Cannot deactivate device."
	echo "[OK]"
else
	echo "[N/A]"
fi

cleanup