summaryrefslogtreecommitdiff
path: root/tests/integrity-compat-test
blob: 208eafb7a4cc12c2e1d64c3ec5607125d6d8917c (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
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
#!/bin/bash
#
# Test integritysetup compatibility.
#
[ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
INTSETUP=$CRYPTSETUP_PATH/integritysetup

INTSETUP_VALGRIND=../.libs/integritysetup
INTSETUP_LIB_VALGRIND=../.libs

DEV_NAME=dmc_test
DEV_NAME2=dmc_fake
DEV_LOOP=""
DEV=test123.img
DEV2=test124.img
KEY_FILE=key.img
KEY_FILE2=key2.img

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

cleanup() {
	[ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
	[ -b /dev/mapper/$DEV_NAME2 ] && dmremove $DEV_NAME2
	[ -n "$DEV_LOOP" ] && losetup -d "$DEV_LOOP"
	DEV_LOOP=""
	rm -f $DEV $DEV2 $KEY_FILE $KEY_FILE2 >/dev/null 2>&1
}

fail()
{
	[ -n "$1" ] && echo "$1"
	echo "FAILED backtrace:"
	while caller $frame; do ((frame++)); done
	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
	}
	[ $VER_MIN -gt 2 ] && {
		DM_INTEGRITY_BITMAP=1
	}
	[ $VER_MIN -gt 5 ] && {
		DM_INTEGRITY_RESIZE_SUPPORTED=1
	}
	[ $VER_MIN -gt 6 ] && {
		DM_INTEGRITY_HMAC_FIX=1
	}
	[ $VER_MIN -gt 7 ] && {
		DM_INTEGRITY_RESET=1
	}
}

add_device() {
	cleanup
	dd if=/dev/urandom of=$KEY_FILE bs=4096 count=1 >/dev/null 2>&1
	dd if=/dev/urandom of=$KEY_FILE2 bs=1 count=32 >/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()
{
	command -v valgrind >/dev/null || 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 outtagsize sector_size csum [keyfile keysize]
{
	if [ -n "$8" ] ; then
		KEY_PARAMS="--integrity-key-file $7 --integrity-key-size $8"
	else
		KEY_PARAMS=""
	fi

	if [ $3 -ne 0 ] ; then
		TAG_PARAMS="--tag-size $3"
	else
		TAG_PARAMS=""
	fi

	echo -n "[INTEGRITY:$2:$4:$5]"
	[ -n "$8" ] && echo -n "[KEYFILE:$8]"
	echo -n "[FORMAT]"
	$INTSETUP format --integrity-legacy-padding -q --integrity $1 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
		if [[ $1 =~ "sha2" || $1 =~ "crc" ]] ; then
			fail "Cannot format device."
		fi
		echo "[N/A]"
		return
	fi

	dump_check "tag_size" $4
	dump_check "sector_size" $5
	echo -n "[ACTIVATE]"
	$INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
	if [ -n "$8" ]; then
		KEY_HEX=$(xxd -c 4096 -l $8 -p $7)
		[ -z "$KEY_HEX" ] && fail "Cannot decode key."
		dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
	fi
	status_check "tag size" $4
	status_check "integrity" $2
	status_check "sector size" "$5 bytes"
	int_check_sum $1 $6 $7 $8
	echo -n "[REMOVE]"
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	echo "[OK]"
}

int_error_detection() # mode alg tagsize outtagsize sector_size key_file key_size
{
	if [ "$1" == "B" ] ; then
		INT_MODE="-B"
	else
		INT_MODE=""
	fi
	if [ -n "$7" ] ; then
		KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
	else
		KEY_PARAMS=""
	fi
	if [ $3 -ne 0 ] ; then
		TAG_PARAMS="--tag-size $3"
	else
		TAG_PARAMS=""
	fi
	dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1

	echo -n "[INTEGRITY:$1:$2:$4:$5]"
	echo -n "[FORMAT]"
	$INTSETUP format -q --integrity $2 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV $INT_MODE >/dev/null 2>&1
	if [ $? -ne 0 ] ; then
		if [[ $2 =~ "sha2" || $2 =~ "crc" ]] ; then
			fail "Cannot format device."
		fi
		echo "[N/A]"
		return
	fi
	echo -n "[ACTIVATE]"
	$INTSETUP open $DEV $DEV_NAME --integrity $2 --integrity-no-journal $KEY_PARAMS $INT_MODE || fail "Cannot activate device."

	if [ -n "$6" -a -n "$7" ]; then
		echo -n "[KEYED HASH]"
		KEY_HEX=$(xxd -c 256 -l $7 -p $6)
		[ -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 $2 $KEY_PARAMS $INT_MODE || 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:$8]"
	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 4096 -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]"
}

check_device_size() # device_name expected_size error_message
{
	CURRENT_SIZE=$(dmsetup table | grep $1 | cut -d' ' -f 3)
	[ $CURRENT_SIZE -eq $2 ] || fail "$3: expected $1 to be of size $2, but is $CURRENT_SIZE"
}

test_resize() # description detached_metadata wipe args
{
	echo -n "$1"
	if [ -z "$DM_INTEGRITY_RESIZE_SUPPORTED" ] ; then
		echo "[N/A]"
		return
	fi

	args="$4"
	if [ $2 -ne 0 ] ; then
		echo -n "[DETACHED]"
	else
		echo -n "[INTERLEAVE]"
	fi
	if [ $3 -ne 0 ] ; then
		wipe_flag="--wipe"
		echo -n "[WIPE]"
	else
		wipe_flag=""
		echo -n "[RECALCULATE]"
	fi

	add_device
	if [ $2 -ne 0 ] ; then
		echo -n "[FORMAT]"
		$INTSETUP format -q $args $DEV2 --data-device $DEV  >/dev/null 2>&1 || fail "Cannot format device."
		echo -n "[ACTIVATE]"
		$INTSETUP open -q $args $DEV2 $DEV_NAME --data-device $DEV  >/dev/null 2>&1 || fail "Cannot activate device."
	else
		echo -n "[FORMAT]"
		$INTSETUP format -q $args $DEV  >/dev/null 2>&1 || fail "Cannot format device."
		echo -n "[ACTIVATE]"
		$INTSETUP open -q $args $DEV $DEV_NAME  >/dev/null 2>&1 || fail "Cannot activate device."
	fi

	if [ $2 -ne 0 ] ; then
		# the whole device has 32MiB, if metadata is detached
		WHOLE_DISK_SIZE=65536
	else
		WHOLE_DISK_SIZE=$(dmsetup table | grep $DEV_NAME | cut -d' ' -f 3)
	fi

	echo -n "[SHRINK]"
	$INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 1MiB || fail "Failed to resize the device to 1MiB."
	dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after shrink."
	check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"

	echo -n "[FILL]"
	$INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 0 || fail "Failed to resize the device to maximum size."
	dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after resize to maximum size."
	check_device_size $DEV_NAME $WHOLE_DISK_SIZE "Resizing disk to maximum size failed"

	echo -n "[EXPAND FIXED]"
	fallocate $DEV --len 64M
	$INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 40MiB || fail "Failed to expand the device to a fixed size."
	dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detected after expanding to a fixed size."
	check_device_size $DEV_NAME $(( 40*1024*1024 / 512 )) "Resizing disk after expanding to a fixed size failed"

	echo -n "[FILL]"
	$INTSETUP resize -q $wipe_flag $DEV_NAME --device-size 0 >/dev/null 2>&1 || fail "Failed to resize the device to maximum size after increasing image size."
	dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Error detection failed after increasing image size."
	CURRENT_SIZE=$(dmsetup table | grep $DEV_NAME | cut -d' ' -f 3)
	[ $CURRENT_SIZE -ge $(( 40*1024*1024 / 512 )) ] || fail "Growing integrity device failed $CURRENT_SIZE is not greater than 40MB ($(( 40*1024*1024 / 512 )) blocks)."
	if [ $2 -ne 0 ] ; then
		[ $CURRENT_SIZE -eq 131072 ] || fail "Growing integrity device failed $CURRENT_SIZE is not equal to 64MB (131072 blocks)."
	fi

	echo -n "[REMOVE]"
	$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."
command -v blockdev >/dev/null || skip "Cannot find blockdev utility, test skipped."

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

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

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

command -v xxd >/dev/null || skip "WARNING: xxd tool required."
int_error_detection J hmac-sha256  0 32 512 $KEY_FILE 32
int_error_detection J hmac-sha256  0 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\)
int_journal sha1   20 512  75 9999 hmac-sha256 $KEY_FILE 4096 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 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 -n "[OK]"
	if [ -n "$DM_INTEGRITY_RESET" ] ; then
		$INTSETUP open $DEV $DEV_NAME -I sha256 --integrity-recalculate-reset || fail "Cannot activate device."
		dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot reset recalculate tags in-kernel"
		int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
		$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
		echo "[RESET OK]"
	else
		echo "[RESET N/A]"
	fi
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

echo -n "Bitmap mode parameters:"
if [ -n "$DM_INTEGRITY_BITMAP" ] ; then
	add_device
	$INTSETUP format -q $DEV --integrity-bitmap-mode $DEV2 || fail "Cannot format device."
	$INTSETUP open $DEV --integrity-bitmap-mode --bitmap-sectors-per-bit 65536 --bitmap-flush-time 5000 $DEV_NAME || fail "Cannot activate device."
	$INTSETUP status $DEV_NAME | grep -q 'bitmap 512-byte sectors per bit: 65536' || fail
	$INTSETUP status $DEV_NAME | grep -q 'bitmap flush interval: 5000 ms' || fail
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	echo "[OK]"
	echo "Bitmap error detection tests:"
	int_error_detection B crc32c      0  4 512
	int_error_detection B crc32c      0  4 4096
	int_error_detection B sha256      0 32 512
	int_error_detection B sha256      0 32 4096
	int_error_detection B hmac-sha256 0 32 512 $KEY_FILE 32
	int_error_detection B hmac-sha256 0 32 4096 $KEY_FILE 32
else
	echo "[N/A]"
fi

echo -n "Big device:"
add_device
DEV_LOOP=$(losetup -f $DEV --show)
if [ -n "$DEV_LOOP" ] ; then
dmsetup create $DEV_NAME2 <<EOF
0 16284 linear $DEV_LOOP 0
16284 80000000000 zero
EOF
	[ ! -b /dev/mapper/$DEV_NAME2 ] && fail
	$INTSETUP format -q -s 512 --no-wipe /dev/mapper/$DEV_NAME2
	$INTSETUP open /dev/mapper/$DEV_NAME2 $DEV_NAME || fail
	D_SIZE=$($INTSETUP dump /dev/mapper/$DEV_NAME2 | grep provided_data_sectors | sed -e 's/.*provided_data_sectors\ \+//g')
	A_SIZE=$(blockdev --getsz /dev/mapper/$DEV_NAME)
	# Compare strings (to avoid 64bit integers), not integers
	[ -n "$A_SIZE" -a "$D_SIZE" != "$A_SIZE" ] && fail
	echo "[OK]"
else
	echo "[N/A]"
fi

echo -n "Deferred removal of device:"
add_device
$INTSETUP format -q $DEV || fail "Cannot format device."
$INTSETUP open $DEV $DEV_NAME || fail "Cannot activate device."
dmsetup create $DEV_NAME2 --table "0 8 linear /dev/mapper/$DEV_NAME 0"
[ ! -b /dev/mapper/$DEV_NAME2 ] && fail
$INTSETUP close $DEV_NAME >/dev/null 2>&1 && fail
$INTSETUP -q status $DEV_NAME >/dev/null 2>&1 || fail
$INTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
if [ $? -eq 0 ] ; then
	dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" || fail
	$INTSETUP close --cancel-deferred $DEV_NAME >/dev/null 2>&1
	dmsetup info $DEV_NAME | grep -q "DEFERRED REMOVE" >/dev/null 2>&1 && fail
	$INTSETUP close --deferred $DEV_NAME >/dev/null 2>&1
	dmsetup remove $DEV_NAME2 || fail
	$INTSETUP -q status $DEV_NAME >/dev/null 2>&1 && fail
	echo "[OK]"
else
	dmsetup remove $DEV_NAME2 >/dev/null 2>&1
	$INTSETUP close $DEV_NAME >/dev/null 2>&1
	echo "[N/A]"
fi

echo -n "Fixed HMAC and legacy flags:"
if [ -n "$DM_INTEGRITY_HMAC_FIX" ] ; then
	add_device
	# only data HMAC
	ARGS="--integrity hmac-sha256 --integrity-key-file $KEY_FILE --integrity-key-size 32"
	$INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
	$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
	$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	# New version - must fail (no journal HMAC)
	$INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
	$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS  >/dev/null 2>&1 && fail "Cannot activate device."
	$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."

	# data and journal HMAC
	ARGS="$ARGS --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE2 --journal-integrity-key-size 32"
	$INTSETUP format -q $DEV --integrity-legacy-hmac --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
	$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS >/dev/null 2>&1 && fail "Cannot activate device."
	$INTSETUP open $DEV $DEV_NAME --integrity-legacy-recalculate $ARGS || fail "Cannot activate device."
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	# New fixed version
	$INTSETUP format -q $DEV --no-wipe --tag-size 32 $ARGS || fail "Cannot format device."
	$INTSETUP dump $DEV | grep "flags" | grep -q "fix_hmac" || fail "Flag for HMAC not set."
	$INTSETUP open $DEV $DEV_NAME --integrity-recalculate $ARGS || fail "Cannot activate device."
	$INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
	echo "[OK]"
else
	echo "[N/A]"
fi

# shrinking the mapping should also work on older kernels
echo -n "[INTEGRITY BASIC RESIZE NOKEY]"
add_device
ARGS="--integrity crc32"

echo -n "[FORMAT]"
$INTSETUP format -q $DEV $ARGS || fail "Cannot format device."
echo -n "[ACTIVATE]"
$INTSETUP open -q $DEV $DEV_NAME $ARGS >/dev/null 2>&1 || fail "Cannot activate device."
echo -n "[SHRINK]"
$INTSETUP resize $DEV_NAME --device-size 1MiB  >/dev/null 2>&1 || fail "Failed to resize the device to 1MiB."
check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"
dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detectied after resize."
echo "[OK]"

echo -n "[INTEGRITY BASIC RESIZE KEY]"
add_device

ARGS="--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"

echo -n "[FORMAT]"
$INTSETUP format -q $DEV $ARGS || fail "Cannot format device."
echo -n "[ACTIVATE]"
$INTSETUP open -q $DEV $DEV_NAME $ARGS >/dev/null 2>&1 || fail "Cannot activate device."
echo -n "[SHRINK]"
$INTSETUP resize $DEV_NAME --device-size 1MiB >/dev/null 2>&1 || fail "Failed to resize the device to 1MiB."
check_device_size $DEV_NAME $(( 1024*1024 / 512 )) "Shrinking device failed"
dd if=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Errors detectied after resize."
echo "[OK]"

test_resize "[INTEGRITY RESIZE NOKEY]" 0 0 "--integrity crc32"
test_resize "[INTEGRITY RESIZE NOKEY]" 0 1 "--integrity crc32"
test_resize "[INTEGRITY RESIZE NOKEY DETACHED]" 1 0 "--integrity crc32"
test_resize "[INTEGRITY RESIZE NOKEY DETACHED]" 1 1 "--integrity crc32"
if [ -n "$DM_INTEGRITY_HMAC_FIX" ] ; then
	test_resize "[INTEGRITY RESIZE KEY]" 0 0 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
	test_resize "[INTEGRITY RESIZE KEY]" 0 1 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
	test_resize "[INTEGRITY RESIZE KEY DETACHED]" 1 0 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
	test_resize "[INTEGRITY RESIZE KEY DETACHED]" 1 1 "--integrity hmac-sha256 --integrity-key-size 128 --integrity-key-file $KEY_FILE --journal-integrity hmac-sha256 --journal-integrity-key-file $KEY_FILE --journal-integrity-key-size 128 --journal-crypt ctr-aes --journal-crypt-key-size 16 --journal-crypt-key-file $KEY_FILE"
fi

cleanup