Imported Upstream version 2.3.3
[platform/upstream/cryptsetup.git] / tests / integrity-compat-test
1 #!/bin/bash
2 #
3 # Test integritysetup compatibility.
4 #
5 [ -z "$CRYPTSETUP_PATH" ] && CRYPTSETUP_PATH=".."
6 INTSETUP=$CRYPTSETUP_PATH/integritysetup
7
8 INTSETUP_VALGRIND=../.libs/integritysetup
9 INTSETUP_LIB_VALGRIND=../.libs
10
11 DEV_NAME=dmc_test
12 DEV_NAME_BIG=dmc_fake
13 DEV_LOOP=""
14 DEV=test123.img
15 DEV2=test124.img
16 KEY_FILE=key.img
17
18 dmremove() { # device
19         udevadm settle >/dev/null 2>&1
20         dmsetup remove --retry $1 >/dev/null 2>&1
21 }
22
23 cleanup() {
24         [ -b /dev/mapper/$DEV_NAME ] && dmremove $DEV_NAME
25         [ -b /dev/mapper/$DEV_NAME_BIG ] && dmremove $DEV_NAME_BIG
26         [ -n "$DEV_LOOP" ] && losetup -d "$DEV_LOOP"
27         DEV_LOOP=""
28         rm -f $DEV $DEV2 $KEY_FILE >/dev/null 2>&1
29 }
30
31 fail()
32 {
33         echo
34         echo "FAILED backtrace:"
35         while caller $frame; do ((frame++)); done
36         cleanup
37         exit 100
38 }
39
40 skip()
41 {
42         [ -n "$1" ] && echo "$1"
43         exit 77
44 }
45
46 function dm_integrity_features()
47 {
48         VER_STR=$(dmsetup targets | grep integrity | cut -f2 -dv)
49         [ -z "$VER_STR" ] && skip "Cannot find dm-integrity target, test skipped."
50
51         VER_MAJ=$(echo $VER_STR | cut -f 1 -d.)
52         VER_MIN=$(echo $VER_STR | cut -f 2 -d.)
53         VER_PTC=$(echo $VER_STR | cut -f 3 -d.)
54
55         [ $VER_MAJ -lt 1 ] && return
56         [ $VER_MIN -gt 1 ] && {
57                 DM_INTEGRITY_META=1
58                 DM_INTEGRITY_RECALC=1
59         }
60         [ $VER_MIN -gt 2 ] && {
61                 DM_INTEGRITY_BITMAP=1
62         }
63 }
64
65 add_device() {
66         cleanup
67         dd if=/dev/urandom of=$KEY_FILE bs=1 count=512 >/dev/null 2>&1
68         dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
69         dd if=/dev/zero of=$DEV2 bs=1M count=32 >/dev/null 2>&1
70         sync
71 }
72
73 status_check() # name value
74 {
75         X=$($INTSETUP status $DEV_NAME | grep "$1" | sed 's/.*: //' | sed 's/^[[:space:]]*//')
76         if [ "$X" != "$2" ] ; then
77                 echo "[status FAIL]"
78                 echo " Expecting $1:$2 got \"$X\"."
79                 fail
80         fi
81 }
82
83 dump_check() # name value
84 {
85         X=$($INTSETUP dump $DEV | grep "$1" | cut -d' '  -f 2)
86         if [ "$X" != "$2" ] ; then
87                 echo "[dump FAIL]"
88                 echo " Expecting $1:$2 got \"$X\"."
89                 fail
90         fi
91 }
92
93 kernel_param_check() # number value
94 {
95         X=$(dmsetup table $DEV_NAME | cut -d " " -f $1)
96         if [ "$X" != $2 ] ; then
97                 echo "[param_check FAIL]"
98                 echo "Expecting $2 got \"$X\"."
99                 fail
100         fi
101 }
102
103 function valgrind_setup()
104 {
105     which valgrind >/dev/null 2>&1 || fail "Cannot find valgrind."
106     [ ! -f $INTSETUP_VALGRIND ] && fail "Unable to get location of cryptsetup executable."
107     export LD_LIBRARY_PATH="$INTSETUP_LIB_VALGRIND:$LD_LIBRARY_PATH"
108 }
109
110 function valgrind_run()
111 {
112     INFOSTRING="$(basename ${BASH_SOURCE[1]})-line-${BASH_LINENO[0]}" ./valg.sh ${INTSETUP_VALGRIND} "$@"
113 }
114
115 int_check_sum_only() # checksum
116 {
117         VSUM=$(sha256sum /dev/mapper/$DEV_NAME | cut -d' ' -f 1)
118         if [ "$VSUM" = "$1" ] ; then
119                 echo -n "[CHECKSUM OK]"
120         else
121                 echo "[FAIL]"
122                 echo " Expecting $1 got $VSUM."
123                 fail
124         fi
125 }
126
127 int_check_sum() # alg checksum [keyfile keysize]
128 {
129         if [ -n "$4" ] ; then
130                 KEY_PARAMS="--integrity-key-file $3 --integrity-key-size $4"
131         else
132                 KEY_PARAMS=""
133         fi
134
135         # Fill device with zeroes and reopen it
136         dd if=/dev/zero of=/dev/mapper/$DEV_NAME bs=1M oflag=direct >/dev/null 2>&1
137         dmremove $DEV_NAME
138
139         $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
140
141         int_check_sum_only $2
142 }
143
144 intformat() # alg alg_out tagsize outtagsize sector_size csum [keyfile keysize]
145 {
146         if [ -n "$8" ] ; then
147                 KEY_PARAMS="--integrity-key-file $7 --integrity-key-size $8"
148         else
149                 KEY_PARAMS=""
150         fi
151
152         if [ $3 -ne 0 ] ; then
153                 TAG_PARAMS="--tag-size $3"
154         else
155                 TAG_PARAMS=""
156         fi
157
158         echo -n "[INTEGRITY:$2:$4:$5]"
159         echo -n "[FORMAT]"
160         $INTSETUP format --integrity-legacy-padding -q --integrity $1 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV >/dev/null || fail "Cannot format device."
161         dump_check "tag_size" $4
162         dump_check "sector_size" $5
163         echo -n "[ACTIVATE]"
164         $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device."
165         status_check "tag size" $4
166         status_check "integrity" $2
167         status_check "sector size" "$5 bytes"
168         int_check_sum $1 $6 $7 $8
169         echo -n "[REMOVE]"
170         $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
171         echo "[OK]"
172 }
173
174 int_error_detection() # mode alg tagsize outtagsize sector_size key_file key_size
175 {
176         if [ "$1" == "B" ] ; then
177                 INT_MODE="-B"
178         else
179                 INT_MODE=""
180         fi
181         if [ -n "$7" ] ; then
182                 KEY_PARAMS="--integrity-key-file $6 --integrity-key-size $7"
183         else
184                 KEY_PARAMS=""
185         fi
186         if [ $3 -ne 0 ] ; then
187                 TAG_PARAMS="--tag-size $3"
188         else
189                 TAG_PARAMS=""
190         fi
191         dd if=/dev/zero of=$DEV bs=1M count=32 >/dev/null 2>&1
192
193         echo -n "[INTEGRITY:$1:$2:$4:$5]"
194         echo -n "[FORMAT]"
195         $INTSETUP format -q --integrity $2 $TAG_PARAMS --sector-size $5 $KEY_PARAMS $DEV $INT_MODE >/dev/null || fail "Cannot format device."
196         echo -n "[ACTIVATE]"
197         $INTSETUP open $DEV $DEV_NAME --integrity $2 --integrity-no-journal $KEY_PARAMS $INT_MODE || fail "Cannot activate device."
198
199         if [ -n "$6" -a -n "$7" ]; then
200                 echo -n "[KEYED HASH]"
201                 KEY_HEX=$(xxd -c 256 -l $7 -p $6)
202                 [ -z "$KEY_HEX" ] && fail "Cannot decode key."
203                 dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
204         fi
205
206         echo -n "[WRITE DATA]"
207         echo -n "EXAMPLE TEXT" | dd of=/dev/mapper/$DEV_NAME >/dev/null 2>&1 || fail "Cannot write to device."
208         $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
209
210         # find offset of data area
211         ARR=($(dd if=$DEV bs=512 2>/dev/null | hexdump -C | grep 'EXAMPLE TEXT'))
212         OFF_HEX=${ARR[0]}
213         OFF_DEC=$((16#$OFF_HEX))
214
215         echo -n "[CORRUPT DATA:$OFF_DEC]"
216         echo -n "Z" | dd of=$DEV bs=1 seek=$OFF_DEC conv=notrunc >/dev/null 2>&1 || fail "Cannot write to device."
217
218         echo -n "[DETECT ERROR]"
219         $INTSETUP open $DEV $DEV_NAME --integrity $2 $KEY_PARAMS $INT_MODE || fail "Cannot activate device."
220         dd if=/dev/mapper/$DEV_NAME  >/dev/null 2>&1 && fail "Error detection failed."
221         echo -n "[REMOVE]"
222         $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
223         echo "[OK]"
224 }
225
226 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
227 {
228     echo -n "[INTEGRITY JOURNAL:$6:${4}%:${5}ms]"
229     echo -n "[FORMAT]"
230     ARGS="--integrity $1 --journal-watermark $4 --journal-commit-time $5 --journal-integrity $6 --journal-integrity-key-file $7 --journal-integrity-key-size $8"
231     $INTSETUP format -q --tag-size $2 --sector-size $3 $ARGS $DEV || fail "Cannot format device."
232
233     echo -n "[ACTIVATE]"
234
235     $INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."
236
237     echo -n "[KEYED HASH]"
238     KEY_HEX=$(xxd -c 256 -l $8 -p $7)
239     [ -z "$KEY_HEX" ] && fail "Cannot decode key."
240     dmsetup table --showkeys $DEV_NAME | grep -q $KEY_HEX || fail "Key mismatch."
241
242     status_check "journal watermark" "${4}%"
243     status_check "journal commit time" "${5} ms"
244     status_check "journal integrity MAC" $9
245
246     echo -n "[REMOVE]"
247     $INTSETUP close $DEV_NAME || fail "Cannot deactivate device."
248     echo "[OK]"
249 }
250
251
252 int_journal_crypt() # crypt_alg crypt_alg_kernel crypt_key crypt_key_size
253 {
254         echo -n "[JOURNAL CRYPT:$1:${4}B]"
255
256         echo -n "[FORMAT]"
257         ARGS="--journal-crypt $1 --journal-crypt-key-file $3 --journal-crypt-key-size $4"
258         $INTSETUP format -q $ARGS $DEV || fail "Cannot format device."
259
260         echo -n "[ACTIVATE]"
261         $INTSETUP open $DEV $DEV_NAME $ARGS || fail "Cannot activate device."
262
263         KEY_HEX=$(xxd -c 256 -l $4 -p $3)
264         [ -z "$KEY_HEX" ] && fail "Cannot decode key."
265         dmsetup table --showkeys $DEV_NAME | grep -q "journal_crypt:$2:$KEY_HEX" || fail "Key mismatch."
266
267         $INTSETUP close $DEV_NAME
268         echo "[OK]"
269 }
270
271 int_mode() # alg tag_size sector_size [keyfile keysize]
272 {
273         if [ -n "$5" ] ; then
274                 KEY_PARAMS="--integrity-key-file $4 --integrity-key-size $5"
275         else
276                 KEY_PARAMS=""
277         fi
278
279         echo -n "[MODE TESTS:$1:$2:$3]"
280         ARGS="--tag-size $2 --sector-size $3"
281
282         $INTSETUP format -q $ARGS $KEY_PARAMS $DEV --integrity $1 || fail "Cannot format device."
283
284         echo -n "[JOURNALED WRITES]"
285         $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS || fail "Cannot activate device with journal."
286         status_check "mode" "read/write"
287         kernel_param_check 7 "J"
288
289         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
290
291         echo -n "[DIRECT WRITES]"
292         $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-no-journal || fail "Cannot activate device without journal."
293         status_check "mode" "read/write"
294         status_check "journal" "not active"
295         kernel_param_check 7 "D"
296
297         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
298
299         echo -n "[RECOVERY MODE]"
300         $INTSETUP open $DEV $DEV_NAME --integrity $1 $KEY_PARAMS --integrity-recovery-mode || fail "Cannot activate device in recovery mode."
301         status_check "mode" "read/write recovery"
302         kernel_param_check 7 "R"
303
304         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
305
306         echo "[OK]"
307 }
308
309 [ $(id -u) != 0 ] && skip "WARNING: You must be root to run this test, test skipped."
310 [ ! -x "$INTSETUP" ] && skip "Cannot find $INTSETUP, test skipped."
311 which blockdev >/dev/null || skip "Cannot find blockdev utility, test skipped."
312
313 [ -n "$VALG" ] && valgrind_setup && INTSETUP=valgrind_run
314 which hexdump >/dev/null 2>&1 || skip "WARNING: hexdump tool required."
315 modprobe dm-integrity >/dev/null 2>&1
316 dm_integrity_features
317
318 add_device
319 intformat crc32c      crc32c          0  4  512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
320 intformat crc32       crc32           0  4  512 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
321 intformat sha1        sha1            0 20  512 6eedd6344dab8875cd185fcd6565dfc869ab36bc57e577f40c685290b1fa7fe7
322 intformat sha1        sha1           16 16 4096 e152ec88227b539cd9cafd8bdb587a1072d720cd6bcebe1398d4136c9e7f337b
323 intformat sha256      sha256          0 32  512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11
324 intformat hmac-sha256 hmac\(sha256\)  0 32  512 8e5fe4119558e117bfc40e3b0f13ade3abe497b52604d4c7cca0cfd6c7f4cf11 $KEY_FILE 32
325 intformat sha256      sha256          0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4
326 intformat hmac-sha256 hmac\(sha256\)  0 32 4096 33f7dfa5163ca9f740383fb8b0919574e38a7b20a94a4170fde4238196b7c4b4 $KEY_FILE 32
327
328 echo "Error detection tests:"
329 int_error_detection J crc32c  0  4  512
330 int_error_detection J crc32c  0  4  4096
331 int_error_detection J crc32   0  4  512
332 int_error_detection J crc32   0  4  4096
333 int_error_detection J sha1    0 20 512
334 int_error_detection J sha1   16 16 512
335 int_error_detection J sha1    0 20 4096
336 int_error_detection J sha256  0 32 512
337 int_error_detection J sha256  0 32 4096
338
339 which xxd >/dev/null 2>&1 || skip "WARNING: xxd tool required."
340 int_error_detection J hmac-sha256  0 32 512 $KEY_FILE 32
341 int_error_detection J hmac-sha256  0 32 4096 $KEY_FILE 32
342
343 echo "Journal parameters tests:"
344 # Watermark is calculated in kernel, so it can be rounded down/up
345 int_journal crc32  4  512  66 1000 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)
346 int_journal sha256 32 4096 34 5000 hmac-sha1   $KEY_FILE 16 hmac\(sha1\)
347 int_journal sha1   20 512  75 9999 hmac-sha256 $KEY_FILE 32 hmac\(sha256\)
348
349 echo "Journal encryption tests:"
350 int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 32
351 int_journal_crypt cbc-aes cbc\(aes\) $KEY_FILE 16
352 int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 32
353 int_journal_crypt ctr-aes ctr\(aes\) $KEY_FILE 16
354
355 echo "Mode tests:"
356 int_mode crc32c      4  512
357 int_mode crc32       4  512
358 int_mode sha1        20 512
359 int_mode sha256      32 512
360 int_mode hmac-sha256 32 512  $KEY_FILE 32
361 int_mode hmac-sha256 32 4096 $KEY_FILE 32
362
363 echo -n "Recalculate tags in-kernel:"
364 add_device
365 if [ -n "$DM_INTEGRITY_RECALC" ] ; then
366         $INTSETUP format -q $DEV --no-wipe || fail "Cannot format device."
367         $INTSETUP open $DEV $DEV_NAME --integrity-recalculate || fail "Cannot activate device."
368         dd if=/dev/mapper/$DEV_NAME of=/dev/null bs=1M 2>/dev/null || fail "Cannot recalculate tags in-kernel"
369         int_check_sum_only 08f63eb27fb9ce2ce903b0a56429c68ce5e209253ba42154841ef045a53839d7
370         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
371         echo "[OK]"
372 else
373         echo "[N/A]"
374 fi
375
376 echo -n "Separate metadata device:"
377 if [ -n "$DM_INTEGRITY_META" ] ; then
378         add_device
379         $INTSETUP format -q $DEV --data-device $DEV2 || fail "Cannot format device."
380         $INTSETUP open $DEV --data-device $DEV2 $DEV_NAME || fail "Cannot activate device."
381         int_check_sum_only 83ee47245398adee79bd9c0a8bc57b821e92aba10f5f9ade8a5d1fae4d8c4302
382         $INTSETUP status $DEV_NAME | grep -q 'metadata device:' || fail
383         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
384         echo "[OK]"
385 else
386         echo "[N/A]"
387 fi
388
389 echo -n "Bitmap mode parameters:"
390 if [ -n "$DM_INTEGRITY_BITMAP" ] ; then
391         add_device
392         $INTSETUP format -q $DEV --integrity-bitmap-mode $DEV2 || fail "Cannot format device."
393         $INTSETUP open $DEV --integrity-bitmap-mode --bitmap-sectors-per-bit 65536 --bitmap-flush-time 5000 $DEV_NAME || fail "Cannot activate device."
394         $INTSETUP status $DEV_NAME | grep -q 'bitmap 512-byte sectors per bit: 65536' || fail
395         $INTSETUP status $DEV_NAME | grep -q 'bitmap flush interval: 5000 ms' || fail
396         $INTSETUP close $DEV_NAME fail "Cannot deactivate device."
397         echo "[OK]"
398         echo "Bitmap error detection tests:"
399         int_error_detection B crc32c      0  4 512
400         int_error_detection B crc32c      0  4 4096
401         int_error_detection B sha256      0 32 512
402         int_error_detection B sha256      0 32 4096
403         int_error_detection B hmac-sha256 0 32 512 $KEY_FILE 32
404         int_error_detection B hmac-sha256 0 32 4096 $KEY_FILE 32
405 else
406         echo "[N/A]"
407 fi
408
409 echo -n "Big device:"
410 add_device
411 DEV_LOOP=$(losetup -f $DEV --show)
412 if [ -n "$DEV_LOOP" ] ; then
413 dmsetup create $DEV_NAME_BIG <<EOF
414 0 16284 linear $DEV_LOOP 0
415 16284 80000000000 zero
416 EOF
417         [ ! -b /dev/mapper/$DEV_NAME_BIG ] && fail
418         $INTSETUP format -q -s 512 --no-wipe /dev/mapper/$DEV_NAME_BIG
419         $INTSETUP open /dev/mapper/$DEV_NAME_BIG $DEV_NAME || fail
420         D_SIZE=$($INTSETUP dump /dev/mapper/$DEV_NAME_BIG | grep provided_data_sectors | sed -e 's/.*provided_data_sectors\ \+//g')
421         A_SIZE=$(blockdev --getsz /dev/mapper/$DEV_NAME)
422         # Compare strings (to avoid 64bit integers), not integers
423         [ -n "$A_SIZE" -a "$D_SIZE" != "$A_SIZE" ] && fail
424         echo "[OK]"
425 else
426         echo "[N/A]"
427 fi
428
429 cleanup