README.md
1# fsverity-utils
2
3## Introduction
4
5This is fsverity-utils, a set of userspace utilities for fs-verity.
6fs-verity is a Linux kernel feature that does transparent on-demand
7integrity/authenticity verification of the contents of read-only
8files, using a hidden Merkle tree (hash tree) associated with the
9file. It is similar to dm-verity, but implemented at the file level
10rather than at the block device level. See the [kernel
11documentation](https://www.kernel.org/doc/html/latest/filesystems/fsverity.html)
12for more information about fs-verity, including which filesystems
13support it.
14
15fsverity-utils currently contains just one program, `fsverity`. The
16`fsverity` program allows you to set up fs-verity protected files.
17In addition, the file digest computation and signing functionality of
18`fsverity` is optionally exposed through a C library `libfsverity`.
19See `libfsverity.h` for the API of this library.
20
21## Building and installing
22
23To build fsverity-utils, first install the needed build dependencies. For
24example, on Debian-based systems, run:
25
26```bash
27 sudo apt-get install libssl-dev
28```
29
30OpenSSL must be version 1.0.0 or later. This is the only runtime dependency.
31
32Then, to build and install fsverity-utils:
33
34```bash
35 make
36 sudo make install
37```
38
39By default, the following targets are built and installed: the program
40`fsverity`, the static library `libfsverity.a`, the shared library
41`libfsverity.so`, and the manual page `fsverity.1`. You can also run
42`make check` to build and run the tests, or `make help` to display all
43available build targets.
44
45By default, `fsverity` is statically linked to `libfsverity`. You can
46use `make USE_SHARED_LIB=1` to use dynamic linking instead.
47
48See the `Makefile` for other supported build and installation options.
49
50### Building on Windows
51
52There is minimal support for building Windows executables using MinGW.
53```bash
54 make CC=x86_64-w64-mingw32-gcc
55```
56
57`fsverity.exe` will be built, and it supports the `digest` and `sign` commands.
58
59A Windows build of OpenSSL/libcrypto needs to be available.
60
61## Examples
62
63Full usage information for `fsverity` can be found in the manual page
64(`man fsverity`). Here, we just show some typical examples.
65
66### Basic use
67
68```bash
69 mkfs.ext4 -O verity /dev/vdc
70 mount /dev/vdc /vdc
71 cd /vdc
72
73 # Create a test file
74 head -c 1000000 /dev/urandom > file
75 sha256sum file
76
77 # Enable verity on the file
78 fsverity enable file
79
80 # Show the verity file digest
81 fsverity measure file
82
83 # File should still be readable as usual. However, all data read
84 # is now transparently checked against a hidden Merkle tree, whose
85 # root hash is incorporated into the verity file digest. Reads of
86 # any corrupted parts of the data will fail.
87 sha256sum file
88```
89
90Note that in the above example, the file isn't signed. Therefore, to
91get any authenticity protection (as opposed to just integrity
92protection), the output of `fsverity measure` needs to be compared
93against a trusted value.
94
95### With IMA
96
97Since Linux v5.19, the kernel's IMA (Integrity Measurement
98Architecture) subsystem supports using fs-verity file digests in lieu
99of traditional file digests. This must be configured in the IMA
100policy. For more information, see the IMA documentation.
101
102### Using builtin signatures
103
104First, note that fs-verity is essentially just a way of hashing a
105file; it doesn't mandate a specific way of handling signatures.
106There are several possible ways that signatures could be handled:
107
108* Do it entirely in userspace
109* Use IMA appraisal
110* Use fs-verity built-in signatures
111
112Any such solution needs two parts: (a) a policy that determines which
113files are required to have fs-verity enabled and have a valid
114signature, and (b) enforcement of the policy. Each part could happen
115either in a trusted userspace program(s) or in the kernel.
116
117fs-verity built-in signatures (which are supported when the kernel was
118built with `CONFIG_FS_VERITY_BUILTIN_SIGNATURES=y`) are a hybrid
119solution where the policy of which files are required to be signed is
120determined and enforced by a trusted userspace program, but the actual
121signature verification happens in the kernel. Specifically, with
122built-in signatures, the filesystem supports storing a signed file
123digest in each file's verity metadata. Before allowing access to the
124file, the filesystem will automatically verify the signature against
125the set of X.509 certificates in the ".fs-verity" kernel keyring. If
126set, the sysctl `fs.verity.require_signatures=1` will make the kernel
127enforce that every verity file has a valid built-in signature.
128
129fs-verity built-in signatures are primarily intended as a
130proof-of-concept; they reuse the kernel code that verifies the
131signatures of loadable kernel modules. This solution still requires a
132trusted userspace program to enforce that particular files have
133fs-verity enabled. Also, this solution uses PKCS#7 signatures, which
134are complex and prone to security bugs.
135
136Thus, if possible one of the other solutions should be used instead.
137For example, the trusted userspace program could verify signatures
138itself, using a simple signature format using a modern algorithm such
139as Ed25519.
140
141That being said, here are some examples of using built-in signatures:
142
143```bash
144 # Generate a new certificate and private key:
145 openssl req -newkey rsa:4096 -nodes -keyout key.pem -x509 -out cert.pem
146
147 # Convert the certificate from PEM to DER format:
148 openssl x509 -in cert.pem -out cert.der -outform der
149
150 # Load the certificate into the fs-verity keyring:
151 keyctl padd asymmetric '' %keyring:.fs-verity < cert.der
152
153 # Optionally, lock the keyring so that no more keys can be added
154 # (requires keyctl v1.5.11 or later):
155 keyctl restrict_keyring %keyring:.fs-verity
156
157 # Optionally, require that all verity files be signed:
158 sysctl fs.verity.require_signatures=1
159
160 # Now set up fs-verity on a test file:
161 sha256sum file
162 fsverity sign file file.sig --key=key.pem --cert=cert.pem
163 fsverity enable file --signature=file.sig
164 rm -f file.sig
165 sha256sum file
166
167 # The digest to be signed can also be printed separately, hex
168 # encoded, in case the integrated signing cannot be used:
169 fsverity digest file --compact --for-builtin-sig | tr -d '\n' | xxd -p -r | openssl smime -sign -in /dev/stdin ...
170```
171
172## Notices
173
174fsverity-utils is provided under the terms of the MIT license. A copy
175of this license can be found in the file named [LICENSE](LICENSE).
176
177Send questions and bug reports to [email protected].
178
179Signed release tarballs for fsverity-utils can be found on
180[kernel.org](https://kernel.org/pub/linux/kernel/people/ebiggers/fsverity-utils/).
181
182## Contributing
183
184Send patches to [email protected] with the additional tag
185`fsverity-utils` in the subject, i.e. `[fsverity-utils PATCH]`.
186Patches should follow the Linux kernel's coding style. A
187`.clang-format` file is provided to approximate this coding style;
188consider using `git clang-format`. Additionally, like the Linux
189kernel itself, patches require the following "sign-off" procedure:
190
191The sign-off is a simple line at the end of the explanation for the
192patch, which certifies that you wrote it or otherwise have the right
193to pass it on as an open-source patch. The rules are pretty simple:
194if you can certify the below:
195
196Developer's Certificate of Origin 1.1
197
198By making a contribution to this project, I certify that:
199
200 (a) The contribution was created in whole or in part by me and I
201 have the right to submit it under the open source license
202 indicated in the file; or
203
204 (b) The contribution is based upon previous work that, to the best
205 of my knowledge, is covered under an appropriate open source
206 license and I have the right under that license to submit that
207 work with modifications, whether created in whole or in part
208 by me, under the same open source license (unless I am
209 permitted to submit under a different license), as indicated
210 in the file; or
211
212 (c) The contribution was provided directly to me by some other
213 person who certified (a), (b) or (c) and I have not modified
214 it.
215
216 (d) I understand and agree that this project and the contribution
217 are public and that a record of the contribution (including all
218 personal information I submit with it, including my sign-off) is
219 maintained indefinitely and may be redistributed consistent with
220 this project or the open source license(s) involved.
221
222then you just add a line saying::
223
224 Signed-off-by: Random J Developer <[email protected]>
225
226using your real name (sorry, no pseudonyms or anonymous contributions.)
227