summaryrefslogtreecommitdiff
path: root/tests/generic/624
blob: db4b6731031971e631b9064a91f23e9054c44cf2 (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
#! /bin/bash
# SPDX-License-Identifier: GPL-2.0-only
# Copyright 2021 Google LLC
#
# FS QA Test No. 624
#
# Test retrieving the Merkle tree and fs-verity descriptor of a verity file
# using FS_IOC_READ_VERITY_METADATA.
#
. ./common/preamble
_begin_fstest auto quick verity

# Override the default cleanup function.
_cleanup()
{
	cd /
	_restore_fsverity_signatures
	rm -f $tmp.*
}

. ./common/filter
. ./common/verity

_supported_fs generic
_require_scratch_verity
_disable_fsverity_signatures
fsv_orig_file=$SCRATCH_MNT/file
fsv_file=$SCRATCH_MNT/file.fsv

_scratch_mkfs_verity &>> $seqres.full
_scratch_mount
_fsv_create_enable_file $fsv_file
_require_fsverity_dump_metadata $fsv_file

# Test FS_IOC_READ_VERITY_METADATA on a file that uses the given Merkle tree
# block size.
test_block_size()
{
	local block_size=$1
	local digest_size=32 # assuming SHA-256
	local i

	# Create the file.  Make the file size big enough to result in multiple
	# Merkle tree levels being needed.  The following expression computes a
	# file size that needs 2 blocks at level 0, and thus 1 block at level 1.
	local file_size=$((block_size * (2 * (block_size / digest_size))))
	head -c $file_size /dev/zero > $fsv_orig_file
	local tree_params=("--salt=abcd" "--block-size=$block_size")
	cp $fsv_orig_file $fsv_file
	_fsv_enable $fsv_file "${tree_params[@]}"

	# Use the 'fsverity digest' command to compute the expected Merkle tree,
	# descriptor, and file digest.
	#
	# Ideally we'd just hard-code expected values into the .out file and
	# echo the actual values.  That doesn't quite work here, since all these
	# values depend on the Merkle tree block size, and the Merkle tree block
	# sizes that are supported (and thus get tested here) vary.  Therefore,
	# we calculate the expected values in userspace with the help of
	# 'fsverity digest', then do explicit comparisons with them.  This works
	# fine as long as fsverity-utils and the kernel don't get broken in the
	# same way, in which case generic/575 should detect the problem anyway.
	local expected_file_digest=$(_fsv_digest $fsv_orig_file \
		"${tree_params[@]}" \
		--out-merkle-tree=$tmp.merkle_tree.expected \
		--out-descriptor=$tmp.descriptor.expected)
	local merkle_tree_size=$(_get_filesize $tmp.merkle_tree.expected)
	local descriptor_size=$(_get_filesize $tmp.descriptor.expected)

	# 'fsverity measure' should return the expected file digest.
	local actual_file_digest=$(_fsv_measure $fsv_file)
	if [ "$actual_file_digest" != "$expected_file_digest" ]; then
		echo "Measure returned $actual_file_digest but expected $expected_file_digest"
	fi

	# Test dumping the Merkle tree.
	_fsv_dump_merkle_tree $fsv_file > $tmp.merkle_tree.actual
	if ! cmp $tmp.merkle_tree.expected $tmp.merkle_tree.actual; then
		echo "Dumped Merkle tree didn't match"
	fi

	# Test dumping the Merkle tree in chunks.
	for (( i = 0; i < merkle_tree_size; i += 997 )); do
		_fsv_dump_merkle_tree $fsv_file --offset=$i --length=997
	done > $tmp.merkle_tree.actual
	if ! cmp $tmp.merkle_tree.expected $tmp.merkle_tree.actual; then
		echo "Dumped Merkle tree (in chunks) didn't match"
	fi

	# Test dumping the descriptor.
	_fsv_dump_descriptor $fsv_file > $tmp.descriptor.actual
	if ! cmp $tmp.descriptor.expected $tmp.descriptor.actual; then
		echo "Dumped descriptor didn't match"
	fi

	# Test dumping the descriptor in chunks.
	for (( i = 0; i < descriptor_size; i += 13 )); do
		_fsv_dump_descriptor $fsv_file --offset=$i --length=13
	done > $tmp.descriptor.actual
	if ! cmp $tmp.descriptor.expected $tmp.descriptor.actual; then
		echo "Dumped descriptor (in chunks) didn't match"
	fi
}

# Always test FSV_BLOCK_SIZE.  Also test some other block sizes if they happen
# to be supported.
_fsv_scratch_begin_subtest "Testing block_size=FSV_BLOCK_SIZE"
test_block_size $FSV_BLOCK_SIZE
for block_size in 1024 4096 16384 65536; do
	_fsv_scratch_begin_subtest "Testing block_size=$block_size if supported"
	if (( block_size == FSV_BLOCK_SIZE )); then
		continue # Skip redundant test case.
	fi
	if ! _fsv_can_enable $fsv_file --block-size=$block_size; then
		echo "block_size=$block_size is unsupported" >> $seqres.full
		continue
	fi
	test_block_size $block_size
done

# success, all done
status=0
exit