Commit | Line | Data |
---|---|---|
a4ffc152 MP |
1 | dm-verity |
2 | ========== | |
3 | ||
4 | Device-Mapper's "verity" target provides transparent integrity checking of | |
5 | block devices using a cryptographic digest provided by the kernel crypto API. | |
6 | This target is read-only. | |
7 | ||
8 | Construction Parameters | |
9 | ======================= | |
18068bdd | 10 | <version> <dev> <hash_dev> |
a4ffc152 MP |
11 | <data_block_size> <hash_block_size> |
12 | <num_data_blocks> <hash_start_block> | |
13 | <algorithm> <digest> <salt> | |
65ff5b7d | 14 | [<#opt_params> <opt_params>] |
a4ffc152 MP |
15 | |
16 | <version> | |
18068bdd | 17 | This is the type of the on-disk hash format. |
a4ffc152 MP |
18 | |
19 | 0 is the original format used in the Chromium OS. | |
18068bdd | 20 | The salt is appended when hashing, digests are stored continuously and |
a739ff3f | 21 | the rest of the block is padded with zeroes. |
a4ffc152 MP |
22 | |
23 | 1 is the current format that should be used for new devices. | |
18068bdd | 24 | The salt is prepended when hashing and each digest is |
a739ff3f | 25 | padded with zeroes to the power of two. |
a4ffc152 MP |
26 | |
27 | <dev> | |
18068bdd | 28 | This is the device containing data, the integrity of which needs to be |
a4ffc152 MP |
29 | checked. It may be specified as a path, like /dev/sdaX, or a device number, |
30 | <major>:<minor>. | |
31 | ||
32 | <hash_dev> | |
18068bdd | 33 | This is the device that supplies the hash tree data. It may be |
a4ffc152 | 34 | specified similarly to the device path and may be the same device. If the |
18068bdd MB |
35 | same device is used, the hash_start should be outside the configured |
36 | dm-verity device. | |
a4ffc152 MP |
37 | |
38 | <data_block_size> | |
18068bdd MB |
39 | The block size on a data device in bytes. |
40 | Each block corresponds to one digest on the hash device. | |
a4ffc152 MP |
41 | |
42 | <hash_block_size> | |
18068bdd | 43 | The size of a hash block in bytes. |
a4ffc152 MP |
44 | |
45 | <num_data_blocks> | |
46 | The number of data blocks on the data device. Additional blocks are | |
47 | inaccessible. You can place hashes to the same partition as data, in this | |
48 | case hashes are placed after <num_data_blocks>. | |
49 | ||
50 | <hash_start_block> | |
51 | This is the offset, in <hash_block_size>-blocks, from the start of hash_dev | |
52 | to the root block of the hash tree. | |
53 | ||
54 | <algorithm> | |
55 | The cryptographic hash algorithm used for this device. This should | |
56 | be the name of the algorithm, like "sha1". | |
57 | ||
58 | <digest> | |
59 | The hexadecimal encoding of the cryptographic hash of the root hash block | |
60 | and the salt. This hash should be trusted as there is no other authenticity | |
61 | beyond this point. | |
62 | ||
63 | <salt> | |
64 | The hexadecimal encoding of the salt value. | |
65 | ||
65ff5b7d ST |
66 | <#opt_params> |
67 | Number of optional parameters. If there are no optional parameters, | |
68 | the optional paramaters section can be skipped or #opt_params can be zero. | |
69 | Otherwise #opt_params is the number of following arguments. | |
70 | ||
71 | Example of optional parameters section: | |
72 | 1 ignore_corruption | |
73 | ||
74 | ignore_corruption | |
75 | Log corrupted blocks, but allow read operations to proceed normally. | |
76 | ||
77 | restart_on_corruption | |
78 | Restart the system when a corrupted block is discovered. This option is | |
79 | not compatible with ignore_corruption and requires user space support to | |
80 | avoid restart loops. | |
81 | ||
0cc37c2d ST |
82 | ignore_zero_blocks |
83 | Do not verify blocks that are expected to contain zeroes and always return | |
84 | zeroes instead. This may be useful if the partition contains unused blocks | |
85 | that are not guaranteed to contain zeroes. | |
86 | ||
a739ff3f ST |
87 | use_fec_from_device <fec_dev> |
88 | Use forward error correction (FEC) to recover from corruption if hash | |
89 | verification fails. Use encoding data from the specified device. This | |
90 | may be the same device where data and hash blocks reside, in which case | |
91 | fec_start must be outside data and hash areas. | |
92 | ||
93 | If the encoding data covers additional metadata, it must be accessible | |
94 | on the hash device after the hash blocks. | |
95 | ||
96 | Note: block sizes for data and hash devices must match. Also, if the | |
97 | verity <dev> is encrypted the <fec_dev> should be too. | |
98 | ||
99 | fec_roots <num> | |
100 | Number of generator roots. This equals to the number of parity bytes in | |
101 | the encoding data. For example, in RS(M, N) encoding, the number of roots | |
102 | is M-N. | |
103 | ||
104 | fec_blocks <num> | |
105 | The number of encoding data blocks on the FEC device. The block size for | |
106 | the FEC device is <data_block_size>. | |
107 | ||
108 | fec_start <offset> | |
109 | This is the offset, in <data_block_size> blocks, from the start of the | |
110 | FEC device to the beginning of the encoding data. | |
111 | ||
843f38d3 PT |
112 | check_at_most_once |
113 | Verify data blocks only the first time they are read from the data device, | |
114 | rather than every time. This reduces the overhead of dm-verity so that it | |
115 | can be used on systems that are memory and/or CPU constrained. However, it | |
116 | provides a reduced level of security because only offline tampering of the | |
117 | data device's content will be detected, not online tampering. | |
118 | ||
119 | Hash blocks are still verified each time they are read from the hash device, | |
120 | since verification of hash blocks is less performance critical than data | |
121 | blocks, and a hash block will not be verified any more after all the data | |
122 | blocks it covers have been verified anyway. | |
a739ff3f | 123 | |
a4ffc152 MP |
124 | Theory of operation |
125 | =================== | |
126 | ||
18068bdd | 127 | dm-verity is meant to be set up as part of a verified boot path. This |
a4ffc152 MP |
128 | may be anything ranging from a boot using tboot or trustedgrub to just |
129 | booting from a known-good device (like a USB drive or CD). | |
130 | ||
131 | When a dm-verity device is configured, it is expected that the caller | |
132 | has been authenticated in some way (cryptographic signatures, etc). | |
133 | After instantiation, all hashes will be verified on-demand during | |
134 | disk access. If they cannot be verified up to the root node of the | |
18068bdd | 135 | tree, the root hash, then the I/O will fail. This should detect |
a4ffc152 MP |
136 | tampering with any data on the device and the hash data. |
137 | ||
138 | Cryptographic hashes are used to assert the integrity of the device on a | |
18068bdd MB |
139 | per-block basis. This allows for a lightweight hash computation on first read |
140 | into the page cache. Block hashes are stored linearly, aligned to the nearest | |
141 | block size. | |
a4ffc152 | 142 | |
a739ff3f ST |
143 | If forward error correction (FEC) support is enabled any recovery of |
144 | corrupted data will be verified using the cryptographic hash of the | |
145 | corresponding data. This is why combining error correction with | |
146 | integrity checking is essential. | |
147 | ||
a4ffc152 MP |
148 | Hash Tree |
149 | --------- | |
150 | ||
151 | Each node in the tree is a cryptographic hash. If it is a leaf node, the hash | |
18068bdd MB |
152 | of some data block on disk is calculated. If it is an intermediary node, |
153 | the hash of a number of child nodes is calculated. | |
a4ffc152 MP |
154 | |
155 | Each entry in the tree is a collection of neighboring nodes that fit in one | |
156 | block. The number is determined based on block_size and the size of the | |
157 | selected cryptographic digest algorithm. The hashes are linearly-ordered in | |
158 | this entry and any unaligned trailing space is ignored but included when | |
159 | calculating the parent node. | |
160 | ||
161 | The tree looks something like: | |
162 | ||
163 | alg = sha256, num_blocks = 32768, block_size = 4096 | |
164 | ||
165 | [ root ] | |
166 | / . . . \ | |
167 | [entry_0] [entry_1] | |
168 | / . . . \ . . . \ | |
169 | [entry_0_0] . . . [entry_0_127] . . . . [entry_1_127] | |
170 | / ... \ / . . . \ / \ | |
171 | blk_0 ... blk_127 blk_16256 blk_16383 blk_32640 . . . blk_32767 | |
172 | ||
173 | ||
174 | On-disk format | |
175 | ============== | |
176 | ||
18068bdd MB |
177 | The verity kernel code does not read the verity metadata on-disk header. |
178 | It only reads the hash blocks which directly follow the header. | |
179 | It is expected that a user-space tool will verify the integrity of the | |
180 | verity header. | |
a4ffc152 | 181 | |
18068bdd MB |
182 | Alternatively, the header can be omitted and the dmsetup parameters can |
183 | be passed via the kernel command-line in a rooted chain of trust where | |
184 | the command-line is verified. | |
a4ffc152 MP |
185 | |
186 | Directly following the header (and with sector number padded to the next hash | |
187 | block boundary) are the hash blocks which are stored a depth at a time | |
188 | (starting from the root), sorted in order of increasing index. | |
189 | ||
18068bdd MB |
190 | The full specification of kernel parameters and on-disk metadata format |
191 | is available at the cryptsetup project's wiki page | |
e44f23b3 | 192 | https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity |
18068bdd | 193 | |
a4ffc152 MP |
194 | Status |
195 | ====== | |
196 | V (for Valid) is returned if every check performed so far was valid. | |
197 | If any check failed, C (for Corruption) is returned. | |
198 | ||
199 | Example | |
200 | ======= | |
18068bdd MB |
201 | Set up a device: |
202 | # dmsetup create vroot --readonly --table \ | |
203 | "0 2097152 verity 1 /dev/sda1 /dev/sda2 4096 4096 262144 1 sha256 "\ | |
a4ffc152 MP |
204 | "4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 "\ |
205 | "1234000000000000000000000000000000000000000000000000000000000000" | |
206 | ||
207 | A command line tool veritysetup is available to compute or verify | |
18068bdd | 208 | the hash tree or activate the kernel device. This is available from |
e44f23b3 | 209 | the cryptsetup upstream repository https://gitlab.com/cryptsetup/cryptsetup/ |
18068bdd MB |
210 | (as a libcryptsetup extension). |
211 | ||
212 | Create hash on the device: | |
213 | # veritysetup format /dev/sda1 /dev/sda2 | |
214 | ... | |
215 | Root hash: 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 | |
216 | ||
217 | Activate the device: | |
218 | # veritysetup create vroot /dev/sda1 /dev/sda2 \ | |
219 | 4392712ba01368efdf14b05c76f9e4df0d53664630b5d48632ed17a137f39076 |